From 44327fe49fe9fa5d48420f83a48510c77c7e2939 Mon Sep 17 00:00:00 2001 From: Raph Levien Date: Thu, 2 Dec 2021 15:07:33 -0800 Subject: [PATCH] Beginnings of new element pipeline This successfully renders the tiger; fills and strokes are supported. Other parts of the imaging model, not yet. Progress toward #119 --- piet-gpu/bin/cli.rs | 4 +- piet-gpu/shader/backdrop.spv | Bin 12592 -> 12636 bytes piet-gpu/shader/backdrop_lg.spv | Bin 12624 -> 12668 bytes piet-gpu/shader/bbox_clear.comp | 4 +- piet-gpu/shader/binning.spv | Bin 16372 -> 16416 bytes piet-gpu/shader/build.ninja | 4 +- piet-gpu/shader/coarse.spv | Bin 64156 -> 64200 bytes piet-gpu/shader/draw_leaf.comp | 86 ++- piet-gpu/shader/elements.comp | 2 +- piet-gpu/shader/elements.spv | Bin 81072 -> 81476 bytes piet-gpu/shader/gen/bbox_clear.dxil | Bin 3152 -> 3160 bytes piet-gpu/shader/gen/bbox_clear.hlsl | 17 +- piet-gpu/shader/gen/bbox_clear.msl | 17 +- piet-gpu/shader/gen/bbox_clear.spv | Bin 2688 -> 2748 bytes piet-gpu/shader/gen/draw_leaf.dxil | Bin 4428 -> 6908 bytes piet-gpu/shader/gen/draw_leaf.hlsl | 622 +++++++++++++++++++-- piet-gpu/shader/gen/draw_leaf.msl | 623 +++++++++++++++++++++- piet-gpu/shader/gen/draw_leaf.spv | Bin 8536 -> 38596 bytes piet-gpu/shader/gen/draw_reduce.hlsl | 3 +- piet-gpu/shader/gen/draw_reduce.msl | 3 +- piet-gpu/shader/gen/draw_reduce.spv | Bin 6864 -> 6908 bytes piet-gpu/shader/gen/pathseg.dxil | Bin 9428 -> 9596 bytes piet-gpu/shader/gen/pathseg.hlsl | 144 ++--- piet-gpu/shader/gen/pathseg.msl | 104 ++-- piet-gpu/shader/gen/pathseg.spv | Bin 33960 -> 34748 bytes piet-gpu/shader/gen/pathtag_reduce.dxil | Bin 4700 -> 4700 bytes piet-gpu/shader/gen/pathtag_reduce.hlsl | 25 +- piet-gpu/shader/gen/pathtag_reduce.msl | 19 +- piet-gpu/shader/gen/pathtag_reduce.spv | Bin 7808 -> 7836 bytes piet-gpu/shader/gen/transform_leaf.dxil | Bin 5664 -> 5664 bytes piet-gpu/shader/gen/transform_leaf.hlsl | 5 +- piet-gpu/shader/gen/transform_leaf.msl | 3 +- piet-gpu/shader/gen/transform_leaf.spv | Bin 12480 -> 12524 bytes piet-gpu/shader/gen/transform_reduce.dxil | Bin 4696 -> 4696 bytes piet-gpu/shader/gen/transform_reduce.hlsl | 5 +- piet-gpu/shader/gen/transform_reduce.msl | 3 +- piet-gpu/shader/gen/transform_reduce.spv | Bin 7832 -> 7876 bytes piet-gpu/shader/kernel4.spv | Bin 39080 -> 39124 bytes piet-gpu/shader/path_coarse.comp | 3 + piet-gpu/shader/path_coarse.spv | Bin 43400 -> 39324 bytes piet-gpu/shader/pathseg.comp | 23 +- piet-gpu/shader/setup.h | 6 +- piet-gpu/shader/tile_alloc.spv | Bin 15148 -> 15192 bytes piet-gpu/src/encoder.rs | 199 +++++++ piet-gpu/src/lib.rs | 125 ++--- piet-gpu/src/render_ctx.rs | 195 +++---- piet-gpu/src/stages.rs | 108 +++- piet-gpu/src/stages/draw.rs | 2 +- piet-gpu/src/stages/path.rs | 13 +- piet-gpu/src/stages/transform.rs | 5 + tests/src/draw.rs | 7 +- tests/src/path.rs | 28 +- 52 files changed, 1956 insertions(+), 451 deletions(-) create mode 100644 piet-gpu/src/encoder.rs diff --git a/piet-gpu/bin/cli.rs b/piet-gpu/bin/cli.rs index c48f65f..60c9660 100644 --- a/piet-gpu/bin/cli.rs +++ b/piet-gpu/bin/cli.rs @@ -276,8 +276,8 @@ fn main() -> Result<(), Error> { /* let mut data: Vec = Default::default(); - renderer.tile_buf.read(&mut data).unwrap(); - piet_gpu::dump_k1_data(&data); + renderer.memory_buf_dev.read(&mut data).unwrap(); + piet_gpu::dump_k1_data(&data[2..]); trace_ptcl(&data); */ diff --git a/piet-gpu/shader/backdrop.spv b/piet-gpu/shader/backdrop.spv index 4dd01ed09041003f552686fe65cb30abee67e2bd..a1ed3320f81fcf8b024ac9e673006b6b4ce80a45 100644 GIT binary patch delta 105 zcmdmxbSG&;9lH)I!*&J+23{b}i!Vql$zWh$V_*l1@d3q3iW2jRH(Ln&Pyhg4)fv(N delta 77 zcmcbUv>|Cj9Xmfe!*&J+23{a8DN4*Mo_vs9ScnhED@ZKKC`n9@&reG$PA!?dirr}Q f5B6Own~(8?Ff$7?Y@Zw`AUxSXz+`iVz!wDorfnF( diff --git a/piet-gpu/shader/backdrop_lg.spv b/piet-gpu/shader/backdrop_lg.spv index b00e3cd68b5eeca1a1554487c6e1a4fb0e15daeb..457cb02e46cffa7a0fad71b0630bcc7f250234c7 100644 GIT binary patch delta 105 zcmcbR^e1UU9lH)I!*&J+23{b}i!Vql$zWh$V_*l1@d3q3iW2jRH(LluC;|X?78x@D delta 77 zcmey9bRlU&9Xmfe!*&J+23{a8DN4*Mo_vs9ScnhED@ZKKC`n9@&reG$PA!?dirr}Q f5B6Own~(8?Ff$7?Y@Zw`AUxSXz+`iVfQTXhx2_l> diff --git a/piet-gpu/shader/bbox_clear.comp b/piet-gpu/shader/bbox_clear.comp index 4ac5062..c609642 100644 --- a/piet-gpu/shader/bbox_clear.comp +++ b/piet-gpu/shader/bbox_clear.comp @@ -19,8 +19,8 @@ layout(binding = 1) readonly buffer ConfigBuf { void main() { uint ix = gl_GlobalInvocationID.x; - if (ix < conf.n_elements) { - uint out_ix = (conf.bbox_alloc.offset >> 2) + 4 * ix; + if (ix < conf.n_path) { + uint out_ix = (conf.bbox_alloc.offset >> 2) + 6 * ix; memory[out_ix] = 0xffff; memory[out_ix + 1] = 0xffff; memory[out_ix + 2] = 0; diff --git a/piet-gpu/shader/binning.spv b/piet-gpu/shader/binning.spv index 38d10b372c31dfd40157815a30b97eee8b316662..5ec7aec1bbb810f495c2e8ea6b4b0f14dd863c98 100644 GIT binary patch delta 110 zcmexTzo3C}gCD03E5k1a1_oXr&WkTdEXiPCU}Inhi}3-)N{SNmisSRs(uz|{7#Jou zaT-mo;N)Y6C=lGdmNS=?A7X+aP_;4;yKENa-^t7t-kZEzHcq48JBD3JXu>5jNTEB78>&0HISC^Z)<= diff --git a/piet-gpu/shader/build.ninja b/piet-gpu/shader/build.ninja index 1df1876..497915c 100644 --- a/piet-gpu/shader/build.ninja +++ b/piet-gpu/shader/build.ninja @@ -25,7 +25,7 @@ rule msl build elements.spv: glsl elements.comp | scene.h state.h annotated.h -build binning.spv: glsl binning.comp | annotated.h state.h bins.h setup.h +build binning.spv: glsl binning.comp | annotated.h state.h bins.h setup.h mem.h build tile_alloc.spv: glsl tile_alloc.comp | annotated.h tile.h setup.h @@ -90,7 +90,7 @@ build gen/draw_root.hlsl: hlsl gen/draw_root.spv build gen/draw_root.dxil: dxil gen/draw_root.hlsl build gen/draw_root.msl: msl gen/draw_root.spv -build gen/draw_leaf.spv: glsl draw_leaf.comp | scene.h drawtag.h setup.h mem.h +build gen/draw_leaf.spv: glsl draw_leaf.comp | scene.h drawtag.h annotated.h setup.h mem.h build gen/draw_leaf.hlsl: hlsl gen/draw_leaf.spv build gen/draw_leaf.dxil: dxil gen/draw_leaf.hlsl build gen/draw_leaf.msl: msl gen/draw_leaf.spv diff --git a/piet-gpu/shader/coarse.spv b/piet-gpu/shader/coarse.spv index a2071ad5468f95741035f45785e3e17d0dffb073..8d4f7c07d368e18d09344ad3fd846eae873874c0 100644 GIT binary patch delta 107 zcmbR9mHEV1<_&rpI;;%$SQr?185kJy;tLW>G8h=x7}&vLd_b|1qQt!7`24iA;?xob xhRI19Mw25n_}C!|1UL6;oaN((m>>vLtqjC2n?ucQxfn$zPj>X&e8cg`4gkuD8?^uc delta 73 zcmX@{m3hur<_&rp{Ok<(SQr?185kH!iW2jRCl_i63-JMY1&JjYC5h?r`DtmzsU?%6 dG>kT{&^X4oxyjsui&1#;Zb#3}98L#z0031{7-Ikc diff --git a/piet-gpu/shader/draw_leaf.comp b/piet-gpu/shader/draw_leaf.comp index ec6a928..85d9528 100644 --- a/piet-gpu/shader/draw_leaf.comp +++ b/piet-gpu/shader/draw_leaf.comp @@ -28,6 +28,7 @@ layout(binding = 2) readonly buffer SceneBuf { #include "scene.h" #include "tile.h" #include "drawtag.h" +#include "annotated.h" #define Monoid DrawMonoid @@ -70,10 +71,93 @@ void main() { if (gl_LocalInvocationID.x > 0) { row = combine_tag_monoid(row, sh_scratch[gl_LocalInvocationID.x - 1]); } - uint out_base = (conf.drawmonoid_alloc.offset >> 2) + gl_GlobalInvocationID.x * 2 * N_ROWS; + uint out_ix = gl_GlobalInvocationID.x * N_ROWS; + uint out_base = (conf.drawmonoid_alloc.offset >> 2) + out_ix * 2; + AnnotatedRef out_ref = AnnotatedRef(conf.anno_alloc.offset + out_ix * Annotated_size); for (uint i = 0; i < N_ROWS; i++) { Monoid m = combine_tag_monoid(row, local[i]); memory[out_base + i * 2] = m.path_ix; memory[out_base + i * 2 + 1] = m.clip_ix; + + // For compatibility, we'll generate an Annotated object, same as old + // pipeline. However, going forward we'll get rid of that, and have + // later stages read scene + bbox etc. + ElementRef this_ref = Element_index(ref, i); + tag_word = Element_tag(this_ref).tag; + if (tag_word == Element_FillColor || tag_word == Element_FillLinGradient || tag_word == Element_FillImage) { + uint bbox_offset = (conf.bbox_alloc.offset >> 2) + 6 * (m.path_ix - 1); + float bbox_l = float(memory[bbox_offset]) - 32768.0; + float bbox_t = float(memory[bbox_offset + 1]) - 32768.0; + float bbox_r = float(memory[bbox_offset + 2]) - 32768.0; + float bbox_b = float(memory[bbox_offset + 3]) - 32768.0; + vec4 bbox = vec4(bbox_l, bbox_t, bbox_r, bbox_b); + float linewidth = uintBitsToFloat(memory[bbox_offset + 4]); + uint fill_mode = uint(linewidth >= 0.0); + vec4 mat; + vec2 translate; + if (linewidth >= 0.0 || tag_word == Element_FillLinGradient) { + uint trans_ix = memory[bbox_offset + 5]; + uint t = (conf.trans_alloc.offset >> 2) + 6 * trans_ix; + mat = uintBitsToFloat(uvec4(memory[t], memory[t + 1], memory[t + 2], memory[t + 3])); + if (tag_word == Element_FillLinGradient) { + translate = uintBitsToFloat(uvec2(memory[t + 4], memory[t + 5])); + } + } + if (linewidth >= 0.0) { + // TODO: need to deal with anisotropic case + linewidth *= sqrt(abs(mat.x * mat.w - mat.y * mat.z)); + } + linewidth = max(linewidth, 0.0); + switch (tag_word) { + case Element_FillColor: + FillColor fill = Element_FillColor_read(this_ref); + AnnoColor anno_fill; + anno_fill.bbox = bbox; + anno_fill.linewidth = linewidth; + anno_fill.rgba_color = fill.rgba_color; + Annotated_Color_write(conf.anno_alloc, out_ref, fill_mode, anno_fill); + break; + case Element_FillLinGradient: + FillLinGradient lin = Element_FillLinGradient_read(this_ref); + AnnoLinGradient anno_lin; + anno_lin.bbox = bbox; + anno_lin.linewidth = linewidth; + anno_lin.index = lin.index; + vec2 p0 = mat.xy * lin.p0.x + mat.zw * lin.p0.y + translate; + vec2 p1 = mat.xy * lin.p1.x + mat.zw * lin.p1.y + translate; + vec2 dxy = p1 - p0; + float scale = 1.0 / (dxy.x * dxy.x + dxy.y * dxy.y); + float line_x = dxy.x * scale; + float line_y = dxy.y * scale; + anno_lin.line_x = line_x; + anno_lin.line_y = line_y; + anno_lin.line_c = -(p0.x * line_x + p0.y * line_y); + Annotated_LinGradient_write(conf.anno_alloc, out_ref, fill_mode, anno_lin); + break; + case Element_FillImage: + FillImage fill_img = Element_FillImage_read(this_ref); + AnnoImage anno_img; + anno_img.bbox = bbox; + anno_img.linewidth = linewidth; + anno_img.index = fill_img.index; + anno_img.offset = fill_img.offset; + Annotated_Image_write(conf.anno_alloc, out_ref, fill_mode, anno_img); + break; + } + } else if (tag_word == Element_BeginClip) { + Clip begin_clip = Element_BeginClip_read(this_ref); + AnnoBeginClip anno_begin_clip; + // This is the absolute bbox, it's been transformed during encoding. + anno_begin_clip.bbox = begin_clip.bbox; + anno_begin_clip.linewidth = 0.0; // don't support clip-with-stroke + Annotated_BeginClip_write(conf.anno_alloc, out_ref, 0, anno_begin_clip); + } else if (tag_word == Element_EndClip) { + Clip end_clip = Element_EndClip_read(this_ref); + AnnoEndClip anno_end_clip; + // This bbox is expected to be the same as the begin one. + anno_end_clip.bbox = end_clip.bbox; + Annotated_EndClip_write(conf.anno_alloc, out_ref, anno_end_clip); + } + out_ref.offset += Annotated_size; } } diff --git a/piet-gpu/shader/elements.comp b/piet-gpu/shader/elements.comp index 873fc41..6f33544 100644 --- a/piet-gpu/shader/elements.comp +++ b/piet-gpu/shader/elements.comp @@ -445,7 +445,7 @@ void main() { vec2 lw = get_linewidth(st); anno_begin_clip.linewidth = st.linewidth * sqrt(abs(st.mat.x * st.mat.w - st.mat.y * st.mat.z)); } else { - anno_fill.linewidth = 0.0; + anno_begin_clip.linewidth = 0.0; } out_ref = AnnotatedRef(conf.anno_alloc.offset + (st.path_count - 1) * Annotated_size); Annotated_BeginClip_write(conf.anno_alloc, out_ref, fill_mode, anno_begin_clip); diff --git a/piet-gpu/shader/elements.spv b/piet-gpu/shader/elements.spv index 37cc05108a7d6805a08ce6e63808096dc1b8f785..f906dac2bed79e34763736d9e148541190bdd856 100644 GIT binary patch delta 439 zcmdn+ljX=CmJJ*x^=u4m3>91q3_!$?l$2i)pO}-ApUeOh0NMY<`~;e%n=djJGm1V9V432^a6*jZswBfK zV+Mvw2?mDv$!|HFC(mIPkPklc&|597$v{C`$SJZTF@Yn&`GSvtR>xs+-?J==g_BP+ zYcjr`{FPa^-rP|_La8LRB0eWSF-5p#VWLxb+jmpo7Di|1)**F=R5*C#7O-Q}c;mFjWAfa(jIV0LM zDS<(OgN;SPf+z|b<$a=U5?D+5CU z11m!;P|793(}w{_3jkHc0L7i058PAaVPFWEype6s=8KHQjH0d%nJf)CjRA8R7g#a_ zl~qbGFvLy%$l*MB4zqx~@R5h!YH3Xd3erMOksXN%90|@Bd<0gt9~S35%c7V$`82a8 zlhb5i;Pc|thkegp+yyU7tiJ<97+&qHdJ6$=Rji&RSC^>Awgp zaRGV!2s9uH(E?%(Qb1&E-pF>IrQR6mabXr`9Z)!N0I^9LgO}lgCtQXL{`}|nGGDMj zYoP+yVh65PAI=`2G=nl5Cqq-hf}Ea$*h?LbObrSW8ZpWVH%*cf7!)|zTDGSsvvB|w zTqx;V;JTQT(cq2&ONzm10gi(mj3C7(2?C;grn3YXQVYVJ7(`t{qa0b3*?56EK1^{u z#xiSZ=B!{Rn8=LAYb>|7=H3o=hKbBM_>3h+vOtDiRPbPjBQwxIn~Vdtj_GW%*IhTW KFfoB#2m}C5DZ5Aj diff --git a/piet-gpu/shader/gen/bbox_clear.hlsl b/piet-gpu/shader/gen/bbox_clear.hlsl index 7a4e86a..903a185 100644 --- a/piet-gpu/shader/gen/bbox_clear.hlsl +++ b/piet-gpu/shader/gen/bbox_clear.hlsl @@ -18,16 +18,17 @@ struct Config Alloc bbox_alloc; Alloc drawmonoid_alloc; uint n_trans; + uint n_path; uint trans_offset; - uint pathtag_offset; uint linewidth_offset; + uint pathtag_offset; uint pathseg_offset; }; static const uint3 gl_WorkGroupSize = uint3(512u, 1u, 1u); ByteAddressBuffer _21 : register(t1); -RWByteAddressBuffer _44 : register(u0); +RWByteAddressBuffer _45 : register(u0); static uint3 gl_GlobalInvocationID; struct SPIRV_Cross_Input @@ -38,13 +39,13 @@ struct SPIRV_Cross_Input void comp_main() { uint ix = gl_GlobalInvocationID.x; - if (ix < _21.Load(0)) + if (ix < _21.Load(52)) { - uint out_ix = (_21.Load(40) >> uint(2)) + (4u * ix); - _44.Store(out_ix * 4 + 8, 65535u); - _44.Store((out_ix + 1u) * 4 + 8, 65535u); - _44.Store((out_ix + 2u) * 4 + 8, 0u); - _44.Store((out_ix + 3u) * 4 + 8, 0u); + uint out_ix = (_21.Load(40) >> uint(2)) + (6u * ix); + _45.Store(out_ix * 4 + 8, 65535u); + _45.Store((out_ix + 1u) * 4 + 8, 65535u); + _45.Store((out_ix + 2u) * 4 + 8, 0u); + _45.Store((out_ix + 3u) * 4 + 8, 0u); } } diff --git a/piet-gpu/shader/gen/bbox_clear.msl b/piet-gpu/shader/gen/bbox_clear.msl index 6f73531..9af5b11 100644 --- a/piet-gpu/shader/gen/bbox_clear.msl +++ b/piet-gpu/shader/gen/bbox_clear.msl @@ -23,9 +23,10 @@ struct Config Alloc bbox_alloc; Alloc drawmonoid_alloc; uint n_trans; + uint n_path; uint trans_offset; - uint pathtag_offset; uint linewidth_offset; + uint pathtag_offset; uint pathseg_offset; }; @@ -43,16 +44,16 @@ struct Memory constant uint3 gl_WorkGroupSize [[maybe_unused]] = uint3(512u, 1u, 1u); -kernel void main0(device Memory& _44 [[buffer(0)]], const device ConfigBuf& _21 [[buffer(1)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]]) +kernel void main0(device Memory& _45 [[buffer(0)]], const device ConfigBuf& _21 [[buffer(1)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]]) { uint ix = gl_GlobalInvocationID.x; - if (ix < _21.conf.n_elements) + if (ix < _21.conf.n_path) { - uint out_ix = (_21.conf.bbox_alloc.offset >> uint(2)) + (4u * ix); - _44.memory[out_ix] = 65535u; - _44.memory[out_ix + 1u] = 65535u; - _44.memory[out_ix + 2u] = 0u; - _44.memory[out_ix + 3u] = 0u; + uint out_ix = (_21.conf.bbox_alloc.offset >> uint(2)) + (6u * ix); + _45.memory[out_ix] = 65535u; + _45.memory[out_ix + 1u] = 65535u; + _45.memory[out_ix + 2u] = 0u; + _45.memory[out_ix + 3u] = 0u; } } diff --git a/piet-gpu/shader/gen/bbox_clear.spv b/piet-gpu/shader/gen/bbox_clear.spv index 2b659f4150af48bb12a07b6376675f7eca199a18..c4595020a0486470934ae2a053384d4b4702108c 100644 GIT binary patch literal 2748 zcmaKs*>2NN5Qa~iqy!3-rR-2#3S}?*zLrG+si+q`faNA`Yss;z#AUhTf(POmcqtYM z!T;Hw=BO7OX>?}(Sg;#pLY$j)6Xo4mdcU+VEP4yK?_9@X zuWOWs*i6Z$rMoHWM@fcaQnXJv*nWU~3s?!{T!q zhiQ_Tc3IC_8g|lrB}(6BAM$Qg zBzgAsm2B{(#>F(vySjNzS+n?jb#)jQmCXUkFY|0QS;J<+A#<`YPUC)@6~htETeEN@ zD%OXw%w@f!wCCL)lU}hNCRtb{XDg|P9#2H&Zk0ZJN{q@zz1l0R%4<_VSLK+Jjvc9b>FcXr?vtKqMYI;0)_TBf ztp}!Ssg8rftNFgzToq4kV4SYz&dpvOg3)1b0^Rwh23GD_(_NPQF7D@p&-hQ2vLM%w z`(7Ot&W?b`gF!wJPd@zF5#ePF@?Dk8=_nt)g-(jz$lmsJPBI6~_HsK$J}`F4?8pVi z>VeB5*w1=^GU`IWSoddI)sgHbMfym;qXJBVNj2#2J;9)hSSmPz#1jrEcfON z3LR$29?goF3-Tr1^v~wQE^sU!?*iLCM=*bm-GWaeV;J}f>EQ5$t59}#g(X8zPqJbH*PIj6<3^JX_I zp1zpOo@0xQ{k(|#lxnnHn5kzD4uO-0-LHJBx{;ZyAMcvvzkf&ZZ%Vdz5bN$X`-hU5 zpVjk3JOQsLGjn85z=#9gRc+*BUpe^x6vBUjUa}v2=iDX-wY(@RddBz2Ua$*K>OSy2 zfZ|5x(F*6!)}l&Tr*JHzNY0e)vUI zP5d(=i_iSXV>#w({deV{pXWqi%++kpi>KbNwao?b^CIvsHFi-vzUX*!pc~9$EQklQ zH}j8U*5pBl4;b?{pBv%>k>$809*ntJ9R7jwV={}1<~iNW8Q_Q|w4dFP&c-?{g_H{YsT)p8Wh6wLw~v68KRDZdO46>Zea z${^{tpKrSDurhj(=tVnunzWy^dK(*?oy2_#7u`;{J~c_I_bO>Udu>**eKtq@u+#1J z-ewj$Fvf3|q6iDtAAk zO4XaqpzdY13ze)*gn9?P&N>bB^YPRm%;KgC;`c$teTeV5pYemV#-8KkHBJnU!cMWy zqaS0ffstIS?y6N@^=E;m8RrOo?up?Ml^3L|&pfO4>Le?JIL!vm8(t*2ySvxm3bF3c zH(Y|}>u(V2@IHSFu7WzP_d}aNntX%?!)d>UHgmU2v%#e6mhPvzg%h9(#)fE8rW2e5 z%6(?DZs#;O45a^}{RFFif2db(97x-tmH3(!vs>0nc>fw)eTF^K?AcWCohE8}222B8 zxgTT}UIOoiHRs@Z0_j^r?L1t2m0M*veXG*E#{yj18eMegOQ3G)pplZ=BvDV{H(iEn zlW(#Jm!>QAMpxnb{xq=i@{yMJxkjA#X%I_WqW^!R>u_(R0vSm=0Q^A9@VwDYVrlvw b{6H&k@1wkYq{-(uPvf6RYw0ha*)sSCPRLcg diff --git a/piet-gpu/shader/gen/draw_leaf.dxil b/piet-gpu/shader/gen/draw_leaf.dxil index 17bace791dbb74eb82af09a2c637f0ac09ca665f..f95e5bcfcdd97577ea4addb88b9a791740cf430c 100644 GIT binary patch literal 6908 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 ZBu&wA4U-Y<^&p>zZ|Am%WV=2*{sZO}B254Q diff --git a/piet-gpu/shader/gen/draw_leaf.hlsl b/piet-gpu/shader/gen/draw_leaf.hlsl index e5f50fd..0ef9538 100644 --- a/piet-gpu/shader/gen/draw_leaf.hlsl +++ b/piet-gpu/shader/gen/draw_leaf.hlsl @@ -1,8 +1,56 @@ +struct Alloc +{ + uint offset; +}; + struct ElementRef { uint offset; }; +struct FillColorRef +{ + uint offset; +}; + +struct FillColor +{ + uint rgba_color; +}; + +struct FillLinGradientRef +{ + uint offset; +}; + +struct FillLinGradient +{ + uint index; + float2 p0; + float2 p1; +}; + +struct FillImageRef +{ + uint offset; +}; + +struct FillImage +{ + uint index; + int2 offset; +}; + +struct ClipRef +{ + uint offset; +}; + +struct Clip +{ + float4 bbox; +}; + struct ElementTag { uint tag; @@ -15,7 +63,68 @@ struct DrawMonoid uint clip_ix; }; -struct Alloc +struct AnnoImageRef +{ + uint offset; +}; + +struct AnnoImage +{ + float4 bbox; + float linewidth; + uint index; + int2 offset; +}; + +struct AnnoColorRef +{ + uint offset; +}; + +struct AnnoColor +{ + float4 bbox; + float linewidth; + uint rgba_color; +}; + +struct AnnoLinGradientRef +{ + uint offset; +}; + +struct AnnoLinGradient +{ + float4 bbox; + float linewidth; + uint index; + float line_x; + float line_y; + float line_c; +}; + +struct AnnoBeginClipRef +{ + uint offset; +}; + +struct AnnoBeginClip +{ + float4 bbox; + float linewidth; +}; + +struct AnnoEndClipRef +{ + uint offset; +}; + +struct AnnoEndClip +{ + float4 bbox; +}; + +struct AnnotatedRef { uint offset; }; @@ -35,23 +144,24 @@ struct Config Alloc bbox_alloc; Alloc drawmonoid_alloc; uint n_trans; + uint n_path; uint trans_offset; - uint pathtag_offset; uint linewidth_offset; + uint pathtag_offset; uint pathseg_offset; }; static const uint3 gl_WorkGroupSize = uint3(512u, 1u, 1u); -static const DrawMonoid _67 = { 0u, 0u }; -static const DrawMonoid _94 = { 1u, 0u }; -static const DrawMonoid _96 = { 1u, 1u }; -static const DrawMonoid _98 = { 0u, 1u }; +static const DrawMonoid _418 = { 0u, 0u }; +static const DrawMonoid _443 = { 1u, 0u }; +static const DrawMonoid _445 = { 1u, 1u }; +static const DrawMonoid _447 = { 0u, 1u }; -ByteAddressBuffer _49 : register(t2); -ByteAddressBuffer _218 : register(t3); -ByteAddressBuffer _248 : register(t1); -RWByteAddressBuffer _277 : register(u0); +RWByteAddressBuffer _201 : register(u0); +ByteAddressBuffer _225 : register(t2); +ByteAddressBuffer _1008 : register(t3); +ByteAddressBuffer _1042 : register(t1); static uint3 gl_WorkGroupID; static uint3 gl_LocalInvocationID; @@ -67,9 +177,9 @@ groupshared DrawMonoid sh_scratch[512]; ElementTag Element_tag(ElementRef ref) { - uint tag_and_flags = _49.Load((ref.offset >> uint(2)) * 4 + 0); - ElementTag _63 = { tag_and_flags & 65535u, tag_and_flags >> uint(16) }; - return _63; + uint tag_and_flags = _225.Load((ref.offset >> uint(2)) * 4 + 0); + ElementTag _375 = { tag_and_flags & 65535u, tag_and_flags >> uint(16) }; + return _375; } DrawMonoid map_tag(uint tag_word) @@ -80,27 +190,27 @@ DrawMonoid map_tag(uint tag_word) case 5u: case 6u: { - return _94; + return _443; } case 9u: { - return _96; + return _445; } case 10u: { - return _98; + return _447; } default: { - return _67; + return _418; } } } ElementRef Element_index(ElementRef ref, uint index) { - ElementRef _42 = { ref.offset + (index * 36u) }; - return _42; + ElementRef _214 = { ref.offset + (index * 36u) }; + return _214; } DrawMonoid combine_tag_monoid(DrawMonoid a, DrawMonoid b) @@ -113,14 +223,326 @@ DrawMonoid combine_tag_monoid(DrawMonoid a, DrawMonoid b) DrawMonoid tag_monoid_identity() { - return _67; + return _418; +} + +FillColor FillColor_read(FillColorRef ref) +{ + uint ix = ref.offset >> uint(2); + uint raw0 = _225.Load((ix + 0u) * 4 + 0); + FillColor s; + s.rgba_color = raw0; + return s; +} + +FillColor Element_FillColor_read(ElementRef ref) +{ + FillColorRef _381 = { ref.offset + 4u }; + FillColorRef param = _381; + return FillColor_read(param); +} + +bool touch_mem(Alloc alloc, uint offset) +{ + return true; +} + +void write_mem(Alloc alloc, uint offset, uint val) +{ + Alloc param = alloc; + uint param_1 = offset; + if (!touch_mem(param, param_1)) + { + return; + } + _201.Store(offset * 4 + 8, val); +} + +void AnnoColor_write(Alloc a, AnnoColorRef ref, AnnoColor s) +{ + uint ix = ref.offset >> uint(2); + Alloc param = a; + uint param_1 = ix + 0u; + uint param_2 = asuint(s.bbox.x); + write_mem(param, param_1, param_2); + Alloc param_3 = a; + uint param_4 = ix + 1u; + uint param_5 = asuint(s.bbox.y); + write_mem(param_3, param_4, param_5); + Alloc param_6 = a; + uint param_7 = ix + 2u; + uint param_8 = asuint(s.bbox.z); + write_mem(param_6, param_7, param_8); + Alloc param_9 = a; + uint param_10 = ix + 3u; + uint param_11 = asuint(s.bbox.w); + write_mem(param_9, param_10, param_11); + Alloc param_12 = a; + uint param_13 = ix + 4u; + uint param_14 = asuint(s.linewidth); + write_mem(param_12, param_13, param_14); + Alloc param_15 = a; + uint param_16 = ix + 5u; + uint param_17 = s.rgba_color; + write_mem(param_15, param_16, param_17); +} + +void Annotated_Color_write(Alloc a, AnnotatedRef ref, uint flags, AnnoColor s) +{ + Alloc param = a; + uint param_1 = ref.offset >> uint(2); + uint param_2 = (flags << uint(16)) | 1u; + write_mem(param, param_1, param_2); + AnnoColorRef _808 = { ref.offset + 4u }; + Alloc param_3 = a; + AnnoColorRef param_4 = _808; + AnnoColor param_5 = s; + AnnoColor_write(param_3, param_4, param_5); +} + +FillLinGradient FillLinGradient_read(FillLinGradientRef ref) +{ + uint ix = ref.offset >> uint(2); + uint raw0 = _225.Load((ix + 0u) * 4 + 0); + uint raw1 = _225.Load((ix + 1u) * 4 + 0); + uint raw2 = _225.Load((ix + 2u) * 4 + 0); + uint raw3 = _225.Load((ix + 3u) * 4 + 0); + uint raw4 = _225.Load((ix + 4u) * 4 + 0); + FillLinGradient s; + s.index = raw0; + s.p0 = float2(asfloat(raw1), asfloat(raw2)); + s.p1 = float2(asfloat(raw3), asfloat(raw4)); + return s; +} + +FillLinGradient Element_FillLinGradient_read(ElementRef ref) +{ + FillLinGradientRef _389 = { ref.offset + 4u }; + FillLinGradientRef param = _389; + return FillLinGradient_read(param); +} + +void AnnoLinGradient_write(Alloc a, AnnoLinGradientRef ref, AnnoLinGradient s) +{ + uint ix = ref.offset >> uint(2); + Alloc param = a; + uint param_1 = ix + 0u; + uint param_2 = asuint(s.bbox.x); + write_mem(param, param_1, param_2); + Alloc param_3 = a; + uint param_4 = ix + 1u; + uint param_5 = asuint(s.bbox.y); + write_mem(param_3, param_4, param_5); + Alloc param_6 = a; + uint param_7 = ix + 2u; + uint param_8 = asuint(s.bbox.z); + write_mem(param_6, param_7, param_8); + Alloc param_9 = a; + uint param_10 = ix + 3u; + uint param_11 = asuint(s.bbox.w); + write_mem(param_9, param_10, param_11); + Alloc param_12 = a; + uint param_13 = ix + 4u; + uint param_14 = asuint(s.linewidth); + write_mem(param_12, param_13, param_14); + Alloc param_15 = a; + uint param_16 = ix + 5u; + uint param_17 = s.index; + write_mem(param_15, param_16, param_17); + Alloc param_18 = a; + uint param_19 = ix + 6u; + uint param_20 = asuint(s.line_x); + write_mem(param_18, param_19, param_20); + Alloc param_21 = a; + uint param_22 = ix + 7u; + uint param_23 = asuint(s.line_y); + write_mem(param_21, param_22, param_23); + Alloc param_24 = a; + uint param_25 = ix + 8u; + uint param_26 = asuint(s.line_c); + write_mem(param_24, param_25, param_26); +} + +void Annotated_LinGradient_write(Alloc a, AnnotatedRef ref, uint flags, AnnoLinGradient s) +{ + Alloc param = a; + uint param_1 = ref.offset >> uint(2); + uint param_2 = (flags << uint(16)) | 2u; + write_mem(param, param_1, param_2); + AnnoLinGradientRef _829 = { ref.offset + 4u }; + Alloc param_3 = a; + AnnoLinGradientRef param_4 = _829; + AnnoLinGradient param_5 = s; + AnnoLinGradient_write(param_3, param_4, param_5); +} + +FillImage FillImage_read(FillImageRef ref) +{ + uint ix = ref.offset >> uint(2); + uint raw0 = _225.Load((ix + 0u) * 4 + 0); + uint raw1 = _225.Load((ix + 1u) * 4 + 0); + FillImage s; + s.index = raw0; + s.offset = int2(int(raw1 << uint(16)) >> 16, int(raw1) >> 16); + return s; +} + +FillImage Element_FillImage_read(ElementRef ref) +{ + FillImageRef _397 = { ref.offset + 4u }; + FillImageRef param = _397; + return FillImage_read(param); +} + +void AnnoImage_write(Alloc a, AnnoImageRef ref, AnnoImage s) +{ + uint ix = ref.offset >> uint(2); + Alloc param = a; + uint param_1 = ix + 0u; + uint param_2 = asuint(s.bbox.x); + write_mem(param, param_1, param_2); + Alloc param_3 = a; + uint param_4 = ix + 1u; + uint param_5 = asuint(s.bbox.y); + write_mem(param_3, param_4, param_5); + Alloc param_6 = a; + uint param_7 = ix + 2u; + uint param_8 = asuint(s.bbox.z); + write_mem(param_6, param_7, param_8); + Alloc param_9 = a; + uint param_10 = ix + 3u; + uint param_11 = asuint(s.bbox.w); + write_mem(param_9, param_10, param_11); + Alloc param_12 = a; + uint param_13 = ix + 4u; + uint param_14 = asuint(s.linewidth); + write_mem(param_12, param_13, param_14); + Alloc param_15 = a; + uint param_16 = ix + 5u; + uint param_17 = s.index; + write_mem(param_15, param_16, param_17); + Alloc param_18 = a; + uint param_19 = ix + 6u; + uint param_20 = (uint(s.offset.x) & 65535u) | (uint(s.offset.y) << uint(16)); + write_mem(param_18, param_19, param_20); +} + +void Annotated_Image_write(Alloc a, AnnotatedRef ref, uint flags, AnnoImage s) +{ + Alloc param = a; + uint param_1 = ref.offset >> uint(2); + uint param_2 = (flags << uint(16)) | 3u; + write_mem(param, param_1, param_2); + AnnoImageRef _850 = { ref.offset + 4u }; + Alloc param_3 = a; + AnnoImageRef param_4 = _850; + AnnoImage param_5 = s; + AnnoImage_write(param_3, param_4, param_5); +} + +Clip Clip_read(ClipRef ref) +{ + uint ix = ref.offset >> uint(2); + uint raw0 = _225.Load((ix + 0u) * 4 + 0); + uint raw1 = _225.Load((ix + 1u) * 4 + 0); + uint raw2 = _225.Load((ix + 2u) * 4 + 0); + uint raw3 = _225.Load((ix + 3u) * 4 + 0); + Clip s; + s.bbox = float4(asfloat(raw0), asfloat(raw1), asfloat(raw2), asfloat(raw3)); + return s; +} + +Clip Element_BeginClip_read(ElementRef ref) +{ + ClipRef _405 = { ref.offset + 4u }; + ClipRef param = _405; + return Clip_read(param); +} + +void AnnoBeginClip_write(Alloc a, AnnoBeginClipRef ref, AnnoBeginClip s) +{ + uint ix = ref.offset >> uint(2); + Alloc param = a; + uint param_1 = ix + 0u; + uint param_2 = asuint(s.bbox.x); + write_mem(param, param_1, param_2); + Alloc param_3 = a; + uint param_4 = ix + 1u; + uint param_5 = asuint(s.bbox.y); + write_mem(param_3, param_4, param_5); + Alloc param_6 = a; + uint param_7 = ix + 2u; + uint param_8 = asuint(s.bbox.z); + write_mem(param_6, param_7, param_8); + Alloc param_9 = a; + uint param_10 = ix + 3u; + uint param_11 = asuint(s.bbox.w); + write_mem(param_9, param_10, param_11); + Alloc param_12 = a; + uint param_13 = ix + 4u; + uint param_14 = asuint(s.linewidth); + write_mem(param_12, param_13, param_14); +} + +void Annotated_BeginClip_write(Alloc a, AnnotatedRef ref, uint flags, AnnoBeginClip s) +{ + Alloc param = a; + uint param_1 = ref.offset >> uint(2); + uint param_2 = (flags << uint(16)) | 4u; + write_mem(param, param_1, param_2); + AnnoBeginClipRef _871 = { ref.offset + 4u }; + Alloc param_3 = a; + AnnoBeginClipRef param_4 = _871; + AnnoBeginClip param_5 = s; + AnnoBeginClip_write(param_3, param_4, param_5); +} + +Clip Element_EndClip_read(ElementRef ref) +{ + ClipRef _413 = { ref.offset + 4u }; + ClipRef param = _413; + return Clip_read(param); +} + +void AnnoEndClip_write(Alloc a, AnnoEndClipRef ref, AnnoEndClip s) +{ + uint ix = ref.offset >> uint(2); + Alloc param = a; + uint param_1 = ix + 0u; + uint param_2 = asuint(s.bbox.x); + write_mem(param, param_1, param_2); + Alloc param_3 = a; + uint param_4 = ix + 1u; + uint param_5 = asuint(s.bbox.y); + write_mem(param_3, param_4, param_5); + Alloc param_6 = a; + uint param_7 = ix + 2u; + uint param_8 = asuint(s.bbox.z); + write_mem(param_6, param_7, param_8); + Alloc param_9 = a; + uint param_10 = ix + 3u; + uint param_11 = asuint(s.bbox.w); + write_mem(param_9, param_10, param_11); +} + +void Annotated_EndClip_write(Alloc a, AnnotatedRef ref, AnnoEndClip s) +{ + Alloc param = a; + uint param_1 = ref.offset >> uint(2); + uint param_2 = 5u; + write_mem(param, param_1, param_2); + AnnoEndClipRef _889 = { ref.offset + 4u }; + Alloc param_3 = a; + AnnoEndClipRef param_4 = _889; + AnnoEndClip param_5 = s; + AnnoEndClip_write(param_3, param_4, param_5); } void comp_main() { uint ix = gl_GlobalInvocationID.x * 8u; - ElementRef _115 = { ix * 36u }; - ElementRef ref = _115; + ElementRef _907 = { ix * 36u }; + ElementRef ref = _907; ElementRef param = ref; uint tag_word = Element_tag(param).tag; uint param_1 = tag_word; @@ -157,11 +579,11 @@ void comp_main() DrawMonoid row = tag_monoid_identity(); if (gl_WorkGroupID.x > 0u) { - DrawMonoid _224; - _224.path_ix = _218.Load((gl_WorkGroupID.x - 1u) * 8 + 0); - _224.clip_ix = _218.Load((gl_WorkGroupID.x - 1u) * 8 + 4); - row.path_ix = _224.path_ix; - row.clip_ix = _224.clip_ix; + DrawMonoid _1014; + _1014.path_ix = _1008.Load((gl_WorkGroupID.x - 1u) * 8 + 0); + _1014.clip_ix = _1008.Load((gl_WorkGroupID.x - 1u) * 8 + 4); + row.path_ix = _1014.path_ix; + row.clip_ix = _1014.clip_ix; } if (gl_LocalInvocationID.x > 0u) { @@ -169,14 +591,154 @@ void comp_main() DrawMonoid param_11 = sh_scratch[gl_LocalInvocationID.x - 1u]; row = combine_tag_monoid(param_10, param_11); } - uint out_base = (_248.Load(44) >> uint(2)) + ((gl_GlobalInvocationID.x * 2u) * 8u); + uint out_ix = gl_GlobalInvocationID.x * 8u; + uint out_base = (_1042.Load(44) >> uint(2)) + (out_ix * 2u); + AnnotatedRef _1058 = { _1042.Load(32) + (out_ix * 40u) }; + AnnotatedRef out_ref = _1058; + float4 mat; + float2 translate; + AnnoColor anno_fill; + Alloc param_18; + AnnoLinGradient anno_lin; + Alloc param_23; + AnnoImage anno_img; + Alloc param_28; + AnnoBeginClip anno_begin_clip; + Alloc param_33; + AnnoEndClip anno_end_clip; + Alloc param_38; for (uint i_2 = 0u; i_2 < 8u; i_2++) { DrawMonoid param_12 = row; DrawMonoid param_13 = local[i_2]; DrawMonoid m = combine_tag_monoid(param_12, param_13); - _277.Store((out_base + (i_2 * 2u)) * 4 + 8, m.path_ix); - _277.Store(((out_base + (i_2 * 2u)) + 1u) * 4 + 8, m.clip_ix); + _201.Store((out_base + (i_2 * 2u)) * 4 + 8, m.path_ix); + _201.Store(((out_base + (i_2 * 2u)) + 1u) * 4 + 8, m.clip_ix); + ElementRef param_14 = ref; + uint param_15 = i_2; + ElementRef this_ref = Element_index(param_14, param_15); + ElementRef param_16 = this_ref; + tag_word = Element_tag(param_16).tag; + if (((tag_word == 4u) || (tag_word == 5u)) || (tag_word == 6u)) + { + uint bbox_offset = (_1042.Load(40) >> uint(2)) + (6u * (m.path_ix - 1u)); + float bbox_l = float(_201.Load(bbox_offset * 4 + 8)) - 32768.0f; + float bbox_t = float(_201.Load((bbox_offset + 1u) * 4 + 8)) - 32768.0f; + float bbox_r = float(_201.Load((bbox_offset + 2u) * 4 + 8)) - 32768.0f; + float bbox_b = float(_201.Load((bbox_offset + 3u) * 4 + 8)) - 32768.0f; + float4 bbox = float4(bbox_l, bbox_t, bbox_r, bbox_b); + float linewidth = asfloat(_201.Load((bbox_offset + 4u) * 4 + 8)); + uint fill_mode = uint(linewidth >= 0.0f); + if ((linewidth >= 0.0f) || (tag_word == 5u)) + { + uint trans_ix = _201.Load((bbox_offset + 5u) * 4 + 8); + uint t = (_1042.Load(36) >> uint(2)) + (6u * trans_ix); + mat = asfloat(uint4(_201.Load(t * 4 + 8), _201.Load((t + 1u) * 4 + 8), _201.Load((t + 2u) * 4 + 8), _201.Load((t + 3u) * 4 + 8))); + if (tag_word == 5u) + { + translate = asfloat(uint2(_201.Load((t + 4u) * 4 + 8), _201.Load((t + 5u) * 4 + 8))); + } + } + if (linewidth >= 0.0f) + { + linewidth *= sqrt(abs((mat.x * mat.w) - (mat.y * mat.z))); + } + linewidth = max(linewidth, 0.0f); + switch (tag_word) + { + case 4u: + { + ElementRef param_17 = this_ref; + FillColor fill = Element_FillColor_read(param_17); + anno_fill.bbox = bbox; + anno_fill.linewidth = linewidth; + anno_fill.rgba_color = fill.rgba_color; + Alloc _1261; + _1261.offset = _1042.Load(32); + param_18.offset = _1261.offset; + AnnotatedRef param_19 = out_ref; + uint param_20 = fill_mode; + AnnoColor param_21 = anno_fill; + Annotated_Color_write(param_18, param_19, param_20, param_21); + break; + } + case 5u: + { + ElementRef param_22 = this_ref; + FillLinGradient lin = Element_FillLinGradient_read(param_22); + anno_lin.bbox = bbox; + anno_lin.linewidth = linewidth; + anno_lin.index = lin.index; + float2 p0 = ((mat.xy * lin.p0.x) + (mat.zw * lin.p0.y)) + translate; + float2 p1 = ((mat.xy * lin.p1.x) + (mat.zw * lin.p1.y)) + translate; + float2 dxy = p1 - p0; + float scale = 1.0f / ((dxy.x * dxy.x) + (dxy.y * dxy.y)); + float line_x = dxy.x * scale; + float line_y = dxy.y * scale; + anno_lin.line_x = line_x; + anno_lin.line_y = line_y; + anno_lin.line_c = -((p0.x * line_x) + (p0.y * line_y)); + Alloc _1357; + _1357.offset = _1042.Load(32); + param_23.offset = _1357.offset; + AnnotatedRef param_24 = out_ref; + uint param_25 = fill_mode; + AnnoLinGradient param_26 = anno_lin; + Annotated_LinGradient_write(param_23, param_24, param_25, param_26); + break; + } + case 6u: + { + ElementRef param_27 = this_ref; + FillImage fill_img = Element_FillImage_read(param_27); + anno_img.bbox = bbox; + anno_img.linewidth = linewidth; + anno_img.index = fill_img.index; + anno_img.offset = fill_img.offset; + Alloc _1385; + _1385.offset = _1042.Load(32); + param_28.offset = _1385.offset; + AnnotatedRef param_29 = out_ref; + uint param_30 = fill_mode; + AnnoImage param_31 = anno_img; + Annotated_Image_write(param_28, param_29, param_30, param_31); + break; + } + } + } + else + { + if (tag_word == 9u) + { + ElementRef param_32 = this_ref; + Clip begin_clip = Element_BeginClip_read(param_32); + anno_begin_clip.bbox = begin_clip.bbox; + anno_begin_clip.linewidth = 0.0f; + Alloc _1413; + _1413.offset = _1042.Load(32); + param_33.offset = _1413.offset; + AnnotatedRef param_34 = out_ref; + uint param_35 = 0u; + AnnoBeginClip param_36 = anno_begin_clip; + Annotated_BeginClip_write(param_33, param_34, param_35, param_36); + } + else + { + if (tag_word == 10u) + { + ElementRef param_37 = this_ref; + Clip end_clip = Element_EndClip_read(param_37); + anno_end_clip.bbox = end_clip.bbox; + Alloc _1438; + _1438.offset = _1042.Load(32); + param_38.offset = _1438.offset; + AnnotatedRef param_39 = out_ref; + AnnoEndClip param_40 = anno_end_clip; + Annotated_EndClip_write(param_38, param_39, param_40); + } + } + } + out_ref.offset += 40u; } } diff --git a/piet-gpu/shader/gen/draw_leaf.msl b/piet-gpu/shader/gen/draw_leaf.msl index d52a560..f713186 100644 --- a/piet-gpu/shader/gen/draw_leaf.msl +++ b/piet-gpu/shader/gen/draw_leaf.msl @@ -44,11 +44,59 @@ struct spvUnsafeArray } }; +struct Alloc +{ + uint offset; +}; + struct ElementRef { uint offset; }; +struct FillColorRef +{ + uint offset; +}; + +struct FillColor +{ + uint rgba_color; +}; + +struct FillLinGradientRef +{ + uint offset; +}; + +struct FillLinGradient +{ + uint index; + float2 p0; + float2 p1; +}; + +struct FillImageRef +{ + uint offset; +}; + +struct FillImage +{ + uint index; + int2 offset; +}; + +struct ClipRef +{ + uint offset; +}; + +struct Clip +{ + float4 bbox; +}; + struct ElementTag { uint tag; @@ -61,6 +109,79 @@ struct DrawMonoid uint clip_ix; }; +struct AnnoImageRef +{ + uint offset; +}; + +struct AnnoImage +{ + float4 bbox; + float linewidth; + uint index; + int2 offset; +}; + +struct AnnoColorRef +{ + uint offset; +}; + +struct AnnoColor +{ + float4 bbox; + float linewidth; + uint rgba_color; +}; + +struct AnnoLinGradientRef +{ + uint offset; +}; + +struct AnnoLinGradient +{ + float4 bbox; + float linewidth; + uint index; + float line_x; + float line_y; + float line_c; +}; + +struct AnnoBeginClipRef +{ + uint offset; +}; + +struct AnnoBeginClip +{ + float4 bbox; + float linewidth; +}; + +struct AnnoEndClipRef +{ + uint offset; +}; + +struct AnnoEndClip +{ + float4 bbox; +}; + +struct AnnotatedRef +{ + uint offset; +}; + +struct Memory +{ + uint mem_offset; + uint mem_error; + uint memory[1]; +}; + struct SceneBuf { uint scene[1]; @@ -77,7 +198,7 @@ struct ParentBuf DrawMonoid_1 parent[1]; }; -struct Alloc +struct Alloc_1 { uint offset; }; @@ -88,18 +209,19 @@ struct Config uint n_pathseg; uint width_in_tiles; uint height_in_tiles; - Alloc tile_alloc; - Alloc bin_alloc; - Alloc ptcl_alloc; - Alloc pathseg_alloc; - Alloc anno_alloc; - Alloc trans_alloc; - Alloc bbox_alloc; - Alloc drawmonoid_alloc; + Alloc_1 tile_alloc; + Alloc_1 bin_alloc; + Alloc_1 ptcl_alloc; + Alloc_1 pathseg_alloc; + Alloc_1 anno_alloc; + Alloc_1 trans_alloc; + Alloc_1 bbox_alloc; + Alloc_1 drawmonoid_alloc; uint n_trans; + uint n_path; uint trans_offset; - uint pathtag_offset; uint linewidth_offset; + uint pathtag_offset; uint pathseg_offset; }; @@ -108,19 +230,12 @@ struct ConfigBuf Config conf; }; -struct Memory -{ - uint mem_offset; - uint mem_error; - uint memory[1]; -}; - constant uint3 gl_WorkGroupSize [[maybe_unused]] = uint3(512u, 1u, 1u); static inline __attribute__((always_inline)) -ElementTag Element_tag(thread const ElementRef& ref, const device SceneBuf& v_49) +ElementTag Element_tag(thread const ElementRef& ref, const device SceneBuf& v_225) { - uint tag_and_flags = v_49.scene[ref.offset >> uint(2)]; + uint tag_and_flags = v_225.scene[ref.offset >> uint(2)]; return ElementTag{ tag_and_flags & 65535u, tag_and_flags >> uint(16) }; } @@ -171,13 +286,336 @@ DrawMonoid tag_monoid_identity() return DrawMonoid{ 0u, 0u }; } -kernel void main0(device Memory& _277 [[buffer(0)]], const device ConfigBuf& _248 [[buffer(1)]], const device SceneBuf& v_49 [[buffer(2)]], const device ParentBuf& _218 [[buffer(3)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]], uint3 gl_LocalInvocationID [[thread_position_in_threadgroup]], uint3 gl_WorkGroupID [[threadgroup_position_in_grid]]) +static inline __attribute__((always_inline)) +FillColor FillColor_read(thread const FillColorRef& ref, const device SceneBuf& v_225) +{ + uint ix = ref.offset >> uint(2); + uint raw0 = v_225.scene[ix + 0u]; + FillColor s; + s.rgba_color = raw0; + return s; +} + +static inline __attribute__((always_inline)) +FillColor Element_FillColor_read(thread const ElementRef& ref, const device SceneBuf& v_225) +{ + FillColorRef param = FillColorRef{ ref.offset + 4u }; + return FillColor_read(param, v_225); +} + +static inline __attribute__((always_inline)) +bool touch_mem(thread const Alloc& alloc, thread const uint& offset) +{ + return true; +} + +static inline __attribute__((always_inline)) +void write_mem(thread const Alloc& alloc, thread const uint& offset, thread const uint& val, device Memory& v_201) +{ + Alloc param = alloc; + uint param_1 = offset; + if (!touch_mem(param, param_1)) + { + return; + } + v_201.memory[offset] = val; +} + +static inline __attribute__((always_inline)) +void AnnoColor_write(thread const Alloc& a, thread const AnnoColorRef& ref, thread const AnnoColor& s, device Memory& v_201) +{ + uint ix = ref.offset >> uint(2); + Alloc param = a; + uint param_1 = ix + 0u; + uint param_2 = as_type(s.bbox.x); + write_mem(param, param_1, param_2, v_201); + Alloc param_3 = a; + uint param_4 = ix + 1u; + uint param_5 = as_type(s.bbox.y); + write_mem(param_3, param_4, param_5, v_201); + Alloc param_6 = a; + uint param_7 = ix + 2u; + uint param_8 = as_type(s.bbox.z); + write_mem(param_6, param_7, param_8, v_201); + Alloc param_9 = a; + uint param_10 = ix + 3u; + uint param_11 = as_type(s.bbox.w); + write_mem(param_9, param_10, param_11, v_201); + Alloc param_12 = a; + uint param_13 = ix + 4u; + uint param_14 = as_type(s.linewidth); + write_mem(param_12, param_13, param_14, v_201); + Alloc param_15 = a; + uint param_16 = ix + 5u; + uint param_17 = s.rgba_color; + write_mem(param_15, param_16, param_17, v_201); +} + +static inline __attribute__((always_inline)) +void Annotated_Color_write(thread const Alloc& a, thread const AnnotatedRef& ref, thread const uint& flags, thread const AnnoColor& s, device Memory& v_201) +{ + Alloc param = a; + uint param_1 = ref.offset >> uint(2); + uint param_2 = (flags << uint(16)) | 1u; + write_mem(param, param_1, param_2, v_201); + Alloc param_3 = a; + AnnoColorRef param_4 = AnnoColorRef{ ref.offset + 4u }; + AnnoColor param_5 = s; + AnnoColor_write(param_3, param_4, param_5, v_201); +} + +static inline __attribute__((always_inline)) +FillLinGradient FillLinGradient_read(thread const FillLinGradientRef& ref, const device SceneBuf& v_225) +{ + uint ix = ref.offset >> uint(2); + uint raw0 = v_225.scene[ix + 0u]; + uint raw1 = v_225.scene[ix + 1u]; + uint raw2 = v_225.scene[ix + 2u]; + uint raw3 = v_225.scene[ix + 3u]; + uint raw4 = v_225.scene[ix + 4u]; + FillLinGradient s; + s.index = raw0; + s.p0 = float2(as_type(raw1), as_type(raw2)); + s.p1 = float2(as_type(raw3), as_type(raw4)); + return s; +} + +static inline __attribute__((always_inline)) +FillLinGradient Element_FillLinGradient_read(thread const ElementRef& ref, const device SceneBuf& v_225) +{ + FillLinGradientRef param = FillLinGradientRef{ ref.offset + 4u }; + return FillLinGradient_read(param, v_225); +} + +static inline __attribute__((always_inline)) +void AnnoLinGradient_write(thread const Alloc& a, thread const AnnoLinGradientRef& ref, thread const AnnoLinGradient& s, device Memory& v_201) +{ + uint ix = ref.offset >> uint(2); + Alloc param = a; + uint param_1 = ix + 0u; + uint param_2 = as_type(s.bbox.x); + write_mem(param, param_1, param_2, v_201); + Alloc param_3 = a; + uint param_4 = ix + 1u; + uint param_5 = as_type(s.bbox.y); + write_mem(param_3, param_4, param_5, v_201); + Alloc param_6 = a; + uint param_7 = ix + 2u; + uint param_8 = as_type(s.bbox.z); + write_mem(param_6, param_7, param_8, v_201); + Alloc param_9 = a; + uint param_10 = ix + 3u; + uint param_11 = as_type(s.bbox.w); + write_mem(param_9, param_10, param_11, v_201); + Alloc param_12 = a; + uint param_13 = ix + 4u; + uint param_14 = as_type(s.linewidth); + write_mem(param_12, param_13, param_14, v_201); + Alloc param_15 = a; + uint param_16 = ix + 5u; + uint param_17 = s.index; + write_mem(param_15, param_16, param_17, v_201); + Alloc param_18 = a; + uint param_19 = ix + 6u; + uint param_20 = as_type(s.line_x); + write_mem(param_18, param_19, param_20, v_201); + Alloc param_21 = a; + uint param_22 = ix + 7u; + uint param_23 = as_type(s.line_y); + write_mem(param_21, param_22, param_23, v_201); + Alloc param_24 = a; + uint param_25 = ix + 8u; + uint param_26 = as_type(s.line_c); + write_mem(param_24, param_25, param_26, v_201); +} + +static inline __attribute__((always_inline)) +void Annotated_LinGradient_write(thread const Alloc& a, thread const AnnotatedRef& ref, thread const uint& flags, thread const AnnoLinGradient& s, device Memory& v_201) +{ + Alloc param = a; + uint param_1 = ref.offset >> uint(2); + uint param_2 = (flags << uint(16)) | 2u; + write_mem(param, param_1, param_2, v_201); + Alloc param_3 = a; + AnnoLinGradientRef param_4 = AnnoLinGradientRef{ ref.offset + 4u }; + AnnoLinGradient param_5 = s; + AnnoLinGradient_write(param_3, param_4, param_5, v_201); +} + +static inline __attribute__((always_inline)) +FillImage FillImage_read(thread const FillImageRef& ref, const device SceneBuf& v_225) +{ + uint ix = ref.offset >> uint(2); + uint raw0 = v_225.scene[ix + 0u]; + uint raw1 = v_225.scene[ix + 1u]; + FillImage s; + s.index = raw0; + s.offset = int2(int(raw1 << uint(16)) >> 16, int(raw1) >> 16); + return s; +} + +static inline __attribute__((always_inline)) +FillImage Element_FillImage_read(thread const ElementRef& ref, const device SceneBuf& v_225) +{ + FillImageRef param = FillImageRef{ ref.offset + 4u }; + return FillImage_read(param, v_225); +} + +static inline __attribute__((always_inline)) +void AnnoImage_write(thread const Alloc& a, thread const AnnoImageRef& ref, thread const AnnoImage& s, device Memory& v_201) +{ + uint ix = ref.offset >> uint(2); + Alloc param = a; + uint param_1 = ix + 0u; + uint param_2 = as_type(s.bbox.x); + write_mem(param, param_1, param_2, v_201); + Alloc param_3 = a; + uint param_4 = ix + 1u; + uint param_5 = as_type(s.bbox.y); + write_mem(param_3, param_4, param_5, v_201); + Alloc param_6 = a; + uint param_7 = ix + 2u; + uint param_8 = as_type(s.bbox.z); + write_mem(param_6, param_7, param_8, v_201); + Alloc param_9 = a; + uint param_10 = ix + 3u; + uint param_11 = as_type(s.bbox.w); + write_mem(param_9, param_10, param_11, v_201); + Alloc param_12 = a; + uint param_13 = ix + 4u; + uint param_14 = as_type(s.linewidth); + write_mem(param_12, param_13, param_14, v_201); + Alloc param_15 = a; + uint param_16 = ix + 5u; + uint param_17 = s.index; + write_mem(param_15, param_16, param_17, v_201); + Alloc param_18 = a; + uint param_19 = ix + 6u; + uint param_20 = (uint(s.offset.x) & 65535u) | (uint(s.offset.y) << uint(16)); + write_mem(param_18, param_19, param_20, v_201); +} + +static inline __attribute__((always_inline)) +void Annotated_Image_write(thread const Alloc& a, thread const AnnotatedRef& ref, thread const uint& flags, thread const AnnoImage& s, device Memory& v_201) +{ + Alloc param = a; + uint param_1 = ref.offset >> uint(2); + uint param_2 = (flags << uint(16)) | 3u; + write_mem(param, param_1, param_2, v_201); + Alloc param_3 = a; + AnnoImageRef param_4 = AnnoImageRef{ ref.offset + 4u }; + AnnoImage param_5 = s; + AnnoImage_write(param_3, param_4, param_5, v_201); +} + +static inline __attribute__((always_inline)) +Clip Clip_read(thread const ClipRef& ref, const device SceneBuf& v_225) +{ + uint ix = ref.offset >> uint(2); + uint raw0 = v_225.scene[ix + 0u]; + uint raw1 = v_225.scene[ix + 1u]; + uint raw2 = v_225.scene[ix + 2u]; + uint raw3 = v_225.scene[ix + 3u]; + Clip s; + s.bbox = float4(as_type(raw0), as_type(raw1), as_type(raw2), as_type(raw3)); + return s; +} + +static inline __attribute__((always_inline)) +Clip Element_BeginClip_read(thread const ElementRef& ref, const device SceneBuf& v_225) +{ + ClipRef param = ClipRef{ ref.offset + 4u }; + return Clip_read(param, v_225); +} + +static inline __attribute__((always_inline)) +void AnnoBeginClip_write(thread const Alloc& a, thread const AnnoBeginClipRef& ref, thread const AnnoBeginClip& s, device Memory& v_201) +{ + uint ix = ref.offset >> uint(2); + Alloc param = a; + uint param_1 = ix + 0u; + uint param_2 = as_type(s.bbox.x); + write_mem(param, param_1, param_2, v_201); + Alloc param_3 = a; + uint param_4 = ix + 1u; + uint param_5 = as_type(s.bbox.y); + write_mem(param_3, param_4, param_5, v_201); + Alloc param_6 = a; + uint param_7 = ix + 2u; + uint param_8 = as_type(s.bbox.z); + write_mem(param_6, param_7, param_8, v_201); + Alloc param_9 = a; + uint param_10 = ix + 3u; + uint param_11 = as_type(s.bbox.w); + write_mem(param_9, param_10, param_11, v_201); + Alloc param_12 = a; + uint param_13 = ix + 4u; + uint param_14 = as_type(s.linewidth); + write_mem(param_12, param_13, param_14, v_201); +} + +static inline __attribute__((always_inline)) +void Annotated_BeginClip_write(thread const Alloc& a, thread const AnnotatedRef& ref, thread const uint& flags, thread const AnnoBeginClip& s, device Memory& v_201) +{ + Alloc param = a; + uint param_1 = ref.offset >> uint(2); + uint param_2 = (flags << uint(16)) | 4u; + write_mem(param, param_1, param_2, v_201); + Alloc param_3 = a; + AnnoBeginClipRef param_4 = AnnoBeginClipRef{ ref.offset + 4u }; + AnnoBeginClip param_5 = s; + AnnoBeginClip_write(param_3, param_4, param_5, v_201); +} + +static inline __attribute__((always_inline)) +Clip Element_EndClip_read(thread const ElementRef& ref, const device SceneBuf& v_225) +{ + ClipRef param = ClipRef{ ref.offset + 4u }; + return Clip_read(param, v_225); +} + +static inline __attribute__((always_inline)) +void AnnoEndClip_write(thread const Alloc& a, thread const AnnoEndClipRef& ref, thread const AnnoEndClip& s, device Memory& v_201) +{ + uint ix = ref.offset >> uint(2); + Alloc param = a; + uint param_1 = ix + 0u; + uint param_2 = as_type(s.bbox.x); + write_mem(param, param_1, param_2, v_201); + Alloc param_3 = a; + uint param_4 = ix + 1u; + uint param_5 = as_type(s.bbox.y); + write_mem(param_3, param_4, param_5, v_201); + Alloc param_6 = a; + uint param_7 = ix + 2u; + uint param_8 = as_type(s.bbox.z); + write_mem(param_6, param_7, param_8, v_201); + Alloc param_9 = a; + uint param_10 = ix + 3u; + uint param_11 = as_type(s.bbox.w); + write_mem(param_9, param_10, param_11, v_201); +} + +static inline __attribute__((always_inline)) +void Annotated_EndClip_write(thread const Alloc& a, thread const AnnotatedRef& ref, thread const AnnoEndClip& s, device Memory& v_201) +{ + Alloc param = a; + uint param_1 = ref.offset >> uint(2); + uint param_2 = 5u; + write_mem(param, param_1, param_2, v_201); + Alloc param_3 = a; + AnnoEndClipRef param_4 = AnnoEndClipRef{ ref.offset + 4u }; + AnnoEndClip param_5 = s; + AnnoEndClip_write(param_3, param_4, param_5, v_201); +} + +kernel void main0(device Memory& v_201 [[buffer(0)]], const device ConfigBuf& _1042 [[buffer(1)]], const device SceneBuf& v_225 [[buffer(2)]], const device ParentBuf& _1008 [[buffer(3)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]], uint3 gl_LocalInvocationID [[thread_position_in_threadgroup]], uint3 gl_WorkGroupID [[threadgroup_position_in_grid]]) { threadgroup DrawMonoid sh_scratch[512]; uint ix = gl_GlobalInvocationID.x * 8u; ElementRef ref = ElementRef{ ix * 36u }; ElementRef param = ref; - uint tag_word = Element_tag(param, v_49).tag; + uint tag_word = Element_tag(param, v_225).tag; uint param_1 = tag_word; DrawMonoid agg = map_tag(param_1); spvUnsafeArray local; @@ -187,7 +625,7 @@ kernel void main0(device Memory& _277 [[buffer(0)]], const device ConfigBuf& _24 ElementRef param_2 = ref; uint param_3 = i; ElementRef param_4 = Element_index(param_2, param_3); - tag_word = Element_tag(param_4, v_49).tag; + tag_word = Element_tag(param_4, v_225).tag; uint param_5 = tag_word; DrawMonoid param_6 = agg; DrawMonoid param_7 = map_tag(param_5); @@ -212,9 +650,9 @@ kernel void main0(device Memory& _277 [[buffer(0)]], const device ConfigBuf& _24 DrawMonoid row = tag_monoid_identity(); if (gl_WorkGroupID.x > 0u) { - uint _221 = gl_WorkGroupID.x - 1u; - row.path_ix = _218.parent[_221].path_ix; - row.clip_ix = _218.parent[_221].clip_ix; + uint _1011 = gl_WorkGroupID.x - 1u; + row.path_ix = _1008.parent[_1011].path_ix; + row.clip_ix = _1008.parent[_1011].clip_ix; } if (gl_LocalInvocationID.x > 0u) { @@ -222,14 +660,143 @@ kernel void main0(device Memory& _277 [[buffer(0)]], const device ConfigBuf& _24 DrawMonoid param_11 = sh_scratch[gl_LocalInvocationID.x - 1u]; row = combine_tag_monoid(param_10, param_11); } - uint out_base = (_248.conf.drawmonoid_alloc.offset >> uint(2)) + ((gl_GlobalInvocationID.x * 2u) * 8u); + uint out_ix = gl_GlobalInvocationID.x * 8u; + uint out_base = (_1042.conf.drawmonoid_alloc.offset >> uint(2)) + (out_ix * 2u); + AnnotatedRef out_ref = AnnotatedRef{ _1042.conf.anno_alloc.offset + (out_ix * 40u) }; + float4 mat; + float2 translate; + AnnoColor anno_fill; + Alloc param_18; + AnnoLinGradient anno_lin; + Alloc param_23; + AnnoImage anno_img; + Alloc param_28; + AnnoBeginClip anno_begin_clip; + Alloc param_33; + AnnoEndClip anno_end_clip; + Alloc param_38; for (uint i_2 = 0u; i_2 < 8u; i_2++) { DrawMonoid param_12 = row; DrawMonoid param_13 = local[i_2]; DrawMonoid m = combine_tag_monoid(param_12, param_13); - _277.memory[out_base + (i_2 * 2u)] = m.path_ix; - _277.memory[(out_base + (i_2 * 2u)) + 1u] = m.clip_ix; + v_201.memory[out_base + (i_2 * 2u)] = m.path_ix; + v_201.memory[(out_base + (i_2 * 2u)) + 1u] = m.clip_ix; + ElementRef param_14 = ref; + uint param_15 = i_2; + ElementRef this_ref = Element_index(param_14, param_15); + ElementRef param_16 = this_ref; + tag_word = Element_tag(param_16, v_225).tag; + if (((tag_word == 4u) || (tag_word == 5u)) || (tag_word == 6u)) + { + uint bbox_offset = (_1042.conf.bbox_alloc.offset >> uint(2)) + (6u * (m.path_ix - 1u)); + float bbox_l = float(v_201.memory[bbox_offset]) - 32768.0; + float bbox_t = float(v_201.memory[bbox_offset + 1u]) - 32768.0; + float bbox_r = float(v_201.memory[bbox_offset + 2u]) - 32768.0; + float bbox_b = float(v_201.memory[bbox_offset + 3u]) - 32768.0; + float4 bbox = float4(bbox_l, bbox_t, bbox_r, bbox_b); + float linewidth = as_type(v_201.memory[bbox_offset + 4u]); + uint fill_mode = uint(linewidth >= 0.0); + if ((linewidth >= 0.0) || (tag_word == 5u)) + { + uint trans_ix = v_201.memory[bbox_offset + 5u]; + uint t = (_1042.conf.trans_alloc.offset >> uint(2)) + (6u * trans_ix); + mat = as_type(uint4(v_201.memory[t], v_201.memory[t + 1u], v_201.memory[t + 2u], v_201.memory[t + 3u])); + if (tag_word == 5u) + { + translate = as_type(uint2(v_201.memory[t + 4u], v_201.memory[t + 5u])); + } + } + if (linewidth >= 0.0) + { + linewidth *= sqrt(abs((mat.x * mat.w) - (mat.y * mat.z))); + } + linewidth = fast::max(linewidth, 0.0); + switch (tag_word) + { + case 4u: + { + ElementRef param_17 = this_ref; + FillColor fill = Element_FillColor_read(param_17, v_225); + anno_fill.bbox = bbox; + anno_fill.linewidth = linewidth; + anno_fill.rgba_color = fill.rgba_color; + param_18.offset = _1042.conf.anno_alloc.offset; + AnnotatedRef param_19 = out_ref; + uint param_20 = fill_mode; + AnnoColor param_21 = anno_fill; + Annotated_Color_write(param_18, param_19, param_20, param_21, v_201); + break; + } + case 5u: + { + ElementRef param_22 = this_ref; + FillLinGradient lin = Element_FillLinGradient_read(param_22, v_225); + anno_lin.bbox = bbox; + anno_lin.linewidth = linewidth; + anno_lin.index = lin.index; + float2 p0 = ((mat.xy * lin.p0.x) + (mat.zw * lin.p0.y)) + translate; + float2 p1 = ((mat.xy * lin.p1.x) + (mat.zw * lin.p1.y)) + translate; + float2 dxy = p1 - p0; + float scale = 1.0 / ((dxy.x * dxy.x) + (dxy.y * dxy.y)); + float line_x = dxy.x * scale; + float line_y = dxy.y * scale; + anno_lin.line_x = line_x; + anno_lin.line_y = line_y; + anno_lin.line_c = -((p0.x * line_x) + (p0.y * line_y)); + param_23.offset = _1042.conf.anno_alloc.offset; + AnnotatedRef param_24 = out_ref; + uint param_25 = fill_mode; + AnnoLinGradient param_26 = anno_lin; + Annotated_LinGradient_write(param_23, param_24, param_25, param_26, v_201); + break; + } + case 6u: + { + ElementRef param_27 = this_ref; + FillImage fill_img = Element_FillImage_read(param_27, v_225); + anno_img.bbox = bbox; + anno_img.linewidth = linewidth; + anno_img.index = fill_img.index; + anno_img.offset = fill_img.offset; + param_28.offset = _1042.conf.anno_alloc.offset; + AnnotatedRef param_29 = out_ref; + uint param_30 = fill_mode; + AnnoImage param_31 = anno_img; + Annotated_Image_write(param_28, param_29, param_30, param_31, v_201); + break; + } + } + } + else + { + if (tag_word == 9u) + { + ElementRef param_32 = this_ref; + Clip begin_clip = Element_BeginClip_read(param_32, v_225); + anno_begin_clip.bbox = begin_clip.bbox; + anno_begin_clip.linewidth = 0.0; + param_33.offset = _1042.conf.anno_alloc.offset; + AnnotatedRef param_34 = out_ref; + uint param_35 = 0u; + AnnoBeginClip param_36 = anno_begin_clip; + Annotated_BeginClip_write(param_33, param_34, param_35, param_36, v_201); + } + else + { + if (tag_word == 10u) + { + ElementRef param_37 = this_ref; + Clip end_clip = Element_EndClip_read(param_37, v_225); + anno_end_clip.bbox = end_clip.bbox; + param_38.offset = _1042.conf.anno_alloc.offset; + AnnotatedRef param_39 = out_ref; + AnnoEndClip param_40 = anno_end_clip; + Annotated_EndClip_write(param_38, param_39, param_40, v_201); + } + } + } + out_ref.offset += 40u; } } diff --git a/piet-gpu/shader/gen/draw_leaf.spv b/piet-gpu/shader/gen/draw_leaf.spv index 30740a287f301b01fbf5674faf684dddcab4dff7..8fade688ab936b660e7d9aebe2ffcf337a1d4484 100644 GIT binary patch literal 38596 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 literal 8536 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 diff --git a/piet-gpu/shader/gen/draw_reduce.hlsl b/piet-gpu/shader/gen/draw_reduce.hlsl index 27c206a..b28c956 100644 --- a/piet-gpu/shader/gen/draw_reduce.hlsl +++ b/piet-gpu/shader/gen/draw_reduce.hlsl @@ -37,9 +37,10 @@ struct Config Alloc bbox_alloc; Alloc drawmonoid_alloc; uint n_trans; + uint n_path; uint trans_offset; - uint pathtag_offset; uint linewidth_offset; + uint pathtag_offset; uint pathseg_offset; }; diff --git a/piet-gpu/shader/gen/draw_reduce.msl b/piet-gpu/shader/gen/draw_reduce.msl index dd2f517..550cf8c 100644 --- a/piet-gpu/shader/gen/draw_reduce.msl +++ b/piet-gpu/shader/gen/draw_reduce.msl @@ -67,9 +67,10 @@ struct Config Alloc bbox_alloc; Alloc drawmonoid_alloc; uint n_trans; + uint n_path; uint trans_offset; - uint pathtag_offset; uint linewidth_offset; + uint pathtag_offset; uint pathseg_offset; }; diff --git a/piet-gpu/shader/gen/draw_reduce.spv b/piet-gpu/shader/gen/draw_reduce.spv index 286bd332de696ebae624c53e6906d69400a05eed..02ebc5dd3dde42750026dc89ddb54cf9df6e77cb 100644 GIT binary patch delta 106 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 diff --git a/piet-gpu/shader/gen/pathseg.hlsl b/piet-gpu/shader/gen/pathseg.hlsl index e29ddd3..c7f7df0 100644 --- a/piet-gpu/shader/gen/pathseg.hlsl +++ b/piet-gpu/shader/gen/pathseg.hlsl @@ -65,9 +65,10 @@ struct Config Alloc bbox_alloc; Alloc drawmonoid_alloc; uint n_trans; + uint n_path; uint trans_offset; - uint pathtag_offset; uint linewidth_offset; + uint pathtag_offset; uint pathseg_offset; }; @@ -79,7 +80,7 @@ static const Monoid _567 = { 0.0f.xxxx, 0u }; RWByteAddressBuffer _111 : register(u0); ByteAddressBuffer _574 : register(t2); ByteAddressBuffer _639 : register(t1); -ByteAddressBuffer _710 : register(t3); +ByteAddressBuffer _709 : register(t3); static uint3 gl_WorkGroupID; static uint3 gl_LocalInvocationID; @@ -355,7 +356,7 @@ uint round_up(float x) void comp_main() { uint ix = gl_GlobalInvocationID.x * 4u; - uint tag_word = _574.Load(((_639.Load(56) >> uint(2)) + (ix >> uint(2))) * 4 + 0); + uint tag_word = _574.Load(((_639.Load(64) >> uint(2)) + (ix >> uint(2))) * 4 + 0); uint param = tag_word; TagMonoid local_tm = reduce_tag(param); sh_tag[gl_LocalInvocationID.x] = local_tm; @@ -376,17 +377,17 @@ void comp_main() TagMonoid tm = tag_monoid_identity(); if (gl_WorkGroupID.x > 0u) { - TagMonoid _716; - _716.trans_ix = _710.Load((gl_WorkGroupID.x - 1u) * 20 + 0); - _716.linewidth_ix = _710.Load((gl_WorkGroupID.x - 1u) * 20 + 4); - _716.pathseg_ix = _710.Load((gl_WorkGroupID.x - 1u) * 20 + 8); - _716.path_ix = _710.Load((gl_WorkGroupID.x - 1u) * 20 + 12); - _716.pathseg_offset = _710.Load((gl_WorkGroupID.x - 1u) * 20 + 16); - tm.trans_ix = _716.trans_ix; - tm.linewidth_ix = _716.linewidth_ix; - tm.pathseg_ix = _716.pathseg_ix; - tm.path_ix = _716.path_ix; - tm.pathseg_offset = _716.pathseg_offset; + TagMonoid _715; + _715.trans_ix = _709.Load((gl_WorkGroupID.x - 1u) * 20 + 0); + _715.linewidth_ix = _709.Load((gl_WorkGroupID.x - 1u) * 20 + 4); + _715.pathseg_ix = _709.Load((gl_WorkGroupID.x - 1u) * 20 + 8); + _715.path_ix = _709.Load((gl_WorkGroupID.x - 1u) * 20 + 12); + _715.pathseg_offset = _709.Load((gl_WorkGroupID.x - 1u) * 20 + 16); + tm.trans_ix = _715.trans_ix; + tm.linewidth_ix = _715.linewidth_ix; + tm.pathseg_ix = _715.pathseg_ix; + tm.path_ix = _715.path_ix; + tm.pathseg_offset = _715.pathseg_offset; } if (gl_LocalInvocationID.x > 0u) { @@ -394,13 +395,16 @@ void comp_main() TagMonoid param_4 = sh_tag[gl_LocalInvocationID.x - 1u]; tm = combine_tag_monoid(param_3, param_4); } - uint ps_ix = (_639.Load(64) >> uint(2)) + tm.pathseg_offset; + uint ps_ix = (_639.Load(68) >> uint(2)) + tm.pathseg_offset; uint lw_ix = (_639.Load(60) >> uint(2)) + tm.linewidth_ix; uint save_path_ix = tm.path_ix; - TransformSegRef _768 = { _639.Load(36) + (tm.trans_ix * 24u) }; - TransformSegRef trans_ref = _768; - PathSegRef _778 = { _639.Load(28) + (tm.pathseg_ix * 52u) }; - PathSegRef ps_ref = _778; + uint trans_ix = tm.trans_ix; + TransformSegRef _770 = { _639.Load(36) + (trans_ix * 24u) }; + TransformSegRef trans_ref = _770; + PathSegRef _780 = { _639.Load(28) + (tm.pathseg_ix * 52u) }; + PathSegRef ps_ref = _780; + float linewidth[4]; + uint save_trans_ix[4]; float2 p0; float2 p1; float2 p2; @@ -411,6 +415,8 @@ void comp_main() Alloc param_15; for (uint i_1 = 0u; i_1 < 4u; i_1++) { + linewidth[i_1] = asfloat(_574.Load(lw_ix * 4 + 0)); + save_trans_ix[i_1] = trans_ix; uint tag_byte = tag_word >> (i_1 * 8u); uint seg_type = tag_byte & 3u; if (seg_type != 0u) @@ -449,10 +455,9 @@ void comp_main() } } } - float linewidth = asfloat(_574.Load(lw_ix * 4 + 0)); - Alloc _864; - _864.offset = _639.Load(36); - param_13.offset = _864.offset; + Alloc _876; + _876.offset = _639.Load(36); + param_13.offset = _876.offset; TransformSegRef param_14 = trans_ref; TransformSeg transform = TransformSeg_read(param_13, param_14); p0 = ((transform.mat.xy * p0.x) + (transform.mat.zw * p0.y)) + transform.translate; @@ -461,25 +466,25 @@ void comp_main() if (seg_type >= 2u) { p2 = ((transform.mat.xy * p2.x) + (transform.mat.zw * p2.y)) + transform.translate; - float4 _934 = bbox; - float2 _937 = min(_934.xy, p2); - bbox.x = _937.x; - bbox.y = _937.y; - float4 _942 = bbox; - float2 _945 = max(_942.zw, p2); - bbox.z = _945.x; - bbox.w = _945.y; + float4 _946 = bbox; + float2 _949 = min(_946.xy, p2); + bbox.x = _949.x; + bbox.y = _949.y; + float4 _954 = bbox; + float2 _957 = max(_954.zw, p2); + bbox.z = _957.x; + bbox.w = _957.y; if (seg_type == 3u) { p3 = ((transform.mat.xy * p3.x) + (transform.mat.zw * p3.y)) + transform.translate; - float4 _970 = bbox; - float2 _973 = min(_970.xy, p3); - bbox.x = _973.x; - bbox.y = _973.y; - float4 _978 = bbox; - float2 _981 = max(_978.zw, p3); - bbox.z = _981.x; - bbox.w = _981.y; + float4 _982 = bbox; + float2 _985 = min(_982.xy, p3); + bbox.x = _985.x; + bbox.y = _985.y; + float4 _990 = bbox; + float2 _993 = max(_990.zw, p3); + bbox.z = _993.x; + bbox.w = _993.y; } else { @@ -495,9 +500,9 @@ void comp_main() p1 = lerp(p0, p3, 0.3333333432674407958984375f.xx); } float2 stroke = 0.0f.xx; - if (linewidth >= 0.0f) + if (linewidth[i_1] >= 0.0f) { - stroke = float2(length(transform.mat.xz), length(transform.mat.yw)) * (0.5f * linewidth); + stroke = float2(length(transform.mat.xz), length(transform.mat.yw)) * (0.5f * linewidth[i_1]); bbox += float4(-stroke, stroke); } local[i_1].bbox = bbox; @@ -509,10 +514,10 @@ void comp_main() cubic.path_ix = tm.path_ix; cubic.trans_ix = (gl_GlobalInvocationID.x * 4u) + i_1; cubic.stroke = stroke; - uint fill_mode = uint(linewidth >= 0.0f); - Alloc _1070; - _1070.offset = _639.Load(28); - param_15.offset = _1070.offset; + uint fill_mode = uint(linewidth[i_1] >= 0.0f); + Alloc _1088; + _1088.offset = _639.Load(28); + param_15.offset = _1088.offset; PathSegRef param_16 = ps_ref; uint param_17 = fill_mode; PathCubic param_18 = cubic; @@ -528,6 +533,7 @@ void comp_main() uint is_path = (tag_byte >> uint(4)) & 1u; local[i_1].flags = is_path; tm.path_ix += is_path; + trans_ix += ((tag_byte >> uint(5)) & 1u); trans_ref.offset += (((tag_byte >> uint(5)) & 1u) * 24u); lw_ix += ((tag_byte >> uint(6)) & 1u); } @@ -556,7 +562,7 @@ void comp_main() } GroupMemoryBarrierWithGroupSync(); uint path_ix = save_path_ix; - uint bbox_out_ix = (_639.Load(40) >> uint(2)) + (path_ix * 4u); + uint bbox_out_ix = (_639.Load(40) >> uint(2)) + (path_ix * 6u); Monoid row = monoid_identity(); if (gl_LocalInvocationID.x > 0u) { @@ -568,22 +574,24 @@ void comp_main() Monoid param_24 = local[i_4]; Monoid m = combine_monoid(param_23, param_24); bool do_atomic = false; - bool _1240 = i_4 == 3u; - bool _1247; - if (_1240) + bool _1263 = i_4 == 3u; + bool _1270; + if (_1263) { - _1247 = gl_LocalInvocationID.x == 511u; + _1270 = gl_LocalInvocationID.x == 511u; } else { - _1247 = _1240; + _1270 = _1263; } - if (_1247) + if (_1270) { do_atomic = true; } if ((m.flags & 1u) != 0u) { + _111.Store((bbox_out_ix + 4u) * 4 + 8, asuint(linewidth[i_4])); + _111.Store((bbox_out_ix + 5u) * 4 + 8, save_trans_ix[i_4]); if ((m.flags & 2u) == 0u) { do_atomic = true; @@ -598,38 +606,38 @@ void comp_main() _111.Store((bbox_out_ix + 2u) * 4 + 8, round_up(param_27)); float param_28 = m.bbox.w; _111.Store((bbox_out_ix + 3u) * 4 + 8, round_up(param_28)); - bbox_out_ix += 4u; + bbox_out_ix += 6u; do_atomic = false; } } if (do_atomic) { - bool _1299 = m.bbox.z > m.bbox.x; - bool _1308; - if (!_1299) + bool _1335 = m.bbox.z > m.bbox.x; + bool _1344; + if (!_1335) { - _1308 = m.bbox.w > m.bbox.y; + _1344 = m.bbox.w > m.bbox.y; } else { - _1308 = _1299; + _1344 = _1335; } - if (_1308) + if (_1344) { float param_29 = m.bbox.x; - uint _1317; - _111.InterlockedMin(bbox_out_ix * 4 + 8, round_down(param_29), _1317); + uint _1353; + _111.InterlockedMin(bbox_out_ix * 4 + 8, round_down(param_29), _1353); float param_30 = m.bbox.y; - uint _1325; - _111.InterlockedMin((bbox_out_ix + 1u) * 4 + 8, round_down(param_30), _1325); + uint _1361; + _111.InterlockedMin((bbox_out_ix + 1u) * 4 + 8, round_down(param_30), _1361); float param_31 = m.bbox.z; - uint _1333; - _111.InterlockedMax((bbox_out_ix + 2u) * 4 + 8, round_up(param_31), _1333); + uint _1369; + _111.InterlockedMax((bbox_out_ix + 2u) * 4 + 8, round_up(param_31), _1369); float param_32 = m.bbox.w; - uint _1341; - _111.InterlockedMax((bbox_out_ix + 3u) * 4 + 8, round_up(param_32), _1341); + uint _1377; + _111.InterlockedMax((bbox_out_ix + 3u) * 4 + 8, round_up(param_32), _1377); } - bbox_out_ix += 4u; + bbox_out_ix += 6u; } } } diff --git a/piet-gpu/shader/gen/pathseg.msl b/piet-gpu/shader/gen/pathseg.msl index 71299bd..0f60d4d 100644 --- a/piet-gpu/shader/gen/pathseg.msl +++ b/piet-gpu/shader/gen/pathseg.msl @@ -130,9 +130,10 @@ struct Config Alloc_1 bbox_alloc; Alloc_1 drawmonoid_alloc; uint n_trans; + uint n_path; uint trans_offset; - uint pathtag_offset; uint linewidth_offset; + uint pathtag_offset; uint pathseg_offset; }; @@ -429,7 +430,7 @@ uint round_up(thread const float& x) return uint(fast::min(65535.0, ceil(x) + 32768.0)); } -kernel void main0(device Memory& v_111 [[buffer(0)]], const device ConfigBuf& _639 [[buffer(1)]], const device SceneBuf& v_574 [[buffer(2)]], const device ParentBuf& _710 [[buffer(3)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]], uint3 gl_LocalInvocationID [[thread_position_in_threadgroup]], uint3 gl_WorkGroupID [[threadgroup_position_in_grid]]) +kernel void main0(device Memory& v_111 [[buffer(0)]], const device ConfigBuf& _639 [[buffer(1)]], const device SceneBuf& v_574 [[buffer(2)]], const device ParentBuf& _709 [[buffer(3)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]], uint3 gl_LocalInvocationID [[thread_position_in_threadgroup]], uint3 gl_WorkGroupID [[threadgroup_position_in_grid]]) { threadgroup TagMonoid sh_tag[512]; threadgroup Monoid sh_scratch[512]; @@ -455,12 +456,12 @@ kernel void main0(device Memory& v_111 [[buffer(0)]], const device ConfigBuf& _6 TagMonoid tm = tag_monoid_identity(); if (gl_WorkGroupID.x > 0u) { - uint _713 = gl_WorkGroupID.x - 1u; - tm.trans_ix = _710.parent[_713].trans_ix; - tm.linewidth_ix = _710.parent[_713].linewidth_ix; - tm.pathseg_ix = _710.parent[_713].pathseg_ix; - tm.path_ix = _710.parent[_713].path_ix; - tm.pathseg_offset = _710.parent[_713].pathseg_offset; + uint _712 = gl_WorkGroupID.x - 1u; + tm.trans_ix = _709.parent[_712].trans_ix; + tm.linewidth_ix = _709.parent[_712].linewidth_ix; + tm.pathseg_ix = _709.parent[_712].pathseg_ix; + tm.path_ix = _709.parent[_712].path_ix; + tm.pathseg_offset = _709.parent[_712].pathseg_offset; } if (gl_LocalInvocationID.x > 0u) { @@ -471,8 +472,11 @@ kernel void main0(device Memory& v_111 [[buffer(0)]], const device ConfigBuf& _6 uint ps_ix = (_639.conf.pathseg_offset >> uint(2)) + tm.pathseg_offset; uint lw_ix = (_639.conf.linewidth_offset >> uint(2)) + tm.linewidth_ix; uint save_path_ix = tm.path_ix; - TransformSegRef trans_ref = TransformSegRef{ _639.conf.trans_alloc.offset + (tm.trans_ix * 24u) }; + uint trans_ix = tm.trans_ix; + TransformSegRef trans_ref = TransformSegRef{ _639.conf.trans_alloc.offset + (trans_ix * 24u) }; PathSegRef ps_ref = PathSegRef{ _639.conf.pathseg_alloc.offset + (tm.pathseg_ix * 52u) }; + spvUnsafeArray linewidth; + spvUnsafeArray save_trans_ix; float2 p0; float2 p1; float2 p2; @@ -483,6 +487,8 @@ kernel void main0(device Memory& v_111 [[buffer(0)]], const device ConfigBuf& _6 Alloc param_15; for (uint i_1 = 0u; i_1 < 4u; i_1++) { + linewidth[i_1] = as_type(v_574.scene[lw_ix]); + save_trans_ix[i_1] = trans_ix; uint tag_byte = tag_word >> (i_1 * 8u); uint seg_type = tag_byte & 3u; if (seg_type != 0u) @@ -521,7 +527,6 @@ kernel void main0(device Memory& v_111 [[buffer(0)]], const device ConfigBuf& _6 } } } - float linewidth = as_type(v_574.scene[lw_ix]); param_13.offset = _639.conf.trans_alloc.offset; TransformSegRef param_14 = trans_ref; TransformSeg transform = TransformSeg_read(param_13, param_14, v_111); @@ -531,25 +536,25 @@ kernel void main0(device Memory& v_111 [[buffer(0)]], const device ConfigBuf& _6 if (seg_type >= 2u) { p2 = ((transform.mat.xy * p2.x) + (transform.mat.zw * p2.y)) + transform.translate; - float4 _934 = bbox; - float2 _937 = fast::min(_934.xy, p2); - bbox.x = _937.x; - bbox.y = _937.y; - float4 _942 = bbox; - float2 _945 = fast::max(_942.zw, p2); - bbox.z = _945.x; - bbox.w = _945.y; + float4 _946 = bbox; + float2 _949 = fast::min(_946.xy, p2); + bbox.x = _949.x; + bbox.y = _949.y; + float4 _954 = bbox; + float2 _957 = fast::max(_954.zw, p2); + bbox.z = _957.x; + bbox.w = _957.y; if (seg_type == 3u) { p3 = ((transform.mat.xy * p3.x) + (transform.mat.zw * p3.y)) + transform.translate; - float4 _970 = bbox; - float2 _973 = fast::min(_970.xy, p3); - bbox.x = _973.x; - bbox.y = _973.y; - float4 _978 = bbox; - float2 _981 = fast::max(_978.zw, p3); - bbox.z = _981.x; - bbox.w = _981.y; + float4 _982 = bbox; + float2 _985 = fast::min(_982.xy, p3); + bbox.x = _985.x; + bbox.y = _985.y; + float4 _990 = bbox; + float2 _993 = fast::max(_990.zw, p3); + bbox.z = _993.x; + bbox.w = _993.y; } else { @@ -565,9 +570,9 @@ kernel void main0(device Memory& v_111 [[buffer(0)]], const device ConfigBuf& _6 p1 = mix(p0, p3, float2(0.3333333432674407958984375)); } float2 stroke = float2(0.0); - if (linewidth >= 0.0) + if (linewidth[i_1] >= 0.0) { - stroke = float2(length(transform.mat.xz), length(transform.mat.yw)) * (0.5 * linewidth); + stroke = float2(length(transform.mat.xz), length(transform.mat.yw)) * (0.5 * linewidth[i_1]); bbox += float4(-stroke, stroke); } local[i_1].bbox = bbox; @@ -579,7 +584,7 @@ kernel void main0(device Memory& v_111 [[buffer(0)]], const device ConfigBuf& _6 cubic.path_ix = tm.path_ix; cubic.trans_ix = (gl_GlobalInvocationID.x * 4u) + i_1; cubic.stroke = stroke; - uint fill_mode = uint(linewidth >= 0.0); + uint fill_mode = uint(linewidth[i_1] >= 0.0); param_15.offset = _639.conf.pathseg_alloc.offset; PathSegRef param_16 = ps_ref; uint param_17 = fill_mode; @@ -596,6 +601,7 @@ kernel void main0(device Memory& v_111 [[buffer(0)]], const device ConfigBuf& _6 uint is_path = (tag_byte >> uint(4)) & 1u; local[i_1].flags = is_path; tm.path_ix += is_path; + trans_ix += ((tag_byte >> uint(5)) & 1u); trans_ref.offset += (((tag_byte >> uint(5)) & 1u) * 24u); lw_ix += ((tag_byte >> uint(6)) & 1u); } @@ -624,7 +630,7 @@ kernel void main0(device Memory& v_111 [[buffer(0)]], const device ConfigBuf& _6 } threadgroup_barrier(mem_flags::mem_threadgroup); uint path_ix = save_path_ix; - uint bbox_out_ix = (_639.conf.bbox_alloc.offset >> uint(2)) + (path_ix * 4u); + uint bbox_out_ix = (_639.conf.bbox_alloc.offset >> uint(2)) + (path_ix * 6u); Monoid row = monoid_identity(); if (gl_LocalInvocationID.x > 0u) { @@ -636,22 +642,24 @@ kernel void main0(device Memory& v_111 [[buffer(0)]], const device ConfigBuf& _6 Monoid param_24 = local[i_4]; Monoid m = combine_monoid(param_23, param_24); bool do_atomic = false; - bool _1240 = i_4 == 3u; - bool _1247; - if (_1240) + bool _1263 = i_4 == 3u; + bool _1270; + if (_1263) { - _1247 = gl_LocalInvocationID.x == 511u; + _1270 = gl_LocalInvocationID.x == 511u; } else { - _1247 = _1240; + _1270 = _1263; } - if (_1247) + if (_1270) { do_atomic = true; } if ((m.flags & 1u) != 0u) { + v_111.memory[bbox_out_ix + 4u] = as_type(linewidth[i_4]); + v_111.memory[bbox_out_ix + 5u] = save_trans_ix[i_4]; if ((m.flags & 2u) == 0u) { do_atomic = true; @@ -666,34 +674,34 @@ kernel void main0(device Memory& v_111 [[buffer(0)]], const device ConfigBuf& _6 v_111.memory[bbox_out_ix + 2u] = round_up(param_27); float param_28 = m.bbox.w; v_111.memory[bbox_out_ix + 3u] = round_up(param_28); - bbox_out_ix += 4u; + bbox_out_ix += 6u; do_atomic = false; } } if (do_atomic) { - bool _1299 = m.bbox.z > m.bbox.x; - bool _1308; - if (!_1299) + bool _1335 = m.bbox.z > m.bbox.x; + bool _1344; + if (!_1335) { - _1308 = m.bbox.w > m.bbox.y; + _1344 = m.bbox.w > m.bbox.y; } else { - _1308 = _1299; + _1344 = _1335; } - if (_1308) + if (_1344) { float param_29 = m.bbox.x; - uint _1317 = atomic_fetch_min_explicit((device atomic_uint*)&v_111.memory[bbox_out_ix], round_down(param_29), memory_order_relaxed); + uint _1353 = atomic_fetch_min_explicit((device atomic_uint*)&v_111.memory[bbox_out_ix], round_down(param_29), memory_order_relaxed); float param_30 = m.bbox.y; - uint _1325 = atomic_fetch_min_explicit((device atomic_uint*)&v_111.memory[bbox_out_ix + 1u], round_down(param_30), memory_order_relaxed); + uint _1361 = atomic_fetch_min_explicit((device atomic_uint*)&v_111.memory[bbox_out_ix + 1u], round_down(param_30), memory_order_relaxed); float param_31 = m.bbox.z; - uint _1333 = atomic_fetch_max_explicit((device atomic_uint*)&v_111.memory[bbox_out_ix + 2u], round_up(param_31), memory_order_relaxed); + uint _1369 = atomic_fetch_max_explicit((device atomic_uint*)&v_111.memory[bbox_out_ix + 2u], round_up(param_31), memory_order_relaxed); float param_32 = m.bbox.w; - uint _1341 = atomic_fetch_max_explicit((device atomic_uint*)&v_111.memory[bbox_out_ix + 3u], round_up(param_32), memory_order_relaxed); + uint _1377 = atomic_fetch_max_explicit((device atomic_uint*)&v_111.memory[bbox_out_ix + 3u], round_up(param_32), memory_order_relaxed); } - bbox_out_ix += 4u; + bbox_out_ix += 6u; } } } diff --git a/piet-gpu/shader/gen/pathseg.spv b/piet-gpu/shader/gen/pathseg.spv index bc165ac544b202659b7c62175b161a7100b2d61a..fc63eb5375b579bd2fcdb56a795572c245b9a9e6 100644 GIT binary patch literal 34748 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

