From 5e221d2e91b772f1d23aa3148302eae86f4e48de Mon Sep 17 00:00:00 2001 From: Raph Levien Date: Sat, 25 Dec 2021 16:55:13 -0800 Subject: [PATCH 1/6] Add capability to function as a guest in Metal WIP --- piet-gpu-hal/src/lib.rs | 2 +- piet-gpu-hal/src/metal.rs | 76 +++++++++++++++++++++------------------ piet-gpu-hal/src/mux.rs | 5 +++ 3 files changed, 47 insertions(+), 36 deletions(-) diff --git a/piet-gpu-hal/src/lib.rs b/piet-gpu-hal/src/lib.rs index a0a4da3..be0c1d6 100644 --- a/piet-gpu-hal/src/lib.rs +++ b/piet-gpu-hal/src/lib.rs @@ -16,7 +16,7 @@ mod macros; mod mux; pub use crate::mux::{ - DescriptorSet, Fence, Instance, Pipeline, QueryPool, Sampler, Semaphore, ShaderCode, Surface, + DescriptorSet, Device, Fence, Instance, Pipeline, QueryPool, Sampler, Semaphore, ShaderCode, Surface, Swapchain, }; pub use bufwrite::BufWrite; diff --git a/piet-gpu-hal/src/metal.rs b/piet-gpu-hal/src/metal.rs index 45e0406..dd622fc 100644 --- a/piet-gpu-hal/src/metal.rs +++ b/piet-gpu-hal/src/metal.rs @@ -153,41 +153,7 @@ impl MtlInstance { pub fn device(&self, _surface: Option<&MtlSurface>) -> Result { if let Some(device) = metal::Device::system_default() { let cmd_queue = device.new_command_queue(); - let is_mac = device.supports_feature_set(MTLFeatureSet::macOS_GPUFamily1_v1); - let is_ios = device.supports_feature_set(MTLFeatureSet::iOS_GPUFamily1_v1); - let version = NSOperatingSystemVersion::get(); - - let use_staging_buffers = - if (is_mac && version.at_least(10, 15)) || (is_ios && version.at_least(13, 0)) { - !device.has_unified_memory() - } else { - !device.is_low_power() - }; - // TODO: these are conservative; we need to derive these from - // supports_feature_set queries. - let gpu_info = GpuInfo { - has_descriptor_indexing: false, - has_subgroups: false, - subgroup_size: None, - // The workgroup limits are taken from the minimum of a desktop installation; - // we don't support iOS right now, but in case of testing on those devices it might - // need to change these (or just queried properly). - workgroup_limits: WorkgroupLimits { - max_size: [1024, 1024, 64], - max_invocations: 1024, - }, - has_memory_model: false, - use_staging_buffers, - }; - let helpers = Arc::new(Helpers { - clear_pipeline: clear::make_clear_pipeline(&device), - }); - Ok(MtlDevice { - device, - cmd_queue: Arc::new(Mutex::new(cmd_queue)), - gpu_info, - helpers, - }) + Ok(MtlDevice::new_from_raw_mtl(device, cmd_queue)) } else { Err("can't create system default Metal device".into()) } @@ -212,6 +178,46 @@ impl MtlInstance { } } +impl MtlDevice { + pub fn new_from_raw_mtl(device: metal::Device, cmd_queue: metal::CommandQueue) -> MtlDevice { + let is_mac = device.supports_feature_set(MTLFeatureSet::macOS_GPUFamily1_v1); + let is_ios = device.supports_feature_set(MTLFeatureSet::iOS_GPUFamily1_v1); + let version = NSOperatingSystemVersion::get(); + + let use_staging_buffers = + if (is_mac && version.at_least(10, 15)) || (is_ios && version.at_least(13, 0)) { + !device.has_unified_memory() + } else { + !device.is_low_power() + }; + // TODO: these are conservative; we need to derive these from + // supports_feature_set queries. + let gpu_info = GpuInfo { + has_descriptor_indexing: false, + has_subgroups: false, + subgroup_size: None, + // The workgroup limits are taken from the minimum of a desktop installation; + // we don't support iOS right now, but in case of testing on those devices it might + // need to change these (or just queried properly). + workgroup_limits: WorkgroupLimits { + max_size: [1024, 1024, 64], + max_invocations: 1024, + }, + has_memory_model: false, + use_staging_buffers, + }; + let helpers = Arc::new(Helpers { + clear_pipeline: clear::make_clear_pipeline(&device), + }); + MtlDevice { + device, + cmd_queue: Arc::new(Mutex::new(cmd_queue)), + gpu_info, + helpers, + } + } +} + impl crate::backend::Device for MtlDevice { type Buffer = Buffer; diff --git a/piet-gpu-hal/src/mux.rs b/piet-gpu-hal/src/mux.rs index 24fef5c..654a77b 100644 --- a/piet-gpu-hal/src/mux.rs +++ b/piet-gpu-hal/src/mux.rs @@ -208,6 +208,11 @@ impl Instance { // but not doing so lets us diverge more easily (at the moment, the divergence is // missing functionality). impl Device { + #[cfg(target_os = "macos")] + pub fn new_from_raw_mtl(device: &::metal::DeviceRef, queue: &::metal::CommandQueueRef) -> Device { + Device::Mtl(metal::MtlDevice::new_from_raw_mtl(device.to_owned(), queue.to_owned())) + } + pub fn query_gpu_info(&self) -> GpuInfo { mux_match! { self; Device::Vk(d) => d.query_gpu_info(), From 833d993a4e5fa5a24b01c28488d8d3aa91e7e5a1 Mon Sep 17 00:00:00 2001 From: Raph Levien Date: Tue, 18 Jan 2022 18:41:28 -0800 Subject: [PATCH 2/6] More progress exposing interface Much of the surface area exists for rendering now. WIP of course still --- piet-gpu-hal/src/hub.rs | 27 ++++++++++++++++ piet-gpu-hal/src/lib.rs | 4 +-- piet-gpu-hal/src/metal.rs | 14 ++++++++ piet-gpu-hal/src/mux.rs | 31 ++++++++++++++++-- piet-gpu/src/glyph_render.rs | 63 ++++++++++++++++++++++++++++++++++++ piet-gpu/src/lib.rs | 1 + piet-gpu/src/text.rs | 2 +- 7 files changed, 137 insertions(+), 5 deletions(-) create mode 100644 piet-gpu/src/glyph_render.rs diff --git a/piet-gpu-hal/src/hub.rs b/piet-gpu-hal/src/hub.rs index 7b93372..ec4d169 100644 --- a/piet-gpu-hal/src/hub.rs +++ b/piet-gpu-hal/src/hub.rs @@ -401,6 +401,33 @@ impl Session { pub fn backend_type(&self) -> BackendType { self.0.device.backend_type() } + + #[cfg(target_os = "macos")] + pub unsafe fn cmd_buf_from_raw_mtl(&self, raw_cmd_buf: &::metal::CommandBufferRef) -> CmdBuf { + let cmd_buf = Some(self.0.device.cmd_buf_from_raw_mtl(raw_cmd_buf)); + let resources = Vec::new(); + // Expect client to do cleanup manually. + let session = Weak::new(); + CmdBuf { + cmd_buf, + fence: None, + resources, + session, + } + } + + #[cfg(target_os = "macos")] + pub unsafe fn image_from_raw_mtl( + &self, + raw_texture: &::metal::TextureRef, + width: u32, + height: u32, + ) -> Image { + let image = self.0.device.image_from_raw_mtl(raw_texture, width, height); + // Expect client to do cleanup manually. + let session = Weak::new(); + Image(Arc::new(ImageInner { image, session })) + } } impl SessionInner { diff --git a/piet-gpu-hal/src/lib.rs b/piet-gpu-hal/src/lib.rs index be0c1d6..3ee72b2 100644 --- a/piet-gpu-hal/src/lib.rs +++ b/piet-gpu-hal/src/lib.rs @@ -16,8 +16,8 @@ mod macros; mod mux; pub use crate::mux::{ - DescriptorSet, Device, Fence, Instance, Pipeline, QueryPool, Sampler, Semaphore, ShaderCode, Surface, - Swapchain, + DescriptorSet, Device, Fence, Instance, Pipeline, QueryPool, Sampler, Semaphore, ShaderCode, + Surface, Swapchain, }; pub use bufwrite::BufWrite; pub use hub::{ diff --git a/piet-gpu-hal/src/metal.rs b/piet-gpu-hal/src/metal.rs index dd622fc..00eef49 100644 --- a/piet-gpu-hal/src/metal.rs +++ b/piet-gpu-hal/src/metal.rs @@ -216,6 +216,20 @@ impl MtlDevice { helpers, } } + + pub fn cmd_buf_from_raw_mtl(&self, raw_cmd_buf: metal::CommandBuffer) -> CmdBuf { + let cmd_buf = raw_cmd_buf; + let helpers = self.helpers.clone(); + CmdBuf { cmd_buf, helpers } + } + + pub fn image_from_raw_mtl(&self, texture: metal::Texture, width: u32, height: u32) -> Image { + Image { + texture, + width, + height, + } + } } impl crate::backend::Device for MtlDevice { diff --git a/piet-gpu-hal/src/mux.rs b/piet-gpu-hal/src/mux.rs index 654a77b..e4d7937 100644 --- a/piet-gpu-hal/src/mux.rs +++ b/piet-gpu-hal/src/mux.rs @@ -209,8 +209,35 @@ impl Instance { // missing functionality). impl Device { #[cfg(target_os = "macos")] - pub fn new_from_raw_mtl(device: &::metal::DeviceRef, queue: &::metal::CommandQueueRef) -> Device { - Device::Mtl(metal::MtlDevice::new_from_raw_mtl(device.to_owned(), queue.to_owned())) + pub fn new_from_raw_mtl( + device: &::metal::DeviceRef, + queue: &::metal::CommandQueueRef, + ) -> Device { + Device::Mtl(metal::MtlDevice::new_from_raw_mtl( + device.to_owned(), + queue.to_owned(), + )) + } + + #[cfg(target_os = "macos")] + pub fn cmd_buf_from_raw_mtl(&self, raw_cmd_buf: &::metal::CommandBufferRef) -> CmdBuf { + // Note: this will cause problems if we support multiple back-ends on mac. But it will + // be a compile error; + let Device::Mtl(d) = self; + CmdBuf::Mtl(d.cmd_buf_from_raw_mtl(raw_cmd_buf.to_owned())) + } + + #[cfg(target_os = "macos")] + pub fn image_from_raw_mtl( + &self, + raw_texture: &::metal::TextureRef, + width: u32, + height: u32, + ) -> Image { + // Note: this will cause problems if we support multiple back-ends on mac. But it will + // be a compile error; + let Device::Mtl(d) = self; + Image::Mtl(d.image_from_raw_mtl(raw_texture.to_owned(), width, height)) } pub fn query_gpu_info(&self) -> GpuInfo { diff --git a/piet-gpu/src/glyph_render.rs b/piet-gpu/src/glyph_render.rs new file mode 100644 index 0000000..900938d --- /dev/null +++ b/piet-gpu/src/glyph_render.rs @@ -0,0 +1,63 @@ +// 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. + +//! An experimental API for glyph rendering. + +use swash::{scale::ScaleContext, CacheKey, FontRef}; + +use crate::{encoder::GlyphEncoder, PietGpuRenderContext}; + +pub struct GlyphRenderer { + pub render_ctx: PietGpuRenderContext, + scale_context: ScaleContext, +} + +#[repr(transparent)] +pub struct FontId(CacheKey); + +impl GlyphRenderer { + pub fn new() -> GlyphRenderer { + GlyphRenderer { + render_ctx: PietGpuRenderContext::new(), + scale_context: ScaleContext::new(), + } + } + + pub unsafe fn add_glyph(&mut self, font_data: &[u8], font_id: u64, glyph_id: u16) { + // This transmute is dodgy because the definition in swash isn't repr(transparent). + // I think the best solution is to have a from_u64 method, but we'll work that out + // later. + let font_id = FontId(std::mem::transmute(font_id)); + let encoder = self.make_glyph(font_data, font_id, glyph_id); + self.render_ctx.encode_glyph(&encoder); + // TODO: don't fill glyph if RGBA + self.render_ctx.fill_glyph(0xff_ff_ff_ff); + } + + fn make_glyph(&mut self, font_data: &[u8], font_id: FontId, glyph_id: u16) -> GlyphEncoder { + let mut encoder = GlyphEncoder::default(); + let font_ref = FontRef { + data: font_data, + offset: 0, + key: font_id.0, + }; + let mut scaler = self.scale_context.builder(font_ref).size(2048.).build(); + if let Some(outline) = scaler.scale_outline(glyph_id) { + crate::text::append_outline(&mut encoder, outline.verbs(), outline.points()); + } + encoder + } +} diff --git a/piet-gpu/src/lib.rs b/piet-gpu/src/lib.rs index f045d65..47de115 100644 --- a/piet-gpu/src/lib.rs +++ b/piet-gpu/src/lib.rs @@ -1,4 +1,5 @@ mod encoder; +pub mod glyph_render; mod gradient; mod pico_svg; mod render_ctx; diff --git a/piet-gpu/src/text.rs b/piet-gpu/src/text.rs index dec3ffa..0fb508b 100644 --- a/piet-gpu/src/text.rs +++ b/piet-gpu/src/text.rs @@ -260,7 +260,7 @@ impl TextLayoutBuilder for PietGpuTextLayoutBuilder { } } -fn append_outline(encoder: &mut GlyphEncoder, verbs: &[Verb], points: &[Vector]) { +pub(crate) fn append_outline(encoder: &mut GlyphEncoder, verbs: &[Verb], points: &[Vector]) { let mut path_encoder = encoder.path_encoder(); let mut i = 0; for verb in verbs { From 0cf370f9c704f04cfd9aae02b5c7b194f427ba84 Mon Sep 17 00:00:00 2001 From: Raph Levien Date: Wed, 19 Jan 2022 11:58:01 -0800 Subject: [PATCH 3/6] Mostly working rendering This exposes interfaces to render glyphs into a texture atlas. The main changes are: * Methods to plumb raw Metal GPU resources (device, texture, etc) into piet-gpu-hal objects. * A new glyph_render API specialized to rendering glyphs. This is basically the same as just painting to a canvas, but will allow better caching (and has more direct access to fonts, bypassing the Piet font type which is underdeveloped). * Ability to render to A8 target in addition to RGBA. WIP, there are some rough edges, not least of which is that the image format changes are only on mac and cause compile errors elsewhere. --- piet-gpu-hal/src/backend.rs | 11 +++- piet-gpu-hal/src/hub.rs | 11 ++-- piet-gpu-hal/src/lib.rs | 9 ++++ piet-gpu-hal/src/metal.rs | 15 ++++-- piet-gpu-hal/src/mux.rs | 14 +++-- piet-gpu/shader/build.ninja | 6 +++ piet-gpu/shader/gen/backdrop.dxil | Bin 4672 -> 4680 bytes piet-gpu/shader/gen/backdrop_lg.dxil | Bin 4676 -> 4684 bytes piet-gpu/shader/gen/bbox_clear.dxil | Bin 3160 -> 3168 bytes piet-gpu/shader/gen/binning.dxil | Bin 5800 -> 5800 bytes piet-gpu/shader/gen/coarse.dxil | Bin 10984 -> 10980 bytes piet-gpu/shader/gen/draw_leaf.dxil | Bin 6880 -> 6880 bytes piet-gpu/shader/gen/draw_reduce.dxil | Bin 3940 -> 3948 bytes piet-gpu/shader/gen/draw_root.dxil | Bin 3944 -> 3948 bytes piet-gpu/shader/gen/kernel4.dxil | Bin 10004 -> 10008 bytes piet-gpu/shader/gen/path_coarse.dxil | Bin 7064 -> 7068 bytes piet-gpu/shader/gen/pathseg.dxil | Bin 9592 -> 9596 bytes piet-gpu/shader/gen/pathtag_reduce.dxil | Bin 4644 -> 4640 bytes piet-gpu/shader/gen/pathtag_root.dxil | Bin 4716 -> 4720 bytes piet-gpu/shader/gen/tile_alloc.dxil | Bin 5048 -> 5056 bytes piet-gpu/shader/gen/transform_leaf.dxil | Bin 5664 -> 5664 bytes piet-gpu/shader/gen/transform_reduce.dxil | Bin 4696 -> 4696 bytes piet-gpu/shader/gen/transform_root.dxil | Bin 4824 -> 4828 bytes piet-gpu/shader/kernel4.comp | 10 ++++ piet-gpu/src/glyph_render.rs | 42 +++++++++++---- piet-gpu/src/lib.rs | 61 ++++++++++++++++++++-- 26 files changed, 153 insertions(+), 26 deletions(-) diff --git a/piet-gpu-hal/src/backend.rs b/piet-gpu-hal/src/backend.rs index a4422b9..1086d3b 100644 --- a/piet-gpu-hal/src/backend.rs +++ b/piet-gpu-hal/src/backend.rs @@ -16,7 +16,9 @@ //! The generic trait for backends to implement. -use crate::{BindType, BufferUsage, Error, GpuInfo, ImageLayout, MapMode, SamplerParams}; +use crate::{ + BindType, BufferUsage, Error, GpuInfo, ImageFormat, ImageLayout, MapMode, SamplerParams, +}; pub trait Device: Sized { type Buffer: 'static; @@ -47,7 +49,12 @@ pub trait Device: Sized { /// Maybe doesn't need result return? unsafe fn destroy_buffer(&self, buffer: &Self::Buffer) -> Result<(), Error>; - unsafe fn create_image2d(&self, width: u32, height: u32) -> Result; + unsafe fn create_image2d( + &self, + width: u32, + height: u32, + format: ImageFormat, + ) -> Result; /// Destroy an image. /// diff --git a/piet-gpu-hal/src/hub.rs b/piet-gpu-hal/src/hub.rs index ec4d169..ecfc2d4 100644 --- a/piet-gpu-hal/src/hub.rs +++ b/piet-gpu-hal/src/hub.rs @@ -13,7 +13,7 @@ use std::sync::{Arc, Mutex, Weak}; use bytemuck::Pod; use smallvec::SmallVec; -use crate::{mux, BackendType, BufWrite, MapMode}; +use crate::{mux, BackendType, BufWrite, ImageFormat, MapMode}; use crate::{BindType, BufferUsage, Error, GpuInfo, ImageLayout, SamplerParams}; @@ -312,8 +312,13 @@ impl Session { /// /// Currently this creates only a 2D image in RGBA8 format, with usage /// so that it can be accessed by shaders and used for transfer. - pub unsafe fn create_image2d(&self, width: u32, height: u32) -> Result { - let image = self.0.device.create_image2d(width, height)?; + pub unsafe fn create_image2d( + &self, + width: u32, + height: u32, + format: ImageFormat, + ) -> Result { + let image = self.0.device.create_image2d(width, height, format)?; Ok(Image(Arc::new(ImageInner { image, session: Arc::downgrade(&self.0), diff --git a/piet-gpu-hal/src/lib.rs b/piet-gpu-hal/src/lib.rs index 3ee72b2..fab7d65 100644 --- a/piet-gpu-hal/src/lib.rs +++ b/piet-gpu-hal/src/lib.rs @@ -91,6 +91,15 @@ pub enum SamplerParams { Linear, } +/// Image format. +#[derive(Copy, Clone, Debug)] +pub enum ImageFormat { + // 8 bit grayscale / alpha + A8, + // 8 bit per pixel RGBA + Rgba8, +} + bitflags! { /// The intended usage for a buffer, specified on creation. pub struct BufferUsage: u32 { diff --git a/piet-gpu-hal/src/metal.rs b/piet-gpu-hal/src/metal.rs index 00eef49..e3157d4 100644 --- a/piet-gpu-hal/src/metal.rs +++ b/piet-gpu-hal/src/metal.rs @@ -30,7 +30,7 @@ use metal::{CGFloat, MTLFeatureSet}; use raw_window_handle::{HasRawWindowHandle, RawWindowHandle}; -use crate::{BufferUsage, Error, GpuInfo, MapMode, WorkgroupLimits}; +use crate::{BufferUsage, Error, GpuInfo, ImageFormat, MapMode, WorkgroupLimits}; use util::*; @@ -279,14 +279,23 @@ impl crate::backend::Device for MtlDevice { Ok(()) } - unsafe fn create_image2d(&self, width: u32, height: u32) -> Result { + unsafe fn create_image2d( + &self, + width: u32, + height: u32, + format: ImageFormat, + ) -> Result { let desc = metal::TextureDescriptor::new(); desc.set_width(width as u64); desc.set_height(height as u64); // These are defaults so don't need to be explicitly set. //desc.set_depth(1); //desc.set_mipmap_level_count(1); - //desc.set_pixel_format(metal::MTLPixelFormat::RGBA8Unorm); + let mtl_format = match format { + ImageFormat::A8 => metal::MTLPixelFormat::R8Unorm, + ImageFormat::Rgba8 => metal::MTLPixelFormat::RGBA8Unorm, + }; + desc.set_pixel_format(mtl_format); desc.set_usage(metal::MTLTextureUsage::ShaderRead | metal::MTLTextureUsage::ShaderWrite); let texture = self.device.new_texture(&desc); Ok(Image { diff --git a/piet-gpu-hal/src/mux.rs b/piet-gpu-hal/src/mux.rs index e4d7937..4a54e96 100644 --- a/piet-gpu-hal/src/mux.rs +++ b/piet-gpu-hal/src/mux.rs @@ -35,6 +35,7 @@ use crate::backend::DescriptorSetBuilder as DescriptorSetBuilderTrait; use crate::backend::Device as DeviceTrait; use crate::BackendType; use crate::BindType; +use crate::ImageFormat; use crate::MapMode; use crate::{BufferUsage, Error, GpuInfo, ImageLayout, InstanceFlags}; @@ -264,11 +265,16 @@ impl Device { } } - pub unsafe fn create_image2d(&self, width: u32, height: u32) -> Result { + pub unsafe fn create_image2d( + &self, + width: u32, + height: u32, + format: ImageFormat, + ) -> Result { mux_match! { self; - Device::Vk(d) => d.create_image2d(width, height).map(Image::Vk), - Device::Dx12(d) => d.create_image2d(width, height).map(Image::Dx12), - Device::Mtl(d) => d.create_image2d(width, height).map(Image::Mtl), + Device::Vk(d) => d.create_image2d(width, height, format).map(Image::Vk), + Device::Dx12(d) => d.create_image2d(width, height, format).map(Image::Dx12), + Device::Mtl(d) => d.create_image2d(width, height, format).map(Image::Mtl), } } diff --git a/piet-gpu/shader/build.ninja b/piet-gpu/shader/build.ninja index 6a59f59..e79908a 100644 --- a/piet-gpu/shader/build.ninja +++ b/piet-gpu/shader/build.ninja @@ -58,6 +58,12 @@ build gen/kernel4.hlsl: hlsl gen/kernel4.spv build gen/kernel4.dxil: dxil gen/kernel4.hlsl build gen/kernel4.msl: msl gen/kernel4.spv +build gen/kernel4_gray.spv: glsl kernel4.comp | ptcl.h setup.h + flags = -DGRAY +build gen/kernel4_gray.hlsl: hlsl gen/kernel4_gray.spv +build gen/kernel4_gray.dxil: dxil gen/kernel4_gray.hlsl +build gen/kernel4_gray.msl: msl gen/kernel4_gray.spv + # New element pipeline follows build gen/transform_reduce.spv: glsl transform_reduce.comp | scene.h setup.h mem.h diff --git a/piet-gpu/shader/gen/backdrop.dxil b/piet-gpu/shader/gen/backdrop.dxil index 4ebcb1cc55f84fabfcb69250b09215f2e5f48a4a..10e1bd0ece9195f54e1875111def69587d416c35 100644 GIT binary patch delta 1082 zcmZ9KZA@Eb6vv-?d%3+Wx8>r-J_3)oaBa$6C%v4q=RhP-N7Muy0T3$>vOFVW!4 z7C+E;kaSz!-N+&{=`w@Ffhi%IP7>2noH$6fF*4cGU`1>?Gm|+@wisi))oG&V%X7~E z{Qe)#KTo`DxlC8zY3IQI3KQqXIh`QgBi#6D<@1j|cy#MB(JQ%F)l%Qt)EbZjz=J$+ z9tR*d0}+R!V?fmHTzu0&18{c!2kB!B-$@JK%7O;vmkw>v;USh@0@>pLR>8Z^gVTM$ zv?{ueApl+xu1L5MBgM|!5G{8OtBLp>MlZA2md&`DNZ*OTe2(TgP=xpSVjb#0-`yC5 z9OTsdRWU=P23{wCI?$`Xsh!Bw*wWK79JE1?I~h?VN#AG8AlLpXxb$Y@@P+Sxxt*CH zA2l4xG)S!>t??^&`K;o^Ed6@c<#vta1)5DJH}{|o?mnDMdu?a{?X^&TMG}Q==wOd? zzJIu>v|{+eu2ZB!}Otn0)7=P*gEFxuf-n=)IQ8Za<7}uBEb>DWWKs{xLNFMZOasX|{MeWnmE6 z^&=Gkyype<*9&Syq?D8a9}ngd^-=8UKw`{>d-RAMWL1ZwWG~ap13g8CirN1Ew2quQ zR?L=?lxSuW7=njT*hsLdQ(>eBlrK>&b$Vi$PSoOWa6(k6tv#2pOWn--5F`~XEICi( zs=`yG!;5RiyeIzltV;*=c|$owGwtn4lX^5nt+MnuCH$<^cAr;T_r&}+17LbU@nHaz zAC=7N3-~2~v5=nX*pM*PW4_t|#>XVc!U9P6zt;TD)4n>?MtS!B1{!Dxhy*_#bTEFl zutAMSm324lc5DUY%{m2V!GI*8=@Qlo7$z3%I_qjItnKWHj=q)k_ee@0$xpBr*G`^E z!C!H-YBe`JiKBVnHZE9UNv*`Z#5pkYOx`x|X+k5>Q4h|9iXuEcRU|K+W{Yp*M?gZ( zHDx&#LrKNU40%ftR2@t!`!V4p)D*|0CT|%ZG#Fb;q9FVoS&97jLW@*6BQx~~aj3!n zz=UsLyUwbPEvB_jl>=NgW7Q6fI{ESLpwzbBBiK|r_0g?zkpJZTrstNn%6xOeph~wt zH0O~oZd!W(sof Z!yKHf%faZ~9BfjFu+8YR0|HUkscB-qi0DJK4bi+@aGjCaA9`26!c&o`g% zljr+;UhZTDGgC{gMw9#1v74_Gk20)>R(`VWYmbTm0CXUglkPw2d#yZ9<=s5-%=P0+ zmVLU^T3OX42Y>+*@EHPtFb6zN@QwyvH=2SGEe^oILxx^K=}wHD<2e92NdU~;ENZgrAU$ayarwD6H5S(BU`-k01jXt^V~wYdfsARX ziYR)+xm}@7iPgY*Mgx%|@iI1d4KPj%p1C&na9s!23k~493;`|Vc->=~SoOAK`{jd$ z@lCe&uE^T@!;Q$+;`$c7ur#+xnm?Zk1-uUYHa<4WT4Z*Kqy>H>Lw2>0w-WFo{0zy4 z+y*=h@Gr*$KTOSzT=UK@n`KUY!#jB$jThURT5ZRXVOi?+t7plN&wjZ6e$a1n|6Fi6 zrTmoc(eLG_7K*ay#s28*9q)tN-`{=D`@k$4DdD}1w)TsimR5d8ZO0LX5Wku)!^?2e zElEMRO+}e~aVQz}c!Lo9G1NyxfLUBSy%hx+m<%`>5D=C5L}{Lo$AGXJl5Vjmn|#{o_VUJJfy;{5R` zc3;RSZK6IRz`WuJjZNZ+GIfSyIi=maJVL^OflIJtpR@K2^t3wrud zGM@%{gxGag^*4hf7SasalD|MXP5^O;>5)`ZE+)A=3GwwETr!r5?m@|zi)&7}fJRkk zxU~cdosraX3PPRu93k%)&k$fJjmo%d#E2neM30xYxL~38FikUFcQm+%;|o890&1zV*87HRjQ6rM`-U$8xmd! z2*+zy-A}ZV1e(HM#aeeU3^VtFQU`e<^_Z4$<)S&_`tio`ZW^D)za~7P0c|>x|G3~2 mlLo7GcL*?*Ai&QAc>bUOlUD>dTgk%)9g;7+^qt0k8vg)Ncy-|b diff --git a/piet-gpu/shader/gen/backdrop_lg.dxil b/piet-gpu/shader/gen/backdrop_lg.dxil index e6b2f1aa3f98102c410ab7d255fec28fe675633d..58e21a21a25f338d85723057bb88f2e442e8817b 100644 GIT binary patch delta 1089 zcmZ9KZ%i9?7{`CTUav>FmMb0bdRbFx&Ncyx}M})_D_DvdGUTY*zvBjuA-_>1pp5e zU<3g`nn4ODQ;znO?%<-U6am1;k%!7BGGsR){*>mYG`C&ZewPQGc?l#g0J4-^ejZ$G z2FAsd>pTSDW$~t*>oVX>goT8vu~UaeAJFDZ-fBto8 zYY_Xb{MD^;rL8C1@SWQV$ONoTBJ=8T<^8F(hGlWlc`wfAB9*pg$;wRtA)isBb&#FP=bL zup0Lq_!E>9BtT>Q2Z|cn$L}iFA)$eTKRBGS1za)V6Pq(yo-IE{WiP3yj;TT`AB%B2?m9OFv z$H-t@eU!$2RQt8ZlA6v^nMuo!eU<4PBm`QsJLco^@=_GQ$s2BSPle z8zwwmiXxRnOUdj;5hAv0^Jwh4M>W4;I{fcf>C(nt{8tN-%s+f{oe~%o+r%bcO%a-{#h2JOBUy delta 1134 zcmY+De@q)y0LNdi?e(?0((Cx)byREzRMIeZAR|bo-nG!NNbz8Xz+~n?FoQuMVC?|t+6 zzP$HI-crU~hM~CHW`A&IsN7!XBWe03)A!56Z)5;~;t4}Q^oG0I)y_h7pkx_dvvPv2k3?ZT9e*83W+r)C1KYGUU>(z>jK=8EdS7%2KLZ z!L32?D>Cwuoa#cksK^1(MF8Lo%*gFM7D!Fe1g3ebBNd%9Szt{GD}ch(-L{(kIu^3_ zVbyMc|5ag4f0sceN`sgY+|iR(J70IMaq zh?mCZ0Cpubac_EN^z7iwic>9E8{Wz3Y&_Y~)aE*Ze4;j7e)kyh;j#B)=fgp}_hDXN zilfT%!|#r&`GQPp(Z4aXFnIgM_g}v^c-yHSEfTwpu2Uzwm^Sf79Y+wY^!y4@!wYcA zt4u)xo7$3|#gQbr1{bQ;KHz`uXV@#+K0y34a|c8;9aRH?1=DoND80uQ>8BCSL{KhP z-yA|4$a)r-AUba>ZTa7lkAyTYrj26cP5Er-F2INsdHh zIDuKVIb^qR<@l$8HeHKcmhxs`O-CYOPXNb_yPqQBi?SU%ZUzoM76LEhdwbm33wDOj z9#j4Vgk;no?Bfv9o9bt=&r>z&LC$y==>!pt`|x8sB_n3Fg9bXbr2fcq8kfE#=$!zMY&>XN{z>9@+Cpw{sHCv)4yRxuCHH;&`Q@ zGBFf=lG31OzJ7EsaVx%S$3s)jLOes5lswcRO~XiGhGkC> zq@C_Zt=yr?i$U)sr&)?yng96xtMN?Xs>Ev&h}`3n%PafaZ5DV9t|K|?fv7&Gc8LmC#37&mLf{D`- QoTV3G+JfXtAN=3(Hzz=H&j0`b diff --git a/piet-gpu/shader/gen/bbox_clear.dxil b/piet-gpu/shader/gen/bbox_clear.dxil index 9ce0addb78ff37cc0ac08c5bf861f956dbca95c2..ec661f81be0e0643f9b6ed85e6bb99ef2a302e78 100644 GIT binary patch delta 444 zcmca1@jyb-CBn&>0Szz$`3V~(evAkcXB>(Pmza#A$#*iHh!kbD$EkHd`APsS_2w5rnoVj5aYNi$uP?p zY+a=U1B3nKj~u?C!Yzz94HP&H9cRcf3AZTToFKsM%;W6LAkCEC6ksXb(sFZyfPk}r zv#_h+2E_?x0_Ry6gjpCBE{aWiX6CqI7U!V_J_2p2hbQnJW^3AEkn0>6$*?taawvt6P*>B;q)Fh%ij@kH&})vG5bzM^kI=9LadrUnHGjr+$m{4ruNCu0DciYiNh;}TI9gQN=}z5G%+J_izIj$5k2 zMEs=+d@rQNUbi)ciS$dA_&r$I_*||sKv1wp!USmG!Od*@F&1YjRRg8~p431N)((eEmWG_hfVqqdESVV?DkT^g>?TJtJJ+jm9Ny?C z!NZkYEX{UAL5*Xwb3&7Wg0zrRWJh8GM}qSOAAwbAO%rsa#U4d+Bqbb#Ecy!CUG8GkR!1n@rHxIwW+xpE4XHC(aOmw%hk(FNzE$>Zd$-4 zIj=i*=AD>Zvu{sn$Z%?Vo+N%OE!;xQT-D&!goiuNENq=P^`zz`Xf7%S6V>E!_6?C4Cc8uXH#vH7H1E z+*8hoHcd)kP~c!=kubU4!3YvHkykOfoZ-a4W6r}UdB%vv$snl#q@q{C=V)@T8jFME zged|JtP{fo4t6*)12x#BZ!lzRFO+#c1ul|tz|?ViY3%naaFNUlmW}0X^PbB&y1E!7 ZT>u%_FID0HVd25=wHI|78-TF^0ss#tsty1E diff --git a/piet-gpu/shader/gen/binning.dxil b/piet-gpu/shader/gen/binning.dxil index 50034cce738c087ced84608eeb4c0ac98cd99046..849a59fc82b517ed778fa90ada4ee59404d5de8d 100644 GIT binary patch delta 1688 zcmZ9NeM}Q)9LJyQ9pzfCa?n-}D|iJ##4@kQn>x0ZmrikL$8c6bQ(i@^*g2iANv}tN zmKVo%sHjt~lbPz6!O7GuEa};fF~x}qA?VNm8g;L6ZW2v4vpXd-+5L5SzMtRoe4hI~ zPtKR@OIGDtvU9-yp0g@9ieI=`xaDt^_e@6WW7E>@+T-WC(AARAKb_0IgV}woJnZZE zSxsJ@+zVt)^bZlVM7tTG`=db02H@_1$Wkc)y9fZ@VSfrMa3~S$O^TH1jbvS`AAz{^ zIl)VKU=a5=_z#gCP=;}^M-c|;5q;`gDo7*Q2>@^YMl zcVrkdVOwC#X(VjKVm(@?2oNnsq7C1(r~F5%-ATCk1|AzAu>{orrI8%uw9A>-iWz4UnUaNGD-BlTx*?Ek(%*0Q)_=PU13msV76E!a{~X?vUL z#G;Nhm)saFK00c-G1_iDozrl?@E&HGdoc9zfqSNmjQEjruPR&;#RUieC9+nB3!h%i zUJW-npp9vULRkwiFEjy$bngIhQW;>Z-Q&*mK`6S5cN--%N!WIEE4EuhZB&^Rkf_v? z`0D#FUw2Stv^aV@rjw^bYpBCGNP7V3%FOjyXoJE{hfBGpC3GIvH5kfwLlIASFr=4u zyLt69k}#!{5;H;P_k-zre|91gkmizd*t|T-A1hr$)LTbrbZIF#t%of^L)fP{roo-_ zFhkY`&`j9IRZJ-yYp92OC_9QLIhg1n^OqPE}0H3yt$FA%xxl za0CvYRiafetBC@Xj$HwnFdR4#-mhu2SnCYaO-czjZ3!I#Bfv;K9B@v*P5SDuyFg;4 z${GZa0mpi`T?|=-+DlWlV8zDCwyJB@lkTe4e)wq%K>(C-mWQ9lOF&!HUh;SZ3=6Z^ zA9>YG7)ZGres|%ECQN(1H`@*wPP&=BCJY0Ju>8|d7L81D+#FX8^Ui|60)tWQ4sNQGdRZKkEj!;rY*5C#7BfaQ{0y?enLx`uxUa8*y`D3Wu}<*WigV9 z;203x$qrv*X#5n@EqG~hcR7Wl8;%dFo-S+X>?3G9@ zG>82ya?z?TSH5`>C=dEYIHXkA$oh zPYH#AQ?MW^Y@8=OVMo!VMDAxTyGI#?J`v&k*){CPN&*f0LQI}%*GElZFYG!2C_0Whl3%vv2*cc~qHQJmVvq{&E#O z{I)t96pbm({Cc)jrB?bvR`yCaxf`m3eLCYpv)3bsS&u5&k$-3I-Ak!rABrY)XIvnO zQhW~5tU*pZ0e(6oJD`&ccU$VxEOE*CxPs7EiyfdID6VHVb7^hE)vd$k<`?a^Tn?n> z*NwnLKml!`c^#|@iIbv&?wrLALG6BAjt z?_^onA@u?WQI{NuY~c^^vOen-Jfyt4l4JBEDJ48%i|Vmr=dpE^v{*`^140@p4(7)S zC3VXXfwXu;Ko=pDYZJt({#*fWID!gO(Ml2C{TyB?!bGzOS3HN4Mc9`ozzGc(L>iyz YjIzxuiKAeN;ygAcLf$M!|KCsOUqhujTmS$7 delta 1688 zcmYL~eM}Q)9LJw~;kcHoT;K32f>#iRSYkm?*u=HGO;NNls1;EUP-OD5PMn)!(rckm zEGXOQ#>BZ(oOTmURfaFo+&KAT#hwkyts}0#Ub>TizPD@t=^lI~ z9R9$u@F>D9;p7qL6R3ehq`ZU2$EHF_`)?J(pRQG;G!|iNi(@*Ej?8R5^>yoD8+ES)@j2+ zD8wh?rfb4TW$ zO6!{eEo&xjSOy4WuAfp1Mapy;I1*8p~N}_I|9_&xThU_mLoD3^J5kT-kWD!p%lvynG&;PxK6h`+bn| zxgXp%V?MXPQ2Uam=FqT(VhaaARH~4Zga)uYT8>yeIw1~QMY)&|i!Uex-((@ypef=j zl87c9GYC_574T3sBN}HJ5@&Kj-X!iGnQXrl6EZJvuxX1Yd}0m%Kr1l*l~1Q*4=LDk z9UuD*0TY_whKp(Wn-kh8oiK$Sl`yT(Q9{aTstzA#iAtH|6|j{m!r3?rR6vlxj{1e@@KsDB6IGyw`CV_ZN(2RF%o$DpLJB;sCwqEZ0|>2v{4kmosNpgV`M4l(CwhV zR3eDDitUMC>x=+t4VqJ_g%$@Y6An$Sp$Bmu8s z<p|x{urMP zn$BHQ>7hLC4^`H3U$D@U1uBAqM5}r`TKPL>1Eb6>ZOb>-n9u+i`akXSwen6_9(x6j zN)3gTNTnSbzGT7tL_O~>dvojyHXXrVldCP9Bh@xbFG>b`{D<0{4$y@^`Usw zaH0t$XDW`<8BCCuPJqD9%?lWucYGz?871*4g_MFyt&%!m9BaRs=@Bx>yEesLi|2Lw ztpg9z7dM6wDxiSgWBmq16Bdu*qT{gRYV~1Pop41|8dT*WS{CSU*m6NEW8pHiw0%^c zfco4c^M~SjKxxOEljfqoL)d9zvQ{%IglUvxZU-b@@aca)j`rJfGcSZwgK5^~%qSmC zd-?3c`^0GMQB)p4rart(l6uH_zxf*Jt_bI diff --git a/piet-gpu/shader/gen/coarse.dxil b/piet-gpu/shader/gen/coarse.dxil index 16d47ceb1c63abdaee8fa52a8b5a604855d036d4..a3e34c66bc3f07a896b41c4b1bb84eb997911c30 100644 GIT binary patch delta 7096 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 delta 7027 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 N>>G%7fbc#0{{{N9tmXg! delta 2058 zcmYLJZBSEJ8b0^tCL|CfALJV}5KI6Q_oB#$OCbq_;ufsB5&|Z8i9$i4gNT%^qud0D zfH($^!EB^8h1xQTPCBkT*tOjRsPa)~K-aFd+6ilQt?TSM?hbWV?d}Z{_x?KPyw82l zd7tNb-{897y4V7fK7XrW^#j+1ccYqrT;43uNWcFqwwB4+c=g_&)Q+(p+DrQU_mTPA zFZ42T6kCJ;QUd*vUa7dptDg39BAw)yXhI!Ej!MAO8j$Qp0DM1cYnzNQAy+a741^uz z@G)@P$(h#U`T2m4$!|N^)A}50E#noIcU9FgiSeLz4h#H2$=q_WD&dn(xx+D-OyqBB zkS9d}C9_jIs8L^Qus_+%$Fv?fxZ$wL9MRZE4R;;r3^{Xl>`Kj_9~>(*J}Asw$voqn zzjVtrRdnt27ne#{UCN!Ut6Qq-TdJFWjSel7d^i(VAuj)|`G%}q^4)QelJEFyVp+yd zMpdRUBXgzi5%u%&OLJ5AbzhvmG;v57^_g|U-n+xO zLL(lr3%5FfoXNNmU(bra9FX>klK|5m=!h85M>P2v3I+q%3F3vVG~)HL`v1#)5o@^w zz=v=?!T@U{*AZ*1WGGwzir)pemjktWuoY*lFQ#Gk^xpJ9kZt97b@*HO*E}{&1M-+Z zbDq(HF=QT~X~;aLoV&D(isNhoo%Cfz$sO=fOnlq$gfm{~v$0bNVgevq4qIJ1*`9K% zeXaux2cw(a3?}~9klL0kNkF63P)CorgZ1j&f?BXn6<)a_dydr^o zHnzM=Kd)~bkG6800rmJGwvM46A+jPYOd~!pz8cPP%(n9PE-n4-PlEUaf$$gB&%miQ^=KiR z1F(SK3a{~`Sw=Hy$iu8@9u5#CSKEsGpUO{>TpC6d?|VF`E=bHeObI!vO^Mow=9c!+ zd&P3ffwqfq1z*iO;xJz>(29mw2>!}hMrh$L7oKxe-YM{hjyGYI{w^eBXw!Mv$L9-; z^q4SE-6k@#NL$RQFNMZ{#tZ5*J^vf#4ll%!OiLwr&DqvzgN}U6Llw<4cCR8XJE7lSB(vP zJvA^}q^S*`cf%J#X+~k{KAyt%0kg%bYH3m&Lbe_C_`7s8N^#PAu$xr1+Ev+2 zLZ9G+@N*onSR@mkIYz}FPf<$6S{_oNMPuEB2SjoN!Vg6W2oC)s8PW*vh@_b}T&3BN zEX9mf0%INIM-fpef+f9r%PLlupk-Y1SEc6rCFkQw4ZU=!QE;dcizL47HbDlK0_DFt)yqTExnVD+c4OB(EzpuD)?oITuBmG4HxxV&4{G-hQOqw$u>U>1978%`QT} z9SuVdTUt(Uv{#0pTVg70k*$U|*;1;(z=S!+uGH7j3n%tUT)^^>ZkeT9wp8~AW$y-$n348!#y_GW zbAnWo#ZI0UHFI5BOCcZiUQt-WQ}|%{i7l+#)zqw-&bc0j{zvql&IKw%(Cb5Cs8rq8 zeWH~0AcT!9_<^446vc;I;jUx_!iFy;B8j^CUtbyR2kI88w=Z;-?edA1=r4vEsR*fu Y25E<=&ut4d=F8U*_zYldCc)D8KPdvc82|tP diff --git a/piet-gpu/shader/gen/draw_reduce.dxil b/piet-gpu/shader/gen/draw_reduce.dxil index 9b1b0fd6893fc7bdecd4093fd10ad0e5e93d2257..c6c962474bc385ae7d5db75c0397b5bab5dcc8d2 100644 GIT binary patch delta 789 zcmaDN_eM_ACBn&>0Szz$`8gXU^Vuz1cYE&tG_%1jEL6N_$GKe&E)kwSXV@7S5*Sz+ zJ_D73_zXZ=0H|XNP~6G+z&%AC28LIg53;{!WHB(XmYBSSvqh2bXaGxUAX{rd1IrTb zmRlSQcO@B488e8a0rgc%FfceyUd!w}c@7s>y)esyn+6J;hK@V5n1opl%v4}F-_{Z# zu}D&e>4t!faLbul3Je!m7A`c?aXBJz>4DE>mK=^1yeuJ%2Ur#gcx-81y3#&Z#lyujow=2@CudhFYbVbZQb|4WA?C@cXZKz`IdT4H&E!H}yZVlU$`z5ONfQ_pIM~ifI2<}2sm#X4(3Fs{ zz>$d!&J;p0mDog8jFK8a>L*JExEA!Pu{f|!<-5$#D8PI70#D=v*3B%3bq*R_VA{d- zfU7~9VS~VqCLr$wlLB{x4#Osa15F0r4m=?Y*ByD7Me7fg2po1`4UpYo5Fv1K0TZhm zj{pP9!GtE}_ne0kOcWWkew55$rtZO1rmym-AHy75Q>{mf9*YL(G^fS=3$1G9ZaGnZGQ cJ4C#S)w-bh0e_$Uk7oOZ=13-XP?`q;0G?L=x&QzG delta 781 zcmX|M5FRDJAb1{ElGZ+~ZZ^^7u4P`ADrp=4fbTyKlUI?@W{j^V z6bz0t0DSu`%+Y>@qMD4v7@MU^D;FfNrr>fcsGYEL4hI;~eNu2|3ZCd@ty8Tn;1n0fdTx{FSl;2rdXLv%dC=qCzXR=~_1Dhs ziN$wcjk{y-(yit=XOA&yJa`#l@M4a9wg5ikxUas@c-iJi6*gO<_Y2SQT-B z;iV@vs|W%lLAYZ3cAjBCC7n7%sF`#B)(WONIDQ&IMV4`TdEIE?Wi9BcH#spJwfeC2 zf-Nn&ln&#M_~Zm7=E7|lvCCBCzmn|FKjfXD&BJU};CVCjC#LEREEfutbYZy<8afhPnHz{&@Nr|kK%(g?AFHTC+;}fbO6e*; zo8t-*NzNM>Ll@%>K!j=4k^!z+TJFxJdwt}~LBzyh+LfeB^+i_DX3>T+nHHCXhH-`GEpCO^ zQXLC5A$KT$kbFeoW?CLZ=5S1iu9k%nQwZa_yh58Wf@oX_y;pC@wrnW0v>5XnmCRVb p?o&vEmU6%4#lI7p981gc1%F&OD{G`uZa%Si9v1CYr{jOW@DH5N{G|W@ diff --git a/piet-gpu/shader/gen/draw_root.dxil b/piet-gpu/shader/gen/draw_root.dxil index a84fd4aa668225d7ed426d81a25bc91b30599fa8..d0a326fddecd7759773f6d6aaa0833a4b3993080 100644 GIT binary patch delta 732 zcmaDM_eM_ACBn&>0Szz$`8gXUjoB?1imYbeD5##d$vR7x-~cuoGv>02+%(s0v2fz!}&hZ>VG%YvB-CKuaUBP5z6 zq>dLh@E+XU$e_S5LqUY8bK3@!?VL<%z5)#CO$;{DY}pcK0xY4i(p;HLN*aUP*A%0xrpU-LW(8#N3*FdrCuwQ`_?-@ndP>YUZj2uO>X)d1hhj z#HlAu_fDL;(U)_QQA&kgQEG91X;E@&aWK;gKFN9BGo|Oo$X$t^C4KkK6b9zaa@@j9 zK_bjv>q?kUnJ-}TmE&El%o!; z3;3PFdL$$mIGPxZxbh#cePus5Ihs$_xrs?t!@xU$Cxn5ekr$}gG2t-8p$h93uvZ%7 zI5-?);E@*aH()rnf{CY1n#qo#Ig%}z!;OcBf#o1WBdgtw$-DVf*jt=+dK$S7On$~E zmtwGhh2_l;W`U3gT;@p^Kt7qQzs5y!7w` zn^#*+Tp~PuSU4CM5*Sz+7?~ItKzs(Easi-@H|z`yPRktR4;(EDg6f7#=b$v}SflWCLoelwe@+ocxp1w_cjXk<8V@DD{D{Au2R-co-L%1dg4ROlT**`y?S!&)U#zQ{<20k(~ZoncG|4i zZeqS`r{+OchRt5ApBN{L@G45nco{Bu;$^;|hB>Ptgp)y;jgz4%;X#gTLF~oJ0lZ?0 z=S4T(?O^s*P>?)mGE0ELw7@#4fkA@@-xOMuS745T%SpTm>K4zOo;l9M31~%*3RsVc;FW6T-lh z$jdC+;23eZqmdElK81A~*sBb392^cZ@JI{v8!$Xu!Nk)h-DJnm9Lbi<;l{(mz;ckG zvDNOu>bWJJ&jxqlV9=4rC2OzVSe+2Ss>&CmwD0!kk=;buW{03+2nAdN#{h9 zX2=9?Yl!$|{S8f;ESnw99MU;+NOQ&`ZUc!tjwD8&G|4F{2O5A0hk+T0quJDcY~%6! J07|wn007!1_iF$E diff --git a/piet-gpu/shader/gen/kernel4.dxil b/piet-gpu/shader/gen/kernel4.dxil index 3b3c42e8c69d2a7f2bbfca14d8254af7ed99cfb1..3e21354162cfcbfc0937e0f4e6e1894c546c9b19 100644 GIT binary patch delta 5994 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 delta 5973 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 diff --git a/piet-gpu/shader/gen/path_coarse.dxil b/piet-gpu/shader/gen/path_coarse.dxil index 9fd593ca43dc26f919b022903612dc81fad0890b..b6c9398fd96324a92f6916a55a37f0d0c4376553 100644 GIT binary patch delta 2074 zcmZ8heNYo;8sANJHwjtdhVZeW2+ITlXb1~bg5bp@AfQ$*SafKMHzDFcTh8OIIAtnr zKKL+rp?oYjpdevRJv#j`Kxv!S(Ja9;wzNdBOu6e-P_%cgy#}t_a5vn|?UKZsx&3F~ z_xZiQ-}Ah`=h^L74XUJt6}kf8{~nOp4~|KH%iBG<{Mt~;p`4|~<)*^k-1!}a75krA zk^q1KfPoDN0N6di9LE@jmx=2N+}|Xk0Py3)pLv}eP)H4NW1`~Djwr%L%%ia&F{Vi! z1RcLZ0D$TXJ91RgGO|b#f=um3Do4^nFLq(V0<@q2c#2bF#gKVuRYk*Wx=61F$CHUw@Ln+g8ZJ>1gSLvD769j-4f)R0B);Vb)1TPOS( zcJZZek6piq(-~`7XFJ4?-yXeSAd8#}FQqdYiLMVfwgmajG!F8u1S;C11%f43n!l6r zQiccstHIFDkv{Xr60eaob^!z*SxD{GuJasSJQ;#8ux8XsHHqSjRKP5_dhkxp9gQ)uAdJEHnIcANnCR_%iDsvCB)S@#WwVu)zm z4^ObMQ{GT4M>I(wmUK2v+Le&_09VOiNu{AZe=N4aZb#IBX&^o#D0 zI9Ame630L)Awrtn{UjjC>~vcXs6FEFI_#dJxf_xbtI|voz@X;peYzw(ux#1qr(TXY zf{LRAMJUP?M*LGu%|!gd#F5dk$BxG_y|Ubq%OiSk*EiSo3-F+Y=j8dniQhdXW9>SX zDLbqKqE>82&9b2Fix*njPeaBmw!JI-AV;239g(0NU~S)C%?ZxQm$wIe#b!CHQ`}jb zSZh78XiU%-M4zPZJlW^V#8uC7toR=`die`qH*v| z>S%O^Y3PPPiF=jf-Lp0etDEGKo_X)(zM&7I|h*G98nsOG2U{Q3v#zZIxgB!N?O;oi3-s)yN(>rtbk za!mbvE9eQg5Xb~N7iq^8OfSLr_uhC#^^;`p_Y>4W3=x^Q&fdIq`BdnV0>LEpc})4X z5)zFjQ3n#?EBbRqCG&KL)2$Z{h?fqpsr73R~NCLtySv)yIh>W=ES6Lvwyj zEP`Xur;YWj-)(UZsZ~7Elo$Cwe_w@)z{~)Q#J6^53IlyMtcY>uZxZCicihp3fXCf9 zJWhU1Lbc>)zCNv<6MI`>QRy?Ud2m}n;7ty}uQXVN*aR)o=(VC_Bm7t`%qe#laTf zHrK)%h$1GmBoBp7u7#^w=(tOCy(i8F#`a>58wz5pXa$X<TtN6TdyHPU;G=F3&42m-!CrGS&}gtlmlXL{B{-<$XC93*SiE zoXhxkPr^`EUE1{!X>vY&vJ5NL<+eVXYdM_$M9d{oy2^;slSJu#B&l?y{8fO0pQ8Q? D17*T* delta 2185 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 delta 5206 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 HC;^(+@?;a4n4CL{#>{vC-KtMaDktP1Nn+j_3Ek z=Q)1Q9h_pnZLjo&I*%(0NC$UHc_wA9oz2ib6w9CD|)sf z&HYhdDA4<;7yuFI!9^Vac?PJRK@(Y&cOKW)Z8QL9=Ppx!VRS2htZMqE@$rx3=`-nZ z!!;W{a)KBMQhKNNp;x^ER&HWSJMImWXdHYD(R}()Nnf~%T;dw2iq}LL_^K?OgNd+6 zq1s>dxiCnbL3M1Uot_TH>wQX`r&J@+k7-24>AxSpv(U%1jLIO$ z63QxnelaU??km3r--6-?X^*}U6Vq?&ZS0#h?)ER-p0wA+kWtN(=;G*+HS0sa+&d(!#s#E1YTdZ&Z%9c zS=kdTf$-X5QAny*_3v`AI^6>$D(Ejp%PC$JO)EN#w9ZR61`PaAG%tI#X*&mr2>&Gm ztQ*oPt;nr%r3V71U|cbD90c$=*wlD=R_-qd43~tk zCRIQ4pTKNEK(Q7C6!}Js44$m=4vv8%53tbloEXPypKO*6z#XB+8%FT6tqg%wufzd%(RCF6gv2;o@XxO?4RbbyR=0R70mOa1` zpcjU8eYIno<=?)X{7$rr^R{S_dwPVK65~1hGa(e_izna!?5(R!SjqItCqpQHkyCWE zOWVIBUDc{icG*=~b~R5&9FTMYVJwCmc)~*==qkY29t05VebLnPc+p2le2If-l{$Jd zzlA2|VXHpB*UqO{_A`gbuQA&=eC%cfevLOB!pJ!~Zcai7C|SC|{<&eXW@Aa%f-q-i z>pr|{!UE7PSnT&q)>&fzMhjb?F$n?Aal+!rnH; diff --git a/piet-gpu/shader/gen/pathtag_root.dxil b/piet-gpu/shader/gen/pathtag_root.dxil index 77f12e6db0ec75e4d05be227c033a9793a2cc1a0..48584bd22a13f8f01c186da6383ccc3ba77385b3 100644 GIT binary patch delta 1497 zcmZ9Me@qis9Khe*wbvhB+f$%kSH)xe&I@04m5MQLQ%##gA0F5$0nE=mxV2CBU!eXZSNF~+xz32d_M1c z-+S--UfxW~Y>L6gS*+lH1A$zB$#7b+wxHqg_zh1~9&_FOxGQZ@la1T_YOfjq9>~E( z6aa|ml828UZud=Z>bI})s8syeup4y z-Uxc%0c0k5btQv7 zOFegEub_$adjJhO>3DhTr{SCd6N0C8UAy;f^M=%hbH{d^nJm9^_S=&}wWZ}j#p3H#Z=~g=GCu{Uuf)3j$2-1Qb?tb^ zr6Sdd?8<|g4X(yL`x|z;8n>anTEn?l&KTb-Pn_7^W&CdPB*6NQE~r6Yu$w}Ry2p&! zFF5QU?Zd`Gf_yA5gm3DQP9+&v0WUxG*2Zw%MEeqLj$24&bGt~eDiC>>qJh%O_Ta|2 z`uA0c10P7nl`xsS?D<1>x7q@Vzy3LZpaMPdVnjY~`I_a^x+xm? zVNLFk;42A~BupX(6`)0< ztfT}dc8|oNX1qvPvzTWl$v%{dWh+^xf(Nt`cjK#@Et!4!bDqo}hQ_SRX1o$0Su+yM zp;^*Q)*PC^I}m(6^f6IvO-4HLt3w-8Tk|`u{X?Yg!IY%e=EJ6T6Ji))Q!v<5ViXWY za>xXr<_R$)A~n{sBpx<4HOiVGxc@_sVUKdJqm82AWk4*t&&L31t+O9*&=7ExNrBXB=U z$v6)0o6u(~7#|KJN%)AgdZ$_14}uR%aGrr%XL> zFLA~>IIVG@M3o_!ykfPW;GBc14rK|oyCStYq2(;!>hw>im3bw7dPOhrxz!AeQrLM4 z7<$1;tf7z6UAW@eJU5$)^`0r#uTp{>v#jA9evBfRFCe@h_;=-fRE> delta 1493 zcmYL}e^3-v9Khf1-tPU{MdyPA8+RKdGCGS z_xs&9FP3^cH8I~|vHme|xADuD-}`*#z9>-N-*O!R0MwmMJR)98JU{gYe)+@5BdTkY zX}-929Xt1?WL6$s!c>pN%4f!BZ`_*sYJ9d=v?W<@JfhE8J8bM5G~}EaUKz&0z(IK} zx^lcH9+RCg$qa#1*}F5Fass5x5!i?A;I~QvNFk)4m5c7%5Uju2!NeI{?P>1pw<)m3 zA3msIfTY!Yl1NgwoRA{6g25C*0vA)ChVO|u7A`v6l2^e4Mnb5PeC~LExW)qF=YRDf zD9>o}n{7l1N5GB2dE0q+61j|WuLgO_t4SBaK}5x3P){Jqg4RP_l6*zbj7#u8x)*#F z7!ZX`cnG*Caw~`riUmM+2~Y(tm{}VVL}CP#0c9vzMAtEWoT6$3ASQ}jVGm$>$t}*H z1v_GxCd&jUk*6>Iw1w>)Sg0HiAIAwtv4Jz}|FMu!;m7g}@nytL~!H`MbF~xl&vl=_Gfpe5{_R=YKB=STq z)O_59DC*t9HUB?|K)zP?eKwD=cE--?>qi~%mC`oVEWM3 z2Ln5oYO;lk$9!fC)>%|Pp?0w<@2HA)s^}~`vMuyrqG4K{rSgqx=?X2ax1)}S{)Ibg zy~;nDMOS9gtL>gG4}Bv-uU55>n&~PtZLoX)^Gzz+pz0j8)75r*jgu}HTE@s>%WQ`L mRso+!kSaWq&k~RQ`5Cz_R-ZT&y{6wC9;^nQC?-rVe*Xdj6YOFD diff --git a/piet-gpu/shader/gen/tile_alloc.dxil b/piet-gpu/shader/gen/tile_alloc.dxil index d69db16005e41c4d04ccba4f03161ff131490b28..1a97d8203297cd715fe74a88b950c7f381d1942e 100644 GIT binary patch delta 1254 zcmZ8hZ%i9y7=Q12yVSv|ap%ONF6bNjfC7X(}nbHZ44M@jyL0oK0 zTib15x)l`!<26%sjwpsr`o(ai1W}ljh3KY)Fs%fWWt;O0Ci~!Zb}sSx^uE9M_j{k` z_dZYFU;$THgO-n9USJYH?&Hq=Tc)CuEKtuyCSV^ht?L<*M{C%X&q}#TUQ+(Rb?!aFO8&M zymX~Z|FzZ^ct7y2k|+wWtTdEd&J;S2hc_Jz*+o`pFsC$34l<;_TUelTG<)!s_QaCG z$;L1K7@8dH-sc-uhfkj0J@)2hziRi`n7r}z#e0XoU*C@2XE&~|Z*NT?s_9w$BiNP% zF*zX5@Er+Z1Js>WdQFA_03G9<=b&ORVD^2(=st6#`9fX>wo~LQR@jpaeK16zR{8@1=vTm)eA-mCC8G#RwO_)9VKde=_cYEMq46E3Q^KAB$?keE4E9(?6o20YL1PEa0 zO$(E>K=rv-T|l3A(|BP|&dr<)I*T;=t+LWYi@<8&R4^XUv?PZd@Q7JYi( ziq`@0W(%W4LP!Wkt3~%yH8da)!SCty>L6fWge@%0qO$~A1dam#FGPxs6IKS@y|KDv zP640ZydFp%>?Jk&m~1QKn3{;2Y8Ab_DL7Q`;p>W@)@Amp8$5B@mO2G)o8JTm0w?=# z2-`F2@Wj|#T=E>od~we0K+1ck9$lT;uco`|rPbyE87x6$czGmL>VHdCBoOtI{>!ow zn?HRZFiMBwK**lvt6}mRN3?igo?Kz7avG*H!OB8ju`R z#LtfT6GR`aZWzo*48mJLx#@hqjk6jlZ%AlZ))tx9;VG7wlIbR&ob{V2I zS`bEE&tU!+cP)>FAG>0D%uujXpY7jb+_cT x>RfonESa%NW(v;~{owCcq~$J{mwb{C*_C=)O*%`Q4akwH_TU*a{{cOYe*ktthPD6z delta 1237 zcmYLJZA?>F7(Ttdy}hLuxNT{@m9JYIg;jwI17vKnen15gQv$;#C}}&3GeWIE2y7(1 z{h*Y{lA2o<+?=U`ncELjMFuRAwSyo!iG^(F7Gl6K^K|5mKb}gcc`tOci30$bxFi1neb?@}?cQED7H&|F#Pz;X zU%9dBc%={k6X1bG2!PlcuymYNP%N(1g`X=h03MEBMt^`fLZ((IXa3|OQaU68s-qyz zGbab)vjB7x0Gwd@g*A?3WQJ6t7QbkS1dCpeL1rNc=owxpfeXS))Hr5VT)7PT z<-y5?8i7l7rYpD8+SY#Vf~^j^A&_6Ybej0`^p)j6_?FK5vY=0jh&-zo^bZ)F^mnW7Vr&dE|~L|_@DTk9JZwFH8L*316Q>Cf8_ZTz+vw1 zDaV)v{B6e^@BMIZTP&Bz&1FNHmLsx(HX^?yMp{p8QQ&(AZR~4Wai6N}TkwFrU42@I zqN;CCwyxO+nP*mj8pnuFR(RG_J(duw?;Cy->fhu15!v^7=l`M8dK6SkWxUqp5KTE70uYh z`(cfEEyN6n6`UY*Tb%B|#Ua<~AzMZe5YnCLd2uCIO5+QHdJa66kaxX^pMO!h5?NA9 zC`&Y!^||rB=Ll?3_BvK_;N*ZA3d z$u>SzVUabPW&cvu)Iu2;hDIk=nd1^!)03Gp3*XLMPE8?@{3H9CsCL30Wul)$D)sX8Z?N Cy@mJy diff --git a/piet-gpu/shader/gen/transform_leaf.dxil b/piet-gpu/shader/gen/transform_leaf.dxil index 32ec39935ac137a362c71d89ded97dd979d0760c..915248b0d34164c12e496d8b1f9d41e43a5c5e9c 100644 GIT binary patch delta 1694 zcmZ9NYfuwc7>0K@%Vr@PNJt2Q*s=lTl0+r}43`$%4FLsjRAG!2+X$$XN}vc9r_8Vk z*HRoKL5g-%uqqVM27(oo>14S`2C+g*Ep;r4qE%X3hWbNiI-Twc_{05mp6@;L&N<(E z&e;}Ki%P6F=n{c9zAmu}6`VX;V2<7LQhxM;+b?a;V!Rz`s0xB}jDHzylt-QKin>;G z^bF?F3b^MsgLpnd_4)xGdu?)FM!5){{Z);-YshgGB!b}+I6hHbX^@`rTLDd3F)_wzA_kCt~G|aXrD2*CVseFOIJ*qB~!2bIIsPb zwpK6yl@;4ds~+)<0MBmk2eB-4#Tt&=^9k;qTuwVKDINkqLV$&q*sJ1E)9xra zkcV=m8Uhf&oQ}7OXfJ4&bQ4NN6obi_0Dx)A!u_! zIZ!iE354$TH7QuI%r$aKYdsP} z<}>mgAVGr7cMb6GXM^DBNBkK;RABFyugHQto1!Z#HV)AX)rHOOv4-hF&nOM|hU|w{ zTdFXm+yo(md^&}qRTTnw=|EIgCEV9v=4{GzkCI;&ft|+nyi;g3zZREK3X^Uw1TxT0 z$yy;M6VO_q>Pcne7T9i?Sv?de)#4TtkoVO6o71S#ts=8ANxh$d?*WaGlCArMPJiSo z@r7}ULVLk>m+I{8Kx$1n_Gy=dwu8cAj(UTd$;*!SBx=$?r)Au8m~aDlx_87(m@4#H z8Y7-x6s?P*E}Rh;mu!DBy!nZKBB^kYpGhDN%uSdcqIWBlm-sTP59Rlxp+K@vv3!`t z_5ANyTvf_qd8aX#KhE-+GWjD`uI2y8V$#?05`VCBcME@##f&!jFpEz9Z3e3|vhV=g zbtbaU&1LoeoR@}lWI;2+M7GV(HG)T4j|kDSdg6XI46(r(r0qJM>K4>Y!lnG@xFg*QX{iSQw;WF?Hi2+JnMb%uCnT zvFdzK1dDZ9`i^ACFo*|hS?tKur>X^iiMo^Q9`({F<~=iK zgxk-A(4D9wLg~;c*U5J#UvSov9Hvu--)$Ft{I(wp?|BeHUqr7IDX&djl2pCG=Xi^4fq>%bkNNW~zzpOmoaTAej9h{SOe> BKSuxn delta 1610 zcmZ9MeM}Q)0LJgG*W;+AwzP%PqTErwEY-BimmA`h9yOqB%~rK2ZU-nb=STerb4ui{ zNFfzM<&d#0(}Fmil2HX07?^Q^cz*AGu!GmH|)DSCVO|aw&GGmZ|mdpDkCZnPyH(AQR0C!OV+LF{MlBtx66(i zA(*0`I9OWZjnsJk#%q4L#7BFgfbUCz+D}10g#au*Z*8Rx8O9RO4LOvX&Q!wiPd@pz zY?IXr=o&2rwMAtpuamlPTLD_ekB25R$6=-`0Uf(ggnwR*c|2`Nl-0fii<<`|pfyC> zV&lyn?y*HmnEV98Zh07;Ck$@g@v8^APG3Jac)9e)2aUFM4{Yi2=vm+0-r%vT>}hd0 z1f692#8_nDF|RfCj$fU&TsqY|eltHb6X3rtLb?meJ#RVnF%#wIYAq0rX~-Sa?ky(d zJyWp{z)<9rJH>wGgMA2@G*Oi zab?+n!<`!nItb*oVp>R2#k4cZGlDTegqY^EiI{*z)h%dE`DXAY+56lJ(zS10v zMmhBjK~vp-rKt=POhj-tPxN1&fo+|yjT5bRRZoXeGm_3gKPaWZh~{+KVjLcPiY)Vq z3!Jwpq|3zKnV(S^ZI^L`cmVuOE_DE9K!3K$4*J0v2`|#fKr$>+16rVyH?cOb!%A_6 zQNKHlmK0l7N#y{{(Rm>ogH@9eHYMcuxM+n41}r9j5RZI;ja82y29m6i)Gz=Na_N~5 zCadk}fua-~FkBUD%mg5ZMR}DA4>2mprO8L>;&RY7mw7g1cSbc8Eo2^l=T+uRYqSG5 z)$o}aXmBsR0tvoNuYiNg=+ygc!-5kPH&D^@paOY%K2ADSlBXHH(rETIEGofb^zvsK zX5b16XW6hB^VYDblJB&mSB|Ip8Z7T)sWJL{Kvslw=6tqnvIGQAOo!c_3Evgy$D=7o z)|`IWx@MSr>T&r(mpgB}WXsGU*LB}AY`!9~ayx_!g>ktwXRMOLFHZwqo%IWOQIua8 znu4EFf*llb0Al$N(fZ~;)UPh?tc z;>$aPbz9ALaE2L^jSymDUiRxMzP!cgA9mjCo-@bXvu5lP-kh6qU~1%zhvdy1*HBm? zfpkg53P&O-cHvth`PpOjeP|M3Q}4qs3P{vn5-@&0J`xF5c2HFPHv*?t;M0Ol*N+RB za}wX81v`pb>Te0S_B4J`z@GXac=W8Luo!lb$SP-;iaLqtxibZMYOdicyTwN?Hai2!5N;T+ZJ<23-8{4T|S&WkdRI?@5y`g4?mb|cfNxp1M zA0KW9>I@`l$l;OFFA^|s4VfpPU%yzuZ4S~a;H2IxptqRx+92nUJRw!Uv)f3+Djw|# z%UQdMNtno8UbE#xkvEvj-|Up;7fCU<2gufjLl&JEOBMEssOAFu&+6j;q(Q)^c~E>8A`PkDXG zy^YCV?@?SB@k#15Dg3*~j4bJiHE>^|eHW7Z29wi59zj)iJ;Zu`%}fCV3vVg^{R>!d BFXsRN diff --git a/piet-gpu/shader/gen/transform_reduce.dxil b/piet-gpu/shader/gen/transform_reduce.dxil index 63df381194f6336e5c7fa13118ab5248ff4ef02a..5bd59c0abba2a99dff2fa37e30bd43212e60370e 100644 GIT binary patch delta 1346 zcmZ9MZA=?w0LPzu>Gj%O*_B?yl@@z+g@G$uI~icy>Xj}PUy7Zp45l9rC`c5RWg3Ep zq}Niq?giwUt(|;W|Sl#ia7j4z*Z)<>CIE`^9x%ox3xBPh13}F79@1A0s`k z)f^whXNL&sAds|#A*K!Ezfl2cvyk*Y4S=<8MrwB}(B+?vjKpL~8ej#A4lvB3-&acy zsWfmZNNlnaT~?s>i3ga&mr&?bA)frAK40$-V@HRIIIE+L(QN{S_)&JK#IVrjO%^Lq zmk_b!_o)3cbg=DLKRn0JeSZG?=1Vs}ven$Ql^5WrgV!cf{WA+AXD93uOQ6uzvAw;% zwY}-ce)!WY)hBbBgLK`;Z~myRQ~eTRimm?NbqC7s*K94XDJw6C-V!E&vkNr0ClN1)e(kSY`pSYV!^_rC2=xk#+p z*uVh>$7a+OO^DF7SWwh?eUI7im5U^_<{BI4bXlp`px7$Yu-y2#+&i#{-#ujHlx#FE75 zL0VLXSJjv1gIPvIn^-`ih&1PwYclVC+K%%t*&rK10yNHF?sf*yKyd^nFX(ExL#IwW z#w+9)LeKBSE$cg1wdOTD9h+Z!NXDdC{~t%W6ps%>MX+|5)$vNA1j>#_A-Mx_B+OO+ zTERA&YtVb^5nU9EQ0^dn4AdCseJ`Su*j`@7?$YOXXG3H4qsKzHUlwpja(Qoc;mKHBr5{q%I7FV$*b|d9fT8n#(ZftIiRpNnRS5`aneU-amHktb%Ocm zpv_hDQ_nl?=z%ykDT}`xj2n=BXu*_^sz#&UxZ#K{0_dhCpYv4#EhX*`(mb;Kh~p*a z(|F^aZz*GMpG{-Iscz~Z8ubruznGak*zJ5n!2BJT(^%v2bk4&x+5h!_lD*m}S5GJOWrEu(xGC0cwoOBw2Ks8_1x+jg!{%``y*lzQqp)N& zo+b1UlV?D)5dt1a_{g>J{0J-{{*_~{D|Z>yPD4$Q525JKb}(<3yxX+CW~vu5tZf h`P#pjl6PUk$&VhM+_9`y-P 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 GlyphRenderer { + let render_ctx = PietGpuRenderContext::new(); + let scale_context = ScaleContext::new(); GlyphRenderer { - render_ctx: PietGpuRenderContext::new(), - scale_context: ScaleContext::new(), + render_ctx, + scale_context, } } - pub unsafe fn add_glyph(&mut self, font_data: &[u8], font_id: u64, glyph_id: u16) { + pub unsafe fn add_glyph( + &mut self, + font_data: &[u8], + font_id: u64, + glyph_id: u16, + transform: [f32; 6], + ) { // This transmute is dodgy because the definition in swash isn't repr(transparent). // I think the best solution is to have a from_u64 method, but we'll work that out // later. let font_id = FontId(std::mem::transmute(font_id)); let encoder = self.make_glyph(font_data, font_id, glyph_id); + const DEFAULT_UPEM: u16 = 2048; + let affine = Affine::new([ + transform[0] as f64, + transform[1] as f64, + transform[2] as f64, + transform[3] as f64, + transform[4] as f64, + transform[5] as f64, + ]) * Affine::scale(1.0 / DEFAULT_UPEM as f64); + self.render_ctx.transform(affine); self.render_ctx.encode_glyph(&encoder); // TODO: don't fill glyph if RGBA self.render_ctx.fill_glyph(0xff_ff_ff_ff); + self.render_ctx.transform(affine.inverse()); + } + + pub fn reset(&mut self) { + self.render_ctx = PietGpuRenderContext::new(); } fn make_glyph(&mut self, font_data: &[u8], font_id: FontId, glyph_id: u16) -> GlyphEncoder { let mut encoder = GlyphEncoder::default(); - let font_ref = FontRef { - data: font_data, - offset: 0, - key: font_id.0, - }; + let font_data = FontDataRef::new(font_data).expect("invalid font"); + let mut font_ref = font_data.get(0).expect("invalid font index"); + font_ref.key = font_id.0; let mut scaler = self.scale_context.builder(font_ref).size(2048.).build(); if let Some(outline) = scaler.scale_outline(glyph_id) { crate::text::append_outline(&mut encoder, outline.verbs(), outline.points()); + } else { + println!("failed to scale"); } encoder } diff --git a/piet-gpu/src/lib.rs b/piet-gpu/src/lib.rs index 47de115..3c1e27f 100644 --- a/piet-gpu/src/lib.rs +++ b/piet-gpu/src/lib.rs @@ -49,6 +49,18 @@ pub fn dump_k1_data(k1_buf: &[u32]) { } } +pub struct RenderConfig { + width: usize, + height: usize, + format: PixelFormat, +} + +// Should we just use the enum from piet-gpu-hal? +pub enum PixelFormat { + A8, + Rgba8, +} + pub struct Renderer { // These sizes are aligned to tile boundaries, though at some point // we'll want to have a good strategy for dealing with odd sizes. @@ -106,15 +118,41 @@ pub struct Renderer { gradients: Image, } +impl RenderConfig { + pub fn new(width: usize, height: usize) -> RenderConfig { + RenderConfig { + width, + height, + format: PixelFormat::Rgba8, + } + } + + pub fn pixel_format(mut self, format: PixelFormat) -> Self { + self.format = format; + self + } +} + impl Renderer { - /// Create a new renderer. pub unsafe fn new( session: &Session, width: usize, height: usize, n_bufs: usize, + ) -> Result { + let config = RenderConfig::new(width, height); + Self::new_from_config(session, config, n_bufs) + } + + /// Create a new renderer. + pub unsafe fn new_from_config( + session: &Session, + config: RenderConfig, + n_bufs: usize, ) -> Result { // For now, round up to tile alignment + let width = config.width; + let height = config.height; let width = width + (width.wrapping_neg() & (TILE_W - 1)); let height = height + (height.wrapping_neg() & (TILE_W - 1)); let dev = BufferUsage::STORAGE | BufferUsage::COPY_DST; @@ -126,7 +164,11 @@ impl Renderer { .map(|_| session.create_buffer(8 * 1024 * 1024, host_upload).unwrap()) .collect::>(); - let image_dev = session.create_image2d(width as u32, height as u32)?; + let image_format = match config.format { + PixelFormat::A8 => piet_gpu_hal::ImageFormat::A8, + PixelFormat::Rgba8 => piet_gpu_hal::ImageFormat::Rgba8, + }; + let image_dev = session.create_image2d(width as u32, height as u32, image_format)?; // Note: this must be updated when the config struct size changes. const CONFIG_BUFFER_SIZE: u64 = std::mem::size_of::() as u64; @@ -211,7 +253,10 @@ impl Renderer { .collect(); let gradients = Self::make_gradient_image(&session); - let k4_code = include_shader!(session, "../shader/gen/kernel4"); + let k4_code = match config.format { + PixelFormat::A8 => include_shader!(session, "../shader/gen/kernel4_gray"), + PixelFormat::Rgba8 => include_shader!(session, "../shader/gen/kernel4"), + }; let k4_pipeline = session.create_compute_pipeline( k4_code, &[ @@ -428,7 +473,8 @@ impl Renderer { return Err("unsupported image format".into()); } let buffer = session.create_buffer_init(&buf, BufferUsage::COPY_SRC)?; - let image = session.create_image2d(width.try_into()?, height.try_into()?)?; + const RGBA: piet_gpu_hal::ImageFormat = piet_gpu_hal::ImageFormat::Rgba8; + let image = session.create_image2d(width.try_into()?, height.try_into()?, RGBA)?; let mut cmd_buf = session.cmd_buf()?; cmd_buf.begin(); cmd_buf.image_barrier(&image, ImageLayout::Undefined, ImageLayout::BlitDst); @@ -464,8 +510,13 @@ impl Renderer { fn make_gradient_image(session: &Session) -> Image { unsafe { + const RGBA: piet_gpu_hal::ImageFormat = piet_gpu_hal::ImageFormat::Rgba8; session - .create_image2d(gradient::N_SAMPLES as u32, gradient::N_GRADIENTS as u32) + .create_image2d( + gradient::N_SAMPLES as u32, + gradient::N_GRADIENTS as u32, + RGBA, + ) .unwrap() } } From 2613a7e500a8f6c0a2ebf0a88302bb4558ce18c3 Mon Sep 17 00:00:00 2001 From: Raph Levien Date: Wed, 19 Jan 2022 12:18:32 -0800 Subject: [PATCH 4/6] Add generated kernel4_gray shaders --- piet-gpu/shader/gen/kernel4_gray.dxil | Bin 0 -> 9936 bytes piet-gpu/shader/gen/kernel4_gray.hlsl | 688 ++++++++++++++++++++++++ piet-gpu/shader/gen/kernel4_gray.msl | 727 ++++++++++++++++++++++++++ piet-gpu/shader/gen/kernel4_gray.spv | Bin 0 -> 38880 bytes 4 files changed, 1415 insertions(+) create mode 100644 piet-gpu/shader/gen/kernel4_gray.dxil create mode 100644 piet-gpu/shader/gen/kernel4_gray.hlsl create mode 100644 piet-gpu/shader/gen/kernel4_gray.msl create mode 100644 piet-gpu/shader/gen/kernel4_gray.spv diff --git a/piet-gpu/shader/gen/kernel4_gray.dxil b/piet-gpu/shader/gen/kernel4_gray.dxil new file mode 100644 index 0000000000000000000000000000000000000000..7bd557b984270e95bd0f3e3266d850a75a725d7b GIT binary patch literal 9936 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 z image_atlas : register(u3, space0); +RWTexture2D gradients : register(u4, space0); +RWTexture2D image : register(u2, space0); + +static uint3 gl_WorkGroupID; +static uint3 gl_LocalInvocationID; +struct SPIRV_Cross_Input +{ + uint3 gl_WorkGroupID : SV_GroupID; + uint3 gl_LocalInvocationID : SV_GroupThreadID; +}; + +uint spvPackUnorm4x8(float4 value) +{ + uint4 Packed = uint4(round(saturate(value) * 255.0)); + return Packed.x | (Packed.y << 8) | (Packed.z << 16) | (Packed.w << 24); +} + +float4 spvUnpackUnorm4x8(uint value) +{ + uint4 Packed = uint4(value & 0xff, (value >> 8) & 0xff, (value >> 16) & 0xff, value >> 24); + return float4(Packed) / 255.0; +} + +Alloc slice_mem(Alloc a, uint offset, uint size) +{ + Alloc _215 = { a.offset + offset }; + return _215; +} + +bool touch_mem(Alloc alloc, uint offset) +{ + return true; +} + +uint read_mem(Alloc alloc, uint offset) +{ + Alloc param = alloc; + uint param_1 = offset; + if (!touch_mem(param, param_1)) + { + return 0u; + } + uint v = _202.Load(offset * 4 + 8); + return v; +} + +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 _432 = { tag_and_flags & 65535u, tag_and_flags >> uint(16) }; + return _432; +} + +CmdStroke CmdStroke_read(Alloc a, CmdStrokeRef 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); + CmdStroke s; + s.tile_ref = raw0; + s.half_width = asfloat(raw1); + return s; +} + +CmdStroke Cmd_Stroke_read(Alloc a, CmdRef ref) +{ + CmdStrokeRef _449 = { ref.offset + 4u }; + Alloc param = a; + CmdStrokeRef param_1 = _449; + return CmdStroke_read(param, param_1); +} + +Alloc new_alloc(uint offset, uint size, bool mem_ok) +{ + Alloc a; + a.offset = offset; + return a; +} + +TileSeg TileSeg_read(Alloc a, TileSegRef 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); + TileSeg s; + s.origin = float2(asfloat(raw0), asfloat(raw1)); + s._vector = float2(asfloat(raw2), asfloat(raw3)); + s.y_edge = asfloat(raw4); + TileSegRef _572 = { raw5 }; + s.next = _572; + return s; +} + +uint2 chunk_offset(uint i) +{ + return uint2((i % 2u) * 8u, (i / 2u) * 4u); +} + +CmdFill CmdFill_read(Alloc a, CmdFillRef 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); + CmdFill s; + s.tile_ref = raw0; + s.backdrop = int(raw1); + return s; +} + +CmdFill Cmd_Fill_read(Alloc a, CmdRef ref) +{ + CmdFillRef _439 = { ref.offset + 4u }; + Alloc param = a; + CmdFillRef param_1 = _439; + return CmdFill_read(param, param_1); +} + +CmdAlpha CmdAlpha_read(Alloc a, CmdAlphaRef ref) +{ + uint ix = ref.offset >> uint(2); + Alloc param = a; + uint param_1 = ix + 0u; + uint raw0 = read_mem(param, param_1); + CmdAlpha s; + s.alpha = asfloat(raw0); + return s; +} + +CmdAlpha Cmd_Alpha_read(Alloc a, CmdRef ref) +{ + CmdAlphaRef _459 = { ref.offset + 4u }; + Alloc param = a; + CmdAlphaRef param_1 = _459; + return CmdAlpha_read(param, param_1); +} + +CmdColor CmdColor_read(Alloc a, CmdColorRef ref) +{ + uint ix = ref.offset >> uint(2); + Alloc param = a; + uint param_1 = ix + 0u; + uint raw0 = read_mem(param, param_1); + CmdColor s; + s.rgba_color = raw0; + return s; +} + +CmdColor Cmd_Color_read(Alloc a, CmdRef ref) +{ + CmdColorRef _469 = { ref.offset + 4u }; + Alloc param = a; + CmdColorRef param_1 = _469; + return CmdColor_read(param, param_1); +} + +float3 fromsRGB(float3 srgb) +{ + bool3 cutoff = bool3(srgb.x >= 0.040449999272823333740234375f.xxx.x, srgb.y >= 0.040449999272823333740234375f.xxx.y, srgb.z >= 0.040449999272823333740234375f.xxx.z); + float3 below = srgb / 12.9200000762939453125f.xxx; + float3 above = pow((srgb + 0.054999999701976776123046875f.xxx) / 1.05499994754791259765625f.xxx, 2.400000095367431640625f.xxx); + return float3(cutoff.x ? above.x : below.x, cutoff.y ? above.y : below.y, cutoff.z ? above.z : below.z); +} + +float4 unpacksRGB(uint srgba) +{ + float4 color = spvUnpackUnorm4x8(srgba).wzyx; + float3 param = color.xyz; + return float4(fromsRGB(param), color.w); +} + +CmdLinGrad CmdLinGrad_read(Alloc a, CmdLinGradRef 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); + CmdLinGrad s; + s.index = raw0; + s.line_x = asfloat(raw1); + s.line_y = asfloat(raw2); + s.line_c = asfloat(raw3); + return s; +} + +CmdLinGrad Cmd_LinGrad_read(Alloc a, CmdRef ref) +{ + CmdLinGradRef _479 = { ref.offset + 4u }; + Alloc param = a; + CmdLinGradRef param_1 = _479; + return CmdLinGrad_read(param, param_1); +} + +CmdImage CmdImage_read(Alloc a, CmdImageRef 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); + CmdImage s; + s.index = raw0; + s.offset = int2(int(raw1 << uint(16)) >> 16, int(raw1) >> 16); + return s; +} + +CmdImage Cmd_Image_read(Alloc a, CmdRef ref) +{ + CmdImageRef _489 = { ref.offset + 4u }; + Alloc param = a; + CmdImageRef param_1 = _489; + return CmdImage_read(param, param_1); +} + +void fillImage(out float4 spvReturnValue[8], uint2 xy, CmdImage cmd_img) +{ + float4 rgba[8]; + for (uint i = 0u; i < 8u; i++) + { + uint param = i; + int2 uv = int2(xy + chunk_offset(param)) + cmd_img.offset; + float4 fg_rgba = image_atlas[uv]; + float3 param_1 = fg_rgba.xyz; + float3 _695 = fromsRGB(param_1); + fg_rgba.x = _695.x; + fg_rgba.y = _695.y; + fg_rgba.z = _695.z; + rgba[i] = fg_rgba; + } + spvReturnValue = rgba; +} + +float3 tosRGB(float3 rgb) +{ + bool3 cutoff = bool3(rgb.x >= 0.003130800090730190277099609375f.xxx.x, rgb.y >= 0.003130800090730190277099609375f.xxx.y, rgb.z >= 0.003130800090730190277099609375f.xxx.z); + float3 below = 12.9200000762939453125f.xxx * rgb; + float3 above = (1.05499994754791259765625f.xxx * pow(rgb, 0.416660010814666748046875f.xxx)) - 0.054999999701976776123046875f.xxx; + return float3(cutoff.x ? above.x : below.x, cutoff.y ? above.y : below.y, cutoff.z ? above.z : below.z); +} + +uint packsRGB(inout float4 rgba) +{ + float3 param = rgba.xyz; + rgba = float4(tosRGB(param), rgba.w); + return spvPackUnorm4x8(rgba.wzyx); +} + +CmdJump CmdJump_read(Alloc a, CmdJumpRef ref) +{ + uint ix = ref.offset >> uint(2); + Alloc param = a; + uint param_1 = ix + 0u; + uint raw0 = read_mem(param, param_1); + CmdJump s; + s.new_ref = raw0; + return s; +} + +CmdJump Cmd_Jump_read(Alloc a, CmdRef ref) +{ + CmdJumpRef _499 = { ref.offset + 4u }; + Alloc param = a; + CmdJumpRef param_1 = _499; + return CmdJump_read(param, param_1); +} + +void comp_main() +{ + uint tile_ix = (gl_WorkGroupID.y * _723.Load(8)) + gl_WorkGroupID.x; + Alloc _738; + _738.offset = _723.Load(24); + Alloc param; + param.offset = _738.offset; + uint param_1 = tile_ix * 1024u; + uint param_2 = 1024u; + Alloc cmd_alloc = slice_mem(param, param_1, param_2); + CmdRef _747 = { cmd_alloc.offset }; + CmdRef cmd_ref = _747; + 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]; + for (uint i = 0u; i < 8u; i++) + { + rgba[i] = 0.0f.xxxx; + } + uint clip_depth = 0u; + bool mem_ok = _202.Load(4) == 0u; + float df[8]; + TileSegRef tile_seg_ref; + float area[8]; + uint blend_stack[128][8]; + float blend_alpha_stack[128][8]; + while (mem_ok) + { + Alloc param_3 = cmd_alloc; + CmdRef param_4 = cmd_ref; + uint tag = Cmd_tag(param_3, param_4).tag; + if (tag == 0u) + { + break; + } + switch (tag) + { + case 2u: + { + Alloc param_5 = cmd_alloc; + CmdRef param_6 = cmd_ref; + CmdStroke stroke = Cmd_Stroke_read(param_5, param_6); + for (uint k = 0u; k < 8u; k++) + { + df[k] = 1000000000.0f; + } + TileSegRef _842 = { stroke.tile_ref }; + tile_seg_ref = _842; + do + { + uint param_7 = tile_seg_ref.offset; + uint param_8 = 24u; + 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); + float2 line_vec = seg._vector; + for (uint k_1 = 0u; k_1 < 8u; k_1++) + { + float2 dpos = (xy + 0.5f.xx) - seg.origin; + uint param_12 = k_1; + dpos += float2(chunk_offset(param_12)); + float t = clamp(dot(line_vec, dpos) / dot(line_vec, line_vec), 0.0f, 1.0f); + df[k_1] = min(df[k_1], length((line_vec * t) - dpos)); + } + tile_seg_ref = seg.next; + } while (tile_seg_ref.offset != 0u); + for (uint k_2 = 0u; k_2 < 8u; k_2++) + { + area[k_2] = clamp((stroke.half_width + 0.5f) - df[k_2], 0.0f, 1.0f); + } + cmd_ref.offset += 12u; + break; + } + case 1u: + { + Alloc param_13 = cmd_alloc; + CmdRef param_14 = cmd_ref; + CmdFill fill = Cmd_Fill_read(param_13, param_14); + for (uint k_3 = 0u; k_3 < 8u; k_3++) + { + area[k_3] = float(fill.backdrop); + } + TileSegRef _964 = { fill.tile_ref }; + tile_seg_ref = _964; + do + { + uint param_15 = tile_seg_ref.offset; + uint param_16 = 24u; + 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); + for (uint k_4 = 0u; k_4 < 8u; k_4++) + { + uint param_20 = k_4; + float2 my_xy = xy + float2(chunk_offset(param_20)); + float2 start = seg_1.origin - my_xy; + float2 end = start + seg_1._vector; + float2 window = clamp(float2(start.y, end.y), 0.0f.xx, 1.0f.xx); + if (window.x != window.y) + { + float2 t_1 = (window - start.y.xx) / seg_1._vector.y.xx; + float2 xs = float2(lerp(start.x, end.x, t_1.x), lerp(start.x, end.x, t_1.y)); + float xmin = min(min(xs.x, xs.y), 1.0f) - 9.9999999747524270787835121154785e-07f; + float xmax = max(xs.x, xs.y); + float b = min(xmax, 1.0f); + float c = max(b, 0.0f); + float d = max(xmin, 0.0f); + float a = ((b + (0.5f * ((d * d) - (c * c)))) - xmin) / (xmax - xmin); + area[k_4] += (a * (window.x - window.y)); + } + area[k_4] += (sign(seg_1._vector.x) * clamp((my_xy.y - seg_1.y_edge) + 1.0f, 0.0f, 1.0f)); + } + tile_seg_ref = seg_1.next; + } while (tile_seg_ref.offset != 0u); + for (uint k_5 = 0u; k_5 < 8u; k_5++) + { + area[k_5] = min(abs(area[k_5]), 1.0f); + } + cmd_ref.offset += 12u; + break; + } + case 3u: + { + for (uint k_6 = 0u; k_6 < 8u; k_6++) + { + area[k_6] = 1.0f; + } + cmd_ref.offset += 4u; + break; + } + case 4u: + { + Alloc param_21 = cmd_alloc; + CmdRef param_22 = cmd_ref; + CmdAlpha alpha = Cmd_Alpha_read(param_21, param_22); + for (uint k_7 = 0u; k_7 < 8u; k_7++) + { + area[k_7] = alpha.alpha; + } + cmd_ref.offset += 8u; + break; + } + case 5u: + { + Alloc param_23 = cmd_alloc; + CmdRef param_24 = cmd_ref; + CmdColor color = Cmd_Color_read(param_23, param_24); + uint param_25 = color.rgba_color; + float4 fg = unpacksRGB(param_25); + for (uint k_8 = 0u; k_8 < 8u; k_8++) + { + float4 fg_k = fg * area[k_8]; + rgba[k_8] = (rgba[k_8] * (1.0f - fg_k.w)) + fg_k; + } + cmd_ref.offset += 8u; + break; + } + case 6u: + { + Alloc param_26 = cmd_alloc; + CmdRef param_27 = cmd_ref; + CmdLinGrad lin = Cmd_LinGrad_read(param_26, param_27); + 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++) + { + uint param_28 = k_9; + float2 chunk_xy = float2(chunk_offset(param_28)); + float my_d = (d_1 + (lin.line_x * chunk_xy.x)) + (lin.line_y * chunk_xy.y); + 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 _1298 = fromsRGB(param_29); + fg_rgba.x = _1298.x; + fg_rgba.y = _1298.y; + fg_rgba.z = _1298.z; + rgba[k_9] = fg_rgba; + } + cmd_ref.offset += 20u; + break; + } + case 7u: + { + 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 _1327[8]; + fillImage(_1327, param_32, param_33); + float4 img[8] = _1327; + 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; + } + cmd_ref.offset += 12u; + break; + } + case 8u: + { + for (uint k_11 = 0u; k_11 < 8u; k_11++) + { + uint d_2 = min(clip_depth, 127u); + float4 param_34 = float4(rgba[k_11]); + uint _1390 = packsRGB(param_34); + blend_stack[d_2][k_11] = _1390; + blend_alpha_stack[d_2][k_11] = clamp(abs(area[k_11]), 0.0f, 1.0f); + rgba[k_11] = 0.0f.xxxx; + } + clip_depth++; + cmd_ref.offset += 4u; + break; + } + case 9u: + { + clip_depth--; + for (uint k_12 = 0u; k_12 < 8u; k_12++) + { + uint d_3 = min(clip_depth, 127u); + uint param_35 = blend_stack[d_3][k_12]; + float4 bg = unpacksRGB(param_35); + float4 fg_1 = (rgba[k_12] * area[k_12]) * blend_alpha_stack[d_3][k_12]; + rgba[k_12] = (bg * (1.0f - fg_1.w)) + fg_1; + } + cmd_ref.offset += 4u; + break; + } + case 10u: + { + Alloc param_36 = cmd_alloc; + CmdRef param_37 = cmd_ref; + CmdRef _1469 = { Cmd_Jump_read(param_36, param_37).new_ref }; + cmd_ref = _1469; + cmd_alloc.offset = cmd_ref.offset; + break; + } + } + } + for (uint i_1 = 0u; i_1 < 8u; i_1++) + { + uint param_38 = i_1; + image[int2(xy_uint + chunk_offset(param_38))] = rgba[i_1].w.x; + } +} + +[numthreads(8, 4, 1)] +void main(SPIRV_Cross_Input stage_input) +{ + gl_WorkGroupID = stage_input.gl_WorkGroupID; + gl_LocalInvocationID = stage_input.gl_LocalInvocationID; + comp_main(); +} diff --git a/piet-gpu/shader/gen/kernel4_gray.msl b/piet-gpu/shader/gen/kernel4_gray.msl new file mode 100644 index 0000000..e672020 --- /dev/null +++ b/piet-gpu/shader/gen/kernel4_gray.msl @@ -0,0 +1,727 @@ +#pragma clang diagnostic ignored "-Wmissing-prototypes" +#pragma clang diagnostic ignored "-Wmissing-braces" + +#include +#include + +using namespace metal; + +template +struct spvUnsafeArray +{ + T elements[Num ? Num : 1]; + + thread T& operator [] (size_t pos) thread + { + return elements[pos]; + } + constexpr const thread T& operator [] (size_t pos) const thread + { + return elements[pos]; + } + + device T& operator [] (size_t pos) device + { + return elements[pos]; + } + constexpr const device T& operator [] (size_t pos) const device + { + return elements[pos]; + } + + constexpr const constant T& operator [] (size_t pos) const constant + { + return elements[pos]; + } + + threadgroup T& operator [] (size_t pos) threadgroup + { + return elements[pos]; + } + constexpr const threadgroup T& operator [] (size_t pos) const threadgroup + { + return elements[pos]; + } +}; + +struct Alloc +{ + uint offset; +}; + +struct CmdStrokeRef +{ + uint offset; +}; + +struct CmdStroke +{ + uint tile_ref; + float half_width; +}; + +struct CmdFillRef +{ + uint offset; +}; + +struct CmdFill +{ + uint tile_ref; + int backdrop; +}; + +struct CmdColorRef +{ + uint offset; +}; + +struct CmdColor +{ + uint rgba_color; +}; + +struct CmdLinGradRef +{ + uint offset; +}; + +struct CmdLinGrad +{ + uint index; + float line_x; + float line_y; + float line_c; +}; + +struct CmdImageRef +{ + uint offset; +}; + +struct CmdImage +{ + uint index; + int2 offset; +}; + +struct CmdAlphaRef +{ + uint offset; +}; + +struct CmdAlpha +{ + float alpha; +}; + +struct CmdJumpRef +{ + uint offset; +}; + +struct CmdJump +{ + uint new_ref; +}; + +struct CmdRef +{ + uint offset; +}; + +struct CmdTag +{ + uint tag; + uint flags; +}; + +struct TileSegRef +{ + uint offset; +}; + +struct TileSeg +{ + float2 origin; + float2 vector; + float y_edge; + TileSegRef next; +}; + +struct Memory +{ + uint mem_offset; + uint mem_error; + uint memory[1]; +}; + +struct Alloc_1 +{ + uint offset; +}; + +struct Config +{ + uint n_elements; + uint n_pathseg; + uint width_in_tiles; + uint height_in_tiles; + Alloc_1 tile_alloc; + Alloc_1 bin_alloc; + Alloc_1 ptcl_alloc; + Alloc_1 pathseg_alloc; + Alloc_1 anno_alloc; + Alloc_1 trans_alloc; + Alloc_1 bbox_alloc; + Alloc_1 drawmonoid_alloc; + uint n_trans; + uint n_path; + uint trans_offset; + uint linewidth_offset; + uint pathtag_offset; + uint pathseg_offset; +}; + +struct ConfigBuf +{ + Config conf; +}; + +constant uint3 gl_WorkGroupSize [[maybe_unused]] = uint3(8u, 4u, 1u); + +static inline __attribute__((always_inline)) +Alloc slice_mem(thread const Alloc& a, thread const uint& offset, thread const uint& size) +{ + return Alloc{ a.offset + offset }; +} + +static inline __attribute__((always_inline)) +bool touch_mem(thread const Alloc& alloc, thread const uint& offset) +{ + return true; +} + +static inline __attribute__((always_inline)) +uint read_mem(thread const Alloc& alloc, thread const uint& offset, device Memory& v_202) +{ + Alloc param = alloc; + uint param_1 = offset; + if (!touch_mem(param, param_1)) + { + return 0u; + } + uint v = v_202.memory[offset]; + return v; +} + +static inline __attribute__((always_inline)) +CmdTag Cmd_tag(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_202) +{ + Alloc param = a; + uint param_1 = ref.offset >> uint(2); + uint tag_and_flags = read_mem(param, param_1, v_202); + 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_202) +{ + uint ix = ref.offset >> uint(2); + Alloc param = a; + uint param_1 = ix + 0u; + uint raw0 = read_mem(param, param_1, v_202); + Alloc param_2 = a; + uint param_3 = ix + 1u; + uint raw1 = read_mem(param_2, param_3, v_202); + CmdStroke s; + s.tile_ref = raw0; + s.half_width = as_type(raw1); + return s; +} + +static inline __attribute__((always_inline)) +CmdStroke Cmd_Stroke_read(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_202) +{ + Alloc param = a; + CmdStrokeRef param_1 = CmdStrokeRef{ ref.offset + 4u }; + return CmdStroke_read(param, param_1, v_202); +} + +static inline __attribute__((always_inline)) +Alloc new_alloc(thread const uint& offset, thread const uint& size, thread const bool& mem_ok) +{ + Alloc a; + a.offset = offset; + return a; +} + +static inline __attribute__((always_inline)) +TileSeg TileSeg_read(thread const Alloc& a, thread const TileSegRef& ref, device Memory& v_202) +{ + uint ix = ref.offset >> uint(2); + Alloc param = a; + uint param_1 = ix + 0u; + uint raw0 = read_mem(param, param_1, v_202); + Alloc param_2 = a; + uint param_3 = ix + 1u; + uint raw1 = read_mem(param_2, param_3, v_202); + Alloc param_4 = a; + uint param_5 = ix + 2u; + uint raw2 = read_mem(param_4, param_5, v_202); + Alloc param_6 = a; + uint param_7 = ix + 3u; + uint raw3 = read_mem(param_6, param_7, v_202); + Alloc param_8 = a; + uint param_9 = ix + 4u; + uint raw4 = read_mem(param_8, param_9, v_202); + Alloc param_10 = a; + uint param_11 = ix + 5u; + uint raw5 = read_mem(param_10, param_11, v_202); + TileSeg s; + s.origin = float2(as_type(raw0), as_type(raw1)); + s.vector = float2(as_type(raw2), as_type(raw3)); + s.y_edge = as_type(raw4); + s.next = TileSegRef{ raw5 }; + return s; +} + +static inline __attribute__((always_inline)) +uint2 chunk_offset(thread const uint& i) +{ + return uint2((i % 2u) * 8u, (i / 2u) * 4u); +} + +static inline __attribute__((always_inline)) +CmdFill CmdFill_read(thread const Alloc& a, thread const CmdFillRef& ref, device Memory& v_202) +{ + uint ix = ref.offset >> uint(2); + Alloc param = a; + uint param_1 = ix + 0u; + uint raw0 = read_mem(param, param_1, v_202); + Alloc param_2 = a; + uint param_3 = ix + 1u; + uint raw1 = read_mem(param_2, param_3, v_202); + CmdFill s; + s.tile_ref = raw0; + s.backdrop = int(raw1); + return s; +} + +static inline __attribute__((always_inline)) +CmdFill Cmd_Fill_read(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_202) +{ + Alloc param = a; + CmdFillRef param_1 = CmdFillRef{ ref.offset + 4u }; + return CmdFill_read(param, param_1, v_202); +} + +static inline __attribute__((always_inline)) +CmdAlpha CmdAlpha_read(thread const Alloc& a, thread const CmdAlphaRef& ref, device Memory& v_202) +{ + uint ix = ref.offset >> uint(2); + Alloc param = a; + uint param_1 = ix + 0u; + uint raw0 = read_mem(param, param_1, v_202); + 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_202) +{ + Alloc param = a; + CmdAlphaRef param_1 = CmdAlphaRef{ ref.offset + 4u }; + return CmdAlpha_read(param, param_1, v_202); +} + +static inline __attribute__((always_inline)) +CmdColor CmdColor_read(thread const Alloc& a, thread const CmdColorRef& ref, device Memory& v_202) +{ + uint ix = ref.offset >> uint(2); + Alloc param = a; + uint param_1 = ix + 0u; + uint raw0 = read_mem(param, param_1, v_202); + 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_202) +{ + Alloc param = a; + CmdColorRef param_1 = CmdColorRef{ ref.offset + 4u }; + return CmdColor_read(param, param_1, v_202); +} + +static inline __attribute__((always_inline)) +float3 fromsRGB(thread const float3& srgb) +{ + bool3 cutoff = srgb >= float3(0.040449999272823333740234375); + float3 below = srgb / float3(12.9200000762939453125); + float3 above = pow((srgb + float3(0.054999999701976776123046875)) / float3(1.05499994754791259765625), float3(2.400000095367431640625)); + return select(below, above, cutoff); +} + +static inline __attribute__((always_inline)) +float4 unpacksRGB(thread const uint& srgba) +{ + float4 color = unpack_unorm4x8_to_float(srgba).wzyx; + float3 param = color.xyz; + return float4(fromsRGB(param), color.w); +} + +static inline __attribute__((always_inline)) +CmdLinGrad CmdLinGrad_read(thread const Alloc& a, thread const CmdLinGradRef& ref, device Memory& v_202) +{ + uint ix = ref.offset >> uint(2); + Alloc param = a; + uint param_1 = ix + 0u; + uint raw0 = read_mem(param, param_1, v_202); + Alloc param_2 = a; + uint param_3 = ix + 1u; + uint raw1 = read_mem(param_2, param_3, v_202); + Alloc param_4 = a; + uint param_5 = ix + 2u; + uint raw2 = read_mem(param_4, param_5, v_202); + Alloc param_6 = a; + uint param_7 = ix + 3u; + uint raw3 = read_mem(param_6, param_7, v_202); + CmdLinGrad s; + s.index = raw0; + s.line_x = as_type(raw1); + s.line_y = as_type(raw2); + s.line_c = as_type(raw3); + return s; +} + +static inline __attribute__((always_inline)) +CmdLinGrad Cmd_LinGrad_read(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_202) +{ + Alloc param = a; + CmdLinGradRef param_1 = CmdLinGradRef{ ref.offset + 4u }; + return CmdLinGrad_read(param, param_1, v_202); +} + +static inline __attribute__((always_inline)) +CmdImage CmdImage_read(thread const Alloc& a, thread const CmdImageRef& ref, device Memory& v_202) +{ + uint ix = ref.offset >> uint(2); + Alloc param = a; + uint param_1 = ix + 0u; + uint raw0 = read_mem(param, param_1, v_202); + Alloc param_2 = a; + uint param_3 = ix + 1u; + uint raw1 = read_mem(param_2, param_3, v_202); + CmdImage s; + s.index = raw0; + s.offset = int2(int(raw1 << uint(16)) >> 16, int(raw1) >> 16); + return s; +} + +static inline __attribute__((always_inline)) +CmdImage Cmd_Image_read(thread const Alloc& a, thread const CmdRef& ref, device Memory& v_202) +{ + Alloc param = a; + CmdImageRef param_1 = CmdImageRef{ ref.offset + 4u }; + return CmdImage_read(param, param_1, v_202); +} + +static inline __attribute__((always_inline)) +spvUnsafeArray fillImage(thread const uint2& xy, thread const CmdImage& cmd_img, thread texture2d image_atlas) +{ + spvUnsafeArray rgba; + for (uint i = 0u; i < 8u; i++) + { + uint param = i; + 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 _695 = fromsRGB(param_1); + fg_rgba.x = _695.x; + fg_rgba.y = _695.y; + fg_rgba.z = _695.z; + rgba[i] = fg_rgba; + } + return rgba; +} + +static inline __attribute__((always_inline)) +float3 tosRGB(thread const float3& rgb) +{ + bool3 cutoff = rgb >= float3(0.003130800090730190277099609375); + float3 below = float3(12.9200000762939453125) * rgb; + float3 above = (float3(1.05499994754791259765625) * pow(rgb, float3(0.416660010814666748046875))) - float3(0.054999999701976776123046875); + return select(below, above, cutoff); +} + +static inline __attribute__((always_inline)) +uint packsRGB(thread float4& rgba) +{ + float3 param = rgba.xyz; + rgba = float4(tosRGB(param), rgba.w); + return pack_float_to_unorm4x8(rgba.wzyx); +} + +static inline __attribute__((always_inline)) +CmdJump CmdJump_read(thread const Alloc& a, thread const CmdJumpRef& ref, device Memory& v_202) +{ + uint ix = ref.offset >> uint(2); + Alloc param = a; + uint param_1 = ix + 0u; + uint raw0 = read_mem(param, param_1, v_202); + 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_202) +{ + Alloc param = a; + CmdJumpRef param_1 = CmdJumpRef{ ref.offset + 4u }; + return CmdJump_read(param, param_1, v_202); +} + +kernel void main0(device Memory& v_202 [[buffer(0)]], const device ConfigBuf& _723 [[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 * _723.conf.width_in_tiles) + gl_WorkGroupID.x; + Alloc param; + param.offset = _723.conf.ptcl_alloc.offset; + uint param_1 = tile_ix * 1024u; + uint param_2 = 1024u; + Alloc cmd_alloc = slice_mem(param, param_1, param_2); + CmdRef cmd_ref = CmdRef{ cmd_alloc.offset }; + uint2 xy_uint = uint2(gl_LocalInvocationID.x + (16u * gl_WorkGroupID.x), gl_LocalInvocationID.y + (16u * gl_WorkGroupID.y)); + float2 xy = float2(xy_uint); + spvUnsafeArray rgba; + for (uint i = 0u; i < 8u; i++) + { + rgba[i] = float4(0.0); + } + uint clip_depth = 0u; + bool mem_ok = v_202.mem_error == 0u; + spvUnsafeArray df; + TileSegRef tile_seg_ref; + spvUnsafeArray area; + spvUnsafeArray, 128> blend_stack; + spvUnsafeArray, 128> blend_alpha_stack; + while (mem_ok) + { + Alloc param_3 = cmd_alloc; + CmdRef param_4 = cmd_ref; + uint tag = Cmd_tag(param_3, param_4, v_202).tag; + if (tag == 0u) + { + break; + } + switch (tag) + { + case 2u: + { + Alloc param_5 = cmd_alloc; + CmdRef param_6 = cmd_ref; + CmdStroke stroke = Cmd_Stroke_read(param_5, param_6, v_202); + for (uint k = 0u; k < 8u; k++) + { + df[k] = 1000000000.0; + } + tile_seg_ref = TileSegRef{ stroke.tile_ref }; + do + { + uint param_7 = tile_seg_ref.offset; + uint param_8 = 24u; + 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_202); + float2 line_vec = seg.vector; + for (uint k_1 = 0u; k_1 < 8u; k_1++) + { + float2 dpos = (xy + float2(0.5)) - seg.origin; + uint param_12 = k_1; + dpos += float2(chunk_offset(param_12)); + float t = fast::clamp(dot(line_vec, dpos) / dot(line_vec, line_vec), 0.0, 1.0); + df[k_1] = fast::min(df[k_1], length((line_vec * t) - dpos)); + } + tile_seg_ref = seg.next; + } while (tile_seg_ref.offset != 0u); + for (uint k_2 = 0u; k_2 < 8u; k_2++) + { + area[k_2] = fast::clamp((stroke.half_width + 0.5) - df[k_2], 0.0, 1.0); + } + cmd_ref.offset += 12u; + break; + } + case 1u: + { + Alloc param_13 = cmd_alloc; + CmdRef param_14 = cmd_ref; + CmdFill fill = Cmd_Fill_read(param_13, param_14, v_202); + for (uint k_3 = 0u; k_3 < 8u; k_3++) + { + area[k_3] = float(fill.backdrop); + } + tile_seg_ref = TileSegRef{ fill.tile_ref }; + do + { + uint param_15 = tile_seg_ref.offset; + uint param_16 = 24u; + 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_202); + for (uint k_4 = 0u; k_4 < 8u; k_4++) + { + uint param_20 = k_4; + float2 my_xy = xy + float2(chunk_offset(param_20)); + float2 start = seg_1.origin - my_xy; + float2 end = start + seg_1.vector; + float2 window = fast::clamp(float2(start.y, end.y), float2(0.0), float2(1.0)); + if ((isunordered(window.x, window.y) || window.x != window.y)) + { + float2 t_1 = (window - float2(start.y)) / float2(seg_1.vector.y); + float2 xs = float2(mix(start.x, end.x, t_1.x), mix(start.x, end.x, t_1.y)); + float xmin = fast::min(fast::min(xs.x, xs.y), 1.0) - 9.9999999747524270787835121154785e-07; + float xmax = fast::max(xs.x, xs.y); + float b = fast::min(xmax, 1.0); + float c = fast::max(b, 0.0); + float d = fast::max(xmin, 0.0); + float a = ((b + (0.5 * ((d * d) - (c * c)))) - xmin) / (xmax - xmin); + area[k_4] += (a * (window.x - window.y)); + } + area[k_4] += (sign(seg_1.vector.x) * fast::clamp((my_xy.y - seg_1.y_edge) + 1.0, 0.0, 1.0)); + } + tile_seg_ref = seg_1.next; + } while (tile_seg_ref.offset != 0u); + for (uint k_5 = 0u; k_5 < 8u; k_5++) + { + area[k_5] = fast::min(abs(area[k_5]), 1.0); + } + cmd_ref.offset += 12u; + break; + } + case 3u: + { + for (uint k_6 = 0u; k_6 < 8u; k_6++) + { + area[k_6] = 1.0; + } + cmd_ref.offset += 4u; + break; + } + case 4u: + { + Alloc param_21 = cmd_alloc; + CmdRef param_22 = cmd_ref; + CmdAlpha alpha = Cmd_Alpha_read(param_21, param_22, v_202); + for (uint k_7 = 0u; k_7 < 8u; k_7++) + { + area[k_7] = alpha.alpha; + } + cmd_ref.offset += 8u; + break; + } + case 5u: + { + Alloc param_23 = cmd_alloc; + CmdRef param_24 = cmd_ref; + CmdColor color = Cmd_Color_read(param_23, param_24, v_202); + uint param_25 = color.rgba_color; + float4 fg = unpacksRGB(param_25); + for (uint k_8 = 0u; k_8 < 8u; k_8++) + { + float4 fg_k = fg * area[k_8]; + rgba[k_8] = (rgba[k_8] * (1.0 - fg_k.w)) + fg_k; + } + cmd_ref.offset += 8u; + break; + } + case 6u: + { + Alloc param_26 = cmd_alloc; + CmdRef param_27 = cmd_ref; + CmdLinGrad lin = Cmd_LinGrad_read(param_26, param_27, v_202); + 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++) + { + uint param_28 = k_9; + float2 chunk_xy = float2(chunk_offset(param_28)); + float my_d = (d_1 + (lin.line_x * chunk_xy.x)) + (lin.line_y * chunk_xy.y); + 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 _1298 = fromsRGB(param_29); + fg_rgba.x = _1298.x; + fg_rgba.y = _1298.y; + fg_rgba.z = _1298.z; + rgba[k_9] = fg_rgba; + } + cmd_ref.offset += 20u; + break; + } + case 7u: + { + Alloc param_30 = cmd_alloc; + CmdRef param_31 = cmd_ref; + CmdImage fill_img = Cmd_Image_read(param_30, param_31, v_202); + uint2 param_32 = xy_uint; + CmdImage param_33 = fill_img; + spvUnsafeArray img; + img = fillImage(param_32, param_33, image_atlas); + 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; + } + cmd_ref.offset += 12u; + break; + } + case 8u: + { + for (uint k_11 = 0u; k_11 < 8u; k_11++) + { + uint d_2 = min(clip_depth, 127u); + float4 param_34 = float4(rgba[k_11]); + uint _1390 = packsRGB(param_34); + blend_stack[d_2][k_11] = _1390; + blend_alpha_stack[d_2][k_11] = fast::clamp(abs(area[k_11]), 0.0, 1.0); + rgba[k_11] = float4(0.0); + } + clip_depth++; + cmd_ref.offset += 4u; + break; + } + case 9u: + { + clip_depth--; + for (uint k_12 = 0u; k_12 < 8u; k_12++) + { + uint d_3 = min(clip_depth, 127u); + uint param_35 = blend_stack[d_3][k_12]; + float4 bg = unpacksRGB(param_35); + float4 fg_1 = (rgba[k_12] * area[k_12]) * blend_alpha_stack[d_3][k_12]; + rgba[k_12] = (bg * (1.0 - fg_1.w)) + fg_1; + } + cmd_ref.offset += 4u; + break; + } + case 10u: + { + Alloc param_36 = cmd_alloc; + CmdRef param_37 = cmd_ref; + cmd_ref = CmdRef{ Cmd_Jump_read(param_36, param_37, v_202).new_ref }; + cmd_alloc.offset = cmd_ref.offset; + break; + } + } + } + for (uint i_1 = 0u; i_1 < 8u; i_1++) + { + uint param_38 = i_1; + image.write(float4(rgba[i_1].w), uint2(int2(xy_uint + chunk_offset(param_38)))); + } +} + diff --git a/piet-gpu/shader/gen/kernel4_gray.spv b/piet-gpu/shader/gen/kernel4_gray.spv new file mode 100644 index 0000000000000000000000000000000000000000..61e5b1cc0b7161e3317f50b0f55fdf0ac03c307e GIT binary patch literal 38880 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 WwQ~Qu*Npdk`#jk8JQu~Di~kSi%`^i5 literal 0 HcmV?d00001 From b2e7c80d3ba3d6d9f99d6f9ec911109c83d049d9 Mon Sep 17 00:00:00 2001 From: Raph Levien Date: Mon, 7 Feb 2022 13:54:24 -0800 Subject: [PATCH 5/6] Fix non-mac builds Also updates comment. We know the implementation is incomplete and needs refinement, but it seems useful to commit as a starting point for further work. --- piet-gpu-hal/src/dx12.rs | 9 ++++++--- piet-gpu-hal/src/hub.rs | 5 +---- piet-gpu-hal/src/vulkan.rs | 10 +++++++--- piet-gpu/src/glyph_render.rs | 2 +- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/piet-gpu-hal/src/dx12.rs b/piet-gpu-hal/src/dx12.rs index 337ca04..78ad449 100644 --- a/piet-gpu-hal/src/dx12.rs +++ b/piet-gpu-hal/src/dx12.rs @@ -21,7 +21,7 @@ use raw_window_handle::{HasRawWindowHandle, RawWindowHandle}; use smallvec::SmallVec; -use crate::{BindType, BufferUsage, Error, GpuInfo, ImageLayout, MapMode, WorkgroupLimits}; +use crate::{BindType, BufferUsage, Error, GpuInfo, ImageLayout, MapMode, WorkgroupLimits, ImageFormat}; use self::{ descriptor::{CpuHeapRefOwned, DescriptorPool, GpuHeapRefOwned}, @@ -321,8 +321,11 @@ impl crate::backend::Device for Dx12Device { Ok(()) } - unsafe fn create_image2d(&self, width: u32, height: u32) -> Result { - let format = winapi::shared::dxgiformat::DXGI_FORMAT_R8G8B8A8_UNORM; + unsafe fn create_image2d(&self, width: u32, height: u32, format: ImageFormat) -> Result { + let format = match format { + ImageFormat::A8 => winapi::shared::dxgiformat::DXGI_FORMAT_R8_UNORM, + ImageFormat::Rgba8 => winapi::shared::dxgiformat::DXGI_FORMAT_R8G8B8A8_UNORM, + }; let resource = self .device .create_texture2d_buffer(width.into(), height, format, true)?; diff --git a/piet-gpu-hal/src/hub.rs b/piet-gpu-hal/src/hub.rs index ecfc2d4..8c5926a 100644 --- a/piet-gpu-hal/src/hub.rs +++ b/piet-gpu-hal/src/hub.rs @@ -308,10 +308,7 @@ impl Session { } } - /// Create an image. - /// - /// Currently this creates only a 2D image in RGBA8 format, with usage - /// so that it can be accessed by shaders and used for transfer. + /// Create an image of the given size and pixel format. pub unsafe fn create_image2d( &self, width: u32, diff --git a/piet-gpu-hal/src/vulkan.rs b/piet-gpu-hal/src/vulkan.rs index d5b31cb..924e2d6 100644 --- a/piet-gpu-hal/src/vulkan.rs +++ b/piet-gpu-hal/src/vulkan.rs @@ -13,7 +13,7 @@ use smallvec::SmallVec; use crate::backend::Device as DeviceTrait; use crate::{ - BindType, BufferUsage, Error, GpuInfo, ImageLayout, MapMode, SamplerParams, SubgroupSize, + BindType, BufferUsage, Error, GpuInfo, ImageFormat, ImageLayout, MapMode, SamplerParams, SubgroupSize, WorkgroupLimits, }; @@ -533,7 +533,7 @@ impl crate::backend::Device for VkDevice { Ok(()) } - unsafe fn create_image2d(&self, width: u32, height: u32) -> Result { + unsafe fn create_image2d(&self, width: u32, height: u32, format: ImageFormat) -> Result { let device = &self.device.device; let extent = vk::Extent3D { width, @@ -545,10 +545,14 @@ impl crate::backend::Device for VkDevice { let usage = vk::ImageUsageFlags::STORAGE | vk::ImageUsageFlags::TRANSFER_SRC | vk::ImageUsageFlags::TRANSFER_DST; + let vk_format = match format { + ImageFormat::A8 => vk::Format::R8_UNORM, + ImageFormat::Rgba8 => vk::Format::R8G8B8A8_UNORM, + }; let image = device.create_image( &vk::ImageCreateInfo::builder() .image_type(vk::ImageType::TYPE_2D) - .format(vk::Format::R8G8B8A8_UNORM) + .format(vk_format) .extent(extent) .mip_levels(1) .array_layers(1) diff --git a/piet-gpu/src/glyph_render.rs b/piet-gpu/src/glyph_render.rs index b848703..8f4c626 100644 --- a/piet-gpu/src/glyph_render.rs +++ b/piet-gpu/src/glyph_render.rs @@ -17,7 +17,7 @@ //! An experimental API for glyph rendering. use piet::{kurbo::Affine, RenderContext}; -use swash::{scale::ScaleContext, CacheKey, FontDataRef, FontRef}; +use swash::{scale::ScaleContext, CacheKey, FontDataRef}; use crate::{encoder::GlyphEncoder, PietGpuRenderContext}; From 43c5ed29b2c7cd96849578429fcadea889509523 Mon Sep 17 00:00:00 2001 From: Raph Levien Date: Mon, 7 Feb 2022 17:30:17 -0800 Subject: [PATCH 6/6] Fix generated shaders --- piet-gpu/shader/build.ninja | 6 +++--- piet-gpu/shader/gen/backdrop.dxil | Bin 4680 -> 4672 bytes piet-gpu/shader/gen/backdrop_lg.dxil | Bin 4684 -> 4676 bytes piet-gpu/shader/gen/bbox_clear.dxil | Bin 3168 -> 3160 bytes piet-gpu/shader/gen/binning.dxil | Bin 5800 -> 5800 bytes piet-gpu/shader/gen/coarse.dxil | Bin 10980 -> 10984 bytes piet-gpu/shader/gen/draw_leaf.dxil | Bin 6880 -> 6880 bytes piet-gpu/shader/gen/draw_reduce.dxil | Bin 3948 -> 3940 bytes piet-gpu/shader/gen/draw_root.dxil | Bin 3948 -> 3944 bytes piet-gpu/shader/gen/kernel4.dxil | Bin 10008 -> 10004 bytes piet-gpu/shader/gen/kernel4_gray.dxil | Bin 9936 -> 9932 bytes piet-gpu/shader/gen/path_coarse.dxil | Bin 7068 -> 7064 bytes piet-gpu/shader/gen/pathseg.dxil | Bin 9596 -> 9592 bytes piet-gpu/shader/gen/pathtag_reduce.dxil | Bin 4640 -> 4644 bytes piet-gpu/shader/gen/pathtag_root.dxil | Bin 4720 -> 4716 bytes piet-gpu/shader/gen/tile_alloc.dxil | Bin 5056 -> 5048 bytes piet-gpu/shader/gen/transform_leaf.dxil | Bin 5664 -> 5664 bytes piet-gpu/shader/gen/transform_reduce.dxil | Bin 4696 -> 4696 bytes piet-gpu/shader/gen/transform_root.dxil | Bin 4828 -> 4824 bytes 19 files changed, 3 insertions(+), 3 deletions(-) diff --git a/piet-gpu/shader/build.ninja b/piet-gpu/shader/build.ninja index 448caf2..7b80f6f 100644 --- a/piet-gpu/shader/build.ninja +++ b/piet-gpu/shader/build.ninja @@ -119,6 +119,6 @@ build gen/draw_leaf.hlsl: hlsl gen/draw_leaf.spv build gen/draw_leaf.dxil: dxil gen/draw_leaf.hlsl build gen/draw_leaf.msl: msl gen/draw_leaf.spv -build spv: phony gen/backdrop_lg.spv gen/backdrop.spv gen/bbox_clear.spv gen/binning.spv gen/coarse.spv gen/draw_leaf.spv gen/draw_reduce.spv gen/draw_root.spv gen/kernel4.spv gen/path_coarse.spv gen/pathseg.spv gen/pathtag_reduce.spv gen/pathtag_root.spv gen/tile_alloc.spv gen/transform_leaf.spv gen/transform_reduce.spv gen/transform_root.spv -build dxil: phony gen/backdrop.hlsl gen/backdrop_lg.hlsl gen/bbox_clear.hlsl gen/binning.hlsl gen/coarse.hlsl gen/draw_leaf.hlsl gen/draw_reduce.hlsl gen/draw_root.hlsl gen/kernel4.hlsl gen/path_coarse.hlsl gen/pathseg.hlsl gen/pathtag_reduce.hlsl gen/pathtag_root.hlsl gen/tile_alloc.hlsl gen/transform_leaf.hlsl gen/transform_reduce.hlsl gen/transform_root.hlsl -build msl: phony gen/backdrop_lg.msl gen/backdrop.msl gen/bbox_clear.msl gen/binning.msl gen/coarse.msl gen/draw_leaf.msl gen/draw_reduce.msl gen/draw_root.msl gen/kernel4.msl gen/path_coarse.msl gen/pathseg.msl gen/pathtag_reduce.msl gen/pathtag_root.msl gen/tile_alloc.msl gen/transform_leaf.msl gen/transform_reduce.msl gen/transform_root.msl +build spv: phony gen/backdrop_lg.spv gen/backdrop.spv gen/bbox_clear.spv gen/binning.spv gen/coarse.spv gen/draw_leaf.spv gen/draw_reduce.spv gen/draw_root.spv gen/kernel4.spv gen/kernel4_gray.spv gen/path_coarse.spv gen/pathseg.spv gen/pathtag_reduce.spv gen/pathtag_root.spv gen/tile_alloc.spv gen/transform_leaf.spv gen/transform_reduce.spv gen/transform_root.spv +build dxil: phony gen/backdrop.hlsl gen/backdrop_lg.hlsl gen/bbox_clear.hlsl gen/binning.hlsl gen/coarse.hlsl gen/draw_leaf.hlsl gen/draw_reduce.hlsl gen/draw_root.hlsl gen/kernel4.hlsl gen/kernel4_gray.hlsl gen/path_coarse.hlsl gen/pathseg.hlsl gen/pathtag_reduce.hlsl gen/pathtag_root.hlsl gen/tile_alloc.hlsl gen/transform_leaf.hlsl gen/transform_reduce.hlsl gen/transform_root.hlsl +build msl: phony gen/backdrop_lg.msl gen/backdrop.msl gen/bbox_clear.msl gen/binning.msl gen/coarse.msl gen/draw_leaf.msl gen/draw_reduce.msl gen/draw_root.msl gen/kernel4.msl gen/kernel4_gray.msl gen/path_coarse.msl gen/pathseg.msl gen/pathtag_reduce.msl gen/pathtag_root.msl gen/tile_alloc.msl gen/transform_leaf.msl gen/transform_reduce.msl gen/transform_root.msl diff --git a/piet-gpu/shader/gen/backdrop.dxil b/piet-gpu/shader/gen/backdrop.dxil index 10e1bd0ece9195f54e1875111def69587d416c35..4ebcb1cc55f84fabfcb69250b09215f2e5f48a4a 100644 GIT binary patch delta 1144 zcmY+EeM}o=9LJyDwb!TR3Rj@)pg7wB4XMBmB#e=nU0YzV(WUIoGPZayh(kuvfkX^R zukGkMhJ@uT;@d0)mueuPAPlBUT4>0|HUkscB-qi0DJK4bi+@aGjCaA9`26!c&o`g% zljr+;UhZTDGgC{gMw9#1v74_Gk20)>R(`VWYmbTm0CXUglkPw2d#yZ9<=s5-%=P0+ zmVLU^T3OX42Y>+*@EHPtFb6zN@QwyvH=2SGEe^oILxx^K=}wHD<2e92NdU~;ENZgrAU$ayarwD6H5S(BU`-k01jXt^V~wYdfsARX ziYR)+xm}@7iPgY*Mgx%|@iI1d4KPj%p1C&na9s!23k~493;`|Vc->=~SoOAK`{jd$ z@lCe&uE^T@!;Q$+;`$c7ur#+xnm?Zk1-uUYHa<4WT4Z*Kqy>H>Lw2>0w-WFo{0zy4 z+y*=h@Gr*$KTOSzT=UK@n`KUY!#jB$jThURT5ZRXVOi?+t7plN&wjZ6e$a1n|6Fi6 zrTmoc(eLG_7K*ay#s28*9q)tN-`{=D`@k$4DdD}1w)TsimR5d8ZO0LX5Wku)!^?2e zElEMRO+}e~aVQz}c!Lo9G1NyxfLUBSy%hx+m<%`>5D=C5L}{Lo$AGXJl5Vjmn|#{o_VUJJfy;{5R` zc3;RSZK6IRz`WuJjZNZ+GIfSyIi=maJVL^OflIJtpR@K2^t3wrud zGM@%{gxGag^*4hf7SasalD|MXP5^O;>5)`ZE+)A=3GwwETr!r5?m@|zi)&7}fJRkk zxU~cdosraX3PPRu93k%)&k$fJjmo%d#E2neM30xYxL~38FikUFcQm+%;|o890&1zV*87HRjQ6rM`-U$8xmd! z2*+zy-A}ZV1e(HM#aeeU3^VtFQU`e<^_Z4$<)S&_`tio`ZW^D)za~7P0c|>x|G3~2 mlLo7GcL*?*Ai&QAc>bUOlUD>dTgk%)9g;7+^qt0k8vg)Ncy-|b delta 1082 zcmZ9KZA@Eb6vv-?d%3+Wx8>r-J_3)oaBa$6C%v4q=RhP-N7Muy0T3$>vOFVW!4 z7C+E;kaSz!-N+&{=`w@Ffhi%IP7>2noH$6fF*4cGU`1>?Gm|+@wisi))oG&V%X7~E z{Qe)#KTo`DxlC8zY3IQI3KQqXIh`QgBi#6D<@1j|cy#MB(JQ%F)l%Qt)EbZjz=J$+ z9tR*d0}+R!V?fmHTzu0&18{c!2kB!B-$@JK%7O;vmkw>v;USh@0@>pLR>8Z^gVTM$ zv?{ueApl+xu1L5MBgM|!5G{8OtBLp>MlZA2md&`DNZ*OTe2(TgP=xpSVjb#0-`yC5 z9OTsdRWU=P23{wCI?$`Xsh!Bw*wWK79JE1?I~h?VN#AG8AlLpXxb$Y@@P+Sxxt*CH zA2l4xG)S!>t??^&`K;o^Ed6@c<#vta1)5DJH}{|o?mnDMdu?a{?X^&TMG}Q==wOd? zzJIu>v|{+eu2ZB!}Otn0)7=P*gEFxuf-n=)IQ8Za<7}uBEb>DWWKs{xLNFMZOasX|{MeWnmE6 z^&=Gkyype<*9&Syq?D8a9}ngd^-=8UKw`{>d-RAMWL1ZwWG~ap13g8CirN1Ew2quQ zR?L=?lxSuW7=njT*hsLdQ(>eBlrK>&b$Vi$PSoOWa6(k6tv#2pOWn--5F`~XEICi( zs=`yG!;5RiyeIzltV;*=c|$owGwtn4lX^5nt+MnuCH$<^cAr;T_r&}+17LbU@nHaz zAC=7N3-~2~v5=nX*pM*PW4_t|#>XVc!U9P6zt;TD)4n>?MtS!B1{!Dxhy*_#bTEFl zutAMSm324lc5DUY%{m2V!GI*8=@Qlo7$z3%I_qjItnKWHj=q)k_ee@0$xpBr*G`^E z!C!H-YBe`JiKBVnHZE9UNv*`Z#5pkYOx`x|X+k5>Q4h|9iXuEcRU|K+W{Yp*M?gZ( zHDx&#LrKNU40%ftR2@t!`!V4p)D*|0CT|%ZG#Fb;q9FVoS&97jLW@*6BQx~~aj3!n zz=UsLyUwbPEvB_jl>=NgW7Q6fI{ESLpwzbBBiK|r_0g?zkpJZTrstNn%6xOeph~wt zH0O~oZd!W(sof Z!yKHf%faZ~9BfjFu+8YRC?|t+6 zzP$HI-crU~hM~CHW`A&IsN7!XBWe03)A!56Z)5;~;t4}Q^oG0I)y_h7pkx_dvvPv2k3?ZT9e*83W+r)C1KYGUU>(z>jK=8EdS7%2KLZ z!L32?D>Cwuoa#cksK^1(MF8Lo%*gFM7D!Fe1g3ebBNd%9Szt{GD}ch(-L{(kIu^3_ zVbyMc|5ag4f0sceN`sgY+|iR(J70IMaq zh?mCZ0Cpubac_EN^z7iwic>9E8{Wz3Y&_Y~)aE*Ze4;j7e)kyh;j#B)=fgp}_hDXN zilfT%!|#r&`GQPp(Z4aXFnIgM_g}v^c-yHSEfTwpu2Uzwm^Sf79Y+wY^!y4@!wYcA zt4u)xo7$3|#gQbr1{bQ;KHz`uXV@#+K0y34a|c8;9aRH?1=DoND80uQ>8BCSL{KhP z-yA|4$a)r-AUba>ZTa7lkAyTYrj26cP5Er-F2INsdHh zIDuKVIb^qR<@l$8HeHKcmhxs`O-CYOPXNb_yPqQBi?SU%ZUzoM76LEhdwbm33wDOj z9#j4Vgk;no?Bfv9o9bt=&r>z&LC$y==>!pt`|x8sB_n3Fg9bXbr2fcq8kfE#=$!zMY&>XN{z>9@+Cpw{sHCv)4yRxuCHH;&`Q@ zGBFf=lG31OzJ7EsaVx%S$3s)jLOes5lswcRO~XiGhGkC> zq@C_Zt=yr?i$U)sr&)?yng96xtMN?Xs>Ev&h}`3n%PafaZ5DV9t|K|?fv7&Gc8LmC#37&mLf{D`- QoTV3G+JfXtAN=3(Hzz=H&j0`b delta 1089 zcmZ9KZ%i9?7{`CTUav>FmMb0bdRbFx&Ncyx}M})_D_DvdGUTY*zvBjuA-_>1pp5e zU<3g`nn4ODQ;znO?%<-U6am1;k%!7BGGsR){*>mYG`C&ZewPQGc?l#g0J4-^ejZ$G z2FAsd>pTSDW$~t*>oVX>goT8vu~UaeAJFDZ-fBto8 zYY_Xb{MD^;rL8C1@SWQV$ONoTBJ=8T<^8F(hGlWlc`wfAB9*pg$;wRtA)isBb&#FP=bL zup0Lq_!E>9BtT>Q2Z|cn$L}iFA)$eTKRBGS1za)V6Pq(yo-IE{WiP3yj;TT`AB%B2?m9OFv z$H-t@eU!$2RQt8ZlA6v^nMuo!eU<4PBm`QsJLco^@=_GQ$s2BSPle z8zwwmiXxRnOUdj;5hAv0^Jwh4M>W4;I{fcf>C(nt{8tN-%s+f{oe~%o+r%bcO%a-{#h2JOBUy diff --git a/piet-gpu/shader/gen/bbox_clear.dxil b/piet-gpu/shader/gen/bbox_clear.dxil index ec661f81be0e0643f9b6ed85e6bb99ef2a302e78..9ce0addb78ff37cc0ac08c5bf861f956dbca95c2 100644 GIT binary patch delta 504 zcmaDLaYI7VCBn)1oyHQwLu*{OJbYdyDR|#on2~{jA!4IsJe%d$vJVezG}NbL?O)@F&1YjRRg8~p431N)((eEmWG_hfVqqdESVV?DkT^g>?TJtJJ+jm9Ny?C z!NZkYEX{UAL5*Xwb3&7Wg0zrRWJh8GM}qSOAAwbAO%rsa#U4d+Bqbb#Ecy!CUG8GkR!1n@rHxIwW+xpE4XHC(aOmw%hk(FNzE$>Zd$-4 zIj=i*=AD>Zvu{sn$Z%?Vo+N%OE!;xQT-D&!goiuNENq=P^`zz`Xf7%S6V>E!_6?C4Cc8uXH#vH7H1E z+*8hoHcd)kP~c!=kubU4!3YvHkykOfoZ-a4W6r}UdB%vv$snl#q@q{C=V)@T8jFME zged|JtP{fo4t6*)12x#BZ!lzRFO+#c1ul|tz|?ViY3%naaFNUlmW}0X^PbB&y1E!7 ZT>u%_FID0HVd25=wHI|78-TF^0ss#tsty1E delta 444 zcmca1@jyb-CBn&>0Szz$`3V~(evAkcXB>(Pmza#A$#*iHh!kbD$EkHd`APsS_2w5rnoVj5aYNi$uP?p zY+a=U1B3nKj~u?C!Yzz94HP&H9cRcf3AZTToFKsM%;W6LAkCEC6ksXb(sFZyfPk}r zv#_h+2E_?x0_Ry6gjpCBE{aWiX6CqI7U!V_J_2p2hbQnJW^3AEkn0>6$*?taawvt6P*>B;q)Fh%ij@kH&})vG5bzM^kI=9LadrUnHGjr+$m{4ruNCu0DciYiNh;}TI9gQN=}z5G%+J_izIj$5k2 zMEs=+d@rQNUbi)ciS$dA_&r$I_*||sKv1wp!USmG!Od*#iRSYkm?*u=HGO;NNls1;EUP-OD5PMn)!(rckm zEGXOQ#>BZ(oOTmURfaFo+&KAT#hwkyts}0#Ub>TizPD@t=^lI~ z9R9$u@F>D9;p7qL6R3ehq`ZU2$EHF_`)?J(pRQG;G!|iNi(@*Ej?8R5^>yoD8+ES)@j2+ zD8wh?rfb4TW$ zO6!{eEo&xjSOy4WuAfp1Mapy;I1*8p~N}_I|9_&xThU_mLoD3^J5kT-kWD!p%lvynG&;PxK6h`+bn| zxgXp%V?MXPQ2Uam=FqT(VhaaARH~4Zga)uYT8>yeIw1~QMY)&|i!Uex-((@ypef=j zl87c9GYC_574T3sBN}HJ5@&Kj-X!iGnQXrl6EZJvuxX1Yd}0m%Kr1l*l~1Q*4=LDk z9UuD*0TY_whKp(Wn-kh8oiK$Sl`yT(Q9{aTstzA#iAtH|6|j{m!r3?rR6vlxj{1e@@KsDB6IGyw`CV_ZN(2RF%o$DpLJB;sCwqEZ0|>2v{4kmosNpgV`M4l(CwhV zR3eDDitUMC>x=+t4VqJ_g%$@Y6An$Sp$Bmu8s z<p|x{urMP zn$BHQ>7hLC4^`H3U$D@U1uBAqM5}r`TKPL>1Eb6>ZOb>-n9u+i`akXSwen6_9(x6j zN)3gTNTnSbzGT7tL_O~>dvojyHXXrVldCP9Bh@xbFG>b`{D<0{4$y@^`Usw zaH0t$XDW`<8BCCuPJqD9%?lWucYGz?871*4g_MFyt&%!m9BaRs=@Bx>yEesLi|2Lw ztpg9z7dM6wDxiSgWBmq16Bdu*qT{gRYV~1Pop41|8dT*WS{CSU*m6NEW8pHiw0%^c zfco4c^M~SjKxxOEljfqoL)d9zvQ{%IglUvxZU-b@@aca)j`rJfGcSZwgK5^~%qSmC zd-?3c`^0GMQB)p4rart(l6uH_zxf*Jt_bI delta 1688 zcmZ9NeM}Q)9LJyQ9pzfCa?n-}D|iJ##4@kQn>x0ZmrikL$8c6bQ(i@^*g2iANv}tN zmKVo%sHjt~lbPz6!O7GuEa};fF~x}qA?VNm8g;L6ZW2v4vpXd-+5L5SzMtRoe4hI~ zPtKR@OIGDtvU9-yp0g@9ieI=`xaDt^_e@6WW7E>@+T-WC(AARAKb_0IgV}woJnZZE zSxsJ@+zVt)^bZlVM7tTG`=db02H@_1$Wkc)y9fZ@VSfrMa3~S$O^TH1jbvS`AAz{^ zIl)VKU=a5=_z#gCP=;}^M-c|;5q;`gDo7*Q2>@^YMl zcVrkdVOwC#X(VjKVm(@?2oNnsq7C1(r~F5%-ATCk1|AzAu>{orrI8%uw9A>-iWz4UnUaNGD-BlTx*?Ek(%*0Q)_=PU13msV76E!a{~X?vUL z#G;Nhm)saFK00c-G1_iDozrl?@E&HGdoc9zfqSNmjQEjruPR&;#RUieC9+nB3!h%i zUJW-npp9vULRkwiFEjy$bngIhQW;>Z-Q&*mK`6S5cN--%N!WIEE4EuhZB&^Rkf_v? z`0D#FUw2Stv^aV@rjw^bYpBCGNP7V3%FOjyXoJE{hfBGpC3GIvH5kfwLlIASFr=4u zyLt69k}#!{5;H;P_k-zre|91gkmizd*t|T-A1hr$)LTbrbZIF#t%of^L)fP{roo-_ zFhkY`&`j9IRZJ-yYp92OC_9QLIhg1n^OqPE}0H3yt$FA%xxl za0CvYRiafetBC@Xj$HwnFdR4#-mhu2SnCYaO-czjZ3!I#Bfv;K9B@v*P5SDuyFg;4 z${GZa0mpi`T?|=-+DlWlV8zDCwyJB@lkTe4e)wq%K>(C-mWQ9lOF&!HUh;SZ3=6Z^ zA9>YG7)ZGres|%ECQN(1H`@*wPP&=BCJY0Ju>8|d7L81D+#FX8^Ui|60)tWQ4sNQGdRZKkEj!;rY*5C#7BfaQ{0y?enLx`uxUa8*y`D3Wu}<*WigV9 z;203x$qrv*X#5n@EqG~hcR7Wl8;%dFo-S+X>?3G9@ zG>82ya?z?TSH5`>C=dEYIHXkA$oh zPYH#AQ?MW^Y@8=OVMo!VMDAxTyGI#?J`v&k*){CPN&*f0LQI}%*GElZFYG!2C_0Whl3%vv2*cc~qHQJmVvq{&E#O z{I)t96pbm({Cc)jrB?bvR`yCaxf`m3eLCYpv)3bsS&u5&k$-3I-Ak!rABrY)XIvnO zQhW~5tU*pZ0e(6oJD`&ccU$VxEOE*CxPs7EiyfdID6VHVb7^hE)vd$k<`?a^Tn?n> z*NwnLKml!`c^#|@iIbv&?wrLALG6BAjt z?_^onA@u?WQI{NuY~c^^vOen-Jfyt4l4JBEDJ48%i|Vmr=dpE^v{*`^140@p4(7)S zC3VXXfwXu;Ko=pDYZJt({#*fWID!gO(Ml2C{TyB?!bGzOS3HN4Mc9`ozzGc(L>iyz YjIzxuiKAeN;ygAcLf$M!|KCsOUqhujTmS$7 diff --git a/piet-gpu/shader/gen/coarse.dxil b/piet-gpu/shader/gen/coarse.dxil index a3e34c66bc3f07a896b41c4b1bb84eb997911c30..16d47ceb1c63abdaee8fa52a8b5a604855d036d4 100644 GIT binary patch delta 7027 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 diff --git a/piet-gpu/shader/gen/draw_leaf.dxil b/piet-gpu/shader/gen/draw_leaf.dxil index b880f593366b34dfb2d99952366c977ff6c6c7d6..17bfd04821a365b1d94408450ff3b37ff214016d 100644 GIT binary patch delta 2058 zcmYLJZBSEJ8b0^tCL|CfALJV}5KI6Q_oB#$OCbq_;ufsB5&|Z8i9$i4gNT%^qud0D zfH($^!EB^8h1xQTPCBkT*tOjRsPa)~K-aFd+6ilQt?TSM?hbWV?d}Z{_x?KPyw82l zd7tNb-{897y4V7fK7XrW^#j+1ccYqrT;43uNWcFqwwB4+c=g_&)Q+(p+DrQU_mTPA zFZ42T6kCJ;QUd*vUa7dptDg39BAw)yXhI!Ej!MAO8j$Qp0DM1cYnzNQAy+a741^uz z@G)@P$(h#U`T2m4$!|N^)A}50E#noIcU9FgiSeLz4h#H2$=q_WD&dn(xx+D-OyqBB zkS9d}C9_jIs8L^Qus_+%$Fv?fxZ$wL9MRZE4R;;r3^{Xl>`Kj_9~>(*J}Asw$voqn zzjVtrRdnt27ne#{UCN!Ut6Qq-TdJFWjSel7d^i(VAuj)|`G%}q^4)QelJEFyVp+yd zMpdRUBXgzi5%u%&OLJ5AbzhvmG;v57^_g|U-n+xO zLL(lr3%5FfoXNNmU(bra9FX>klK|5m=!h85M>P2v3I+q%3F3vVG~)HL`v1#)5o@^w zz=v=?!T@U{*AZ*1WGGwzir)pemjktWuoY*lFQ#Gk^xpJ9kZt97b@*HO*E}{&1M-+Z zbDq(HF=QT~X~;aLoV&D(isNhoo%Cfz$sO=fOnlq$gfm{~v$0bNVgevq4qIJ1*`9K% zeXaux2cw(a3?}~9klL0kNkF63P)CorgZ1j&f?BXn6<)a_dydr^o zHnzM=Kd)~bkG6800rmJGwvM46A+jPYOd~!pz8cPP%(n9PE-n4-PlEUaf$$gB&%miQ^=KiR z1F(SK3a{~`Sw=Hy$iu8@9u5#CSKEsGpUO{>TpC6d?|VF`E=bHeObI!vO^Mow=9c!+ zd&P3ffwqfq1z*iO;xJz>(29mw2>!}hMrh$L7oKxe-YM{hjyGYI{w^eBXw!Mv$L9-; z^q4SE-6k@#NL$RQFNMZ{#tZ5*J^vf#4ll%!OiLwr&DqvzgN}U6Llw<4cCR8XJE7lSB(vP zJvA^}q^S*`cf%J#X+~k{KAyt%0kg%bYH3m&Lbe_C_`7s8N^#PAu$xr1+Ev+2 zLZ9G+@N*onSR@mkIYz}FPf<$6S{_oNMPuEB2SjoN!Vg6W2oC)s8PW*vh@_b}T&3BN zEX9mf0%INIM-fpef+f9r%PLlupk-Y1SEc6rCFkQw4ZU=!QE;dcizL47HbDlK0_DFt)yqTExnVD+c4OB(EzpuD)?oITuBmG4HxxV&4{G-hQOqw$u>U>1978%`QT} z9SuVdTUt(Uv{#0pTVg70k*$U|*;1;(z=S!+uGH7j3n%tUT)^^>ZkeT9wp8~AW$y-$n348!#y_GW zbAnWo#ZI0UHFI5BOCcZiUQt-WQ}|%{i7l+#)zqw-&bc0j{zvql&IKw%(Cb5Cs8rq8 zeWH~0AcT!9_<^446vc;I;jUx_!iFy;B8j^CUtbyR2kI88w=Z;-?edA1=r4vEsR*fu Y25E<=&ut4d=F8U*_zYldCc)D8KPdvc82|tP delta 2057 zcmZ8idr(tX9=`YHCL|=3Jjjz*AV_${-XMm@A||{FimW;Y5fi*bVF8gvKuX(DZ^A2B z7y_q(6zCd3Tc)NOv^$H|*-3a0v63#Sy^NC{bmKRtpCsCn-ujglS?> z?y0h>T3+jQGSMGU*sfwd#%iSI?w6{dk7@WZzDo6#Y9Q%GV)E@+&HgslgS|7?3Tn6i z{r;&v>ZFLNhH>WcoAF?XD>^f~rhB?DIXky9`2FnM(x+&?I5Ay#>&C6$rQI68aVyrX z?O;8)GT&XeJ@C2Wes^u{o;CQUjdc+@|436YYYe&UHfs<O0hFJE~+o*4uW6a=rVCZ@0v?WyFG_vAwd>Vq)Y?ebi+Y-Cf@~{;e^8_^7X!Nch zq%BWU@7nWP4E-M4wiH?kG=$ZSxEP3>J}f0?!&swlwr9T`r3zAtuiF#qoOqd7B}ENT zdw>}iLB~(Pw5b4N4B<|oWTNpRSD9df&q6$EU}lHKPf+_5uSpS2OFT0t{@6 zJ7H=B-AT)I;OY)Ny$G{Y-UbiZ(znfNw#;}|Fx!GbQ?zLwi%_mWEz9kMz=ii4^GzHI z1=3*ZC754YHnAKq2c(>!e8-ttY8t(%EGYuIFiRCF)esw{d=uKd{1$Rdw2w|4L4IXN z)RMFYzTF`s=(o6Y5xIA(El(rFMy=qyvpJAe@)L z?QPfH$yN(T88G(RS^YrI3logDmwuP+@-FX3OI>EzYv|(ZpqIxJ^w$u%zeGp8+g(}n zCDVf2yhy=J@aLxm@X4-dRDEC+meJ^5Yj1#m@k&{OpVU40vbRPT|B%xqzBVh8y!P(gvI+-o7EaU0%jLIib_}(fX zt_$qu3(q^UpUYIp&z2Wc884owDj2`7?)Z<7z{1NJrLu`0lE9c|C;8i^U-ss#WvP%2 zuU`iJe)d62PVBChJ==tSu;7C-b6-)C5w@6w&iQTlpcPTsO)^n0nKdQn5%?4T9Bc!J z1d+)b`5Cgo3KwY7{3>h=gLS&d66W3|B5#i#z$Lv9v>PqIywu z$!t#1Qk30F(mD36jm)_z(%*E|tNTnxz08}sj~KTa;*ZqBD^UxZ&_@$K=v95wl|oag z7kV(T)ac)w^A1ZwHW<_b9*e@sQZ~pVj0)>vt6eu(A3IR5v`Spm+}D_^Kp_^MzbS0s zSUtMFhSY%ujWzB~^s9jeu@%xkr|K7|`h(^Dp5R(fw+?POLi-2PKixwn+3e&+VI#+? z*5~pN`(2sdcMG38GH{Ub=W_C{noD2wK@su08Y@)lg)WZzpb|%K=YW>+)Qk1cUZKWW zgrUAxcq|Tw6TpU8C@v`f_e_!LY}I=CvGumY)lT6S{WU-#5yD*{N75?fd~9^rWl0lp N>>G%7fbc#0{{{N9tmXg! diff --git a/piet-gpu/shader/gen/draw_reduce.dxil b/piet-gpu/shader/gen/draw_reduce.dxil index c6c962474bc385ae7d5db75c0397b5bab5dcc8d2..9b1b0fd6893fc7bdecd4093fd10ad0e5e93d2257 100644 GIT binary patch delta 781 zcmX|M5FRDJAb1{ElGZ+~ZZ^^7u4P`ADrp=4fbTyKlUI?@W{j^V z6bz0t0DSu`%+Y>@qMD4v7@MU^D;FfNrr>fcsGYEL4hI;~eNu2|3ZCd@ty8Tn;1n0fdTx{FSl;2rdXLv%dC=qCzXR=~_1Dhs ziN$wcjk{y-(yit=XOA&yJa`#l@M4a9wg5ikxUas@c-iJi6*gO<_Y2SQT-B z;iV@vs|W%lLAYZ3cAjBCC7n7%sF`#B)(WONIDQ&IMV4`TdEIE?Wi9BcH#spJwfeC2 zf-Nn&ln&#M_~Zm7=E7|lvCCBCzmn|FKjfXD&BJU};CVCjC#LEREEfutbYZy<8afhPnHz{&@Nr|kK%(g?AFHTC+;}fbO6e*; zo8t-*NzNM>Ll@%>K!j=4k^!z+TJFxJdwt}~LBzyh+LfeB^+i_DX3>T+nHHCXhH-`GEpCO^ zQXLC5A$KT$kbFeoW?CLZ=5S1iu9k%nQwZa_yh58Wf@oX_y;pC@wrnW0v>5XnmCRVb p?o&vEmU6%4#lI7p981gc1%F&OD{G`uZa%Si9v1CYr{jOW@DH5N{G|W@ delta 789 zcmaDN_eM_ACBn&>0Szz$`8gXU^Vuz1cYE&tG_%1jEL6N_$GKe&E)kwSXV@7S5*Sz+ zJ_D73_zXZ=0H|XNP~6G+z&%AC28LIg53;{!WHB(XmYBSSvqh2bXaGxUAX{rd1IrTb zmRlSQcO@B488e8a0rgc%FfceyUd!w}c@7s>y)esyn+6J;hK@V5n1opl%v4}F-_{Z# zu}D&e>4t!faLbul3Je!m7A`c?aXBJz>4DE>mK=^1yeuJ%2Ur#gcx-81y3#&Z#lyujow=2@CudhFYbVbZQb|4WA?C@cXZKz`IdT4H&E!H}yZVlU$`z5ONfQ_pIM~ifI2<}2sm#X4(3Fs{ zz>$d!&J;p0mDog8jFK8a>L*JExEA!Pu{f|!<-5$#D8PI70#D=v*3B%3bq*R_VA{d- zfU7~9VS~VqCLr$wlLB{x4#Osa15F0r4m=?Y*ByD7Me7fg2po1`4UpYo5Fv1K0TZhm zj{pP9!GtE}_ne0kOcWWkew55$rtZO1rmym-AHy75Q>{mf9*YL(G^fS=3$1G9ZaGnZGQ cJ4C#S)w-bh0e_$Uk7oOZ=13-XP?`q;0G?L=x&QzG diff --git a/piet-gpu/shader/gen/draw_root.dxil b/piet-gpu/shader/gen/draw_root.dxil index d0a326fddecd7759773f6d6aaa0833a4b3993080..a84fd4aa668225d7ed426d81a25bc91b30599fa8 100644 GIT binary patch delta 732 zcmaDO_d-t6CBn%$N@nBKG)4CQUz1y!7w` zn^#*+Tp~PuSU4CM5*Sz+7?~ItKzs(Easi-@H|z`yPRktR4;(EDg6f7#=b$v}SflWCLoelwe@+ocxp1w_cjXk<8V@DD{D{Au2R-co-L%1dg4ROlT**`y?S!&)U#zQ{<20k(~ZoncG|4i zZeqS`r{+OchRt5ApBN{L@G45nco{Bu;$^;|hB>Ptgp)y;jgz4%;X#gTLF~oJ0lZ?0 z=S4T(?O^s*P>?)mGE0ELw7@#4fkA@@-xOMuS745T%SpTm>K4zOo;l9M31~%*3RsVc;FW6T-lh z$jdC+;23eZqmdElK81A~*sBb392^cZ@JI{v8!$Xu!Nk)h-DJnm9Lbi<;l{(mz;ckG zvDNOu>bWJJ&jxqlV9=4rC2OzVSe+2Ss>&CmwD0!kk=;buW{03+2nAdN#{h9 zX2=9?Yl!$|{S8f;ESnw99MU;+NOQ&`ZUc!tjwD8&G|4F{2O5A0hk+T0quJDcY~%6! J07|wn007!1_iF$E delta 732 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 delta 5994 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 diff --git a/piet-gpu/shader/gen/kernel4_gray.dxil b/piet-gpu/shader/gen/kernel4_gray.dxil index 7bd557b984270e95bd0f3e3266d850a75a725d7b..6ec6d57058b870d1a8d3a1264b1ffd429577a045 100644 GIT binary patch delta 5733 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 BT95z$ diff --git a/piet-gpu/shader/gen/path_coarse.dxil b/piet-gpu/shader/gen/path_coarse.dxil index b6c9398fd96324a92f6916a55a37f0d0c4376553..9fd593ca43dc26f919b022903612dc81fad0890b 100644 GIT binary patch delta 2185 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 D17*T* diff --git a/piet-gpu/shader/gen/pathseg.dxil b/piet-gpu/shader/gen/pathseg.dxil index 657b340c047a9a12b261d41c7eb9f942a21768d9..3c8131532b027bf002a5b5c7a02d729315e7be6a 100644 GIT binary patch delta 5206 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 diff --git a/piet-gpu/shader/gen/pathtag_reduce.dxil b/piet-gpu/shader/gen/pathtag_reduce.dxil index 78d2cf95cd36038a3f59c07e09d9af483621dd23..245c4922dfd27d0d2d5f30b89554bd048b453099 100644 GIT binary patch delta 1172 zcmYL}VMrTi7{}ksUCuLJ;w5MFb?UrmqFJ^(+@?;a4n4CL{#>{vC-KtMaDktP1Nn+j_3Ek z=Q)1Q9h_pnZLjo&I*%(0NC$UHc_wA9oz2ib6w9CD|)sf z&HYhdDA4<;7yuFI!9^Vac?PJRK@(Y&cOKW)Z8QL9=Ppx!VRS2htZMqE@$rx3=`-nZ z!!;W{a)KBMQhKNNp;x^ER&HWSJMImWXdHYD(R}()Nnf~%T;dw2iq}LL_^K?OgNd+6 zq1s>dxiCnbL3M1Uot_TH>wQX`r&J@+k7-24>AxSpv(U%1jLIO$ z63QxnelaU??km3r--6-?X^*}U6Vq?&ZS0#h?)ER-p0wA+kWtN(=;G*+HS0sa+&d(!#s#E1YTdZ&Z%9c zS=kdTf$-X5QAny*_3v`AI^6>$D(Ejp%PC$JO)EN#w9ZR61`PaAG%tI#X*&mr2>&Gm ztQ*oPt;nr%r3V71U|cbD90c$=*wlD=R_-qd43~tk zCRIQ4pTKNEK(Q7C6!}Js44$m=4vv8%53tbloEXPypKO*6z#XB+8%FT6tqg%wufzd%(RCF6gv2;o@XxO?4RbbyR=0R70mOa1` zpcjU8eYIno<=?)X{7$rr^R{S_dwPVK65~1hGa(e_izna!?5(R!SjqItCqpQHkyCWE zOWVIBUDc{icG*=~b~R5&9FTMYVJwCmc)~*==qkY29t05VebLnPc+p2le2If-l{$Jd zzlA2|VXHpB*UqO{_A`gbuQA&=eC%cfevLOB!pJ!~Zcai7C|SC|{<&eXW@Aa%f-q-i z>pr|{!UE7PSnT&q)>&fzMhjb?F$n?Aal+!rnH; delta 1220 zcmZvbe@q)?7{}jhukH1EEytD4tL4WPT88|XSH>uWWzcpooiGo#RA{#34iP&ehLOpb zy7c;!Zs89iH6mH`7+umJCYXsCCQEvQnGGa?xM+i!P8Tuaj~Qa(KgReLX-v%Sk2lZv z`##V6exCQ=EGfX5BT4QK+Sw)uEH9ljx>6D;@j=$t-;rhy?_4H;jX9Km$U%z zKn2by0LW?p(@9t{3w^gI{f(6Xz<=!m_7EW&*rvjXBE#nfP2b4)FrKg)ZgG2BIdzm1 z6-ixW0|WQWV0k|%=!5m=X#hOqHM)*~5oI=5M(c20uT>b)mW?q|=OH{EU_|+iF+%4# z2xAMXnPhr5P(&)n^q&Y;TWlg0yHde>xPGQo2gxMJF1 zes87FM|Zz_@(WA1`RfGpgeUf6>GSn}diOfL^-lZT7A#IItl#;;b>r&7`f7*v;I&Ux zuPesq45&T>8#AIuslWfaQ z>8uiGCF+t>;_&bZ?I-|cYAp!y_h*Cl%Rzd0SIx=xBw~JZSAC4sCxefRay*EL3{4NF zQ~!mtF4ao|Woj${7a?W2t&V3WNnj#4c^bM|b6tK1?cFhlUzQ7ROQC0v5ClNwbVgZ+ z%>ZSQg9Rk2oX)$;q{@i1OKH$T5~Iz0SfU(j`AQ{lv8-FxhkV(q z#}TtADBTTeJ|kkI$b=nJR{}g979@ovHqeg}0ZGB;F^1T`2iEcj^4P0WTh{Bi7l~Oy z=a_J}TEM(?`}f5WlX^ToB1C1|cCbrewHGR&-BUtTrX@vgNcDs&%X33_2yV-v4Oxa( zG0ZP5YLRFtcg`RJnl z!5YQ0D;%A>Qcl^huM=sy9d{|=Woxg^r+y+wBehhSgZh~Z9!>B1`>oU#ITmqKHW&2^ z7ivD1o2Y|%WFqn$W$&bZ<-$!l{{YM*Cn7ymxj_BKEj8!-dYDFDjto+J&rlE9XLts_ HC;MdyPA8+RKdGCGS z_xs&9FP3^cH8I~|vHme|xADuD-}`*#z9>-N-*O!R0MwmMJR)98JU{gYe)+@5BdTkY zX}-929Xt1?WL6$s!c>pN%4f!BZ`_*sYJ9d=v?W<@JfhE8J8bM5G~}EaUKz&0z(IK} zx^lcH9+RCg$qa#1*}F5Fass5x5!i?A;I~QvNFk)4m5c7%5Uju2!NeI{?P>1pw<)m3 zA3msIfTY!Yl1NgwoRA{6g25C*0vA)ChVO|u7A`v6l2^e4Mnb5PeC~LExW)qF=YRDf zD9>o}n{7l1N5GB2dE0q+61j|WuLgO_t4SBaK}5x3P){Jqg4RP_l6*zbj7#u8x)*#F z7!ZX`cnG*Caw~`riUmM+2~Y(tm{}VVL}CP#0c9vzMAtEWoT6$3ASQ}jVGm$>$t}*H z1v_GxCd&jUk*6>Iw1w>)Sg0HiAIAwtv4Jz}|FMu!;m7g}@nytL~!H`MbF~xl&vl=_Gfpe5{_R=YKB=STq z)O_59DC*t9HUB?|K)zP?eKwD=cE--?>qi~%mC`oVEWM3 z2Ln5oYO;lk$9!fC)>%|Pp?0w<@2HA)s^}~`vMuyrqG4K{rSgqx=?X2ax1)}S{)Ibg zy~;nDMOS9gtL>gG4}Bv-uU55>n&~PtZLoX)^Gzz+pz0j8)75r*jgu}HTE@s>%WQ`L mRso+!kSaWq&k~RQ`5Cz_R-ZT&y{6wC9;^nQC?-rVe*Xdj6YOFD delta 1497 zcmZ9Me@qis9Khe*wbvhB+f$%kSH)xe&I@04m5MQLQ%##gA0F5$0nE=mxV2CBU!eXZSNF~+xz32d_M1c z-+S--UfxW~Y>L6gS*+lH1A$zB$#7b+wxHqg_zh1~9&_FOxGQZ@la1T_YOfjq9>~E( z6aa|ml828UZud=Z>bI})s8syeup4y z-Uxc%0c0k5btQv7 zOFegEub_$adjJhO>3DhTr{SCd6N0C8UAy;f^M=%hbH{d^nJm9^_S=&}wWZ}j#p3H#Z=~g=GCu{Uuf)3j$2-1Qb?tb^ zr6Sdd?8<|g4X(yL`x|z;8n>anTEn?l&KTb-Pn_7^W&CdPB*6NQE~r6Yu$w}Ry2p&! zFF5QU?Zd`Gf_yA5gm3DQP9+&v0WUxG*2Zw%MEeqLj$24&bGt~eDiC>>qJh%O_Ta|2 z`uA0c10P7nl`xsS?D<1>x7q@Vzy3LZpaMPdVnjY~`I_a^x+xm? zVNLFk;42A~BupX(6`)0< ztfT}dc8|oNX1qvPvzTWl$v%{dWh+^xf(Nt`cjK#@Et!4!bDqo}hQ_SRX1o$0Su+yM zp;^*Q)*PC^I}m(6^f6IvO-4HLt3w-8Tk|`u{X?Yg!IY%e=EJ6T6Ji))Q!v<5ViXWY za>xXr<_R$)A~n{sBpx<4HOiVGxc@_sVUKdJqm82AWk4*t&&L31t+O9*&=7ExNrBXB=U z$v6)0o6u(~7#|KJN%)AgdZ$_14}uR%aGrr%XL> zFLA~>IIVG@M3o_!ykfPW;GBc14rK|oyCStYq2(;!>hw>im3bw7dPOhrxz!AeQrLM4 z7<$1;tf7z6UAW@eJU5$)^`0r#uTp{>v#jA9evBfRFCe@h_;=-fRE> diff --git a/piet-gpu/shader/gen/tile_alloc.dxil b/piet-gpu/shader/gen/tile_alloc.dxil index 1a97d8203297cd715fe74a88b950c7f381d1942e..d69db16005e41c4d04ccba4f03161ff131490b28 100644 GIT binary patch delta 1237 zcmYLJZA?>F7(Ttdy}hLuxNT{@m9JYIg;jwI17vKnen15gQv$;#C}}&3GeWIE2y7(1 z{h*Y{lA2o<+?=U`ncELjMFuRAwSyo!iG^(F7Gl6K^K|5mKb}gcc`tOci30$bxFi1neb?@}?cQED7H&|F#Pz;X zU%9dBc%={k6X1bG2!PlcuymYNP%N(1g`X=h03MEBMt^`fLZ((IXa3|OQaU68s-qyz zGbab)vjB7x0Gwd@g*A?3WQJ6t7QbkS1dCpeL1rNc=owxpfeXS))Hr5VT)7PT z<-y5?8i7l7rYpD8+SY#Vf~^j^A&_6Ybej0`^p)j6_?FK5vY=0jh&-zo^bZ)F^mnW7Vr&dE|~L|_@DTk9JZwFH8L*316Q>Cf8_ZTz+vw1 zDaV)v{B6e^@BMIZTP&Bz&1FNHmLsx(HX^?yMp{p8QQ&(AZR~4Wai6N}TkwFrU42@I zqN;CCwyxO+nP*mj8pnuFR(RG_J(duw?;Cy->fhu15!v^7=l`M8dK6SkWxUqp5KTE70uYh z`(cfEEyN6n6`UY*Tb%B|#Ua<~AzMZe5YnCLd2uCIO5+QHdJa66kaxX^pMO!h5?NA9 zC`&Y!^||rB=Ll?3_BvK_;N*ZA3d z$u>SzVUabPW&cvu)Iu2;hDIk=nd1^!)03Gp3*XLMPE8?@{3H9CsCL30Wul)$D)sX8Z?N Cy@mJy delta 1254 zcmZ8hZ%i9y7=Q12yVSv|ap%ONF6bNjfC7X(}nbHZ44M@jyL0oK0 zTib15x)l`!<26%sjwpsr`o(ai1W}ljh3KY)Fs%fWWt;O0Ci~!Zb}sSx^uE9M_j{k` z_dZYFU;$THgO-n9USJYH?&Hq=Tc)CuEKtuyCSV^ht?L<*M{C%X&q}#TUQ+(Rb?!aFO8&M zymX~Z|FzZ^ct7y2k|+wWtTdEd&J;S2hc_Jz*+o`pFsC$34l<;_TUelTG<)!s_QaCG z$;L1K7@8dH-sc-uhfkj0J@)2hziRi`n7r}z#e0XoU*C@2XE&~|Z*NT?s_9w$BiNP% zF*zX5@Er+Z1Js>WdQFA_03G9<=b&ORVD^2(=st6#`9fX>wo~LQR@jpaeK16zR{8@1=vTm)eA-mCC8G#RwO_)9VKde=_cYEMq46E3Q^KAB$?keE4E9(?6o20YL1PEa0 zO$(E>K=rv-T|l3A(|BP|&dr<)I*T;=t+LWYi@<8&R4^XUv?PZd@Q7JYi( ziq`@0W(%W4LP!Wkt3~%yH8da)!SCty>L6fWge@%0qO$~A1dam#FGPxs6IKS@y|KDv zP640ZydFp%>?Jk&m~1QKn3{;2Y8Ab_DL7Q`;p>W@)@Amp8$5B@mO2G)o8JTm0w?=# z2-`F2@Wj|#T=E>od~we0K+1ck9$lT;uco`|rPbyE87x6$czGmL>VHdCBoOtI{>!ow zn?HRZFiMBwK**lvt6}mRN3?igo?Kz7avG*H!OB8ju`R z#LtfT6GR`aZWzo*48mJLx#@hqjk6jlZ%AlZ))tx9;VG7wlIbR&ob{V2I zS`bEE&tU!+cP)>FAG>0D%uujXpY7jb+_cT x>RfonESa%NW(v;~{owCcq~$J{mwb{C*_C=)O*%`Q4akwH_TU*a{{cOYe*ktthPD6z diff --git a/piet-gpu/shader/gen/transform_leaf.dxil b/piet-gpu/shader/gen/transform_leaf.dxil index 915248b0d34164c12e496d8b1f9d41e43a5c5e9c..32ec39935ac137a362c71d89ded97dd979d0760c 100644 GIT binary patch delta 1610 zcmZ9MeM}Q)0LJgG*W;+AwzP%PqTErwEY-BimmA`h9yOqB%~rK2ZU-nb=STerb4ui{ zNFfzM<&d#0(}Fmil2HX07?^Q^cz*AGu!GmH|)DSCVO|aw&GGmZ|mdpDkCZnPyH(AQR0C!OV+LF{MlBtx66(i zA(*0`I9OWZjnsJk#%q4L#7BFgfbUCz+D}10g#au*Z*8Rx8O9RO4LOvX&Q!wiPd@pz zY?IXr=o&2rwMAtpuamlPTLD_ekB25R$6=-`0Uf(ggnwR*c|2`Nl-0fii<<`|pfyC> zV&lyn?y*HmnEV98Zh07;Ck$@g@v8^APG3Jac)9e)2aUFM4{Yi2=vm+0-r%vT>}hd0 z1f692#8_nDF|RfCj$fU&TsqY|eltHb6X3rtLb?meJ#RVnF%#wIYAq0rX~-Sa?ky(d zJyWp{z)<9rJH>wGgMA2@G*Oi zab?+n!<`!nItb*oVp>R2#k4cZGlDTegqY^EiI{*z)h%dE`DXAY+56lJ(zS10v zMmhBjK~vp-rKt=POhj-tPxN1&fo+|yjT5bRRZoXeGm_3gKPaWZh~{+KVjLcPiY)Vq z3!Jwpq|3zKnV(S^ZI^L`cmVuOE_DE9K!3K$4*J0v2`|#fKr$>+16rVyH?cOb!%A_6 zQNKHlmK0l7N#y{{(Rm>ogH@9eHYMcuxM+n41}r9j5RZI;ja82y29m6i)Gz=Na_N~5 zCadk}fua-~FkBUD%mg5ZMR}DA4>2mprO8L>;&RY7mw7g1cSbc8Eo2^l=T+uRYqSG5 z)$o}aXmBsR0tvoNuYiNg=+ygc!-5kPH&D^@paOY%K2ADSlBXHH(rETIEGofb^zvsK zX5b16XW6hB^VYDblJB&mSB|Ip8Z7T)sWJL{Kvslw=6tqnvIGQAOo!c_3Evgy$D=7o z)|`IWx@MSr>T&r(mpgB}WXsGU*LB}AY`!9~ayx_!g>ktwXRMOLFHZwqo%IWOQIua8 znu4EFf*llb0Al$N(fZ~;)UPh?tc z;>$aPbz9ALaE2L^jSymDUiRxMzP!cgA9mjCo-@bXvu5lP-kh6qU~1%zhvdy1*HBm? zfpkg53P&O-cHvth`PpOjeP|M3Q}4qs3P{vn5-@&0J`xF5c2HFPHv*?t;M0Ol*N+RB za}wX81v`pb>Te0S_B4J`z@GXac=W8Luo!lb$SP-;iaLqtxibZMYOdicyTwN?Hai2!5N;T+ZJ<23-8{4T|S&WkdRI?@5y`g4?mb|cfNxp1M zA0KW9>I@`l$l;OFFA^|s4VfpPU%yzuZ4S~a;H2IxptqRx+92nUJRw!Uv)f3+Djw|# z%UQdMNtno8UbE#xkvEvj-|Up;7fCU<2gufjLl&JEOBMEssOAFu&+6j;q(Q)^c~E>8A`PkDXG zy^YCV?@?SB@k#15Dg3*~j4bJiHE>^|eHW7Z29wi59zj)iJ;Zu`%}fCV3vVg^{R>!d BFXsRN delta 1694 zcmZ9NYfuwc7>0K@%Vr@PNJt2Q*s=lTl0+r}43`$%4FLsjRAG!2+X$$XN}vc9r_8Vk z*HRoKL5g-%uqqVM27(oo>14S`2C+g*Ep;r4qE%X3hWbNiI-Twc_{05mp6@;L&N<(E z&e;}Ki%P6F=n{c9zAmu}6`VX;V2<7LQhxM;+b?a;V!Rz`s0xB}jDHzylt-QKin>;G z^bF?F3b^MsgLpnd_4)xGdu?)FM!5){{Z);-YshgGB!b}+I6hHbX^@`rTLDd3F)_wzA_kCt~G|aXrD2*CVseFOIJ*qB~!2bIIsPb zwpK6yl@;4ds~+)<0MBmk2eB-4#Tt&=^9k;qTuwVKDINkqLV$&q*sJ1E)9xra zkcV=m8Uhf&oQ}7OXfJ4&bQ4NN6obi_0Dx)A!u_! zIZ!iE354$TH7QuI%r$aKYdsP} z<}>mgAVGr7cMb6GXM^DBNBkK;RABFyugHQto1!Z#HV)AX)rHOOv4-hF&nOM|hU|w{ zTdFXm+yo(md^&}qRTTnw=|EIgCEV9v=4{GzkCI;&ft|+nyi;g3zZREK3X^Uw1TxT0 z$yy;M6VO_q>Pcne7T9i?Sv?de)#4TtkoVO6o71S#ts=8ANxh$d?*WaGlCArMPJiSo z@r7}ULVLk>m+I{8Kx$1n_Gy=dwu8cAj(UTd$;*!SBx=$?r)Au8m~aDlx_87(m@4#H z8Y7-x6s?P*E}Rh;mu!DBy!nZKBB^kYpGhDN%uSdcqIWBlm-sTP59Rlxp+K@vv3!`t z_5ANyTvf_qd8aX#KhE-+GWjD`uI2y8V$#?05`VCBcME@##f&!jFpEz9Z3e3|vhV=g zbtbaU&1LoeoR@}lWI;2+M7GV(HG)T4j|kDSdg6XI46(r(r0qJM>K4>Y!lnG@xFg*QX{iSQw;WF?Hi2+JnMb%uCnT zvFdzK1dDZ9`i^ACFo*|hS?tKur>X^iiMo^Q9`({F<~=iK zgxk-A(4D9wLg~;c*U5J#UvSov9Hvu--)$Ft{I(wp?|BeHUqr7IDX&djl2pCG=Xi^4fq>%bkNNW~zzpOmoaTAej9h{SOe> BKSuxn diff --git a/piet-gpu/shader/gen/transform_reduce.dxil b/piet-gpu/shader/gen/transform_reduce.dxil index 5bd59c0abba2a99dff2fa37e30bd43212e60370e..63df381194f6336e5c7fa13118ab5248ff4ef02a 100644 GIT binary patch delta 1372 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