Let a part be left out of a mask without being taken out of it
A layer built from parts was missing the one control a correction most often wants: seeing what it did. The question a subtracted gradient raises is whether it took only the sky, and the question a stroke raises is whether it filled the shoulder — and the only way to ask either was to remove the part and look, which answered the question and lost the part. The layer's own ring answers a different question, about the adjustment, and hiding eight layers to check one correction is not an A/B anybody performs. So a part carries `hidden`. It is an edit and a history step, as the layer's switch is, and it is folded into the render fingerprint because hiding a part changes the mask as surely as removing it does. Where the mask is built the shown parts are walked rather than the parts, which is what makes a hidden base hand the fold to the first part that is shown — and a revealed layer whose every part is hidden clears its slice rather than leaving whatever the last rasterisation put there to be read back. `covers` asks the same shown parts, so a layer whose only adding part is hidden costs no slice at all. In the sidecar the key is `hidden`, in the part's block or, for the base, in the mask block — under a word that cannot be confused with the layer's `enabled`, which has always meant the layer. Absent means shown, so no file written before the switch existed reads any differently. The row wears the same ring the layer does, one row down, because it is the same question about a smaller thing.
This commit is contained in:
+40
-2
@@ -758,12 +758,24 @@ impl MaskPass {
|
||||
// is done where it is read back rather than where it is drawn —
|
||||
// a brush deposits dabs and cannot know what the rest of the
|
||||
// frame is. See `fs_combine`.
|
||||
let direct = layer.parts().len() == 1 && !layer.base().invert;
|
||||
// TRACES: FR-DEV-19a
|
||||
// The shown parts, not the parts: a hidden one is skipped here
|
||||
// and nowhere else, and the first *shown* part is the one that
|
||||
// opens the fold. Which can leave nothing — a revealed layer with
|
||||
// every part hidden — and that clears the slice rather than
|
||||
// leaving whatever the last rasterisation put there to be read
|
||||
// back as this mask.
|
||||
let shown: Vec<&dr_pipeline::mask::MaskPart> = layer.shown_parts().collect();
|
||||
if shown.is_empty() {
|
||||
self.clear_slice(&mut encoder, slot as u32);
|
||||
continue;
|
||||
}
|
||||
let direct = shown.len() == 1 && !shown[0].invert;
|
||||
if !direct {
|
||||
self.ensure_scratch(width, height)?;
|
||||
}
|
||||
|
||||
for (index, part) in layer.parts().iter().enumerate() {
|
||||
for (index, part) in shown.iter().copied().enumerate() {
|
||||
let base = index == 0;
|
||||
let field = match (&part.source, labels) {
|
||||
(MaskSource::Regions { .. }, None) => {
|
||||
@@ -1369,6 +1381,32 @@ impl MaskPass {
|
||||
pass.draw(0..3, 0..1);
|
||||
}
|
||||
|
||||
/// Leave a layer's slice covering nothing.
|
||||
///
|
||||
/// A pass that clears and draws nothing, for the one case where a layer
|
||||
/// reaches the array with no part to draw: every part hidden while the
|
||||
/// layer is being revealed. The slice has to be written, because the
|
||||
/// shader reads it whatever this function did.
|
||||
fn clear_slice(&self, encoder: &mut wgpu::CommandEncoder, slot: u32) {
|
||||
let target = self.slice_view(slot);
|
||||
encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||
label: Some("mask-clear-pass"),
|
||||
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
|
||||
view: &target,
|
||||
depth_slice: None,
|
||||
resolve_target: None,
|
||||
ops: wgpu::Operations {
|
||||
load: wgpu::LoadOp::Clear(wgpu::Color::BLACK),
|
||||
store: wgpu::StoreOp::Store,
|
||||
},
|
||||
})],
|
||||
depth_stencil_attachment: None,
|
||||
timestamp_writes: None,
|
||||
occlusion_query_set: None,
|
||||
multiview_mask: None,
|
||||
});
|
||||
}
|
||||
|
||||
/// The texture a part is drawn in before it is joined.
|
||||
///
|
||||
/// Allocated on the first mask that has more than one part and kept at the
|
||||
|
||||
Reference in New Issue
Block a user