From 076e6d600d828f7b7902b2603d22178faf25c3c9 Mon Sep 17 00:00:00 2001 From: Raph Levien Date: Wed, 20 May 2020 07:38:52 -0700 Subject: [PATCH] Progress on wiring up fills Write the right_edge to the binning output. More work on encoding the fill/stroke distinction and plumbing that through the pipeline. This is a bit unsatisfying because of the code duplication; having an extra fill/stroke bool might be better, but I want to avoid making the structs bigger (this could be solved by better packing in the struct encoding). Fills are plumbed through to the last stage. Backdrop is WIP. --- piet-gpu-types/src/annotated.rs | 13 +++-- piet-gpu-types/src/bins.rs | 3 ++ piet-gpu-types/src/scene.rs | 11 ++++- piet-gpu/shader/annotated.h | 81 +++++++++++++++++++++++++------- piet-gpu/shader/binning.comp | 23 ++++----- piet-gpu/shader/binning.spv | Bin 21800 -> 22016 bytes piet-gpu/shader/bins.h | 6 ++- piet-gpu/shader/coarse.comp | 34 ++++++++++---- piet-gpu/shader/coarse.spv | Bin 30280 -> 33272 bytes piet-gpu/shader/elements.comp | 24 +++++++--- piet-gpu/shader/elements.spv | Bin 45068 -> 45312 bytes piet-gpu/shader/scene.h | 21 +++++---- piet-gpu/src/pico_svg.rs | 4 +- piet-gpu/src/render_ctx.rs | 22 ++++++--- 14 files changed, 175 insertions(+), 67 deletions(-) diff --git a/piet-gpu-types/src/annotated.rs b/piet-gpu-types/src/annotated.rs index 247ab12..f7a6ad6 100644 --- a/piet-gpu-types/src/annotated.rs +++ b/piet-gpu-types/src/annotated.rs @@ -3,7 +3,14 @@ use piet_gpu_derive::piet_gpu; piet_gpu! { #[gpu_write] mod annotated { - struct AnnoLineSeg { + struct AnnoFillLineSeg { + p0: [f32; 2], + p1: [f32; 2], + // A note: the layout of this struct is shared with + // AnnoStrokeLineSeg. In that case, we actually write + // [0.0, 0.0] as the stroke field, to minimize divergence. + } + struct AnnoStrokeLineSeg { p0: [f32; 2], p1: [f32; 2], // halfwidth in both x and y for binning @@ -35,8 +42,8 @@ piet_gpu! { } enum Annotated { Nop, - // The segments need a flag to indicate fill/stroke - Line(AnnoLineSeg), + FillLine(AnnoFillLineSeg), + StrokeLine(AnnoStrokeLineSeg), Quad(AnnoQuadSeg), Cubic(AnnoCubicSeg), Stroke(AnnoStroke), diff --git a/piet-gpu-types/src/bins.rs b/piet-gpu-types/src/bins.rs index 88f16f1..1ac2413 100644 --- a/piet-gpu-types/src/bins.rs +++ b/piet-gpu-types/src/bins.rs @@ -7,6 +7,9 @@ piet_gpu! { mod bins { struct BinInstance { element_ix: u32, + // Right edge of the bounding box of the associated fill + // element; used in backdrop computation. + right_edge: f32, } struct BinChunk { diff --git a/piet-gpu-types/src/scene.rs b/piet-gpu-types/src/scene.rs index 7451c9c..5792c94 100644 --- a/piet-gpu-types/src/scene.rs +++ b/piet-gpu-types/src/scene.rs @@ -85,8 +85,15 @@ piet_gpu! { } enum Element { Nop, - // The segments need a flag to indicate fill/stroke - Line(LineSeg), + // Another approach to encoding would be to use a single + // variant but have a bool for fill/stroke. This could be + // packed into the tag, so the on-the-wire representation + // would be very similar to what's here. + StrokeLine(LineSeg), + FillLine(LineSeg), + + // Note: we'll need to handle the stroke/fill distinction + // for these as well, when we do flattening on the GPU. Quad(QuadSeg), Cubic(CubicSeg), Stroke(Stroke), diff --git a/piet-gpu/shader/annotated.h b/piet-gpu/shader/annotated.h index a3fc464..9812264 100644 --- a/piet-gpu/shader/annotated.h +++ b/piet-gpu/shader/annotated.h @@ -1,6 +1,10 @@ // Code auto-generated by piet-gpu-derive -struct AnnoLineSegRef { +struct AnnoFillLineSegRef { + uint offset; +}; + +struct AnnoStrokeLineSegRef { uint offset; }; @@ -24,16 +28,27 @@ struct AnnotatedRef { uint offset; }; -struct AnnoLineSeg { +struct AnnoFillLineSeg { + vec2 p0; + vec2 p1; +}; + +#define AnnoFillLineSeg_size 16 + +AnnoFillLineSegRef AnnoFillLineSeg_index(AnnoFillLineSegRef ref, uint index) { + return AnnoFillLineSegRef(ref.offset + index * AnnoFillLineSeg_size); +} + +struct AnnoStrokeLineSeg { vec2 p0; vec2 p1; vec2 stroke; }; -#define AnnoLineSeg_size 24 +#define AnnoStrokeLineSeg_size 24 -AnnoLineSegRef AnnoLineSeg_index(AnnoLineSegRef ref, uint index) { - return AnnoLineSegRef(ref.offset + index * AnnoLineSeg_size); +AnnoStrokeLineSegRef AnnoStrokeLineSeg_index(AnnoStrokeLineSegRef ref, uint index) { + return AnnoStrokeLineSegRef(ref.offset + index * AnnoStrokeLineSeg_size); } struct AnnoQuadSeg { @@ -87,18 +102,39 @@ AnnoStrokeRef AnnoStroke_index(AnnoStrokeRef ref, uint index) { } #define Annotated_Nop 0 -#define Annotated_Line 1 -#define Annotated_Quad 2 -#define Annotated_Cubic 3 -#define Annotated_Stroke 4 -#define Annotated_Fill 5 +#define Annotated_FillLine 1 +#define Annotated_StrokeLine 2 +#define Annotated_Quad 3 +#define Annotated_Cubic 4 +#define Annotated_Stroke 5 +#define Annotated_Fill 6 #define Annotated_size 44 AnnotatedRef Annotated_index(AnnotatedRef ref, uint index) { return AnnotatedRef(ref.offset + index * Annotated_size); } -AnnoLineSeg AnnoLineSeg_read(AnnoLineSegRef ref) { +AnnoFillLineSeg AnnoFillLineSeg_read(AnnoFillLineSegRef ref) { + uint ix = ref.offset >> 2; + uint raw0 = annotated[ix + 0]; + uint raw1 = annotated[ix + 1]; + uint raw2 = annotated[ix + 2]; + uint raw3 = annotated[ix + 3]; + AnnoFillLineSeg s; + s.p0 = vec2(uintBitsToFloat(raw0), uintBitsToFloat(raw1)); + s.p1 = vec2(uintBitsToFloat(raw2), uintBitsToFloat(raw3)); + return s; +} + +void AnnoFillLineSeg_write(AnnoFillLineSegRef ref, AnnoFillLineSeg s) { + uint ix = ref.offset >> 2; + annotated[ix + 0] = floatBitsToUint(s.p0.x); + annotated[ix + 1] = floatBitsToUint(s.p0.y); + annotated[ix + 2] = floatBitsToUint(s.p1.x); + annotated[ix + 3] = floatBitsToUint(s.p1.y); +} + +AnnoStrokeLineSeg AnnoStrokeLineSeg_read(AnnoStrokeLineSegRef ref) { uint ix = ref.offset >> 2; uint raw0 = annotated[ix + 0]; uint raw1 = annotated[ix + 1]; @@ -106,14 +142,14 @@ AnnoLineSeg AnnoLineSeg_read(AnnoLineSegRef ref) { uint raw3 = annotated[ix + 3]; uint raw4 = annotated[ix + 4]; uint raw5 = annotated[ix + 5]; - AnnoLineSeg s; + AnnoStrokeLineSeg s; s.p0 = vec2(uintBitsToFloat(raw0), uintBitsToFloat(raw1)); s.p1 = vec2(uintBitsToFloat(raw2), uintBitsToFloat(raw3)); s.stroke = vec2(uintBitsToFloat(raw4), uintBitsToFloat(raw5)); return s; } -void AnnoLineSeg_write(AnnoLineSegRef ref, AnnoLineSeg s) { +void AnnoStrokeLineSeg_write(AnnoStrokeLineSegRef ref, AnnoStrokeLineSeg s) { uint ix = ref.offset >> 2; annotated[ix + 0] = floatBitsToUint(s.p0.x); annotated[ix + 1] = floatBitsToUint(s.p0.y); @@ -239,8 +275,12 @@ uint Annotated_tag(AnnotatedRef ref) { return annotated[ref.offset >> 2]; } -AnnoLineSeg Annotated_Line_read(AnnotatedRef ref) { - return AnnoLineSeg_read(AnnoLineSegRef(ref.offset + 4)); +AnnoFillLineSeg Annotated_FillLine_read(AnnotatedRef ref) { + return AnnoFillLineSeg_read(AnnoFillLineSegRef(ref.offset + 4)); +} + +AnnoStrokeLineSeg Annotated_StrokeLine_read(AnnotatedRef ref) { + return AnnoStrokeLineSeg_read(AnnoStrokeLineSegRef(ref.offset + 4)); } AnnoQuadSeg Annotated_Quad_read(AnnotatedRef ref) { @@ -263,9 +303,14 @@ void Annotated_Nop_write(AnnotatedRef ref) { annotated[ref.offset >> 2] = Annotated_Nop; } -void Annotated_Line_write(AnnotatedRef ref, AnnoLineSeg s) { - annotated[ref.offset >> 2] = Annotated_Line; - AnnoLineSeg_write(AnnoLineSegRef(ref.offset + 4), s); +void Annotated_FillLine_write(AnnotatedRef ref, AnnoFillLineSeg s) { + annotated[ref.offset >> 2] = Annotated_FillLine; + AnnoFillLineSeg_write(AnnoFillLineSegRef(ref.offset + 4), s); +} + +void Annotated_StrokeLine_write(AnnotatedRef ref, AnnoStrokeLineSeg s) { + annotated[ref.offset >> 2] = Annotated_StrokeLine; + AnnoStrokeLineSeg_write(AnnoStrokeLineSegRef(ref.offset + 4), s); } void Annotated_Quad_write(AnnotatedRef ref, AnnoQuadSeg s) { diff --git a/piet-gpu/shader/binning.comp b/piet-gpu/shader/binning.comp index cba0217..60b12e0 100644 --- a/piet-gpu/shader/binning.comp +++ b/piet-gpu/shader/binning.comp @@ -84,8 +84,9 @@ void main() { int x0 = 0, y0 = 0, x1 = 0, y1 = 0; float my_right_edge = INFINITY; switch (tag) { - case Annotated_Line: - AnnoLineSeg line = Annotated_Line_read(ref); + case Annotated_FillLine: + case Annotated_StrokeLine: + AnnoStrokeLineSeg line = Annotated_StrokeLine_read(ref); x0 = int(floor((min(line.p0.x, line.p1.x) - line.stroke.x) * SX)); y0 = int(floor((min(line.p0.y, line.p1.y) - line.stroke.y) * SY)); x1 = int(ceil((max(line.p0.x, line.p1.x) + line.stroke.x) * SX)); @@ -107,7 +108,7 @@ void main() { // If the last element in this partition is a fill edge, then we need to do a // look-forward to find the right edge of its corresponding fill. That data is // recorded in aggregates computed in the element processing pass. - if (gl_LocalInvocationID.x == N_TILE - 1 && tag == Annotated_Line) { + if (gl_LocalInvocationID.x == N_TILE - 1 && tag == Annotated_FillLine) { uint aggregate_ix = (my_tile + 1) * ELEMENT_BINNING_RATIO; // This is sequential but the expectation is that the amount of // look-forward is small (performance may degrade in the case @@ -165,9 +166,9 @@ void main() { uint chunk_new_start; // Refactor to reduce code duplication? if (chunk_n > 0) { - uint next_chunk = chunk_ref.offset + BinChunk_size + chunk_n * 4; - if (next_chunk + BinChunk_size + min(24, element_count * 4) > wr_limit) { - uint alloc_amount = max(BIN_ALLOC, BinChunk_size + element_count * 4); + uint next_chunk = chunk_ref.offset + BinChunk_size + chunk_n * BinInstance_size; + if (next_chunk + BinChunk_size + min(24, element_count * BinInstance_size) > wr_limit) { + uint alloc_amount = max(BIN_ALLOC, BinChunk_size + element_count * BinInstance_size); // could try to reduce fragmentation if BIN_ALLOC is only a bit above needed next_chunk = atomicAdd(alloc, alloc_amount); wr_limit = next_chunk + alloc_amount; @@ -176,10 +177,10 @@ void main() { chunk_ref = BinChunkRef(next_chunk); } BinInstanceRef instance_ref = BinInstanceRef(chunk_ref.offset + BinChunk_size); - if (instance_ref.offset + element_count * 4 > wr_limit) { + if (instance_ref.offset + element_count * BinInstance_size > wr_limit) { chunk_end = wr_limit; - chunk_n = (wr_limit - instance_ref.offset) / 4; - uint alloc_amount = max(BIN_ALLOC, BinChunk_size + (element_count - chunk_n) * 4); + chunk_n = (wr_limit - instance_ref.offset) / BinInstance_size; + uint alloc_amount = max(BIN_ALLOC, BinChunk_size + (element_count - chunk_n) * BinInstance_size); chunk_new_start = atomicAdd(alloc, alloc_amount); wr_limit = chunk_new_start + alloc_amount; BinChunk_write(chunk_ref, BinChunk(chunk_n, BinChunkRef(chunk_new_start))); @@ -209,11 +210,11 @@ void main() { if (my_slice > 0) { idx += count[my_slice - 1][bin_ix]; } - uint out_offset = sh_chunk_start[bin_ix] + idx * 4; + uint out_offset = sh_chunk_start[bin_ix] + idx * BinInstance_size; if (out_offset >= sh_chunk_end[bin_ix]) { out_offset += sh_chunk_jump[bin_ix]; } - BinInstance_write(BinInstanceRef(out_offset), BinInstance(element_ix)); + BinInstance_write(BinInstanceRef(out_offset), BinInstance(element_ix, my_right_edge)); } x++; if (x == x1) { diff --git a/piet-gpu/shader/binning.spv b/piet-gpu/shader/binning.spv index a5379e6dad7ab1566cc2378b2fa9ed054c62b1a3..4fda673c4aea604390b10ba4ceb6b93a76378ee0 100644 GIT binary patch literal 22016 zcmai*2b^D3wS_NCNq|s7=p`id7NkR{Nq~e%r1v&Vl1Uht%!J7V2t^286c9nID56*Z zv5O5x$M<`eoSe1R-e;eE%02hq%+RswR%5Dam1->i z-PTdn*Z68xl&V^z>aOcqbB>#{%aW1#yX?8wt~#t$wH)f;sR`dd2qZ&m7tAf46f)vP%^vyM7y)||t7<}F^_vt(r1Kwr;5|6pIw{Qlv- zc_aPj_vtsb@arF(H?VYm>ClBonL`);46K?yI5>3N$nem)eRGI-T;IZD`xYRRSyycr z4=q@*q;I6El{MfmX;b@mG9RsLF|**vP<^$qkb>Kh#C z>1WrOx4L65^X{tFtM)`IV)R@v+&|KneNq^h`a0p}rYbDRQx8SPq zx8|a&+Pl@yA!jcgJlAD(Oln@`nD&Jey!O-PI;wej_}NbGSO)tp$9c1nvQ*O@9;?f zNdM4ay%Mc>hoZYKo~cKGhkGxm&;2e&_X_yvJv(D*bAPvVOjU30XRz~qlp>e0PNXIl zr)7(u-r_DvZJ*oXE=$eb)A+juYVQ2P_iFKuYAK*K){g21aB{x6<=5ogS>4v+qy4_6 z#Yg+Sqs2%2y{pBWemkmr;H`c-t4F}hS??lh$Mo1ryrX&?o;;oeub8{8>bvmz?i!u9 zmWJF~Cu-;H`wCpff10|SvtP9MXztIn_-O8bZ1K@Kd$z@!IqR&RZ}EC-8~?=?--oL1 zuZxXKfAyBuzDA2rjeUHJ@8;xc->~6Mu6*-`o1kOa8s3__j_OEo=H@ss_rnsW!h1&U zH5bj=wkI^2xOcQ|S9Lyko;Rwyx%M4fzjG`c=$SJ#uXkYf;Q3T;>e+5(Vs+Q=BiK(G z8a{W{@X*r5T70HnL#zvidEHplKhpB;tgau8KUlYYHGI*sp242x&}xmRt9lLk^nrn) zd86yuU2DcEogJUP{HaFzdAVT{qIs_O8iU$#-l$WJyQ;T=mz>>0*S6B$S>1^iLH~Q< z{k4B*bw7A+|Hz`=#Y^z*svd-w=dAt@qvfpl3Ye#E9rrQtiha#KhF{1c+veNgWext0 zI*YCTgnEs;t0%$aRUY4U+#jO*jB1Ukv-%NyML(U@+DyQL<~_yntpi_S@2>WQuQw*$v^C3snlyQ-_fjBUw4 z|Gd$0T;I|b^)5LV|L*D@c;_iFa4e!nt+ohjMdU(5|amm6wFpz0x;0zs{+RE%jFSwZ2!WpR;t);ySO+Y9>1O zfBhsf_c`#Pr6WD{BscSU5?cTK3$b=p{f&La^SQHHj#lP+MH|1ljo(u6S0 zQVypNpLbqcwW?|sYpO;waA*B|+j7*_;*$&h6u6A%Gr+5irUS{Z{k4Wz#0U-)-_uD30HA%PaAtDXV3k^kWOw+E{AmNiF?& zu9bPnC*x-u=kfJ8+V94c38?CmX>EJ)`uI5RNffV%Sp2?gX?`76HCNjJ+iKL4C>zpl zb!xeBCNd`bQA?SO&p5ccag4nVbz+YP8&}PE>rxxfu}|dh3Do+k8*4pkHQO0$BkII* ze8y7K*Ll{aE}ux9d5~`jHZKpYX-tE{gGeb~tYLf&AizyRP~> z?n^25r~Phf{oN<>`y1{aaNJK(o0H@IF11|0?@^nhn&Xyx-jsR2058Y63Z2?l@*V^C zo(W$Q?w$#s08ie=*%=f*g;k^4@W z`BHxed@LpFaTnOcHpAhjCNf79aoC!Z+{&~Fs`KN@Ts^D*8raQjlXf4T2=YT8e1aJgU3LvtMx|2p`j zg5Ln&0-o{s&Q^}+3HU~Z|8{JO7rE?j2e7`*k?rNa8>xl+PE>N=h2%T)w`b!`aL<~Z znR)k}&qc@U`C{3d{Xq(K8>)Iw{sYB5Zy%nY=i~1@%RMXo#woeqHzoJ`rsRHOl>FW{ z?srA(8x!Aeig5e$yCPh>-xlHSfydkUx7+x4+V~R%_Y8Ql;GUI!V|`?P{<_uC?N$G5zV`z;Z>{(euC+;54J`z=v&zadKQ zcSFhjW(arv{Z953gPDCH$ut%J}9~01>wf`dm!BSeh-8j&-eI}`yO9% z-{DK{dwjV0Eibt57QVyBZvVc+hugpJ@bc;01)jYZQ#_Boj}GJ>@C>`8(XYZs{z|x- z=W^Oz4)$Cw+bxHyU*5F40&H9L#JUQs?iqeG{dpf>t(|fZcc}NH+l?fEKe78Pc^ySR+lez@Zv?l`^PAAr?V2-@`0E=Q7vt1lz{8cT&q^dly(OYx{1n znrCo)-UD_{?`y{RUa)@Zj`414FUP3ueH1mvC^pZ`r@DD~#yTc#?{9pqU84_Be~{v( z{X>o2Iyrq9Y>W>!Iei4IHilvz^7|;pG7oXuegbUUtm`Mi?d$p}H1+AMgzpibrueM4 ztv1J?mNA&G{aB};&w%YGd;9^gnroanP%G!aeE+X?{4BO|tv&}=bFDI#&x6~?@(`MO z^7sPSw(92bAhlZZ{vuc{d*TtW+LtKa?;DZ-m%-|`f0$Y>{tC5ol2~7b8!P;4VE0ni z?dxED)ZI(pp!RYNwLMBvb8f}PvHx#^?bkjZqn1x)FL>X43+&I@)RU8%^PE`L+8(F& z91;6m4)&QG?DII-XYo^%jOV*x$87FDp!Rx!H-2@w()aj_M^IgNQ-2@s`-`>X(w=es z7@Tqa2rPG8enUJBo>c63kBX|9N3+7M#ZKZvX zb@sjacVKNOc>fIMPd#2^Xitp4fHU4Q z#$VC3WxUUVjia9N{tc{Nj`#0y{?y~up7A~h)|UM!PY(Y8XT0UQJ&&#}e*bLz+Sm65 zbZr^$zrg&dzdwzkJu&_b&Unkd{)4V&Uq)gw)k~5e(meqjjk=@9RoH8zqgH{Ju$|DGv2bV)zGzNysLwaqn`1u z0ah=^I}V=lYR`Dr1Z#7=o-1`a0?&k;1>>6wyd?)Sm4zf2~&DeR**axnD4w~ciJ5|kb?n`Ym-bgQcI%AcNU$;T?sgPdZ4CLChy3LfW0{9Id-6DN`<^@= zO+8~g0qhuUb0YX8%CQvv%wMig`}=YFI2l`eAE%(HXAGx;9mB));eB=**fmhUgfVy@ zoDNpcTAcwlj(Wy^CRqJ0^7TGA3+&}QXzQV!a?TyNue)J+AGQ6gAgL zoH&<*&B=MRPq}LnU+ef@0X7GHmxJZ8T?I~@E5Y*Y>ubR6`}$fm^=r7dy^mi7R=bX3 z{Hv+e664k2_86~0Q-7q1aU)pm21?G1o51clZMi>Q3s$$E>#60A`DSY8$GZOaC+b@% zUfN&Z*sU|}+rW-D{0(5|@k8Wv8}%FE`l!1W^4C#rq1cz$w$8zuz>Yhy-VCnivN`|W z0#|d7#OJMG*TVbE`{Z`8e(Jst-A)c~1K&?=eC_G)?O@0MXU;GCzXPnV&v~Cc+SAWF zz-2#o!qsv=Yg3E=JHcwh9O~P(qYcxo_@4caFsOHrRIW2OGz_{`WEJ4^q6ef2grr zo451+VX!gsy!r@OEzfHCeUuMSj4e*vkAiKR`{ZNb_WR`HXzJMy_k-OJw$+wcpHQbf zN?z`zPlDBQ-+T(J7XMF!orj$9p8>1smpM|4|AXK%*U!S+bNw8edfI#*Y#+(}A@Bnf zW9e%@YWg|9&b4!7ofuyL+i&uG7_63kp-rt^Kj%8_zX&#mdzyRtOJFtE-@W@~u$OyR z+anY;^AIP_SHRaZ@Ao!wz6w`MoUeluN88sZYQ_<}#{L`qH^Ao;XC^qYA45~m7{3Wt za}UMmTX6f&JN*B^)$~cb$Kkfs=G;C?t(F+y2CK#YJ7Bf4pC{qYSNeGhtfr6O_wM=c z!lCv1`x9V&67zdt3{=Gyr4j-P{X#6BCGK7WCxUw&5bOR#=9XSHXpwWZy! zz|M8}uffL2JpBf&kGk!hA2s)J#%`VV&wyS3@ZZ9XpPvi;4y<-GW7(Jde-E~ex^4W~ z(I3I?J^T9uST6n(wf<9CU8?HO{BQ}I?-g{%f zwo}jh*I2N+W3nIjiCX$u9qb&0uL0L5F~`C6QO|w9CRn|kr?nbh+nTdrZ8SoS-dp;Z zgFoxlmV0YFxc%N*7frw1TNA+g<=)b6EPqa{E%~npRtsMrY@F<)4Z!-S+ur$Ci~ok; z@?P2qZoJ$}8-vwyFKq(0jk+FvZyRB~GkaU}JgC80&Dj+IdC%+3@9X_q#qXhwG=F z_t_)B>dxCtYPo%QM!o`kbrVm1BwU}ohaLs?9a=waX?HYOn=$85%VRqRtQLMO_+Rebn==c|5q*$-!sFiEuCHNZSb%HRnj2*e8R_zD|MLSN77Wa5c}#^naS1qAlM5 zr-RiqXJ>%b9N$UQ^7MHo*g4BPS`S<;@3*~RFLT#+7Ddh6#fdW)Y@Fme53Xje@tF@V z*P{>q0B!Wu7QY2xZQ%>S=ACo!Y_OVs8Izj(IJsG;{W;)Pzpb<6T)1b6dVB`J>fwvP z_L=A6AXu$@E)KzMr_DV2snrr=F<349JaC!EFnm{vdVH3E)$_X`BVgmGyO++V_HsS6 zEv2Zr9^%Bg09^KUA$%{2dVH3F)x$3Wn{Vd%Vz8Qi8K0W-oIb77{t~e5^A2|@SS|Kf zf*<7mllyP(m%;tFTA#Q69{A;Oebnu5IkhpwS5Rxu^Yu#bp0v?Nn>n3G?L1i9hiAxD z;POnl8m^Y_NNsBIzozjIzZPEp8_0EVebil#>#4n54{fiasF{a2ab68B&un>YuK{~D z=G?mhu9h6NsX4~Pww6z)wl8b>K@FeQ@LQQ*?bh0FZul+K_U}1)Bfh>1h6r}+N{*pK$KJpruExQ<;O+ezRu?kR9J z&)UR26`Z)*)Als5Hsd;n^4QJ*mvMXGYX1B;anAxLuJ*L;1#2^|Yax$q9=MF#2UnX< zN!$hC#MPd*3&Glq>zc}A>j#%{&xNb`^UcKdckUBcd)h7nYcsBULmt}@xQu%qTx~HW zafiW)t37R(fVCOdJtmLse6VZjbJ_Fn0*YGf7lK`r*q4FTyf0U$zKCKQb@%DT)R$1) zyY3(Rlzv7Bdn>q%dplgMJY(JlPh9P3`*yH4<2v{9*xmsy>mU>C$WDBtQPx+!FNz%{|Hzu_K$+iG4_vv)sE(lSeN?a6#F!;ZMB>G{nVeJ zn0w9xx&FqUK>bOIcJEDb?#*uSW)!bYDBhbJQ*TP~-rSrz^YfWTcYc!d17P*sD-VLz zyjQX|p9N=aw5RRoz}n17oSfDGPoj8Dq$H;;z~(fW+Vf&8^&=F|i{$tPuzqEZ55v`S ze|{0H=Kk?L+4f(esJrgQl;?L+zYJcBqHeD81 z*Wmhq0N{rm&4TGsA|V6|f?xfgx}{yxQiw5RQl!P<=L zT+3to3Al{=Q@C3B9QYYLakZ!I&%xS^`!uyYwqJtFxW9s{ok>Z)zXm6+_O$&CSetQO zdwFcX1($Ju2UnX;RlDN--6IXlM{sXMdxbA6rZ2tt8asLHZdx4U;{{|mabX z=NTi{Ke4BQ-LHu~9js>i8PtbRY=1Dt`IhUG_J@JpmuWu}td{n(z_ve>VtcthX+In6 z{?q?p=IG^M{ST+;FV{zZ-#3l`YxiA5oOh8`vF%Cm+KuA7$S%~oH+Wa-Jt)4H>_wgT zkRypP2A=+pg4@RZl^l;oQ_pkz7_eIA)EH{GDP`*Q!w^Eq$K_PT$6~ zZ#DhOfB$pd52SeQM{(Zwq29m2Q>hQ2IPVA5dh7o;?Bc4IhpHT}}pIpDIdbKz=vhjK3u!0pR< zFZ)}Bt}Xoyg43UI>`zUUU=Khr7B?;+I5Z-}<)`B}$#aJ9vh%+D}* T3`LvYEyiC0R`>oAdw=~e9^Xm4 literal 21800 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 diff --git a/piet-gpu/shader/bins.h b/piet-gpu/shader/bins.h index 3ce06e0..85f7536 100644 --- a/piet-gpu/shader/bins.h +++ b/piet-gpu/shader/bins.h @@ -10,9 +10,10 @@ struct BinChunkRef { struct BinInstance { uint element_ix; + float right_edge; }; -#define BinInstance_size 4 +#define BinInstance_size 8 BinInstanceRef BinInstance_index(BinInstanceRef ref, uint index) { return BinInstanceRef(ref.offset + index * BinInstance_size); @@ -32,14 +33,17 @@ BinChunkRef BinChunk_index(BinChunkRef ref, uint index) { BinInstance BinInstance_read(BinInstanceRef ref) { uint ix = ref.offset >> 2; uint raw0 = bins[ix + 0]; + uint raw1 = bins[ix + 1]; BinInstance s; s.element_ix = raw0; + s.right_edge = uintBitsToFloat(raw1); return s; } void BinInstance_write(BinInstanceRef ref, BinInstance s) { uint ix = ref.offset >> 2; bins[ix + 0] = s.element_ix; + bins[ix + 1] = floatBitsToUint(s.right_edge); } BinChunk BinChunk_read(BinChunkRef ref) { diff --git a/piet-gpu/shader/coarse.comp b/piet-gpu/shader/coarse.comp index e331076..57abd73 100644 --- a/piet-gpu/shader/coarse.comp +++ b/piet-gpu/shader/coarse.comp @@ -30,6 +30,7 @@ layout(set = 0, binding = 3) buffer PtclBuf { #define N_RINGBUF 512 shared uint sh_elements[N_RINGBUF]; +shared float sh_right_edge[N_RINGBUF]; shared uint sh_chunk[N_WG]; shared uint sh_chunk_next[N_WG]; shared uint sh_chunk_n[N_WG]; @@ -41,6 +42,7 @@ shared uint sh_selected_n; shared uint sh_elements_ref; shared uint sh_bitmaps[N_SLICE][N_TILE]; +shared uint sh_backdrop[N_SLICE][N_TILE]; // scale factors useful for converting coordinates to tiles #define SX (1.0 / float(TILE_WIDTH_PX)) @@ -113,6 +115,7 @@ void main() { while (true) { for (uint i = 0; i < N_SLICE; i++) { sh_bitmaps[i][th_ix] = 0; + sh_backdrop[i][th_ix] = 0; } while (wr_ix - rd_ix <= N_TILE) { @@ -157,8 +160,10 @@ void main() { } BinInstanceRef inst_ref = BinInstanceRef(sh_elements_ref); if (th_ix < chunk_n) { - uint el = BinInstance_read(BinInstance_index(inst_ref, th_ix)).element_ix; - sh_elements[(wr_ix + th_ix) % N_RINGBUF] = el; + BinInstance inst = BinInstance_read(BinInstance_index(inst_ref, th_ix)); + uint wr_el_ix = (wr_ix + th_ix) % N_RINGBUF; + sh_elements[wr_el_ix] = inst.element_ix; + sh_right_edge[wr_el_ix] = inst.right_edge; } wr_ix += chunk_n; } @@ -180,8 +185,9 @@ void main() { // Bounding box of element in pixel coordinates. float xmin, xmax, ymin, ymax; switch (tag) { - case Annotated_Line: - AnnoLineSeg line = Annotated_Line_read(ref); + case Annotated_FillLine: + case Annotated_StrokeLine: + AnnoStrokeLineSeg line = Annotated_StrokeLine_read(ref); xmin = min(line.p0.x, line.p1.x) - line.stroke.x; xmax = max(line.p0.x, line.p1.x) + line.stroke.x; ymin = min(line.p0.y, line.p1.y) - line.stroke.y; @@ -214,7 +220,7 @@ void main() { break; } - // Draw the coverage area into the bitmaks. This uses an algorithm + // Draw the coverage area into the bitmasks. This uses an algorithm // that computes the coverage of a span for given scanline. // Compute bounding box in tiles and clip to this bin. @@ -263,15 +269,27 @@ void main() { tag = Annotated_tag(ref); switch (tag) { - case Annotated_Line: - AnnoLineSeg line = Annotated_Line_read(ref); + case Annotated_FillLine: + case Annotated_StrokeLine: + AnnoStrokeLineSeg line = Annotated_StrokeLine_read(ref); Segment seg = Segment(line.p0, line.p1); alloc_chunk(chunk_n_segs, seg_chunk_ref, first_seg_chunk, seg_limit); Segment_write(SegmentRef(seg_chunk_ref.offset + SegChunk_size + Segment_size * chunk_n_segs), seg); chunk_n_segs++; break; case Annotated_Fill: - chunk_n_segs = 0; + if (chunk_n_segs > 0) { + AnnoFill fill = Annotated_Fill_read(ref); + SegChunk_write(seg_chunk_ref, SegChunk(chunk_n_segs, SegChunkRef(0))); + seg_chunk_ref.offset += SegChunk_size + Segment_size * chunk_n_segs; + CmdFill cmd_fill; + cmd_fill.seg_ref = first_seg_chunk.offset; + cmd_fill.rgba_color = fill.rgba_color; + alloc_cmd(cmd_ref, cmd_limit); + Cmd_Fill_write(cmd_ref, cmd_fill); + cmd_ref.offset += Cmd_size; + chunk_n_segs = 0; + } break; case Annotated_Stroke: if (chunk_n_segs > 0) { diff --git a/piet-gpu/shader/coarse.spv b/piet-gpu/shader/coarse.spv index d61b227981fefe57ee154d9dd72928df4528cb29..e201c5ee594c6bd6ed8b29c3756015d10c16c85a 100644 GIT binary patch literal 33272 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 literal 30280 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 b8Mxeka(#?xuHJv{gUqLOxi8!wIY<5v^rU{n diff --git a/piet-gpu/shader/elements.comp b/piet-gpu/shader/elements.comp index 15ad80d..341952b 100644 --- a/piet-gpu/shader/elements.comp +++ b/piet-gpu/shader/elements.comp @@ -98,8 +98,9 @@ State map_element(ElementRef ref) { c.linewidth = 1.0; // TODO should be 0.0 c.flags = 0; switch (tag) { - case Element_Line: - LineSeg line = Element_Line_read(ref); + case Element_FillLine: + case Element_StrokeLine: + LineSeg line = Element_FillLine_read(ref); c.bbox.xy = min(line.p0, line.p1); c.bbox.zw = max(line.p0, line.p1); break; @@ -272,13 +273,22 @@ void main() { AnnotatedRef out_ref = AnnotatedRef((ix + i) * Annotated_size); uint tag = Element_tag(this_ref); switch (tag) { - case Element_Line: - LineSeg line = Element_Line_read(this_ref); - AnnoLineSeg anno_line; + case Element_FillLine: + case Element_StrokeLine: + LineSeg line = Element_StrokeLine_read(this_ref); + AnnoStrokeLineSeg anno_line; anno_line.p0 = st.mat.xz * line.p0.x + st.mat.yw * line.p0.y + st.translate; anno_line.p1 = st.mat.xz * line.p1.x + st.mat.yw * line.p1.y + st.translate; - anno_line.stroke = get_linewidth(st); - Annotated_Line_write(out_ref, anno_line); + if (tag == Element_StrokeLine) { + anno_line.stroke = get_linewidth(st); + } else { + anno_line.stroke = vec2(0.0); + } + // We do encoding a bit by hand to minimize divergence. Another approach + // would be to have a fill/stroke bool. + uint out_tag = tag == Element_FillLine ? Annotated_FillLine : Annotated_StrokeLine; + annotated[out_ref.offset >> 2] = out_tag; + AnnoStrokeLineSeg_write(AnnoStrokeLineSegRef(out_ref.offset + 4), anno_line); break; case Element_Stroke: Stroke stroke = Element_Stroke_read(this_ref); diff --git a/piet-gpu/shader/elements.spv b/piet-gpu/shader/elements.spv index ff0ae2d456ea352ee946cbe946a3e9b56ffc4853..c947240a374822edb8c39f605604b116253e8cd9 100644 GIT binary patch literal 45312 zcma)_2Y_Bx)wM6oObEUAmQX|Qz4sRBOm-Is=oZ+Q6N9FSJR?Y z)r?i2R=?H2T?Vc=se9OptFN)L_F1Y9yOwQMe7eA$w6Q}*k5eCyFdMqs?6iI~|_@H5dMyTWUxYUZhagGP@V zHvG^5le#A!JhXd-se@NIc$HPwJ9w4#@b6$vs%jzu%{ddeHHO}tv(gWw_FaaL?8&L- zXKK#QYEF3V*IFgHp9!q4t0s4?CahxI8LN4~wf~@r!-ot@iBog6O2oILnj7DCeO=Xj z;GGU0GOVme%}-g+0`S_em0#{B^~h6?^~pVk6IN~4w=lRK->bf~BIU7$Nj&Ck^Ox~l&0_-V5SH9x6QUe+j2jq!KaPFSsd+?N0+X0M_nas=B|>)%l= zj(@xE&T1*}mZQgv!G&77S{$jUxw9Hj`>6Nf|Kxrqj@*C9prPZ(jGt)S8LH*bjMb}# zI(V6XS;w~aU01aNc$e;p;}0Be1?|19=4a}3>w$NjIAq+U5#uM0Z7)+RpSqu^wRKe+!h3wd?iV#bV~2FZ`?R?GtJ|1k zhIDgTqSl$JP3U{Z_A0bTC40L{_tD1qw`-iS+5%i(W(IW+8JW|%aph_6zs-Bb%~EYs zjB6hx4?(Zw-xy=-BF4ZXhTH9bM`+ivT~Caes~w9Np6ma;g7)|wit)P^<6EcQ{|Mmv z?NW^2vl!oAhyNbH@p}~G_bJAI?Hv5t3byOtyJ!5Y)!<_M|G8iPk2r&R;>=PFE8_I* zn*Tl(_FhLdv?oSa<#k|}ZuVud*VX(?-Rqr|=UB^+-hD3jlYK64?sLymb+4!U??3)f zy4E?N<~4N;yD#Uj=Zd=b7^-=JU*vb^iKx)T&d>&(wK$ zRY${3q@OnTfSRB3UgJE~op<(8S2ag<0zBitKD|17>yQ<*QbzNbW**0xueC=ys^h`! zdGx7Hs^hnhB`XBC7Ii=6Tuy;cU9|RG)ciE(qF&C$d8>IG%X6ZunydOQ+SIsTpJh*N z&3U#B^-S5i^}hWM@iN!b!I|rsbsjGT!`f4A%~jpc)Va=5oeQ_7mhYhL$4~frSqams z%JE)z&Y^GTo~OF7SB!SC|0B$#_Nh5_HF{01&T)QEj*jXAaC?4pRTuZl=O+07&(_#7 zt+`xO6YS_Bs zef`Q;AA$dRact%7sBWYmQsbNG_iy1DtJ~6n6vVQGu=YF{r-}Zi)wYn2L za(H*^J6`Lak&*wS7~|Z**h$^(J@^pVRrhuP=`snZ+piI&oi@f?^KT#eiOr8f7`7~jt7)iz(P%{!{M0qs56QGERLLh zuiCsPZYLKE^7O==zRl~noz*OD-g<;K?_6!Z24Pw?F9=WGRlv!+M%%9^@49W?lXs&w z@5#G)oA>11rp5Hg7$yTi3VSe67?q7@oS00;jIy+J1Fi9n~p?-x-D9 zISs!H3%^SWzbhJk*A;%Z7Jhg1^6RYbZu6e?xWCPN*2DJ^9G9N;c&yEP*5j!*?>P?7 z!`t)itUd&DEf_Mkb&NWz&l`MNZV07)h6bOb!53)o#TtCsUc94P5uWv46~x+H_R^>cM@g&%r(S zzMi#d>x8L>vE|2r%20yOBkMG4hs*B)5>l`oh0L^#8 z*8E-pPmSAAy$)~tvG>3}YqV?YtUl`H+gVN5RaFP^-7NOL@TsvntHt0$eFxLZ+gUB% z%id9K0UvWnd!4sz*tUmv*W-5RW$W8|2RL%fpn>Cu4jHq}xXEz2s z4eB1v`@ZbmBaBxIuJcjwtn*3W_C2JlI$gg}?b}`E^=M!LRAXxhKMTDrg;>+rZ4juTStk)je%qz9wk-J=oS;kG-vXRGa5(Q)}$AZLR#; zgx*!X)YkL038kZY6|FtLj_NPs`d;`?@c8ag!zb2rpT1AIE}hkky?9r(B7FFvyiuLh zdeus7&i`IMybEdYjT(GYxW(mIY~8SL*Wd#ie1~4VPqim}%=qyK4%&an&;xs(tvahA z4Zj26Om+0cLG5R)NUuQM0!6!8M#9q9sIs)E~>rrm+{Udw%bXLbS_;C$>LN7jD zbt=5|=Gt{`)O%Vl-_GjvUc9S13(g+vnWV?)oL)Yi)p-qmeuIC%7w@R9gijoQNNX?M z0M7pT5xCqxkMZM-1t9lvUJ!(SYr=W7uD`!`R%`XLcU9}cTRCed=ddAKuCE*Q^5?$T;DZ}{7<@$io!dPz zyqBGKHt<%y+DV`By?i>WgBtwcf^UWYW2_BJ1*)p8`EQ=1=WFq)&(({={cOdY^yz5f z&ek*bVjB1u&u8xbE!O6%abGRt=h(!SnNMy$9?4qyKZ8%r z*VTFsz|?xbZ*ToR8zi3h{lzr!v3|Mn=vv&Lb+5)bmXq=Qz>Zg21l2Vx z$0x>O=-T?xjIk7bVk`|dhMKkkwawa>0n7E#=FdYiZbh);)U>Ts+Z^XJrCc9vKE!66 z53r6?)8+%L>*qKhUgi2|^NV`Mtq*pbn(Mv+z2iKGTz7xApq4pr1XgpLu{WbPmd9AW z6}`tLe0#9#9KJKyH4EPz?3}{)0uLzoeqd{leSfg|<<4aUedaO}>|E3q!DAGCYR|l! zoBr17y+9wwxqtmmKt*pLT8L^I1Llc#LZKtGUk(rZ4x2F(=nP+KkELX)C5< zwHed*l!aL*Q=k<_oGciTdw9m1^ba3|7Wx%YOenjn)NTtJRhUi$2mVv zFL#Z8Nw1IEdNud{pq98#f&J+J481mE#r^^~b*cZ3R*rui?zPwPZ_&HPo=fugYwlb# zuMfawyxAb0x5+mToJ)Rd`~qO(c`nAj8(LZ4-nEbU2GzKK?e98GLQ8!o*Y*ME`d?6U z&t>_wHD9ylH`d(qPy2H<_gt30QgipE$07GxkAwG2xqfTVyJl)02f6o6wajZU#QhOI z0`8s)9|QN^6h0B|eK7n`_)Il--WS2MuJTLauB&zC9&Mf8i{;k&1wH?3Y1S$Ceyo-} zC$pGi3Vs&c>v!zu!@W<<#i;2hK;89w!(#X>&k=RK-h``_ExvEHe2?8IzHh_T;wxUB z*|@LXDfEor*NIluM&297g559K1LNQvwwCT3=^lEI4N2&^q2eHS}k)v z9Nw1z;m5#_#l8?;r-4U--RH*p4%|Jh9{(SK`_=xpfL))q)>+*OHx08apQOAFMUwJqq^tCEjDTOIq(_a5T=l-T9IPbsEtN9@M;{YLmmxbHW@jpzG~aQ%J1QF7mJgpb6&UBMmi`;FKg@B59C`+lS3LkjMA z-)ofi0}DP9yYDk%*WdRUCHH+s$$g&@Zau!s2pOZxQY@vF|Oy9q)UKaGx=JZxL=j-&=&A3irK5xX( zKI8b_B6jon-Xh%RSl?TO8_#zZ;o5y?5w6{L7V=HF3VMG$h~_=>DYOl^2C`h$#9F@* zAFs)i;A;AO!d3KOu%FNI*Vau_^V%xjgeX3L9t!r^$md_%`(!r$Vd&btMjO+9L*jZb z*7g~363_k(^7yQ3^ZuMVj|4l$v0lgJu^kOoJCQk<^H{K&_w&sCIB;|B$D^rd+zDVc z@A=2pu}*{=Pn)^DXQ(Cj$>5e&`=0_=^SOUV=HmLF3Ric$_ZYe3wVeT0)8_p}z7DZQ zVLKCi8@;;oa8I2D_P*pAJ4UXb*!z*|>zbYe_88fJOs?bp1FJPlxO^9VgeTs?Vy4Sts9So6sBNuJ+=n|XeRrmm0o$KQj^<9AN;crASy zuCC8y`d4T#(Hv_Yxjy1o>Al9gcV7d$_wBv@yg~ma&5!m!)OP#idJAlfTz}pMtNCuh z>yP|(nz4-C!szAwBJ=$tKF#^QgQlK*e*&9t3Ul+j_Pb#Bruvcf{NDqs--3_V#P`9* zQTP7%0lgpV)AnbYn)QiO&tJjKdj5u{o_hWcF6;RR+i<~ggbkLUFlwQfw$ z{eQ!a>3pnHu1{kA2b`GJ`6cZ^ntJN|s@7Ad8`PMd=f;%llbF-M6Z2{GY2luW>iT#d zb%524={emAHm2vaG3ELsW*0ayJsYiiShxX0qDr=j7J`29heK{+dde(V1uyM=# z!|Z74`gpwN0K2aoYaMcZl4nkEGtXRT>iW1x<_4R`J>vY`NAsYm>*HRV7wlehta;@6 zB+q={W}f-c)b(+HF90@Ad4E_CO?}ddHeau21qT3~uIG1WjEZ_tK(Z^OX08 zerW3YxF`FA-II5=}jMmI6PEk7Lav*C%Bz zKvUPpeY_0VJmvjiSu}NhJRg<=dp9k6!=1F52f@Sst6$ygU!B09VU(LYrE7 zPk95)d>+e{u=yS%*8sWiC}Ur_w&z+V_r0Wc_uMMAJ^AGC)OL^Isl9<^L|HU@jFwfWvh?sbQ0R-1qiqIZloeKw`{ z+5Szi{bumgu{qc}GM_ErYOaIx*$V8(`DojcrsjOaiL(tj^Vu3K&wRE8UquXc>)DQ8 zE%W&nIP)0@mS;ZOgPo6Kv}Ha%SGey|i+yU@5u93f0L!g~uG)$JTt}}S|DD0EQNAzl z0?zkk{mrSSU&ibTHpflG_1R-LxLVe253nECP227?HP=m?INt^vC(jIf!PPuY=G_yl z=3Mutcf7sNZTr&iNAsh7P;Iw2?_m0UX!qRs(UQ5=FTVc zI0Rg-$DwdFkG1P@IM|Qtq3tl5n(HA>oTI>5k0ZhItjE#d%ZZ_GO~=ryWj&4syB_M= zkDyn}oR0^qX*-Ty9@~lFtj7spdDi13uR*PPSA^33H7uyb*YHfuYTUOnT_1}FAe zV0q?wE;!epbHMT(pYMU)uj4Vn;e&5E3ccE z!quLl7SDmp!G1gkv|UD1Gp;!6bOqRTwPILb*PP`2e_#`E&TQ#8gkr2f^xz`4HHcd5)Cplb8>K6VvDHU%-9NR*%mVu(~mQ z_Iw0v%shL__0iw^(qmxvs_XJ7y*##Gf*q^vae8^KT~C0$b~#3yKE_e^{K!7F*Y+g6 z`&!#mVE3@S&lk_oKTGqY{a3Z!KJ$7GY>d1YdLFEn_tNsGX~r_PIAebec5LSL8*t|Q zB3SNv`ELEU;L}-C$Hf14V0Gv561_a@@O!Z9U>t4wyg;w+`022{3O+&0Y|D2bpTgC5;D~uW`wXmR^V9mS#B97~e2!*J$9pbV zlh>9n(6pUN9%K9)Y#jCE{tvjB`%5(SnF zJtx>W>RGF~z}BQKYc)5xxyJLLsb}20V8^Ow+zk+ubC{b`;{V&i!4SOjc+=J4n2a?d6A!lK|i>D5zLKd^P>J}lSIbJd*2 zH&6T*1DF1C-^-N#j?2830GIPx60YX6>J7}?_xnr1)m&*wz8>Nw02>HMP+)r}e;U<@&7;SC7vIV1Jh)*9Eyg=6A1c49;HjcPixBYny=G zYwG6rcQDk9?KNdnuw!#JErDafYoB(vbOI;Ot0Bn!S(SIZR=X| zx)5y}G{^dhwr#EHwuf(-@A?=Qwg{8wj>ueKMzSfnBeh<8uA9d#~9Z?3~N@ z&O4x~=bo@*?cJ^UC_0iRIkadV8^Ow>~3J|Fh_Y!+#Ow8 z{PrmP^4-!Ld!lPgj&Fk{!PQrkCg3+8=x&K912=o?AZK7z4Q)!GCgY4F}8J z+XJwT1n)zyZjNE}YS!+xX*5{P^)()0s{`Qb@i`DYs`fF4Tp#V8A7jAH^J6TUdVI!# zjgkE(*C%T<0h~1&50-25-wjLzJJ#F>(aW<&lfW0_;}~t_8u|Pt_q&1j2K&tMaD2<> z+#}#>sZX1lZ$Kuuw(PgeIHoO-wDcf{C=?GwB`4N9ssLzj>!ZkqMY zOP}9qeF*H_!XIt$=NkN_27k5SZ-L*gdFKBx+`Q%de*ss|{qPa6TFxnJQp@^030BKm zJPlTRism)p8Tw~wPteSxJ!5|b*5-b4Zt~ck2bXbw4OjEplejN}6IXl2{syegxUP{r zw%>xwxW9+1d96y^m%)jvJ!4-1YcsBEEsyOra2fXvxSH45#C;Q-xNm?n_77lf#`T!V zWBVi6wek7J>)|^zwb=gzc8;;X3s&2a^TPY#do;(Wd)(ir|1-_K;PEi0T))Kp3)uN3 z=3l{TvHuNhow5HNtd^Yr06RuKIX?uOGv~EjKVy1Md_>dk`6ABwvH*Btnx6$}o-gy$ zFGTZvS%g04$H(CEeEGb=ziRN#X?pwncS_3f{+*JN`*%vh{dY0`of3J@r%%Av<+^6A zJ_W1ieEJNmHihQeTeDjHzW}S{eEK(7tvsLp1J6Fvp0QtowHepB%VYBj}HsiWC`N7(Z>mHNGwh-83nR9JnxLWLsfITL$FA7)7x!4cv81=^arTpDc7od0tD5_169HBHQAz-qBC3wCW{Ukk8WQR4Y;?*`XA*Q8b9)?HqcRzp+IHEDIQ zTGq)qsb%fg1gqtmv=&&cye6#;&)(LavFm`fxzAi1d2H)}%ed>q)yiwq2Jpnyp0OK> zX~uPpTb$$Chq-PHFXL_kS1Yeco5B-Ud*W^e)@EFfl{~gBz-8Pm;cDeIX)Ac*YR}lM z!P<=LF_*`-Ex3%k9bB!vCJlrquJ(-m7Fe5c-8=Hwb^w=gcZ92z*QA}`iK{(hcLr-S zu6s}(+pgd;?(T54-DtVi?Ey|)?HRi#SetR(%ktRv0+(_3fvfFJOWb|IiK{(h_XBG) zuIGe2wjp5mUalScgVkam3U&|0J`AjuYs+x3W7KnP83FcO%QaN4Ut*2~yMGdM6j&|x z(O~yM><56=lJh{YW7Ly#4A`8xhRXFz%&}niKw^#qtHnMZ?6Hh}0$43M4+1+zJvk?W z&6#V1T))KZ274S6^I))A?32MBkJt|Zt0m{5V8^H@=V4%TPNI1{<@y=3Kj-)1VC`PF z#kp?#J$pHtpJixXx0j}0mgaSPdHP(pk78V|n_jn%EBMLaQ)+Ha+K+}Cr@W3HgQlMA z=&@k6td%*`vKGgKTN*LFPMrW(E3cy`!n41%XY5H}ZLWv4%40hftd?3&16zOgrd%KW zU8C>RcGpjw^;-$ssx&_<(_Ft5=~tn-eyh=E{mx)qxqjyq`~vWWHBU`v!i`g|-&ttt zS--QvYFR&XsAZn#g4J>#`W{%VT)*?+SwHO=dp=m3>u0U<*uD=|ORYZuTYuJ1u8;n% z(M7f0^%H0P*2K0B&Cgn`#yyXIZJO)1E`8ST62_J5cSXUk1z%V5)O0D_IOY0XhNhnN zyBw^R^)rWB=6NMpE$ep`Sgl;YtKnHc?HPLwSexr-t@7Be2dm{AzX7af?KjfjL~}k_ zPq{vhcg=3D?XIUd>$xGeO=x~LqPZW}r{9?7dTvUe^}LmF<$B)H;CDCp{SE$bgFn{b zPZj(*@bfj#@wp9dUFGrlF`9ag&+TBf93N{|%R1f(R?G3Z3#?WipP#^Ue6(lmPr=$e zKF(bp+dbei?!9oe@;U2g@Wj=gvG;+s8P_$G$MyiYjQexATKSyyAUtukXY4~@ZN~Lj z$Yc8jxQsgmu2w#0JpxZ$?HT(hSetP@rt;Vx2bXbw30IqqmgkEnz=^9pW1m!~8P~lb zkL_u28TT2u+B~$xeHNU!+B5c7U~R^AkI7?u0qn8NdG%|sTI?@^JtndL2CNqQOJLVF z_TPflV*ef3HH!WBV72@#<7Kcpjq6zL?)O*dU!{2t=<=(zR$V!7TBC0fL$-Se#Z1#@pf(ZIwH<>#Cz=)G(VfsypHsx-<;-k zWJ~&-$A4m+dU+ndi>99Q_&u^3w%ThUU})?jPe zmfmaIZ1f*8&TCt0{3~3)vc|umsps19cd(j!+jr8l;{Ok@x@%`lxj&z|F5)-Q>pUs>x{=AflkLR4z0bw2#3K~uL@W6G`7 zS~|eKzf`wYd1~#CzAMeo&a~9J3)otBqqo+6^!`2FverIu{mNRWLsL(!eH}wft&8G6 zJzU*djVZTQYnc(eM4ii8<*C)@o;_)PcBiG*J;2ubZF+0ug}P)Vc!xv&(7LYD~GcTFabZpH$) zxPE1=^P;Jz*7?9{sdXv*=ZC9Xt1;!)YAp+b{a&JOt@70B^Uq+KpZ#d5br9HEhtONA z&ykBUuB>$txPE1=i=wHg)_!2M)VezU{o(4?YD~GcTFc@s+|FgK^3>`zb{Ngi{8;ggv}GAr*18m2zp~b)(bQAx0I*tWT@U|d;Of?DOu4mM%W~jN>Ri?;PpzZS z52X1SO|#aK^as$abqu|=`rXdIEp4sgt2X$04Zd-M`?sRY@!K}Ie=EAQ@7mzsZt(pY zd{~1Y(BS^9=raD~f{$fhN7g*|kCouALwPJ#MpMr{ZWXZF6#QI!*GMh*wY9)%Id*G< z)yikpb>R7ZaP1kpE?Ap!U2A!4>x0X<8^G0GppM*YH-smy_Ke*Ktj)L{GkI*AfXld> z!qv)W)y?3Et36{k2WvB~$6g-Wmf$k(R&cfQS#@i8;%d*>ZNS=$>mHKFwjH>PI}ons zxsi4F7CdpaXYBT1ZN_yk%46FRT*loAt~O5*cV~FwYR}kRz}k%Ko|eb98@PJv-LbRN--NEs_4GUS&0w{h&p!gMNpqZWT_ZL9lK&QPng3R}TJG=WzYU)J z>dF6ObZyChJ6J9G?*J#iam}x$U-I7xF7w|7SIcvN`F{dWe)Z)4DY~}gzZ`5yqQCI8RC$!}cqtLc~g4}#1555d*) zTw(r);pX?6QXc&i`3-ZOQ*Duv+pz2Tp$DnqN)7 zu|LZwB&ySoc!hfe-m9>^8W#>mi%vl zli#@JSJN-~-v*cY{|HwbL(6^P9kBVmuQ<+Y-=EObllxt;T5`V!PHtnGTTQ>@eji-s z{xe){A}zT;0GsaB=Dw6Z z<30kbC)Yp0$z=?4sp(h#PA;_d?-A%)f4kiKTsQbons_q(VKnb~N6_b<_b&#P_q>nc zjw$bXpP;Gdp7$wOE%!WQsAUfS0juSn_a#`(bK7~j=f8qmPxGEfsV!U9ej2!1)?-@m zzZvT|1t-68&9A0k@=p&g^UnZR z^W4t-XM~%-dCi{*U0d?c3|342S-{C}T=T2xm;AGW%lxy!)yjL`?C|6-=RXI!w&b4^ ztd{(9fs^03=2z1%`R4|g`R9SFmG``P;pT5%^XEg?mi+UB)slY!aPk}1{A&6o|AOE$ z|3YxJ@}9RaJo(G{FM_Tu`4cWx$!cG0df=Uve!AE^{phS1ZrG<>BUP?)??ewPo#B1gj*sq4JE%{dmt0n&$;N&;1`PKAG{x!j6{w?vie?4&W8`u15`X&GR;4=RPaJBN>+Yp}o<^6smbZyDMF<346HvuQV zam}x$Uvuw&m-+ZPjpp7znf^O9K9&A-ntT5Y`t1EpiBse>5SfYq}1 zjiHwH*b=Oky}uP$t=#)t!>y;xvkjVh=DsaBb2o-_SJN-KwgZ>B2Ex_Kz5gw^xte=_ zdvtAC`yIe)$-g5w`HgFSHT{x*Cvcg6XSiCq_jiFOf4TQ}Mc0=6yMfh`e|K>58`u15 z`X&D!;4=T7aJ6#pe;c0s<=)>5U0d?+4OUD3eZa|YT=T2xm;C#J%l!Mn)ylm;2%h}q z-XDyvE%}Fl)slaIaPk}1{A&6o|4?w5e;8b?ecx%nLm3V?zx&m3p7$fr)RTK8SS`6n zfs@;q=2p|MdET8%JU?gCJnzn;KZoYI_C5MMdyZzTdb#HhKvU1Tbs$*HT2spycxusZ zEoz=m%~~!*^K%|8wVYpLuK^d(tn2&qUIV;F984^)0djpN*F1HPg&U)+dmNg2>K+eP zE9;&BPu<$BTP?@N_e}@Eo3SUNsptAJ39ROx^5^^~F|He~ZcOW!du&g^b_m#cYI82~ z{2RVQ!CogFqpi7q7i07D16tPaq8cAV|3jMVcL}}g)q1`lPS#JK<7=MvI}C1&a{UfR zQ_uPx0ah#5??`yoPrLI`Yk!Y#KSLY^Z^k|vO+D*(3|KAecO*q1PjOLnML7(&XB*v=e-yEI-S38-Ox=#fU zo|gB=^d5KPp9WU<{i8VVAGKXY^Hb)&5^nCR>681rj8jkUGvI1v?la-$)|PtC2CJV% zOFid+)vZUIdioImI+~wrXjzME!Pav(I5u?|N|Zm-qM^(6uH1jbO*BXY5VjZ_05qy0-ZJNM5hw z>-1UgThO&7$E{$;s%MV3fip*I(C0Yb`8)p~gIxoClIwP`HGM!UkL?}k+A{V|u;bM; z_Aan{E63aGh?>6f`3X34F4ya)=-T3UH#l=H>$nG9TjqQ(*si z3jU@XkD+Ue-{auqC~Ns8y0+wa0_<4z%<)NZ=4cK2pFmD4f-VRE8yfW>B8kT_u{0&`O=KOcC zW7RYEAK-7w@gcgl_KXfQ@Hgf754yJaeF;vEvX-yVwIv6S4wYloGskJrGDmCBC&zzU zaBB_dldA)4P41m?KAq^=GPVosc=e3!1J2&DPWO(QzMF8L^f|UK*!bno4yH#_e+(a= z`DOsC`K+D4Sv4bE-F@^4ac2hm@o!dXn~A38^O-m`%>vHamHT5>bZzmQt?(=N>g?#+ z?xVKp=;xq0R^7iflAQMc;#o+aIce79bE5v%W6g8Z`>|$y=Ax-tvpBWP15VB5@tzl5 zTm0rL{K{iBKf1Qmya3p->eif`_NjS6ur)ak{jJBE7p70m`Yc52PqSvR$JO6ySp@8H zokH`OY6JR3(bVJ951jqs-jM5KP3AGCv9nhe12^}|;%MsGD@%aY%Du8ATs?bbX|NyH zUE5MLHS>v+ZvfbJFZbp$XzIzgELhFGl)bqeT-|)mC9&p8d$Sj{;6kE7rECkU)S`}(Y} zK8d+4xH;eL(9~1!K(LyPulKE38UHP`W=-3psb~BSU^QFDXTCe4IbWaW%%g8&?*wkf z-Wg3j^W6okW*k4p5;||MIr{43e#!B+m**N}pMAS4*!5_BKi>^qTl{thd+liY?SZZ> z_vk&rj#batZ-bMgJh%5k*A~CM!O2mcL;Ij>OOAcPj#WR7nfv{8Kd`yACEg&g>zSHe zA2ogBGZ>uO%A7;cwZ(6LaB3^BJ44a6rM6*U$Es)SaBy;z*N_qD+Tu47oE&8>qtLY_ z$7rx))ieJCz~~XS+7j;s zaOQ73=dY%3d`<+Xw(|I&gsv@qCxfl+16t{K3c9w`cB+`Bp0THalcQX_@1Sdo-|67w zD38T=(X}PV8DPh%XZ~k`&8;o*&H|gaS@YTG+A{VWu;bM;_FS-Qm$9y$n!fS*9ys$V z>pc%$Tl~%kXI|ynU4X7F^STi1SoMtkJ~%nbJ@Er{ZSlJZoE&8>KSbA-92bKftDgB^ z0yej{#Jd!nwJYOYhORARF9$nbJ!7u`XYCy8+NtTg3D;}CCtV4)-tt-WDm3*xi(U;@ zGe(|8uYs$(jy~sH5BB5prMBy6H_?2~5u4BV&^LgcPx-rSH=?Oq-?iFl-Y1Rec;jUJ z&0y;-$NvaTJ>%u&c;ocEe+8Q(@oojXM){p>`7O2G^|=jfz2*A+7)?Fvb30hgb1MJ; zbnbwwXMKJG_T&0!yNh-Y&H0H_&riYTD}UeaZZvi0cPG8v`5Dvk#&Nv$-V1Kl`!h84 z)O#OT&F?a)_kOr~>U|LG$9lE>oc0Tv`NY{{4}r}$g;riu9!A$@%@5Gat=YK7FjnR~ z1?({>=llqoddADk@y5w9eH3httdG20AJ-|qkAYpoV#)llA;1xVfHBps8m) zp9HIUUC6kn;LY>uX*BgmI99%Ycn0iP^^AKKY(4Hb>yhgh`>(*wdY(g5Pd(3r)jYoW zndJ*`^$&^~e+^GA*Tt_sqzV+MM?$5r&<%+*Zei`7WC@cox7Ur z?K_V@fSvD@dc6EiTI_!WYxnuu@$$E8`}=5rs_h{Oj{|zaD#! zoyR)IZhCAvcAkTBkKF>qm;t;ay}GeHXVo&l8Nq7hv6~659-oZyAHaE`s>wP*Z-;O4v+LQ~K9g~1tbEbW>1BH-q{7e!Ogy!(OG zjN`{xnZL(dUwz8G!YbB#|Gf!aJ=@|HY{w`qOY-Cw~fHfb=w$CJ?pj! zSj{+o%#-zVzv-(_xp%#%nZtYNX4uS;d#K#!v(n#tUiSJ{*t6Gt){wi`{hJtDg9p>A zn|lj-HFJ4C-v+Ffz3zLtZQ<(i*$!+yx#!FENxcJWd+L?@{jaRodvogD5qs+00W7y( z|1QQ(;9>OY*1J8unz>y6oxy6U*ZbuzaP|1?3btN-j3L)YyZ80oz{V)|;O=ns`0N2T zhCarS>r>9jdzNz=h0k8Kzt6GaJjZ&@-bwRwJI&`JF3=>wdemI(E(s}=jR&AUBmweKx4^i literal 45068 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 2]; } -LineSeg Element_Line_read(ElementRef ref) { +LineSeg Element_StrokeLine_read(ElementRef ref) { + return LineSeg_read(LineSegRef(ref.offset + 4)); +} + +LineSeg Element_FillLine_read(ElementRef ref) { return LineSeg_read(LineSegRef(ref.offset + 4)); } diff --git a/piet-gpu/src/pico_svg.rs b/piet-gpu/src/pico_svg.rs index 9cf5cc3..b2f054c 100644 --- a/piet-gpu/src/pico_svg.rs +++ b/piet-gpu/src/pico_svg.rs @@ -61,8 +61,8 @@ impl PicoSvg { for item in &self.items { match item { Item::Fill(fill_item) => { - //rc.fill(&fill_item.path, &fill_item.color); - rc.stroke(&fill_item.path, &fill_item.color, 1.0); + rc.fill(&fill_item.path, &fill_item.color); + //rc.stroke(&fill_item.path, &fill_item.color, 1.0); } Item::Stroke(stroke_item) => { rc.stroke(&stroke_item.path, &stroke_item.color, stroke_item.width); diff --git a/piet-gpu/src/render_ctx.rs b/piet-gpu/src/render_ctx.rs index e01a6ae..8d68b0c 100644 --- a/piet-gpu/src/render_ctx.rs +++ b/piet-gpu/src/render_ctx.rs @@ -94,7 +94,7 @@ impl RenderContext for PietGpuRenderContext { } let brush = brush.make_brush(self, || shape.bounding_box()).into_owned(); let path = shape.to_bez_path(TOLERANCE); - self.encode_path(path); + self.encode_path(path, false); match brush { PietGpuBrush::Solid(rgba_color) => { let stroke = Stroke { rgba_color }; @@ -116,7 +116,7 @@ impl RenderContext for PietGpuRenderContext { fn fill(&mut self, shape: impl Shape, brush: &impl IntoBrush) { let brush = brush.make_brush(self, || shape.bounding_box()).into_owned(); let path = shape.to_bez_path(TOLERANCE); - self.encode_path(path); + self.encode_path(path, true); match brush { PietGpuBrush::Solid(rgba_color) => { let fill = Fill { rgba_color }; @@ -198,7 +198,15 @@ impl RenderContext for PietGpuRenderContext { } impl PietGpuRenderContext { - fn encode_path(&mut self, path: impl Iterator) { + fn encode_line_seg(&mut self, seg: LineSeg, is_fill: bool) { + if is_fill { + self.elements.push(Element::FillLine(seg)); + } else { + self.elements.push(Element::StrokeLine(seg)); + } + } + + fn encode_path(&mut self, path: impl Iterator, is_fill: bool) { let flatten = true; if flatten { let mut start_pt = None; @@ -215,7 +223,7 @@ impl PietGpuRenderContext { p0: last_pt.unwrap(), p1: scene_pt, }; - self.elements.push(Element::Line(seg)); + self.encode_line_seg(seg, is_fill); last_pt = Some(scene_pt); } PathEl::ClosePath => { @@ -224,7 +232,7 @@ impl PietGpuRenderContext { p0: last, p1: start, }; - self.elements.push(Element::Line(seg)); + self.encode_line_seg(seg, is_fill); } } _ => (), @@ -246,7 +254,7 @@ impl PietGpuRenderContext { p0: last_pt.unwrap(), p1: scene_pt, }; - self.elements.push(Element::Line(seg)); + self.encode_line_seg(seg, is_fill); last_pt = Some(scene_pt); } PathEl::QuadTo(p1, p2) => { @@ -279,7 +287,7 @@ impl PietGpuRenderContext { p0: last, p1: start, }; - self.elements.push(Element::Line(seg)); + self.encode_line_seg(seg, is_fill); } } }