Run the view transform after the detail stage, in a pass of its own
The fused pass stops at "linear working values" when a sharpener, a blur or a repair follows, and the detail passes convolve what it hands on. Until now it handed on the rendering: the base curve, and since the last commit the view transform, ran before the store. So every kernel worked on display-referred values while its comments promised the opposite — D19's second finding. A fused pass composed for a detail stage now stops before the view transform, and carries a second shader, `ComposedShader::view`, composed from the same inputs. It runs the same prologue, for the positions a fragment reads (a film's grain seeds from `source_px`) and the corners it blacks out, takes its colour from the detail stage's result bound where the sample cache would be, and runs the view transform, the output transform and the mask reveal. `render_detailed` dispatches it after the last detail pass, in the same encoder. So no detail pass encodes any more. Every pass writes an intermediate, the last one included, which retires three things that existed only to make the last pass encode: `writes_output` and the runner's second layout, the body-less resolve pass for an active kernel with nothing to draw at this scale, and capture sharpening's pass-through, which now emits no pass at all. An empty chain is a whole render: the view pass reads the fused result directly. The detail stage no longer takes an output space either, so `compose_detail_for` folds into `compose_detail` and the space is named once, on the fused half. The cost is one full-render read and write per frame when a detail stage exists, and a third intermediate for a one-pass chain.
This commit is contained in:
@@ -956,42 +956,31 @@ impl EditGraph {
|
||||
}
|
||||
|
||||
/// TRACES: FR-DEV-3 | FR-DSP-1
|
||||
/// Generate the detail stage for this edit at one resolution, to sRGB.
|
||||
/// Generate the detail stage for this edit at one resolution.
|
||||
///
|
||||
/// Empty for every edit with no active neighbourhood operation, which is
|
||||
/// almost all of them — and in that case [`Self::compose`] emits the
|
||||
/// single encoded dispatch it always has.
|
||||
pub fn compose_detail(
|
||||
&self,
|
||||
source: (u32, u32),
|
||||
render: (u32, u32),
|
||||
) -> crate::detail::ComposedDetail {
|
||||
self.compose_detail_for(source, render, dr_types::ColourSpace::Srgb)
|
||||
}
|
||||
|
||||
/// TRACES: FR-EXP-2
|
||||
/// The detail stage, encoded into a chosen output space.
|
||||
///
|
||||
/// The space belongs here as well as on [`Self::compose_for`] because when
|
||||
/// a detail stage exists it is the *last* pass that performs the output
|
||||
/// transform — the fused pass stops at linear working values. Composing
|
||||
/// the two halves for different spaces would encode the edit twice, or
|
||||
/// not at all.
|
||||
/// No output space: since D19 no detail pass encodes. The fused pass's
|
||||
/// view pass reads what the last one wrote and performs the view transform
|
||||
/// and the output transform, so it is [`Self::compose_for`] alone that
|
||||
/// names the space.
|
||||
///
|
||||
/// `source` is the demosaiced image's size and `render` the size being
|
||||
/// drawn. The scale is worked out here rather than handed in, because the
|
||||
/// repairs need the *source* size as well — a spot is stored in normalised
|
||||
/// source coordinates and has to be put through the framing to find out
|
||||
/// where it lands on this render, and a [`crate::detail::RenderScale`]
|
||||
/// describes the region on screen rather than the photograph.
|
||||
pub fn compose_detail_for(
|
||||
pub fn compose_detail(
|
||||
&self,
|
||||
source: (u32, u32),
|
||||
render: (u32, u32),
|
||||
output: dr_types::ColourSpace,
|
||||
) -> crate::detail::ComposedDetail {
|
||||
let scale = self.render_scale(source, render);
|
||||
let spots = self.spots.passes(&self.framing, source, scale);
|
||||
crate::detail::compose_detail_with(&self.ops, &spots, scale, output)
|
||||
crate::detail::compose_detail_with(&self.ops, &spots, scale)
|
||||
}
|
||||
|
||||
/// TRACES: FR-DEV-3d
|
||||
|
||||
Reference in New Issue
Block a user