From 753b97c3420c523c32dd579c15d10e87bea1b9c7 Mon Sep 17 00:00:00 2001 From: Chad Brokaw Date: Mon, 11 Apr 2022 05:30:08 -0400 Subject: [PATCH] Rebase on radial branch --- Cargo.lock | 12 +- Cargo.toml | 1 + piet-gpu-types/src/ptcl.rs | 14 +- piet-gpu/bin/cli.rs | 8 +- piet-gpu/bin/winit.rs | 32 +- piet-gpu/shader/coarse.comp | 22 +- piet-gpu/shader/draw_leaf.comp | 36 +- piet-gpu/shader/drawtag.h | 5 +- piet-gpu/shader/gen/binning.dxil | Bin 6336 -> 6336 bytes piet-gpu/shader/gen/coarse.dxil | Bin 10544 -> 11652 bytes piet-gpu/shader/gen/coarse.hlsl | 505 +++++++++++++++--------- piet-gpu/shader/gen/coarse.msl | 544 ++++++++++++++++---------- piet-gpu/shader/gen/coarse.spv | Bin 52244 -> 58964 bytes piet-gpu/shader/gen/draw_leaf.dxil | Bin 6072 -> 6760 bytes piet-gpu/shader/gen/draw_leaf.hlsl | 128 +++--- piet-gpu/shader/gen/draw_leaf.msl | 112 ++++-- piet-gpu/shader/gen/draw_leaf.spv | Bin 16412 -> 20104 bytes piet-gpu/shader/gen/draw_reduce.dxil | Bin 4256 -> 4264 bytes piet-gpu/shader/gen/draw_reduce.hlsl | 26 +- piet-gpu/shader/gen/draw_reduce.msl | 18 +- piet-gpu/shader/gen/draw_reduce.spv | Bin 7124 -> 7140 bytes piet-gpu/shader/gen/draw_root.dxil | Bin 4468 -> 4468 bytes piet-gpu/shader/gen/kernel4.dxil | Bin 14236 -> 15108 bytes piet-gpu/shader/gen/kernel4.hlsl | 288 +++++++++----- piet-gpu/shader/gen/kernel4.msl | 335 ++++++++++------ piet-gpu/shader/gen/kernel4.spv | Bin 58596 -> 65556 bytes piet-gpu/shader/gen/kernel4_gray.dxil | Bin 14140 -> 15016 bytes piet-gpu/shader/gen/kernel4_gray.hlsl | 286 +++++++++----- piet-gpu/shader/gen/kernel4_gray.msl | 333 ++++++++++------ piet-gpu/shader/gen/kernel4_gray.spv | Bin 58352 -> 65312 bytes piet-gpu/shader/gen/tile_alloc.dxil | Bin 5132 -> 5136 bytes piet-gpu/shader/kernel4.comp | 19 +- piet-gpu/shader/ptcl.h | 77 +++- piet-gpu/src/encoder.rs | 30 +- piet-gpu/src/gradient.rs | 51 ++- piet-gpu/src/lib.rs | 3 +- piet-gpu/src/render_ctx.rs | 25 +- piet-gpu/src/test_scenes.rs | 29 +- piet-scene/Cargo.toml | 9 + piet-scene/src/brush/color.rs | 62 +++ piet-scene/src/brush/gradient.rs | 87 ++++ piet-scene/src/brush/image.rs | 96 +++++ piet-scene/src/brush/mod.rs | 35 ++ piet-scene/src/geometry.rs | 189 +++++++++ piet-scene/src/lib.rs | 21 + piet-scene/src/main.rs | 30 ++ piet-scene/src/path.rs | 311 +++++++++++++++ piet-scene/src/resource/mod.rs | 37 ++ piet-scene/src/resource/ramp_cache.rs | 138 +++++++ piet-scene/src/scene/blend.rs | 102 +++++ piet-scene/src/scene/builder.rs | 433 ++++++++++++++++++++ piet-scene/src/scene/mod.rs | 97 +++++ piet-scene/src/scene/style.rs | 71 ++++ 53 files changed, 3653 insertions(+), 1004 deletions(-) create mode 100644 piet-scene/Cargo.toml create mode 100644 piet-scene/src/brush/color.rs create mode 100644 piet-scene/src/brush/gradient.rs create mode 100644 piet-scene/src/brush/image.rs create mode 100644 piet-scene/src/brush/mod.rs create mode 100644 piet-scene/src/geometry.rs create mode 100644 piet-scene/src/lib.rs create mode 100644 piet-scene/src/main.rs create mode 100644 piet-scene/src/path.rs create mode 100644 piet-scene/src/resource/mod.rs create mode 100644 piet-scene/src/resource/ramp_cache.rs create mode 100644 piet-scene/src/scene/blend.rs create mode 100644 piet-scene/src/scene/builder.rs create mode 100644 piet-scene/src/scene/mod.rs create mode 100644 piet-scene/src/scene/style.rs diff --git a/Cargo.lock b/Cargo.lock index 737c033..78b6326 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -949,6 +949,14 @@ dependencies = [ "piet-gpu-derive", ] +[[package]] +name = "piet-scene" +version = "0.1.0" +dependencies = [ + "bytemuck", + "smallvec", +] + [[package]] name = "pkg-config" version = "0.3.22" @@ -1139,9 +1147,9 @@ checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" [[package]] name = "smallvec" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" +checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" [[package]] name = "smithay-client-toolkit" diff --git a/Cargo.toml b/Cargo.toml index bfa0030..b94b82b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,5 +5,6 @@ members = [ "piet-gpu-derive", "piet-gpu-hal", "piet-gpu-types", + "piet-scene", "tests" ] diff --git a/piet-gpu-types/src/ptcl.rs b/piet-gpu-types/src/ptcl.rs index e8c29c3..14831ca 100644 --- a/piet-gpu-types/src/ptcl.rs +++ b/piet-gpu-types/src/ptcl.rs @@ -24,6 +24,14 @@ piet_gpu! { line_y: f32, line_c: f32, } + struct CmdRadGrad { + index: u32, + mat: [f32; 4], + xlat: [f32; 2], + c1: [f32; 2], + ra: f32, + roff: f32, + } struct CmdImage { index: u32, offset: [i16; 2], @@ -31,6 +39,9 @@ piet_gpu! { struct CmdAlpha { alpha: f32, } + struct CmdEndClip { + blend: u32, + } struct CmdJump { new_ref: u32, } @@ -42,9 +53,10 @@ piet_gpu! { Alpha(CmdAlpha), Color(CmdColor), LinGrad(CmdLinGrad), + RadGrad(CmdRadGrad), Image(CmdImage), BeginClip, - EndClip, + EndClip(CmdEndClip), Jump(CmdJump), } } diff --git a/piet-gpu/bin/cli.rs b/piet-gpu/bin/cli.rs index abe6ae1..70023af 100644 --- a/piet-gpu/bin/cli.rs +++ b/piet-gpu/bin/cli.rs @@ -6,7 +6,7 @@ use clap::{App, Arg}; use piet_gpu_hal::{BufferUsage, Error, Instance, InstanceFlags, Session}; -use piet_gpu::{test_scenes, PicoSvg, PietGpuRenderContext, Renderer}; +use piet_gpu::{test_scenes, PietGpuRenderContext, Renderer}; const WIDTH: usize = 2048; const HEIGHT: usize = 1536; @@ -243,11 +243,7 @@ fn main() -> Result<(), Error> { if matches.is_present("flip") { scale = -scale; } - let xml_str = std::fs::read_to_string(input).unwrap(); - let start = std::time::Instant::now(); - let svg = PicoSvg::load(&xml_str, scale).unwrap(); - println!("parsing time: {:?}", start.elapsed()); - test_scenes::render_svg(&mut ctx, &svg); + test_scenes::render_svg(&mut ctx, input, scale); } else { test_scenes::render_scene(&mut ctx); } diff --git a/piet-gpu/bin/winit.rs b/piet-gpu/bin/winit.rs index b1db5e0..3ca0742 100644 --- a/piet-gpu/bin/winit.rs +++ b/piet-gpu/bin/winit.rs @@ -2,7 +2,7 @@ use piet::kurbo::Point; use piet::{RenderContext, Text, TextAttribute, TextLayoutBuilder}; use piet_gpu_hal::{CmdBuf, Error, ImageLayout, Instance, Session, SubmittedCmdBuf}; -use piet_gpu::{test_scenes, PicoSvg, PietGpuRenderContext, Renderer}; +use piet_gpu::{test_scenes, PietGpuRenderContext, Renderer}; use clap::{App, Arg}; @@ -29,25 +29,6 @@ fn main() -> Result<(), Error> { ) .get_matches(); - // Collect SVG if input - let svg = match matches.value_of("INPUT") { - Some(file) => { - let mut scale = matches - .value_of("scale") - .map(|scale| scale.parse().unwrap()) - .unwrap_or(8.0); - if matches.is_present("flip") { - scale = -scale; - } - let xml_str = std::fs::read_to_string(file).unwrap(); - let start = std::time::Instant::now(); - let svg = PicoSvg::load(&xml_str, scale).unwrap(); - println!("parsing time: {:?}", start.elapsed()); - Some(svg) - } - None => None, - }; - let event_loop = EventLoop::new(); let window = WindowBuilder::new() .with_inner_size(winit::dpi::LogicalSize { @@ -125,8 +106,15 @@ fn main() -> Result<(), Error> { } let mut ctx = PietGpuRenderContext::new(); - if let Some(svg) = &svg { - test_scenes::render_svg(&mut ctx, svg); + if let Some(input) = matches.value_of("INPUT") { + let mut scale = matches + .value_of("scale") + .map(|scale| scale.parse().unwrap()) + .unwrap_or(8.0); + if matches.is_present("flip") { + scale = -scale; + } + test_scenes::render_svg(&mut ctx, input, scale); } else { use piet_gpu::{Blend, BlendMode::*, CompositionMode::*}; let blends = [ diff --git a/piet-gpu/shader/coarse.comp b/piet-gpu/shader/coarse.comp index 454371c..adbedfd 100644 --- a/piet-gpu/shader/coarse.comp +++ b/piet-gpu/shader/coarse.comp @@ -229,6 +229,7 @@ void main() { case Drawtag_FillColor: case Drawtag_FillImage: case Drawtag_FillLinGradient: + case Drawtag_FillRadGradient: case Drawtag_BeginClip: case Drawtag_EndClip: uint drawmonoid_base = drawmonoid_start + 4 * element_ix; @@ -305,7 +306,7 @@ void main() { is_blend = (blend != BlendComp_default); } include_tile = tile.tile.offset != 0 || (tile.backdrop == 0) == is_clip - || is_blend; + || (is_clip && is_blend); } if (include_tile) { uint el_slice = el_ix / 32; @@ -373,6 +374,25 @@ void main() { Cmd_LinGrad_write(cmd_alloc, cmd_ref, cmd_lin); cmd_ref.offset += 4 + CmdLinGrad_size; break; + case Drawtag_FillRadGradient: + if (!alloc_cmd(cmd_alloc, cmd_ref, cmd_limit)) { + break; + } + linewidth = uintBitsToFloat(memory[di]); + write_fill(cmd_alloc, cmd_ref, tile, linewidth); + CmdRadGrad cmd_rad; + cmd_rad.index = scene[dd]; + // Given that this is basically a memcpy, we might consider + // letting the fine raster read the info itself. + cmd_rad.mat = uintBitsToFloat(uvec4(memory[di + 1], memory[di + 2], + memory[di + 3], memory[di + 4])); + cmd_rad.xlat = uintBitsToFloat(uvec2(memory[di + 5], memory[di + 6])); + cmd_rad.c1 = uintBitsToFloat(uvec2(memory[di + 7], memory[di + 8])); + cmd_rad.ra = uintBitsToFloat(memory[di + 9]); + cmd_rad.roff = uintBitsToFloat(memory[di + 10]); + Cmd_RadGrad_write(cmd_alloc, cmd_ref, cmd_rad); + cmd_ref.offset += 4 + CmdRadGrad_size; + break; case Drawtag_FillImage: linewidth = uintBitsToFloat(memory[di]); if (!alloc_cmd(cmd_alloc, cmd_ref, cmd_limit)) { diff --git a/piet-gpu/shader/draw_leaf.comp b/piet-gpu/shader/draw_leaf.comp index 1cee0ef..ef369c9 100644 --- a/piet-gpu/shader/draw_leaf.comp +++ b/piet-gpu/shader/draw_leaf.comp @@ -94,8 +94,8 @@ void main() { // pipeline. However, going forward we'll get rid of that, and have // later stages read scene + bbox etc. tag_word = scene[drawtag_base + ix + i]; - if (tag_word == Drawtag_FillColor || tag_word == Drawtag_FillLinGradient || tag_word == Drawtag_FillImage || - tag_word == Drawtag_BeginClip) { + if (tag_word == Drawtag_FillColor || tag_word == Drawtag_FillLinGradient || tag_word == Drawtag_FillRadGradient || + tag_word == Drawtag_FillImage || tag_word == Drawtag_BeginClip) { uint bbox_offset = (conf.path_bbox_alloc.offset >> 2) + 6 * m.path_ix; float bbox_l = float(memory[bbox_offset]) - 32768.0; float bbox_t = float(memory[bbox_offset + 1]) - 32768.0; @@ -106,11 +106,11 @@ void main() { uint fill_mode = uint(linewidth >= 0.0); vec4 mat; vec2 translate; - if (linewidth >= 0.0 || tag_word == Drawtag_FillLinGradient) { + if (linewidth >= 0.0 || tag_word == Drawtag_FillLinGradient || tag_word == Drawtag_FillRadGradient) { 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 == Drawtag_FillLinGradient) { + if (tag_word == Drawtag_FillLinGradient || tag_word == Drawtag_FillRadGradient) { translate = uintBitsToFloat(uvec2(memory[t + 4], memory[t + 5])); } } @@ -125,7 +125,6 @@ void main() { break; case Drawtag_FillLinGradient: memory[di] = floatBitsToUint(linewidth); - uint index = scene[dd]; vec2 p0 = uintBitsToFloat(uvec2(scene[dd + 1], scene[dd + 2])); vec2 p1 = uintBitsToFloat(uvec2(scene[dd + 3], scene[dd + 4])); p0 = mat.xy * p0.x + mat.zw * p0.y + translate; @@ -139,6 +138,33 @@ void main() { memory[di + 2] = floatBitsToUint(line_y); memory[di + 3] = floatBitsToUint(line_c); break; + case Drawtag_FillRadGradient: + p0 = uintBitsToFloat(uvec2(scene[dd + 1], scene[dd + 2])); + p1 = uintBitsToFloat(uvec2(scene[dd + 3], scene[dd + 4])); + float r0 = uintBitsToFloat(scene[dd + 5]); + float r1 = uintBitsToFloat(scene[dd + 6]); + float inv_det = 1.0 / (mat.x * mat.w - mat.y * mat.z); + vec4 inv_mat = inv_det * vec4(mat.w, -mat.y, -mat.z, mat.x); + vec2 inv_tr = inv_mat.xz * translate.x + inv_mat.yw * translate.y; + inv_tr += p0; + vec2 center1 = p1 - p0; + float rr = r1 / (r1 - r0); + float rainv = rr / (r1 * r1 - dot(center1, center1)); + vec2 c1 = center1 * rainv; + float ra = rr * rainv; + float roff = rr - 1.0; + memory[di] = floatBitsToUint(linewidth); + memory[di + 1] = floatBitsToUint(inv_mat.x); + memory[di + 2] = floatBitsToUint(inv_mat.y); + memory[di + 3] = floatBitsToUint(inv_mat.z); + memory[di + 4] = floatBitsToUint(inv_mat.w); + memory[di + 5] = floatBitsToUint(inv_tr.x); + memory[di + 6] = floatBitsToUint(inv_tr.y); + memory[di + 7] = floatBitsToUint(c1.x); + memory[di + 8] = floatBitsToUint(c1.y); + memory[di + 9] = floatBitsToUint(ra); + memory[di + 10] = floatBitsToUint(roff); + break; case Drawtag_BeginClip: break; } diff --git a/piet-gpu/shader/drawtag.h b/piet-gpu/shader/drawtag.h index 7f73546..1e35318 100644 --- a/piet-gpu/shader/drawtag.h +++ b/piet-gpu/shader/drawtag.h @@ -4,11 +4,12 @@ // Design of draw tag: & 0x1c gives scene size in bytes // & 1 gives clip -// (tag >> 4) & 0x1c is info size in bytes +// (tag >> 4) & 0x3c is info size in bytes #define Drawtag_Nop 0 #define Drawtag_FillColor 0x44 #define Drawtag_FillLinGradient 0x114 +#define Drawtag_FillRadGradient 0x2dc #define Drawtag_FillImage 0x48 #define Drawtag_BeginClip 0x05 #define Drawtag_EndClip 0x25 @@ -36,5 +37,5 @@ DrawMonoid combine_draw_monoid(DrawMonoid a, DrawMonoid b) { DrawMonoid map_tag(uint tag_word) { // TODO: at some point, EndClip should not generate a path uint has_path = uint(tag_word != Drawtag_Nop); - return DrawMonoid(has_path, tag_word & 1, tag_word & 0x1c, (tag_word >> 4) & 0x1c); + return DrawMonoid(has_path, tag_word & 1, tag_word & 0x1c, (tag_word >> 4) & 0x3c); } diff --git a/piet-gpu/shader/gen/binning.dxil b/piet-gpu/shader/gen/binning.dxil index 3050aa83bdb31b0655c4e6a2c8d80987840b6532..4a4f0734c4735cdf4f37ec0ade7e7e7cacccabbc 100644 GIT binary patch delta 2206 zcmZ8ieNYo;8h4vW=hjc?DaB6R|5NWEwfHF#mI!gc#6)|VMYbiam z2@q2ZHO%4{p1sA=k+!sk)1f%$9|<6bbJ~LE&EOqggXPrg^m<^=n|8F*+m%3XZvV+X z&+qqq{od!@gp47h+EQIq4F2yKQeQ=J)mIlzS6=^paLciKhi*Zop-U0eE^$c_=GJ$i z{%_nzH^%-Lg|#G-KoYfyM;T@SM-6J;#sWNQFq2;ZXxRt_VkHtXim-;`Fl>$*p!gja zWtR=_MjZ~MQELO%Vj=+=wTMTD%`3^Nc}V)dkWZ+z99HiJK*2$*ZMhS?iQpy=nocN!vV5dc~U0Jd{Rtjwi?*}qVv%t%wxw?i;Ake@L=ijPgvdsDhp-T(coi6aXzL;?~PtoY-)gR zPZ(}?z5SW}tUY;Fzw3;C)g)1KI_2H>FXtBy=LPys^_|e**?l~(2)hbsYg^M;#7z@T z#CjvzrWhmqG!ejCTkHNx^|*=lus4j|Ah9eI4AbNkAE!UN>+F_f+Zp}c9&(__`@pdy ztKigs?&oKcy@9zaGaW;BPFydO`PbLKp8INJZGFR`vV-*vP1`*ESkgPkcHWt_pPQ|| zGuy*_Q0#rM^*&be{HfT-C-0XO6lBg^qL6?@SxW-&yl~1YxF$zD#S|_RFLfp1JEWE_ z&;!=h!Hpk(b3e(iDtu-&!h3(lZo)26ap54O42*)RUm(F! zU!QiffygH%+X#036wn%HN7uk(h=q-lR=koNO7rftb}%z6T2%}7RZ6SJgYpk?Opil9 z!OZLSgJZ-SeHu@#G|kxo4IJgn%50q^b(SvUotje0!HPXHjJ%(@S;V=OI+ruckfw-D*cE|@wSdw6&!jU2ZzDV`rVAG()PY4U?fe3$bPJkxm@5&%* z7WYYs8+mHWO7i&24Dwoq2v%4McgC~;4OZb^+ZZzuV5qaUotTS_|Y`i-6{8 z+jcx*rK!Y!JLBk={8?})rpy+MTUb+<%8UcZjAJ1t^O0L4`8837vhv>F0c~X4mW?ap zmwsEE1OFh7uQN5!YeN^vBdk&i1DXPDy@bq;S{)_>$Zh0eRSFlBSW)0`iV~Msx5Izx zB2omk-09lK?BR4IRv10v?|2En>kC7Iw1xF_VmlS3+j?NbvbawzTb@cbjEoB^q)3`% z7l3A@eLGN5jwvy-!>oOwHXbU&O|;516#ogZk8KJ0XsM9V<#XG{;q`F7VWz!o#X%& zb(+(wvt8ZVCr<4?qadAT3a)bM3ZvV%pgXXb&^V_R&k8Cx$F#ba#3B1iYAD{gq{!BN z{hJv7l7Rim`@?XQ^U*{NJh>#Gb#Pjnus6!NoqRw^L^)R`>>I;A{WF!V7Z9L~TkfDH2_05e zRhZwqwvP*F2y{q9dhA!Zpnya~NbYHTiU?l=rBWt*4H$x*^VV8I%*i>MC++DMC74!_H&Ubg+}f46ru)gr zab`RMgnhlN=~MhUbbPuU4Dk89=gCwyMl_?a@pJ>z%ZxMPO6RJR)+EeSE7gk$KQwmR zJbQRgn;zlLX>(nMJpB_xnkYR#r{5u56Q6IpIc<5j*!1-CdZ@E{wI^-$BYmb1UEYv+ z^sTQ-0%_LHerqTDhb6Ic9QU64p580*&w0ViLf=rQCweoasg>P-8|c;~30KPIY2+n1 zIiJ*wz7AvDW*rIjar<@pv>4o-CRt^q01mfhlpoFzhB&$oYO^69#+9a6VOYa+13JTV z2M=j_WL1T8$eXkt6-ZFT-caVFid(lO-tu0RUhflg?6U-kM;JRQ#z+;@r zs|piMNkIl1#_SYgM_!-=+HMhjcuaI2Q3@foCXpE^5eVMfs1VL4i&4ANg`CnRkvz~P xl82v>3q6cK2&oPwm@CLW3vkQ1*X;+ahX zX{u1dt!){wy&zcW6njA}jvYFaK(6MhT*cBGu0vb6<8FFa&jP16(>boaU5WJepWWyA z{hsG}pWpku@A`B6InvVF;*z3!w?2Q$@9B+keEFa~aC&WAI*H;&bHVg;<~M#gcw6;w zn5oFVwusjAZ2z+Fyv1i;jZm#6fXzp{ypslK*rY-Xfbg*4_Z)_J`mjN(d-?Da1C*#x zlnx`nRV2m%6t=K-F$s8KgIF``0Twp2w&htGkYS4oeF{PPu;KSaVE+##AwPzB1Z=iw zmZ($pOXEb9o^E04vme1Fyb22T5+7g0BRyU;EfGq?|7--I3lMn%q1|yne2B~4P5|&z z_8rf!^ca~!tjwlFf@CUs$S3M2!JMnpB)1X-ZywK;z`2X5=!FT3`mHV!K^!Dif;W>1 zLXe80hKt!*GtCYU@+TM?O-1SVEq<4UZ>ZfjG33pl?iGyOoLy}{+P2HtF`U^p%#SOH zVh-lM_DAH_UPSj$cl|1_I7KSGu3kw+kJ#vD;)7UhJ7y;6fXjdd0aot*@Wb(DB1B?- zYTAS}07L>Weoo?tOT;}pFYMw@GEa1gDer?bf^)8MnaVQhh=QV+I#Hk^f!@}3Jc0r?;8NDb& zQLI`tR1LMtDz#R2)KG+?qApQ04#qB0*yzYO<;YZHF*v_FYTwJ*=4hzK8@V6K^t&M* zO%gOzFj-8%KJ5Sw%6zO=AoBl`on3wSL zVSnDzrvE!S<`h1{)Qhui--1XVh~U@za z=}r|D1dtwQM=#}}UFP@|QH9b`16P53@%eK_o9$Pwmt?_Y4%@yWx51F@zwA9ji})}w zXn}Kp6xO2^)?78%+Q>vmqHQ9vDc{=4NnBm)hCl5g5?HnDN%DWwCz6l|w)MsC-#vqW z;SNBov;{xkE$-BY>2>|E`iZ#fox9eHpPme|DkSilgqMMAvU4vk(OU0vnXP)c))Hf= z!t-`Z^2TFsfO>wV-)-Qt8EtNRT?pO*=c^ZjRSTt0U*I*#GNB|SnypMCjRwg-@a0aA zq_9u&ZEKY8mv`W9B9~hrG1^t-EAdIDs_zG@gU+1~$lr+ge6~e;c`Dfv1#}szq_h>%8)u!TjTi>t0GK-W8oCvP#yUKo2;FwBF@47pqm*XYhUEXDdk=f%-7s(VAgk@%(n9Ohg>>fz9a zfaPOL^4KF`&Rl$phzN6TBIcriTlrY!^4~%VNVm``rLiHEEvA7M+xQQE50^oBnG}`kFGO8+|e%%jK`!H+nVhv!m{_^sNoCvaD-c zzBe4GgJMg+)7^H5mz*b*_hnF+2tFaSJaXvjZfz^{pJ@QlC6{A*j4Z)5hqB?`crNNd5}T9X#F0mPIP%0}az001c}!m6$fSxRr~ZLs dmz;qce3!I+Ud+91Ubk4zWz-3S?4Kh1{0|^9yNdt- diff --git a/piet-gpu/shader/gen/coarse.dxil b/piet-gpu/shader/gen/coarse.dxil index 12e88dde300ffb33e17ea6c31c7c14b60812b006..879b7c8390fc9b8adc5e4950306e92c00760dfe2 100644 GIT binary patch delta 8239 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 delta 7124 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 uint(16), raw1 & 65535u, raw1 >> uint(16)); - TileRef _391 = { raw2 }; - s.tiles = _391; + TileRef _409 = { raw2 }; + s.tiles = _409; return s; } @@ -255,11 +270,11 @@ void write_tile_alloc(uint el_ix, Alloc a) Alloc read_tile_alloc(uint el_ix, bool mem_ok) { - uint _741; - _242.GetDimensions(_741); - _741 = (_741 - 8) / 4; + uint _892; + _260.GetDimensions(_892); + _892 = (_892 - 8) / 4; uint param = 0u; - uint param_1 = uint(int(_741) * 4); + uint param_1 = uint(int(_892) * 4); bool param_2 = mem_ok; return new_alloc(param, param_1, param_2); } @@ -273,31 +288,31 @@ Tile Tile_read(Alloc a, TileRef ref) Alloc param_2 = a; uint param_3 = ix + 1u; uint raw1 = read_mem(param_2, param_3); - TileSegRef _416 = { raw0 }; + TileSegRef _434 = { raw0 }; Tile s; - s.tile = _416; + s.tile = _434; s.backdrop = int(raw1); return s; } MallocResult malloc(uint size) { - uint _248; - _242.InterlockedAdd(0, size, _248); - uint offset = _248; - uint _255; - _242.GetDimensions(_255); - _255 = (_255 - 8) / 4; + uint _266; + _260.InterlockedAdd(0, size, _266); + uint offset = _266; + uint _273; + _260.GetDimensions(_273); + _273 = (_273 - 8) / 4; MallocResult r; - r.failed = (offset + size) > uint(int(_255) * 4); + r.failed = (offset + size) > uint(int(_273) * 4); uint param = offset; uint param_1 = size; bool param_2 = !r.failed; r.alloc = new_alloc(param, param_1, param_2); if (r.failed) { - uint _277; - _242.InterlockedMax(4, 1u, _277); + uint _295; + _260.InterlockedMax(4, 1u, _295); return r; } return r; @@ -311,7 +326,7 @@ void write_mem(Alloc alloc, uint offset, uint val) { return; } - _242.Store(offset * 4 + 8, val); + _260.Store(offset * 4 + 8, val); } void CmdJump_write(Alloc a, CmdJumpRef ref, CmdJump s) @@ -327,11 +342,11 @@ void Cmd_Jump_write(Alloc a, CmdRef ref, CmdJump s) { Alloc param = a; uint param_1 = ref.offset >> uint(2); - uint param_2 = 10u; + uint param_2 = 11u; write_mem(param, param_1, param_2); - CmdJumpRef _734 = { ref.offset + 4u }; + CmdJumpRef _885 = { ref.offset + 4u }; Alloc param_3 = a; - CmdJumpRef param_4 = _734; + CmdJumpRef param_4 = _885; CmdJump param_5 = s; CmdJump_write(param_3, param_4, param_5); } @@ -343,22 +358,22 @@ bool alloc_cmd(inout Alloc cmd_alloc, inout CmdRef cmd_ref, inout uint cmd_limit return true; } uint param = 1024u; - MallocResult _762 = malloc(param); - MallocResult new_cmd = _762; + MallocResult _913 = malloc(param); + MallocResult new_cmd = _913; if (new_cmd.failed) { return false; } - CmdJump _772 = { new_cmd.alloc.offset }; - CmdJump jump = _772; + CmdJump _923 = { new_cmd.alloc.offset }; + CmdJump jump = _923; Alloc param_1 = cmd_alloc; CmdRef param_2 = cmd_ref; CmdJump param_3 = jump; Cmd_Jump_write(param_1, param_2, param_3); cmd_alloc = new_cmd.alloc; - CmdRef _784 = { cmd_alloc.offset }; - cmd_ref = _784; - cmd_limit = (cmd_alloc.offset + 1024u) - 60u; + CmdRef _935 = { cmd_alloc.offset }; + cmd_ref = _935; + cmd_limit = (cmd_alloc.offset + 1024u) - 144u; return true; } @@ -381,9 +396,9 @@ void Cmd_Fill_write(Alloc a, CmdRef ref, CmdFill s) uint param_1 = ref.offset >> uint(2); uint param_2 = 1u; write_mem(param, param_1, param_2); - CmdFillRef _604 = { ref.offset + 4u }; + CmdFillRef _742 = { ref.offset + 4u }; Alloc param_3 = a; - CmdFillRef param_4 = _604; + CmdFillRef param_4 = _742; CmdFill param_5 = s; CmdFill_write(param_3, param_4, param_5); } @@ -415,9 +430,9 @@ void Cmd_Stroke_write(Alloc a, CmdRef ref, CmdStroke s) uint param_1 = ref.offset >> uint(2); uint param_2 = 2u; write_mem(param, param_1, param_2); - CmdStrokeRef _622 = { ref.offset + 4u }; + CmdStrokeRef _760 = { ref.offset + 4u }; Alloc param_3 = a; - CmdStrokeRef param_4 = _622; + CmdStrokeRef param_4 = _760; CmdStroke param_5 = s; CmdStroke_write(param_3, param_4, param_5); } @@ -428,8 +443,8 @@ void write_fill(Alloc alloc, inout CmdRef cmd_ref, Tile tile, float linewidth) { if (tile.tile.offset != 0u) { - CmdFill _807 = { tile.tile.offset, tile.backdrop }; - CmdFill cmd_fill = _807; + CmdFill _958 = { tile.tile.offset, tile.backdrop }; + CmdFill cmd_fill = _958; Alloc param = alloc; CmdRef param_1 = cmd_ref; CmdFill param_2 = cmd_fill; @@ -446,8 +461,8 @@ void write_fill(Alloc alloc, inout CmdRef cmd_ref, Tile tile, float linewidth) } else { - CmdStroke _837 = { tile.tile.offset, 0.5f * linewidth }; - CmdStroke cmd_stroke = _837; + CmdStroke _988 = { tile.tile.offset, 0.5f * linewidth }; + CmdStroke cmd_stroke = _988; Alloc param_5 = alloc; CmdRef param_6 = cmd_ref; CmdStroke param_7 = cmd_stroke; @@ -471,9 +486,9 @@ void Cmd_Color_write(Alloc a, CmdRef ref, CmdColor s) uint param_1 = ref.offset >> uint(2); uint param_2 = 5u; write_mem(param, param_1, param_2); - CmdColorRef _649 = { ref.offset + 4u }; + CmdColorRef _786 = { ref.offset + 4u }; Alloc param_3 = a; - CmdColorRef param_4 = _649; + CmdColorRef param_4 = _786; CmdColor param_5 = s; CmdColor_write(param_3, param_4, param_5); } @@ -505,13 +520,75 @@ void Cmd_LinGrad_write(Alloc a, CmdRef ref, CmdLinGrad s) uint param_1 = ref.offset >> uint(2); uint param_2 = 6u; write_mem(param, param_1, param_2); - CmdLinGradRef _668 = { ref.offset + 4u }; + CmdLinGradRef _804 = { ref.offset + 4u }; Alloc param_3 = a; - CmdLinGradRef param_4 = _668; + CmdLinGradRef param_4 = _804; CmdLinGrad param_5 = s; CmdLinGrad_write(param_3, param_4, param_5); } +void CmdRadGrad_write(Alloc a, CmdRadGradRef ref, CmdRadGrad s) +{ + uint ix = ref.offset >> uint(2); + Alloc param = a; + uint param_1 = ix + 0u; + uint param_2 = s.index; + write_mem(param, param_1, param_2); + Alloc param_3 = a; + uint param_4 = ix + 1u; + uint param_5 = asuint(s.mat.x); + write_mem(param_3, param_4, param_5); + Alloc param_6 = a; + uint param_7 = ix + 2u; + uint param_8 = asuint(s.mat.y); + write_mem(param_6, param_7, param_8); + Alloc param_9 = a; + uint param_10 = ix + 3u; + uint param_11 = asuint(s.mat.z); + write_mem(param_9, param_10, param_11); + Alloc param_12 = a; + uint param_13 = ix + 4u; + uint param_14 = asuint(s.mat.w); + write_mem(param_12, param_13, param_14); + Alloc param_15 = a; + uint param_16 = ix + 5u; + uint param_17 = asuint(s.xlat.x); + write_mem(param_15, param_16, param_17); + Alloc param_18 = a; + uint param_19 = ix + 6u; + uint param_20 = asuint(s.xlat.y); + write_mem(param_18, param_19, param_20); + Alloc param_21 = a; + uint param_22 = ix + 7u; + uint param_23 = asuint(s.c1.x); + write_mem(param_21, param_22, param_23); + Alloc param_24 = a; + uint param_25 = ix + 8u; + uint param_26 = asuint(s.c1.y); + write_mem(param_24, param_25, param_26); + Alloc param_27 = a; + uint param_28 = ix + 9u; + uint param_29 = asuint(s.ra); + write_mem(param_27, param_28, param_29); + Alloc param_30 = a; + uint param_31 = ix + 10u; + uint param_32 = asuint(s.roff); + write_mem(param_30, param_31, param_32); +} + +void Cmd_RadGrad_write(Alloc a, CmdRef ref, CmdRadGrad s) +{ + Alloc param = a; + uint param_1 = ref.offset >> uint(2); + uint param_2 = 7u; + write_mem(param, param_1, param_2); + CmdRadGradRef _822 = { ref.offset + 4u }; + Alloc param_3 = a; + CmdRadGradRef param_4 = _822; + CmdRadGrad param_5 = s; + CmdRadGrad_write(param_3, param_4, param_5); +} + void CmdImage_write(Alloc a, CmdImageRef ref, CmdImage s) { uint ix = ref.offset >> uint(2); @@ -529,11 +606,11 @@ void Cmd_Image_write(Alloc a, CmdRef ref, CmdImage s) { Alloc param = a; uint param_1 = ref.offset >> uint(2); - uint param_2 = 7u; + uint param_2 = 8u; write_mem(param, param_1, param_2); - CmdImageRef _687 = { ref.offset + 4u }; + CmdImageRef _840 = { ref.offset + 4u }; Alloc param_3 = a; - CmdImageRef param_4 = _687; + CmdImageRef param_4 = _840; CmdImage param_5 = s; CmdImage_write(param_3, param_4, param_5); } @@ -542,7 +619,7 @@ void Cmd_BeginClip_write(Alloc a, CmdRef ref) { Alloc param = a; uint param_1 = ref.offset >> uint(2); - uint param_2 = 8u; + uint param_2 = 9u; write_mem(param, param_1, param_2); } @@ -559,11 +636,11 @@ void Cmd_EndClip_write(Alloc a, CmdRef ref, CmdEndClip s) { Alloc param = a; uint param_1 = ref.offset >> uint(2); - uint param_2 = 9u; + uint param_2 = 10u; write_mem(param, param_1, param_2); - CmdEndClipRef _715 = { ref.offset + 4u }; + CmdEndClipRef _866 = { ref.offset + 4u }; Alloc param_3 = a; - CmdEndClipRef param_4 = _715; + CmdEndClipRef param_4 = _866; CmdEndClip param_5 = s; CmdEndClip_write(param_3, param_4, param_5); } @@ -578,80 +655,81 @@ void Cmd_End_write(Alloc a, CmdRef ref) void comp_main() { - uint width_in_bins = ((_854.Load(8) + 16u) - 1u) / 16u; + uint width_in_bins = ((_1005.Load(8) + 16u) - 1u) / 16u; uint bin_ix = (width_in_bins * gl_WorkGroupID.y) + gl_WorkGroupID.x; uint partition_ix = 0u; - uint n_partitions = ((_854.Load(0) + 256u) - 1u) / 256u; + uint n_partitions = ((_1005.Load(0) + 256u) - 1u) / 256u; uint th_ix = gl_LocalInvocationID.x; uint bin_tile_x = 16u * gl_WorkGroupID.x; uint bin_tile_y = 16u * gl_WorkGroupID.y; uint tile_x = gl_LocalInvocationID.x % 16u; uint tile_y = gl_LocalInvocationID.x / 16u; - uint this_tile_ix = (((bin_tile_y + tile_y) * _854.Load(8)) + bin_tile_x) + tile_x; - Alloc _919; - _919.offset = _854.Load(24); + uint this_tile_ix = (((bin_tile_y + tile_y) * _1005.Load(8)) + bin_tile_x) + tile_x; + Alloc _1070; + _1070.offset = _1005.Load(24); Alloc param; - param.offset = _919.offset; + param.offset = _1070.offset; uint param_1 = this_tile_ix * 1024u; uint param_2 = 1024u; Alloc cmd_alloc = slice_mem(param, param_1, param_2); - CmdRef _928 = { cmd_alloc.offset }; - CmdRef cmd_ref = _928; - uint cmd_limit = (cmd_ref.offset + 1024u) - 60u; + CmdRef _1079 = { cmd_alloc.offset }; + CmdRef cmd_ref = _1079; + uint cmd_limit = (cmd_ref.offset + 1024u) - 144u; uint clip_depth = 0u; uint clip_zero_depth = 0u; uint rd_ix = 0u; uint wr_ix = 0u; uint part_start_ix = 0u; uint ready_ix = 0u; - uint drawmonoid_start = _854.Load(44) >> uint(2); - uint drawtag_start = _854.Load(100) >> uint(2); - uint drawdata_start = _854.Load(104) >> uint(2); - uint drawinfo_start = _854.Load(68) >> uint(2); - bool mem_ok = _242.Load(4) == 0u; + uint drawmonoid_start = _1005.Load(44) >> uint(2); + uint drawtag_start = _1005.Load(100) >> uint(2); + uint drawdata_start = _1005.Load(104) >> uint(2); + uint drawinfo_start = _1005.Load(68) >> uint(2); + bool mem_ok = _260.Load(4) == 0u; Alloc param_3; Alloc param_5; - uint _1154; + uint _1304; uint element_ix; Alloc param_14; uint tile_count; - uint _1455; + uint _1605; float linewidth; CmdLinGrad cmd_lin; + CmdRadGrad cmd_rad; while (true) { for (uint i = 0u; i < 8u; i++) { sh_bitmaps[i][th_ix] = 0u; } - bool _1206; + bool _1356; for (;;) { if ((ready_ix == wr_ix) && (partition_ix < n_partitions)) { part_start_ix = ready_ix; uint count = 0u; - bool _1003 = th_ix < 256u; - bool _1011; - if (_1003) + bool _1154 = th_ix < 256u; + bool _1162; + if (_1154) { - _1011 = (partition_ix + th_ix) < n_partitions; + _1162 = (partition_ix + th_ix) < n_partitions; } else { - _1011 = _1003; + _1162 = _1154; } - if (_1011) + if (_1162) { - uint in_ix = (_854.Load(20) >> uint(2)) + ((((partition_ix + th_ix) * 256u) + bin_ix) * 2u); - Alloc _1029; - _1029.offset = _854.Load(20); - param_3.offset = _1029.offset; + uint in_ix = (_1005.Load(20) >> uint(2)) + ((((partition_ix + th_ix) * 256u) + bin_ix) * 2u); + Alloc _1179; + _1179.offset = _1005.Load(20); + param_3.offset = _1179.offset; uint param_4 = in_ix; count = read_mem(param_3, param_4); - Alloc _1040; - _1040.offset = _854.Load(20); - param_5.offset = _1040.offset; + Alloc _1190; + _1190.offset = _1005.Load(20); + param_5.offset = _1190.offset; uint param_6 = in_ix + 1u; uint offset = read_mem(param_5, param_6); uint param_7 = offset; @@ -697,16 +775,16 @@ void comp_main() } if (part_ix > 0u) { - _1154 = sh_part_count[part_ix - 1u]; + _1304 = sh_part_count[part_ix - 1u]; } else { - _1154 = part_start_ix; + _1304 = part_start_ix; } - ix -= _1154; + ix -= _1304; Alloc bin_alloc = sh_part_elements[part_ix]; - BinInstanceRef _1173 = { bin_alloc.offset }; - BinInstanceRef inst_ref = _1173; + BinInstanceRef _1323 = { bin_alloc.offset }; + BinInstanceRef inst_ref = _1323; BinInstanceRef param_10 = inst_ref; uint param_11 = ix; Alloc param_12 = bin_alloc; @@ -716,16 +794,16 @@ void comp_main() } GroupMemoryBarrierWithGroupSync(); wr_ix = min((rd_ix + 256u), ready_ix); - bool _1196 = (wr_ix - rd_ix) < 256u; - if (_1196) + bool _1346 = (wr_ix - rd_ix) < 256u; + if (_1346) { - _1206 = (wr_ix < ready_ix) || (partition_ix < n_partitions); + _1356 = (wr_ix < ready_ix) || (partition_ix < n_partitions); } else { - _1206 = _1196; + _1356 = _1346; } - if (_1206) + if (_1356) { continue; } @@ -738,23 +816,24 @@ void comp_main() if ((th_ix + rd_ix) < wr_ix) { element_ix = sh_elements[th_ix]; - tag = _1222.Load((drawtag_start + element_ix) * 4 + 0); + tag = _1372.Load((drawtag_start + element_ix) * 4 + 0); } switch (tag) { case 68u: case 72u: case 276u: + case 732u: case 5u: case 37u: { uint drawmonoid_base = drawmonoid_start + (4u * element_ix); - uint path_ix = _242.Load(drawmonoid_base * 4 + 8); - PathRef _1247 = { _854.Load(16) + (path_ix * 12u) }; - Alloc _1250; - _1250.offset = _854.Load(16); - param_14.offset = _1250.offset; - PathRef param_15 = _1247; + uint path_ix = _260.Load(drawmonoid_base * 4 + 8); + PathRef _1397 = { _1005.Load(16) + (path_ix * 12u) }; + Alloc _1400; + _1400.offset = _1005.Load(16); + param_14.offset = _1400.offset; + PathRef param_15 = _1397; Path path = Path_read(param_14, param_15); uint stride = path.bbox.z - path.bbox.x; sh_tile_stride[th_ix] = stride; @@ -810,16 +889,16 @@ void comp_main() } } uint element_ix_1 = sh_elements[el_ix]; - uint tag_1 = _1222.Load((drawtag_start + element_ix_1) * 4 + 0); + uint tag_1 = _1372.Load((drawtag_start + element_ix_1) * 4 + 0); if (el_ix > 0u) { - _1455 = sh_tile_count[el_ix - 1u]; + _1605 = sh_tile_count[el_ix - 1u]; } else { - _1455 = 0u; + _1605 = 0u; } - uint seq_ix = ix_1 - _1455; + uint seq_ix = ix_1 - _1605; uint width = sh_tile_width[el_ix]; uint x = sh_tile_x0[el_ix] + (seq_ix % width); uint y = sh_tile_y0[el_ix] + (seq_ix / width); @@ -828,38 +907,47 @@ void comp_main() { uint param_21 = el_ix; bool param_22 = mem_ok; - TileRef _1507 = { sh_tile_base[el_ix] + (((sh_tile_stride[el_ix] * y) + x) * 8u) }; + TileRef _1657 = { sh_tile_base[el_ix] + (((sh_tile_stride[el_ix] * y) + x) * 8u) }; Alloc param_23 = read_tile_alloc(param_21, param_22); - TileRef param_24 = _1507; + TileRef param_24 = _1657; Tile tile = Tile_read(param_23, param_24); bool is_clip = (tag_1 & 1u) != 0u; bool is_blend = false; if (is_clip) { uint drawmonoid_base_1 = drawmonoid_start + (4u * element_ix_1); - uint scene_offset = _242.Load((drawmonoid_base_1 + 2u) * 4 + 8); + uint scene_offset = _260.Load((drawmonoid_base_1 + 2u) * 4 + 8); uint dd = drawdata_start + (scene_offset >> uint(2)); - uint blend = _1222.Load(dd * 4 + 0); + uint blend = _1372.Load(dd * 4 + 0); is_blend = blend != 3u; } - bool _1542 = tile.tile.offset != 0u; - bool _1551; - if (!_1542) + bool _1692 = tile.tile.offset != 0u; + bool _1701; + if (!_1692) { - _1551 = (tile.backdrop == 0) == is_clip; + _1701 = (tile.backdrop == 0) == is_clip; } else { - _1551 = _1542; + _1701 = _1692; } - include_tile = _1551 || is_blend; + bool _1708; + if (!_1701) + { + _1708 = is_clip && is_blend; + } + else + { + _1708 = _1701; + } + include_tile = _1708; } if (include_tile) { uint el_slice = el_ix / 32u; uint el_mask = 1u << (el_ix & 31u); - uint _1573; - InterlockedOr(sh_bitmaps[el_slice][(y * 16u) + x], el_mask, _1573); + uint _1728; + InterlockedOr(sh_bitmaps[el_slice][(y * 16u) + x], el_mask, _1728); } } GroupMemoryBarrierWithGroupSync(); @@ -883,33 +971,33 @@ void comp_main() uint element_ref_ix = (slice_ix * 32u) + uint(int(firstbitlow(bitmap))); uint element_ix_2 = sh_elements[element_ref_ix]; bitmap &= (bitmap - 1u); - uint drawtag = _1222.Load((drawtag_start + element_ix_2) * 4 + 0); + uint drawtag = _1372.Load((drawtag_start + element_ix_2) * 4 + 0); if (clip_zero_depth == 0u) { uint param_25 = element_ref_ix; bool param_26 = mem_ok; - TileRef _1650 = { sh_tile_base[element_ref_ix] + (((sh_tile_stride[element_ref_ix] * tile_y) + tile_x) * 8u) }; + TileRef _1805 = { sh_tile_base[element_ref_ix] + (((sh_tile_stride[element_ref_ix] * tile_y) + tile_x) * 8u) }; Alloc param_27 = read_tile_alloc(param_25, param_26); - TileRef param_28 = _1650; + TileRef param_28 = _1805; Tile tile_1 = Tile_read(param_27, param_28); uint drawmonoid_base_2 = drawmonoid_start + (4u * element_ix_2); - uint scene_offset_1 = _242.Load((drawmonoid_base_2 + 2u) * 4 + 8); - uint info_offset = _242.Load((drawmonoid_base_2 + 3u) * 4 + 8); + uint scene_offset_1 = _260.Load((drawmonoid_base_2 + 2u) * 4 + 8); + uint info_offset = _260.Load((drawmonoid_base_2 + 3u) * 4 + 8); uint dd_1 = drawdata_start + (scene_offset_1 >> uint(2)); uint di = drawinfo_start + (info_offset >> uint(2)); switch (drawtag) { case 68u: { - linewidth = asfloat(_242.Load(di * 4 + 8)); + linewidth = asfloat(_260.Load(di * 4 + 8)); Alloc param_29 = cmd_alloc; CmdRef param_30 = cmd_ref; uint param_31 = cmd_limit; - bool _1697 = alloc_cmd(param_29, param_30, param_31); + bool _1853 = alloc_cmd(param_29, param_30, param_31); cmd_alloc = param_29; cmd_ref = param_30; cmd_limit = param_31; - if (!_1697) + if (!_1853) { break; } @@ -919,11 +1007,11 @@ void comp_main() float param_35 = linewidth; write_fill(param_32, param_33, param_34, param_35); cmd_ref = param_33; - uint rgba = _1222.Load(dd_1 * 4 + 0); - CmdColor _1720 = { rgba }; + uint rgba = _1372.Load(dd_1 * 4 + 0); + CmdColor _1876 = { rgba }; Alloc param_36 = cmd_alloc; CmdRef param_37 = cmd_ref; - CmdColor param_38 = _1720; + CmdColor param_38 = _1876; Cmd_Color_write(param_36, param_37, param_38); cmd_ref.offset += 8u; break; @@ -933,25 +1021,25 @@ void comp_main() Alloc param_39 = cmd_alloc; CmdRef param_40 = cmd_ref; uint param_41 = cmd_limit; - bool _1738 = alloc_cmd(param_39, param_40, param_41); + bool _1894 = alloc_cmd(param_39, param_40, param_41); cmd_alloc = param_39; cmd_ref = param_40; cmd_limit = param_41; - if (!_1738) + if (!_1894) { break; } - linewidth = asfloat(_242.Load(di * 4 + 8)); + linewidth = asfloat(_260.Load(di * 4 + 8)); Alloc param_42 = cmd_alloc; CmdRef param_43 = cmd_ref; Tile param_44 = tile_1; float param_45 = linewidth; write_fill(param_42, param_43, param_44, param_45); cmd_ref = param_43; - cmd_lin.index = _1222.Load(dd_1 * 4 + 0); - cmd_lin.line_x = asfloat(_242.Load((di + 1u) * 4 + 8)); - cmd_lin.line_y = asfloat(_242.Load((di + 2u) * 4 + 8)); - cmd_lin.line_c = asfloat(_242.Load((di + 3u) * 4 + 8)); + cmd_lin.index = _1372.Load(dd_1 * 4 + 0); + cmd_lin.line_x = asfloat(_260.Load((di + 1u) * 4 + 8)); + cmd_lin.line_y = asfloat(_260.Load((di + 2u) * 4 + 8)); + cmd_lin.line_c = asfloat(_260.Load((di + 3u) * 4 + 8)); Alloc param_46 = cmd_alloc; CmdRef param_47 = cmd_ref; CmdLinGrad param_48 = cmd_lin; @@ -959,69 +1047,102 @@ void comp_main() cmd_ref.offset += 20u; break; } - case 72u: + case 732u: { - linewidth = asfloat(_242.Load(di * 4 + 8)); Alloc param_49 = cmd_alloc; CmdRef param_50 = cmd_ref; uint param_51 = cmd_limit; - bool _1806 = alloc_cmd(param_49, param_50, param_51); + bool _1958 = alloc_cmd(param_49, param_50, param_51); cmd_alloc = param_49; cmd_ref = param_50; cmd_limit = param_51; - if (!_1806) + if (!_1958) { break; } + linewidth = asfloat(_260.Load(di * 4 + 8)); Alloc param_52 = cmd_alloc; CmdRef param_53 = cmd_ref; Tile param_54 = tile_1; float param_55 = linewidth; write_fill(param_52, param_53, param_54, param_55); cmd_ref = param_53; - uint index = _1222.Load(dd_1 * 4 + 0); - uint raw1 = _1222.Load((dd_1 + 1u) * 4 + 0); - int2 offset_1 = int2(int(raw1 << uint(16)) >> 16, int(raw1) >> 16); - CmdImage _1845 = { index, offset_1 }; + cmd_rad.index = _1372.Load(dd_1 * 4 + 0); + cmd_rad.mat = asfloat(uint4(_260.Load((di + 1u) * 4 + 8), _260.Load((di + 2u) * 4 + 8), _260.Load((di + 3u) * 4 + 8), _260.Load((di + 4u) * 4 + 8))); + cmd_rad.xlat = asfloat(uint2(_260.Load((di + 5u) * 4 + 8), _260.Load((di + 6u) * 4 + 8))); + cmd_rad.c1 = asfloat(uint2(_260.Load((di + 7u) * 4 + 8), _260.Load((di + 8u) * 4 + 8))); + cmd_rad.ra = asfloat(_260.Load((di + 9u) * 4 + 8)); + cmd_rad.roff = asfloat(_260.Load((di + 10u) * 4 + 8)); Alloc param_56 = cmd_alloc; CmdRef param_57 = cmd_ref; - CmdImage param_58 = _1845; - Cmd_Image_write(param_56, param_57, param_58); + CmdRadGrad param_58 = cmd_rad; + Cmd_RadGrad_write(param_56, param_57, param_58); + cmd_ref.offset += 48u; + break; + } + case 72u: + { + linewidth = asfloat(_260.Load(di * 4 + 8)); + Alloc param_59 = cmd_alloc; + CmdRef param_60 = cmd_ref; + uint param_61 = cmd_limit; + bool _2064 = alloc_cmd(param_59, param_60, param_61); + cmd_alloc = param_59; + cmd_ref = param_60; + cmd_limit = param_61; + if (!_2064) + { + break; + } + Alloc param_62 = cmd_alloc; + CmdRef param_63 = cmd_ref; + Tile param_64 = tile_1; + float param_65 = linewidth; + write_fill(param_62, param_63, param_64, param_65); + cmd_ref = param_63; + uint index = _1372.Load(dd_1 * 4 + 0); + uint raw1 = _1372.Load((dd_1 + 1u) * 4 + 0); + int2 offset_1 = int2(int(raw1 << uint(16)) >> 16, int(raw1) >> 16); + CmdImage _2103 = { index, offset_1 }; + Alloc param_66 = cmd_alloc; + CmdRef param_67 = cmd_ref; + CmdImage param_68 = _2103; + Cmd_Image_write(param_66, param_67, param_68); cmd_ref.offset += 12u; break; } case 5u: { - bool _1859 = tile_1.tile.offset == 0u; - bool _1865; - if (_1859) + bool _2117 = tile_1.tile.offset == 0u; + bool _2123; + if (_2117) { - _1865 = tile_1.backdrop == 0; + _2123 = tile_1.backdrop == 0; } else { - _1865 = _1859; + _2123 = _2117; } - if (_1865) + if (_2123) { clip_zero_depth = clip_depth + 1u; } else { - Alloc param_59 = cmd_alloc; - CmdRef param_60 = cmd_ref; - uint param_61 = cmd_limit; - bool _1877 = alloc_cmd(param_59, param_60, param_61); - cmd_alloc = param_59; - cmd_ref = param_60; - cmd_limit = param_61; - if (!_1877) + Alloc param_69 = cmd_alloc; + CmdRef param_70 = cmd_ref; + uint param_71 = cmd_limit; + bool _2135 = alloc_cmd(param_69, param_70, param_71); + cmd_alloc = param_69; + cmd_ref = param_70; + cmd_limit = param_71; + if (!_2135) { break; } - Alloc param_62 = cmd_alloc; - CmdRef param_63 = cmd_ref; - Cmd_BeginClip_write(param_62, param_63); + Alloc param_72 = cmd_alloc; + CmdRef param_73 = cmd_ref; + Cmd_BeginClip_write(param_72, param_73); cmd_ref.offset += 4u; } clip_depth++; @@ -1030,29 +1151,29 @@ void comp_main() case 37u: { clip_depth--; - Alloc param_64 = cmd_alloc; - CmdRef param_65 = cmd_ref; - uint param_66 = cmd_limit; - bool _1905 = alloc_cmd(param_64, param_65, param_66); - cmd_alloc = param_64; - cmd_ref = param_65; - cmd_limit = param_66; - if (!_1905) + Alloc param_74 = cmd_alloc; + CmdRef param_75 = cmd_ref; + uint param_76 = cmd_limit; + bool _2163 = alloc_cmd(param_74, param_75, param_76); + cmd_alloc = param_74; + cmd_ref = param_75; + cmd_limit = param_76; + if (!_2163) { break; } - Alloc param_67 = cmd_alloc; - CmdRef param_68 = cmd_ref; - Tile param_69 = tile_1; - float param_70 = -1.0f; - write_fill(param_67, param_68, param_69, param_70); - cmd_ref = param_68; - uint blend_1 = _1222.Load(dd_1 * 4 + 0); - CmdEndClip _1928 = { blend_1 }; - Alloc param_71 = cmd_alloc; - CmdRef param_72 = cmd_ref; - CmdEndClip param_73 = _1928; - Cmd_EndClip_write(param_71, param_72, param_73); + Alloc param_77 = cmd_alloc; + CmdRef param_78 = cmd_ref; + Tile param_79 = tile_1; + float param_80 = -1.0f; + write_fill(param_77, param_78, param_79, param_80); + cmd_ref = param_78; + uint blend_1 = _1372.Load(dd_1 * 4 + 0); + CmdEndClip _2186 = { blend_1 }; + Alloc param_81 = cmd_alloc; + CmdRef param_82 = cmd_ref; + CmdEndClip param_83 = _2186; + Cmd_EndClip_write(param_81, param_82, param_83); cmd_ref.offset += 8u; break; } @@ -1086,21 +1207,21 @@ void comp_main() break; } } - bool _1975 = (bin_tile_x + tile_x) < _854.Load(8); - bool _1984; - if (_1975) + bool _2233 = (bin_tile_x + tile_x) < _1005.Load(8); + bool _2242; + if (_2233) { - _1984 = (bin_tile_y + tile_y) < _854.Load(12); + _2242 = (bin_tile_y + tile_y) < _1005.Load(12); } else { - _1984 = _1975; + _2242 = _2233; } - if (_1984) + if (_2242) { - Alloc param_74 = cmd_alloc; - CmdRef param_75 = cmd_ref; - Cmd_End_write(param_74, param_75); + Alloc param_84 = cmd_alloc; + CmdRef param_85 = cmd_ref; + Cmd_End_write(param_84, param_85); } } diff --git a/piet-gpu/shader/gen/coarse.msl b/piet-gpu/shader/gen/coarse.msl index 4226352..abd636b 100644 --- a/piet-gpu/shader/gen/coarse.msl +++ b/piet-gpu/shader/gen/coarse.msl @@ -107,6 +107,21 @@ struct CmdLinGrad float line_c; }; +struct CmdRadGradRef +{ + uint offset; +}; + +struct CmdRadGrad +{ + uint index; + float4 mat; + float2 xlat; + float2 c1; + float ra; + float roff; +}; + struct CmdImageRef { uint offset; @@ -211,7 +226,7 @@ bool touch_mem(thread const Alloc& alloc, thread const uint& offset) } static inline __attribute__((always_inline)) -uint read_mem(thread const Alloc& alloc, thread const uint& offset, device Memory& v_242, constant uint& v_242BufferSize) +uint read_mem(thread const Alloc& alloc, thread const uint& offset, device Memory& v_260, constant uint& v_260BufferSize) { Alloc param = alloc; uint param_1 = offset; @@ -219,7 +234,7 @@ uint read_mem(thread const Alloc& alloc, thread const uint& offset, device Memor { return 0u; } - uint v = v_242.memory[offset]; + uint v = v_260.memory[offset]; return v; } @@ -238,30 +253,30 @@ BinInstanceRef BinInstance_index(thread const BinInstanceRef& ref, thread const } static inline __attribute__((always_inline)) -BinInstance BinInstance_read(thread const Alloc& a, thread const BinInstanceRef& ref, device Memory& v_242, constant uint& v_242BufferSize) +BinInstance BinInstance_read(thread const Alloc& a, thread const BinInstanceRef& ref, device Memory& v_260, constant uint& v_260BufferSize) { uint ix = ref.offset >> uint(2); Alloc param = a; uint param_1 = ix + 0u; - uint raw0 = read_mem(param, param_1, v_242, v_242BufferSize); + uint raw0 = read_mem(param, param_1, v_260, v_260BufferSize); BinInstance s; s.element_ix = raw0; return s; } static inline __attribute__((always_inline)) -Path Path_read(thread const Alloc& a, thread const PathRef& ref, device Memory& v_242, constant uint& v_242BufferSize) +Path Path_read(thread const Alloc& a, thread const PathRef& ref, device Memory& v_260, constant uint& v_260BufferSize) { uint ix = ref.offset >> uint(2); Alloc param = a; uint param_1 = ix + 0u; - uint raw0 = read_mem(param, param_1, v_242, v_242BufferSize); + uint raw0 = read_mem(param, param_1, v_260, v_260BufferSize); Alloc param_2 = a; uint param_3 = ix + 1u; - uint raw1 = read_mem(param_2, param_3, v_242, v_242BufferSize); + uint raw1 = read_mem(param_2, param_3, v_260, v_260BufferSize); Alloc param_4 = a; uint param_5 = ix + 2u; - uint raw2 = read_mem(param_4, param_5, v_242, v_242BufferSize); + uint raw2 = read_mem(param_4, param_5, v_260, v_260BufferSize); Path s; s.bbox = uint4(raw0 & 65535u, raw0 >> uint(16), raw1 & 65535u, raw1 >> uint(16)); s.tiles = TileRef{ raw2 }; @@ -274,24 +289,24 @@ void write_tile_alloc(thread const uint& el_ix, thread const Alloc& a) } static inline __attribute__((always_inline)) -Alloc read_tile_alloc(thread const uint& el_ix, thread const bool& mem_ok, device Memory& v_242, constant uint& v_242BufferSize) +Alloc read_tile_alloc(thread const uint& el_ix, thread const bool& mem_ok, device Memory& v_260, constant uint& v_260BufferSize) { uint param = 0u; - uint param_1 = uint(int((v_242BufferSize - 8) / 4) * 4); + uint param_1 = uint(int((v_260BufferSize - 8) / 4) * 4); bool param_2 = mem_ok; return new_alloc(param, param_1, param_2); } static inline __attribute__((always_inline)) -Tile Tile_read(thread const Alloc& a, thread const TileRef& ref, device Memory& v_242, constant uint& v_242BufferSize) +Tile Tile_read(thread const Alloc& a, thread const TileRef& ref, device Memory& v_260, constant uint& v_260BufferSize) { uint ix = ref.offset >> uint(2); Alloc param = a; uint param_1 = ix + 0u; - uint raw0 = read_mem(param, param_1, v_242, v_242BufferSize); + uint raw0 = read_mem(param, param_1, v_260, v_260BufferSize); Alloc param_2 = a; uint param_3 = ix + 1u; - uint raw1 = read_mem(param_2, param_3, v_242, v_242BufferSize); + uint raw1 = read_mem(param_2, param_3, v_260, v_260BufferSize); Tile s; s.tile = TileSegRef{ raw0 }; s.backdrop = int(raw1); @@ -299,26 +314,26 @@ Tile Tile_read(thread const Alloc& a, thread const TileRef& ref, device Memory& } static inline __attribute__((always_inline)) -MallocResult malloc(thread const uint& size, device Memory& v_242, constant uint& v_242BufferSize) +MallocResult malloc(thread const uint& size, device Memory& v_260, constant uint& v_260BufferSize) { - uint _248 = atomic_fetch_add_explicit((device atomic_uint*)&v_242.mem_offset, size, memory_order_relaxed); - uint offset = _248; + uint _266 = atomic_fetch_add_explicit((device atomic_uint*)&v_260.mem_offset, size, memory_order_relaxed); + uint offset = _266; MallocResult r; - r.failed = (offset + size) > uint(int((v_242BufferSize - 8) / 4) * 4); + r.failed = (offset + size) > uint(int((v_260BufferSize - 8) / 4) * 4); uint param = offset; uint param_1 = size; bool param_2 = !r.failed; r.alloc = new_alloc(param, param_1, param_2); if (r.failed) { - uint _277 = atomic_fetch_max_explicit((device atomic_uint*)&v_242.mem_error, 1u, memory_order_relaxed); + uint _295 = atomic_fetch_max_explicit((device atomic_uint*)&v_260.mem_error, 1u, memory_order_relaxed); return r; } return r; } static inline __attribute__((always_inline)) -void write_mem(thread const Alloc& alloc, thread const uint& offset, thread const uint& val, device Memory& v_242, constant uint& v_242BufferSize) +void write_mem(thread const Alloc& alloc, thread const uint& offset, thread const uint& val, device Memory& v_260, constant uint& v_260BufferSize) { Alloc param = alloc; uint param_1 = offset; @@ -326,42 +341,42 @@ void write_mem(thread const Alloc& alloc, thread const uint& offset, thread cons { return; } - v_242.memory[offset] = val; + v_260.memory[offset] = val; } static inline __attribute__((always_inline)) -void CmdJump_write(thread const Alloc& a, thread const CmdJumpRef& ref, thread const CmdJump& s, device Memory& v_242, constant uint& v_242BufferSize) +void CmdJump_write(thread const Alloc& a, thread const CmdJumpRef& ref, thread const CmdJump& s, device Memory& v_260, constant uint& v_260BufferSize) { uint ix = ref.offset >> uint(2); Alloc param = a; uint param_1 = ix + 0u; uint param_2 = s.new_ref; - write_mem(param, param_1, param_2, v_242, v_242BufferSize); + write_mem(param, param_1, param_2, v_260, v_260BufferSize); } static inline __attribute__((always_inline)) -void Cmd_Jump_write(thread const Alloc& a, thread const CmdRef& ref, thread const CmdJump& s, device Memory& v_242, constant uint& v_242BufferSize) +void Cmd_Jump_write(thread const Alloc& a, thread const CmdRef& ref, thread const CmdJump& s, device Memory& v_260, constant uint& v_260BufferSize) { Alloc param = a; uint param_1 = ref.offset >> uint(2); - uint param_2 = 10u; - write_mem(param, param_1, param_2, v_242, v_242BufferSize); + uint param_2 = 11u; + write_mem(param, param_1, param_2, v_260, v_260BufferSize); Alloc param_3 = a; CmdJumpRef param_4 = CmdJumpRef{ ref.offset + 4u }; CmdJump param_5 = s; - CmdJump_write(param_3, param_4, param_5, v_242, v_242BufferSize); + CmdJump_write(param_3, param_4, param_5, v_260, v_260BufferSize); } static inline __attribute__((always_inline)) -bool alloc_cmd(thread Alloc& cmd_alloc, thread CmdRef& cmd_ref, thread uint& cmd_limit, device Memory& v_242, constant uint& v_242BufferSize) +bool alloc_cmd(thread Alloc& cmd_alloc, thread CmdRef& cmd_ref, thread uint& cmd_limit, device Memory& v_260, constant uint& v_260BufferSize) { if (cmd_ref.offset < cmd_limit) { return true; } uint param = 1024u; - MallocResult _762 = malloc(param, v_242, v_242BufferSize); - MallocResult new_cmd = _762; + MallocResult _913 = malloc(param, v_260, v_260BufferSize); + MallocResult new_cmd = _913; if (new_cmd.failed) { return false; @@ -370,78 +385,78 @@ bool alloc_cmd(thread Alloc& cmd_alloc, thread CmdRef& cmd_ref, thread uint& cmd Alloc param_1 = cmd_alloc; CmdRef param_2 = cmd_ref; CmdJump param_3 = jump; - Cmd_Jump_write(param_1, param_2, param_3, v_242, v_242BufferSize); + Cmd_Jump_write(param_1, param_2, param_3, v_260, v_260BufferSize); cmd_alloc = new_cmd.alloc; cmd_ref = CmdRef{ cmd_alloc.offset }; - cmd_limit = (cmd_alloc.offset + 1024u) - 60u; + cmd_limit = (cmd_alloc.offset + 1024u) - 144u; return true; } static inline __attribute__((always_inline)) -void CmdFill_write(thread const Alloc& a, thread const CmdFillRef& ref, thread const CmdFill& s, device Memory& v_242, constant uint& v_242BufferSize) +void CmdFill_write(thread const Alloc& a, thread const CmdFillRef& ref, thread const CmdFill& s, device Memory& v_260, constant uint& v_260BufferSize) { uint ix = ref.offset >> uint(2); Alloc param = a; uint param_1 = ix + 0u; uint param_2 = s.tile_ref; - write_mem(param, param_1, param_2, v_242, v_242BufferSize); + write_mem(param, param_1, param_2, v_260, v_260BufferSize); Alloc param_3 = a; uint param_4 = ix + 1u; uint param_5 = uint(s.backdrop); - write_mem(param_3, param_4, param_5, v_242, v_242BufferSize); + write_mem(param_3, param_4, param_5, v_260, v_260BufferSize); } static inline __attribute__((always_inline)) -void Cmd_Fill_write(thread const Alloc& a, thread const CmdRef& ref, thread const CmdFill& s, device Memory& v_242, constant uint& v_242BufferSize) +void Cmd_Fill_write(thread const Alloc& a, thread const CmdRef& ref, thread const CmdFill& s, device Memory& v_260, constant uint& v_260BufferSize) { Alloc param = a; uint param_1 = ref.offset >> uint(2); uint param_2 = 1u; - write_mem(param, param_1, param_2, v_242, v_242BufferSize); + write_mem(param, param_1, param_2, v_260, v_260BufferSize); Alloc param_3 = a; CmdFillRef param_4 = CmdFillRef{ ref.offset + 4u }; CmdFill param_5 = s; - CmdFill_write(param_3, param_4, param_5, v_242, v_242BufferSize); + CmdFill_write(param_3, param_4, param_5, v_260, v_260BufferSize); } static inline __attribute__((always_inline)) -void Cmd_Solid_write(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_242, constant uint& v_242BufferSize) +void Cmd_Solid_write(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_260, constant uint& v_260BufferSize) { Alloc param = a; uint param_1 = ref.offset >> uint(2); uint param_2 = 3u; - write_mem(param, param_1, param_2, v_242, v_242BufferSize); + write_mem(param, param_1, param_2, v_260, v_260BufferSize); } static inline __attribute__((always_inline)) -void CmdStroke_write(thread const Alloc& a, thread const CmdStrokeRef& ref, thread const CmdStroke& s, device Memory& v_242, constant uint& v_242BufferSize) +void CmdStroke_write(thread const Alloc& a, thread const CmdStrokeRef& ref, thread const CmdStroke& s, device Memory& v_260, constant uint& v_260BufferSize) { uint ix = ref.offset >> uint(2); Alloc param = a; uint param_1 = ix + 0u; uint param_2 = s.tile_ref; - write_mem(param, param_1, param_2, v_242, v_242BufferSize); + write_mem(param, param_1, param_2, v_260, v_260BufferSize); Alloc param_3 = a; uint param_4 = ix + 1u; uint param_5 = as_type(s.half_width); - write_mem(param_3, param_4, param_5, v_242, v_242BufferSize); + write_mem(param_3, param_4, param_5, v_260, v_260BufferSize); } static inline __attribute__((always_inline)) -void Cmd_Stroke_write(thread const Alloc& a, thread const CmdRef& ref, thread const CmdStroke& s, device Memory& v_242, constant uint& v_242BufferSize) +void Cmd_Stroke_write(thread const Alloc& a, thread const CmdRef& ref, thread const CmdStroke& s, device Memory& v_260, constant uint& v_260BufferSize) { Alloc param = a; uint param_1 = ref.offset >> uint(2); uint param_2 = 2u; - write_mem(param, param_1, param_2, v_242, v_242BufferSize); + write_mem(param, param_1, param_2, v_260, v_260BufferSize); Alloc param_3 = a; CmdStrokeRef param_4 = CmdStrokeRef{ ref.offset + 4u }; CmdStroke param_5 = s; - CmdStroke_write(param_3, param_4, param_5, v_242, v_242BufferSize); + CmdStroke_write(param_3, param_4, param_5, v_260, v_260BufferSize); } static inline __attribute__((always_inline)) -void write_fill(thread const Alloc& alloc, thread CmdRef& cmd_ref, thread const Tile& tile, thread const float& linewidth, device Memory& v_242, constant uint& v_242BufferSize) +void write_fill(thread const Alloc& alloc, thread CmdRef& cmd_ref, thread const Tile& tile, thread const float& linewidth, device Memory& v_260, constant uint& v_260BufferSize) { if (linewidth < 0.0) { @@ -451,14 +466,14 @@ void write_fill(thread const Alloc& alloc, thread CmdRef& cmd_ref, thread const Alloc param = alloc; CmdRef param_1 = cmd_ref; CmdFill param_2 = cmd_fill; - Cmd_Fill_write(param, param_1, param_2, v_242, v_242BufferSize); + Cmd_Fill_write(param, param_1, param_2, v_260, v_260BufferSize); cmd_ref.offset += 12u; } else { Alloc param_3 = alloc; CmdRef param_4 = cmd_ref; - Cmd_Solid_write(param_3, param_4, v_242, v_242BufferSize); + Cmd_Solid_write(param_3, param_4, v_260, v_260BufferSize); cmd_ref.offset += 4u; } } @@ -468,138 +483,201 @@ void write_fill(thread const Alloc& alloc, thread CmdRef& cmd_ref, thread const Alloc param_5 = alloc; CmdRef param_6 = cmd_ref; CmdStroke param_7 = cmd_stroke; - Cmd_Stroke_write(param_5, param_6, param_7, v_242, v_242BufferSize); + Cmd_Stroke_write(param_5, param_6, param_7, v_260, v_260BufferSize); cmd_ref.offset += 12u; } } static inline __attribute__((always_inline)) -void CmdColor_write(thread const Alloc& a, thread const CmdColorRef& ref, thread const CmdColor& s, device Memory& v_242, constant uint& v_242BufferSize) +void CmdColor_write(thread const Alloc& a, thread const CmdColorRef& ref, thread const CmdColor& s, device Memory& v_260, constant uint& v_260BufferSize) { uint ix = ref.offset >> uint(2); Alloc param = a; uint param_1 = ix + 0u; uint param_2 = s.rgba_color; - write_mem(param, param_1, param_2, v_242, v_242BufferSize); + write_mem(param, param_1, param_2, v_260, v_260BufferSize); } static inline __attribute__((always_inline)) -void Cmd_Color_write(thread const Alloc& a, thread const CmdRef& ref, thread const CmdColor& s, device Memory& v_242, constant uint& v_242BufferSize) +void Cmd_Color_write(thread const Alloc& a, thread const CmdRef& ref, thread const CmdColor& s, device Memory& v_260, constant uint& v_260BufferSize) { Alloc param = a; uint param_1 = ref.offset >> uint(2); uint param_2 = 5u; - write_mem(param, param_1, param_2, v_242, v_242BufferSize); + write_mem(param, param_1, param_2, v_260, v_260BufferSize); Alloc param_3 = a; CmdColorRef param_4 = CmdColorRef{ ref.offset + 4u }; CmdColor param_5 = s; - CmdColor_write(param_3, param_4, param_5, v_242, v_242BufferSize); + CmdColor_write(param_3, param_4, param_5, v_260, v_260BufferSize); } static inline __attribute__((always_inline)) -void CmdLinGrad_write(thread const Alloc& a, thread const CmdLinGradRef& ref, thread const CmdLinGrad& s, device Memory& v_242, constant uint& v_242BufferSize) +void CmdLinGrad_write(thread const Alloc& a, thread const CmdLinGradRef& ref, thread const CmdLinGrad& s, device Memory& v_260, constant uint& v_260BufferSize) { uint ix = ref.offset >> uint(2); Alloc param = a; uint param_1 = ix + 0u; uint param_2 = s.index; - write_mem(param, param_1, param_2, v_242, v_242BufferSize); + write_mem(param, param_1, param_2, v_260, v_260BufferSize); Alloc param_3 = a; uint param_4 = ix + 1u; uint param_5 = as_type(s.line_x); - write_mem(param_3, param_4, param_5, v_242, v_242BufferSize); + write_mem(param_3, param_4, param_5, v_260, v_260BufferSize); Alloc param_6 = a; uint param_7 = ix + 2u; uint param_8 = as_type(s.line_y); - write_mem(param_6, param_7, param_8, v_242, v_242BufferSize); + write_mem(param_6, param_7, param_8, v_260, v_260BufferSize); Alloc param_9 = a; uint param_10 = ix + 3u; uint param_11 = as_type(s.line_c); - write_mem(param_9, param_10, param_11, v_242, v_242BufferSize); + write_mem(param_9, param_10, param_11, v_260, v_260BufferSize); } static inline __attribute__((always_inline)) -void Cmd_LinGrad_write(thread const Alloc& a, thread const CmdRef& ref, thread const CmdLinGrad& s, device Memory& v_242, constant uint& v_242BufferSize) +void Cmd_LinGrad_write(thread const Alloc& a, thread const CmdRef& ref, thread const CmdLinGrad& s, device Memory& v_260, constant uint& v_260BufferSize) { Alloc param = a; uint param_1 = ref.offset >> uint(2); uint param_2 = 6u; - write_mem(param, param_1, param_2, v_242, v_242BufferSize); + write_mem(param, param_1, param_2, v_260, v_260BufferSize); Alloc param_3 = a; CmdLinGradRef param_4 = CmdLinGradRef{ ref.offset + 4u }; CmdLinGrad param_5 = s; - CmdLinGrad_write(param_3, param_4, param_5, v_242, v_242BufferSize); + CmdLinGrad_write(param_3, param_4, param_5, v_260, v_260BufferSize); } static inline __attribute__((always_inline)) -void CmdImage_write(thread const Alloc& a, thread const CmdImageRef& ref, thread const CmdImage& s, device Memory& v_242, constant uint& v_242BufferSize) +void CmdRadGrad_write(thread const Alloc& a, thread const CmdRadGradRef& ref, thread const CmdRadGrad& s, device Memory& v_260, constant uint& v_260BufferSize) { uint ix = ref.offset >> uint(2); Alloc param = a; uint param_1 = ix + 0u; uint param_2 = s.index; - write_mem(param, param_1, param_2, v_242, v_242BufferSize); + write_mem(param, param_1, param_2, v_260, v_260BufferSize); Alloc param_3 = a; uint param_4 = ix + 1u; - uint param_5 = (uint(s.offset.x) & 65535u) | (uint(s.offset.y) << uint(16)); - write_mem(param_3, param_4, param_5, v_242, v_242BufferSize); + uint param_5 = as_type(s.mat.x); + write_mem(param_3, param_4, param_5, v_260, v_260BufferSize); + Alloc param_6 = a; + uint param_7 = ix + 2u; + uint param_8 = as_type(s.mat.y); + write_mem(param_6, param_7, param_8, v_260, v_260BufferSize); + Alloc param_9 = a; + uint param_10 = ix + 3u; + uint param_11 = as_type(s.mat.z); + write_mem(param_9, param_10, param_11, v_260, v_260BufferSize); + Alloc param_12 = a; + uint param_13 = ix + 4u; + uint param_14 = as_type(s.mat.w); + write_mem(param_12, param_13, param_14, v_260, v_260BufferSize); + Alloc param_15 = a; + uint param_16 = ix + 5u; + uint param_17 = as_type(s.xlat.x); + write_mem(param_15, param_16, param_17, v_260, v_260BufferSize); + Alloc param_18 = a; + uint param_19 = ix + 6u; + uint param_20 = as_type(s.xlat.y); + write_mem(param_18, param_19, param_20, v_260, v_260BufferSize); + Alloc param_21 = a; + uint param_22 = ix + 7u; + uint param_23 = as_type(s.c1.x); + write_mem(param_21, param_22, param_23, v_260, v_260BufferSize); + Alloc param_24 = a; + uint param_25 = ix + 8u; + uint param_26 = as_type(s.c1.y); + write_mem(param_24, param_25, param_26, v_260, v_260BufferSize); + Alloc param_27 = a; + uint param_28 = ix + 9u; + uint param_29 = as_type(s.ra); + write_mem(param_27, param_28, param_29, v_260, v_260BufferSize); + Alloc param_30 = a; + uint param_31 = ix + 10u; + uint param_32 = as_type(s.roff); + write_mem(param_30, param_31, param_32, v_260, v_260BufferSize); } static inline __attribute__((always_inline)) -void Cmd_Image_write(thread const Alloc& a, thread const CmdRef& ref, thread const CmdImage& s, device Memory& v_242, constant uint& v_242BufferSize) +void Cmd_RadGrad_write(thread const Alloc& a, thread const CmdRef& ref, thread const CmdRadGrad& s, device Memory& v_260, constant uint& v_260BufferSize) { Alloc param = a; uint param_1 = ref.offset >> uint(2); uint param_2 = 7u; - write_mem(param, param_1, param_2, v_242, v_242BufferSize); + write_mem(param, param_1, param_2, v_260, v_260BufferSize); Alloc param_3 = a; - CmdImageRef param_4 = CmdImageRef{ ref.offset + 4u }; - CmdImage param_5 = s; - CmdImage_write(param_3, param_4, param_5, v_242, v_242BufferSize); + CmdRadGradRef param_4 = CmdRadGradRef{ ref.offset + 4u }; + CmdRadGrad param_5 = s; + CmdRadGrad_write(param_3, param_4, param_5, v_260, v_260BufferSize); } static inline __attribute__((always_inline)) -void Cmd_BeginClip_write(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_242, constant uint& v_242BufferSize) +void CmdImage_write(thread const Alloc& a, thread const CmdImageRef& ref, thread const CmdImage& s, device Memory& v_260, constant uint& v_260BufferSize) +{ + uint ix = ref.offset >> uint(2); + Alloc param = a; + uint param_1 = ix + 0u; + uint param_2 = s.index; + write_mem(param, param_1, param_2, v_260, v_260BufferSize); + Alloc param_3 = a; + uint param_4 = ix + 1u; + uint param_5 = (uint(s.offset.x) & 65535u) | (uint(s.offset.y) << uint(16)); + write_mem(param_3, param_4, param_5, v_260, v_260BufferSize); +} + +static inline __attribute__((always_inline)) +void Cmd_Image_write(thread const Alloc& a, thread const CmdRef& ref, thread const CmdImage& s, device Memory& v_260, constant uint& v_260BufferSize) { Alloc param = a; uint param_1 = ref.offset >> uint(2); uint param_2 = 8u; - write_mem(param, param_1, param_2, v_242, v_242BufferSize); + write_mem(param, param_1, param_2, v_260, v_260BufferSize); + Alloc param_3 = a; + CmdImageRef param_4 = CmdImageRef{ ref.offset + 4u }; + CmdImage param_5 = s; + CmdImage_write(param_3, param_4, param_5, v_260, v_260BufferSize); } static inline __attribute__((always_inline)) -void CmdEndClip_write(thread const Alloc& a, thread const CmdEndClipRef& ref, thread const CmdEndClip& s, device Memory& v_242, constant uint& v_242BufferSize) +void Cmd_BeginClip_write(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_260, constant uint& v_260BufferSize) +{ + Alloc param = a; + uint param_1 = ref.offset >> uint(2); + uint param_2 = 9u; + write_mem(param, param_1, param_2, v_260, v_260BufferSize); +} + +static inline __attribute__((always_inline)) +void CmdEndClip_write(thread const Alloc& a, thread const CmdEndClipRef& ref, thread const CmdEndClip& s, device Memory& v_260, constant uint& v_260BufferSize) { uint ix = ref.offset >> uint(2); Alloc param = a; uint param_1 = ix + 0u; uint param_2 = s.blend; - write_mem(param, param_1, param_2, v_242, v_242BufferSize); + write_mem(param, param_1, param_2, v_260, v_260BufferSize); } static inline __attribute__((always_inline)) -void Cmd_EndClip_write(thread const Alloc& a, thread const CmdRef& ref, thread const CmdEndClip& s, device Memory& v_242, constant uint& v_242BufferSize) +void Cmd_EndClip_write(thread const Alloc& a, thread const CmdRef& ref, thread const CmdEndClip& s, device Memory& v_260, constant uint& v_260BufferSize) { Alloc param = a; uint param_1 = ref.offset >> uint(2); - uint param_2 = 9u; - write_mem(param, param_1, param_2, v_242, v_242BufferSize); + uint param_2 = 10u; + write_mem(param, param_1, param_2, v_260, v_260BufferSize); Alloc param_3 = a; CmdEndClipRef param_4 = CmdEndClipRef{ ref.offset + 4u }; CmdEndClip param_5 = s; - CmdEndClip_write(param_3, param_4, param_5, v_242, v_242BufferSize); + CmdEndClip_write(param_3, param_4, param_5, v_260, v_260BufferSize); } static inline __attribute__((always_inline)) -void Cmd_End_write(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_242, constant uint& v_242BufferSize) +void Cmd_End_write(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_260, constant uint& v_260BufferSize) { Alloc param = a; uint param_1 = ref.offset >> uint(2); uint param_2 = 0u; - write_mem(param, param_1, param_2, v_242, v_242BufferSize); + write_mem(param, param_1, param_2, v_260, v_260BufferSize); } -kernel void main0(constant uint* spvBufferSizeConstants [[buffer(25)]], device Memory& v_242 [[buffer(0)]], const device ConfigBuf& _854 [[buffer(1)]], const device SceneBuf& _1222 [[buffer(2)]], uint3 gl_WorkGroupID [[threadgroup_position_in_grid]], uint3 gl_LocalInvocationID [[thread_position_in_threadgroup]]) +kernel void main0(constant uint* spvBufferSizeConstants [[buffer(25)]], device Memory& v_260 [[buffer(0)]], const device ConfigBuf& _1005 [[buffer(1)]], const device SceneBuf& _1372 [[buffer(2)]], uint3 gl_WorkGroupID [[threadgroup_position_in_grid]], uint3 gl_LocalInvocationID [[thread_position_in_threadgroup]]) { threadgroup uint sh_bitmaps[8][256]; threadgroup Alloc sh_part_elements[256]; @@ -611,76 +689,77 @@ kernel void main0(constant uint* spvBufferSizeConstants [[buffer(25)]], device M threadgroup uint sh_tile_y0[256]; threadgroup uint sh_tile_base[256]; threadgroup uint sh_tile_count[256]; - constant uint& v_242BufferSize = spvBufferSizeConstants[0]; - uint width_in_bins = ((_854.conf.width_in_tiles + 16u) - 1u) / 16u; + constant uint& v_260BufferSize = spvBufferSizeConstants[0]; + uint width_in_bins = ((_1005.conf.width_in_tiles + 16u) - 1u) / 16u; uint bin_ix = (width_in_bins * gl_WorkGroupID.y) + gl_WorkGroupID.x; uint partition_ix = 0u; - uint n_partitions = ((_854.conf.n_elements + 256u) - 1u) / 256u; + uint n_partitions = ((_1005.conf.n_elements + 256u) - 1u) / 256u; uint th_ix = gl_LocalInvocationID.x; uint bin_tile_x = 16u * gl_WorkGroupID.x; uint bin_tile_y = 16u * gl_WorkGroupID.y; uint tile_x = gl_LocalInvocationID.x % 16u; uint tile_y = gl_LocalInvocationID.x / 16u; - uint this_tile_ix = (((bin_tile_y + tile_y) * _854.conf.width_in_tiles) + bin_tile_x) + tile_x; + uint this_tile_ix = (((bin_tile_y + tile_y) * _1005.conf.width_in_tiles) + bin_tile_x) + tile_x; Alloc param; - param.offset = _854.conf.ptcl_alloc.offset; + param.offset = _1005.conf.ptcl_alloc.offset; uint param_1 = this_tile_ix * 1024u; uint param_2 = 1024u; Alloc cmd_alloc = slice_mem(param, param_1, param_2); CmdRef cmd_ref = CmdRef{ cmd_alloc.offset }; - uint cmd_limit = (cmd_ref.offset + 1024u) - 60u; + uint cmd_limit = (cmd_ref.offset + 1024u) - 144u; uint clip_depth = 0u; uint clip_zero_depth = 0u; uint rd_ix = 0u; uint wr_ix = 0u; uint part_start_ix = 0u; uint ready_ix = 0u; - uint drawmonoid_start = _854.conf.drawmonoid_alloc.offset >> uint(2); - uint drawtag_start = _854.conf.drawtag_offset >> uint(2); - uint drawdata_start = _854.conf.drawdata_offset >> uint(2); - uint drawinfo_start = _854.conf.drawinfo_alloc.offset >> uint(2); - bool mem_ok = v_242.mem_error == 0u; + uint drawmonoid_start = _1005.conf.drawmonoid_alloc.offset >> uint(2); + uint drawtag_start = _1005.conf.drawtag_offset >> uint(2); + uint drawdata_start = _1005.conf.drawdata_offset >> uint(2); + uint drawinfo_start = _1005.conf.drawinfo_alloc.offset >> uint(2); + bool mem_ok = v_260.mem_error == 0u; Alloc param_3; Alloc param_5; - uint _1154; + uint _1304; uint element_ix; Alloc param_14; uint tile_count; - uint _1455; + uint _1605; float linewidth; CmdLinGrad cmd_lin; + CmdRadGrad cmd_rad; while (true) { for (uint i = 0u; i < 8u; i++) { sh_bitmaps[i][th_ix] = 0u; } - bool _1206; + bool _1356; for (;;) { if ((ready_ix == wr_ix) && (partition_ix < n_partitions)) { part_start_ix = ready_ix; uint count = 0u; - bool _1003 = th_ix < 256u; - bool _1011; - if (_1003) + bool _1154 = th_ix < 256u; + bool _1162; + if (_1154) { - _1011 = (partition_ix + th_ix) < n_partitions; + _1162 = (partition_ix + th_ix) < n_partitions; } else { - _1011 = _1003; + _1162 = _1154; } - if (_1011) + if (_1162) { - uint in_ix = (_854.conf.bin_alloc.offset >> uint(2)) + ((((partition_ix + th_ix) * 256u) + bin_ix) * 2u); - param_3.offset = _854.conf.bin_alloc.offset; + uint in_ix = (_1005.conf.bin_alloc.offset >> uint(2)) + ((((partition_ix + th_ix) * 256u) + bin_ix) * 2u); + param_3.offset = _1005.conf.bin_alloc.offset; uint param_4 = in_ix; - count = read_mem(param_3, param_4, v_242, v_242BufferSize); - param_5.offset = _854.conf.bin_alloc.offset; + count = read_mem(param_3, param_4, v_260, v_260BufferSize); + param_5.offset = _1005.conf.bin_alloc.offset; uint param_6 = in_ix + 1u; - uint offset = read_mem(param_5, param_6, v_242, v_242BufferSize); + uint offset = read_mem(param_5, param_6, v_260, v_260BufferSize); uint param_7 = offset; uint param_8 = count * 4u; bool param_9 = mem_ok; @@ -724,34 +803,34 @@ kernel void main0(constant uint* spvBufferSizeConstants [[buffer(25)]], device M } if (part_ix > 0u) { - _1154 = sh_part_count[part_ix - 1u]; + _1304 = sh_part_count[part_ix - 1u]; } else { - _1154 = part_start_ix; + _1304 = part_start_ix; } - ix -= _1154; + ix -= _1304; Alloc bin_alloc = sh_part_elements[part_ix]; BinInstanceRef inst_ref = BinInstanceRef{ bin_alloc.offset }; BinInstanceRef param_10 = inst_ref; uint param_11 = ix; Alloc param_12 = bin_alloc; BinInstanceRef param_13 = BinInstance_index(param_10, param_11); - BinInstance inst = BinInstance_read(param_12, param_13, v_242, v_242BufferSize); + BinInstance inst = BinInstance_read(param_12, param_13, v_260, v_260BufferSize); sh_elements[th_ix] = inst.element_ix; } threadgroup_barrier(mem_flags::mem_threadgroup); wr_ix = min((rd_ix + 256u), ready_ix); - bool _1196 = (wr_ix - rd_ix) < 256u; - if (_1196) + bool _1346 = (wr_ix - rd_ix) < 256u; + if (_1346) { - _1206 = (wr_ix < ready_ix) || (partition_ix < n_partitions); + _1356 = (wr_ix < ready_ix) || (partition_ix < n_partitions); } else { - _1206 = _1196; + _1356 = _1346; } - if (_1206) + if (_1356) { continue; } @@ -764,21 +843,22 @@ kernel void main0(constant uint* spvBufferSizeConstants [[buffer(25)]], device M if ((th_ix + rd_ix) < wr_ix) { element_ix = sh_elements[th_ix]; - tag = _1222.scene[drawtag_start + element_ix]; + tag = _1372.scene[drawtag_start + element_ix]; } switch (tag) { case 68u: case 72u: case 276u: + case 732u: case 5u: case 37u: { uint drawmonoid_base = drawmonoid_start + (4u * element_ix); - uint path_ix = v_242.memory[drawmonoid_base]; - param_14.offset = _854.conf.tile_alloc.offset; - PathRef param_15 = PathRef{ _854.conf.tile_alloc.offset + (path_ix * 12u) }; - Path path = Path_read(param_14, param_15, v_242, v_242BufferSize); + uint path_ix = v_260.memory[drawmonoid_base]; + param_14.offset = _1005.conf.tile_alloc.offset; + PathRef param_15 = PathRef{ _1005.conf.tile_alloc.offset + (path_ix * 12u) }; + Path path = Path_read(param_14, param_15, v_260, v_260BufferSize); uint stride = path.bbox.z - path.bbox.x; sh_tile_stride[th_ix] = stride; int dx = int(path.bbox.x) - int(bin_tile_x); @@ -833,16 +913,16 @@ kernel void main0(constant uint* spvBufferSizeConstants [[buffer(25)]], device M } } uint element_ix_1 = sh_elements[el_ix]; - uint tag_1 = _1222.scene[drawtag_start + element_ix_1]; + uint tag_1 = _1372.scene[drawtag_start + element_ix_1]; if (el_ix > 0u) { - _1455 = sh_tile_count[el_ix - 1u]; + _1605 = sh_tile_count[el_ix - 1u]; } else { - _1455 = 0u; + _1605 = 0u; } - uint seq_ix = ix_1 - _1455; + uint seq_ix = ix_1 - _1605; uint width = sh_tile_width[el_ix]; uint x = sh_tile_x0[el_ix] + (seq_ix % width); uint y = sh_tile_y0[el_ix] + (seq_ix / width); @@ -851,36 +931,45 @@ kernel void main0(constant uint* spvBufferSizeConstants [[buffer(25)]], device M { uint param_21 = el_ix; bool param_22 = mem_ok; - Alloc param_23 = read_tile_alloc(param_21, param_22, v_242, v_242BufferSize); + Alloc param_23 = read_tile_alloc(param_21, param_22, v_260, v_260BufferSize); TileRef param_24 = TileRef{ sh_tile_base[el_ix] + (((sh_tile_stride[el_ix] * y) + x) * 8u) }; - Tile tile = Tile_read(param_23, param_24, v_242, v_242BufferSize); + Tile tile = Tile_read(param_23, param_24, v_260, v_260BufferSize); bool is_clip = (tag_1 & 1u) != 0u; bool is_blend = false; if (is_clip) { uint drawmonoid_base_1 = drawmonoid_start + (4u * element_ix_1); - uint scene_offset = v_242.memory[drawmonoid_base_1 + 2u]; + uint scene_offset = v_260.memory[drawmonoid_base_1 + 2u]; uint dd = drawdata_start + (scene_offset >> uint(2)); - uint blend = _1222.scene[dd]; + uint blend = _1372.scene[dd]; is_blend = blend != 3u; } - bool _1542 = tile.tile.offset != 0u; - bool _1551; - if (!_1542) + bool _1692 = tile.tile.offset != 0u; + bool _1701; + if (!_1692) { - _1551 = (tile.backdrop == 0) == is_clip; + _1701 = (tile.backdrop == 0) == is_clip; } else { - _1551 = _1542; + _1701 = _1692; } - include_tile = _1551 || is_blend; + bool _1708; + if (!_1701) + { + _1708 = is_clip && is_blend; + } + else + { + _1708 = _1701; + } + include_tile = _1708; } if (include_tile) { uint el_slice = el_ix / 32u; uint el_mask = 1u << (el_ix & 31u); - uint _1573 = atomic_fetch_or_explicit((threadgroup atomic_uint*)&sh_bitmaps[el_slice][(y * 16u) + x], el_mask, memory_order_relaxed); + uint _1728 = atomic_fetch_or_explicit((threadgroup atomic_uint*)&sh_bitmaps[el_slice][(y * 16u) + x], el_mask, memory_order_relaxed); } } threadgroup_barrier(mem_flags::mem_threadgroup); @@ -904,32 +993,32 @@ kernel void main0(constant uint* spvBufferSizeConstants [[buffer(25)]], device M uint element_ref_ix = (slice_ix * 32u) + uint(int(spvFindLSB(bitmap))); uint element_ix_2 = sh_elements[element_ref_ix]; bitmap &= (bitmap - 1u); - uint drawtag = _1222.scene[drawtag_start + element_ix_2]; + uint drawtag = _1372.scene[drawtag_start + element_ix_2]; if (clip_zero_depth == 0u) { uint param_25 = element_ref_ix; bool param_26 = mem_ok; - Alloc param_27 = read_tile_alloc(param_25, param_26, v_242, v_242BufferSize); + Alloc param_27 = read_tile_alloc(param_25, param_26, v_260, v_260BufferSize); TileRef param_28 = TileRef{ sh_tile_base[element_ref_ix] + (((sh_tile_stride[element_ref_ix] * tile_y) + tile_x) * 8u) }; - Tile tile_1 = Tile_read(param_27, param_28, v_242, v_242BufferSize); + Tile tile_1 = Tile_read(param_27, param_28, v_260, v_260BufferSize); uint drawmonoid_base_2 = drawmonoid_start + (4u * element_ix_2); - uint scene_offset_1 = v_242.memory[drawmonoid_base_2 + 2u]; - uint info_offset = v_242.memory[drawmonoid_base_2 + 3u]; + uint scene_offset_1 = v_260.memory[drawmonoid_base_2 + 2u]; + uint info_offset = v_260.memory[drawmonoid_base_2 + 3u]; uint dd_1 = drawdata_start + (scene_offset_1 >> uint(2)); uint di = drawinfo_start + (info_offset >> uint(2)); switch (drawtag) { case 68u: { - linewidth = as_type(v_242.memory[di]); + linewidth = as_type(v_260.memory[di]); Alloc param_29 = cmd_alloc; CmdRef param_30 = cmd_ref; uint param_31 = cmd_limit; - bool _1697 = alloc_cmd(param_29, param_30, param_31, v_242, v_242BufferSize); + bool _1853 = alloc_cmd(param_29, param_30, param_31, v_260, v_260BufferSize); cmd_alloc = param_29; cmd_ref = param_30; cmd_limit = param_31; - if (!_1697) + if (!_1853) { break; } @@ -937,13 +1026,13 @@ kernel void main0(constant uint* spvBufferSizeConstants [[buffer(25)]], device M CmdRef param_33 = cmd_ref; Tile param_34 = tile_1; float param_35 = linewidth; - write_fill(param_32, param_33, param_34, param_35, v_242, v_242BufferSize); + write_fill(param_32, param_33, param_34, param_35, v_260, v_260BufferSize); cmd_ref = param_33; - uint rgba = _1222.scene[dd_1]; + uint rgba = _1372.scene[dd_1]; Alloc param_36 = cmd_alloc; CmdRef param_37 = cmd_ref; CmdColor param_38 = CmdColor{ rgba }; - Cmd_Color_write(param_36, param_37, param_38, v_242, v_242BufferSize); + Cmd_Color_write(param_36, param_37, param_38, v_260, v_260BufferSize); cmd_ref.offset += 8u; break; } @@ -952,94 +1041,127 @@ kernel void main0(constant uint* spvBufferSizeConstants [[buffer(25)]], device M Alloc param_39 = cmd_alloc; CmdRef param_40 = cmd_ref; uint param_41 = cmd_limit; - bool _1738 = alloc_cmd(param_39, param_40, param_41, v_242, v_242BufferSize); + bool _1894 = alloc_cmd(param_39, param_40, param_41, v_260, v_260BufferSize); cmd_alloc = param_39; cmd_ref = param_40; cmd_limit = param_41; - if (!_1738) + if (!_1894) { break; } - linewidth = as_type(v_242.memory[di]); + linewidth = as_type(v_260.memory[di]); Alloc param_42 = cmd_alloc; CmdRef param_43 = cmd_ref; Tile param_44 = tile_1; float param_45 = linewidth; - write_fill(param_42, param_43, param_44, param_45, v_242, v_242BufferSize); + write_fill(param_42, param_43, param_44, param_45, v_260, v_260BufferSize); cmd_ref = param_43; - cmd_lin.index = _1222.scene[dd_1]; - cmd_lin.line_x = as_type(v_242.memory[di + 1u]); - cmd_lin.line_y = as_type(v_242.memory[di + 2u]); - cmd_lin.line_c = as_type(v_242.memory[di + 3u]); + cmd_lin.index = _1372.scene[dd_1]; + cmd_lin.line_x = as_type(v_260.memory[di + 1u]); + cmd_lin.line_y = as_type(v_260.memory[di + 2u]); + cmd_lin.line_c = as_type(v_260.memory[di + 3u]); Alloc param_46 = cmd_alloc; CmdRef param_47 = cmd_ref; CmdLinGrad param_48 = cmd_lin; - Cmd_LinGrad_write(param_46, param_47, param_48, v_242, v_242BufferSize); + Cmd_LinGrad_write(param_46, param_47, param_48, v_260, v_260BufferSize); cmd_ref.offset += 20u; break; } - case 72u: + case 732u: { - linewidth = as_type(v_242.memory[di]); Alloc param_49 = cmd_alloc; CmdRef param_50 = cmd_ref; uint param_51 = cmd_limit; - bool _1806 = alloc_cmd(param_49, param_50, param_51, v_242, v_242BufferSize); + bool _1958 = alloc_cmd(param_49, param_50, param_51, v_260, v_260BufferSize); cmd_alloc = param_49; cmd_ref = param_50; cmd_limit = param_51; - if (!_1806) + if (!_1958) { break; } + linewidth = as_type(v_260.memory[di]); Alloc param_52 = cmd_alloc; CmdRef param_53 = cmd_ref; Tile param_54 = tile_1; float param_55 = linewidth; - write_fill(param_52, param_53, param_54, param_55, v_242, v_242BufferSize); + write_fill(param_52, param_53, param_54, param_55, v_260, v_260BufferSize); cmd_ref = param_53; - uint index = _1222.scene[dd_1]; - uint raw1 = _1222.scene[dd_1 + 1u]; - int2 offset_1 = int2(int(raw1 << uint(16)) >> 16, int(raw1) >> 16); + cmd_rad.index = _1372.scene[dd_1]; + cmd_rad.mat = as_type(uint4(v_260.memory[di + 1u], v_260.memory[di + 2u], v_260.memory[di + 3u], v_260.memory[di + 4u])); + cmd_rad.xlat = as_type(uint2(v_260.memory[di + 5u], v_260.memory[di + 6u])); + cmd_rad.c1 = as_type(uint2(v_260.memory[di + 7u], v_260.memory[di + 8u])); + cmd_rad.ra = as_type(v_260.memory[di + 9u]); + cmd_rad.roff = as_type(v_260.memory[di + 10u]); Alloc param_56 = cmd_alloc; CmdRef param_57 = cmd_ref; - CmdImage param_58 = CmdImage{ index, offset_1 }; - Cmd_Image_write(param_56, param_57, param_58, v_242, v_242BufferSize); + CmdRadGrad param_58 = cmd_rad; + Cmd_RadGrad_write(param_56, param_57, param_58, v_260, v_260BufferSize); + cmd_ref.offset += 48u; + break; + } + case 72u: + { + linewidth = as_type(v_260.memory[di]); + Alloc param_59 = cmd_alloc; + CmdRef param_60 = cmd_ref; + uint param_61 = cmd_limit; + bool _2064 = alloc_cmd(param_59, param_60, param_61, v_260, v_260BufferSize); + cmd_alloc = param_59; + cmd_ref = param_60; + cmd_limit = param_61; + if (!_2064) + { + break; + } + Alloc param_62 = cmd_alloc; + CmdRef param_63 = cmd_ref; + Tile param_64 = tile_1; + float param_65 = linewidth; + write_fill(param_62, param_63, param_64, param_65, v_260, v_260BufferSize); + cmd_ref = param_63; + uint index = _1372.scene[dd_1]; + uint raw1 = _1372.scene[dd_1 + 1u]; + int2 offset_1 = int2(int(raw1 << uint(16)) >> 16, int(raw1) >> 16); + Alloc param_66 = cmd_alloc; + CmdRef param_67 = cmd_ref; + CmdImage param_68 = CmdImage{ index, offset_1 }; + Cmd_Image_write(param_66, param_67, param_68, v_260, v_260BufferSize); cmd_ref.offset += 12u; break; } case 5u: { - bool _1859 = tile_1.tile.offset == 0u; - bool _1865; - if (_1859) + bool _2117 = tile_1.tile.offset == 0u; + bool _2123; + if (_2117) { - _1865 = tile_1.backdrop == 0; + _2123 = tile_1.backdrop == 0; } else { - _1865 = _1859; + _2123 = _2117; } - if (_1865) + if (_2123) { clip_zero_depth = clip_depth + 1u; } else { - Alloc param_59 = cmd_alloc; - CmdRef param_60 = cmd_ref; - uint param_61 = cmd_limit; - bool _1877 = alloc_cmd(param_59, param_60, param_61, v_242, v_242BufferSize); - cmd_alloc = param_59; - cmd_ref = param_60; - cmd_limit = param_61; - if (!_1877) + Alloc param_69 = cmd_alloc; + CmdRef param_70 = cmd_ref; + uint param_71 = cmd_limit; + bool _2135 = alloc_cmd(param_69, param_70, param_71, v_260, v_260BufferSize); + cmd_alloc = param_69; + cmd_ref = param_70; + cmd_limit = param_71; + if (!_2135) { break; } - Alloc param_62 = cmd_alloc; - CmdRef param_63 = cmd_ref; - Cmd_BeginClip_write(param_62, param_63, v_242, v_242BufferSize); + Alloc param_72 = cmd_alloc; + CmdRef param_73 = cmd_ref; + Cmd_BeginClip_write(param_72, param_73, v_260, v_260BufferSize); cmd_ref.offset += 4u; } clip_depth++; @@ -1048,28 +1170,28 @@ kernel void main0(constant uint* spvBufferSizeConstants [[buffer(25)]], device M case 37u: { clip_depth--; - Alloc param_64 = cmd_alloc; - CmdRef param_65 = cmd_ref; - uint param_66 = cmd_limit; - bool _1905 = alloc_cmd(param_64, param_65, param_66, v_242, v_242BufferSize); - cmd_alloc = param_64; - cmd_ref = param_65; - cmd_limit = param_66; - if (!_1905) + Alloc param_74 = cmd_alloc; + CmdRef param_75 = cmd_ref; + uint param_76 = cmd_limit; + bool _2163 = alloc_cmd(param_74, param_75, param_76, v_260, v_260BufferSize); + cmd_alloc = param_74; + cmd_ref = param_75; + cmd_limit = param_76; + if (!_2163) { break; } - Alloc param_67 = cmd_alloc; - CmdRef param_68 = cmd_ref; - Tile param_69 = tile_1; - float param_70 = -1.0; - write_fill(param_67, param_68, param_69, param_70, v_242, v_242BufferSize); - cmd_ref = param_68; - uint blend_1 = _1222.scene[dd_1]; - Alloc param_71 = cmd_alloc; - CmdRef param_72 = cmd_ref; - CmdEndClip param_73 = CmdEndClip{ blend_1 }; - Cmd_EndClip_write(param_71, param_72, param_73, v_242, v_242BufferSize); + Alloc param_77 = cmd_alloc; + CmdRef param_78 = cmd_ref; + Tile param_79 = tile_1; + float param_80 = -1.0; + write_fill(param_77, param_78, param_79, param_80, v_260, v_260BufferSize); + cmd_ref = param_78; + uint blend_1 = _1372.scene[dd_1]; + Alloc param_81 = cmd_alloc; + CmdRef param_82 = cmd_ref; + CmdEndClip param_83 = CmdEndClip{ blend_1 }; + Cmd_EndClip_write(param_81, param_82, param_83, v_260, v_260BufferSize); cmd_ref.offset += 8u; break; } @@ -1103,21 +1225,21 @@ kernel void main0(constant uint* spvBufferSizeConstants [[buffer(25)]], device M break; } } - bool _1975 = (bin_tile_x + tile_x) < _854.conf.width_in_tiles; - bool _1984; - if (_1975) + bool _2233 = (bin_tile_x + tile_x) < _1005.conf.width_in_tiles; + bool _2242; + if (_2233) { - _1984 = (bin_tile_y + tile_y) < _854.conf.height_in_tiles; + _2242 = (bin_tile_y + tile_y) < _1005.conf.height_in_tiles; } else { - _1984 = _1975; + _2242 = _2233; } - if (_1984) + if (_2242) { - Alloc param_74 = cmd_alloc; - CmdRef param_75 = cmd_ref; - Cmd_End_write(param_74, param_75, v_242, v_242BufferSize); + Alloc param_84 = cmd_alloc; + CmdRef param_85 = cmd_ref; + Cmd_End_write(param_84, param_85, v_260, v_260BufferSize); } } diff --git a/piet-gpu/shader/gen/coarse.spv b/piet-gpu/shader/gen/coarse.spv index b85fd8cd546262ba315eca88fc6be6357bb82392..fdc10a08e6089784d240cac387f52eef71f95253 100644 GIT binary patch literal 58964 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

