Skip to content

Commit 8da2642

Browse files
Pre-split edges into band-sorted buffers (remove CSR)
1 parent bb7311e commit 8da2642

4 files changed

Lines changed: 199 additions & 428 deletions

File tree

src/ImageSharp.Drawing.WebGPU/Shaders/CompositeComputeShader.cs

Lines changed: 18 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)