@@ -24,10 +24,6 @@ struct Edge {
2424 y0: i32,
2525 x1: i32,
2626 y1: i32,
27- min_row: i32,
28- max_row: i32,
29- csr_band_offset: u32,
30- definition_edge_start: u32,
3127 }
3228
3329 struct Params {
@@ -82,8 +78,7 @@ struct DispatchConfig {
8278 @group(0) @binding(3) var output_texture: texture_storage_2d<__OUTPUT_FORMAT__, write>;
8379 @group(0) @binding(4) var<storage, read> commands: array<Params>;
8480 @group(0) @binding(5) var<uniform> dispatch_config: DispatchConfig;
85- @group(0) @binding(6) var<storage, read> csr_offsets: array<u32>;
86- @group(0) @binding(7) var<storage, read> csr_indices: array<u32>;
81+ @group(0) @binding(6) var<storage, read> band_offsets: array<u32>;
8782
8883 // Workgroup shared memory for per-tile coverage accumulation.
8984 // Layout: 16 rows x 16 columns. Index = row * 16 + col.
@@ -859,35 +854,24 @@ fn cs_main(
859854
860855 // Determine this tile's position in coverage-local space.
861856 let band_top = tile_min_y - command.edge_origin_y;
862- let band_bottom = band_top + 16;
863857 let band_left_fixed = (tile_min_x - command.edge_origin_x) << FIXED_SHIFT;
864858
865- // CSR band lookup: which 16-row bands overlap this tile?
859+ // Band lookup: when edge_origin_y is 16-aligned the tile maps to one band;
860+ // otherwise it can overlap two bands.
866861 var first_band = band_top / 16;
867862 if band_top < 0 && (band_top % 16) != 0 {
868863 first_band -= 1;
869864 }
870865 first_band = max(first_band, 0);
871- var last_band = (band_bottom - 1) / 16;
872- if band_bottom - 1 < 0 && ((band_bottom - 1) % 16) != 0 {
873- last_band -= 1;
874- }
875- last_band = min(last_band, i32(command.csr_band_count) - 1);
866+ let last_band = min((band_top + 15) / 16, i32(command.csr_band_count) - 1);
876867
877- // Early exit: skip if no CSR bands have edges for this tile (uniform).
878868 if first_band > last_band {
879869 continue;
880870 }
881- var tile_has_edges = false;
882- for (var b = first_band; b <= last_band; b++) {
883- let s = csr_offsets[command.csr_offsets_start + u32(b)];
884- let e = csr_offsets[command.csr_offsets_start + u32(b) + 1u];
885- if e > s {
886- tile_has_edges = true;
887- break;
888- }
889- }
890- if !tile_has_edges {
871+
872+ let edge_range_start = band_offsets[command.csr_offsets_start + u32(first_band)];
873+ let edge_range_end = band_offsets[command.csr_offsets_start + u32(last_band) + 1u];
874+ if edge_range_start == edge_range_end {
891875 continue;
892876 }
893877
@@ -899,37 +883,33 @@ fn cs_main(
899883 }
900884 workgroupBarrier();
901885
902- // Cooperatively rasterize edges from the relevant CSR bands .
886+ // Cooperatively rasterize edges from each overlapping band .
903887 let tile_top_fixed = band_top << FIXED_SHIFT;
904888 let tile_bottom_fixed = tile_top_fixed + (i32(16) << FIXED_SHIFT);
905889 let tile_right_fixed = band_left_fixed + (i32(16) << FIXED_SHIFT);
890+
906891 for (var band = first_band; band <= last_band; band++) {
907- let csr_start = csr_offsets[command.csr_offsets_start + u32(band)];
908- let csr_end = csr_offsets[command.csr_offsets_start + u32(band) + 1u];
909- let band_edge_count = csr_end - csr_start;
910- let csr_band_top_fixed = (band * 16) << FIXED_SHIFT;
892+ let b_start = band_offsets[command.csr_offsets_start + u32(band)];
893+ let b_end = band_offsets[command.csr_offsets_start + u32(band) + 1u];
894+ let b_count = b_end - b_start;
895+
896+ let csr_band_top_fixed = band * (i32(16) << FIXED_SHIFT);
911897 let csr_band_bottom_fixed = csr_band_top_fixed + (i32(16) << FIXED_SHIFT);
912898 let clip_top = max(tile_top_fixed, csr_band_top_fixed);
913899 let clip_bottom = min(tile_bottom_fixed, csr_band_bottom_fixed);
900+
914901 var ei = thread_id;
915902 loop {
916- if ei >= band_edge_count {
903+ if ei >= b_count {
917904 break;
918905 }
919- let edge_local_idx = csr_indices[csr_start + ei];
920- let edge = edges[command.edge_start + edge_local_idx];
921-
922- // X-range spatial filter: skip edges that cannot affect this tile.
906+ let edge = edges[command.edge_start + b_start + ei];
923907 if min(edge.x0, edge.x1) >= tile_right_fixed {
924- // Edge entirely right of tile: no contribution.
925908 } else if max(edge.x0, edge.x1) < band_left_fixed {
926- // Edge entirely left of tile: only affects start_cover.
927909 accumulate_start_cover(edge.y0, edge.y1, clip_top, clip_bottom, tile_top_fixed);
928910 } else {
929- // Edge overlaps tile: full rasterization.
930911 rasterize_edge(edge, band_top, band_left_fixed, clip_top, clip_bottom);
931912 }
932-
933913 ei += 256u;
934914 }
935915 }
0 commit comments