Skip to content

Commit 403b4fb

Browse files
Reimplement all GPU brushes
1 parent 359bc73 commit 403b4fb

38 files changed

Lines changed: 1732 additions & 359 deletions

File tree

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public static unsafe bool TryCreateBindGroupLayout(
6262
out BindGroupLayout* layout,
6363
out string? error)
6464
{
65-
BindGroupLayoutEntry* entries = stackalloc BindGroupLayoutEntry[8];
65+
BindGroupLayoutEntry* entries = stackalloc BindGroupLayoutEntry[9];
6666
entries[0] = CreateUniformEntry(0, (nuint)sizeof(GpuSceneConfig));
6767
entries[1] = CreateStorageEntry(1, BufferBindingType.ReadOnlyStorage, 0);
6868
entries[2] = CreateStorageEntry(2, BufferBindingType.ReadOnlyStorage, 0);
@@ -71,10 +71,11 @@ public static unsafe bool TryCreateBindGroupLayout(
7171
entries[5] = CreateOutputTextureEntry(5, outputTextureFormat);
7272
entries[6] = CreateSampledTextureEntry(6);
7373
entries[7] = CreateSampledTextureEntry(7);
74+
entries[8] = CreateSampledTextureEntry(8);
7475

7576
BindGroupLayoutDescriptor descriptor = new()
7677
{
77-
EntryCount = 8,
78+
EntryCount = 9,
7879
Entries = entries
7980
};
8081

src/ImageSharp.Drawing.WebGPU/Shaders/Shared/drawtag.wgsl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,12 @@ struct DrawMonoid {
1818
// version of the draw monoid.
1919
const DRAWTAG_NOP = 0u;
2020
const DRAWTAG_FILL_COLOR = 0x44u;
21+
const DRAWTAG_FILL_RECOLOR = 0x4cu;
2122
const DRAWTAG_FILL_LIN_GRADIENT = 0x114u;
2223
const DRAWTAG_FILL_RAD_GRADIENT = 0x29cu;
24+
const DRAWTAG_FILL_ELLIPTIC_GRADIENT = 0x1d8u;
2325
const DRAWTAG_FILL_SWEEP_GRADIENT = 0x254u;
24-
const DRAWTAG_FILL_IMAGE = 0x28Cu;
26+
const DRAWTAG_FILL_IMAGE = 0x294u;
2527
const DRAWTAG_BLURRED_ROUNDED_RECT = 0x2d4u;
2628
const DRAWTAG_BEGIN_CLIP = 0x49u;
2729
const DRAWTAG_END_CLIP = 0x21u;

src/ImageSharp.Drawing.WebGPU/Shaders/Shared/ptcl.wgsl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@ const CMD_FILL = 1u;
1515
const CMD_STROKE = 2u;
1616
const CMD_SOLID = 3u;
1717
const CMD_COLOR = 5u;
18+
const CMD_RECOLOR = 14u;
1819
const CMD_LIN_GRAD = 6u;
1920
const CMD_RAD_GRAD = 7u;
21+
const CMD_ELLIPTIC_GRAD = 15u;
2022
const CMD_SWEEP_GRAD = 8u;
2123
const CMD_IMAGE = 9u;
2224
const CMD_BEGIN_CLIP = 10u;
@@ -46,6 +48,12 @@ struct CmdColor {
4648
rgba_color: u32,
4749
}
4850

51+
struct CmdRecolor {
52+
source_color: u32,
53+
target_color: u32,
54+
threshold: f32,
55+
}
56+
4957
struct CmdBlurRect {
5058
// Solid fill color.
5159
rgba_color: u32,
@@ -83,6 +91,13 @@ struct CmdRadGrad {
8391
flags: u32,
8492
}
8593

94+
struct CmdEllipticGrad {
95+
index: u32,
96+
extend_mode: u32,
97+
matrx: vec4<f32>,
98+
xlat: vec2<f32>,
99+
}
100+
86101
struct CmdSweepGrad {
87102
index: u32,
88103
extend_mode: u32,

src/ImageSharp.Drawing.WebGPU/Shaders/coarse.wgsl

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,15 @@ fn write_color(color: CmdColor) {
116116
cmd_offset += 2u;
117117
}
118118

119+
fn write_recolor(source_color: u32, target_color: u32, threshold: u32) {
120+
alloc_cmd(4u);
121+
ptcl[cmd_offset] = CMD_RECOLOR;
122+
ptcl[cmd_offset + 1u] = source_color;
123+
ptcl[cmd_offset + 2u] = target_color;
124+
ptcl[cmd_offset + 3u] = threshold;
125+
cmd_offset += 4u;
126+
}
127+
119128
fn write_grad(ty: u32, index: u32, info_offset: u32) {
120129
alloc_cmd(3u);
121130
ptcl[cmd_offset] = ty;
@@ -381,6 +390,10 @@ fn main(
381390
let rgba_color = scene[dd];
382391
write_color(CmdColor(rgba_color));
383392
}
393+
case DRAWTAG_FILL_RECOLOR: {
394+
write_path(tile, tile_ix, draw_flags);
395+
write_recolor(scene[dd], scene[dd + 1u], scene[dd + 2u]);
396+
}
384397
case DRAWTAG_BLURRED_ROUNDED_RECT: {
385398
write_path(tile, tile_ix, draw_flags);
386399
let rgba_color = scene[dd];
@@ -399,6 +412,12 @@ fn main(
399412
let info_offset = di + 1u;
400413
write_grad(CMD_RAD_GRAD, index, info_offset);
401414
}
415+
case DRAWTAG_FILL_ELLIPTIC_GRADIENT: {
416+
write_path(tile, tile_ix, draw_flags);
417+
let index = scene[dd];
418+
let info_offset = di + 1u;
419+
write_grad(CMD_ELLIPTIC_GRAD, index, info_offset);
420+
}
402421
case DRAWTAG_FILL_SWEEP_GRADIENT: {
403422
write_path(tile, tile_ix, draw_flags);
404423
let index = scene[dd];

src/ImageSharp.Drawing.WebGPU/Shaders/draw_leaf.wgsl

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,8 @@ fn main(
108108
}
109109
let dd = config.drawdata_base + m.scene_offset;
110110
let di = m.info_offset;
111-
if tag_word == DRAWTAG_FILL_COLOR || tag_word == DRAWTAG_FILL_LIN_GRADIENT ||
112-
tag_word == DRAWTAG_FILL_RAD_GRADIENT || tag_word == DRAWTAG_FILL_SWEEP_GRADIENT ||
111+
if tag_word == DRAWTAG_FILL_COLOR || tag_word == DRAWTAG_FILL_RECOLOR || tag_word == DRAWTAG_FILL_LIN_GRADIENT ||
112+
tag_word == DRAWTAG_FILL_RAD_GRADIENT || tag_word == DRAWTAG_FILL_ELLIPTIC_GRADIENT || tag_word == DRAWTAG_FILL_SWEEP_GRADIENT ||
113113
tag_word == DRAWTAG_FILL_IMAGE || tag_word == DRAWTAG_BEGIN_CLIP || tag_word == DRAWTAG_BLURRED_ROUNDED_RECT
114114
{
115115
let bbox = path_bbox[m.path_ix];
@@ -122,6 +122,7 @@ fn main(
122122
var transform = Transform();
123123
let draw_flags = bbox.draw_flags;
124124
if tag_word == DRAWTAG_FILL_LIN_GRADIENT || tag_word == DRAWTAG_FILL_RAD_GRADIENT ||
125+
tag_word == DRAWTAG_FILL_ELLIPTIC_GRADIENT ||
125126
tag_word == DRAWTAG_FILL_SWEEP_GRADIENT || tag_word == DRAWTAG_FILL_IMAGE ||
126127
tag_word == DRAWTAG_BLURRED_ROUNDED_RECT
127128
{
@@ -131,6 +132,9 @@ fn main(
131132
case DRAWTAG_FILL_COLOR: {
132133
info[di] = draw_flags;
133134
}
135+
case DRAWTAG_FILL_RECOLOR: {
136+
info[di] = draw_flags;
137+
}
134138
case DRAWTAG_BEGIN_CLIP: {
135139
info[di] = draw_flags;
136140
}
@@ -231,6 +235,33 @@ fn main(
231235
info[di + 8u] = bitcast<u32>(radius);
232236
info[di + 9u] = bitcast<u32>((flags << 3u) | kind);
233237
}
238+
case DRAWTAG_FILL_ELLIPTIC_GRADIENT: {
239+
info[di] = draw_flags;
240+
var center = bitcast<vec2<f32>>(vec2(scene[dd + 1u], scene[dd + 2u]));
241+
var axis_end = bitcast<vec2<f32>>(vec2(scene[dd + 3u], scene[dd + 4u]));
242+
let axis_ratio = bitcast<f32>(scene[dd + 5u]);
243+
center = transform_apply(transform, center);
244+
axis_end = transform_apply(transform, axis_end);
245+
let dxy = axis_end - center;
246+
let axis = length(dxy);
247+
let inv_axis = 1.0 / axis;
248+
let inv_second_axis = inv_axis / axis_ratio;
249+
let cos_theta = dxy.x * inv_axis;
250+
let sin_theta = dxy.y * inv_axis;
251+
// Map the ellipse to the unit circle so the fill parameter is length(local_xy).
252+
let m0 = cos_theta * inv_axis;
253+
let m1 = sin_theta * inv_second_axis;
254+
let m2 = -sin_theta * inv_axis;
255+
let m3 = cos_theta * inv_second_axis;
256+
let xlat_x = -(m0 * center.x + m2 * center.y);
257+
let xlat_y = -(m1 * center.x + m3 * center.y);
258+
info[di + 1u] = bitcast<u32>(m0);
259+
info[di + 2u] = bitcast<u32>(m1);
260+
info[di + 3u] = bitcast<u32>(m2);
261+
info[di + 4u] = bitcast<u32>(m3);
262+
info[di + 5u] = bitcast<u32>(xlat_x);
263+
info[di + 6u] = bitcast<u32>(xlat_y);
264+
}
234265
case DRAWTAG_FILL_SWEEP_GRADIENT: {
235266
info[di] = draw_flags;
236267
let p0 = bitcast<vec2<f32>>(vec2(scene[dd + 1u], scene[dd + 2u]));
@@ -247,13 +278,12 @@ fn main(
247278
}
248279
case DRAWTAG_FILL_IMAGE: {
249280
info[di] = draw_flags;
250-
let inv = transform_inverse(transform);
251-
info[di + 1u] = bitcast<u32>(inv.matrx.x);
252-
info[di + 2u] = bitcast<u32>(inv.matrx.y);
253-
info[di + 3u] = bitcast<u32>(inv.matrx.z);
254-
info[di + 4u] = bitcast<u32>(inv.matrx.w);
255-
info[di + 5u] = bitcast<u32>(inv.translate.x);
256-
info[di + 6u] = bitcast<u32>(inv.translate.y);
281+
info[di + 1u] = bitcast<u32>(1.0);
282+
info[di + 2u] = bitcast<u32>(0.0);
283+
info[di + 3u] = bitcast<u32>(0.0);
284+
info[di + 4u] = bitcast<u32>(1.0);
285+
info[di + 5u] = bitcast<u32>(-bitcast<f32>(scene[dd + 3u]));
286+
info[di + 6u] = bitcast<u32>(-bitcast<f32>(scene[dd + 4u]));
257287
info[di + 7u] = scene[dd];
258288
info[di + 8u] = scene[dd + 1u];
259289
info[di + 9u] = scene[dd + 2u];

0 commit comments

Comments
 (0)