Skip to content

Commit 0d6f935

Browse files
Add CSR shaders; restructure WebGPU shaders & tests
1 parent 6fbc481 commit 0d6f935

44 files changed

Lines changed: 2489 additions & 2552 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

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

Lines changed: 0 additions & 118 deletions
This file was deleted.

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

Lines changed: 0 additions & 157 deletions
This file was deleted.
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Copyright (c) Six Labors.
2+
// Licensed under the Six Labors Split License.
3+
4+
namespace SixLabors.ImageSharp.Drawing.Processing.Backends;
5+
6+
/// <summary>
7+
/// GPU compute shader that counts edges per CSR band.
8+
/// Each thread processes one edge and atomically increments band counts
9+
/// for each 16-row band the edge overlaps.
10+
/// </summary>
11+
internal static class CsrCountComputeShader
12+
{
13+
private static readonly byte[] CodeBytes =
14+
[
15+
.. """
16+
struct Edge {
17+
x0: i32,
18+
y0: i32,
19+
x1: i32,
20+
y1: i32,
21+
min_row: i32,
22+
max_row: i32,
23+
csr_band_offset: u32,
24+
definition_edge_start: u32,
25+
}
26+
27+
struct CsrConfig {
28+
total_edge_count: u32,
29+
};
30+
31+
@group(0) @binding(0) var<storage, read> edges: array<Edge>;
32+
@group(0) @binding(1) var<storage, read_write> band_counts: array<atomic<u32>>;
33+
@group(0) @binding(2) var<uniform> config: CsrConfig;
34+
35+
@compute @workgroup_size(256, 1, 1)
36+
fn cs_main(@builtin(global_invocation_id) gid: vec3<u32>) {
37+
let edge_idx = gid.x;
38+
if (edge_idx >= config.total_edge_count) {
39+
return;
40+
}
41+
let edge = edges[edge_idx];
42+
if (edge.min_row > edge.max_row) {
43+
return;
44+
}
45+
let min_band = edge.min_row / 16;
46+
let max_band = edge.max_row / 16;
47+
for (var band = min_band; band <= max_band; band++) {
48+
atomicAdd(&band_counts[edge.csr_band_offset + u32(band)], 1u);
49+
}
50+
}
51+
"""u8,
52+
0
53+
];
54+
55+
/// <summary>Gets the WGSL source for this shader as a null-terminated UTF-8 span.</summary>
56+
public static ReadOnlySpan<byte> Code => CodeBytes;
57+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// Copyright (c) Six Labors.
2+
// Licensed under the Six Labors Split License.
3+
4+
namespace SixLabors.ImageSharp.Drawing.Processing.Backends;
5+
6+
/// <summary>
7+
/// GPU compute shader that scatters edge indices into CSR buckets.
8+
/// Each thread processes one edge. For each band the edge overlaps,
9+
/// it atomically claims a slot in <c>csr_indices</c> via a write cursor.
10+
/// </summary>
11+
internal static class CsrScatterComputeShader
12+
{
13+
private static readonly byte[] CodeBytes =
14+
[
15+
.. """
16+
struct Edge {
17+
x0: i32,
18+
y0: i32,
19+
x1: i32,
20+
y1: i32,
21+
min_row: i32,
22+
max_row: i32,
23+
csr_band_offset: u32,
24+
definition_edge_start: u32,
25+
}
26+
27+
struct CsrConfig {
28+
total_edge_count: u32,
29+
};
30+
31+
@group(0) @binding(0) var<storage, read> edges: array<Edge>;
32+
@group(0) @binding(1) var<storage, read> csr_offsets: array<u32>;
33+
@group(0) @binding(2) var<storage, read_write> write_cursors: array<atomic<u32>>;
34+
@group(0) @binding(3) var<storage, read_write> csr_indices: array<u32>;
35+
@group(0) @binding(4) var<uniform> config: CsrConfig;
36+
37+
@compute @workgroup_size(256, 1, 1)
38+
fn cs_main(@builtin(global_invocation_id) gid: vec3<u32>) {
39+
let edge_idx = gid.x;
40+
if (edge_idx >= config.total_edge_count) {
41+
return;
42+
}
43+
let edge = edges[edge_idx];
44+
if (edge.min_row > edge.max_row) {
45+
return;
46+
}
47+
let local_idx = edge_idx - edge.definition_edge_start;
48+
let min_band = edge.min_row / 16;
49+
let max_band = edge.max_row / 16;
50+
for (var band = min_band; band <= max_band; band++) {
51+
let band_offset = edge.csr_band_offset + u32(band);
52+
let offset = csr_offsets[band_offset];
53+
let slot = atomicAdd(&write_cursors[band_offset], 1u);
54+
csr_indices[offset + slot] = local_idx;
55+
}
56+
}
57+
"""u8,
58+
0
59+
];
60+
61+
/// <summary>Gets the WGSL source for this shader as a null-terminated UTF-8 span.</summary>
62+
public static ReadOnlySpan<byte> Code => CodeBytes;
63+
}

0 commit comments

Comments
 (0)