Merge branch 'worktree-agent-a75c901968abfa183' into integration
# Conflicts: # core/dr-gpu/src/adjust.rs # core/dr-pipeline/ops/README.md # core/dr-pipeline/src/lib.rs # core/dr-pipeline/src/ops/mod.rs # ui/dr-ui/src/develop.rs
This commit is contained in:
+23
-10
@@ -1056,13 +1056,23 @@ impl DevelopSession {
|
||||
/// 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.
|
||||
///
|
||||
/// `space` is the output space `shader` was composed for, and it has to be
|
||||
/// passed rather than assumed because the **detail stage** is composed
|
||||
/// here too and the two halves must agree. When an edit has an active
|
||||
/// neighbourhood operation the fused pass stops at unclipped linear
|
||||
/// working values and the last detail pass performs the output transform;
|
||||
/// composing the fused half for Display P3 and the detail half for sRGB
|
||||
/// would encode the export in the wrong space, with nothing to notice it.
|
||||
/// **And the detail stage with it.** The neighbourhood operations — noise
|
||||
/// reduction, capture sharpening, 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,
|
||||
@@ -1085,15 +1095,18 @@ impl DevelopSession {
|
||||
// scale-free: a sharpening radius is stated in source pixels and the
|
||||
// develop view renders at whatever the viewport needs (FR-DSP-1), so
|
||||
// the conversion is different for the canvas, the thumbnail and the
|
||||
// export. `render_scale` works the ratio out from the framing, which
|
||||
// is also what makes zooming to 1:1 restore an exact preview with no
|
||||
// second render path to maintain.
|
||||
// export. `render_scale` works the ratio out from the framing, so a
|
||||
// crop and a zoom are already accounted for, and zooming to 1:1
|
||||
// restores an exact preview with no second render path to maintain.
|
||||
//
|
||||
// Empty for every edit with no active neighbourhood operation — which
|
||||
// is almost all of them — and `render_detailed` then falls straight
|
||||
// through to the single masked dispatch this used to call.
|
||||
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()
|
||||
|
||||
Reference in New Issue
Block a user