%@;%E^{BJKyBd7@2A{FPXKL^{8how>pS!^q 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

VEY4F1u{O|@pw!x2Y@Dm#R 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 E5B6kiRsaA1 diff --git a/piet-gpu/shader/gen/draw_leaf.dxil b/piet-gpu/shader/gen/draw_leaf.dxil index 77396c1d0bfd610df15affb66d2501573c7ca0d8..6353f1986811fff190667a153540dfa7eb872b0f 100644 GIT binary patch literal 6760 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 Y%-==Ge;V|mUJZqmh1>4%IXv0^4ru(<)Bpeg delta 3915 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 P0HdNf%R>LB%w7Kl+8#4O diff --git a/piet-gpu/shader/gen/draw_leaf.hlsl b/piet-gpu/shader/gen/draw_leaf.hlsl index f812f52..734d21e 100644 --- a/piet-gpu/shader/gen/draw_leaf.hlsl +++ b/piet-gpu/shader/gen/draw_leaf.hlsl @@ -46,10 +46,10 @@ static const uint3 gl_WorkGroupSize = uint3(256u, 1u, 1u); static const DrawMonoid _23 = { 0u, 0u, 0u, 0u }; -ByteAddressBuffer _92 : register(t1, space0); -ByteAddressBuffer _102 : register(t2, space0); -ByteAddressBuffer _202 : register(t3, space0); -RWByteAddressBuffer _284 : register(u0, space0); +ByteAddressBuffer _93 : register(t1, space0); +ByteAddressBuffer _103 : register(t2, space0); +ByteAddressBuffer _203 : register(t3, space0); +RWByteAddressBuffer _285 : register(u0, space0); static uint3 gl_WorkGroupID; static uint3 gl_LocalInvocationID; @@ -66,8 +66,8 @@ groupshared DrawMonoid sh_scratch[256]; DrawMonoid map_tag(uint tag_word) { uint has_path = uint(tag_word != 0u); - DrawMonoid _75 = { has_path, tag_word & 1u, tag_word & 28u, (tag_word >> uint(4)) & 28u }; - return _75; + DrawMonoid _76 = { has_path, tag_word & 1u, tag_word & 28u, (tag_word >> uint(4)) & 60u }; + return _76; } DrawMonoid combine_draw_monoid(DrawMonoid a, DrawMonoid b) @@ -88,15 +88,15 @@ DrawMonoid draw_monoid_identity() void comp_main() { uint ix = gl_GlobalInvocationID.x * 8u; - uint drawtag_base = _92.Load(100) >> uint(2); - uint tag_word = _102.Load((drawtag_base + ix) * 4 + 0); + uint drawtag_base = _93.Load(100) >> uint(2); + uint tag_word = _103.Load((drawtag_base + ix) * 4 + 0); uint param = tag_word; DrawMonoid agg = map_tag(param); DrawMonoid local[8]; local[0] = agg; for (uint i = 1u; i < 8u; i++) { - tag_word = _102.Load(((drawtag_base + ix) + i) * 4 + 0); + tag_word = _103.Load(((drawtag_base + ix) + i) * 4 + 0); uint param_1 = tag_word; DrawMonoid param_2 = agg; DrawMonoid param_3 = map_tag(param_1); @@ -121,15 +121,15 @@ void comp_main() DrawMonoid row = draw_monoid_identity(); if (gl_WorkGroupID.x > 0u) { - DrawMonoid _208; - _208.path_ix = _202.Load((gl_WorkGroupID.x - 1u) * 16 + 0); - _208.clip_ix = _202.Load((gl_WorkGroupID.x - 1u) * 16 + 4); - _208.scene_offset = _202.Load((gl_WorkGroupID.x - 1u) * 16 + 8); - _208.info_offset = _202.Load((gl_WorkGroupID.x - 1u) * 16 + 12); - row.path_ix = _208.path_ix; - row.clip_ix = _208.clip_ix; - row.scene_offset = _208.scene_offset; - row.info_offset = _208.info_offset; + DrawMonoid _209; + _209.path_ix = _203.Load((gl_WorkGroupID.x - 1u) * 16 + 0); + _209.clip_ix = _203.Load((gl_WorkGroupID.x - 1u) * 16 + 4); + _209.scene_offset = _203.Load((gl_WorkGroupID.x - 1u) * 16 + 8); + _209.info_offset = _203.Load((gl_WorkGroupID.x - 1u) * 16 + 12); + row.path_ix = _209.path_ix; + row.clip_ix = _209.clip_ix; + row.scene_offset = _209.scene_offset; + row.info_offset = _209.info_offset; } if (gl_LocalInvocationID.x > 0u) { @@ -137,13 +137,15 @@ void comp_main() DrawMonoid param_7 = sh_scratch[gl_LocalInvocationID.x - 1u]; row = combine_draw_monoid(param_6, param_7); } - uint drawdata_base = _92.Load(104) >> uint(2); - uint drawinfo_base = _92.Load(68) >> uint(2); + uint drawdata_base = _93.Load(104) >> uint(2); + uint drawinfo_base = _93.Load(68) >> uint(2); uint out_ix = gl_GlobalInvocationID.x * 8u; - uint out_base = (_92.Load(44) >> uint(2)) + (out_ix * 4u); - uint clip_out_base = _92.Load(48) >> uint(2); + uint out_base = (_93.Load(44) >> uint(2)) + (out_ix * 4u); + uint clip_out_base = _93.Load(48) >> uint(2); float4 mat; float2 translate; + float2 p0; + float2 p1; for (uint i_2 = 0u; i_2 < 8u; i_2++) { DrawMonoid m = row; @@ -153,31 +155,31 @@ void comp_main() DrawMonoid param_9 = local[i_2 - 1u]; m = combine_draw_monoid(param_8, param_9); } - _284.Store((out_base + (i_2 * 4u)) * 4 + 8, m.path_ix); - _284.Store(((out_base + (i_2 * 4u)) + 1u) * 4 + 8, m.clip_ix); - _284.Store(((out_base + (i_2 * 4u)) + 2u) * 4 + 8, m.scene_offset); - _284.Store(((out_base + (i_2 * 4u)) + 3u) * 4 + 8, m.info_offset); + _285.Store((out_base + (i_2 * 4u)) * 4 + 8, m.path_ix); + _285.Store(((out_base + (i_2 * 4u)) + 1u) * 4 + 8, m.clip_ix); + _285.Store(((out_base + (i_2 * 4u)) + 2u) * 4 + 8, m.scene_offset); + _285.Store(((out_base + (i_2 * 4u)) + 3u) * 4 + 8, m.info_offset); uint dd = drawdata_base + (m.scene_offset >> uint(2)); uint di = drawinfo_base + (m.info_offset >> uint(2)); - tag_word = _102.Load(((drawtag_base + ix) + i_2) * 4 + 0); - if ((((tag_word == 68u) || (tag_word == 276u)) || (tag_word == 72u)) || (tag_word == 5u)) + tag_word = _103.Load(((drawtag_base + ix) + i_2) * 4 + 0); + if (((((tag_word == 68u) || (tag_word == 276u)) || (tag_word == 732u)) || (tag_word == 72u)) || (tag_word == 5u)) { - uint bbox_offset = (_92.Load(40) >> uint(2)) + (6u * m.path_ix); - float bbox_l = float(_284.Load(bbox_offset * 4 + 8)) - 32768.0f; - float bbox_t = float(_284.Load((bbox_offset + 1u) * 4 + 8)) - 32768.0f; - float bbox_r = float(_284.Load((bbox_offset + 2u) * 4 + 8)) - 32768.0f; - float bbox_b = float(_284.Load((bbox_offset + 3u) * 4 + 8)) - 32768.0f; + uint bbox_offset = (_93.Load(40) >> uint(2)) + (6u * m.path_ix); + float bbox_l = float(_285.Load(bbox_offset * 4 + 8)) - 32768.0f; + float bbox_t = float(_285.Load((bbox_offset + 1u) * 4 + 8)) - 32768.0f; + float bbox_r = float(_285.Load((bbox_offset + 2u) * 4 + 8)) - 32768.0f; + float bbox_b = float(_285.Load((bbox_offset + 3u) * 4 + 8)) - 32768.0f; float4 bbox = float4(bbox_l, bbox_t, bbox_r, bbox_b); - float linewidth = asfloat(_284.Load((bbox_offset + 4u) * 4 + 8)); + float linewidth = asfloat(_285.Load((bbox_offset + 4u) * 4 + 8)); uint fill_mode = uint(linewidth >= 0.0f); - if ((linewidth >= 0.0f) || (tag_word == 276u)) + if (((linewidth >= 0.0f) || (tag_word == 276u)) || (tag_word == 732u)) { - uint trans_ix = _284.Load((bbox_offset + 5u) * 4 + 8); - uint t = (_92.Load(36) >> uint(2)) + (6u * trans_ix); - mat = asfloat(uint4(_284.Load(t * 4 + 8), _284.Load((t + 1u) * 4 + 8), _284.Load((t + 2u) * 4 + 8), _284.Load((t + 3u) * 4 + 8))); - if (tag_word == 276u) + uint trans_ix = _285.Load((bbox_offset + 5u) * 4 + 8); + uint t = (_93.Load(36) >> uint(2)) + (6u * trans_ix); + mat = asfloat(uint4(_285.Load(t * 4 + 8), _285.Load((t + 1u) * 4 + 8), _285.Load((t + 2u) * 4 + 8), _285.Load((t + 3u) * 4 + 8))); + if ((tag_word == 276u) || (tag_word == 732u)) { - translate = asfloat(uint2(_284.Load((t + 4u) * 4 + 8), _284.Load((t + 5u) * 4 + 8))); + translate = asfloat(uint2(_285.Load((t + 4u) * 4 + 8), _285.Load((t + 5u) * 4 + 8))); } } if (linewidth >= 0.0f) @@ -189,15 +191,14 @@ void comp_main() case 68u: case 72u: { - _284.Store(di * 4 + 8, asuint(linewidth)); + _285.Store(di * 4 + 8, asuint(linewidth)); break; } case 276u: { - _284.Store(di * 4 + 8, asuint(linewidth)); - uint index = _102.Load(dd * 4 + 0); - float2 p0 = asfloat(uint2(_102.Load((dd + 1u) * 4 + 0), _102.Load((dd + 2u) * 4 + 0))); - float2 p1 = asfloat(uint2(_102.Load((dd + 3u) * 4 + 0), _102.Load((dd + 4u) * 4 + 0))); + _285.Store(di * 4 + 8, asuint(linewidth)); + p0 = asfloat(uint2(_103.Load((dd + 1u) * 4 + 0), _103.Load((dd + 2u) * 4 + 0))); + p1 = asfloat(uint2(_103.Load((dd + 3u) * 4 + 0), _103.Load((dd + 4u) * 4 + 0))); p0 = ((mat.xy * p0.x) + (mat.zw * p0.y)) + translate; p1 = ((mat.xy * p1.x) + (mat.zw * p1.y)) + translate; float2 dxy = p1 - p0; @@ -205,9 +206,38 @@ void comp_main() float line_x = dxy.x * scale; float line_y = dxy.y * scale; float line_c = -((p0.x * line_x) + (p0.y * line_y)); - _284.Store((di + 1u) * 4 + 8, asuint(line_x)); - _284.Store((di + 2u) * 4 + 8, asuint(line_y)); - _284.Store((di + 3u) * 4 + 8, asuint(line_c)); + _285.Store((di + 1u) * 4 + 8, asuint(line_x)); + _285.Store((di + 2u) * 4 + 8, asuint(line_y)); + _285.Store((di + 3u) * 4 + 8, asuint(line_c)); + break; + } + case 732u: + { + p0 = asfloat(uint2(_103.Load((dd + 1u) * 4 + 0), _103.Load((dd + 2u) * 4 + 0))); + p1 = asfloat(uint2(_103.Load((dd + 3u) * 4 + 0), _103.Load((dd + 4u) * 4 + 0))); + float r0 = asfloat(_103.Load((dd + 5u) * 4 + 0)); + float r1 = asfloat(_103.Load((dd + 6u) * 4 + 0)); + float inv_det = 1.0f / ((mat.x * mat.w) - (mat.y * mat.z)); + float4 inv_mat = float4(mat.w, -mat.y, -mat.z, mat.x) * inv_det; + float2 inv_tr = (inv_mat.xz * translate.x) + (inv_mat.yw * translate.y); + inv_tr += p0; + float2 center1 = p1 - p0; + float rr = r1 / (r1 - r0); + float rainv = rr / ((r1 * r1) - dot(center1, center1)); + float2 c1 = center1 * rainv; + float ra = rr * rainv; + float roff = rr - 1.0f; + _285.Store(di * 4 + 8, asuint(linewidth)); + _285.Store((di + 1u) * 4 + 8, asuint(inv_mat.x)); + _285.Store((di + 2u) * 4 + 8, asuint(inv_mat.y)); + _285.Store((di + 3u) * 4 + 8, asuint(inv_mat.z)); + _285.Store((di + 4u) * 4 + 8, asuint(inv_mat.w)); + _285.Store((di + 5u) * 4 + 8, asuint(inv_tr.x)); + _285.Store((di + 6u) * 4 + 8, asuint(inv_tr.y)); + _285.Store((di + 7u) * 4 + 8, asuint(c1.x)); + _285.Store((di + 8u) * 4 + 8, asuint(c1.y)); + _285.Store((di + 9u) * 4 + 8, asuint(ra)); + _285.Store((di + 10u) * 4 + 8, asuint(roff)); break; } case 5u: @@ -223,7 +253,7 @@ void comp_main() { path_ix = m.path_ix; } - _284.Store((clip_out_base + m.clip_ix) * 4 + 8, path_ix); + _285.Store((clip_out_base + m.clip_ix) * 4 + 8, path_ix); } } } diff --git a/piet-gpu/shader/gen/draw_leaf.msl b/piet-gpu/shader/gen/draw_leaf.msl index a8516ae..c11e21b 100644 --- a/piet-gpu/shader/gen/draw_leaf.msl +++ b/piet-gpu/shader/gen/draw_leaf.msl @@ -124,7 +124,7 @@ static inline __attribute__((always_inline)) DrawMonoid map_tag(thread const uint& tag_word) { uint has_path = uint(tag_word != 0u); - return DrawMonoid{ has_path, tag_word & 1u, tag_word & 28u, (tag_word >> uint(4)) & 28u }; + return DrawMonoid{ has_path, tag_word & 1u, tag_word & 28u, (tag_word >> uint(4)) & 60u }; } static inline __attribute__((always_inline)) @@ -144,19 +144,19 @@ DrawMonoid draw_monoid_identity() return DrawMonoid{ 0u, 0u, 0u, 0u }; } -kernel void main0(device Memory& _284 [[buffer(0)]], const device ConfigBuf& _92 [[buffer(1)]], const device SceneBuf& _102 [[buffer(2)]], const device ParentBuf& _202 [[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& _285 [[buffer(0)]], const device ConfigBuf& _93 [[buffer(1)]], const device SceneBuf& _103 [[buffer(2)]], const device ParentBuf& _203 [[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[256]; uint ix = gl_GlobalInvocationID.x * 8u; - uint drawtag_base = _92.conf.drawtag_offset >> uint(2); - uint tag_word = _102.scene[drawtag_base + ix]; + uint drawtag_base = _93.conf.drawtag_offset >> uint(2); + uint tag_word = _103.scene[drawtag_base + ix]; uint param = tag_word; DrawMonoid agg = map_tag(param); spvUnsafeArray local; local[0] = agg; for (uint i = 1u; i < 8u; i++) { - tag_word = _102.scene[(drawtag_base + ix) + i]; + tag_word = _103.scene[(drawtag_base + ix) + i]; uint param_1 = tag_word; DrawMonoid param_2 = agg; DrawMonoid param_3 = map_tag(param_1); @@ -181,11 +181,11 @@ kernel void main0(device Memory& _284 [[buffer(0)]], const device ConfigBuf& _92 DrawMonoid row = draw_monoid_identity(); if (gl_WorkGroupID.x > 0u) { - uint _205 = gl_WorkGroupID.x - 1u; - row.path_ix = _202.parent[_205].path_ix; - row.clip_ix = _202.parent[_205].clip_ix; - row.scene_offset = _202.parent[_205].scene_offset; - row.info_offset = _202.parent[_205].info_offset; + uint _206 = gl_WorkGroupID.x - 1u; + row.path_ix = _203.parent[_206].path_ix; + row.clip_ix = _203.parent[_206].clip_ix; + row.scene_offset = _203.parent[_206].scene_offset; + row.info_offset = _203.parent[_206].info_offset; } if (gl_LocalInvocationID.x > 0u) { @@ -193,13 +193,15 @@ kernel void main0(device Memory& _284 [[buffer(0)]], const device ConfigBuf& _92 DrawMonoid param_7 = sh_scratch[gl_LocalInvocationID.x - 1u]; row = combine_draw_monoid(param_6, param_7); } - uint drawdata_base = _92.conf.drawdata_offset >> uint(2); - uint drawinfo_base = _92.conf.drawinfo_alloc.offset >> uint(2); + uint drawdata_base = _93.conf.drawdata_offset >> uint(2); + uint drawinfo_base = _93.conf.drawinfo_alloc.offset >> uint(2); uint out_ix = gl_GlobalInvocationID.x * 8u; - uint out_base = (_92.conf.drawmonoid_alloc.offset >> uint(2)) + (out_ix * 4u); - uint clip_out_base = _92.conf.clip_alloc.offset >> uint(2); + uint out_base = (_93.conf.drawmonoid_alloc.offset >> uint(2)) + (out_ix * 4u); + uint clip_out_base = _93.conf.clip_alloc.offset >> uint(2); float4 mat; float2 translate; + float2 p0; + float2 p1; for (uint i_2 = 0u; i_2 < 8u; i_2++) { DrawMonoid m = row; @@ -209,31 +211,31 @@ kernel void main0(device Memory& _284 [[buffer(0)]], const device ConfigBuf& _92 DrawMonoid param_9 = local[i_2 - 1u]; m = combine_draw_monoid(param_8, param_9); } - _284.memory[out_base + (i_2 * 4u)] = m.path_ix; - _284.memory[(out_base + (i_2 * 4u)) + 1u] = m.clip_ix; - _284.memory[(out_base + (i_2 * 4u)) + 2u] = m.scene_offset; - _284.memory[(out_base + (i_2 * 4u)) + 3u] = m.info_offset; + _285.memory[out_base + (i_2 * 4u)] = m.path_ix; + _285.memory[(out_base + (i_2 * 4u)) + 1u] = m.clip_ix; + _285.memory[(out_base + (i_2 * 4u)) + 2u] = m.scene_offset; + _285.memory[(out_base + (i_2 * 4u)) + 3u] = m.info_offset; uint dd = drawdata_base + (m.scene_offset >> uint(2)); uint di = drawinfo_base + (m.info_offset >> uint(2)); - tag_word = _102.scene[(drawtag_base + ix) + i_2]; - if ((((tag_word == 68u) || (tag_word == 276u)) || (tag_word == 72u)) || (tag_word == 5u)) + tag_word = _103.scene[(drawtag_base + ix) + i_2]; + if (((((tag_word == 68u) || (tag_word == 276u)) || (tag_word == 732u)) || (tag_word == 72u)) || (tag_word == 5u)) { - uint bbox_offset = (_92.conf.path_bbox_alloc.offset >> uint(2)) + (6u * m.path_ix); - float bbox_l = float(_284.memory[bbox_offset]) - 32768.0; - float bbox_t = float(_284.memory[bbox_offset + 1u]) - 32768.0; - float bbox_r = float(_284.memory[bbox_offset + 2u]) - 32768.0; - float bbox_b = float(_284.memory[bbox_offset + 3u]) - 32768.0; + uint bbox_offset = (_93.conf.path_bbox_alloc.offset >> uint(2)) + (6u * m.path_ix); + float bbox_l = float(_285.memory[bbox_offset]) - 32768.0; + float bbox_t = float(_285.memory[bbox_offset + 1u]) - 32768.0; + float bbox_r = float(_285.memory[bbox_offset + 2u]) - 32768.0; + float bbox_b = float(_285.memory[bbox_offset + 3u]) - 32768.0; float4 bbox = float4(bbox_l, bbox_t, bbox_r, bbox_b); - float linewidth = as_type(_284.memory[bbox_offset + 4u]); + float linewidth = as_type(_285.memory[bbox_offset + 4u]); uint fill_mode = uint(linewidth >= 0.0); - if ((linewidth >= 0.0) || (tag_word == 276u)) + if (((linewidth >= 0.0) || (tag_word == 276u)) || (tag_word == 732u)) { - uint trans_ix = _284.memory[bbox_offset + 5u]; - uint t = (_92.conf.trans_alloc.offset >> uint(2)) + (6u * trans_ix); - mat = as_type(uint4(_284.memory[t], _284.memory[t + 1u], _284.memory[t + 2u], _284.memory[t + 3u])); - if (tag_word == 276u) + uint trans_ix = _285.memory[bbox_offset + 5u]; + uint t = (_93.conf.trans_alloc.offset >> uint(2)) + (6u * trans_ix); + mat = as_type(uint4(_285.memory[t], _285.memory[t + 1u], _285.memory[t + 2u], _285.memory[t + 3u])); + if ((tag_word == 276u) || (tag_word == 732u)) { - translate = as_type(uint2(_284.memory[t + 4u], _284.memory[t + 5u])); + translate = as_type(uint2(_285.memory[t + 4u], _285.memory[t + 5u])); } } if (linewidth >= 0.0) @@ -245,15 +247,14 @@ kernel void main0(device Memory& _284 [[buffer(0)]], const device ConfigBuf& _92 case 68u: case 72u: { - _284.memory[di] = as_type(linewidth); + _285.memory[di] = as_type(linewidth); break; } case 276u: { - _284.memory[di] = as_type(linewidth); - uint index = _102.scene[dd]; - float2 p0 = as_type(uint2(_102.scene[dd + 1u], _102.scene[dd + 2u])); - float2 p1 = as_type(uint2(_102.scene[dd + 3u], _102.scene[dd + 4u])); + _285.memory[di] = as_type(linewidth); + p0 = as_type(uint2(_103.scene[dd + 1u], _103.scene[dd + 2u])); + p1 = as_type(uint2(_103.scene[dd + 3u], _103.scene[dd + 4u])); p0 = ((mat.xy * p0.x) + (mat.zw * p0.y)) + translate; p1 = ((mat.xy * p1.x) + (mat.zw * p1.y)) + translate; float2 dxy = p1 - p0; @@ -261,9 +262,38 @@ kernel void main0(device Memory& _284 [[buffer(0)]], const device ConfigBuf& _92 float line_x = dxy.x * scale; float line_y = dxy.y * scale; float line_c = -((p0.x * line_x) + (p0.y * line_y)); - _284.memory[di + 1u] = as_type(line_x); - _284.memory[di + 2u] = as_type(line_y); - _284.memory[di + 3u] = as_type(line_c); + _285.memory[di + 1u] = as_type(line_x); + _285.memory[di + 2u] = as_type(line_y); + _285.memory[di + 3u] = as_type(line_c); + break; + } + case 732u: + { + p0 = as_type(uint2(_103.scene[dd + 1u], _103.scene[dd + 2u])); + p1 = as_type(uint2(_103.scene[dd + 3u], _103.scene[dd + 4u])); + float r0 = as_type(_103.scene[dd + 5u]); + float r1 = as_type(_103.scene[dd + 6u]); + float inv_det = 1.0 / ((mat.x * mat.w) - (mat.y * mat.z)); + float4 inv_mat = float4(mat.w, -mat.y, -mat.z, mat.x) * inv_det; + float2 inv_tr = (inv_mat.xz * translate.x) + (inv_mat.yw * translate.y); + inv_tr += p0; + float2 center1 = p1 - p0; + float rr = r1 / (r1 - r0); + float rainv = rr / ((r1 * r1) - dot(center1, center1)); + float2 c1 = center1 * rainv; + float ra = rr * rainv; + float roff = rr - 1.0; + _285.memory[di] = as_type(linewidth); + _285.memory[di + 1u] = as_type(inv_mat.x); + _285.memory[di + 2u] = as_type(inv_mat.y); + _285.memory[di + 3u] = as_type(inv_mat.z); + _285.memory[di + 4u] = as_type(inv_mat.w); + _285.memory[di + 5u] = as_type(inv_tr.x); + _285.memory[di + 6u] = as_type(inv_tr.y); + _285.memory[di + 7u] = as_type(c1.x); + _285.memory[di + 8u] = as_type(c1.y); + _285.memory[di + 9u] = as_type(ra); + _285.memory[di + 10u] = as_type(roff); break; } case 5u: @@ -279,7 +309,7 @@ kernel void main0(device Memory& _284 [[buffer(0)]], const device ConfigBuf& _92 { path_ix = m.path_ix; } - _284.memory[clip_out_base + m.clip_ix] = path_ix; + _285.memory[clip_out_base + m.clip_ix] = path_ix; } } } diff --git a/piet-gpu/shader/gen/draw_leaf.spv b/piet-gpu/shader/gen/draw_leaf.spv index d18b2877431a9e97c53c8343f35149e714cb73b8..58dde4387fddb65154909ba8a846f351b6115758 100644 GIT binary patch literal 20104 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 diff --git a/piet-gpu/shader/gen/draw_reduce.dxil b/piet-gpu/shader/gen/draw_reduce.dxil index 4df0ec51bdaf0e94f98038ec143b59dbf32c351f..c101fc8c7f1997dba7d8584f3ec61030fb5e0059 100644 GIT binary patch delta 1034 zcmZ8gZ%kWN6hD1^yuQBo=pJj!URRd94yXgMwp*br)}&A*ve>1@uA>Xl*V@&^h?!=Y z8i{@V_f`=|v!Ov^me>7pWPeO&XF_3%rHdq!F(D(dgP@EcOZ0>DlYa1nw=%zYlY4W1 zzkAO)zjJPmY??3`x_Ud^@V})%c;dQ&#+x5S;@~uH?+m1a0x8};d~Y6Ch;0ptb@qoM zTO_hEGx?x<{b@q=M*bjvS-Jn`@WH~hzK?%PeEVVFtJ_YMyLx+G8Y2M&r~)$vP{Dx0 zvnYdz_)d56Cldp(D{muzSE%jQ=XQ?ms=hmNrinUb(tPKweZfnlydr*qPA-$MYJl(e zfi8laKi~k|XBH_>REw`Yu<~kK$D{?*;;@`yX*c6`gBItPGYsu^BHM_o#`$m=S7glO z@HatIgES^d=k^G0Z$H1A1~XaJaqgLx`Tn?kNQ(>OJS<5uqg0J&`&T7wPMo_^nvMLp zdAi%b+3jc~FJ~SW%Aekuzj&+QQFo@z;rA^kgKwQY`tB>(d5z)hT-^~a@Oj^TW5BR7 z$~U>CN4pQV{po+o;cs&^=6*%aqlLvgzjWNXSXi9*sGX2sp=t7Rti?>I%_)$$krec=5DVd%sQjO)(6aIo`Do4#&8m4pf e^a9m7`5%8nGhL(<&$iqw(l^(rJWisa1o#JgZAotc delta 963 zcmZ9KacmP+9LL|?y*u98P7k_nHwJp$CYElgN1f|7nt1EV=myMAY3YcNca5710YZ!> zg_!K_+RmCVT`a#M?13LKt&cm5_a*G*vwt3`o4vgImtd@G z?<_}IA05y|4&~H?kSK3)UcF{K9lihB4!)fd9h5cc~ zhU6JJKLQFDDZ|gm3P*auNr5zH7cBdf8g5S9hR*H6{~{&1T=PzQA9@)hoGke5skQSW zSb(_?n;U~u{2g=eB0P%n<#0b`!kieIN{>(P-2CUS;IK0bu!{g6aN* zXDpXwru$NY>Gm0;%uSymh2AyE<^a@jWkAQp*H2FzTFkW5swlMJ0y@+=BGdz55B~2-1E$N9t=5DDk{rt{6rmxh>IWB#^Lf{ z0N8wRkmst@yiz`ep1ab*d<<-_o)v{Ws3=-FH(>AUnnk9*zy>X=PZ4>Zy04$2^Wr1N z=Kv-1wpza{*%(SLq=0Z7{VLi#pf~y0;KpM{WQmHda|f?85r6pl5VOmV-*%b!sx!k# zWBt62=S)D_Z4sR8jVT%Sc@!1mxr&ryI3}f)w6n5D6Pm?LKNv30v{$PN69{p5Nkya7 z*b@Q)+Y?I04SFKgr%iCuc}4bQ=E10 zU$^djs4upz=x#Wz-V1o{(G6$he{_2rvB4R2Rrjn08on-C{`SAnMr`nNb#2zOrZ>!Q J5+D4bzW{pEE_MI_ diff --git a/piet-gpu/shader/gen/draw_reduce.hlsl b/piet-gpu/shader/gen/draw_reduce.hlsl index 7220b7e..8311155 100644 --- a/piet-gpu/shader/gen/draw_reduce.hlsl +++ b/piet-gpu/shader/gen/draw_reduce.hlsl @@ -44,10 +44,10 @@ struct Config static const uint3 gl_WorkGroupSize = uint3(256u, 1u, 1u); -ByteAddressBuffer _86 : register(t1, space0); -ByteAddressBuffer _96 : register(t2, space0); -RWByteAddressBuffer _187 : register(u3, space0); -RWByteAddressBuffer _205 : register(u0, space0); +ByteAddressBuffer _87 : register(t1, space0); +ByteAddressBuffer _97 : register(t2, space0); +RWByteAddressBuffer _188 : register(u3, space0); +RWByteAddressBuffer _206 : register(u0, space0); static uint3 gl_WorkGroupID; static uint3 gl_LocalInvocationID; @@ -64,8 +64,8 @@ groupshared DrawMonoid sh_scratch[256]; DrawMonoid map_tag(uint tag_word) { uint has_path = uint(tag_word != 0u); - DrawMonoid _69 = { has_path, tag_word & 1u, tag_word & 28u, (tag_word >> uint(4)) & 28u }; - return _69; + DrawMonoid _70 = { has_path, tag_word & 1u, tag_word & 28u, (tag_word >> uint(4)) & 60u }; + return _70; } DrawMonoid combine_draw_monoid(DrawMonoid a, DrawMonoid b) @@ -81,13 +81,13 @@ DrawMonoid combine_draw_monoid(DrawMonoid a, DrawMonoid b) void comp_main() { uint ix = gl_GlobalInvocationID.x * 8u; - uint drawtag_base = _86.Load(100) >> uint(2); - uint tag_word = _96.Load((drawtag_base + ix) * 4 + 0); + uint drawtag_base = _87.Load(100) >> uint(2); + uint tag_word = _97.Load((drawtag_base + ix) * 4 + 0); uint param = tag_word; DrawMonoid agg = map_tag(param); for (uint i = 1u; i < 8u; i++) { - uint tag_word_1 = _96.Load(((drawtag_base + ix) + i) * 4 + 0); + uint tag_word_1 = _97.Load(((drawtag_base + ix) + i) * 4 + 0); uint param_1 = tag_word_1; DrawMonoid param_2 = agg; DrawMonoid param_3 = map_tag(param_1); @@ -109,10 +109,10 @@ void comp_main() } if (gl_LocalInvocationID.x == 0u) { - _187.Store(gl_WorkGroupID.x * 16 + 0, agg.path_ix); - _187.Store(gl_WorkGroupID.x * 16 + 4, agg.clip_ix); - _187.Store(gl_WorkGroupID.x * 16 + 8, agg.scene_offset); - _187.Store(gl_WorkGroupID.x * 16 + 12, agg.info_offset); + _188.Store(gl_WorkGroupID.x * 16 + 0, agg.path_ix); + _188.Store(gl_WorkGroupID.x * 16 + 4, agg.clip_ix); + _188.Store(gl_WorkGroupID.x * 16 + 8, agg.scene_offset); + _188.Store(gl_WorkGroupID.x * 16 + 12, agg.info_offset); } } diff --git a/piet-gpu/shader/gen/draw_reduce.msl b/piet-gpu/shader/gen/draw_reduce.msl index 8e409a8..759267c 100644 --- a/piet-gpu/shader/gen/draw_reduce.msl +++ b/piet-gpu/shader/gen/draw_reduce.msl @@ -85,7 +85,7 @@ static inline __attribute__((always_inline)) DrawMonoid map_tag(thread const uint& tag_word) { uint has_path = uint(tag_word != 0u); - return DrawMonoid{ has_path, tag_word & 1u, tag_word & 28u, (tag_word >> uint(4)) & 28u }; + return DrawMonoid{ has_path, tag_word & 1u, tag_word & 28u, (tag_word >> uint(4)) & 60u }; } static inline __attribute__((always_inline)) @@ -99,17 +99,17 @@ DrawMonoid combine_draw_monoid(thread const DrawMonoid& a, thread const DrawMono return c; } -kernel void main0(const device ConfigBuf& _86 [[buffer(1)]], const device SceneBuf& _96 [[buffer(2)]], device OutBuf& _187 [[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& _87 [[buffer(1)]], const device SceneBuf& _97 [[buffer(2)]], device OutBuf& _188 [[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[256]; uint ix = gl_GlobalInvocationID.x * 8u; - uint drawtag_base = _86.conf.drawtag_offset >> uint(2); - uint tag_word = _96.scene[drawtag_base + ix]; + uint drawtag_base = _87.conf.drawtag_offset >> uint(2); + uint tag_word = _97.scene[drawtag_base + ix]; uint param = tag_word; DrawMonoid agg = map_tag(param); for (uint i = 1u; i < 8u; i++) { - uint tag_word_1 = _96.scene[(drawtag_base + ix) + i]; + uint tag_word_1 = _97.scene[(drawtag_base + ix) + i]; uint param_1 = tag_word_1; DrawMonoid param_2 = agg; DrawMonoid param_3 = map_tag(param_1); @@ -131,10 +131,10 @@ kernel void main0(const device ConfigBuf& _86 [[buffer(1)]], const device SceneB } if (gl_LocalInvocationID.x == 0u) { - _187.outbuf[gl_WorkGroupID.x].path_ix = agg.path_ix; - _187.outbuf[gl_WorkGroupID.x].clip_ix = agg.clip_ix; - _187.outbuf[gl_WorkGroupID.x].scene_offset = agg.scene_offset; - _187.outbuf[gl_WorkGroupID.x].info_offset = agg.info_offset; + _188.outbuf[gl_WorkGroupID.x].path_ix = agg.path_ix; + _188.outbuf[gl_WorkGroupID.x].clip_ix = agg.clip_ix; + _188.outbuf[gl_WorkGroupID.x].scene_offset = agg.scene_offset; + _188.outbuf[gl_WorkGroupID.x].info_offset = agg.info_offset; } } diff --git a/piet-gpu/shader/gen/draw_reduce.spv b/piet-gpu/shader/gen/draw_reduce.spv index 4daf43af5dd87dfacfc4f1c5727b15274bdd4266..d6c6fb75fa1dc5d7d65bfa5c1ab890d474b0ee68 100644 GIT binary patch literal 7140 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 T+~3O~YjWLfkUsWJ+`j!AnWXVL literal 7124 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 O^WF$)W8cK>+kXJO$?lT? diff --git a/piet-gpu/shader/gen/draw_root.dxil b/piet-gpu/shader/gen/draw_root.dxil index 4ea23f7699a63ef9a4dcac871e1f234a5ea5b0ef..873fa29da1ffca54fc149ad5b31f42a47e79f5ba 100644 GIT binary patch delta 859 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 delta 9976 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 diff --git a/piet-gpu/shader/gen/kernel4.hlsl b/piet-gpu/shader/gen/kernel4.hlsl index f17b240..92fe05b 100644 --- a/piet-gpu/shader/gen/kernel4.hlsl +++ b/piet-gpu/shader/gen/kernel4.hlsl @@ -48,6 +48,21 @@ struct CmdLinGrad float line_c; }; +struct CmdRadGradRef +{ + uint offset; +}; + +struct CmdRadGrad +{ + uint index; + float4 mat; + float2 xlat; + float2 c1; + float ra; + float roff; +}; + struct CmdImageRef { uint offset; @@ -146,8 +161,8 @@ struct Config static const uint3 gl_WorkGroupSize = uint3(8u, 4u, 1u); -RWByteAddressBuffer _278 : register(u0, space0); -ByteAddressBuffer _1521 : register(t1, space0); +RWByteAddressBuffer _291 : register(u0, space0); +ByteAddressBuffer _1666 : register(t1, space0); RWTexture2D image_atlas : register(u3, space0); RWTexture2D gradients : register(u4, space0); RWTexture2D image : register(u2, space0); @@ -174,8 +189,8 @@ float4 spvUnpackUnorm4x8(uint value) Alloc slice_mem(Alloc a, uint offset, uint size) { - Alloc _291 = { a.offset + offset }; - return _291; + Alloc _304 = { a.offset + offset }; + return _304; } bool touch_mem(Alloc alloc, uint offset) @@ -191,7 +206,7 @@ uint read_mem(Alloc alloc, uint offset) { return 0u; } - uint v = _278.Load(offset * 4 + 8); + uint v = _291.Load(offset * 4 + 8); return v; } @@ -200,8 +215,8 @@ CmdTag Cmd_tag(Alloc a, CmdRef ref) Alloc param = a; uint param_1 = ref.offset >> uint(2); uint tag_and_flags = read_mem(param, param_1); - CmdTag _525 = { tag_and_flags & 65535u, tag_and_flags >> uint(16) }; - return _525; + CmdTag _663 = { tag_and_flags & 65535u, tag_and_flags >> uint(16) }; + return _663; } CmdStroke CmdStroke_read(Alloc a, CmdStrokeRef ref) @@ -221,9 +236,9 @@ CmdStroke CmdStroke_read(Alloc a, CmdStrokeRef ref) CmdStroke Cmd_Stroke_read(Alloc a, CmdRef ref) { - CmdStrokeRef _542 = { ref.offset + 4u }; + CmdStrokeRef _679 = { ref.offset + 4u }; Alloc param = a; - CmdStrokeRef param_1 = _542; + CmdStrokeRef param_1 = _679; return CmdStroke_read(param, param_1); } @@ -259,8 +274,8 @@ TileSeg TileSeg_read(Alloc a, TileSegRef ref) s.origin = float2(asfloat(raw0), asfloat(raw1)); s._vector = float2(asfloat(raw2), asfloat(raw3)); s.y_edge = asfloat(raw4); - TileSegRef _675 = { raw5 }; - s.next = _675; + TileSegRef _820 = { raw5 }; + s.next = _820; return s; } @@ -286,9 +301,9 @@ CmdFill CmdFill_read(Alloc a, CmdFillRef ref) CmdFill Cmd_Fill_read(Alloc a, CmdRef ref) { - CmdFillRef _532 = { ref.offset + 4u }; + CmdFillRef _669 = { ref.offset + 4u }; Alloc param = a; - CmdFillRef param_1 = _532; + CmdFillRef param_1 = _669; return CmdFill_read(param, param_1); } @@ -305,9 +320,9 @@ CmdAlpha CmdAlpha_read(Alloc a, CmdAlphaRef ref) CmdAlpha Cmd_Alpha_read(Alloc a, CmdRef ref) { - CmdAlphaRef _552 = { ref.offset + 4u }; + CmdAlphaRef _689 = { ref.offset + 4u }; Alloc param = a; - CmdAlphaRef param_1 = _552; + CmdAlphaRef param_1 = _689; return CmdAlpha_read(param, param_1); } @@ -324,9 +339,9 @@ CmdColor CmdColor_read(Alloc a, CmdColorRef ref) CmdColor Cmd_Color_read(Alloc a, CmdRef ref) { - CmdColorRef _562 = { ref.offset + 4u }; + CmdColorRef _699 = { ref.offset + 4u }; Alloc param = a; - CmdColorRef param_1 = _562; + CmdColorRef param_1 = _699; return CmdColor_read(param, param_1); } @@ -370,12 +385,66 @@ CmdLinGrad CmdLinGrad_read(Alloc a, CmdLinGradRef ref) CmdLinGrad Cmd_LinGrad_read(Alloc a, CmdRef ref) { - CmdLinGradRef _572 = { ref.offset + 4u }; + CmdLinGradRef _709 = { ref.offset + 4u }; Alloc param = a; - CmdLinGradRef param_1 = _572; + CmdLinGradRef param_1 = _709; return CmdLinGrad_read(param, param_1); } +CmdRadGrad CmdRadGrad_read(Alloc a, CmdRadGradRef ref) +{ + uint ix = ref.offset >> uint(2); + Alloc param = a; + uint param_1 = ix + 0u; + uint raw0 = read_mem(param, param_1); + Alloc param_2 = a; + uint param_3 = ix + 1u; + uint raw1 = read_mem(param_2, param_3); + Alloc param_4 = a; + uint param_5 = ix + 2u; + uint raw2 = read_mem(param_4, param_5); + Alloc param_6 = a; + uint param_7 = ix + 3u; + uint raw3 = read_mem(param_6, param_7); + Alloc param_8 = a; + uint param_9 = ix + 4u; + uint raw4 = read_mem(param_8, param_9); + Alloc param_10 = a; + uint param_11 = ix + 5u; + uint raw5 = read_mem(param_10, param_11); + Alloc param_12 = a; + uint param_13 = ix + 6u; + uint raw6 = read_mem(param_12, param_13); + Alloc param_14 = a; + uint param_15 = ix + 7u; + uint raw7 = read_mem(param_14, param_15); + Alloc param_16 = a; + uint param_17 = ix + 8u; + uint raw8 = read_mem(param_16, param_17); + Alloc param_18 = a; + uint param_19 = ix + 9u; + uint raw9 = read_mem(param_18, param_19); + Alloc param_20 = a; + uint param_21 = ix + 10u; + uint raw10 = read_mem(param_20, param_21); + CmdRadGrad s; + s.index = raw0; + s.mat = float4(asfloat(raw1), asfloat(raw2), asfloat(raw3), asfloat(raw4)); + s.xlat = float2(asfloat(raw5), asfloat(raw6)); + s.c1 = float2(asfloat(raw7), asfloat(raw8)); + s.ra = asfloat(raw9); + s.roff = asfloat(raw10); + return s; +} + +CmdRadGrad Cmd_RadGrad_read(Alloc a, CmdRef ref) +{ + CmdRadGradRef _719 = { ref.offset + 4u }; + Alloc param = a; + CmdRadGradRef param_1 = _719; + return CmdRadGrad_read(param, param_1); +} + CmdImage CmdImage_read(Alloc a, CmdImageRef ref) { uint ix = ref.offset >> uint(2); @@ -393,9 +462,9 @@ CmdImage CmdImage_read(Alloc a, CmdImageRef ref) CmdImage Cmd_Image_read(Alloc a, CmdRef ref) { - CmdImageRef _582 = { ref.offset + 4u }; + CmdImageRef _729 = { ref.offset + 4u }; Alloc param = a; - CmdImageRef param_1 = _582; + CmdImageRef param_1 = _729; return CmdImage_read(param, param_1); } @@ -408,10 +477,10 @@ void fillImage(out float4 spvReturnValue[8], uint2 xy, CmdImage cmd_img) int2 uv = int2(xy + chunk_offset(param)) + cmd_img.offset; float4 fg_rgba = image_atlas[uv]; float3 param_1 = fg_rgba.xyz; - float3 _1493 = fromsRGB(param_1); - fg_rgba.x = _1493.x; - fg_rgba.y = _1493.y; - fg_rgba.z = _1493.z; + float3 _1638 = fromsRGB(param_1); + fg_rgba.x = _1638.x; + fg_rgba.y = _1638.y; + fg_rgba.z = _1638.z; rgba[i] = fg_rgba; } spvReturnValue = rgba; @@ -445,9 +514,9 @@ CmdEndClip CmdEndClip_read(Alloc a, CmdEndClipRef ref) CmdEndClip Cmd_EndClip_read(Alloc a, CmdRef ref) { - CmdEndClipRef _592 = { ref.offset + 4u }; + CmdEndClipRef _739 = { ref.offset + 4u }; Alloc param = a; - CmdEndClipRef param_1 = _592; + CmdEndClipRef param_1 = _739; return CmdEndClip_read(param, param_1); } @@ -637,8 +706,8 @@ float3 set_lum(float3 c, float l) { float3 param = c; float3 param_1 = c + (l - lum(param)).xxx; - float3 _901 = clip_color(param_1); - return _901; + float3 _1046 = clip_color(param_1); + return _1046; } float3 mix_blend(float3 cb, float3 cs, uint mode) @@ -726,9 +795,9 @@ float3 mix_blend(float3 cb, float3 cs, uint mode) float3 param_20 = cb; float3 param_21 = cs; float param_22 = sat(param_20); - float3 _1192 = set_sat(param_21, param_22); + float3 _1337 = set_sat(param_21, param_22); float3 param_23 = cb; - float3 param_24 = _1192; + float3 param_24 = _1337; float param_25 = lum(param_23); b = set_lum(param_24, param_25); break; @@ -738,9 +807,9 @@ float3 mix_blend(float3 cb, float3 cs, uint mode) float3 param_26 = cs; float3 param_27 = cb; float param_28 = sat(param_26); - float3 _1206 = set_sat(param_27, param_28); + float3 _1351 = set_sat(param_27, param_28); float3 param_29 = cb; - float3 param_30 = _1206; + float3 param_30 = _1351; float param_31 = lum(param_29); b = set_lum(param_30, param_31); break; @@ -877,24 +946,24 @@ CmdJump CmdJump_read(Alloc a, CmdJumpRef ref) CmdJump Cmd_Jump_read(Alloc a, CmdRef ref) { - CmdJumpRef _602 = { ref.offset + 4u }; + CmdJumpRef _749 = { ref.offset + 4u }; Alloc param = a; - CmdJumpRef param_1 = _602; + CmdJumpRef param_1 = _749; return CmdJump_read(param, param_1); } void comp_main() { - uint tile_ix = (gl_WorkGroupID.y * _1521.Load(8)) + gl_WorkGroupID.x; - Alloc _1536; - _1536.offset = _1521.Load(24); + uint tile_ix = (gl_WorkGroupID.y * _1666.Load(8)) + gl_WorkGroupID.x; + Alloc _1681; + _1681.offset = _1666.Load(24); Alloc param; - param.offset = _1536.offset; + param.offset = _1681.offset; uint param_1 = tile_ix * 1024u; uint param_2 = 1024u; Alloc cmd_alloc = slice_mem(param, param_1, param_2); - CmdRef _1545 = { cmd_alloc.offset }; - CmdRef cmd_ref = _1545; + CmdRef _1690 = { cmd_alloc.offset }; + CmdRef cmd_ref = _1690; uint2 xy_uint = uint2(gl_LocalInvocationID.x + (16u * gl_WorkGroupID.x), gl_LocalInvocationID.y + (16u * gl_WorkGroupID.y)); float2 xy = float2(xy_uint); float4 rgba[8]; @@ -903,7 +972,7 @@ void comp_main() rgba[i] = 0.0f.xxxx; } uint clip_depth = 0u; - bool mem_ok = _278.Load(4) == 0u; + bool mem_ok = _291.Load(4) == 0u; float df[8]; TileSegRef tile_seg_ref; float area[8]; @@ -928,8 +997,8 @@ void comp_main() { df[k] = 1000000000.0f; } - TileSegRef _1638 = { stroke.tile_ref }; - tile_seg_ref = _1638; + TileSegRef _1784 = { stroke.tile_ref }; + tile_seg_ref = _1784; do { uint param_7 = tile_seg_ref.offset; @@ -965,8 +1034,8 @@ void comp_main() { area[k_3] = float(fill.backdrop); } - TileSegRef _1758 = { fill.tile_ref }; - tile_seg_ref = _1758; + TileSegRef _1904 = { fill.tile_ref }; + tile_seg_ref = _1904; do { uint param_15 = tile_seg_ref.offset; @@ -1055,11 +1124,12 @@ void comp_main() int x = int(round(clamp(my_d, 0.0f, 1.0f) * 511.0f)); float4 fg_rgba = gradients[int2(x, int(lin.index))]; float3 param_29 = fg_rgba.xyz; - float3 _2092 = fromsRGB(param_29); - fg_rgba.x = _2092.x; - fg_rgba.y = _2092.y; - fg_rgba.z = _2092.z; - rgba[k_9] = fg_rgba; + float3 _2238 = fromsRGB(param_29); + fg_rgba.x = _2238.x; + fg_rgba.y = _2238.y; + fg_rgba.z = _2238.z; + float4 fg_k_1 = fg_rgba * area[k_9]; + rgba[k_9] = (rgba[k_9] * (1.0f - fg_k_1.w)) + fg_k_1; } cmd_ref.offset += 20u; break; @@ -1068,74 +1138,100 @@ void comp_main() { Alloc param_30 = cmd_alloc; CmdRef param_31 = cmd_ref; - CmdImage fill_img = Cmd_Image_read(param_30, param_31); - uint2 param_32 = xy_uint; - CmdImage param_33 = fill_img; - float4 _2121[8]; - fillImage(_2121, param_32, param_33); - float4 img[8] = _2121; + CmdRadGrad rad = Cmd_RadGrad_read(param_30, param_31); for (uint k_10 = 0u; k_10 < 8u; k_10++) { - float4 fg_k_1 = img[k_10] * area[k_10]; - rgba[k_10] = (rgba[k_10] * (1.0f - fg_k_1.w)) + fg_k_1; + uint param_32 = k_10; + float2 my_xy_1 = xy + float2(chunk_offset(param_32)); + my_xy_1 = ((rad.mat.xz * my_xy_1.x) + (rad.mat.yw * my_xy_1.y)) - rad.xlat; + float ba = dot(my_xy_1, rad.c1); + float ca = rad.ra * dot(my_xy_1, my_xy_1); + float t_2 = (sqrt((ba * ba) + ca) - ba) - rad.roff; + int x_1 = int(round(clamp(t_2, 0.0f, 1.0f) * 511.0f)); + float4 fg_rgba_1 = gradients[int2(x_1, int(rad.index))]; + float3 param_33 = fg_rgba_1.xyz; + float3 _2348 = fromsRGB(param_33); + fg_rgba_1.x = _2348.x; + fg_rgba_1.y = _2348.y; + fg_rgba_1.z = _2348.z; + float4 fg_k_2 = fg_rgba_1 * area[k_10]; + rgba[k_10] = (rgba[k_10] * (1.0f - fg_k_2.w)) + fg_k_2; } - cmd_ref.offset += 12u; + cmd_ref.offset += 48u; break; } case 8u: { + Alloc param_34 = cmd_alloc; + CmdRef param_35 = cmd_ref; + CmdImage fill_img = Cmd_Image_read(param_34, param_35); + uint2 param_36 = xy_uint; + CmdImage param_37 = fill_img; + float4 _2391[8]; + fillImage(_2391, param_36, param_37); + float4 img[8] = _2391; for (uint k_11 = 0u; k_11 < 8u; k_11++) + { + float4 fg_k_3 = img[k_11] * area[k_11]; + rgba[k_11] = (rgba[k_11] * (1.0f - fg_k_3.w)) + fg_k_3; + } + cmd_ref.offset += 12u; + break; + } + case 9u: + { + for (uint k_12 = 0u; k_12 < 8u; k_12++) { uint d_2 = min(clip_depth, 127u); - float4 param_34 = float4(rgba[k_11]); - uint _2184 = packsRGB(param_34); - blend_stack[d_2][k_11] = _2184; - rgba[k_11] = 0.0f.xxxx; + float4 param_38 = float4(rgba[k_12]); + uint _2454 = packsRGB(param_38); + blend_stack[d_2][k_12] = _2454; + rgba[k_12] = 0.0f.xxxx; } clip_depth++; cmd_ref.offset += 4u; break; } - case 9u: + case 10u: { - Alloc param_35 = cmd_alloc; - CmdRef param_36 = cmd_ref; - CmdEndClip end_clip = Cmd_EndClip_read(param_35, param_36); + Alloc param_39 = cmd_alloc; + CmdRef param_40 = cmd_ref; + CmdEndClip end_clip = Cmd_EndClip_read(param_39, param_40); uint blend_mode = end_clip.blend >> uint(8); uint comp_mode = end_clip.blend & 255u; clip_depth--; - for (uint k_12 = 0u; k_12 < 8u; k_12++) + for (uint k_13 = 0u; k_13 < 8u; k_13++) { uint d_3 = min(clip_depth, 127u); - uint param_37 = blend_stack[d_3][k_12]; - float4 bg = unpacksRGB(param_37); - float4 fg_1 = rgba[k_12] * area[k_12]; - float3 param_38 = bg.xyz; - float3 param_39 = fg_1.xyz; - uint param_40 = blend_mode; - float3 blend = mix_blend(param_38, param_39, param_40); - float4 _2251 = fg_1; - float _2255 = fg_1.w; - float3 _2262 = lerp(_2251.xyz, blend, float((_2255 * bg.w) > 0.0f).xxx); - fg_1.x = _2262.x; - fg_1.y = _2262.y; - fg_1.z = _2262.z; - float3 param_41 = bg.xyz; - float3 param_42 = fg_1.xyz; - float param_43 = bg.w; - float param_44 = fg_1.w; - uint param_45 = comp_mode; - rgba[k_12] = mix_compose(param_41, param_42, param_43, param_44, param_45); + uint param_41 = blend_stack[d_3][k_13]; + float4 bg = unpacksRGB(param_41); + float4 fg_1 = rgba[k_13] * area[k_13]; + float3 param_42 = bg.xyz; + float3 param_43 = fg_1.xyz; + uint param_44 = blend_mode; + float3 blend = mix_blend(param_42, param_43, param_44); + float4 _2521 = fg_1; + float _2525 = fg_1.w; + float3 _2532 = lerp(_2521.xyz, blend, float((_2525 * bg.w) > 0.0f).xxx); + fg_1.x = _2532.x; + fg_1.y = _2532.y; + fg_1.z = _2532.z; + float3 param_45 = bg.xyz; + float3 param_46 = fg_1.xyz; + float param_47 = bg.w; + float param_48 = fg_1.w; + uint param_49 = comp_mode; + rgba[k_13] = mix_compose(param_45, param_46, param_47, param_48, param_49); } cmd_ref.offset += 8u; break; } - case 10u: + case 11u: { - Alloc param_46 = cmd_alloc; - CmdRef param_47 = cmd_ref; - CmdRef _2299 = { Cmd_Jump_read(param_46, param_47).new_ref }; - cmd_ref = _2299; + Alloc param_50 = cmd_alloc; + CmdRef param_51 = cmd_ref; + CmdRef _2569 = { Cmd_Jump_read(param_50, param_51).new_ref }; + cmd_ref = _2569; cmd_alloc.offset = cmd_ref.offset; break; } @@ -1143,9 +1239,9 @@ void comp_main() } for (uint i_1 = 0u; i_1 < 8u; i_1++) { - uint param_48 = i_1; - float3 param_49 = rgba[i_1].xyz; - image[int2(xy_uint + chunk_offset(param_48))] = float4(tosRGB(param_49), rgba[i_1].w); + uint param_52 = i_1; + float3 param_53 = rgba[i_1].xyz; + image[int2(xy_uint + chunk_offset(param_52))] = float4(tosRGB(param_53), rgba[i_1].w); } } diff --git a/piet-gpu/shader/gen/kernel4.msl b/piet-gpu/shader/gen/kernel4.msl index c1f41af..6489563 100644 --- a/piet-gpu/shader/gen/kernel4.msl +++ b/piet-gpu/shader/gen/kernel4.msl @@ -94,6 +94,21 @@ struct CmdLinGrad float line_c; }; +struct CmdRadGradRef +{ + uint offset; +}; + +struct CmdRadGrad +{ + uint index; + float4 mat; + float2 xlat; + float2 c1; + float ra; + float roff; +}; + struct CmdImageRef { uint offset; @@ -222,7 +237,7 @@ bool touch_mem(thread const Alloc& alloc, thread const uint& offset) } static inline __attribute__((always_inline)) -uint read_mem(thread const Alloc& alloc, thread const uint& offset, device Memory& v_278) +uint read_mem(thread const Alloc& alloc, thread const uint& offset, device Memory& v_291) { Alloc param = alloc; uint param_1 = offset; @@ -230,29 +245,29 @@ uint read_mem(thread const Alloc& alloc, thread const uint& offset, device Memor { return 0u; } - uint v = v_278.memory[offset]; + uint v = v_291.memory[offset]; return v; } static inline __attribute__((always_inline)) -CmdTag Cmd_tag(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_278) +CmdTag Cmd_tag(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_291) { Alloc param = a; uint param_1 = ref.offset >> uint(2); - uint tag_and_flags = read_mem(param, param_1, v_278); + uint tag_and_flags = read_mem(param, param_1, v_291); return CmdTag{ tag_and_flags & 65535u, tag_and_flags >> uint(16) }; } static inline __attribute__((always_inline)) -CmdStroke CmdStroke_read(thread const Alloc& a, thread const CmdStrokeRef& ref, device Memory& v_278) +CmdStroke CmdStroke_read(thread const Alloc& a, thread const CmdStrokeRef& ref, device Memory& v_291) { uint ix = ref.offset >> uint(2); Alloc param = a; uint param_1 = ix + 0u; - uint raw0 = read_mem(param, param_1, v_278); + uint raw0 = read_mem(param, param_1, v_291); Alloc param_2 = a; uint param_3 = ix + 1u; - uint raw1 = read_mem(param_2, param_3, v_278); + uint raw1 = read_mem(param_2, param_3, v_291); CmdStroke s; s.tile_ref = raw0; s.half_width = as_type(raw1); @@ -260,11 +275,11 @@ CmdStroke CmdStroke_read(thread const Alloc& a, thread const CmdStrokeRef& ref, } static inline __attribute__((always_inline)) -CmdStroke Cmd_Stroke_read(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_278) +CmdStroke Cmd_Stroke_read(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_291) { Alloc param = a; CmdStrokeRef param_1 = CmdStrokeRef{ ref.offset + 4u }; - return CmdStroke_read(param, param_1, v_278); + return CmdStroke_read(param, param_1, v_291); } static inline __attribute__((always_inline)) @@ -276,27 +291,27 @@ Alloc new_alloc(thread const uint& offset, thread const uint& size, thread const } static inline __attribute__((always_inline)) -TileSeg TileSeg_read(thread const Alloc& a, thread const TileSegRef& ref, device Memory& v_278) +TileSeg TileSeg_read(thread const Alloc& a, thread const TileSegRef& ref, device Memory& v_291) { uint ix = ref.offset >> uint(2); Alloc param = a; uint param_1 = ix + 0u; - uint raw0 = read_mem(param, param_1, v_278); + uint raw0 = read_mem(param, param_1, v_291); Alloc param_2 = a; uint param_3 = ix + 1u; - uint raw1 = read_mem(param_2, param_3, v_278); + uint raw1 = read_mem(param_2, param_3, v_291); Alloc param_4 = a; uint param_5 = ix + 2u; - uint raw2 = read_mem(param_4, param_5, v_278); + uint raw2 = read_mem(param_4, param_5, v_291); Alloc param_6 = a; uint param_7 = ix + 3u; - uint raw3 = read_mem(param_6, param_7, v_278); + uint raw3 = read_mem(param_6, param_7, v_291); Alloc param_8 = a; uint param_9 = ix + 4u; - uint raw4 = read_mem(param_8, param_9, v_278); + uint raw4 = read_mem(param_8, param_9, v_291); Alloc param_10 = a; uint param_11 = ix + 5u; - uint raw5 = read_mem(param_10, param_11, v_278); + uint raw5 = read_mem(param_10, param_11, v_291); TileSeg s; s.origin = float2(as_type(raw0), as_type(raw1)); s.vector = float2(as_type(raw2), as_type(raw3)); @@ -312,15 +327,15 @@ uint2 chunk_offset(thread const uint& i) } static inline __attribute__((always_inline)) -CmdFill CmdFill_read(thread const Alloc& a, thread const CmdFillRef& ref, device Memory& v_278) +CmdFill CmdFill_read(thread const Alloc& a, thread const CmdFillRef& ref, device Memory& v_291) { uint ix = ref.offset >> uint(2); Alloc param = a; uint param_1 = ix + 0u; - uint raw0 = read_mem(param, param_1, v_278); + uint raw0 = read_mem(param, param_1, v_291); Alloc param_2 = a; uint param_3 = ix + 1u; - uint raw1 = read_mem(param_2, param_3, v_278); + uint raw1 = read_mem(param_2, param_3, v_291); CmdFill s; s.tile_ref = raw0; s.backdrop = int(raw1); @@ -328,51 +343,51 @@ CmdFill CmdFill_read(thread const Alloc& a, thread const CmdFillRef& ref, device } static inline __attribute__((always_inline)) -CmdFill Cmd_Fill_read(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_278) +CmdFill Cmd_Fill_read(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_291) { Alloc param = a; CmdFillRef param_1 = CmdFillRef{ ref.offset + 4u }; - return CmdFill_read(param, param_1, v_278); + return CmdFill_read(param, param_1, v_291); } static inline __attribute__((always_inline)) -CmdAlpha CmdAlpha_read(thread const Alloc& a, thread const CmdAlphaRef& ref, device Memory& v_278) +CmdAlpha CmdAlpha_read(thread const Alloc& a, thread const CmdAlphaRef& ref, device Memory& v_291) { uint ix = ref.offset >> uint(2); Alloc param = a; uint param_1 = ix + 0u; - uint raw0 = read_mem(param, param_1, v_278); + uint raw0 = read_mem(param, param_1, v_291); CmdAlpha s; s.alpha = as_type(raw0); return s; } static inline __attribute__((always_inline)) -CmdAlpha Cmd_Alpha_read(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_278) +CmdAlpha Cmd_Alpha_read(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_291) { Alloc param = a; CmdAlphaRef param_1 = CmdAlphaRef{ ref.offset + 4u }; - return CmdAlpha_read(param, param_1, v_278); + return CmdAlpha_read(param, param_1, v_291); } static inline __attribute__((always_inline)) -CmdColor CmdColor_read(thread const Alloc& a, thread const CmdColorRef& ref, device Memory& v_278) +CmdColor CmdColor_read(thread const Alloc& a, thread const CmdColorRef& ref, device Memory& v_291) { uint ix = ref.offset >> uint(2); Alloc param = a; uint param_1 = ix + 0u; - uint raw0 = read_mem(param, param_1, v_278); + uint raw0 = read_mem(param, param_1, v_291); CmdColor s; s.rgba_color = raw0; return s; } static inline __attribute__((always_inline)) -CmdColor Cmd_Color_read(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_278) +CmdColor Cmd_Color_read(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_291) { Alloc param = a; CmdColorRef param_1 = CmdColorRef{ ref.offset + 4u }; - return CmdColor_read(param, param_1, v_278); + return CmdColor_read(param, param_1, v_291); } static inline __attribute__((always_inline)) @@ -393,21 +408,21 @@ float4 unpacksRGB(thread const uint& srgba) } static inline __attribute__((always_inline)) -CmdLinGrad CmdLinGrad_read(thread const Alloc& a, thread const CmdLinGradRef& ref, device Memory& v_278) +CmdLinGrad CmdLinGrad_read(thread const Alloc& a, thread const CmdLinGradRef& ref, device Memory& v_291) { uint ix = ref.offset >> uint(2); Alloc param = a; uint param_1 = ix + 0u; - uint raw0 = read_mem(param, param_1, v_278); + uint raw0 = read_mem(param, param_1, v_291); Alloc param_2 = a; uint param_3 = ix + 1u; - uint raw1 = read_mem(param_2, param_3, v_278); + uint raw1 = read_mem(param_2, param_3, v_291); Alloc param_4 = a; uint param_5 = ix + 2u; - uint raw2 = read_mem(param_4, param_5, v_278); + uint raw2 = read_mem(param_4, param_5, v_291); Alloc param_6 = a; uint param_7 = ix + 3u; - uint raw3 = read_mem(param_6, param_7, v_278); + uint raw3 = read_mem(param_6, param_7, v_291); CmdLinGrad s; s.index = raw0; s.line_x = as_type(raw1); @@ -417,23 +432,78 @@ CmdLinGrad CmdLinGrad_read(thread const Alloc& a, thread const CmdLinGradRef& re } static inline __attribute__((always_inline)) -CmdLinGrad Cmd_LinGrad_read(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_278) +CmdLinGrad Cmd_LinGrad_read(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_291) { Alloc param = a; CmdLinGradRef param_1 = CmdLinGradRef{ ref.offset + 4u }; - return CmdLinGrad_read(param, param_1, v_278); + return CmdLinGrad_read(param, param_1, v_291); } static inline __attribute__((always_inline)) -CmdImage CmdImage_read(thread const Alloc& a, thread const CmdImageRef& ref, device Memory& v_278) +CmdRadGrad CmdRadGrad_read(thread const Alloc& a, thread const CmdRadGradRef& ref, device Memory& v_291) { uint ix = ref.offset >> uint(2); Alloc param = a; uint param_1 = ix + 0u; - uint raw0 = read_mem(param, param_1, v_278); + uint raw0 = read_mem(param, param_1, v_291); Alloc param_2 = a; uint param_3 = ix + 1u; - uint raw1 = read_mem(param_2, param_3, v_278); + uint raw1 = read_mem(param_2, param_3, v_291); + Alloc param_4 = a; + uint param_5 = ix + 2u; + uint raw2 = read_mem(param_4, param_5, v_291); + Alloc param_6 = a; + uint param_7 = ix + 3u; + uint raw3 = read_mem(param_6, param_7, v_291); + Alloc param_8 = a; + uint param_9 = ix + 4u; + uint raw4 = read_mem(param_8, param_9, v_291); + Alloc param_10 = a; + uint param_11 = ix + 5u; + uint raw5 = read_mem(param_10, param_11, v_291); + Alloc param_12 = a; + uint param_13 = ix + 6u; + uint raw6 = read_mem(param_12, param_13, v_291); + Alloc param_14 = a; + uint param_15 = ix + 7u; + uint raw7 = read_mem(param_14, param_15, v_291); + Alloc param_16 = a; + uint param_17 = ix + 8u; + uint raw8 = read_mem(param_16, param_17, v_291); + Alloc param_18 = a; + uint param_19 = ix + 9u; + uint raw9 = read_mem(param_18, param_19, v_291); + Alloc param_20 = a; + uint param_21 = ix + 10u; + uint raw10 = read_mem(param_20, param_21, v_291); + CmdRadGrad s; + s.index = raw0; + s.mat = float4(as_type(raw1), as_type(raw2), as_type(raw3), as_type(raw4)); + s.xlat = float2(as_type(raw5), as_type(raw6)); + s.c1 = float2(as_type(raw7), as_type(raw8)); + s.ra = as_type(raw9); + s.roff = as_type(raw10); + return s; +} + +static inline __attribute__((always_inline)) +CmdRadGrad Cmd_RadGrad_read(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_291) +{ + Alloc param = a; + CmdRadGradRef param_1 = CmdRadGradRef{ ref.offset + 4u }; + return CmdRadGrad_read(param, param_1, v_291); +} + +static inline __attribute__((always_inline)) +CmdImage CmdImage_read(thread const Alloc& a, thread const CmdImageRef& ref, device Memory& v_291) +{ + uint ix = ref.offset >> uint(2); + Alloc param = a; + uint param_1 = ix + 0u; + uint raw0 = read_mem(param, param_1, v_291); + Alloc param_2 = a; + uint param_3 = ix + 1u; + uint raw1 = read_mem(param_2, param_3, v_291); CmdImage s; s.index = raw0; s.offset = int2(int(raw1 << uint(16)) >> 16, int(raw1) >> 16); @@ -441,11 +511,11 @@ CmdImage CmdImage_read(thread const Alloc& a, thread const CmdImageRef& ref, dev } static inline __attribute__((always_inline)) -CmdImage Cmd_Image_read(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_278) +CmdImage Cmd_Image_read(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_291) { Alloc param = a; CmdImageRef param_1 = CmdImageRef{ ref.offset + 4u }; - return CmdImage_read(param, param_1, v_278); + return CmdImage_read(param, param_1, v_291); } static inline __attribute__((always_inline)) @@ -458,10 +528,10 @@ spvUnsafeArray fillImage(thread const uint2& xy, thread const CmdImag int2 uv = int2(xy + chunk_offset(param)) + cmd_img.offset; float4 fg_rgba = image_atlas.read(uint2(uv)); float3 param_1 = fg_rgba.xyz; - float3 _1493 = fromsRGB(param_1); - fg_rgba.x = _1493.x; - fg_rgba.y = _1493.y; - fg_rgba.z = _1493.z; + float3 _1638 = fromsRGB(param_1); + fg_rgba.x = _1638.x; + fg_rgba.y = _1638.y; + fg_rgba.z = _1638.z; rgba[i] = fg_rgba; } return rgba; @@ -485,23 +555,23 @@ uint packsRGB(thread float4& rgba) } static inline __attribute__((always_inline)) -CmdEndClip CmdEndClip_read(thread const Alloc& a, thread const CmdEndClipRef& ref, device Memory& v_278) +CmdEndClip CmdEndClip_read(thread const Alloc& a, thread const CmdEndClipRef& ref, device Memory& v_291) { uint ix = ref.offset >> uint(2); Alloc param = a; uint param_1 = ix + 0u; - uint raw0 = read_mem(param, param_1, v_278); + uint raw0 = read_mem(param, param_1, v_291); CmdEndClip s; s.blend = raw0; return s; } static inline __attribute__((always_inline)) -CmdEndClip Cmd_EndClip_read(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_278) +CmdEndClip Cmd_EndClip_read(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_291) { Alloc param = a; CmdEndClipRef param_1 = CmdEndClipRef{ ref.offset + 4u }; - return CmdEndClip_read(param, param_1, v_278); + return CmdEndClip_read(param, param_1, v_291); } static inline __attribute__((always_inline)) @@ -701,8 +771,8 @@ float3 set_lum(thread const float3& c, thread const float& l) { float3 param = c; float3 param_1 = c + float3(l - lum(param)); - float3 _901 = clip_color(param_1); - return _901; + float3 _1046 = clip_color(param_1); + return _1046; } static inline __attribute__((always_inline)) @@ -791,9 +861,9 @@ float3 mix_blend(thread const float3& cb, thread const float3& cs, thread const float3 param_20 = cb; float3 param_21 = cs; float param_22 = sat(param_20); - float3 _1192 = set_sat(param_21, param_22); + float3 _1337 = set_sat(param_21, param_22); float3 param_23 = cb; - float3 param_24 = _1192; + float3 param_24 = _1337; float param_25 = lum(param_23); b = set_lum(param_24, param_25); break; @@ -803,9 +873,9 @@ float3 mix_blend(thread const float3& cb, thread const float3& cs, thread const float3 param_26 = cs; float3 param_27 = cb; float param_28 = sat(param_26); - float3 _1206 = set_sat(param_27, param_28); + float3 _1351 = set_sat(param_27, param_28); float3 param_29 = cb; - float3 param_30 = _1206; + float3 param_30 = _1351; float param_31 = lum(param_29); b = set_lum(param_30, param_31); break; @@ -931,30 +1001,30 @@ float4 mix_compose(thread const float3& cb, thread const float3& cs, thread cons } static inline __attribute__((always_inline)) -CmdJump CmdJump_read(thread const Alloc& a, thread const CmdJumpRef& ref, device Memory& v_278) +CmdJump CmdJump_read(thread const Alloc& a, thread const CmdJumpRef& ref, device Memory& v_291) { uint ix = ref.offset >> uint(2); Alloc param = a; uint param_1 = ix + 0u; - uint raw0 = read_mem(param, param_1, v_278); + uint raw0 = read_mem(param, param_1, v_291); CmdJump s; s.new_ref = raw0; return s; } static inline __attribute__((always_inline)) -CmdJump Cmd_Jump_read(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_278) +CmdJump Cmd_Jump_read(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_291) { Alloc param = a; CmdJumpRef param_1 = CmdJumpRef{ ref.offset + 4u }; - return CmdJump_read(param, param_1, v_278); + return CmdJump_read(param, param_1, v_291); } -kernel void main0(device Memory& v_278 [[buffer(0)]], const device ConfigBuf& _1521 [[buffer(1)]], texture2d image [[texture(2)]], texture2d image_atlas [[texture(3)]], texture2d gradients [[texture(4)]], uint3 gl_WorkGroupID [[threadgroup_position_in_grid]], uint3 gl_LocalInvocationID [[thread_position_in_threadgroup]]) +kernel void main0(device Memory& v_291 [[buffer(0)]], const device ConfigBuf& _1666 [[buffer(1)]], texture2d image [[texture(2)]], texture2d image_atlas [[texture(3)]], texture2d gradients [[texture(4)]], uint3 gl_WorkGroupID [[threadgroup_position_in_grid]], uint3 gl_LocalInvocationID [[thread_position_in_threadgroup]]) { - uint tile_ix = (gl_WorkGroupID.y * _1521.conf.width_in_tiles) + gl_WorkGroupID.x; + uint tile_ix = (gl_WorkGroupID.y * _1666.conf.width_in_tiles) + gl_WorkGroupID.x; Alloc param; - param.offset = _1521.conf.ptcl_alloc.offset; + param.offset = _1666.conf.ptcl_alloc.offset; uint param_1 = tile_ix * 1024u; uint param_2 = 1024u; Alloc cmd_alloc = slice_mem(param, param_1, param_2); @@ -967,7 +1037,7 @@ kernel void main0(device Memory& v_278 [[buffer(0)]], const device ConfigBuf& _1 rgba[i] = float4(0.0); } uint clip_depth = 0u; - bool mem_ok = v_278.mem_error == 0u; + bool mem_ok = v_291.mem_error == 0u; spvUnsafeArray df; TileSegRef tile_seg_ref; spvUnsafeArray area; @@ -976,7 +1046,7 @@ kernel void main0(device Memory& v_278 [[buffer(0)]], const device ConfigBuf& _1 { Alloc param_3 = cmd_alloc; CmdRef param_4 = cmd_ref; - uint tag = Cmd_tag(param_3, param_4, v_278).tag; + uint tag = Cmd_tag(param_3, param_4, v_291).tag; if (tag == 0u) { break; @@ -987,7 +1057,7 @@ kernel void main0(device Memory& v_278 [[buffer(0)]], const device ConfigBuf& _1 { Alloc param_5 = cmd_alloc; CmdRef param_6 = cmd_ref; - CmdStroke stroke = Cmd_Stroke_read(param_5, param_6, v_278); + CmdStroke stroke = Cmd_Stroke_read(param_5, param_6, v_291); for (uint k = 0u; k < 8u; k++) { df[k] = 1000000000.0; @@ -1000,7 +1070,7 @@ kernel void main0(device Memory& v_278 [[buffer(0)]], const device ConfigBuf& _1 bool param_9 = mem_ok; Alloc param_10 = new_alloc(param_7, param_8, param_9); TileSegRef param_11 = tile_seg_ref; - TileSeg seg = TileSeg_read(param_10, param_11, v_278); + TileSeg seg = TileSeg_read(param_10, param_11, v_291); float2 line_vec = seg.vector; for (uint k_1 = 0u; k_1 < 8u; k_1++) { @@ -1023,7 +1093,7 @@ kernel void main0(device Memory& v_278 [[buffer(0)]], const device ConfigBuf& _1 { Alloc param_13 = cmd_alloc; CmdRef param_14 = cmd_ref; - CmdFill fill = Cmd_Fill_read(param_13, param_14, v_278); + CmdFill fill = Cmd_Fill_read(param_13, param_14, v_291); for (uint k_3 = 0u; k_3 < 8u; k_3++) { area[k_3] = float(fill.backdrop); @@ -1036,7 +1106,7 @@ kernel void main0(device Memory& v_278 [[buffer(0)]], const device ConfigBuf& _1 bool param_17 = mem_ok; Alloc param_18 = new_alloc(param_15, param_16, param_17); TileSegRef param_19 = tile_seg_ref; - TileSeg seg_1 = TileSeg_read(param_18, param_19, v_278); + TileSeg seg_1 = TileSeg_read(param_18, param_19, v_291); for (uint k_4 = 0u; k_4 < 8u; k_4++) { uint param_20 = k_4; @@ -1080,7 +1150,7 @@ kernel void main0(device Memory& v_278 [[buffer(0)]], const device ConfigBuf& _1 { Alloc param_21 = cmd_alloc; CmdRef param_22 = cmd_ref; - CmdAlpha alpha = Cmd_Alpha_read(param_21, param_22, v_278); + CmdAlpha alpha = Cmd_Alpha_read(param_21, param_22, v_291); for (uint k_7 = 0u; k_7 < 8u; k_7++) { area[k_7] = alpha.alpha; @@ -1092,7 +1162,7 @@ kernel void main0(device Memory& v_278 [[buffer(0)]], const device ConfigBuf& _1 { Alloc param_23 = cmd_alloc; CmdRef param_24 = cmd_ref; - CmdColor color = Cmd_Color_read(param_23, param_24, v_278); + CmdColor color = Cmd_Color_read(param_23, param_24, v_291); uint param_25 = color.rgba_color; float4 fg = unpacksRGB(param_25); for (uint k_8 = 0u; k_8 < 8u; k_8++) @@ -1107,7 +1177,7 @@ kernel void main0(device Memory& v_278 [[buffer(0)]], const device ConfigBuf& _1 { Alloc param_26 = cmd_alloc; CmdRef param_27 = cmd_ref; - CmdLinGrad lin = Cmd_LinGrad_read(param_26, param_27, v_278); + CmdLinGrad lin = Cmd_LinGrad_read(param_26, param_27, v_291); float d_1 = ((lin.line_x * xy.x) + (lin.line_y * xy.y)) + lin.line_c; for (uint k_9 = 0u; k_9 < 8u; k_9++) { @@ -1117,11 +1187,12 @@ kernel void main0(device Memory& v_278 [[buffer(0)]], const device ConfigBuf& _1 int x = int(round(fast::clamp(my_d, 0.0, 1.0) * 511.0)); float4 fg_rgba = gradients.read(uint2(int2(x, int(lin.index)))); float3 param_29 = fg_rgba.xyz; - float3 _2092 = fromsRGB(param_29); - fg_rgba.x = _2092.x; - fg_rgba.y = _2092.y; - fg_rgba.z = _2092.z; - rgba[k_9] = fg_rgba; + float3 _2238 = fromsRGB(param_29); + fg_rgba.x = _2238.x; + fg_rgba.y = _2238.y; + fg_rgba.z = _2238.z; + float4 fg_k_1 = fg_rgba * area[k_9]; + rgba[k_9] = (rgba[k_9] * (1.0 - fg_k_1.w)) + fg_k_1; } cmd_ref.offset += 20u; break; @@ -1130,72 +1201,98 @@ kernel void main0(device Memory& v_278 [[buffer(0)]], const device ConfigBuf& _1 { Alloc param_30 = cmd_alloc; CmdRef param_31 = cmd_ref; - CmdImage fill_img = Cmd_Image_read(param_30, param_31, v_278); - uint2 param_32 = xy_uint; - CmdImage param_33 = fill_img; - spvUnsafeArray img; - img = fillImage(param_32, param_33, image_atlas); + CmdRadGrad rad = Cmd_RadGrad_read(param_30, param_31, v_291); for (uint k_10 = 0u; k_10 < 8u; k_10++) { - float4 fg_k_1 = img[k_10] * area[k_10]; - rgba[k_10] = (rgba[k_10] * (1.0 - fg_k_1.w)) + fg_k_1; + uint param_32 = k_10; + float2 my_xy_1 = xy + float2(chunk_offset(param_32)); + my_xy_1 = ((rad.mat.xz * my_xy_1.x) + (rad.mat.yw * my_xy_1.y)) - rad.xlat; + float ba = dot(my_xy_1, rad.c1); + float ca = rad.ra * dot(my_xy_1, my_xy_1); + float t_2 = (sqrt((ba * ba) + ca) - ba) - rad.roff; + int x_1 = int(round(fast::clamp(t_2, 0.0, 1.0) * 511.0)); + float4 fg_rgba_1 = gradients.read(uint2(int2(x_1, int(rad.index)))); + float3 param_33 = fg_rgba_1.xyz; + float3 _2348 = fromsRGB(param_33); + fg_rgba_1.x = _2348.x; + fg_rgba_1.y = _2348.y; + fg_rgba_1.z = _2348.z; + float4 fg_k_2 = fg_rgba_1 * area[k_10]; + rgba[k_10] = (rgba[k_10] * (1.0 - fg_k_2.w)) + fg_k_2; } - cmd_ref.offset += 12u; + cmd_ref.offset += 48u; break; } case 8u: { + Alloc param_34 = cmd_alloc; + CmdRef param_35 = cmd_ref; + CmdImage fill_img = Cmd_Image_read(param_34, param_35, v_291); + uint2 param_36 = xy_uint; + CmdImage param_37 = fill_img; + spvUnsafeArray img; + img = fillImage(param_36, param_37, image_atlas); for (uint k_11 = 0u; k_11 < 8u; k_11++) + { + float4 fg_k_3 = img[k_11] * area[k_11]; + rgba[k_11] = (rgba[k_11] * (1.0 - fg_k_3.w)) + fg_k_3; + } + cmd_ref.offset += 12u; + break; + } + case 9u: + { + for (uint k_12 = 0u; k_12 < 8u; k_12++) { uint d_2 = min(clip_depth, 127u); - float4 param_34 = float4(rgba[k_11]); - uint _2184 = packsRGB(param_34); - blend_stack[d_2][k_11] = _2184; - rgba[k_11] = float4(0.0); + float4 param_38 = float4(rgba[k_12]); + uint _2454 = packsRGB(param_38); + blend_stack[d_2][k_12] = _2454; + rgba[k_12] = float4(0.0); } clip_depth++; cmd_ref.offset += 4u; break; } - case 9u: + case 10u: { - Alloc param_35 = cmd_alloc; - CmdRef param_36 = cmd_ref; - CmdEndClip end_clip = Cmd_EndClip_read(param_35, param_36, v_278); + Alloc param_39 = cmd_alloc; + CmdRef param_40 = cmd_ref; + CmdEndClip end_clip = Cmd_EndClip_read(param_39, param_40, v_291); uint blend_mode = end_clip.blend >> uint(8); uint comp_mode = end_clip.blend & 255u; clip_depth--; - for (uint k_12 = 0u; k_12 < 8u; k_12++) + for (uint k_13 = 0u; k_13 < 8u; k_13++) { uint d_3 = min(clip_depth, 127u); - uint param_37 = blend_stack[d_3][k_12]; - float4 bg = unpacksRGB(param_37); - float4 fg_1 = rgba[k_12] * area[k_12]; - float3 param_38 = bg.xyz; - float3 param_39 = fg_1.xyz; - uint param_40 = blend_mode; - float3 blend = mix_blend(param_38, param_39, param_40); - float4 _2251 = fg_1; - float _2255 = fg_1.w; - float3 _2262 = mix(_2251.xyz, blend, float3(float((_2255 * bg.w) > 0.0))); - fg_1.x = _2262.x; - fg_1.y = _2262.y; - fg_1.z = _2262.z; - float3 param_41 = bg.xyz; - float3 param_42 = fg_1.xyz; - float param_43 = bg.w; - float param_44 = fg_1.w; - uint param_45 = comp_mode; - rgba[k_12] = mix_compose(param_41, param_42, param_43, param_44, param_45); + uint param_41 = blend_stack[d_3][k_13]; + float4 bg = unpacksRGB(param_41); + float4 fg_1 = rgba[k_13] * area[k_13]; + float3 param_42 = bg.xyz; + float3 param_43 = fg_1.xyz; + uint param_44 = blend_mode; + float3 blend = mix_blend(param_42, param_43, param_44); + float4 _2521 = fg_1; + float _2525 = fg_1.w; + float3 _2532 = mix(_2521.xyz, blend, float3(float((_2525 * bg.w) > 0.0))); + fg_1.x = _2532.x; + fg_1.y = _2532.y; + fg_1.z = _2532.z; + float3 param_45 = bg.xyz; + float3 param_46 = fg_1.xyz; + float param_47 = bg.w; + float param_48 = fg_1.w; + uint param_49 = comp_mode; + rgba[k_13] = mix_compose(param_45, param_46, param_47, param_48, param_49); } cmd_ref.offset += 8u; break; } - case 10u: + case 11u: { - Alloc param_46 = cmd_alloc; - CmdRef param_47 = cmd_ref; - cmd_ref = CmdRef{ Cmd_Jump_read(param_46, param_47, v_278).new_ref }; + Alloc param_50 = cmd_alloc; + CmdRef param_51 = cmd_ref; + cmd_ref = CmdRef{ Cmd_Jump_read(param_50, param_51, v_291).new_ref }; cmd_alloc.offset = cmd_ref.offset; break; } @@ -1203,9 +1300,9 @@ kernel void main0(device Memory& v_278 [[buffer(0)]], const device ConfigBuf& _1 } for (uint i_1 = 0u; i_1 < 8u; i_1++) { - uint param_48 = i_1; - float3 param_49 = rgba[i_1].xyz; - image.write(float4(tosRGB(param_49), rgba[i_1].w), uint2(int2(xy_uint + chunk_offset(param_48)))); + uint param_52 = i_1; + float3 param_53 = rgba[i_1].xyz; + image.write(float4(tosRGB(param_53), rgba[i_1].w), uint2(int2(xy_uint + chunk_offset(param_52)))); } } diff --git a/piet-gpu/shader/gen/kernel4.spv b/piet-gpu/shader/gen/kernel4.spv index 91272da225f52879a626483478c6068cdabb6a3d..70612634a5e2d8a7713d8107b6f1da6aafffa287 100644 GIT binary patch literal 65556 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 literal 58596 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 diff --git a/piet-gpu/shader/gen/kernel4_gray.dxil b/piet-gpu/shader/gen/kernel4_gray.dxil index 18c4b7eab4faa745a72e49be704b48803ad300d8..a594d502fa09859dac2cb640e38b2553cc692204 100644 GIT binary patch delta 10729 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 delta 9756 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 b^$N^1)$@tCLkXywN6(y=MF4Z<`uG0;Guw+I diff --git a/piet-gpu/shader/gen/kernel4_gray.hlsl b/piet-gpu/shader/gen/kernel4_gray.hlsl index de95771..019a73c 100644 --- a/piet-gpu/shader/gen/kernel4_gray.hlsl +++ b/piet-gpu/shader/gen/kernel4_gray.hlsl @@ -48,6 +48,21 @@ struct CmdLinGrad float line_c; }; +struct CmdRadGradRef +{ + uint offset; +}; + +struct CmdRadGrad +{ + uint index; + float4 mat; + float2 xlat; + float2 c1; + float ra; + float roff; +}; + struct CmdImageRef { uint offset; @@ -146,8 +161,8 @@ struct Config static const uint3 gl_WorkGroupSize = uint3(8u, 4u, 1u); -RWByteAddressBuffer _278 : register(u0, space0); -ByteAddressBuffer _1521 : register(t1, space0); +RWByteAddressBuffer _291 : register(u0, space0); +ByteAddressBuffer _1666 : register(t1, space0); RWTexture2D image_atlas : register(u3, space0); RWTexture2D gradients : register(u4, space0); RWTexture2D image : register(u2, space0); @@ -174,8 +189,8 @@ float4 spvUnpackUnorm4x8(uint value) Alloc slice_mem(Alloc a, uint offset, uint size) { - Alloc _291 = { a.offset + offset }; - return _291; + Alloc _304 = { a.offset + offset }; + return _304; } bool touch_mem(Alloc alloc, uint offset) @@ -191,7 +206,7 @@ uint read_mem(Alloc alloc, uint offset) { return 0u; } - uint v = _278.Load(offset * 4 + 8); + uint v = _291.Load(offset * 4 + 8); return v; } @@ -200,8 +215,8 @@ CmdTag Cmd_tag(Alloc a, CmdRef ref) Alloc param = a; uint param_1 = ref.offset >> uint(2); uint tag_and_flags = read_mem(param, param_1); - CmdTag _525 = { tag_and_flags & 65535u, tag_and_flags >> uint(16) }; - return _525; + CmdTag _663 = { tag_and_flags & 65535u, tag_and_flags >> uint(16) }; + return _663; } CmdStroke CmdStroke_read(Alloc a, CmdStrokeRef ref) @@ -221,9 +236,9 @@ CmdStroke CmdStroke_read(Alloc a, CmdStrokeRef ref) CmdStroke Cmd_Stroke_read(Alloc a, CmdRef ref) { - CmdStrokeRef _542 = { ref.offset + 4u }; + CmdStrokeRef _679 = { ref.offset + 4u }; Alloc param = a; - CmdStrokeRef param_1 = _542; + CmdStrokeRef param_1 = _679; return CmdStroke_read(param, param_1); } @@ -259,8 +274,8 @@ TileSeg TileSeg_read(Alloc a, TileSegRef ref) s.origin = float2(asfloat(raw0), asfloat(raw1)); s._vector = float2(asfloat(raw2), asfloat(raw3)); s.y_edge = asfloat(raw4); - TileSegRef _675 = { raw5 }; - s.next = _675; + TileSegRef _820 = { raw5 }; + s.next = _820; return s; } @@ -286,9 +301,9 @@ CmdFill CmdFill_read(Alloc a, CmdFillRef ref) CmdFill Cmd_Fill_read(Alloc a, CmdRef ref) { - CmdFillRef _532 = { ref.offset + 4u }; + CmdFillRef _669 = { ref.offset + 4u }; Alloc param = a; - CmdFillRef param_1 = _532; + CmdFillRef param_1 = _669; return CmdFill_read(param, param_1); } @@ -305,9 +320,9 @@ CmdAlpha CmdAlpha_read(Alloc a, CmdAlphaRef ref) CmdAlpha Cmd_Alpha_read(Alloc a, CmdRef ref) { - CmdAlphaRef _552 = { ref.offset + 4u }; + CmdAlphaRef _689 = { ref.offset + 4u }; Alloc param = a; - CmdAlphaRef param_1 = _552; + CmdAlphaRef param_1 = _689; return CmdAlpha_read(param, param_1); } @@ -324,9 +339,9 @@ CmdColor CmdColor_read(Alloc a, CmdColorRef ref) CmdColor Cmd_Color_read(Alloc a, CmdRef ref) { - CmdColorRef _562 = { ref.offset + 4u }; + CmdColorRef _699 = { ref.offset + 4u }; Alloc param = a; - CmdColorRef param_1 = _562; + CmdColorRef param_1 = _699; return CmdColor_read(param, param_1); } @@ -370,12 +385,66 @@ CmdLinGrad CmdLinGrad_read(Alloc a, CmdLinGradRef ref) CmdLinGrad Cmd_LinGrad_read(Alloc a, CmdRef ref) { - CmdLinGradRef _572 = { ref.offset + 4u }; + CmdLinGradRef _709 = { ref.offset + 4u }; Alloc param = a; - CmdLinGradRef param_1 = _572; + CmdLinGradRef param_1 = _709; return CmdLinGrad_read(param, param_1); } +CmdRadGrad CmdRadGrad_read(Alloc a, CmdRadGradRef ref) +{ + uint ix = ref.offset >> uint(2); + Alloc param = a; + uint param_1 = ix + 0u; + uint raw0 = read_mem(param, param_1); + Alloc param_2 = a; + uint param_3 = ix + 1u; + uint raw1 = read_mem(param_2, param_3); + Alloc param_4 = a; + uint param_5 = ix + 2u; + uint raw2 = read_mem(param_4, param_5); + Alloc param_6 = a; + uint param_7 = ix + 3u; + uint raw3 = read_mem(param_6, param_7); + Alloc param_8 = a; + uint param_9 = ix + 4u; + uint raw4 = read_mem(param_8, param_9); + Alloc param_10 = a; + uint param_11 = ix + 5u; + uint raw5 = read_mem(param_10, param_11); + Alloc param_12 = a; + uint param_13 = ix + 6u; + uint raw6 = read_mem(param_12, param_13); + Alloc param_14 = a; + uint param_15 = ix + 7u; + uint raw7 = read_mem(param_14, param_15); + Alloc param_16 = a; + uint param_17 = ix + 8u; + uint raw8 = read_mem(param_16, param_17); + Alloc param_18 = a; + uint param_19 = ix + 9u; + uint raw9 = read_mem(param_18, param_19); + Alloc param_20 = a; + uint param_21 = ix + 10u; + uint raw10 = read_mem(param_20, param_21); + CmdRadGrad s; + s.index = raw0; + s.mat = float4(asfloat(raw1), asfloat(raw2), asfloat(raw3), asfloat(raw4)); + s.xlat = float2(asfloat(raw5), asfloat(raw6)); + s.c1 = float2(asfloat(raw7), asfloat(raw8)); + s.ra = asfloat(raw9); + s.roff = asfloat(raw10); + return s; +} + +CmdRadGrad Cmd_RadGrad_read(Alloc a, CmdRef ref) +{ + CmdRadGradRef _719 = { ref.offset + 4u }; + Alloc param = a; + CmdRadGradRef param_1 = _719; + return CmdRadGrad_read(param, param_1); +} + CmdImage CmdImage_read(Alloc a, CmdImageRef ref) { uint ix = ref.offset >> uint(2); @@ -393,9 +462,9 @@ CmdImage CmdImage_read(Alloc a, CmdImageRef ref) CmdImage Cmd_Image_read(Alloc a, CmdRef ref) { - CmdImageRef _582 = { ref.offset + 4u }; + CmdImageRef _729 = { ref.offset + 4u }; Alloc param = a; - CmdImageRef param_1 = _582; + CmdImageRef param_1 = _729; return CmdImage_read(param, param_1); } @@ -408,10 +477,10 @@ void fillImage(out float4 spvReturnValue[8], uint2 xy, CmdImage cmd_img) int2 uv = int2(xy + chunk_offset(param)) + cmd_img.offset; float4 fg_rgba = image_atlas[uv]; float3 param_1 = fg_rgba.xyz; - float3 _1493 = fromsRGB(param_1); - fg_rgba.x = _1493.x; - fg_rgba.y = _1493.y; - fg_rgba.z = _1493.z; + float3 _1638 = fromsRGB(param_1); + fg_rgba.x = _1638.x; + fg_rgba.y = _1638.y; + fg_rgba.z = _1638.z; rgba[i] = fg_rgba; } spvReturnValue = rgba; @@ -445,9 +514,9 @@ CmdEndClip CmdEndClip_read(Alloc a, CmdEndClipRef ref) CmdEndClip Cmd_EndClip_read(Alloc a, CmdRef ref) { - CmdEndClipRef _592 = { ref.offset + 4u }; + CmdEndClipRef _739 = { ref.offset + 4u }; Alloc param = a; - CmdEndClipRef param_1 = _592; + CmdEndClipRef param_1 = _739; return CmdEndClip_read(param, param_1); } @@ -637,8 +706,8 @@ float3 set_lum(float3 c, float l) { float3 param = c; float3 param_1 = c + (l - lum(param)).xxx; - float3 _901 = clip_color(param_1); - return _901; + float3 _1046 = clip_color(param_1); + return _1046; } float3 mix_blend(float3 cb, float3 cs, uint mode) @@ -726,9 +795,9 @@ float3 mix_blend(float3 cb, float3 cs, uint mode) float3 param_20 = cb; float3 param_21 = cs; float param_22 = sat(param_20); - float3 _1192 = set_sat(param_21, param_22); + float3 _1337 = set_sat(param_21, param_22); float3 param_23 = cb; - float3 param_24 = _1192; + float3 param_24 = _1337; float param_25 = lum(param_23); b = set_lum(param_24, param_25); break; @@ -738,9 +807,9 @@ float3 mix_blend(float3 cb, float3 cs, uint mode) float3 param_26 = cs; float3 param_27 = cb; float param_28 = sat(param_26); - float3 _1206 = set_sat(param_27, param_28); + float3 _1351 = set_sat(param_27, param_28); float3 param_29 = cb; - float3 param_30 = _1206; + float3 param_30 = _1351; float param_31 = lum(param_29); b = set_lum(param_30, param_31); break; @@ -877,24 +946,24 @@ CmdJump CmdJump_read(Alloc a, CmdJumpRef ref) CmdJump Cmd_Jump_read(Alloc a, CmdRef ref) { - CmdJumpRef _602 = { ref.offset + 4u }; + CmdJumpRef _749 = { ref.offset + 4u }; Alloc param = a; - CmdJumpRef param_1 = _602; + CmdJumpRef param_1 = _749; return CmdJump_read(param, param_1); } void comp_main() { - uint tile_ix = (gl_WorkGroupID.y * _1521.Load(8)) + gl_WorkGroupID.x; - Alloc _1536; - _1536.offset = _1521.Load(24); + uint tile_ix = (gl_WorkGroupID.y * _1666.Load(8)) + gl_WorkGroupID.x; + Alloc _1681; + _1681.offset = _1666.Load(24); Alloc param; - param.offset = _1536.offset; + param.offset = _1681.offset; uint param_1 = tile_ix * 1024u; uint param_2 = 1024u; Alloc cmd_alloc = slice_mem(param, param_1, param_2); - CmdRef _1545 = { cmd_alloc.offset }; - CmdRef cmd_ref = _1545; + CmdRef _1690 = { cmd_alloc.offset }; + CmdRef cmd_ref = _1690; uint2 xy_uint = uint2(gl_LocalInvocationID.x + (16u * gl_WorkGroupID.x), gl_LocalInvocationID.y + (16u * gl_WorkGroupID.y)); float2 xy = float2(xy_uint); float4 rgba[8]; @@ -903,7 +972,7 @@ void comp_main() rgba[i] = 0.0f.xxxx; } uint clip_depth = 0u; - bool mem_ok = _278.Load(4) == 0u; + bool mem_ok = _291.Load(4) == 0u; float df[8]; TileSegRef tile_seg_ref; float area[8]; @@ -928,8 +997,8 @@ void comp_main() { df[k] = 1000000000.0f; } - TileSegRef _1638 = { stroke.tile_ref }; - tile_seg_ref = _1638; + TileSegRef _1784 = { stroke.tile_ref }; + tile_seg_ref = _1784; do { uint param_7 = tile_seg_ref.offset; @@ -965,8 +1034,8 @@ void comp_main() { area[k_3] = float(fill.backdrop); } - TileSegRef _1758 = { fill.tile_ref }; - tile_seg_ref = _1758; + TileSegRef _1904 = { fill.tile_ref }; + tile_seg_ref = _1904; do { uint param_15 = tile_seg_ref.offset; @@ -1055,11 +1124,12 @@ void comp_main() int x = int(round(clamp(my_d, 0.0f, 1.0f) * 511.0f)); float4 fg_rgba = gradients[int2(x, int(lin.index))]; float3 param_29 = fg_rgba.xyz; - float3 _2092 = fromsRGB(param_29); - fg_rgba.x = _2092.x; - fg_rgba.y = _2092.y; - fg_rgba.z = _2092.z; - rgba[k_9] = fg_rgba; + float3 _2238 = fromsRGB(param_29); + fg_rgba.x = _2238.x; + fg_rgba.y = _2238.y; + fg_rgba.z = _2238.z; + float4 fg_k_1 = fg_rgba * area[k_9]; + rgba[k_9] = (rgba[k_9] * (1.0f - fg_k_1.w)) + fg_k_1; } cmd_ref.offset += 20u; break; @@ -1068,74 +1138,100 @@ void comp_main() { Alloc param_30 = cmd_alloc; CmdRef param_31 = cmd_ref; - CmdImage fill_img = Cmd_Image_read(param_30, param_31); - uint2 param_32 = xy_uint; - CmdImage param_33 = fill_img; - float4 _2121[8]; - fillImage(_2121, param_32, param_33); - float4 img[8] = _2121; + CmdRadGrad rad = Cmd_RadGrad_read(param_30, param_31); for (uint k_10 = 0u; k_10 < 8u; k_10++) { - float4 fg_k_1 = img[k_10] * area[k_10]; - rgba[k_10] = (rgba[k_10] * (1.0f - fg_k_1.w)) + fg_k_1; + uint param_32 = k_10; + float2 my_xy_1 = xy + float2(chunk_offset(param_32)); + my_xy_1 = ((rad.mat.xz * my_xy_1.x) + (rad.mat.yw * my_xy_1.y)) - rad.xlat; + float ba = dot(my_xy_1, rad.c1); + float ca = rad.ra * dot(my_xy_1, my_xy_1); + float t_2 = (sqrt((ba * ba) + ca) - ba) - rad.roff; + int x_1 = int(round(clamp(t_2, 0.0f, 1.0f) * 511.0f)); + float4 fg_rgba_1 = gradients[int2(x_1, int(rad.index))]; + float3 param_33 = fg_rgba_1.xyz; + float3 _2348 = fromsRGB(param_33); + fg_rgba_1.x = _2348.x; + fg_rgba_1.y = _2348.y; + fg_rgba_1.z = _2348.z; + float4 fg_k_2 = fg_rgba_1 * area[k_10]; + rgba[k_10] = (rgba[k_10] * (1.0f - fg_k_2.w)) + fg_k_2; } - cmd_ref.offset += 12u; + cmd_ref.offset += 48u; break; } case 8u: { + Alloc param_34 = cmd_alloc; + CmdRef param_35 = cmd_ref; + CmdImage fill_img = Cmd_Image_read(param_34, param_35); + uint2 param_36 = xy_uint; + CmdImage param_37 = fill_img; + float4 _2391[8]; + fillImage(_2391, param_36, param_37); + float4 img[8] = _2391; for (uint k_11 = 0u; k_11 < 8u; k_11++) + { + float4 fg_k_3 = img[k_11] * area[k_11]; + rgba[k_11] = (rgba[k_11] * (1.0f - fg_k_3.w)) + fg_k_3; + } + cmd_ref.offset += 12u; + break; + } + case 9u: + { + for (uint k_12 = 0u; k_12 < 8u; k_12++) { uint d_2 = min(clip_depth, 127u); - float4 param_34 = float4(rgba[k_11]); - uint _2184 = packsRGB(param_34); - blend_stack[d_2][k_11] = _2184; - rgba[k_11] = 0.0f.xxxx; + float4 param_38 = float4(rgba[k_12]); + uint _2454 = packsRGB(param_38); + blend_stack[d_2][k_12] = _2454; + rgba[k_12] = 0.0f.xxxx; } clip_depth++; cmd_ref.offset += 4u; break; } - case 9u: + case 10u: { - Alloc param_35 = cmd_alloc; - CmdRef param_36 = cmd_ref; - CmdEndClip end_clip = Cmd_EndClip_read(param_35, param_36); + Alloc param_39 = cmd_alloc; + CmdRef param_40 = cmd_ref; + CmdEndClip end_clip = Cmd_EndClip_read(param_39, param_40); uint blend_mode = end_clip.blend >> uint(8); uint comp_mode = end_clip.blend & 255u; clip_depth--; - for (uint k_12 = 0u; k_12 < 8u; k_12++) + for (uint k_13 = 0u; k_13 < 8u; k_13++) { uint d_3 = min(clip_depth, 127u); - uint param_37 = blend_stack[d_3][k_12]; - float4 bg = unpacksRGB(param_37); - float4 fg_1 = rgba[k_12] * area[k_12]; - float3 param_38 = bg.xyz; - float3 param_39 = fg_1.xyz; - uint param_40 = blend_mode; - float3 blend = mix_blend(param_38, param_39, param_40); - float4 _2251 = fg_1; - float _2255 = fg_1.w; - float3 _2262 = lerp(_2251.xyz, blend, float((_2255 * bg.w) > 0.0f).xxx); - fg_1.x = _2262.x; - fg_1.y = _2262.y; - fg_1.z = _2262.z; - float3 param_41 = bg.xyz; - float3 param_42 = fg_1.xyz; - float param_43 = bg.w; - float param_44 = fg_1.w; - uint param_45 = comp_mode; - rgba[k_12] = mix_compose(param_41, param_42, param_43, param_44, param_45); + uint param_41 = blend_stack[d_3][k_13]; + float4 bg = unpacksRGB(param_41); + float4 fg_1 = rgba[k_13] * area[k_13]; + float3 param_42 = bg.xyz; + float3 param_43 = fg_1.xyz; + uint param_44 = blend_mode; + float3 blend = mix_blend(param_42, param_43, param_44); + float4 _2521 = fg_1; + float _2525 = fg_1.w; + float3 _2532 = lerp(_2521.xyz, blend, float((_2525 * bg.w) > 0.0f).xxx); + fg_1.x = _2532.x; + fg_1.y = _2532.y; + fg_1.z = _2532.z; + float3 param_45 = bg.xyz; + float3 param_46 = fg_1.xyz; + float param_47 = bg.w; + float param_48 = fg_1.w; + uint param_49 = comp_mode; + rgba[k_13] = mix_compose(param_45, param_46, param_47, param_48, param_49); } cmd_ref.offset += 8u; break; } - case 10u: + case 11u: { - Alloc param_46 = cmd_alloc; - CmdRef param_47 = cmd_ref; - CmdRef _2299 = { Cmd_Jump_read(param_46, param_47).new_ref }; - cmd_ref = _2299; + Alloc param_50 = cmd_alloc; + CmdRef param_51 = cmd_ref; + CmdRef _2569 = { Cmd_Jump_read(param_50, param_51).new_ref }; + cmd_ref = _2569; cmd_alloc.offset = cmd_ref.offset; break; } @@ -1143,8 +1239,8 @@ void comp_main() } for (uint i_1 = 0u; i_1 < 8u; i_1++) { - uint param_48 = i_1; - image[int2(xy_uint + chunk_offset(param_48))] = rgba[i_1].w.x; + uint param_52 = i_1; + image[int2(xy_uint + chunk_offset(param_52))] = rgba[i_1].w.x; } } diff --git a/piet-gpu/shader/gen/kernel4_gray.msl b/piet-gpu/shader/gen/kernel4_gray.msl index 5128e99..6402c6f 100644 --- a/piet-gpu/shader/gen/kernel4_gray.msl +++ b/piet-gpu/shader/gen/kernel4_gray.msl @@ -94,6 +94,21 @@ struct CmdLinGrad float line_c; }; +struct CmdRadGradRef +{ + uint offset; +}; + +struct CmdRadGrad +{ + uint index; + float4 mat; + float2 xlat; + float2 c1; + float ra; + float roff; +}; + struct CmdImageRef { uint offset; @@ -222,7 +237,7 @@ bool touch_mem(thread const Alloc& alloc, thread const uint& offset) } static inline __attribute__((always_inline)) -uint read_mem(thread const Alloc& alloc, thread const uint& offset, device Memory& v_278) +uint read_mem(thread const Alloc& alloc, thread const uint& offset, device Memory& v_291) { Alloc param = alloc; uint param_1 = offset; @@ -230,29 +245,29 @@ uint read_mem(thread const Alloc& alloc, thread const uint& offset, device Memor { return 0u; } - uint v = v_278.memory[offset]; + uint v = v_291.memory[offset]; return v; } static inline __attribute__((always_inline)) -CmdTag Cmd_tag(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_278) +CmdTag Cmd_tag(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_291) { Alloc param = a; uint param_1 = ref.offset >> uint(2); - uint tag_and_flags = read_mem(param, param_1, v_278); + uint tag_and_flags = read_mem(param, param_1, v_291); return CmdTag{ tag_and_flags & 65535u, tag_and_flags >> uint(16) }; } static inline __attribute__((always_inline)) -CmdStroke CmdStroke_read(thread const Alloc& a, thread const CmdStrokeRef& ref, device Memory& v_278) +CmdStroke CmdStroke_read(thread const Alloc& a, thread const CmdStrokeRef& ref, device Memory& v_291) { uint ix = ref.offset >> uint(2); Alloc param = a; uint param_1 = ix + 0u; - uint raw0 = read_mem(param, param_1, v_278); + uint raw0 = read_mem(param, param_1, v_291); Alloc param_2 = a; uint param_3 = ix + 1u; - uint raw1 = read_mem(param_2, param_3, v_278); + uint raw1 = read_mem(param_2, param_3, v_291); CmdStroke s; s.tile_ref = raw0; s.half_width = as_type(raw1); @@ -260,11 +275,11 @@ CmdStroke CmdStroke_read(thread const Alloc& a, thread const CmdStrokeRef& ref, } static inline __attribute__((always_inline)) -CmdStroke Cmd_Stroke_read(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_278) +CmdStroke Cmd_Stroke_read(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_291) { Alloc param = a; CmdStrokeRef param_1 = CmdStrokeRef{ ref.offset + 4u }; - return CmdStroke_read(param, param_1, v_278); + return CmdStroke_read(param, param_1, v_291); } static inline __attribute__((always_inline)) @@ -276,27 +291,27 @@ Alloc new_alloc(thread const uint& offset, thread const uint& size, thread const } static inline __attribute__((always_inline)) -TileSeg TileSeg_read(thread const Alloc& a, thread const TileSegRef& ref, device Memory& v_278) +TileSeg TileSeg_read(thread const Alloc& a, thread const TileSegRef& ref, device Memory& v_291) { uint ix = ref.offset >> uint(2); Alloc param = a; uint param_1 = ix + 0u; - uint raw0 = read_mem(param, param_1, v_278); + uint raw0 = read_mem(param, param_1, v_291); Alloc param_2 = a; uint param_3 = ix + 1u; - uint raw1 = read_mem(param_2, param_3, v_278); + uint raw1 = read_mem(param_2, param_3, v_291); Alloc param_4 = a; uint param_5 = ix + 2u; - uint raw2 = read_mem(param_4, param_5, v_278); + uint raw2 = read_mem(param_4, param_5, v_291); Alloc param_6 = a; uint param_7 = ix + 3u; - uint raw3 = read_mem(param_6, param_7, v_278); + uint raw3 = read_mem(param_6, param_7, v_291); Alloc param_8 = a; uint param_9 = ix + 4u; - uint raw4 = read_mem(param_8, param_9, v_278); + uint raw4 = read_mem(param_8, param_9, v_291); Alloc param_10 = a; uint param_11 = ix + 5u; - uint raw5 = read_mem(param_10, param_11, v_278); + uint raw5 = read_mem(param_10, param_11, v_291); TileSeg s; s.origin = float2(as_type(raw0), as_type(raw1)); s.vector = float2(as_type(raw2), as_type(raw3)); @@ -312,15 +327,15 @@ uint2 chunk_offset(thread const uint& i) } static inline __attribute__((always_inline)) -CmdFill CmdFill_read(thread const Alloc& a, thread const CmdFillRef& ref, device Memory& v_278) +CmdFill CmdFill_read(thread const Alloc& a, thread const CmdFillRef& ref, device Memory& v_291) { uint ix = ref.offset >> uint(2); Alloc param = a; uint param_1 = ix + 0u; - uint raw0 = read_mem(param, param_1, v_278); + uint raw0 = read_mem(param, param_1, v_291); Alloc param_2 = a; uint param_3 = ix + 1u; - uint raw1 = read_mem(param_2, param_3, v_278); + uint raw1 = read_mem(param_2, param_3, v_291); CmdFill s; s.tile_ref = raw0; s.backdrop = int(raw1); @@ -328,51 +343,51 @@ CmdFill CmdFill_read(thread const Alloc& a, thread const CmdFillRef& ref, device } static inline __attribute__((always_inline)) -CmdFill Cmd_Fill_read(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_278) +CmdFill Cmd_Fill_read(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_291) { Alloc param = a; CmdFillRef param_1 = CmdFillRef{ ref.offset + 4u }; - return CmdFill_read(param, param_1, v_278); + return CmdFill_read(param, param_1, v_291); } static inline __attribute__((always_inline)) -CmdAlpha CmdAlpha_read(thread const Alloc& a, thread const CmdAlphaRef& ref, device Memory& v_278) +CmdAlpha CmdAlpha_read(thread const Alloc& a, thread const CmdAlphaRef& ref, device Memory& v_291) { uint ix = ref.offset >> uint(2); Alloc param = a; uint param_1 = ix + 0u; - uint raw0 = read_mem(param, param_1, v_278); + uint raw0 = read_mem(param, param_1, v_291); CmdAlpha s; s.alpha = as_type(raw0); return s; } static inline __attribute__((always_inline)) -CmdAlpha Cmd_Alpha_read(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_278) +CmdAlpha Cmd_Alpha_read(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_291) { Alloc param = a; CmdAlphaRef param_1 = CmdAlphaRef{ ref.offset + 4u }; - return CmdAlpha_read(param, param_1, v_278); + return CmdAlpha_read(param, param_1, v_291); } static inline __attribute__((always_inline)) -CmdColor CmdColor_read(thread const Alloc& a, thread const CmdColorRef& ref, device Memory& v_278) +CmdColor CmdColor_read(thread const Alloc& a, thread const CmdColorRef& ref, device Memory& v_291) { uint ix = ref.offset >> uint(2); Alloc param = a; uint param_1 = ix + 0u; - uint raw0 = read_mem(param, param_1, v_278); + uint raw0 = read_mem(param, param_1, v_291); CmdColor s; s.rgba_color = raw0; return s; } static inline __attribute__((always_inline)) -CmdColor Cmd_Color_read(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_278) +CmdColor Cmd_Color_read(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_291) { Alloc param = a; CmdColorRef param_1 = CmdColorRef{ ref.offset + 4u }; - return CmdColor_read(param, param_1, v_278); + return CmdColor_read(param, param_1, v_291); } static inline __attribute__((always_inline)) @@ -393,21 +408,21 @@ float4 unpacksRGB(thread const uint& srgba) } static inline __attribute__((always_inline)) -CmdLinGrad CmdLinGrad_read(thread const Alloc& a, thread const CmdLinGradRef& ref, device Memory& v_278) +CmdLinGrad CmdLinGrad_read(thread const Alloc& a, thread const CmdLinGradRef& ref, device Memory& v_291) { uint ix = ref.offset >> uint(2); Alloc param = a; uint param_1 = ix + 0u; - uint raw0 = read_mem(param, param_1, v_278); + uint raw0 = read_mem(param, param_1, v_291); Alloc param_2 = a; uint param_3 = ix + 1u; - uint raw1 = read_mem(param_2, param_3, v_278); + uint raw1 = read_mem(param_2, param_3, v_291); Alloc param_4 = a; uint param_5 = ix + 2u; - uint raw2 = read_mem(param_4, param_5, v_278); + uint raw2 = read_mem(param_4, param_5, v_291); Alloc param_6 = a; uint param_7 = ix + 3u; - uint raw3 = read_mem(param_6, param_7, v_278); + uint raw3 = read_mem(param_6, param_7, v_291); CmdLinGrad s; s.index = raw0; s.line_x = as_type(raw1); @@ -417,23 +432,78 @@ CmdLinGrad CmdLinGrad_read(thread const Alloc& a, thread const CmdLinGradRef& re } static inline __attribute__((always_inline)) -CmdLinGrad Cmd_LinGrad_read(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_278) +CmdLinGrad Cmd_LinGrad_read(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_291) { Alloc param = a; CmdLinGradRef param_1 = CmdLinGradRef{ ref.offset + 4u }; - return CmdLinGrad_read(param, param_1, v_278); + return CmdLinGrad_read(param, param_1, v_291); } static inline __attribute__((always_inline)) -CmdImage CmdImage_read(thread const Alloc& a, thread const CmdImageRef& ref, device Memory& v_278) +CmdRadGrad CmdRadGrad_read(thread const Alloc& a, thread const CmdRadGradRef& ref, device Memory& v_291) { uint ix = ref.offset >> uint(2); Alloc param = a; uint param_1 = ix + 0u; - uint raw0 = read_mem(param, param_1, v_278); + uint raw0 = read_mem(param, param_1, v_291); Alloc param_2 = a; uint param_3 = ix + 1u; - uint raw1 = read_mem(param_2, param_3, v_278); + uint raw1 = read_mem(param_2, param_3, v_291); + Alloc param_4 = a; + uint param_5 = ix + 2u; + uint raw2 = read_mem(param_4, param_5, v_291); + Alloc param_6 = a; + uint param_7 = ix + 3u; + uint raw3 = read_mem(param_6, param_7, v_291); + Alloc param_8 = a; + uint param_9 = ix + 4u; + uint raw4 = read_mem(param_8, param_9, v_291); + Alloc param_10 = a; + uint param_11 = ix + 5u; + uint raw5 = read_mem(param_10, param_11, v_291); + Alloc param_12 = a; + uint param_13 = ix + 6u; + uint raw6 = read_mem(param_12, param_13, v_291); + Alloc param_14 = a; + uint param_15 = ix + 7u; + uint raw7 = read_mem(param_14, param_15, v_291); + Alloc param_16 = a; + uint param_17 = ix + 8u; + uint raw8 = read_mem(param_16, param_17, v_291); + Alloc param_18 = a; + uint param_19 = ix + 9u; + uint raw9 = read_mem(param_18, param_19, v_291); + Alloc param_20 = a; + uint param_21 = ix + 10u; + uint raw10 = read_mem(param_20, param_21, v_291); + CmdRadGrad s; + s.index = raw0; + s.mat = float4(as_type(raw1), as_type(raw2), as_type(raw3), as_type(raw4)); + s.xlat = float2(as_type(raw5), as_type(raw6)); + s.c1 = float2(as_type(raw7), as_type(raw8)); + s.ra = as_type(raw9); + s.roff = as_type(raw10); + return s; +} + +static inline __attribute__((always_inline)) +CmdRadGrad Cmd_RadGrad_read(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_291) +{ + Alloc param = a; + CmdRadGradRef param_1 = CmdRadGradRef{ ref.offset + 4u }; + return CmdRadGrad_read(param, param_1, v_291); +} + +static inline __attribute__((always_inline)) +CmdImage CmdImage_read(thread const Alloc& a, thread const CmdImageRef& ref, device Memory& v_291) +{ + uint ix = ref.offset >> uint(2); + Alloc param = a; + uint param_1 = ix + 0u; + uint raw0 = read_mem(param, param_1, v_291); + Alloc param_2 = a; + uint param_3 = ix + 1u; + uint raw1 = read_mem(param_2, param_3, v_291); CmdImage s; s.index = raw0; s.offset = int2(int(raw1 << uint(16)) >> 16, int(raw1) >> 16); @@ -441,11 +511,11 @@ CmdImage CmdImage_read(thread const Alloc& a, thread const CmdImageRef& ref, dev } static inline __attribute__((always_inline)) -CmdImage Cmd_Image_read(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_278) +CmdImage Cmd_Image_read(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_291) { Alloc param = a; CmdImageRef param_1 = CmdImageRef{ ref.offset + 4u }; - return CmdImage_read(param, param_1, v_278); + return CmdImage_read(param, param_1, v_291); } static inline __attribute__((always_inline)) @@ -458,10 +528,10 @@ spvUnsafeArray fillImage(thread const uint2& xy, thread const CmdImag int2 uv = int2(xy + chunk_offset(param)) + cmd_img.offset; float4 fg_rgba = image_atlas.read(uint2(uv)); float3 param_1 = fg_rgba.xyz; - float3 _1493 = fromsRGB(param_1); - fg_rgba.x = _1493.x; - fg_rgba.y = _1493.y; - fg_rgba.z = _1493.z; + float3 _1638 = fromsRGB(param_1); + fg_rgba.x = _1638.x; + fg_rgba.y = _1638.y; + fg_rgba.z = _1638.z; rgba[i] = fg_rgba; } return rgba; @@ -485,23 +555,23 @@ uint packsRGB(thread float4& rgba) } static inline __attribute__((always_inline)) -CmdEndClip CmdEndClip_read(thread const Alloc& a, thread const CmdEndClipRef& ref, device Memory& v_278) +CmdEndClip CmdEndClip_read(thread const Alloc& a, thread const CmdEndClipRef& ref, device Memory& v_291) { uint ix = ref.offset >> uint(2); Alloc param = a; uint param_1 = ix + 0u; - uint raw0 = read_mem(param, param_1, v_278); + uint raw0 = read_mem(param, param_1, v_291); CmdEndClip s; s.blend = raw0; return s; } static inline __attribute__((always_inline)) -CmdEndClip Cmd_EndClip_read(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_278) +CmdEndClip Cmd_EndClip_read(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_291) { Alloc param = a; CmdEndClipRef param_1 = CmdEndClipRef{ ref.offset + 4u }; - return CmdEndClip_read(param, param_1, v_278); + return CmdEndClip_read(param, param_1, v_291); } static inline __attribute__((always_inline)) @@ -701,8 +771,8 @@ float3 set_lum(thread const float3& c, thread const float& l) { float3 param = c; float3 param_1 = c + float3(l - lum(param)); - float3 _901 = clip_color(param_1); - return _901; + float3 _1046 = clip_color(param_1); + return _1046; } static inline __attribute__((always_inline)) @@ -791,9 +861,9 @@ float3 mix_blend(thread const float3& cb, thread const float3& cs, thread const float3 param_20 = cb; float3 param_21 = cs; float param_22 = sat(param_20); - float3 _1192 = set_sat(param_21, param_22); + float3 _1337 = set_sat(param_21, param_22); float3 param_23 = cb; - float3 param_24 = _1192; + float3 param_24 = _1337; float param_25 = lum(param_23); b = set_lum(param_24, param_25); break; @@ -803,9 +873,9 @@ float3 mix_blend(thread const float3& cb, thread const float3& cs, thread const float3 param_26 = cs; float3 param_27 = cb; float param_28 = sat(param_26); - float3 _1206 = set_sat(param_27, param_28); + float3 _1351 = set_sat(param_27, param_28); float3 param_29 = cb; - float3 param_30 = _1206; + float3 param_30 = _1351; float param_31 = lum(param_29); b = set_lum(param_30, param_31); break; @@ -931,30 +1001,30 @@ float4 mix_compose(thread const float3& cb, thread const float3& cs, thread cons } static inline __attribute__((always_inline)) -CmdJump CmdJump_read(thread const Alloc& a, thread const CmdJumpRef& ref, device Memory& v_278) +CmdJump CmdJump_read(thread const Alloc& a, thread const CmdJumpRef& ref, device Memory& v_291) { uint ix = ref.offset >> uint(2); Alloc param = a; uint param_1 = ix + 0u; - uint raw0 = read_mem(param, param_1, v_278); + uint raw0 = read_mem(param, param_1, v_291); CmdJump s; s.new_ref = raw0; return s; } static inline __attribute__((always_inline)) -CmdJump Cmd_Jump_read(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_278) +CmdJump Cmd_Jump_read(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_291) { Alloc param = a; CmdJumpRef param_1 = CmdJumpRef{ ref.offset + 4u }; - return CmdJump_read(param, param_1, v_278); + return CmdJump_read(param, param_1, v_291); } -kernel void main0(device Memory& v_278 [[buffer(0)]], const device ConfigBuf& _1521 [[buffer(1)]], texture2d image [[texture(2)]], texture2d image_atlas [[texture(3)]], texture2d gradients [[texture(4)]], uint3 gl_WorkGroupID [[threadgroup_position_in_grid]], uint3 gl_LocalInvocationID [[thread_position_in_threadgroup]]) +kernel void main0(device Memory& v_291 [[buffer(0)]], const device ConfigBuf& _1666 [[buffer(1)]], texture2d image [[texture(2)]], texture2d image_atlas [[texture(3)]], texture2d gradients [[texture(4)]], uint3 gl_WorkGroupID [[threadgroup_position_in_grid]], uint3 gl_LocalInvocationID [[thread_position_in_threadgroup]]) { - uint tile_ix = (gl_WorkGroupID.y * _1521.conf.width_in_tiles) + gl_WorkGroupID.x; + uint tile_ix = (gl_WorkGroupID.y * _1666.conf.width_in_tiles) + gl_WorkGroupID.x; Alloc param; - param.offset = _1521.conf.ptcl_alloc.offset; + param.offset = _1666.conf.ptcl_alloc.offset; uint param_1 = tile_ix * 1024u; uint param_2 = 1024u; Alloc cmd_alloc = slice_mem(param, param_1, param_2); @@ -967,7 +1037,7 @@ kernel void main0(device Memory& v_278 [[buffer(0)]], const device ConfigBuf& _1 rgba[i] = float4(0.0); } uint clip_depth = 0u; - bool mem_ok = v_278.mem_error == 0u; + bool mem_ok = v_291.mem_error == 0u; spvUnsafeArray df; TileSegRef tile_seg_ref; spvUnsafeArray area; @@ -976,7 +1046,7 @@ kernel void main0(device Memory& v_278 [[buffer(0)]], const device ConfigBuf& _1 { Alloc param_3 = cmd_alloc; CmdRef param_4 = cmd_ref; - uint tag = Cmd_tag(param_3, param_4, v_278).tag; + uint tag = Cmd_tag(param_3, param_4, v_291).tag; if (tag == 0u) { break; @@ -987,7 +1057,7 @@ kernel void main0(device Memory& v_278 [[buffer(0)]], const device ConfigBuf& _1 { Alloc param_5 = cmd_alloc; CmdRef param_6 = cmd_ref; - CmdStroke stroke = Cmd_Stroke_read(param_5, param_6, v_278); + CmdStroke stroke = Cmd_Stroke_read(param_5, param_6, v_291); for (uint k = 0u; k < 8u; k++) { df[k] = 1000000000.0; @@ -1000,7 +1070,7 @@ kernel void main0(device Memory& v_278 [[buffer(0)]], const device ConfigBuf& _1 bool param_9 = mem_ok; Alloc param_10 = new_alloc(param_7, param_8, param_9); TileSegRef param_11 = tile_seg_ref; - TileSeg seg = TileSeg_read(param_10, param_11, v_278); + TileSeg seg = TileSeg_read(param_10, param_11, v_291); float2 line_vec = seg.vector; for (uint k_1 = 0u; k_1 < 8u; k_1++) { @@ -1023,7 +1093,7 @@ kernel void main0(device Memory& v_278 [[buffer(0)]], const device ConfigBuf& _1 { Alloc param_13 = cmd_alloc; CmdRef param_14 = cmd_ref; - CmdFill fill = Cmd_Fill_read(param_13, param_14, v_278); + CmdFill fill = Cmd_Fill_read(param_13, param_14, v_291); for (uint k_3 = 0u; k_3 < 8u; k_3++) { area[k_3] = float(fill.backdrop); @@ -1036,7 +1106,7 @@ kernel void main0(device Memory& v_278 [[buffer(0)]], const device ConfigBuf& _1 bool param_17 = mem_ok; Alloc param_18 = new_alloc(param_15, param_16, param_17); TileSegRef param_19 = tile_seg_ref; - TileSeg seg_1 = TileSeg_read(param_18, param_19, v_278); + TileSeg seg_1 = TileSeg_read(param_18, param_19, v_291); for (uint k_4 = 0u; k_4 < 8u; k_4++) { uint param_20 = k_4; @@ -1080,7 +1150,7 @@ kernel void main0(device Memory& v_278 [[buffer(0)]], const device ConfigBuf& _1 { Alloc param_21 = cmd_alloc; CmdRef param_22 = cmd_ref; - CmdAlpha alpha = Cmd_Alpha_read(param_21, param_22, v_278); + CmdAlpha alpha = Cmd_Alpha_read(param_21, param_22, v_291); for (uint k_7 = 0u; k_7 < 8u; k_7++) { area[k_7] = alpha.alpha; @@ -1092,7 +1162,7 @@ kernel void main0(device Memory& v_278 [[buffer(0)]], const device ConfigBuf& _1 { Alloc param_23 = cmd_alloc; CmdRef param_24 = cmd_ref; - CmdColor color = Cmd_Color_read(param_23, param_24, v_278); + CmdColor color = Cmd_Color_read(param_23, param_24, v_291); uint param_25 = color.rgba_color; float4 fg = unpacksRGB(param_25); for (uint k_8 = 0u; k_8 < 8u; k_8++) @@ -1107,7 +1177,7 @@ kernel void main0(device Memory& v_278 [[buffer(0)]], const device ConfigBuf& _1 { Alloc param_26 = cmd_alloc; CmdRef param_27 = cmd_ref; - CmdLinGrad lin = Cmd_LinGrad_read(param_26, param_27, v_278); + CmdLinGrad lin = Cmd_LinGrad_read(param_26, param_27, v_291); float d_1 = ((lin.line_x * xy.x) + (lin.line_y * xy.y)) + lin.line_c; for (uint k_9 = 0u; k_9 < 8u; k_9++) { @@ -1117,11 +1187,12 @@ kernel void main0(device Memory& v_278 [[buffer(0)]], const device ConfigBuf& _1 int x = int(round(fast::clamp(my_d, 0.0, 1.0) * 511.0)); float4 fg_rgba = gradients.read(uint2(int2(x, int(lin.index)))); float3 param_29 = fg_rgba.xyz; - float3 _2092 = fromsRGB(param_29); - fg_rgba.x = _2092.x; - fg_rgba.y = _2092.y; - fg_rgba.z = _2092.z; - rgba[k_9] = fg_rgba; + float3 _2238 = fromsRGB(param_29); + fg_rgba.x = _2238.x; + fg_rgba.y = _2238.y; + fg_rgba.z = _2238.z; + float4 fg_k_1 = fg_rgba * area[k_9]; + rgba[k_9] = (rgba[k_9] * (1.0 - fg_k_1.w)) + fg_k_1; } cmd_ref.offset += 20u; break; @@ -1130,72 +1201,98 @@ kernel void main0(device Memory& v_278 [[buffer(0)]], const device ConfigBuf& _1 { Alloc param_30 = cmd_alloc; CmdRef param_31 = cmd_ref; - CmdImage fill_img = Cmd_Image_read(param_30, param_31, v_278); - uint2 param_32 = xy_uint; - CmdImage param_33 = fill_img; - spvUnsafeArray img; - img = fillImage(param_32, param_33, image_atlas); + CmdRadGrad rad = Cmd_RadGrad_read(param_30, param_31, v_291); for (uint k_10 = 0u; k_10 < 8u; k_10++) { - float4 fg_k_1 = img[k_10] * area[k_10]; - rgba[k_10] = (rgba[k_10] * (1.0 - fg_k_1.w)) + fg_k_1; + uint param_32 = k_10; + float2 my_xy_1 = xy + float2(chunk_offset(param_32)); + my_xy_1 = ((rad.mat.xz * my_xy_1.x) + (rad.mat.yw * my_xy_1.y)) - rad.xlat; + float ba = dot(my_xy_1, rad.c1); + float ca = rad.ra * dot(my_xy_1, my_xy_1); + float t_2 = (sqrt((ba * ba) + ca) - ba) - rad.roff; + int x_1 = int(round(fast::clamp(t_2, 0.0, 1.0) * 511.0)); + float4 fg_rgba_1 = gradients.read(uint2(int2(x_1, int(rad.index)))); + float3 param_33 = fg_rgba_1.xyz; + float3 _2348 = fromsRGB(param_33); + fg_rgba_1.x = _2348.x; + fg_rgba_1.y = _2348.y; + fg_rgba_1.z = _2348.z; + float4 fg_k_2 = fg_rgba_1 * area[k_10]; + rgba[k_10] = (rgba[k_10] * (1.0 - fg_k_2.w)) + fg_k_2; } - cmd_ref.offset += 12u; + cmd_ref.offset += 48u; break; } case 8u: { + Alloc param_34 = cmd_alloc; + CmdRef param_35 = cmd_ref; + CmdImage fill_img = Cmd_Image_read(param_34, param_35, v_291); + uint2 param_36 = xy_uint; + CmdImage param_37 = fill_img; + spvUnsafeArray img; + img = fillImage(param_36, param_37, image_atlas); for (uint k_11 = 0u; k_11 < 8u; k_11++) + { + float4 fg_k_3 = img[k_11] * area[k_11]; + rgba[k_11] = (rgba[k_11] * (1.0 - fg_k_3.w)) + fg_k_3; + } + cmd_ref.offset += 12u; + break; + } + case 9u: + { + for (uint k_12 = 0u; k_12 < 8u; k_12++) { uint d_2 = min(clip_depth, 127u); - float4 param_34 = float4(rgba[k_11]); - uint _2184 = packsRGB(param_34); - blend_stack[d_2][k_11] = _2184; - rgba[k_11] = float4(0.0); + float4 param_38 = float4(rgba[k_12]); + uint _2454 = packsRGB(param_38); + blend_stack[d_2][k_12] = _2454; + rgba[k_12] = float4(0.0); } clip_depth++; cmd_ref.offset += 4u; break; } - case 9u: + case 10u: { - Alloc param_35 = cmd_alloc; - CmdRef param_36 = cmd_ref; - CmdEndClip end_clip = Cmd_EndClip_read(param_35, param_36, v_278); + Alloc param_39 = cmd_alloc; + CmdRef param_40 = cmd_ref; + CmdEndClip end_clip = Cmd_EndClip_read(param_39, param_40, v_291); uint blend_mode = end_clip.blend >> uint(8); uint comp_mode = end_clip.blend & 255u; clip_depth--; - for (uint k_12 = 0u; k_12 < 8u; k_12++) + for (uint k_13 = 0u; k_13 < 8u; k_13++) { uint d_3 = min(clip_depth, 127u); - uint param_37 = blend_stack[d_3][k_12]; - float4 bg = unpacksRGB(param_37); - float4 fg_1 = rgba[k_12] * area[k_12]; - float3 param_38 = bg.xyz; - float3 param_39 = fg_1.xyz; - uint param_40 = blend_mode; - float3 blend = mix_blend(param_38, param_39, param_40); - float4 _2251 = fg_1; - float _2255 = fg_1.w; - float3 _2262 = mix(_2251.xyz, blend, float3(float((_2255 * bg.w) > 0.0))); - fg_1.x = _2262.x; - fg_1.y = _2262.y; - fg_1.z = _2262.z; - float3 param_41 = bg.xyz; - float3 param_42 = fg_1.xyz; - float param_43 = bg.w; - float param_44 = fg_1.w; - uint param_45 = comp_mode; - rgba[k_12] = mix_compose(param_41, param_42, param_43, param_44, param_45); + uint param_41 = blend_stack[d_3][k_13]; + float4 bg = unpacksRGB(param_41); + float4 fg_1 = rgba[k_13] * area[k_13]; + float3 param_42 = bg.xyz; + float3 param_43 = fg_1.xyz; + uint param_44 = blend_mode; + float3 blend = mix_blend(param_42, param_43, param_44); + float4 _2521 = fg_1; + float _2525 = fg_1.w; + float3 _2532 = mix(_2521.xyz, blend, float3(float((_2525 * bg.w) > 0.0))); + fg_1.x = _2532.x; + fg_1.y = _2532.y; + fg_1.z = _2532.z; + float3 param_45 = bg.xyz; + float3 param_46 = fg_1.xyz; + float param_47 = bg.w; + float param_48 = fg_1.w; + uint param_49 = comp_mode; + rgba[k_13] = mix_compose(param_45, param_46, param_47, param_48, param_49); } cmd_ref.offset += 8u; break; } - case 10u: + case 11u: { - Alloc param_46 = cmd_alloc; - CmdRef param_47 = cmd_ref; - cmd_ref = CmdRef{ Cmd_Jump_read(param_46, param_47, v_278).new_ref }; + Alloc param_50 = cmd_alloc; + CmdRef param_51 = cmd_ref; + cmd_ref = CmdRef{ Cmd_Jump_read(param_50, param_51, v_291).new_ref }; cmd_alloc.offset = cmd_ref.offset; break; } @@ -1203,8 +1300,8 @@ kernel void main0(device Memory& v_278 [[buffer(0)]], const device ConfigBuf& _1 } for (uint i_1 = 0u; i_1 < 8u; i_1++) { - uint param_48 = i_1; - image.write(float4(rgba[i_1].w), uint2(int2(xy_uint + chunk_offset(param_48)))); + uint param_52 = i_1; + image.write(float4(rgba[i_1].w), uint2(int2(xy_uint + chunk_offset(param_52)))); } } diff --git a/piet-gpu/shader/gen/kernel4_gray.spv b/piet-gpu/shader/gen/kernel4_gray.spv index 791b76cbe5790b68def82df39f9028af0fbc4b61..4633401878da028ffb233d5fda00be249864c016 100644 GIT binary patch literal 65312 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 CD&wO7 literal 58352 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 LKhH(6=i>hd17EVE diff --git a/piet-gpu/shader/gen/tile_alloc.dxil b/piet-gpu/shader/gen/tile_alloc.dxil index 7759910ca527b4ff12fbe9ba3ee03fdb6a428ca7..7b130e013427d747d2d4199badc1dcd7fb8e8297 100644 GIT binary patch delta 1185 zcmZ8hYfM{Z82(N>)fywCeQ zKR&-Ypw1|_n#|yT4`Fk-knujR?Bc+0q_X1Oo&r1B_DjAp7&TJ| zxS%%;HEd}W{9+^Y4$&wwrdKV8VI&6GIH*@e!f=g^F~*(GYYo=H`EwCd6=5V+OX}!; za?4Pj4r-y_UEXLN{|TKW7Wo`Y9R%kh^TG(`iIzCcUCrcrSCwn(mp^~l8Nr@ZHtbY# zb^Xuff7f0(E4(^O^tSFg+8xQh8nwFJ46!tyj@A=41=cd({4{DK^n}BLwOIOwR_9jp zhGy;#Icwl)WyG~mL`|Ih&@~~3b;JjA;M2Ny+T;Rv2cd{B2vM7m@PER z-K?_#jI}El;{%T^a2!NWE)t^KkYM(USJ0nfv9 zao1%3hN+o;se-K{5^l4WWHSBvs6qJIFr){N_@>To3w9!ll0!*m&~4vj+D%|MhudHR z=^^*kXTTr1?@_0qwAYjAGxFWv>xgo#os84oSKl=zW0Tr(2;TaG`2-r0yMyU5B*8Z- z=!qqN8E;BdjVtm)zS$VJ8P0@Ro~A%YUN5VU$Lgb3OzL6do?wcPbQ%}e>BA)r_!j|; z(XdC;)DBG5A1H1DMax6OYq=Q4!h!>4H7WtExIEgnOalWXhR;j;wmD?&t)#!6S>X1h zOjAXog5GUUcFa>2-!#A=ta9z|op^tlUz!y+Cn@zh zMG~<60Pfb>JL3k_zPj%Tr{rSXxPpzyF*KT(d9sIJc{u_0rhW^hdKGm~q~Z9IC`5d$ zez!9vg89S*sr(ywAN135+BSj|cphM9v|R0&qiQV3bKMkqlYvn?W(jAVSE@{QRb`H} zxD-G%3C{}~B~|tkB`Ad4&~`TUkywI-0Q$e;6+ zZRl*AN y({e>iD`%D}8khR2PrpvZ(xj@}wmU)Gn9-5(u~O|l8mUGd^A372$o?Jwy?+3ac!wAO delta 1180 zcmYLJe@q)?82;{hcfE2QTuVx?EsQG^>|EWhY$A2h^a@T;HXDOk`C%-DDH=e=HnZs> zZGm#j8ZBP8q0?E0b4^yv_%R%bGi`wdHh&aEDN0DeEkRA@Vy2skAzrhh-(T-P;vA z^KO}~qOzF)zz$IG6AVD|4g@$UFsg*Sr8K;(l>#s~62TYYTLhWpQiF4_Q{p!Inuuo)o}v9vF$;nc*xEvk*2m4HZLCEfB7!C9 zueKgKw*2GLTw;0c`qG;DS}b~#+H?MLWay+zdR0mfhMZOjinickyW5H_cvc9JG0q%m zpfL?rM2n34N9aQ^JiuQ=X+_{y-^#due0Js*d-eSI?ALoFB>;@%V%0Ej&#-iu<^h`z z3d}PUguCh6v&_5<2LNgUARm(ex7~M{eKY{6xd_L?PMT_LwJTn;V-1YM2WT8y)YN&@ zAxPz=D1f^o2gEV;e<7*yQnZkTlwt?d714ML5%Z>x{bZPflAYQP+p(v!c`d2z_{7z| z7-_Nqf01~f1t>zUcODQI#H|2*i}`>ABS_SY(#T&x`WSMI#3nXHHC?R4^-YnqjBz-V zN|y97R)O^=!7uz7IZ2w)Hv)=zC?(-^+M6--Lb9mT)uNj>Bn&3R^<=0cD$K6)H5UYg zopE93@RVEcXYZs9NT4=$`1{F?F8hd2eOSaGED}a%YJSH4P#GCOBBEQ$b@~dR8&=Iv z=3|)9Ai#C%5hZ9Oa;9II3v>lmFVeWzS6T4F6&WtZfs#wP_$P6%7%A@jadw+4JPheegsZ+ZS zI#)c2oUr{Aw8g!G)s%>tzWwEW0q)=xStklurq8;X-LBPH9J<|kl(8gf22n7{D$5-^ zwcue&90a+%ORmILbD}HR&+upEG<>Ot56jhvq*vd=FUz%1^u5fjFD7zZPnp$0&{e)S zkVXd&w@C&|oX0PQ)5kogow80$7bj#QNP%0~=hiq@BshGewKp?gHab-^`c&;` zcSTiw7PCasjm!;eb;Jkw E0q+okRR910 diff --git a/piet-gpu/shader/kernel4.comp b/piet-gpu/shader/kernel4.comp index a97715a..c49e2fa 100644 --- a/piet-gpu/shader/kernel4.comp +++ b/piet-gpu/shader/kernel4.comp @@ -192,10 +192,27 @@ void main() { int x = int(round(clamp(my_d, 0.0, 1.0) * float(GRADIENT_WIDTH - 1))); mediump vec4 fg_rgba = imageLoad(gradients, ivec2(x, int(lin.index))); fg_rgba.rgb = fromsRGB(fg_rgba.rgb); - rgba[k] = fg_rgba; + mediump vec4 fg_k = fg_rgba * area[k]; + rgba[k] = rgba[k] * (1.0 - fg_k.a) + fg_k; } cmd_ref.offset += 4 + CmdLinGrad_size; break; + case Cmd_RadGrad: + CmdRadGrad rad = Cmd_RadGrad_read(cmd_alloc, cmd_ref); + for (uint k = 0; k < CHUNK; k++) { + vec2 my_xy = xy + vec2(chunk_offset(k)); + my_xy = rad.mat.xz * my_xy.x + rad.mat.yw * my_xy.y - rad.xlat; + float ba = dot(my_xy, rad.c1); + float ca = rad.ra * dot(my_xy, my_xy); + float t = sqrt(ba * ba + ca) - ba - rad.roff; + int x = int(round(clamp(t, 0.0, 1.0) * float(GRADIENT_WIDTH - 1))); + mediump vec4 fg_rgba = imageLoad(gradients, ivec2(x, int(rad.index))); + fg_rgba.rgb = fromsRGB(fg_rgba.rgb); + mediump vec4 fg_k = fg_rgba * area[k]; + rgba[k] = rgba[k] * (1.0 - fg_k.a) + fg_k; + } + cmd_ref.offset += 4 + CmdRadGrad_size; + break; case Cmd_Image: CmdImage fill_img = Cmd_Image_read(cmd_alloc, cmd_ref); mediump vec4 img[CHUNK] = fillImage(xy_uint, fill_img); diff --git a/piet-gpu/shader/ptcl.h b/piet-gpu/shader/ptcl.h index 9b9b341..54dcc9e 100644 --- a/piet-gpu/shader/ptcl.h +++ b/piet-gpu/shader/ptcl.h @@ -18,6 +18,10 @@ struct CmdLinGradRef { uint offset; }; +struct CmdRadGradRef { + uint offset; +}; + struct CmdImageRef { uint offset; }; @@ -83,6 +87,21 @@ CmdLinGradRef CmdLinGrad_index(CmdLinGradRef ref, uint index) { return CmdLinGradRef(ref.offset + index * CmdLinGrad_size); } +struct CmdRadGrad { + uint index; + vec4 mat; + vec2 xlat; + vec2 c1; + float ra; + float roff; +}; + +#define CmdRadGrad_size 44 + +CmdRadGradRef CmdRadGrad_index(CmdRadGradRef ref, uint index) { + return CmdRadGradRef(ref.offset + index * CmdRadGrad_size); +} + struct CmdImage { uint index; ivec2 offset; @@ -131,11 +150,12 @@ CmdJumpRef CmdJump_index(CmdJumpRef ref, uint index) { #define Cmd_Alpha 4 #define Cmd_Color 5 #define Cmd_LinGrad 6 -#define Cmd_Image 7 -#define Cmd_BeginClip 8 -#define Cmd_EndClip 9 -#define Cmd_Jump 10 -#define Cmd_size 20 +#define Cmd_RadGrad 7 +#define Cmd_Image 8 +#define Cmd_BeginClip 9 +#define Cmd_EndClip 10 +#define Cmd_Jump 11 +#define Cmd_size 48 CmdRef Cmd_index(CmdRef ref, uint index) { return CmdRef(ref.offset + index * Cmd_size); @@ -213,6 +233,44 @@ void CmdLinGrad_write(Alloc a, CmdLinGradRef ref, CmdLinGrad s) { write_mem(a, ix + 3, floatBitsToUint(s.line_c)); } +CmdRadGrad CmdRadGrad_read(Alloc a, CmdRadGradRef ref) { + uint ix = ref.offset >> 2; + uint raw0 = read_mem(a, ix + 0); + uint raw1 = read_mem(a, ix + 1); + uint raw2 = read_mem(a, ix + 2); + uint raw3 = read_mem(a, ix + 3); + uint raw4 = read_mem(a, ix + 4); + uint raw5 = read_mem(a, ix + 5); + uint raw6 = read_mem(a, ix + 6); + uint raw7 = read_mem(a, ix + 7); + uint raw8 = read_mem(a, ix + 8); + uint raw9 = read_mem(a, ix + 9); + uint raw10 = read_mem(a, ix + 10); + CmdRadGrad s; + s.index = raw0; + s.mat = vec4(uintBitsToFloat(raw1), uintBitsToFloat(raw2), uintBitsToFloat(raw3), uintBitsToFloat(raw4)); + s.xlat = vec2(uintBitsToFloat(raw5), uintBitsToFloat(raw6)); + s.c1 = vec2(uintBitsToFloat(raw7), uintBitsToFloat(raw8)); + s.ra = uintBitsToFloat(raw9); + s.roff = uintBitsToFloat(raw10); + return s; +} + +void CmdRadGrad_write(Alloc a, CmdRadGradRef ref, CmdRadGrad s) { + uint ix = ref.offset >> 2; + write_mem(a, ix + 0, s.index); + write_mem(a, ix + 1, floatBitsToUint(s.mat.x)); + write_mem(a, ix + 2, floatBitsToUint(s.mat.y)); + write_mem(a, ix + 3, floatBitsToUint(s.mat.z)); + write_mem(a, ix + 4, floatBitsToUint(s.mat.w)); + write_mem(a, ix + 5, floatBitsToUint(s.xlat.x)); + write_mem(a, ix + 6, floatBitsToUint(s.xlat.y)); + write_mem(a, ix + 7, floatBitsToUint(s.c1.x)); + write_mem(a, ix + 8, floatBitsToUint(s.c1.y)); + write_mem(a, ix + 9, floatBitsToUint(s.ra)); + write_mem(a, ix + 10, floatBitsToUint(s.roff)); +} + CmdImage CmdImage_read(Alloc a, CmdImageRef ref) { uint ix = ref.offset >> 2; uint raw0 = read_mem(a, ix + 0); @@ -293,6 +351,10 @@ CmdLinGrad Cmd_LinGrad_read(Alloc a, CmdRef ref) { return CmdLinGrad_read(a, CmdLinGradRef(ref.offset + 4)); } +CmdRadGrad Cmd_RadGrad_read(Alloc a, CmdRef ref) { + return CmdRadGrad_read(a, CmdRadGradRef(ref.offset + 4)); +} + CmdImage Cmd_Image_read(Alloc a, CmdRef ref) { return CmdImage_read(a, CmdImageRef(ref.offset + 4)); } @@ -338,6 +400,11 @@ void Cmd_LinGrad_write(Alloc a, CmdRef ref, CmdLinGrad s) { CmdLinGrad_write(a, CmdLinGradRef(ref.offset + 4), s); } +void Cmd_RadGrad_write(Alloc a, CmdRef ref, CmdRadGrad s) { + write_mem(a, ref.offset >> 2, Cmd_RadGrad); + CmdRadGrad_write(a, CmdRadGradRef(ref.offset + 4), s); +} + void Cmd_Image_write(Alloc a, CmdRef ref, CmdImage s) { write_mem(a, ref.offset >> 2, Cmd_Image); CmdImage_write(a, CmdImageRef(ref.offset + 4), s); diff --git a/piet-gpu/src/encoder.rs b/piet-gpu/src/encoder.rs index 62c59c4..2f4b85e 100644 --- a/piet-gpu/src/encoder.rs +++ b/piet-gpu/src/encoder.rs @@ -62,6 +62,7 @@ const ANNOTATED_SIZE: usize = 40; // Tags for draw objects. See shader/drawtag.h for the authoritative source. const DRAWTAG_FILLCOLOR: u32 = 0x44; const DRAWTAG_FILLLINGRADIENT: u32 = 0x114; +const DRAWTAG_FILLRADGRADIENT: u32 = 0x2dc; const DRAWTAG_BEGINCLIP: u32 = 0x05; const DRAWTAG_ENDCLIP: u32 = 0x25; @@ -79,6 +80,16 @@ pub struct FillLinGradient { p1: [f32; 2], } +#[repr(C)] +#[derive(Clone, Copy, Debug, Default, Zeroable, Pod)] +pub struct FillRadGradient { + index: u32, + p0: [f32; 2], + p1: [f32; 2], + r0: f32, + r1: f32, +} + #[allow(unused)] #[repr(C)] #[derive(Clone, Copy, Debug, Default, Zeroable, Pod)] @@ -123,6 +134,13 @@ impl Encoder { self.transform_stream.push(transform); } + // Swap the last two tags in the tag stream; used for transformed + // gradients. + pub fn swap_last_tags(&mut self) { + let len = self.tag_stream.len(); + self.tag_stream.swap(len - 1, len - 2); + } + // -1.0 means "fill" pub fn linewidth(&mut self, linewidth: f32) { self.tag_stream.push(0x40); @@ -147,6 +165,16 @@ impl Encoder { self.drawdata_stream.extend(bytemuck::bytes_of(&element)); } + + /// Encode a fill radial gradient draw object. + /// + /// This should be encoded after a path. + pub fn fill_rad_gradient(&mut self, index: u32, p0: [f32; 2], p1: [f32; 2], r0: f32, r1: f32) { + self.drawtag_stream.push(DRAWTAG_FILLRADGRADIENT); + let element = FillRadGradient { index, p0, p1, r0, r1 }; + self.drawdata_stream.extend(bytemuck::bytes_of(&element)); + } + /// Start a clip. pub fn begin_clip(&mut self, blend: Option) { self.drawtag_stream.push(DRAWTAG_BEGINCLIP); @@ -220,7 +248,7 @@ impl Encoder { alloc += n_drawobj * DRAW_BBOX_SIZE; let drawinfo_alloc = alloc; // TODO: not optimized; it can be accumulated during encoding or summed from drawtags - const MAX_DRAWINFO_SIZE: usize = 16; + const MAX_DRAWINFO_SIZE: usize = 44; alloc += n_drawobj * MAX_DRAWINFO_SIZE; let config = Config { diff --git a/piet-gpu/src/gradient.rs b/piet-gpu/src/gradient.rs index 20982e9..e655908 100644 --- a/piet-gpu/src/gradient.rs +++ b/piet-gpu/src/gradient.rs @@ -18,15 +18,29 @@ use std::collections::hash_map::{Entry, HashMap}; -use piet::{Color, FixedLinearGradient, GradientStop}; +use piet::kurbo::Point; +use piet::{Color, FixedLinearGradient, GradientStop, FixedRadialGradient}; + +/// Radial gradient compatible with COLRv1 spec +#[derive(Debug, Clone)] +pub struct Colrv1RadialGradient { + /// The center of the iner circle. + pub center0: Point, + /// The offset of the origin relative to the center. + pub center1: Point, + /// The radius of the inner circle. + pub radius0: f64, + /// The radius of the outer circle. + pub radius1: f64, + /// The stops. + pub stops: Vec, +} #[derive(Clone)] pub struct BakedGradient { ramp: Vec, } -/// This is basically the same type as scene::FillLinGradient, so could -/// potentially use that directly. #[derive(Clone)] pub struct LinearGradient { pub(crate) start: [f32; 2], @@ -34,6 +48,15 @@ pub struct LinearGradient { pub(crate) ramp_id: u32, } +#[derive(Clone)] +pub struct RadialGradient { + pub(crate) start: [f32; 2], + pub(crate) end: [f32; 2], + pub(crate) r0: f32, + pub(crate) r1: f32, + pub(crate) ramp_id: u32, +} + #[derive(Default)] pub struct RampCache { ramps: Vec, @@ -154,6 +177,28 @@ impl RampCache { } } + pub fn add_radial_gradient(&mut self, rad: &FixedRadialGradient) -> RadialGradient { + let ramp_id = self.add_ramp(&rad.stops); + RadialGradient { + ramp_id: ramp_id as u32, + start: crate::render_ctx::to_f32_2(rad.center + rad.origin_offset), + end: crate::render_ctx::to_f32_2(rad.center), + r0: 0.0, + r1: rad.radius as f32, + } + } + + pub fn add_radial_gradient_colrv1(&mut self, rad: &Colrv1RadialGradient) -> RadialGradient { + let ramp_id = self.add_ramp(&rad.stops); + RadialGradient { + ramp_id: ramp_id as u32, + start: crate::render_ctx::to_f32_2(rad.center0), + end: crate::render_ctx::to_f32_2(rad.center1), + r0: rad.radius0 as f32, + r1: rad.radius1 as f32, + } + } + /// Dump the contents of a gradient. This is for debugging. #[allow(unused)] pub(crate) fn dump_gradient(&self, lin: &LinearGradient) { diff --git a/piet-gpu/src/lib.rs b/piet-gpu/src/lib.rs index 249735a..475d723 100644 --- a/piet-gpu/src/lib.rs +++ b/piet-gpu/src/lib.rs @@ -12,6 +12,7 @@ use std::convert::TryInto; pub use blend::{Blend, BlendMode, CompositionMode}; pub use render_ctx::PietGpuRenderContext; +pub use gradient::Colrv1RadialGradient; use piet::kurbo::Vec2; use piet::{ImageFormat, RenderContext}; @@ -21,7 +22,7 @@ use piet_gpu_hal::{ ImageLayout, Pipeline, QueryPool, Session, }; -pub use pico_svg::PicoSvg; +use pico_svg::PicoSvg; use stages::{ClipBinding, ElementBinding, ElementCode}; use crate::stages::{ClipCode, Config, ElementStage}; diff --git a/piet-gpu/src/render_ctx.rs b/piet-gpu/src/render_ctx.rs index 024dd2b..dca03eb 100644 --- a/piet-gpu/src/render_ctx.rs +++ b/piet-gpu/src/render_ctx.rs @@ -13,7 +13,7 @@ use piet_gpu_hal::BufWrite; use piet_gpu_types::encoder::{Encode, Encoder}; use piet_gpu_types::scene::Element; -use crate::gradient::{LinearGradient, RampCache}; +use crate::gradient::{LinearGradient, RadialGradient, RampCache, Colrv1RadialGradient}; use crate::text::Font; pub use crate::text::{PietGpuText, PietGpuTextLayout, PietGpuTextLayoutBuilder}; use crate::Blend; @@ -50,6 +50,7 @@ pub struct PietGpuRenderContext { pub enum PietGpuBrush { Solid(u32), LinGradient(LinearGradient), + RadGradient(RadialGradient), } #[derive(Default)] @@ -187,6 +188,10 @@ impl RenderContext for PietGpuRenderContext { let lin = self.ramp_cache.add_linear_gradient(&lin); Ok(PietGpuBrush::LinGradient(lin)) } + FixedGradient::Radial(rad) => { + let rad = self.ramp_cache.add_radial_gradient(&rad); + Ok(PietGpuBrush::RadGradient(rad)) + } _ => todo!("don't do radial gradients yet"), } } @@ -338,6 +343,20 @@ impl PietGpuRenderContext { } } + pub fn radial_gradient_colrv1(&mut self, rad: &Colrv1RadialGradient) -> PietGpuBrush { + PietGpuBrush::RadGradient(self.ramp_cache.add_radial_gradient_colrv1(rad)) + } + + pub fn fill_transform(&mut self, shape: impl Shape, brush: &PietGpuBrush, transform: Affine) { + let path = shape.path_elements(TOLERANCE); + self.encode_linewidth(-1.0); + self.encode_path(path, true); + self.encode_transform(Transform::from_kurbo(transform)); + self.new_encoder.swap_last_tags(); + self.encode_brush(&brush); + self.encode_transform(Transform::from_kurbo(transform.inverse())); + } + fn encode_path(&mut self, path: impl Iterator, is_fill: bool) { if is_fill { self.encode_path_inner( @@ -420,6 +439,10 @@ impl PietGpuRenderContext { self.new_encoder .fill_lin_gradient(lin.ramp_id, lin.start, lin.end); } + PietGpuBrush::RadGradient(rad) => { + self.new_encoder + .fill_rad_gradient(rad.ramp_id, rad.start, rad.end, rad.r0, rad.r1); + } } } } diff --git a/piet-gpu/src/test_scenes.rs b/piet-gpu/src/test_scenes.rs index 350b9dd..cf5a50d 100644 --- a/piet-gpu/src/test_scenes.rs +++ b/piet-gpu/src/test_scenes.rs @@ -2,10 +2,10 @@ use rand::{Rng, RngCore}; -use crate::{Blend, BlendMode, CompositionMode, PietGpuRenderContext}; +use crate::{Blend, BlendMode, CompositionMode, PietGpuRenderContext, Colrv1RadialGradient}; use piet::kurbo::{Affine, BezPath, Circle, Line, Point, Rect, Shape}; use piet::{ - Color, FixedGradient, FixedLinearGradient, GradientStop, Text, TextAttribute, TextLayoutBuilder, + Color, FixedGradient, FixedRadialGradient, GradientStop, Text, TextAttribute, TextLayoutBuilder, }; use crate::{PicoSvg, RenderContext, Vec2}; @@ -21,13 +21,18 @@ pub fn render_blend_test(rc: &mut PietGpuRenderContext, i: usize, blend: Blend) rc.restore().unwrap(); } -pub fn render_svg(rc: &mut impl RenderContext, svg: &PicoSvg) { +pub fn render_svg(rc: &mut impl RenderContext, filename: &str, scale: f64) { + let xml_str = std::fs::read_to_string(filename).unwrap(); + let start = std::time::Instant::now(); + let svg = PicoSvg::load(&xml_str, scale).unwrap(); + println!("parsing time: {:?}", start.elapsed()); + let start = std::time::Instant::now(); svg.render(rc); println!("flattening and encoding time: {:?}", start.elapsed()); } -pub fn render_scene(rc: &mut impl RenderContext) { +pub fn render_scene(rc: &mut PietGpuRenderContext) { const WIDTH: usize = 2048; const HEIGHT: usize = 1536; let mut rng = rand::thread_rng(); @@ -137,7 +142,7 @@ fn render_alpha_test(rc: &mut impl RenderContext) { } #[allow(unused)] -fn render_gradient_test(rc: &mut impl RenderContext) { +fn render_gradient_test(rc: &mut PietGpuRenderContext) { let stops = vec![ GradientStop { color: Color::rgb8(0, 255, 0), @@ -148,14 +153,18 @@ fn render_gradient_test(rc: &mut impl RenderContext) { pos: 1.0, }, ]; - let lin = FixedLinearGradient { - start: Point::new(0.0, 100.0), - end: Point::new(0.0, 300.0), + let rad = Colrv1RadialGradient { + center0: Point::new(200.0, 200.0), + center1: Point::new(250.0, 200.0), + radius0: 50.0, + radius1: 100.0, stops, }; - let brush = FixedGradient::Linear(lin); + let brush = rc.radial_gradient_colrv1(&rad); + //let brush = FixedGradient::Radial(rad); //let brush = Color::rgb8(0, 128, 0); - rc.fill(Rect::new(100.0, 100.0, 300.0, 300.0), &brush); + let transform = Affine::new([1.0, 0.0, 0.0, 0.5, 0.0, 100.0]); + rc.fill_transform(Rect::new(100.0, 100.0, 300.0, 300.0), &brush, transform); } fn diamond(origin: Point) -> impl Shape { diff --git a/piet-scene/Cargo.toml b/piet-scene/Cargo.toml new file mode 100644 index 0000000..8706119 --- /dev/null +++ b/piet-scene/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "piet-scene" +version = "0.1.0" +license = "MIT/Apache-2.0" +edition = "2021" + +[dependencies] +bytemuck = { version = "1.7.2", features = ["derive"] } +smallvec = "1.8.0" diff --git a/piet-scene/src/brush/color.rs b/piet-scene/src/brush/color.rs new file mode 100644 index 0000000..d079210 --- /dev/null +++ b/piet-scene/src/brush/color.rs @@ -0,0 +1,62 @@ +// Copyright 2022 The piet-gpu authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Also licensed under MIT license, at your choice. + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug)] +pub struct Color { + pub r: u8, + pub g: u8, + pub b: u8, + pub a: u8, +} + +impl Color { + pub const fn rgb8(r: u8, g: u8, b: u8) -> Self { + Self { r, g, b, a: 255 } + } + + pub const fn rgba8(r: u8, g: u8, b: u8, a: u8) -> Self { + Self { r, g, b, a } + } + + pub fn rgb>(r: C, g: C, b: C) -> Self { + Self::rgb8( + (r.into() / 255.0) as u8, + (g.into() / 255.0) as u8, + (b.into() / 255.0) as u8, + ) + } + + pub fn rgba>(r: C, g: C, b: C, a: C) -> Self { + Self::rgba8( + (r.into() / 255.0) as u8, + (g.into() / 255.0) as u8, + (b.into() / 255.0) as u8, + (a.into() / 255.0) as u8, + ) + } + + pub fn pack(self) -> u32 { + (self.b as u32) << 24 | (self.g as u32) << 16 | (self.r as u32) << 8 | self.a as u32 + } + + pub fn to_premul_u32(self) -> u32 { + let a = self.a as f64 / 255.0; + let r = (self.r as f64 * a) as u32; + let g = (self.g as f64 * a) as u32; + let b = (self.b as f64 * a) as u32; + r | (g << 8) | (b << 16) | ((self.a as u32) << 24) + } +} diff --git a/piet-scene/src/brush/gradient.rs b/piet-scene/src/brush/gradient.rs new file mode 100644 index 0000000..51d558e --- /dev/null +++ b/piet-scene/src/brush/gradient.rs @@ -0,0 +1,87 @@ +// Copyright 2022 The piet-gpu authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Also licensed under MIT license, at your choice. + +use super::color::Color; +use crate::geometry::Point; +use smallvec::SmallVec; +use std::hash::{Hash, Hasher}; + +#[derive(Copy, Clone, PartialOrd, Default, Debug)] +pub struct Stop { + pub offset: f32, + pub color: Color, +} + +impl Hash for Stop { + fn hash(&self, state: &mut H) { + self.offset.to_bits().hash(state); + self.color.hash(state); + } +} + +// Override PartialEq to use to_bits for the offset to match with the Hash impl +impl std::cmp::PartialEq for Stop { + fn eq(&self, other: &Self) -> bool { + self.offset.to_bits() == other.offset.to_bits() && self.color == other.color + } +} + +impl std::cmp::Eq for Stop {} + +pub type StopVec = SmallVec<[Stop; 4]>; + +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum Extend { + Pad, + Repeat, + Reflect, +} + +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum Space { + Object, + Global, +} + +#[derive(Clone, Debug)] +pub struct LinearGradient { + pub space: Space, + pub start: Point, + pub end: Point, + pub stops: StopVec, + pub extend: Extend, +} + +#[derive(Clone, Debug)] +pub struct RadialGradient { + pub space: Space, + pub center0: Point, + pub radius0: f32, + pub center1: Point, + pub radius1: f32, + pub stops: StopVec, + pub extend: Extend, +} + +#[derive(Clone, Debug)] +pub struct SweepGradient { + pub space: Space, + pub center: Point, + pub start_angle: f32, + pub end_angle: f32, + pub stops: StopVec, + pub extend: Extend, +} diff --git a/piet-scene/src/brush/image.rs b/piet-scene/src/brush/image.rs new file mode 100644 index 0000000..07157e7 --- /dev/null +++ b/piet-scene/src/brush/image.rs @@ -0,0 +1,96 @@ +// Copyright 2022 The piet-gpu authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Also licensed under MIT license, at your choice. + +use std::result::Result; +use std::sync::atomic::{AtomicU64, Ordering}; +use std::sync::Arc; + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum Format { + A8, + Rgba8, +} + +impl Format { + pub fn data_size(self, width: u32, height: u32) -> Option { + (width as usize) + .checked_mul(height as usize) + .and_then(|size| { + size.checked_mul(match self { + Self::A8 => 1, + Self::Rgba8 => 4, + }) + }) + } +} + +#[derive(Clone, Debug)] +pub struct Image(Arc); + +#[derive(Clone, Debug)] +struct Inner { + id: u64, + format: Format, + width: u32, + height: u32, + data: Vec, +} + +impl Image { + pub fn new( + format: Format, + width: u32, + height: u32, + mut data: Vec, + ) -> Result { + let data_size = format.data_size(width, height).ok_or(DataSizeError)?; + if data.len() < data_size { + return Err(DataSizeError); + } + data.truncate(data_size); + static ID: AtomicU64 = AtomicU64::new(1); + Ok(Self(Arc::new(Inner { + id: ID.fetch_add(1, Ordering::Relaxed), + format, + width, + height, + data, + }))) + } + + pub fn id(&self) -> u64 { + self.0.id + } + + pub fn format(&self) -> Format { + self.0.format + } + + pub fn width(&self) -> u32 { + self.0.width + } + + pub fn height(&self) -> u32 { + self.0.height + } + + pub fn data(&self) -> &[u8] { + &self.0.data + } +} + +#[derive(Clone, Debug)] +pub struct DataSizeError; diff --git a/piet-scene/src/brush/mod.rs b/piet-scene/src/brush/mod.rs new file mode 100644 index 0000000..9cde1fb --- /dev/null +++ b/piet-scene/src/brush/mod.rs @@ -0,0 +1,35 @@ +// Copyright 2022 The piet-gpu authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Also licensed under MIT license, at your choice. + +mod color; +mod gradient; +mod image; + +pub use color::Color; +pub use gradient::*; +pub use image::*; + +use crate::resource::PersistentBrush; + +#[derive(Clone, Debug)] +pub enum Brush { + Solid(Color), + LinearGradient(LinearGradient), + RadialGradient(RadialGradient), + SweepGradient(SweepGradient), + Image(Image), + Persistent(PersistentBrush), +} diff --git a/piet-scene/src/geometry.rs b/piet-scene/src/geometry.rs new file mode 100644 index 0000000..a40cc40 --- /dev/null +++ b/piet-scene/src/geometry.rs @@ -0,0 +1,189 @@ +// Copyright 2022 The piet-gpu authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Also licensed under MIT license, at your choice. + +use core::borrow::Borrow; +use core::hash::{Hash, Hasher}; + +/// Two dimensional point. +#[derive(Copy, Clone, PartialEq, PartialOrd, Default, Debug)] +#[repr(C)] +pub struct Point { + pub x: f32, + pub y: f32, +} + +impl Hash for Point { + fn hash(&self, state: &mut H) { + self.x.to_bits().hash(state); + self.y.to_bits().hash(state); + } +} + +impl Point { + pub const fn new(x: f32, y: f32) -> Self { + Self { x, y } + } + + pub fn transform(&self, affine: &Affine) -> Self { + Self { + x: self.x * affine.xx + self.y * affine.yx + affine.dx, + y: self.y * affine.yy + self.y * affine.xy + affine.dy, + } + } +} + +impl From<[f32; 2]> for Point { + fn from(value: [f32; 2]) -> Self { + Self::new(value[0], value[1]) + } +} + +impl From<(f32, f32)> for Point { + fn from(value: (f32, f32)) -> Self { + Self::new(value.0, value.1) + } +} + +/// Affine transformation matrix. +#[derive(Copy, Clone, Debug)] +#[repr(C)] +pub struct Affine { + pub xx: f32, + pub yx: f32, + pub xy: f32, + pub yy: f32, + pub dx: f32, + pub dy: f32, +} + +impl Affine { + pub const fn new(elements: &[f32; 6]) -> Self { + Self { + xx: elements[0], + yx: elements[1], + xy: elements[2], + yy: elements[3], + dx: elements[4], + dy: elements[5], + } + } + + /// Creates a new affine transform representing the specified scale along the + /// x and y axes. + pub fn scale(x: f32, y: f32) -> Self { + Self::new(&[x, 0., 0., y, 0., 0.]) + } + + /// Creates a new affine transform representing the specified translation. + pub fn translate(x: f32, y: f32) -> Self { + Self::new(&[1., 0., 0., 1., x, y]) + } + + /// Creates a new affine transform representing a counter-clockwise + /// rotation for the specified angle in radians. + pub fn rotate(th: f32) -> Self { + let (s, c) = th.sin_cos(); + Self::new(&[c, s, -s, c, 0., 0.]) + } + + /// Creates a new skew transform + pub fn skew(x: f32, y: f32) -> Self { + Self::new(&[1., x.tan(), y.tan(), 1., 0., 0.]) + } + + pub fn around_center(&self, x: f32, y: f32) -> Self { + Self::translate(x, y) * *self * Self::translate(-x, -y) + } + + /// Transforms the specified point. + pub fn transform_point(&self, point: Point) -> Point { + Point { + x: point.x * self.xx + point.y * self.yx + self.dx, + y: point.y * self.yy + point.y * self.xy + self.dy, + } + } +} + +impl std::ops::Mul for Affine { + type Output = Self; + fn mul(self, other: Self) -> Self { + Self::new(&[ + self.xx * other.xx + self.xy * other.yx, + self.yx * other.xx + self.yy * other.yx, + self.xx * other.xy + self.xy * other.yy, + self.yx * other.xy + self.yy * other.yy, + self.xx * other.dx + self.xy * other.dy + self.dx, + self.yx * other.dx + self.yy * other.dy + self.dy, + ]) + } +} + +/// Axis-aligned rectangle represented as minimum and maximum points. +#[derive(Copy, Clone, Default, Debug)] +#[repr(C)] +pub struct Rect { + pub min: Point, + pub max: Point, +} + +impl Rect { + /// Creates a new rectangle that encloses the specified collection of + /// points. + pub fn from_points(points: I) -> Self + where + I: IntoIterator, + I::Item: Borrow, + { + let mut rect = Self { + min: Point::new(f32::MAX, f32::MAX), + max: Point::new(f32::MIN, f32::MIN), + }; + let mut count = 0; + for point in points { + rect.add(*point.borrow()); + count += 1; + } + if count != 0 { + rect + } else { + Self::default() + } + } + + /// Returns the width of the rectangle. + pub fn width(&self) -> f32 { + self.max.x - self.min.x + } + + /// Returns the height of the rectangle. + pub fn height(&self) -> f32 { + self.max.y - self.min.y + } + + /// Extends the rectangle to include the specified point. + pub fn add(&mut self, point: Point) { + self.min.x = self.min.x.min(point.x); + self.min.y = self.min.y.min(point.y); + self.max.x = self.max.x.max(point.x); + self.max.y = self.max.y.max(point.y); + } + + /// Returns a new rectangle that encloses the minimum and maximum points + /// of this rectangle after applying the specified transform to each. + pub fn transform(&self, affine: &Affine) -> Self { + Self::from_points([self.min.transform(affine), self.max.transform(affine)]) + } +} diff --git a/piet-scene/src/lib.rs b/piet-scene/src/lib.rs new file mode 100644 index 0000000..6b23f6d --- /dev/null +++ b/piet-scene/src/lib.rs @@ -0,0 +1,21 @@ +// Copyright 2022 The piet-gpu authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Also licensed under MIT license, at your choice. + +pub mod brush; +pub mod geometry; +pub mod path; +pub mod resource; +pub mod scene; diff --git a/piet-scene/src/main.rs b/piet-scene/src/main.rs new file mode 100644 index 0000000..8fd361a --- /dev/null +++ b/piet-scene/src/main.rs @@ -0,0 +1,30 @@ +use piet_scene::geometry::*; +use piet_scene::path::*; +use piet_scene::scene::*; +use piet_scene::{geometry::*, path::*, resource::ResourceContext, scene::*}; + +fn main() { + let mut scene = Scene::default(); + let mut rcx = ResourceContext::new(); + let mut sb = build_scene(&mut scene, &mut rcx); + + sb.push_layer(Blend::default(), Rect::default().elements()); + + let mut path = Path::new(); + let mut b = PathBuilder::new(&mut path); + b.move_to(100., 100.); + b.line_to(200., 200.); + b.close_path(); + b.move_to(50., 50.); + b.line_to(600., 150.); + b.move_to(4., 2.); + b.quad_to(8., 8., 9., 9.); + b.close_path(); + println!("{:?}", path); + for el in path.elements() { + println!("{:?}", el); + } + //sb.push_layer(path.elements(), BlendMode::default()); + + sb.push_layer(Blend::default(), [Element::MoveTo((0., 0.).into())]); +} diff --git a/piet-scene/src/path.rs b/piet-scene/src/path.rs new file mode 100644 index 0000000..ffbce3e --- /dev/null +++ b/piet-scene/src/path.rs @@ -0,0 +1,311 @@ +// Copyright 2022 The piet-gpu authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Also licensed under MIT license, at your choice. + +use super::geometry::{Point, Rect}; + +/// Action of a path element. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum Verb { + MoveTo, + LineTo, + QuadTo, + CurveTo, + Close, +} + +/// Element of a path represented by a verb and its associated points. +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum Element { + MoveTo(Point), + LineTo(Point), + QuadTo(Point, Point), + CurveTo(Point, Point, Point), + Close, +} + +impl Element { + /// Returns the verb that describes the action of the path element. + pub fn verb(&self) -> Verb { + match self { + Self::MoveTo(..) => Verb::MoveTo, + Self::LineTo(..) => Verb::LineTo, + Self::QuadTo(..) => Verb::QuadTo, + Self::CurveTo(..) => Verb::CurveTo, + Self::Close => Verb::Close, + } + } +} + +/// Encoded collection of path elements. +#[derive(Clone, Default, Debug)] +pub struct Path { + tag_stream: Vec, + pathseg_stream: Vec, + n_path: u32, + n_pathseg: u32, +} + +impl Path { + pub fn new() -> Self { + Self::default() + } + + pub fn elements(&self) -> Elements { + Elements::new(&self) + } +} + +#[derive(Clone)] +pub struct Elements<'a> { + tag_stream: &'a [u8], + points: &'a [[f32; 2]], + tag_ix: usize, + point_ix: usize, + next_element: Option, + close: bool, +} + +impl<'a> Elements<'a> { + fn new(path: &'a Path) -> Self { + let points: &'a [[f32; 2]] = bytemuck::cast_slice(&path.pathseg_stream); + let (point_ix, next_element) = match points.get(0) { + Some(&point) => (1, Some(Element::MoveTo(point.into()))), + None => (0, None), + }; + Self { + tag_stream: &path.tag_stream, + points, + tag_ix: 0, + point_ix, + next_element, + close: false, + } + } +} + +impl<'a> Iterator for Elements<'a> { + type Item = Element; + + fn next(&mut self) -> Option { + // println!("n_points: {}", self.points.len()); + // println!("tag_ix: {}, point_ix: {}, el: {:?}, close: {}", self.tag_ix, self.point_ix, self.next_element, self.close); + if self.close { + self.close = false; + return Some(Element::Close); + } + if let Some(next_el) = self.next_element.take() { + return Some(next_el); + } + let tag = *self.tag_stream.get(self.tag_ix)?; + self.tag_ix += 1; + let end = tag & 4 != 0; + let el = match tag & 3 { + 1 => { + let p0 = *self.points.get(self.point_ix)?; + self.point_ix += 1; + Element::LineTo(p0.into()) + } + 2 => { + let p0 = *self.points.get(self.point_ix)?; + let p1 = *self.points.get(self.point_ix + 1)?; + self.point_ix += 2; + Element::QuadTo(p0.into(), p1.into()) + } + 3 => { + let p0 = *self.points.get(self.point_ix)?; + let p1 = *self.points.get(self.point_ix + 1)?; + let p2 = *self.points.get(self.point_ix + 2)?; + self.point_ix += 3; + Element::CurveTo(p0.into(), p1.into(), p2.into()) + } + _ => return None, + }; + if end { + // println!("END!"); + if let Some(&p0) = self.points.get(self.point_ix) { + self.point_ix += 1; + self.next_element = Some(Element::MoveTo(p0.into())); + } + self.close = tag & 0x80 != 0; + } + Some(el) + } +} + +pub struct PathBuilder<'a> { + tag_stream: &'a mut Vec, + // If we're never going to use the i16 encoding, it might be + // slightly faster to store this as Vec, we'd get aligned + // stores on ARM etc. + pathseg_stream: &'a mut Vec, + first_pt: [f32; 2], + state: State, + n_pathseg: u32, +} + +#[derive(PartialEq)] +enum State { + Start, + MoveTo, + NonemptySubpath, +} + +impl<'a> PathBuilder<'a> { + pub fn new(path: &'a mut Path) -> Self { + Self { + tag_stream: &mut path.tag_stream, + pathseg_stream: &mut path.pathseg_stream, + first_pt: [0.0, 0.0], + state: State::Start, + n_pathseg: 0, + } + } + + fn new_inner(tags: &'a mut Vec, pathsegs: &'a mut Vec) -> PathBuilder<'a> { + PathBuilder { + tag_stream: tags, + pathseg_stream: pathsegs, + first_pt: [0.0, 0.0], + state: State::Start, + n_pathseg: 0, + } + } + + pub fn move_to(&mut self, x: f32, y: f32) { + let buf = [x, y]; + let bytes = bytemuck::bytes_of(&buf); + self.first_pt = buf; + if self.state == State::MoveTo { + let new_len = self.pathseg_stream.len() - 8; + self.pathseg_stream.truncate(new_len); + } + if self.state == State::NonemptySubpath { + if let Some(tag) = self.tag_stream.last_mut() { + *tag |= 4; + } + } + self.pathseg_stream.extend_from_slice(bytes); + self.state = State::MoveTo; + } + + pub fn line_to(&mut self, x: f32, y: f32) { + if self.state == State::Start { + // should warn or error + return; + } + let buf = [x, y]; + let bytes = bytemuck::bytes_of(&buf); + self.pathseg_stream.extend_from_slice(bytes); + self.tag_stream.push(9); + self.state = State::NonemptySubpath; + self.n_pathseg += 1; + } + + pub fn quad_to(&mut self, x1: f32, y1: f32, x2: f32, y2: f32) { + if self.state == State::Start { + return; + } + let buf = [x1, y1, x2, y2]; + let bytes = bytemuck::bytes_of(&buf); + self.pathseg_stream.extend_from_slice(bytes); + self.tag_stream.push(10); + self.state = State::NonemptySubpath; + self.n_pathseg += 1; + } + + 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 = [x1, y1, x2, y2, x3, y3]; + let bytes = bytemuck::bytes_of(&buf); + self.pathseg_stream.extend_from_slice(bytes); + self.tag_stream.push(11); + self.state = State::NonemptySubpath; + self.n_pathseg += 1; + } + + pub fn close_path(&mut self) { + match self.state { + State::Start => return, + State::MoveTo => { + let new_len = self.pathseg_stream.len() - 8; + self.pathseg_stream.truncate(new_len); + self.state = State::Start; + return; + } + State::NonemptySubpath => (), + } + let len = self.pathseg_stream.len(); + if len < 8 { + // can't happen + return; + } + let first_bytes = bytemuck::bytes_of(&self.first_pt); + if &self.pathseg_stream[len - 8..len] != first_bytes { + self.pathseg_stream.extend_from_slice(first_bytes); + self.tag_stream.push(0x80 | 13); + self.n_pathseg += 1; + } else { + if let Some(tag) = self.tag_stream.last_mut() { + *tag |= 0x80 | 4; + } + } + self.state = State::Start; + } + + fn finish(&mut self) { + if self.state == State::MoveTo { + let new_len = self.pathseg_stream.len() - 8; + self.pathseg_stream.truncate(new_len); + } + if let Some(tag) = self.tag_stream.last_mut() { + *tag |= 4; + } + } + + /// Finish encoding a path. + /// + /// Encode this after encoding path segments. + pub fn path(&mut self) { + self.finish(); + // maybe don't encode if path is empty? might throw off sync though + self.tag_stream.push(0x10); + } + + /// Get the number of path segments. + /// + /// This is the number of path segments that will be written by the + /// path stage; use this for allocating the output buffer. + /// + /// Also note: it takes `self` for lifetime reasons. + pub fn n_pathseg(self) -> u32 { + self.n_pathseg + } +} + +impl Rect { + pub fn elements(&self) -> impl Iterator + Clone { + let elements = [ + Element::MoveTo((self.min.x, self.min.y).into()), + Element::LineTo((self.max.x, self.min.y).into()), + Element::LineTo((self.max.x, self.max.y).into()), + Element::LineTo((self.min.x, self.max.y).into()), + Element::Close, + ]; + (0..5).map(move |i| elements[i]) + } +} diff --git a/piet-scene/src/resource/mod.rs b/piet-scene/src/resource/mod.rs new file mode 100644 index 0000000..36e6419 --- /dev/null +++ b/piet-scene/src/resource/mod.rs @@ -0,0 +1,37 @@ +mod ramp_cache; + +use crate::brush::{Brush, Stop}; +use ramp_cache::RampCache; + +/// Context for caching resources across rendering operations. +#[derive(Default)] +pub struct ResourceContext { + ramp_cache: RampCache, +} + +impl ResourceContext { + pub fn new() -> Self { + Self::default() + } + + pub fn advance(&mut self) { + self.ramp_cache.advance(); + } + + pub fn add_ramp(&mut self, stops: &[Stop]) -> u32 { + self.ramp_cache.add(stops) + } + + pub fn create_brush(&mut self, brush: &Brush) -> PersistentBrush { + PersistentBrush { kind: 0, id: 0 } + } + + pub fn destroy_brush(&mut self, brush: PersistentBrush) {} +} + +/// Handle for a brush that is managed by the resource context. +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +pub struct PersistentBrush { + kind: u8, + id: u64, +} diff --git a/piet-scene/src/resource/ramp_cache.rs b/piet-scene/src/resource/ramp_cache.rs new file mode 100644 index 0000000..0c509e4 --- /dev/null +++ b/piet-scene/src/resource/ramp_cache.rs @@ -0,0 +1,138 @@ +use crate::brush::{Color, Stop, StopVec}; +use std::collections::HashMap; + +const N_SAMPLES: usize = 512; +const RETAINED_COUNT: usize = 64; + +#[derive(Default)] +pub struct RampCache { + epoch: u64, + map: HashMap, + data: Vec, +} + +impl RampCache { + pub fn new() -> Self { + Self::default() + } + + pub fn advance(&mut self) { + self.epoch += 1; + if self.map.len() > RETAINED_COUNT { + self.map + .retain(|_key, value| value.0 < RETAINED_COUNT as u32); + self.data.truncate(RETAINED_COUNT * N_SAMPLES); + } + } + + pub fn clear(&mut self) { + self.epoch = 0; + self.map.clear(); + self.data.clear(); + } + + pub fn add(&mut self, stops: &[Stop]) -> u32 { + if let Some(entry) = self.map.get_mut(stops) { + entry.1 = self.epoch; + entry.0 + } else if self.map.len() < RETAINED_COUNT { + let id = (self.data.len() / N_SAMPLES) as u32; + self.data.extend(make_ramp(stops)); + self.map.insert(stops.into(), (id, self.epoch)); + id + } else { + let mut reuse = None; + for (stops, (id, epoch)) in &self.map { + if *epoch + 2 < self.epoch { + reuse = Some((stops.to_owned(), *id)); + break; + } + } + if let Some((old_stops, id)) = reuse { + self.map.remove(&old_stops); + let start = id as usize * N_SAMPLES; + for (dst, src) in self.data[start..start + N_SAMPLES] + .iter_mut() + .zip(make_ramp(stops)) + { + *dst = src; + } + self.map.insert(stops.into(), (id, self.epoch)); + id + } else { + let id = (self.data.len() / N_SAMPLES) as u32; + self.data.extend(make_ramp(stops)); + self.map.insert(stops.into(), (id, self.epoch)); + id + } + } + } + + pub fn data(&self) -> &[u32] { + &self.data + } +} + +fn make_ramp<'a>(stops: &'a [Stop]) -> impl Iterator + 'a { + let mut last_u = 0.0; + let mut last_c = ColorF64::from_color(stops[0].color); + let mut this_u = last_u; + let mut this_c = last_c; + let mut j = 0; + (0..N_SAMPLES).map(move |i| { + let u = (i as f64) / (N_SAMPLES - 1) as f64; + while u > this_u { + last_u = this_u; + last_c = this_c; + if let Some(s) = stops.get(j + 1) { + this_u = s.offset as f64; + this_c = ColorF64::from_color(s.color); + j += 1; + } else { + break; + } + } + let du = this_u - last_u; + let c = if du < 1e-9 { + this_c + } else { + last_c.lerp(&this_c, (u - last_u) / du) + }; + c.to_premul_u32() + }) +} + +#[derive(Copy, Clone)] +struct ColorF64([f64; 4]); + +impl ColorF64 { + fn from_color(color: Color) -> Self { + Self([ + color.r as f64 / 255.0, + color.g as f64 / 255.0, + color.b as f64 / 255.0, + color.a as f64 / 255.0, + ]) + } + + fn lerp(&self, other: &Self, a: f64) -> Self { + fn l(x: f64, y: f64, a: f64) -> f64 { + x + (y - x) * a + } + Self([ + l(self.0[0], other.0[0], a), + l(self.0[1], other.0[1], a), + l(self.0[2], other.0[2], a), + l(self.0[3], other.0[3], a), + ]) + } + + fn to_premul_u32(&self) -> u32 { + let a = self.0[3].min(1.0).max(0.0); + let r = ((self.0[0] * a).min(1.0).max(0.0) / 255.0) as u32; + let g = ((self.0[1] * a).min(1.0).max(0.0) / 255.0) as u32; + let b = ((self.0[2] * a).min(1.0).max(0.0) / 255.0) as u32; + let a = (a / 255.0) as u32; + r | (g << 8) | (b << 16) | (a << 24) + } +} diff --git a/piet-scene/src/scene/blend.rs b/piet-scene/src/scene/blend.rs new file mode 100644 index 0000000..7edc6cd --- /dev/null +++ b/piet-scene/src/scene/blend.rs @@ -0,0 +1,102 @@ +// Copyright 2022 The piet-gpu authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Also licensed under MIT license, at your choice. + +/// Defines the color mixing function for a blend operation. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[repr(C)] +pub enum Mix { + Normal = 0, + Multiply = 1, + Screen = 2, + Overlay = 3, + Darken = 4, + Lighten = 5, + ColorDodge = 6, + ColorBurn = 7, + HardLight = 8, + SoftLight = 9, + Difference = 10, + Exclusion = 11, + Hue = 12, + Saturation = 13, + Color = 14, + Luminosity = 15, +} + +/// Defines the layer composition function for a blend operation. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[repr(C)] +pub enum Compose { + Clear = 0, + Copy = 1, + Dest = 2, + SrcOver = 3, + DestOver = 4, + SrcIn = 5, + DestIn = 6, + SrcOut = 7, + DestOut = 8, + SrcAtop = 9, + DestAtop = 10, + Xor = 11, + Plus = 12, + PlusDarker = 13, + PlusLighter = 14, +} + +/// Blend mode consisting of mixing and composition functions. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub struct Blend { + pub mix: Mix, + pub compose: Compose, +} + +impl Blend { + pub fn new(mix: Mix, compose: Compose) -> Self { + Self { mix, compose } + } + + pub fn pack(&self) -> u32 { + (self.mix as u32) << 8 | self.compose as u32 + } +} + +impl Default for Blend { + fn default() -> Self { + Self { + mix: Mix::Normal, + compose: Compose::SrcOver, + } + } +} + +impl From for Blend { + fn from(mix: Mix) -> Self { + Self { + mix, + compose: Compose::SrcOver, + } + } +} + +impl From for Blend { + fn from(compose: Compose) -> Self { + Self { + mix: Mix::Normal, + compose, + } + } +} diff --git a/piet-scene/src/scene/builder.rs b/piet-scene/src/scene/builder.rs new file mode 100644 index 0000000..59e0a15 --- /dev/null +++ b/piet-scene/src/scene/builder.rs @@ -0,0 +1,433 @@ +// Copyright 2022 The piet-gpu authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Also licensed under MIT license, at your choice. + +use super::style::{Fill, Stroke}; +use super::{Affine, Blend, Element, Fragment, FragmentResources, ResourcePatch, Scene, SceneData}; +use crate::brush::*; +use crate::resource::ResourceContext; +use bytemuck::{Pod, Zeroable}; +use core::borrow::Borrow; + +/// Creates a new builder for constructing a scene. +pub fn build_scene<'a>(scene: &'a mut Scene, resources: &'a mut ResourceContext) -> Builder<'a> { + Builder::new(&mut scene.data, ResourceData::Scene(resources)) +} + +/// Creates a new builder for construction a scene fragment. +pub fn build_fragment<'a>(fragment: &'a mut Fragment) -> Builder<'a> { + Builder::new( + &mut fragment.data, + ResourceData::Fragment(&mut fragment.resources), + ) +} + +/// Builder for constructing a scene or scene fragment. +pub struct Builder<'a> { + scene: &'a mut SceneData, + resources: ResourceData<'a>, +} + +impl<'a> Builder<'a> { + /// Creates a new builder for constructing a scene. + fn new(scene: &'a mut SceneData, resources: ResourceData<'a>) -> Self { + Self { scene, resources } + } + + /// Pushes a transform matrix onto the stack. + pub fn push_transform(&mut self, transform: &Affine) {} + + /// Pops the current transform matrix. + pub fn pop_transform(&mut self) {} + + /// Pushes a new layer bound by the specifed shape and composed with + /// previous layers using the specified blend mode. + pub fn push_layer<'s, E>(&mut self, blend: Blend, elements: E) + where + E: IntoIterator, + E::IntoIter: Clone, + E::Item: Borrow, + { + let elements = elements.into_iter(); + self.encode_path(elements, true); + } + + /// Pops the current layer. + pub fn pop_layer(&mut self) {} + + /// Fills a shape using the specified style and brush. + pub fn fill<'s, E>( + &mut self, + style: Fill, + brush: &Brush, + brush_transform: Option, + elements: E, + ) where + E: IntoIterator, + E::IntoIter: Clone, + E::Item: Borrow, + { + let elements = elements.into_iter(); + self.encode_path(elements, true); + } + + /// Strokes a shape using the specified style and brush. + pub fn stroke<'s, D, E>( + &mut self, + style: &Stroke, + brush: &Brush, + brush_transform: Option, + elements: E, + ) where + D: Borrow<[f32]>, + E: IntoIterator, + E::IntoIter: Clone, + E::Item: Borrow, + { + let elements = elements.into_iter(); + self.encode_path(elements, false); + } + + /// Appends a fragment to the scene. + pub fn append(&mut self, fragment: &Fragment) { + let drawdata_base = self.scene.drawdata_stream.len(); + self.scene.append(&fragment.data); + match &mut self.resources { + ResourceData::Scene(res) => { + for patch in &fragment.resources.patches { + match patch { + ResourcePatch::Ramp { + drawdata_offset, + stops, + } => { + let stops = &fragment.resources.stops[stops.clone()]; + let ramp_id = res.add_ramp(stops); + let patch_base = *drawdata_offset + drawdata_base; + (&mut self.scene.drawdata_stream[patch_base..patch_base + 4]) + .copy_from_slice(bytemuck::bytes_of(&ramp_id)); + } + } + } + } + ResourceData::Fragment(res) => { + let stops_base = res.stops.len(); + res.stops.extend_from_slice(&fragment.resources.stops); + res.patches.extend(fragment.resources.patches.iter().map( + |pending| match pending { + ResourcePatch::Ramp { + drawdata_offset, + stops, + } => ResourcePatch::Ramp { + drawdata_offset: drawdata_offset + drawdata_base, + stops: stops.start + stops_base..stops.end + stops_base, + }, + }, + )); + } + } + } + + /// Completes construction and finalizes the underlying scene. + pub fn finish(self) {} + + fn encode_path(&mut self, elements: E, is_fill: bool) + where + E: Iterator, + E::Item: Borrow, + { + if is_fill { + self.encode_path_inner( + elements + .map(|el| *el.borrow()) + .flat_map(|el| { + match el { + Element::MoveTo(..) => Some(Element::Close), + _ => None, + } + .into_iter() + .chain(Some(el)) + }) + .chain(Some(Element::Close)), + ) + } else { + self.encode_path_inner(elements.map(|el| *el.borrow())) + } + } + + fn encode_path_inner(&mut self, elements: impl Iterator) { + let mut b = PathBuilder::new(&mut self.scene.tag_stream, &mut self.scene.pathseg_stream); + for el in elements { + match el { + Element::MoveTo(p0) => b.move_to(p0.x, p0.y), + Element::LineTo(p0) => b.line_to(p0.x, p0.y), + Element::QuadTo(p0, p1) => b.quad_to(p0.x, p0.y, p1.x, p1.y), + Element::CurveTo(p0, p1, p2) => b.cubic_to(p0.x, p0.y, p1.x, p1.y, p2.x, p2.y), + Element::Close => b.close_path(), + } + } + b.path(); + let n_pathseg = b.n_pathseg(); + self.scene.n_path += 1; + self.scene.n_pathseg += n_pathseg; + } + + fn encode_brush(&mut self, brush: &Brush) { + match brush { + Brush::Solid(color) => { + self.scene.drawtag_stream.push(DRAWTAG_FILLCOLOR); + let rgba_color = color.to_premul_u32(); + self.scene + .drawdata_stream + .extend(bytemuck::bytes_of(&FillColor { rgba_color })); + } + Brush::LinearGradient(gradient) => { + let index = self.add_ramp(&gradient.stops); + self.scene.drawtag_stream.push(DRAWTAG_FILLLINGRADIENT); + self.scene + .drawdata_stream + .extend(bytemuck::bytes_of(&FillLinGradient { + index, + p0: [gradient.start.x, gradient.start.y], + p1: [gradient.end.x, gradient.end.y], + })); + } + Brush::RadialGradient(gradient) => { + let index = self.add_ramp(&gradient.stops); + self.scene.drawtag_stream.push(DRAWTAG_FILLRADGRADIENT); + self.scene + .drawdata_stream + .extend(bytemuck::bytes_of(&FillRadGradient { + index, + p0: [gradient.center0.x, gradient.center0.y], + p1: [gradient.center1.x, gradient.center1.y], + r0: gradient.radius0, + r1: gradient.radius1, + })); + } + Brush::SweepGradient(_gradient) => todo!("sweep gradients aren't done yet!"), + Brush::Image(_image) => todo!("images aren't done yet!"), + Brush::Persistent(_) => todo!("persistent brushes aren't done yet!"), + } + } + + fn add_ramp(&mut self, stops: &[Stop]) -> u32 { + match &mut self.resources { + ResourceData::Scene(res) => res.add_ramp(stops), + ResourceData::Fragment(res) => { + let stops_start = res.stops.len(); + res.stops.extend_from_slice(stops); + let id = res.patches.len() as u32; + res.patches.push(ResourcePatch::Ramp { + drawdata_offset: self.scene.drawdata_stream.len(), + stops: stops_start..stops_start + stops.len(), + }); + id + } + } + } +} + +enum ResourceData<'a> { + Fragment(&'a mut FragmentResources), + Scene(&'a mut ResourceContext), +} + +// Tags for draw objects. See shader/drawtag.h for the authoritative source. +const DRAWTAG_FILLCOLOR: u32 = 0x44; +const DRAWTAG_FILLLINGRADIENT: u32 = 0x114; +const DRAWTAG_FILLRADGRADIENT: u32 = 0x2dc; +const DRAWTAG_BEGINCLIP: u32 = 0x05; +const DRAWTAG_ENDCLIP: u32 = 0x25; + +#[repr(C)] +#[derive(Clone, Copy, Debug, Default, Zeroable, Pod)] +pub struct FillColor { + rgba_color: u32, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug, Default, Zeroable, Pod)] +pub struct FillLinGradient { + index: u32, + p0: [f32; 2], + p1: [f32; 2], +} + +#[repr(C)] +#[derive(Clone, Copy, Debug, Default, Zeroable, Pod)] +pub struct FillRadGradient { + index: u32, + p0: [f32; 2], + p1: [f32; 2], + r0: f32, + r1: f32, +} + +#[allow(unused)] +#[repr(C)] +#[derive(Clone, Copy, Debug, Default, Zeroable, Pod)] +pub struct FillImage { + index: u32, + // [i16; 2] + offset: u32, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug, Default, Zeroable, Pod)] +pub struct Clip { + blend: u32, +} + +struct PathBuilder<'a> { + tag_stream: &'a mut Vec, + // If we're never going to use the i16 encoding, it might be + // slightly faster to store this as Vec, we'd get aligned + // stores on ARM etc. + pathseg_stream: &'a mut Vec, + first_pt: [f32; 2], + state: PathState, + n_pathseg: u32, +} + +#[derive(PartialEq)] +enum PathState { + Start, + MoveTo, + NonemptySubpath, +} + +impl<'a> PathBuilder<'a> { + pub fn new(tags: &'a mut Vec, pathsegs: &'a mut Vec) -> PathBuilder<'a> { + PathBuilder { + tag_stream: tags, + pathseg_stream: pathsegs, + first_pt: [0.0, 0.0], + state: PathState::Start, + n_pathseg: 0, + } + } + + pub fn move_to(&mut self, x: f32, y: f32) { + let buf = [x, y]; + let bytes = bytemuck::bytes_of(&buf); + self.first_pt = buf; + if self.state == PathState::MoveTo { + let new_len = self.pathseg_stream.len() - 8; + self.pathseg_stream.truncate(new_len); + } + if self.state == PathState::NonemptySubpath { + if let Some(tag) = self.tag_stream.last_mut() { + *tag |= 4; + } + } + self.pathseg_stream.extend_from_slice(bytes); + self.state = PathState::MoveTo; + } + + pub fn line_to(&mut self, x: f32, y: f32) { + if self.state == PathState::Start { + // should warn or error + return; + } + let buf = [x, y]; + let bytes = bytemuck::bytes_of(&buf); + self.pathseg_stream.extend_from_slice(bytes); + self.tag_stream.push(9); + self.state = PathState::NonemptySubpath; + self.n_pathseg += 1; + } + + pub fn quad_to(&mut self, x1: f32, y1: f32, x2: f32, y2: f32) { + if self.state == PathState::Start { + return; + } + let buf = [x1, y1, x2, y2]; + let bytes = bytemuck::bytes_of(&buf); + self.pathseg_stream.extend_from_slice(bytes); + self.tag_stream.push(10); + self.state = PathState::NonemptySubpath; + self.n_pathseg += 1; + } + + pub fn cubic_to(&mut self, x1: f32, y1: f32, x2: f32, y2: f32, x3: f32, y3: f32) { + if self.state == PathState::Start { + return; + } + 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); + self.state = PathState::NonemptySubpath; + self.n_pathseg += 1; + } + + pub fn close_path(&mut self) { + match self.state { + PathState::Start => return, + PathState::MoveTo => { + let new_len = self.pathseg_stream.len() - 8; + self.pathseg_stream.truncate(new_len); + self.state = PathState::Start; + return; + } + PathState::NonemptySubpath => (), + } + let len = self.pathseg_stream.len(); + if len < 8 { + // can't happen + return; + } + let first_bytes = bytemuck::bytes_of(&self.first_pt); + if &self.pathseg_stream[len - 8..len] != first_bytes { + self.pathseg_stream.extend_from_slice(first_bytes); + self.tag_stream.push(13); + self.n_pathseg += 1; + } else { + if let Some(tag) = self.tag_stream.last_mut() { + *tag |= 4; + } + } + self.state = PathState::Start; + } + + fn finish(&mut self) { + if self.state == PathState::MoveTo { + let new_len = self.pathseg_stream.len() - 8; + self.pathseg_stream.truncate(new_len); + } + if let Some(tag) = self.tag_stream.last_mut() { + *tag |= 4; + } + } + + /// Finish encoding a path. + /// + /// Encode this after encoding path segments. + pub fn path(&mut self) { + self.finish(); + // maybe don't encode if path is empty? might throw off sync though + self.tag_stream.push(0x10); + } + + /// Get the number of path segments. + /// + /// This is the number of path segments that will be written by the + /// path stage; use this for allocating the output buffer. + /// + /// Also note: it takes `self` for lifetime reasons. + pub fn n_pathseg(self) -> u32 { + self.n_pathseg + } +} diff --git a/piet-scene/src/scene/mod.rs b/piet-scene/src/scene/mod.rs new file mode 100644 index 0000000..df9db90 --- /dev/null +++ b/piet-scene/src/scene/mod.rs @@ -0,0 +1,97 @@ +// Copyright 2022 The piet-gpu authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Also licensed under MIT license, at your choice. + +mod blend; +mod builder; +mod style; + +pub use blend::{Blend, Compose, Mix}; +pub use builder::{build_fragment, build_scene, Builder}; +pub use style::*; + +use super::brush::*; +use super::geometry::{Affine, Rect}; +use super::path::Element; +use core::ops::Range; + +#[derive(Default)] +struct SceneData { + transform_stream: Vec, + tag_stream: Vec, + pathseg_stream: Vec, + linewidth_stream: Vec, + drawtag_stream: Vec, + drawdata_stream: Vec, + n_path: u32, + n_pathseg: u32, + n_clip: u32, +} + +impl SceneData { + fn clear(&mut self) { + self.transform_stream.clear(); + self.tag_stream.clear(); + self.pathseg_stream.clear(); + self.linewidth_stream.clear(); + self.drawtag_stream.clear(); + self.drawdata_stream.clear(); + self.n_path = 0; + self.n_pathseg = 0; + self.n_clip = 0; + } + + fn append(&mut self, other: &SceneData) { + self.transform_stream + .extend_from_slice(&other.transform_stream); + self.tag_stream.extend_from_slice(&other.tag_stream); + self.pathseg_stream.extend_from_slice(&other.pathseg_stream); + self.linewidth_stream + .extend_from_slice(&other.linewidth_stream); + self.drawtag_stream.extend_from_slice(&other.drawtag_stream); + self.drawdata_stream + .extend_from_slice(&other.drawdata_stream); + self.n_path += other.n_path; + self.n_pathseg += other.n_pathseg; + self.n_clip += other.n_clip; + } +} + +/// Encoded definition of a scene that is ready for rendering when paired with +/// an associated resource context. +#[derive(Default)] +pub struct Scene { + data: SceneData, +} + +/// Encoded definition of a scene fragment and associated resources. +#[derive(Default)] +pub struct Fragment { + data: SceneData, + resources: FragmentResources, +} + +#[derive(Default)] +struct FragmentResources { + patches: Vec, + stops: Vec, +} + +enum ResourcePatch { + Ramp { + drawdata_offset: usize, + stops: Range, + }, +} diff --git a/piet-scene/src/scene/style.rs b/piet-scene/src/scene/style.rs new file mode 100644 index 0000000..0aded61 --- /dev/null +++ b/piet-scene/src/scene/style.rs @@ -0,0 +1,71 @@ +// Copyright 2022 The piet-gpu authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Also licensed under MIT license, at your choice. + +use core::borrow::Borrow; + +/// Describes the winding rule that determines the interior portion of a path. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum Fill { + NonZero, + EvenOdd, +} + +/// Defines the connection between two segments of a stroke. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum Join { + /// A straight line connecting the segments. + Bevel, + /// The segments are extended to their natural intersection point. + Miter, + /// An arc between the segments. + Round, +} + +/// Defines the shape to be drawn at the ends of a stroke. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum Cap { + /// Flat cap. + Butt, + /// Square cap with dimensions equal to half the stroke width. + Square, + /// Rounded cap with radius equal to half the stroke width. + Round, +} + +/// Describes the visual style of a stroke. +#[derive(Copy, Clone, Debug)] +pub struct Stroke +where + D: Borrow<[f32]>, +{ + /// Width of the stroke. + pub width: f32, + /// Style for connecting segments of the stroke. + pub join: Join, + /// Limit for miter joins. + pub miter_limit: f32, + /// Style for capping the beginning of an open subpath. + pub start_cap: Cap, + /// Style for capping the end of an open subpath. + pub end_cap: Cap, + /// Lengths of dashes in alternating on/off order. + pub dash_pattern: D, + /// Offset of the first dash. + pub dash_offset: f32, + /// True if the stroke width should be affected by the scale of a + /// transform. + pub scale: bool, +}