[backdrop_dyn] Handle upstream pipeline failure Following #537 it is possible for the flatten stage to fail and flag a failure. In some cases this can cause invalid / corrupt bounding box data to propagate downstream, leading to a hang in the per-tile backdrop calculation loop. Triggering this is highly subtle, so I don't have a test case as part of vello scenes that can reliably reproduce this. Regardless, it makes sense to check for the upstream failures and terminate the work in general.
diff --git a/shader/backdrop_dyn.wgsl b/shader/backdrop_dyn.wgsl index 2664f6c..7bdf5c7 100644 --- a/shader/backdrop_dyn.wgsl +++ b/shader/backdrop_dyn.wgsl
@@ -3,6 +3,7 @@ // Prefix sum for dynamically allocated backdrops +#import bump #import config #import tile @@ -10,9 +11,12 @@ var<uniform> config: Config; @group(0) @binding(1) -var<storage> paths: array<Path>; +var<storage, read_write> bump: BumpAllocators; @group(0) @binding(2) +var<storage> paths: array<Path>; + +@group(0) @binding(3) var<storage, read_write> tiles: array<Tile>; let WG_SIZE = 256u; @@ -26,6 +30,14 @@ @builtin(global_invocation_id) global_id: vec3<u32>, @builtin(local_invocation_id) local_id: vec3<u32>, ) { + // Abort if any of the prior stages failed. + if local_id.x == 0u { + sh_row_count[0] = atomicLoad(&bump.failed); + } + let failed = workgroupUniformLoad(&sh_row_count[0]); + if failed != 0u { + return; + } let drawobj_ix = global_id.x; var row_count = 0u; if drawobj_ix < config.n_drawobj { @@ -34,6 +46,9 @@ sh_row_width[local_id.x] = path.bbox.z - path.bbox.x; row_count = path.bbox.w - path.bbox.y; sh_offset[local_id.x] = path.tiles; + } else { + // Explicitly zero the row width, just in case. + sh_row_width[local_id.x] = 0u; } sh_row_count[local_id.x] = row_count;
diff --git a/src/cpu_shader/backdrop.rs b/src/cpu_shader/backdrop.rs index dadbbf9..9232e80 100644 --- a/src/cpu_shader/backdrop.rs +++ b/src/cpu_shader/backdrop.rs
@@ -1,11 +1,11 @@ // Copyright 2023 the Vello Authors // SPDX-License-Identifier: Apache-2.0 OR MIT OR Unlicense -use vello_encoding::{ConfigUniform, Path, Tile}; +use vello_encoding::{BumpAllocators, ConfigUniform, Path, Tile}; use crate::cpu_dispatch::CpuBinding; -fn backdrop_main(config: &ConfigUniform, paths: &[Path], tiles: &mut [Tile]) { +fn backdrop_main(config: &ConfigUniform, _: &BumpAllocators, paths: &[Path], tiles: &mut [Tile]) { for drawobj_ix in 0..config.layout.n_draw_objects { let path = paths[drawobj_ix as usize]; let width = path.bbox[2] - path.bbox[0]; @@ -24,7 +24,8 @@ pub fn backdrop(_n_wg: u32, resources: &[CpuBinding]) { let config = resources[0].as_typed(); - let paths = resources[1].as_slice(); - let mut tiles = resources[2].as_slice_mut(); - backdrop_main(&config, &paths, &mut tiles); + let bump = resources[1].as_typed(); + let paths = resources[2].as_slice(); + let mut tiles = resources[3].as_slice_mut(); + backdrop_main(&config, &bump, &paths, &mut tiles); }
diff --git a/src/render.rs b/src/render.rs index 279f145..4e6468e 100644 --- a/src/render.rs +++ b/src/render.rs
@@ -357,7 +357,7 @@ recording.dispatch( shaders.backdrop, wg_counts.backdrop, - [config_buf, path_buf, tile_buf], + [config_buf, bump_buf, path_buf, tile_buf], ); recording.dispatch( shaders.coarse,
diff --git a/src/shaders.rs b/src/shaders.rs index e00c1a9..8220879 100644 --- a/src/shaders.rs +++ b/src/shaders.rs
@@ -226,7 +226,7 @@ ); let backdrop = add_shader!( backdrop_dyn, - [Uniform, BufReadOnly, Buffer], + [Uniform, Buffer, BufReadOnly, Buffer], &empty, CpuShaderType::Present(cpu_shader::backdrop) );