WIP: noise reduction
Checkpoint committed by the coordinator, not by the authoring agent: the session hit its API limit mid-task and left this work uncommitted. Committed so it survives, NOT because it is finished - expect failing tests and half-applied changes. The agent resumes from here.
This commit is contained in:
+45
-4
@@ -891,11 +891,30 @@ impl DevelopSession {
|
||||
/// The mask array is rasterised in source space at proxy size and sampled
|
||||
/// through the framing map, so one array is correct at every output size:
|
||||
/// a 256px thumbnail and a 24 MP export bind the same texture.
|
||||
///
|
||||
/// **And the detail stage with it.** The neighbourhood operations — noise
|
||||
/// reduction, and the rest of FR-DEV-3's kernels — cannot be fused into
|
||||
/// the single dispatch, so an edit using one composes a fused pass that
|
||||
/// hands on *linear* values and a chain of passes that finishes the job
|
||||
/// (see `dr_pipeline::detail`). Those two halves must be composed from one
|
||||
/// graph and dispatched together, or the fused shader's storage format
|
||||
/// does not match the texture bound to it; going through
|
||||
/// `render_detailed` here is what makes that true of every path at once.
|
||||
/// It falls through to the plain render when the chain is empty, which is
|
||||
/// almost every edit, so this costs nothing to the frames that do not
|
||||
/// need it.
|
||||
///
|
||||
/// `space` has to be the space `shader` was composed for. It is the last
|
||||
/// pass of the detail chain that performs the output transform when there
|
||||
/// is one, so the two would otherwise be free to disagree about which
|
||||
/// primaries the file is in — and the result would be a correctly
|
||||
/// labelled file with the wrong colours in it (FR-EXP-2).
|
||||
fn render_with_masks(
|
||||
&mut self,
|
||||
shader: &dr_pipeline::operation::ComposedShader,
|
||||
w: u32,
|
||||
h: u32,
|
||||
space: dr_types::ColourSpace,
|
||||
) -> Result<(), String> {
|
||||
let ctx = self.ctx.clone();
|
||||
self.ensure_subject_fields(&ctx);
|
||||
@@ -905,8 +924,30 @@ impl DevelopSession {
|
||||
.then(|| self.masks.as_ref().and_then(|p| p.array()))
|
||||
.flatten();
|
||||
|
||||
// The scale a kernel's radius is converted through. Worked out from
|
||||
// the framing, so a crop and a zoom are already accounted for: what
|
||||
// matters to a sensor-sized radius is how many source pixels one
|
||||
// render pixel stands for, here and now (FR-DSP-1).
|
||||
let scale = self.graph.render_scale(self.demosaiced.size(), (w, h));
|
||||
let detail = self.graph.compose_detail_for(scale, space);
|
||||
// Detail passes read what the colour pass wrote, so the key they are
|
||||
// cached against is the colour key: moving a sharpening slider re-runs
|
||||
// this stage and not the fused one (FR-DEV-3d).
|
||||
let colour_key = self
|
||||
.graph
|
||||
.invalidation()
|
||||
.through(dr_pipeline::Affects::Colour);
|
||||
|
||||
self.adjust
|
||||
.render_masked(&self.demosaiced, shader, w, h, masks)
|
||||
.render_detailed(
|
||||
&self.demosaiced,
|
||||
shader,
|
||||
w,
|
||||
h,
|
||||
masks,
|
||||
&detail,
|
||||
colour_key,
|
||||
)
|
||||
.map(|_| ())
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
@@ -1605,7 +1646,7 @@ impl DevelopSession {
|
||||
|
||||
// Rasterise the masks first: the shader addresses array slices by
|
||||
// index, so the array has to describe *this* stack before it is bound.
|
||||
self.render_with_masks(&shader, w, h)?;
|
||||
self.render_with_masks(&shader, w, h, dr_types::ColourSpace::Srgb)?;
|
||||
let texture = self.adjust.output().ok_or("nothing was rendered")?;
|
||||
|
||||
// The import is fallible on format and usage only, and both are fixed
|
||||
@@ -1729,7 +1770,7 @@ impl DevelopSession {
|
||||
let (w, h) = self.graph.output_size(sw, sh);
|
||||
|
||||
let shader = self.graph.compose_for(space);
|
||||
self.render_with_masks(&shader, w, h)?;
|
||||
self.render_with_masks(&shader, w, h, space)?;
|
||||
|
||||
let (pixels, rw, rh) = self.adjust.export_pixels().map_err(|e| e.to_string())?;
|
||||
dr_export::Frame::in_space(rw, rh, pixels, space).map_err(|e| e.to_string())
|
||||
@@ -1756,7 +1797,7 @@ impl DevelopSession {
|
||||
let (w, h) = fit(fw, fh, edge.max(1), edge.max(1));
|
||||
|
||||
let shader = self.graph.compose_for(dr_types::ColourSpace::Srgb);
|
||||
self.render_with_masks(&shader, w, h)?;
|
||||
self.render_with_masks(&shader, w, h, dr_types::ColourSpace::Srgb)?;
|
||||
|
||||
let (pixels, rw, rh) = self.adjust.export_pixels().map_err(|e| e.to_string())?;
|
||||
Ok((rw, rh, pixels))
|
||||
|
||||
Reference in New Issue
Block a user