Let a detail pass carry a list, not only a kernel
Every neighbourhood pass so far has been a convolution, whose whole description fits in the uniform block because its structure fixes how many numbers it needs. Spot removal is not that shape: sixty-four repairs and one repair are the same shader with a different buffer behind it. So a pass may declare `storage`, which arrives at binding 3 as `array<vec4<f32>>` with `arrayLength` in scope. The alternative — packing the list into uniforms — needs a fixed maximum paid for on every frame, a composer that can emit vec4 fields because a uniform array's stride is 16 whatever it holds, and it gives the next operation that wants a table nothing to build on. The property worth having is what stays out of the generated source: the count is in the buffer, so placing the tenth spot uploads 512 bytes and reuses the compiled pipeline, exactly as moving a slider does for the fused pass. `changing_the_list_does_not_recompile` is that, asserted. One bind group entry rather than two more layouts, and one placeholder buffer allocated in `new` rather than sixteen bytes per pass per frame — a zero-length storage buffer cannot be bound, and per-frame allocation is what this module's documentation exists to refuse. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -358,6 +358,8 @@ impl DetailStage for CaptureSharpen {
|
||||
.map(|label| DetailPass {
|
||||
label,
|
||||
radius: extent,
|
||||
// A convolution, not a list: nothing to bind at binding 3.
|
||||
storage: Vec::new(),
|
||||
uniforms: vec![
|
||||
Uniform {
|
||||
// −100…100 as a gain around zero. A hundred percent is
|
||||
@@ -410,6 +412,8 @@ fn nothing_to_sharpen() -> DetailPass {
|
||||
label: "unresolved",
|
||||
// Reads only the pixel it writes, so a tile needs no halo at all.
|
||||
radius: 0,
|
||||
// A convolution, not a list: nothing to bind at binding 3.
|
||||
storage: Vec::new(),
|
||||
uniforms: Vec::new(),
|
||||
wgsl: "// The chosen radius is finer than one pixel of this render, so the detail
|
||||
// it would act on is not in this texture — it was lost to the downscale
|
||||
|
||||
@@ -475,12 +475,16 @@ impl<B: Band> DetailStage for LocalContrast<B> {
|
||||
DetailPass {
|
||||
label: "base",
|
||||
radius,
|
||||
// A convolution, not a list: nothing to bind at binding 3.
|
||||
storage: Vec::new(),
|
||||
uniforms: shape,
|
||||
wgsl: BASE_X.to_string(),
|
||||
},
|
||||
DetailPass {
|
||||
label: "combine",
|
||||
radius,
|
||||
// A convolution, not a list: nothing to bind at binding 3.
|
||||
storage: Vec::new(),
|
||||
uniforms: combine,
|
||||
wgsl: combine_body(B::RECIPE.midtone_taper),
|
||||
},
|
||||
|
||||
@@ -436,6 +436,8 @@ impl DetailStage for NoiseReduction {
|
||||
passes.push(DetailPass {
|
||||
label: "luminance",
|
||||
radius: luma,
|
||||
// A convolution, not a list: nothing to bind at binding 3.
|
||||
storage: Vec::new(),
|
||||
uniforms: vec![
|
||||
Uniform {
|
||||
name: "radius",
|
||||
@@ -474,6 +476,8 @@ impl DetailStage for NoiseReduction {
|
||||
"chroma-vertical"
|
||||
},
|
||||
radius: chroma,
|
||||
// A convolution, not a list: nothing to bind at binding 3.
|
||||
storage: Vec::new(),
|
||||
uniforms: vec![
|
||||
Uniform {
|
||||
name: "radius",
|
||||
|
||||
Reference in New Issue
Block a user