{KZ~|*!Tec#YJxe{B;t{@T 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 H&F%jH1dE2y literal 33960 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 uint(2)) + ix; - uint tag_word = _151.Load(scene_ix * 4 + 0); + uint scene_ix = (_139.Load(64) >> uint(2)) + ix; + uint tag_word = _150.Load(scene_ix * 4 + 0); uint param = tag_word; TagMonoid agg = reduce_tag(param); for (uint i = 1u; i < 4u; i++) { - tag_word = _151.Load((scene_ix + i) * 4 + 0); + tag_word = _150.Load((scene_ix + i) * 4 + 0); uint param_1 = tag_word; TagMonoid param_2 = agg; TagMonoid param_3 = reduce_tag(param_1); @@ -110,11 +111,11 @@ void comp_main() } if (gl_LocalInvocationID.x == 0u) { - _239.Store(gl_WorkGroupID.x * 20 + 0, agg.trans_ix); - _239.Store(gl_WorkGroupID.x * 20 + 4, agg.linewidth_ix); - _239.Store(gl_WorkGroupID.x * 20 + 8, agg.pathseg_ix); - _239.Store(gl_WorkGroupID.x * 20 + 12, agg.path_ix); - _239.Store(gl_WorkGroupID.x * 20 + 16, agg.pathseg_offset); + _238.Store(gl_WorkGroupID.x * 20 + 0, agg.trans_ix); + _238.Store(gl_WorkGroupID.x * 20 + 4, agg.linewidth_ix); + _238.Store(gl_WorkGroupID.x * 20 + 8, agg.pathseg_ix); + _238.Store(gl_WorkGroupID.x * 20 + 12, agg.path_ix); + _238.Store(gl_WorkGroupID.x * 20 + 16, agg.pathseg_offset); } } diff --git a/piet-gpu/shader/gen/pathtag_reduce.msl b/piet-gpu/shader/gen/pathtag_reduce.msl index 38451d4..e82577c 100644 --- a/piet-gpu/shader/gen/pathtag_reduce.msl +++ b/piet-gpu/shader/gen/pathtag_reduce.msl @@ -34,9 +34,10 @@ struct Config Alloc bbox_alloc; Alloc drawmonoid_alloc; uint n_trans; + uint n_path; uint trans_offset; - uint pathtag_offset; uint linewidth_offset; + uint pathtag_offset; uint pathseg_offset; }; @@ -102,17 +103,17 @@ TagMonoid combine_tag_monoid(thread const TagMonoid& a, thread const TagMonoid& return c; } -kernel void main0(const device ConfigBuf& _139 [[buffer(1)]], const device SceneBuf& _151 [[buffer(2)]], device OutBuf& _239 [[buffer(3)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]], uint3 gl_LocalInvocationID [[thread_position_in_threadgroup]], uint3 gl_WorkGroupID [[threadgroup_position_in_grid]]) +kernel void main0(const device ConfigBuf& _139 [[buffer(1)]], const device SceneBuf& _150 [[buffer(2)]], device OutBuf& _238 [[buffer(3)]], uint3 gl_GlobalInvocationID [[thread_position_in_grid]], uint3 gl_LocalInvocationID [[thread_position_in_threadgroup]], uint3 gl_WorkGroupID [[threadgroup_position_in_grid]]) { threadgroup TagMonoid sh_scratch[128]; uint ix = gl_GlobalInvocationID.x * 4u; uint scene_ix = (_139.conf.pathtag_offset >> uint(2)) + ix; - uint tag_word = _151.scene[scene_ix]; + uint tag_word = _150.scene[scene_ix]; uint param = tag_word; TagMonoid agg = reduce_tag(param); for (uint i = 1u; i < 4u; i++) { - tag_word = _151.scene[scene_ix + i]; + tag_word = _150.scene[scene_ix + i]; uint param_1 = tag_word; TagMonoid param_2 = agg; TagMonoid param_3 = reduce_tag(param_1); @@ -134,11 +135,11 @@ kernel void main0(const device ConfigBuf& _139 [[buffer(1)]], const device Scene } if (gl_LocalInvocationID.x == 0u) { - _239.outbuf[gl_WorkGroupID.x].trans_ix = agg.trans_ix; - _239.outbuf[gl_WorkGroupID.x].linewidth_ix = agg.linewidth_ix; - _239.outbuf[gl_WorkGroupID.x].pathseg_ix = agg.pathseg_ix; - _239.outbuf[gl_WorkGroupID.x].path_ix = agg.path_ix; - _239.outbuf[gl_WorkGroupID.x].pathseg_offset = agg.pathseg_offset; + _238.outbuf[gl_WorkGroupID.x].trans_ix = agg.trans_ix; + _238.outbuf[gl_WorkGroupID.x].linewidth_ix = agg.linewidth_ix; + _238.outbuf[gl_WorkGroupID.x].pathseg_ix = agg.pathseg_ix; + _238.outbuf[gl_WorkGroupID.x].path_ix = agg.path_ix; + _238.outbuf[gl_WorkGroupID.x].pathseg_offset = agg.pathseg_offset; } } diff --git a/piet-gpu/shader/gen/pathtag_reduce.spv b/piet-gpu/shader/gen/pathtag_reduce.spv index eef46a24459484ae0ac3583f17afc40053fd5eb5..6dc35b845e6222173a4d994a2e1bc950f1404231 100644 GIT binary patch literal 7836 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 CNn4Qs literal 7808 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 diff --git a/piet-gpu/shader/gen/transform_leaf.dxil b/piet-gpu/shader/gen/transform_leaf.dxil index dabc049cfc66cc57a325910e517ad994012ae1d4..102d2f06e3d65390fc3cbca7f118a929ac59002b 100644 GIT binary patch delta 58 zcmV-A0LA~HETAkDL|8&Yl(0RV!QrZK{^UF6O86z*u@o!_5Cdjfl4Iy^igO>E$#6*D QRI^YBJq7`AvyKju2MX*N7XSbN delta 58 zcmV-A0LA~HETAkDL|8&Y@QST5q*Z}%F^j2ulyYt#u@o!_5Z7}dpyTY8y6Jx_laSbv Qy|YjVJq7`2vyKju2j!y~G5`Po diff --git a/piet-gpu/shader/gen/transform_leaf.hlsl b/piet-gpu/shader/gen/transform_leaf.hlsl index 2f0de05..6fa9267 100644 --- a/piet-gpu/shader/gen/transform_leaf.hlsl +++ b/piet-gpu/shader/gen/transform_leaf.hlsl @@ -40,9 +40,10 @@ struct Config Alloc bbox_alloc; Alloc drawmonoid_alloc; uint n_trans; + uint n_path; uint trans_offset; - uint pathtag_offset; uint linewidth_offset; + uint pathtag_offset; uint pathseg_offset; }; @@ -149,7 +150,7 @@ void TransformSeg_write(Alloc a, TransformSegRef ref, TransformSeg s) void comp_main() { uint ix = gl_GlobalInvocationID.x * 8u; - TransformRef _285 = { _278.Load(52) + (ix * 24u) }; + TransformRef _285 = { _278.Load(56) + (ix * 24u) }; TransformRef ref = _285; TransformRef param = ref; Transform agg = Transform_read(param); diff --git a/piet-gpu/shader/gen/transform_leaf.msl b/piet-gpu/shader/gen/transform_leaf.msl index 3120b3d..9c7e6b7 100644 --- a/piet-gpu/shader/gen/transform_leaf.msl +++ b/piet-gpu/shader/gen/transform_leaf.msl @@ -103,9 +103,10 @@ struct Config Alloc_1 bbox_alloc; Alloc_1 drawmonoid_alloc; uint n_trans; + uint n_path; uint trans_offset; - uint pathtag_offset; uint linewidth_offset; + uint pathtag_offset; uint pathseg_offset; }; diff --git a/piet-gpu/shader/gen/transform_leaf.spv b/piet-gpu/shader/gen/transform_leaf.spv index 01f047b0a5f8df599282bdea4fec1d55444c97b2..e561e9dcc5b5efa2b6e077e953d952b180e52c0a 100644 GIT binary patch delta 121 zcmX?*_$G0K8ix)mgD@il11|#uLtcDAVo3%A0~-T7Sd0%SR#KFhR~(<8mR6iv!oV;& zio-~>BrzQ>08=Wsxs~H83qQmxL7+ZmAa>at%6pWBQDm~TkmuwCAsa@%&2xp6@4Itd4iAyBk$&uLdtRg%$^ip diff --git a/piet-gpu/shader/gen/transform_reduce.dxil b/piet-gpu/shader/gen/transform_reduce.dxil index 68997d0bbd2f4dd44f1be2c2873d2f72bf5ece3e..1ed5e0e3dc4b5a533f1829c1818e590d6ddede9d 100644 GIT binary patch delta 58 zcmV-A0LA~r$LFV|6{nUkFigJ2 zVkBCUm<|_!DHYtz$oiIQ9bOAY-p#4J@qz$k^%)!h diff --git a/piet-gpu/shader/kernel4.spv b/piet-gpu/shader/kernel4.spv index 04b6364ccf608fe0086b189a14d827bec4935a87..0eb1e5aba458f4e344cc68f4bbaf4f26ee236928 100644 GIT binary patch delta 107 zcmZ3nk?G1trVaN*bXXZKFflOjGB7aY#TO)&WH2zWF|dQh_<&+1MTvRE@%d?K#i=C> x43mXKjV5!5^07k{2yV6&J;==uF+mWhS{aC4Hvd#;rPgWEa7UBc)3KB~)N)prK^V8CbQ%fdu di5hK=5Z%SSSxvElhf#R)a$V2OUvwX20RT1N7oGqB diff --git a/piet-gpu/shader/path_coarse.comp b/piet-gpu/shader/path_coarse.comp index ea525f5..1bd06f9 100644 --- a/piet-gpu/shader/path_coarse.comp +++ b/piet-gpu/shader/path_coarse.comp @@ -100,6 +100,8 @@ void main() { case PathSeg_Cubic: PathCubic cubic = PathSeg_Cubic_read(conf.pathseg_alloc, ref); + // Affine transform is now applied in pathseg + /* uint trans_ix = cubic.trans_ix; if (trans_ix > 0) { TransformSegRef trans_ref = TransformSegRef(conf.trans_alloc.offset + (trans_ix - 1) * TransformSeg_size); @@ -109,6 +111,7 @@ void main() { cubic.p2 = trans.mat.xy * cubic.p2.x + trans.mat.zw * cubic.p2.y + trans.translate; cubic.p3 = trans.mat.xy * cubic.p3.x + trans.mat.zw * cubic.p3.y + trans.translate; } + */ vec2 err_v = 3.0 * (cubic.p2 - cubic.p1) + cubic.p0 - cubic.p3; float err = err_v.x * err_v.x + err_v.y * err_v.y; diff --git a/piet-gpu/shader/path_coarse.spv b/piet-gpu/shader/path_coarse.spv index 240f8f717e522719baa00836d819ff5f7aac99b5..0da044f27840585e1c819014b0fa359181e78b65 100644 GIT binary patch literal 39324 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 B{_MRPO+DAdHDI;%DS5VC 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 2) + tm.pathseg_offset; uint lw_ix = (conf.linewidth_offset >> 2) + tm.linewidth_ix; uint save_path_ix = tm.path_ix; - TransformSegRef trans_ref = TransformSegRef(conf.trans_alloc.offset + tm.trans_ix * TransformSeg_size); + uint trans_ix = tm.trans_ix; + TransformSegRef trans_ref = TransformSegRef(conf.trans_alloc.offset + trans_ix * TransformSeg_size); PathSegRef ps_ref = PathSegRef(conf.pathseg_alloc.offset + tm.pathseg_ix * PathSeg_size); for (uint i = 0; i < N_SEQ; i++) { + linewidth[i] = uintBitsToFloat(scene[lw_ix]); + save_trans_ix[i] = trans_ix; // if N_SEQ > 4, need to load tag_word from local if N_SEQ % 4 == 0 uint tag_byte = tag_word >> (i * 8); uint seg_type = tag_byte & 3; @@ -158,7 +163,6 @@ void main() { } } } - float linewidth = uintBitsToFloat(scene[lw_ix]); TransformSeg transform = TransformSeg_read(conf.trans_alloc, trans_ref); p0 = transform.mat.xy * p0.x + transform.mat.zw * p0.y + transform.translate; p1 = transform.mat.xy * p1.x + transform.mat.zw * p1.y + transform.translate; @@ -183,9 +187,9 @@ void main() { p1 = mix(p0, p3, 1.0 / 3.0); } vec2 stroke = vec2(0.0, 0.0); - if (linewidth >= 0.0) { + if (linewidth[i] >= 0.0) { // See https://www.iquilezles.org/www/articles/ellipses/ellipses.htm - stroke = 0.5 * linewidth * vec2(length(transform.mat.xz), length(transform.mat.yw)); + stroke = 0.5 * linewidth[i] * vec2(length(transform.mat.xz), length(transform.mat.yw)); bbox += vec4(-stroke, stroke); } local[i].bbox = bbox; @@ -201,7 +205,7 @@ void main() { // Not needed, TODO remove from struct cubic.trans_ix = gl_GlobalInvocationID.x * 4 + i; cubic.stroke = stroke; - uint fill_mode = uint(linewidth >= 0.0); + uint fill_mode = uint(linewidth[i] >= 0.0); PathSeg_Cubic_write(conf.pathseg_alloc, ps_ref, fill_mode, cubic); ps_ref.offset += PathSeg_size; @@ -215,6 +219,7 @@ void main() { // Relies on the fact that RESET_BBOX == 1 local[i].flags = is_path; tm.path_ix += is_path; + trans_ix += (tag_byte >> 5) & 1; trans_ref.offset += ((tag_byte >> 5) & 1) * TransformSeg_size; lw_ix += (tag_byte >> 6) & 1; } @@ -244,7 +249,7 @@ void main() { barrier(); uint path_ix = save_path_ix; - uint bbox_out_ix = (conf.bbox_alloc.offset >> 2) + path_ix * 4; + uint bbox_out_ix = (conf.bbox_alloc.offset >> 2) + path_ix * 6; // Write bboxes to paths; do atomic min/max if partial Monoid row = monoid_identity(); if (gl_LocalInvocationID.x > 0) { @@ -259,6 +264,8 @@ void main() { do_atomic = true; } if ((m.flags & FLAG_RESET_BBOX) != 0) { + memory[bbox_out_ix + 4] = floatBitsToUint(linewidth[i]); + memory[bbox_out_ix + 5] = save_trans_ix[i]; if ((m.flags & FLAG_SET_BBOX) == 0) { do_atomic = true; } else { @@ -266,7 +273,7 @@ void main() { memory[bbox_out_ix + 1] = round_down(m.bbox.y); memory[bbox_out_ix + 2] = round_up(m.bbox.z); memory[bbox_out_ix + 3] = round_up(m.bbox.w); - bbox_out_ix += 4; + bbox_out_ix += 6; do_atomic = false; } } @@ -278,7 +285,7 @@ void main() { atomicMax(memory[bbox_out_ix + 2], round_up(m.bbox.z)); atomicMax(memory[bbox_out_ix + 3], round_up(m.bbox.w)); } - bbox_out_ix += 4; + bbox_out_ix += 6; } } } diff --git a/piet-gpu/shader/setup.h b/piet-gpu/shader/setup.h index 3bb1fdd..5d4cc73 100644 --- a/piet-gpu/shader/setup.h +++ b/piet-gpu/shader/setup.h @@ -48,12 +48,14 @@ struct Config { // Number of transforms in scene // This is probably not needed. uint n_trans; + // This only counts actual paths, not EndClip. + uint n_path; // Offset (in bytes) of transform stream in scene buffer uint trans_offset; - // Offset (in bytes) of path tag stream in scene - uint pathtag_offset; // Offset (in bytes) of linewidth stream in scene uint linewidth_offset; + // Offset (in bytes) of path tag stream in scene + uint pathtag_offset; // Offset (in bytes) of path segment stream in scene uint pathseg_offset; }; diff --git a/piet-gpu/shader/tile_alloc.spv b/piet-gpu/shader/tile_alloc.spv index 0de00e3a4de89d3514ac092538e17d630932caf1..b443b031d0471f4fe289b6cae2795e3975dca240 100644 GIT binary patch delta 102 zcmZ2ecB5=V7nd|EgB~LT11|#uLtcDAVo3%A0~-T7Sd4G-L@v?Ehq&}aOA^!L^V8Cb pQ%exCf}3A*<+AWYv, + tag_stream: Vec, + pathseg_stream: Vec, + linewidth_stream: Vec, + drawobj_stream: Vec, + n_path: u32, + n_pathseg: u32, +} + +// Currently same as Element, but may change - should become packed. +const DRAWOBJ_SIZE: usize = 36; +const TRANSFORM_SIZE: usize = 24; +const LINEWIDTH_SIZE: usize = 4; +const PATHSEG_SIZE: usize = 52; +const BBOX_SIZE: usize = 24; +const DRAWMONOID_SIZE: usize = 8; +const ANNOTATED_SIZE: usize = 40; + +// Maybe pull these from the relevant stages? In any case, they may depend +// on runtime query of GPU (supported workgroup size). +const TRANSFORM_PART_SIZE: usize = 4096; +const PATHSEG_PART_SIZE: usize = 2048; +const DRAWOBJ_PART_SIZE: usize = 4096; + +// These are bytemuck versions of elements currently defined in the +// Element struct in piet-gpu-types; that's pretty much going away. + +const ELEMENT_FILLCOLOR: u32 = 4; + +#[repr(C)] +#[derive(Clone, Copy, Debug, Default, Zeroable, Pod)] +pub struct FillColor { + tag: u32, + rgba_color: u32, + padding: [u32; 7], +} + +impl Encoder { + pub fn new() -> Encoder { + Encoder { + transform_stream: vec![Transform::IDENTITY], + tag_stream: Vec::new(), + pathseg_stream: Vec::new(), + linewidth_stream: vec![-1.0], + drawobj_stream: Vec::new(), + n_path: 0, + n_pathseg: 0, + } + } + + pub fn path_encoder(&mut self) -> PathEncoder { + PathEncoder::new(&mut self.tag_stream, &mut self.pathseg_stream) + } + + pub fn finish_path(&mut self, n_pathseg: u32) { + self.n_path += 1; + self.n_pathseg += n_pathseg; + } + + pub fn transform(&mut self, transform: Transform) { + self.tag_stream.push(0x20); + self.transform_stream.push(transform); + } + + // -1.0 means "fill" + pub fn linewidth(&mut self, linewidth: f32) { + self.tag_stream.push(0x40); + self.linewidth_stream.push(linewidth); + } + + /// Encode a fill color draw object. + /// + /// This should be encoded after a path. + pub fn fill_color(&mut self, rgba_color: u32) { + let element = FillColor { + tag: ELEMENT_FILLCOLOR, + rgba_color, + ..Default::default() + }; + self.drawobj_stream.extend(bytemuck::bytes_of(&element)); + } + + /// Return a config for the element processing pipeline. + /// + /// This does not include further pipeline processing. Also returns the + /// beginning of free memory. + pub fn stage_config(&self) -> (Config, usize) { + // Layout of scene buffer + let n_drawobj = self.n_drawobj(); + let n_drawobj_padded = align_up(n_drawobj, DRAWOBJ_PART_SIZE); + let trans_offset = n_drawobj_padded * DRAWOBJ_SIZE; + let n_trans = self.transform_stream.len(); + let n_trans_padded = align_up(n_trans, TRANSFORM_PART_SIZE); + let linewidth_offset = trans_offset + n_trans_padded * TRANSFORM_SIZE; + let n_linewidth = self.linewidth_stream.len(); + let pathtag_offset = linewidth_offset + n_linewidth * LINEWIDTH_SIZE; + let n_pathtag = self.tag_stream.len(); + let n_pathtag_padded = align_up(n_pathtag, PATHSEG_PART_SIZE); + let pathseg_offset = pathtag_offset + n_pathtag_padded; + + // Layout of memory + let mut alloc = 0; + let trans_alloc = alloc; + alloc += trans_alloc + n_trans_padded * TRANSFORM_SIZE; + let pathseg_alloc = alloc; + alloc += pathseg_alloc + self.n_pathseg as usize * PATHSEG_SIZE; + let bbox_alloc = alloc; + let n_path = self.n_path as usize; + alloc += bbox_alloc + n_path * BBOX_SIZE; + let drawmonoid_alloc = alloc; + alloc += n_drawobj_padded * DRAWMONOID_SIZE; + let anno_alloc = alloc; + alloc += n_drawobj * ANNOTATED_SIZE; + + let config = Config { + n_elements: n_drawobj as u32, + n_pathseg: self.n_pathseg, + pathseg_alloc: pathseg_alloc as u32, + anno_alloc: anno_alloc as u32, + trans_alloc: trans_alloc as u32, + bbox_alloc: bbox_alloc as u32, + drawmonoid_alloc: drawmonoid_alloc as u32, + n_trans: n_trans as u32, + n_path: self.n_path, + trans_offset: trans_offset as u32, + linewidth_offset: linewidth_offset as u32, + pathtag_offset: pathtag_offset as u32, + pathseg_offset: pathseg_offset as u32, + ..Default::default() + }; + (config, alloc) + } + + pub fn write_scene(&self, buf: &mut BufWrite) { + buf.extend_slice(&self.drawobj_stream); + let n_drawobj = self.drawobj_stream.len() / DRAWOBJ_SIZE; + buf.fill_zero(padding(n_drawobj, DRAWOBJ_PART_SIZE) * DRAWOBJ_SIZE); + buf.extend_slice(&self.transform_stream); + let n_trans = self.transform_stream.len(); + buf.fill_zero(padding(n_trans, TRANSFORM_PART_SIZE) * TRANSFORM_SIZE); + buf.extend_slice(&self.linewidth_stream); + buf.extend_slice(&self.tag_stream); + let n_pathtag = self.tag_stream.len(); + buf.fill_zero(padding(n_pathtag, PATHSEG_PART_SIZE)); + buf.extend_slice(&self.pathseg_stream); + } + + /// The number of elements in the draw object stream. + pub(crate) fn n_drawobj(&self) -> usize { + self.drawobj_stream.len() / DRAWOBJ_SIZE + } + + /// The number of paths. + pub(crate) fn n_path(&self) -> u32 { + self.n_path + } + + /// The number of path segments. + pub(crate) fn n_pathseg(&self) -> u32 { + self.n_pathseg + } + + pub(crate) fn n_transform(&self) -> usize { + self.transform_stream.len() + } +} + +fn align_up(x: usize, align: usize) -> usize { + debug_assert!(align.is_power_of_two()); + (x + align - 1) & !(align - 1) +} + +fn padding(x: usize, align: usize) -> usize { + x.wrapping_neg() & (align - 1) +} diff --git a/piet-gpu/src/lib.rs b/piet-gpu/src/lib.rs index 2b45e7c..25627f6 100644 --- a/piet-gpu/src/lib.rs +++ b/piet-gpu/src/lib.rs @@ -1,3 +1,4 @@ +mod encoder; mod gradient; mod pico_svg; mod render_ctx; @@ -12,16 +13,15 @@ pub use render_ctx::PietGpuRenderContext; use piet::kurbo::Vec2; use piet::{ImageFormat, RenderContext}; -use piet_gpu_types::encoder::Encode; - use piet_gpu_hal::{ BindType, Buffer, BufferUsage, CmdBuf, DescriptorSet, Error, Image, ImageLayout, Pipeline, QueryPool, Session, ShaderCode, }; use pico_svg::PicoSvg; +use stages::{ElementBinding, ElementCode}; -use crate::stages::Config; +use crate::stages::{Config, ElementStage}; const TILE_W: usize = 16; const TILE_H: usize = 16; @@ -70,8 +70,10 @@ pub struct Renderer { // Device config buf config_buf: Buffer, - el_pipeline: Pipeline, - el_ds: Vec, + // New element pipeline + element_code: ElementCode, + element_stage: ElementStage, + element_bindings: Vec, tile_pipeline: Pipeline, tile_ds: DescriptorSet, @@ -91,7 +93,8 @@ pub struct Renderer { k4_pipeline: Pipeline, k4_ds: DescriptorSet, - n_elements: usize, + n_transform: usize, + n_drawobj: usize, n_paths: usize, n_pathseg: usize, @@ -120,7 +123,7 @@ impl Renderer { // TODO: separate staging buffer (if needed) let scene_bufs = (0..n_bufs) .map(|_| session.create_buffer(8 * 1024 * 1024, host_upload).unwrap()) - .collect(); + .collect::>(); let state_buf = session.create_buffer(1 * 1024 * 1024, dev)?; let image_dev = session.create_image2d(width as u32, height as u32)?; @@ -142,23 +145,21 @@ impl Renderer { .collect(); let memory_buf_dev = session.create_buffer(128 * 1024 * 1024, dev)?; - let el_code = ShaderCode::Spv(include_bytes!("../shader/elements.spv")); - let el_pipeline = session.create_compute_pipeline( - el_code, - &[ - BindType::Buffer, - BindType::Buffer, - BindType::Buffer, - BindType::Buffer, - ], - )?; - let mut el_ds = Vec::with_capacity(n_bufs); - for scene_buf in &scene_bufs { - el_ds.push(session.create_simple_descriptor_set( - &el_pipeline, - &[&memory_buf_dev, &config_buf, scene_buf, &state_buf], - )?); - } + let element_code = ElementCode::new(session); + let element_stage = ElementStage::new(session, &element_code); + let element_bindings = scene_bufs + .iter() + .zip(&config_bufs) + .map(|(scene_buf, config_buf)| { + element_stage.bind( + session, + &element_code, + config_buf, + scene_buf, + &memory_buf_dev, + ) + }) + .collect(); let tile_alloc_code = ShaderCode::Spv(include_bytes!("../shader/tile_alloc.spv")); let tile_pipeline = session @@ -237,8 +238,9 @@ impl Renderer { config_buf, config_bufs, image_dev, - el_pipeline, - el_ds, + element_code, + element_stage, + element_bindings, tile_pipeline, tile_ds, path_pipeline, @@ -251,7 +253,8 @@ impl Renderer { coarse_ds, k4_pipeline, k4_ds, - n_elements: 0, + n_transform: 0, + n_drawobj: 0, n_paths: 0, n_pathseg: 0, _bg_image: bg_image, @@ -270,55 +273,38 @@ impl Renderer { render_ctx: &mut PietGpuRenderContext, buf_ix: usize, ) -> Result<(), Error> { - let n_paths = render_ctx.path_count(); - let n_pathseg = render_ctx.pathseg_count(); - let n_trans = render_ctx.trans_count(); - self.n_paths = n_paths; - self.n_pathseg = n_pathseg; + let (mut config, mut alloc) = render_ctx.stage_config(); + let n_drawobj = render_ctx.n_drawobj(); + // TODO: be more consistent in size types + let n_path = render_ctx.n_path() as usize; + self.n_paths = n_path; + self.n_transform = render_ctx.n_transform(); + self.n_drawobj = render_ctx.n_drawobj(); + self.n_pathseg = render_ctx.n_pathseg() as usize; // These constants depend on encoding and may need to be updated. // Perhaps we can plumb these from piet-gpu-derive? const PATH_SIZE: usize = 12; const BIN_SIZE: usize = 8; - const PATHSEG_SIZE: usize = 52; - const ANNO_SIZE: usize = 40; - const TRANS_SIZE: usize = 24; let width_in_tiles = self.width / TILE_W; let height_in_tiles = self.height / TILE_H; - let mut alloc = 0; let tile_base = alloc; - alloc += ((n_paths + 3) & !3) * PATH_SIZE; + alloc += ((n_path + 3) & !3) * PATH_SIZE; let bin_base = alloc; - alloc += ((n_paths + 255) & !255) * BIN_SIZE; + alloc += ((n_drawobj + 255) & !255) * BIN_SIZE; let ptcl_base = alloc; alloc += width_in_tiles * height_in_tiles * PTCL_INITIAL_ALLOC; - let pathseg_base = alloc; - alloc += (n_pathseg * PATHSEG_SIZE + 3) & !3; - let anno_base = alloc; - alloc += (n_paths * ANNO_SIZE + 3) & !3; - let trans_base = alloc; - alloc += (n_trans * TRANS_SIZE + 3) & !3; - let config = Config { - n_elements: n_paths as u32, - n_pathseg: n_pathseg as u32, - width_in_tiles: width_in_tiles as u32, - height_in_tiles: height_in_tiles as u32, - tile_alloc: tile_base as u32, - bin_alloc: bin_base as u32, - ptcl_alloc: ptcl_base as u32, - pathseg_alloc: pathseg_base as u32, - anno_alloc: anno_base as u32, - trans_alloc: trans_base as u32, - n_trans: n_trans as u32, - // We'll fill the rest of the fields in when we hook up the new element pipeline. - ..Default::default() - }; + config.width_in_tiles = width_in_tiles as u32; + config.height_in_tiles = height_in_tiles as u32; + config.tile_alloc = tile_base as u32; + config.bin_alloc = bin_base as u32; + config.ptcl_alloc = ptcl_base as u32; unsafe { - let scene = render_ctx.get_scene_buf(); - self.n_elements = scene.len() / piet_gpu_types::scene::Element::fixed_size(); // TODO: reallocate scene buffer if size is inadequate - assert!(self.scene_bufs[buf_ix].size() as usize >= scene.len()); - self.scene_bufs[buf_ix].write(scene)?; + { + let mut mapped_scene = self.scene_bufs[buf_ix].map_write(..)?; + render_ctx.write_scene(&mut mapped_scene); + } self.config_bufs[buf_ix].write(&[config])?; self.memory_buf_host[buf_ix].write(&[alloc as u32, 0 /* Overflow flag */])?; @@ -355,11 +341,14 @@ impl Renderer { cmd_buf.image_barrier(&self.gradients, ImageLayout::BlitDst, ImageLayout::General); cmd_buf.reset_query_pool(&query_pool); cmd_buf.write_timestamp(&query_pool, 0); - cmd_buf.dispatch( - &self.el_pipeline, - &self.el_ds[buf_ix], - (((self.n_elements + 127) / 128) as u32, 1, 1), - (128, 1, 1), + self.element_stage.record( + cmd_buf, + &self.element_code, + &self.element_bindings[buf_ix], + self.n_transform as u64, + self.n_paths as u32, + self.n_pathseg as u32, + self.n_drawobj as u64, ); cmd_buf.write_timestamp(&query_pool, 1); cmd_buf.memory_barrier(); diff --git a/piet-gpu/src/render_ctx.rs b/piet-gpu/src/render_ctx.rs index f050c76..5b10fec 100644 --- a/piet-gpu/src/render_ctx.rs +++ b/piet-gpu/src/render_ctx.rs @@ -1,5 +1,6 @@ use std::borrow::Cow; +use crate::stages::Config; use crate::MAX_BLEND_STACK; use piet::kurbo::{Affine, Insets, PathEl, Point, Rect, Shape}; use piet::{ @@ -7,11 +8,9 @@ use piet::{ StrokeStyle, }; +use piet_gpu_hal::BufWrite; use piet_gpu_types::encoder::{Encode, Encoder}; -use piet_gpu_types::scene::{ - Clip, CubicSeg, Element, FillColor, FillLinGradient, LineSeg, QuadSeg, SetFillMode, - SetLineWidth, Transform, -}; +use piet_gpu_types::scene::{Clip, Element, FillColor, FillLinGradient, SetFillMode, Transform}; use crate::gradient::{LinearGradient, RampCache}; use crate::text::Font; @@ -40,6 +39,10 @@ pub struct PietGpuRenderContext { clip_stack: Vec, ramp_cache: RampCache, + + // Fields for new element processing pipeline below + // TODO: delete old encoder, rename + new_encoder: crate::encoder::Encoder, } #[derive(Clone)] @@ -81,7 +84,7 @@ impl PietGpuRenderContext { let elements = Vec::new(); let font = Font::new(); let inner_text = PietGpuText::new(font); - let stroke_width = 0.0; + let stroke_width = -1.0; PietGpuRenderContext { encoder, elements, @@ -95,9 +98,40 @@ impl PietGpuRenderContext { state_stack: Vec::new(), clip_stack: Vec::new(), ramp_cache: RampCache::default(), + new_encoder: crate::encoder::Encoder::new(), } } + pub fn stage_config(&self) -> (Config, usize) { + self.new_encoder.stage_config() + } + + /// Number of draw objects. + /// + /// This is for the new element processing pipeline. It's not necessarily the + /// same as the number of paths (as in the old pipeline), but it might take a + /// while to sort that out. + pub fn n_drawobj(&self) -> usize { + self.new_encoder.n_drawobj() + } + + /// Number of paths. + pub fn n_path(&self) -> u32 { + self.new_encoder.n_path() + } + + pub fn n_pathseg(&self) -> u32 { + self.new_encoder.n_pathseg() + } + + pub fn n_transform(&self) -> usize { + self.new_encoder.n_transform() + } + + pub fn write_scene(&self, buf: &mut BufWrite) { + self.new_encoder.write_scene(buf); + } + pub fn get_scene_buf(&mut self) -> &[u8] { const ALIGN: usize = 128; let padded_size = (self.elements.len() + (ALIGN - 1)) & ALIGN.wrapping_neg(); @@ -171,13 +205,7 @@ impl RenderContext for PietGpuRenderContext { fn clear(&mut self, _color: Color) {} fn stroke(&mut self, shape: impl Shape, brush: &impl IntoBrush, width: f64) { - let width_f32 = width as f32; - if self.stroke_width != width_f32 { - self.elements - .push(Element::SetLineWidth(SetLineWidth { width: width_f32 })); - self.stroke_width = width_f32; - } - self.set_fill_mode(FillMode::Stroke); + self.encode_linewidth(width.abs() as f32); let brush = brush.make_brush(self, || shape.bounding_box()).into_owned(); // Note: the bbox contribution of stroke becomes more complicated with miter joins. self.accumulate_bbox(|| shape.bounding_box() + Insets::uniform(width * 0.5)); @@ -201,7 +229,7 @@ impl RenderContext for PietGpuRenderContext { // Perhaps that should be added to kurbo. self.accumulate_bbox(|| shape.bounding_box()); let path = shape.path_elements(TOLERANCE); - self.set_fill_mode(FillMode::Nonzero); + self.encode_linewidth(-1.0); self.encode_path(path, true); self.encode_brush(&brush); } @@ -318,21 +346,6 @@ impl RenderContext for PietGpuRenderContext { } impl PietGpuRenderContext { - fn encode_line_seg(&mut self, seg: LineSeg) { - self.elements.push(Element::Line(seg)); - self.pathseg_count += 1; - } - - fn encode_quad_seg(&mut self, seg: QuadSeg) { - self.elements.push(Element::Quad(seg)); - self.pathseg_count += 1; - } - - fn encode_cubic_seg(&mut self, seg: CubicSeg) { - self.elements.push(Element::Cubic(seg)); - self.pathseg_count += 1; - } - fn encode_path(&mut self, path: impl Iterator, is_fill: bool) { if is_fill { self.encode_path_inner( @@ -352,99 +365,34 @@ impl PietGpuRenderContext { } fn encode_path_inner(&mut self, path: impl Iterator) { - let flatten = false; - if flatten { - let mut start_pt = None; - let mut last_pt = None; - piet::kurbo::flatten(path, TOLERANCE, |el| { - match el { - PathEl::MoveTo(p) => { - let scene_pt = to_f32_2(p); - start_pt = Some(scene_pt); - last_pt = Some(scene_pt); - } - PathEl::LineTo(p) => { - let scene_pt = to_f32_2(p); - let seg = LineSeg { - p0: last_pt.unwrap(), - p1: scene_pt, - }; - self.encode_line_seg(seg); - last_pt = Some(scene_pt); - } - PathEl::ClosePath => { - if let (Some(start), Some(last)) = (start_pt.take(), last_pt.take()) { - if last != start { - let seg = LineSeg { - p0: last, - p1: start, - }; - self.encode_line_seg(seg); - } - } - } - _ => (), + let mut pe = self.new_encoder.path_encoder(); + for el in path { + match el { + PathEl::MoveTo(p) => { + let p = to_f32_2(p); + pe.move_to(p[0], p[1]); } - //println!("{:?}", el); - }); - } else { - let mut start_pt = None; - let mut last_pt = None; - for el in path { - match el { - PathEl::MoveTo(p) => { - let scene_pt = to_f32_2(p); - start_pt = Some(scene_pt); - last_pt = Some(scene_pt); - } - PathEl::LineTo(p) => { - let scene_pt = to_f32_2(p); - let seg = LineSeg { - p0: last_pt.unwrap(), - p1: scene_pt, - }; - self.encode_line_seg(seg); - last_pt = Some(scene_pt); - } - PathEl::QuadTo(p1, p2) => { - let scene_p1 = to_f32_2(p1); - let scene_p2 = to_f32_2(p2); - let seg = QuadSeg { - p0: last_pt.unwrap(), - p1: scene_p1, - p2: scene_p2, - }; - self.encode_quad_seg(seg); - last_pt = Some(scene_p2); - } - PathEl::CurveTo(p1, p2, p3) => { - let scene_p1 = to_f32_2(p1); - let scene_p2 = to_f32_2(p2); - let scene_p3 = to_f32_2(p3); - let seg = CubicSeg { - p0: last_pt.unwrap(), - p1: scene_p1, - p2: scene_p2, - p3: scene_p3, - }; - self.encode_cubic_seg(seg); - last_pt = Some(scene_p3); - } - PathEl::ClosePath => { - if let (Some(start), Some(last)) = (start_pt.take(), last_pt.take()) { - if last != start { - let seg = LineSeg { - p0: last, - p1: start, - }; - self.encode_line_seg(seg); - } - } - } + PathEl::LineTo(p) => { + let p = to_f32_2(p); + pe.line_to(p[0], p[1]); } - //println!("{:?}", el); + PathEl::QuadTo(p1, p2) => { + let p1 = to_f32_2(p1); + let p2 = to_f32_2(p2); + pe.quad_to(p1[0], p1[1], p2[0], p2[1]); + } + PathEl::CurveTo(p1, p2, p3) => { + let p1 = to_f32_2(p1); + let p2 = to_f32_2(p2); + let p3 = to_f32_2(p3); + pe.cubic_to(p1[0], p1[1], p2[0], p2[1], p3[0], p3[1]); + } + PathEl::ClosePath => pe.close_path(), } } + pe.path(); + let n_pathseg = pe.n_pathseg(); + self.new_encoder.finish_path(n_pathseg); } fn pop_clip(&mut self) { @@ -511,14 +459,17 @@ impl PietGpuRenderContext { self.trans_count += 1; } + fn encode_linewidth(&mut self, linewidth: f32) { + if self.stroke_width != linewidth { + self.new_encoder.linewidth(linewidth); + self.stroke_width = linewidth; + } + } + fn encode_brush(&mut self, brush: &PietGpuBrush) { match brush { PietGpuBrush::Solid(rgba_color) => { - let fill = FillColor { - rgba_color: *rgba_color, - }; - self.elements.push(Element::FillColor(fill)); - self.path_count += 1; + self.new_encoder.fill_color(*rgba_color); } PietGpuBrush::LinGradient(lin) => { let fill_lin = FillLinGradient { diff --git a/piet-gpu/src/stages.rs b/piet-gpu/src/stages.rs index f4a086c..1683cac 100644 --- a/piet-gpu/src/stages.rs +++ b/piet-gpu/src/stages.rs @@ -24,13 +24,14 @@ use bytemuck::{Pod, Zeroable}; pub use draw::{DrawBinding, DrawCode, DrawMonoid, DrawStage}; pub use path::{PathBinding, PathCode, PathEncoder, PathStage}; +use piet_gpu_hal::{Buffer, CmdBuf, Session}; pub use transform::{Transform, TransformBinding, TransformCode, TransformStage}; /// The configuration block passed to piet-gpu shaders. /// /// Note: this should be kept in sync with the version in setup.h. #[repr(C)] -#[derive(Clone, Copy, Default, Zeroable, Pod)] +#[derive(Clone, Copy, Default, Debug, Zeroable, Pod)] pub struct Config { pub n_elements: u32, // paths pub n_pathseg: u32, @@ -45,8 +46,111 @@ pub struct Config { pub bbox_alloc: u32, pub drawmonoid_alloc: u32, pub n_trans: u32, + pub n_path: u32, pub trans_offset: u32, - pub pathtag_offset: u32, pub linewidth_offset: u32, + pub pathtag_offset: u32, pub pathseg_offset: u32, } + +// The "element" stage combines a number of stages for parts of the pipeline. + +pub struct ElementCode { + transform_code: TransformCode, + path_code: PathCode, + draw_code: DrawCode, +} + +pub struct ElementStage { + transform_stage: TransformStage, + path_stage: PathStage, + draw_stage: DrawStage, +} + +pub struct ElementBinding { + transform_binding: TransformBinding, + path_binding: PathBinding, + draw_binding: DrawBinding, +} + +impl ElementCode { + pub unsafe fn new(session: &Session) -> ElementCode { + ElementCode { + transform_code: TransformCode::new(session), + path_code: PathCode::new(session), + draw_code: DrawCode::new(session), + } + } +} + +impl ElementStage { + pub unsafe fn new(session: &Session, code: &ElementCode) -> ElementStage { + ElementStage { + transform_stage: TransformStage::new(session, &code.transform_code), + path_stage: PathStage::new(session, &code.path_code), + draw_stage: DrawStage::new(session, &code.draw_code), + } + } + + pub unsafe fn bind( + &self, + session: &Session, + code: &ElementCode, + config_buf: &Buffer, + scene_buf: &Buffer, + memory_buf: &Buffer, + ) -> ElementBinding { + ElementBinding { + transform_binding: self.transform_stage.bind( + session, + &code.transform_code, + config_buf, + scene_buf, + memory_buf, + ), + path_binding: self.path_stage.bind( + session, + &code.path_code, + config_buf, + scene_buf, + memory_buf, + ), + draw_binding: self.draw_stage.bind( + session, + &code.draw_code, + config_buf, + scene_buf, + memory_buf, + ), + } + } + + pub unsafe fn record( + &self, + cmd_buf: &mut CmdBuf, + code: &ElementCode, + binding: &ElementBinding, + n_transform: u64, + n_paths: u32, + n_tags: u32, + n_drawobj: u64, + ) { + self.transform_stage.record( + cmd_buf, + &code.transform_code, + &binding.transform_binding, + n_transform, + ); + // No memory barrier needed here; path has at least one before pathseg + self.path_stage.record( + cmd_buf, + &code.path_code, + &binding.path_binding, + n_paths, + n_tags, + ); + // No memory barrier needed here; draw has at least one before draw_leaf + self.draw_stage + .record(cmd_buf, &code.draw_code, &binding.draw_binding, n_drawobj); + } +} diff --git a/piet-gpu/src/stages/draw.rs b/piet-gpu/src/stages/draw.rs index d50c6cb..da773cf 100644 --- a/piet-gpu/src/stages/draw.rs +++ b/piet-gpu/src/stages/draw.rs @@ -151,8 +151,8 @@ impl DrawStage { (1, 1, 1), (DRAW_WG as u32, 1, 1), ); - cmd_buf.memory_barrier(); } + cmd_buf.memory_barrier(); cmd_buf.dispatch( &code.leaf_pipeline, &binding.leaf_ds, diff --git a/piet-gpu/src/stages/path.rs b/piet-gpu/src/stages/path.rs index e233c65..c9d2c60 100644 --- a/piet-gpu/src/stages/path.rs +++ b/piet-gpu/src/stages/path.rs @@ -258,11 +258,11 @@ impl<'a> PathEncoder<'a> { self.n_pathseg += 1; } - pub fn quad_to(&mut self, x0: f32, y0: f32, x1: f32, y1: f32) { + pub fn quad_to(&mut self, x1: f32, y1: f32, x2: f32, y2: f32) { if self.state == State::Start { return; } - let buf = [x0, y0, x1, y1]; + let buf = [x1, y1, x2, y2]; let bytes = bytemuck::bytes_of(&buf); self.pathseg_stream.extend_from_slice(bytes); self.tag_stream.push(10); @@ -270,11 +270,11 @@ impl<'a> PathEncoder<'a> { self.n_pathseg += 1; } - pub fn cubic_to(&mut self, x0: f32, y0: f32, x1: f32, y1: f32, x2: f32, y2: f32) { + pub fn cubic_to(&mut self, x1: f32, y1: f32, x2: f32, y2: f32, x3: f32, y3: f32) { if self.state == State::Start { return; } - let buf = [x0, y0, x1, y1, x2, y2]; + let buf = [x1, y1, x2, y2, x3, y3]; let bytes = bytemuck::bytes_of(&buf); self.pathseg_stream.extend_from_slice(bytes); self.tag_stream.push(11); @@ -288,6 +288,7 @@ impl<'a> PathEncoder<'a> { State::MoveTo => { let new_len = self.pathseg_stream.len() - 8; self.pathseg_stream.truncate(new_len); + self.state = State::Start; return; } State::NonemptySubpath => (), @@ -333,7 +334,9 @@ impl<'a> PathEncoder<'a> { /// /// This is the number of path segments that will be written by the /// path stage; use this for allocating the output buffer. - pub fn n_pathseg(&self) -> u32 { + /// + /// Also note: it takes `self` for lifetime reasons. + pub fn n_pathseg(self) -> u32 { self.n_pathseg } } diff --git a/piet-gpu/src/stages/transform.rs b/piet-gpu/src/stages/transform.rs index 4fb5e9f..4383c14 100644 --- a/piet-gpu/src/stages/transform.rs +++ b/piet-gpu/src/stages/transform.rs @@ -167,6 +167,11 @@ impl TransformStage { } impl Transform { + pub const IDENTITY: Transform = Transform { + mat: [1.0, 0.0, 0.0, 1.0], + translate: [0.0, 0.0], + }; + pub fn from_kurbo(a: Affine) -> Transform { let c = a.as_coeffs(); Transform { diff --git a/tests/src/draw.rs b/tests/src/draw.rs index ca19312..2447444 100644 --- a/tests/src/draw.rs +++ b/tests/src/draw.rs @@ -24,6 +24,7 @@ use crate::{Config, Runner, TestResult}; use piet_gpu::stages::{self, DrawCode, DrawMonoid, DrawStage}; const ELEMENT_SIZE: usize = 36; +const ANNOTATED_SIZE: usize = 40; const ELEMENT_FILLCOLOR: u32 = 4; const ELEMENT_FILLLINGRADIENT: u32 = 5; @@ -99,16 +100,18 @@ impl DrawTestData { // Layout of memory let drawmonoid_alloc = 0; + let anno_alloc = drawmonoid_alloc + 8 * n_tags; let stage_config = stages::Config { n_elements: n_tags as u32, - drawmonoid_alloc, + anno_alloc: anno_alloc as u32, + drawmonoid_alloc: drawmonoid_alloc as u32, ..Default::default() }; stage_config } fn memory_size(&self) -> u64 { - 8 + self.tags.len() as u64 * 8 + (8 + self.tags.len() * (8 + ANNOTATED_SIZE)) as u64 } fn fill_scene(&self, buf: &mut BufWrite) { diff --git a/tests/src/path.rs b/tests/src/path.rs index 948bd6f..7c5388f 100644 --- a/tests/src/path.rs +++ b/tests/src/path.rs @@ -19,7 +19,7 @@ use crate::{Config, Runner, TestResult}; use bytemuck::{Pod, Zeroable}; -use piet_gpu::stages::{self, PathCode, PathEncoder, PathStage}; +use piet_gpu::stages::{self, PathCode, PathEncoder, PathStage, Transform}; use piet_gpu_hal::{BufWrite, BufferUsage}; use rand::{prelude::ThreadRng, Rng}; @@ -55,6 +55,8 @@ struct Bbox { top: u32, right: u32, bottom: u32, + linewidth: f32, + trans_ix: u32, } pub unsafe fn path_test(runner: &mut Runner, config: &Config) -> TestResult { @@ -206,11 +208,11 @@ impl PathData { let pathseg_alloc = trans_alloc + n_trans * 24; let bbox_alloc = pathseg_alloc + self.n_pathseg * PATHSEG_SIZE; let stage_config = stages::Config { - n_elements: self.n_path, pathseg_alloc, trans_alloc, bbox_alloc, n_trans, + n_path: self.n_path, pathtag_offset, linewidth_offset, pathseg_offset, @@ -236,7 +238,7 @@ impl PathData { fn memory_full_size(&self) -> u64 { let mut size = self.memory_init_size(); size += (self.n_pathseg * PATHSEG_SIZE) as u64; - size += (self.n_path * 16) as u64; + size += (self.n_path * 24) as u64; size } @@ -246,7 +248,7 @@ impl PathData { let mem_error = 0u32; let mem_init = [mem_offset, mem_error]; buf.push(mem_init); - let trans = [1.0f32, 0.0, 0.0, 1.0, 0.0, 0.0]; + let trans = Transform::IDENTITY; buf.push(trans); } @@ -274,17 +276,15 @@ impl PathData { } let begin_bbox = 32 + PATHSEG_SIZE * self.n_pathseg; for i in 0..self.n_path { - let offset = (begin_bbox + 16 * i) as usize; - let actual = bytemuck::from_bytes::(&memory[offset..offset + 16]); + let offset = (begin_bbox + 24 * i) as usize; + let actual = bytemuck::from_bytes::(&memory[offset..offset + 24]); let expected_f32 = self.bbox[i as usize]; - let expected = Bbox { - left: round_down(expected_f32.0), - top: round_down(expected_f32.1), - right: round_up(expected_f32.2), - bottom: round_up(expected_f32.3), - }; - if expected != *actual { - println!("{}: {:?} {:?}", i, actual, expected); + if round_down(expected_f32.0) != actual.left + || round_down(expected_f32.1) != actual.top + || round_up(expected_f32.2) != actual.right + || round_up(expected_f32.3) != actual.bottom + { + println!("{}: {:?} {:?}", i, actual, expected_f32); return Some(format!("bbox mismatch at {}", i)); } }