Merge branch 'worktree-agent-acd27f9b2974c67eb' into integration

# Conflicts:
#	core/dr-gpu/src/adjust.rs
#	core/dr-pipeline/src/detail.rs
#	core/dr-pipeline/src/ops/mod.rs
This commit is contained in:
2026-08-22 19:31:15 +02:00
7 changed files with 1661 additions and 7 deletions
+27 -6
View File
@@ -891,6 +891,11 @@ mod tests {
use dr_decode::{BaseCurve, CfaPattern, CropRect, RawImage};
use dr_pipeline::ops::{colour_mixer, exposure, saturation};
use dr_pipeline::EditGraph;
// For `Operation::detail`, which is how `the_whole_chain_at_once_compiles`
// asks the chain which of its operations are neighbourhood operations
// rather than being told a list. Imported anonymously: nothing here names
// the trait, only calls through it.
use dr_pipeline::Operation as _;
use crate::Demosaicer;
@@ -1454,8 +1459,20 @@ mod tests {
// allocation would show up.
let (w, h) = g.output_size(32, 32);
let shader = g.compose();
let scale = g.render_scale(img.size(), (w, h));
let detail = g.compose_detail(scale);
// At 512 rather than the 32 this test used before the detail stage
// existed, and the size is load-bearing twice over. A compositional
// radius is a fraction of the frame, so on a 32-pixel target every
// detail kernel rounds to nothing: the chain would compose no passes,
// leaving half the shader uncompiled, and the exclusive-or below would
// find those operations in neither stage and fail for a reason that is
// not a defect. Shadows the smaller size deliberately.
let (w, h) = g.output_size(512, 512);
let scale = g.render_scale((512, 512), (w, h));
let detail = g.compose_detail_for(scale, dr_types::ColourSpace::Srgb);
assert!(
!detail.is_empty(),
"the detail half composed nothing, so nothing of it was compiled"
);
// Every operation has to reach the pipeline, but they do not all reach
// the same half of it, and which half is not this test's business to
@@ -1494,10 +1511,14 @@ mod tests {
"with every operation active the detail stage must run"
);
// Both halves, from the one graph: with a detail stage present the
// fused pass stops at linear working values and the last detail pass
// performs the output transform, so rendering only the first half is
// not a smaller test — it is a texture format the driver rejects.
// The other half of the same edit, and it belongs in this test for the
// reason the test exists: the detail passes are generated WGSL too,
// they carry their own uniform blocks, and "everything at once" is
// exactly where a collision between them would show. Rendering the
// fused half alone is no longer even legal — with a neighbourhood
// operation active the fused pass stops at linear working values and
// the last detail pass performs the output transform, which is the
// mismatch `render_detailed` exists to reject.
let key = g.invalidation().through(dr_pipeline::Affects::Colour);
pass.render_detailed(&img, &shader, w, h, None, &detail, key)
.expect("the full chain must compile");