From 5a7c34e2672c50b41ad5011c7bf626f13c766ff3 Mon Sep 17 00:00:00 2001 From: TheNachoBIT <43283743+TheNachoBIT@users.noreply.github.com> Date: Mon, 26 Aug 2024 11:34:11 -0300 Subject: [PATCH 1/7] Add SDL2 & C-powered window handling compatibility. (#671) This pull request adds `create_surface_unsafe()`, that allows you to add unsafe surface targets. This allows Vello to be used in SDL2, and it should also work in other libraries like GLFW, but that's not tested yet. Here's a screenshot of Vello running in SDL2, i'll push an example of it soon :D. ![image](https://github.com/user-attachments/assets/f968ea22-bbcd-4408-91d4-2e8c15b2df20) --------- Co-authored-by: Daniel McNab <36049421+DJMcNab@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- Cargo.lock | 57 ++++++++++++ Cargo.toml | 1 + examples/simple_sdl2/Cargo.toml | 17 ++++ examples/simple_sdl2/src/main.rs | 153 +++++++++++++++++++++++++++++++ vello/src/util.rs | 18 +++- 6 files changed, 246 insertions(+), 2 deletions(-) create mode 100644 examples/simple_sdl2/Cargo.toml create mode 100644 examples/simple_sdl2/src/main.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dcfb4c496..82f8e5eed 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ env: RUST_MIN_VER_PKGS: "-p vello -p vello_encoding -p vello_shaders" # List of packages that can not target wasm. # `vello_tests` uses `nv-flip`, which doesn't support wasm. - NO_WASM_PKGS: "--exclude vello_tests" + NO_WASM_PKGS: "--exclude vello_tests --exclude simple_sdl2" diff --git a/Cargo.lock b/Cargo.lock index 5c7d5cf06..a93f968ee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -408,6 +408,15 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +[[package]] +name = "cmake" +version = "0.1.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" +dependencies = [ + "cc", +] + [[package]] name = "codespan-reporting" version = "0.11.1" @@ -2029,6 +2038,31 @@ dependencies = [ "tiny-skia", ] +[[package]] +name = "sdl2" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b498da7d14d1ad6c839729bd4ad6fc11d90a57583605f3b4df2cd709a9cd380" +dependencies = [ + "bitflags 1.3.2", + "lazy_static", + "libc", + "raw-window-handle", + "sdl2-sys", +] + +[[package]] +name = "sdl2-sys" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "951deab27af08ed9c6068b7b0d05a93c91f0a8eb16b6b816a5e73452a43521d3" +dependencies = [ + "cfg-if", + "cmake", + "libc", + "version-compare", +] + [[package]] name = "serde" version = "1.0.203" @@ -2085,6 +2119,15 @@ dependencies = [ "winit", ] +[[package]] +name = "simple_sdl2" +version = "0.0.0" +dependencies = [ + "pollster", + "sdl2", + "vello", +] + [[package]] name = "skrifa" version = "0.19.3" @@ -2462,6 +2505,12 @@ dependencies = [ "vello", ] +[[package]] +name = "version-compare" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29" + [[package]] name = "version_check" version = "0.9.4" @@ -3361,3 +3410,11 @@ checksum = "ec866b44a2a1fd6133d363f073ca1b179f438f99e7e5bfb1e33f7181facfe448" dependencies = [ "zune-core", ] + +[[patch.unused]] +name = "bevy" +version = "0.15.0-dev" + +[[patch.unused]] +name = "bevy_vello" +version = "0.5.1" diff --git a/Cargo.toml b/Cargo.toml index ff7b509f9..a881b64bc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ members = [ "examples/run_wasm", "examples/scenes", "examples/simple", + "examples/simple_sdl2", ] [workspace.package] diff --git a/examples/simple_sdl2/Cargo.toml b/examples/simple_sdl2/Cargo.toml new file mode 100644 index 000000000..6e4d4f077 --- /dev/null +++ b/examples/simple_sdl2/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "simple_sdl2" +edition.workspace = true +license.workspace = true +repository.workspace = true +publish = false + +[lints] +workspace = true + +# The dependencies here are independent from the workspace versions +[dependencies] +# When using this example outside of the original Vello workspace, +# remove the path property of the following Vello dependency requirement. +vello = { version = "0.2.0", path = "../../vello" } +pollster = "0.3.0" +sdl2 = { version = "0.37.0", features = ["raw-window-handle", "bundled"] } diff --git a/examples/simple_sdl2/src/main.rs b/examples/simple_sdl2/src/main.rs new file mode 100644 index 000000000..5adacf929 --- /dev/null +++ b/examples/simple_sdl2/src/main.rs @@ -0,0 +1,153 @@ +// Copyright 2024 the Vello Authors +// SPDX-License-Identifier: Apache-2.0 OR MIT + +//! Vello can also be used with non-Winit crates which provide a `RawWindowHandle`. +//! This example uses it with [`sdl2`]. +//! +//! Vello however is primarily designed for Xilem, which uses Winit, and so support for non-Winit crates +//! is on a tier-2 basis, i.e. it is checked in CI, but is not rarely manually validated. +extern crate sdl2; + +use sdl2::event::Event; +use sdl2::keyboard::Keycode; + +use std::num::NonZeroUsize; + +use vello::kurbo::{Affine, Circle, Ellipse, Line, RoundedRect, Stroke}; +use vello::peniko::Color; +use vello::util::{RenderContext, RenderSurface}; +use vello::{AaConfig, DebugLayers, Renderer, RendererOptions, Scene}; + +use vello::wgpu; + +pub fn main() { + let sdl_context = sdl2::init().unwrap(); + let video_subsystem = sdl_context.video().unwrap(); + + let width: u32 = 800; + let height: u32 = 600; + + let window = video_subsystem + .window("Vello SDL2 Demo", width, height) + .position_centered() + .metal_view() + .build() + .unwrap(); + + let mut context = RenderContext::new(); + + let surface_future = unsafe { + context.create_render_surface( + context + .instance + .create_surface_unsafe(wgpu::SurfaceTargetUnsafe::from_window(&window).unwrap()) + .unwrap(), + width, + height, + wgpu::PresentMode::AutoVsync, + ) + }; + + let surface = pollster::block_on(surface_future).expect("Error creating surface."); + + let mut renderers: Vec> = vec![]; + + renderers.resize_with(context.devices.len(), || None); + let _ = renderers[surface.dev_id].insert(create_vello_renderer(&context, &surface)); + + let mut scene = Scene::new(); + + let mut event_pump = sdl_context.event_pump().unwrap(); + + 'running: loop { + scene.reset(); + + add_shapes_to_scene(&mut scene); + + let device_handle = &context.devices[surface.dev_id]; + + let surface_texture = surface + .surface + .get_current_texture() + .expect("failed to get surface texture"); + + renderers[surface.dev_id] + .as_mut() + .unwrap() + .render_to_surface( + &device_handle.device, + &device_handle.queue, + &scene, + &surface_texture, + &vello::RenderParams { + base_color: Color::BLACK, // Background color + width, + height, + antialiasing_method: AaConfig::Msaa16, + debug: DebugLayers::none(), + }, + ) + .expect("failed to render to surface"); + + for event in event_pump.poll_iter() { + match event { + Event::Quit { .. } + | Event::KeyDown { + keycode: Some(Keycode::Escape), + .. + } => break 'running, + _ => {} + } + } + + surface_texture.present(); + } +} + +fn create_vello_renderer(render_cx: &RenderContext, surface: &RenderSurface) -> Renderer { + Renderer::new( + &render_cx.devices[surface.dev_id].device, + RendererOptions { + surface_format: Some(surface.format), + use_cpu: false, + antialiasing_support: vello::AaSupport::all(), + num_init_threads: NonZeroUsize::new(1), + }, + ) + .expect("Couldn't create renderer") +} + +fn add_shapes_to_scene(scene: &mut Scene) { + // Draw an outlined rectangle + let stroke = Stroke::new(6.0); + let rect = RoundedRect::new(10.0, 10.0, 240.0, 240.0, 20.0); + let rect_stroke_color = Color::rgb(0.9804, 0.702, 0.5294); + scene.stroke(&stroke, Affine::IDENTITY, rect_stroke_color, None, &rect); + + // Draw a filled circle + let circle = Circle::new((420.0, 200.0), 120.0); + let circle_fill_color = Color::rgb(0.9529, 0.5451, 0.6588); + scene.fill( + vello::peniko::Fill::NonZero, + Affine::IDENTITY, + circle_fill_color, + None, + &circle, + ); + + // Draw a filled ellipse + let ellipse = Ellipse::new((250.0, 420.0), (100.0, 160.0), -90.0); + let ellipse_fill_color = Color::rgb(0.7961, 0.651, 0.9686); + scene.fill( + vello::peniko::Fill::NonZero, + Affine::IDENTITY, + ellipse_fill_color, + None, + &ellipse, + ); + + // Draw a straight line + let line = Line::new((260.0, 20.0), (620.0, 100.0)); + let line_stroke_color = Color::rgb(0.5373, 0.7059, 0.9804); + scene.stroke(&stroke, Affine::IDENTITY, line_stroke_color, None, &line); +} diff --git a/vello/src/util.rs b/vello/src/util.rs index ce0b3e89a..466448f2d 100644 --- a/vello/src/util.rs +++ b/vello/src/util.rs @@ -46,7 +46,23 @@ impl RenderContext { height: u32, present_mode: wgpu::PresentMode, ) -> Result> { - let surface = self.instance.create_surface(window.into())?; + self.create_render_surface( + self.instance.create_surface(window.into())?, + width, + height, + present_mode, + ) + .await + } + + /// Creates a new render surface for the specified window and dimensions. + pub async fn create_render_surface<'w>( + &mut self, + surface: Surface<'w>, + width: u32, + height: u32, + present_mode: wgpu::PresentMode, + ) -> Result> { let dev_id = self .device(Some(&surface)) .await From aaa9f5f2d0f21f3d038501ea0cf32c989d97aab3 Mon Sep 17 00:00:00 2001 From: Markus Siglreithmaier Date: Tue, 27 Aug 2024 11:04:21 +0200 Subject: [PATCH 2/7] Add support for blurred rounded rectangle. (#665) Implements the blurred rounded rectangle approximation outlined in https://raphlinus.github.io/graphics/2020/04/21/blurred-rounded-rects.html. Closes https://github.com/linebender/vello/issues/640 The convolution is mostly taken verbatim from https://git.sr.ht/~raph/blurrr translated to wgsl. Added input bounds for the `erf` function due to artifacts at `std_dev < 0.1`. Possible optimizations would include moving parts of the precomputation to the CPU side, right now each tile recalculates the same values. Scene output: ![grafik](https://github.com/user-attachments/assets/22014ad8-5c37-4177-b30a-967cd7aa15d2) --------- Co-authored-by: Daniel McNab <36049421+DJMcNab@users.noreply.github.com> --- examples/scenes/src/test_scenes.rs | 52 ++++++++++++ vello/src/scene.rs | 30 +++++++ vello_encoding/src/draw.rs | 19 +++++ vello_encoding/src/encoding.rs | 26 +++++- vello_encoding/src/lib.rs | 4 +- vello_shaders/shader/coarse.wgsl | 14 ++++ vello_shaders/shader/draw_leaf.wgsl | 19 ++++- vello_shaders/shader/fine.wgsl | 84 +++++++++++++++++++ vello_shaders/shader/shared/drawtag.wgsl | 1 + vello_shaders/shader/shared/ptcl.wgsl | 19 +++++ vello_shaders/src/cpu.rs | 1 + vello_shaders/src/cpu/coarse.rs | 24 +++++- vello_shaders/src/cpu/draw_leaf.rs | 15 ++++ .../snapshots/blurred_rounded_rect.png | 3 + vello_tests/tests/compare_gpu_cpu.rs | 9 ++ vello_tests/tests/snapshot_test_scenes.rs | 8 ++ 16 files changed, 319 insertions(+), 9 deletions(-) create mode 100644 vello_tests/snapshots/blurred_rounded_rect.png diff --git a/examples/scenes/src/test_scenes.rs b/examples/scenes/src/test_scenes.rs index 5e895e0fa..92f513d72 100644 --- a/examples/scenes/src/test_scenes.rs +++ b/examples/scenes/src/test_scenes.rs @@ -78,6 +78,7 @@ export_scenes!( longpathdash_round(impls::longpathdash(Cap::Round), "longpathdash (round caps)", false), mmark(crate::mmark::MMark::new(80_000), "mmark", false), many_draw_objects(many_draw_objects), + blurred_rounded_rect(blurred_rounded_rect), ); /// Implementations for the test scenes. @@ -1694,4 +1695,55 @@ mod impls { splash_screen(scene, params); } } + + pub(super) fn blurred_rounded_rect(scene: &mut Scene, params: &mut SceneParams) { + params.resolution = Some(Vec2::new(1200., 1200.)); + params.base_color = Some(Color::WHITE); + + let rect = Rect::from_center_size((0.0, 0.0), (300.0, 240.0)); + let radius = 50.0; + scene.draw_blurred_rounded_rect( + Affine::translate((300.0, 300.0)), + rect, + Color::BLUE, + radius, + params.time.sin() * 50.0 + 50.0, + ); + + // Skewed affine transformation. + scene.draw_blurred_rounded_rect( + Affine::translate((900.0, 300.0)) * Affine::skew(20f64.to_radians().tan(), 0.0), + rect, + Color::BLACK, + radius, + params.time.sin() * 50.0 + 50.0, + ); + + // Stretch affine transformation. + scene.draw_blurred_rounded_rect( + Affine::translate((600.0, 600.0)) * Affine::scale_non_uniform(2.2, 0.9), + rect, + Color::BLACK, + radius, + params.time.sin() * 50.0 + 50.0, + ); + + // Circle. + scene.draw_blurred_rounded_rect( + Affine::IDENTITY, + Rect::new(100.0, 800.0, 400.0, 1100.0), + Color::BLACK, + 150.0, + params.time.sin() * 50.0 + 50.0, + ); + + // Radius larger than one size. + scene.draw_blurred_rounded_rect( + Affine::IDENTITY, + Rect::new(600.0, 800.0, 900.0, 900.0), + Color::BLACK, + 150.0, + params.time.sin() * 50.0 + 50.0, + ); + } } diff --git a/vello/src/scene.rs b/vello/src/scene.rs index 6c558ef20..82e8b47f9 100644 --- a/vello/src/scene.rs +++ b/vello/src/scene.rs @@ -112,6 +112,36 @@ impl Scene { self.encoding.encode_end_clip(); } + /// Draw a rounded rectangle blurred with a gaussian filter. + pub fn draw_blurred_rounded_rect( + &mut self, + transform: Affine, + rect: Rect, + brush: Color, + radius: f64, + std_dev: f64, + ) { + // The impulse response of a gaussian filter is infinite. + // For performance reason we cut off the filter at some extent where the response is close to zero. + let kernel_size = 2.5 * std_dev; + + let t = Transform::from_kurbo(&transform.pre_translate(rect.center().to_vec2())); + self.encoding.encode_transform(t); + + let shape: Rect = + Rect::from_center_size((0.0, 0.0), rect.size()).inflate(kernel_size, kernel_size); + self.encoding.encode_fill_style(Fill::NonZero); + if self.encoding.encode_shape(&shape, true) { + self.encoding.encode_blurred_rounded_rect( + brush, + rect.width() as _, + rect.height() as _, + radius as _, + std_dev as _, + ); + } + } + /// Fills a shape using the specified style and brush. pub fn fill<'b>( &mut self, diff --git a/vello_encoding/src/draw.rs b/vello_encoding/src/draw.rs index 251ba49c0..c95edb805 100644 --- a/vello_encoding/src/draw.rs +++ b/vello_encoding/src/draw.rs @@ -30,6 +30,9 @@ impl DrawTag { /// Image fill. pub const IMAGE: Self = Self(0x248); + /// Blurred rounded rectangle. + pub const BLUR_RECT: Self = Self(0x2d4); // info: 11, scene: 5 (DrawBlurRoundedRect) + /// Begin layer/clip. pub const BEGIN_CLIP: Self = Self(0x9); @@ -126,6 +129,22 @@ pub struct DrawImage { pub width_height: u32, } +/// Draw data for a blurred rounded rectangle. +#[derive(Clone, Copy, Debug, Default, Zeroable, Pod)] +#[repr(C)] +pub struct DrawBlurRoundedRect { + /// Solid color brush. + pub color: DrawColor, + /// Rectangle width. + pub width: f32, + /// Rectangle height. + pub height: f32, + /// Rectangle corner radius. + pub radius: f32, + /// Standard deviation of gaussian filter. + pub std_dev: f32, +} + /// Draw data for a clip or layer. #[derive(Clone, Copy, Debug, Default, Zeroable, Pod)] #[repr(C)] diff --git a/vello_encoding/src/encoding.rs b/vello_encoding/src/encoding.rs index 8cf6affd9..a6db5e888 100644 --- a/vello_encoding/src/encoding.rs +++ b/vello_encoding/src/encoding.rs @@ -1,10 +1,10 @@ // Copyright 2022 the Vello Authors // SPDX-License-Identifier: Apache-2.0 OR MIT -use super::{DrawColor, DrawTag, PathEncoder, PathTag, Style, Transform}; +use super::{DrawBlurRoundedRect, DrawColor, DrawTag, PathEncoder, PathTag, Style, Transform}; use peniko::kurbo::{Shape, Stroke}; -use peniko::{BlendMode, BrushRef, Fill}; +use peniko::{BlendMode, BrushRef, Color, Fill}; #[cfg(feature = "full")] use { @@ -12,7 +12,7 @@ use { DrawImage, DrawLinearGradient, DrawRadialGradient, DrawSweepGradient, Glyph, GlyphRun, Patch, }, - peniko::{Color, ColorStop, Extend, GradientKind, Image}, + peniko::{ColorStop, Extend, GradientKind, Image}, skrifa::instance::NormalizedCoord, }; @@ -433,6 +433,26 @@ impl Encoding { })); } + // Encodes a blurred rounded rectangle brush. + pub fn encode_blurred_rounded_rect( + &mut self, + color: Color, + width: f32, + height: f32, + radius: f32, + std_dev: f32, + ) { + self.draw_tags.push(DrawTag::BLUR_RECT); + self.draw_data + .extend_from_slice(bytemuck::bytes_of(&DrawBlurRoundedRect { + color: DrawColor::new(color), + width, + height, + radius, + std_dev, + })); + } + /// Encodes a begin clip command. pub fn encode_begin_clip(&mut self, blend_mode: BlendMode, alpha: f32) { use super::DrawBeginClip; diff --git a/vello_encoding/src/lib.rs b/vello_encoding/src/lib.rs index 30db95000..18f5bed40 100644 --- a/vello_encoding/src/lib.rs +++ b/vello_encoding/src/lib.rs @@ -31,8 +31,8 @@ pub use config::{ RenderConfig, WorkgroupCounts, WorkgroupSize, }; pub use draw::{ - DrawBbox, DrawBeginClip, DrawColor, DrawImage, DrawLinearGradient, DrawMonoid, - DrawRadialGradient, DrawSweepGradient, DrawTag, DRAW_INFO_FLAGS_FILL_RULE_BIT, + DrawBbox, DrawBeginClip, DrawBlurRoundedRect, DrawColor, DrawImage, DrawLinearGradient, + DrawMonoid, DrawRadialGradient, DrawSweepGradient, DrawTag, DRAW_INFO_FLAGS_FILL_RULE_BIT, }; pub use encoding::{Encoding, StreamOffsets}; pub use mask::{make_mask_lut, make_mask_lut_16}; diff --git a/vello_shaders/shader/coarse.wgsl b/vello_shaders/shader/coarse.wgsl index 6856396b4..d47b43b9b 100644 --- a/vello_shaders/shader/coarse.wgsl +++ b/vello_shaders/shader/coarse.wgsl @@ -146,6 +146,14 @@ fn write_end_clip(end_clip: CmdEndClip) { cmd_offset += 3u; } +fn write_blurred_rounded_rect(color: CmdColor, info_offset: u32) { + alloc_cmd(3u); + ptcl[cmd_offset] = CMD_BLUR_RECT; + ptcl[cmd_offset + 1u] = info_offset; + ptcl[cmd_offset + 2u] = color.rgba_color; + cmd_offset += 3u; +} + @compute @workgroup_size(256) fn main( @builtin(local_invocation_id) local_id: vec3, @@ -374,6 +382,12 @@ fn main( let rgba_color = scene[dd]; write_color(CmdColor(rgba_color)); } + case DRAWTAG_BLURRED_ROUNDED_RECT: { + write_path(tile, tile_ix, draw_flags); + let rgba_color = scene[dd]; + let info_offset = di + 1u; + write_blurred_rounded_rect(CmdColor(rgba_color), info_offset); + } case DRAWTAG_FILL_LIN_GRADIENT: { write_path(tile, tile_ix, draw_flags); let index = scene[dd]; diff --git a/vello_shaders/shader/draw_leaf.wgsl b/vello_shaders/shader/draw_leaf.wgsl index 2ef76db80..9f7d020c7 100644 --- a/vello_shaders/shader/draw_leaf.wgsl +++ b/vello_shaders/shader/draw_leaf.wgsl @@ -110,7 +110,7 @@ fn main( let di = m.info_offset; if tag_word == DRAWTAG_FILL_COLOR || tag_word == DRAWTAG_FILL_LIN_GRADIENT || tag_word == DRAWTAG_FILL_RAD_GRADIENT || tag_word == DRAWTAG_FILL_SWEEP_GRADIENT || - tag_word == DRAWTAG_FILL_IMAGE || tag_word == DRAWTAG_BEGIN_CLIP + tag_word == DRAWTAG_FILL_IMAGE || tag_word == DRAWTAG_BEGIN_CLIP || tag_word == DRAWTAG_BLURRED_ROUNDED_RECT { let bbox = path_bbox[m.path_ix]; // TODO: bbox is mostly yagni here, sort that out. Maybe clips? @@ -122,7 +122,8 @@ fn main( var transform = Transform(); let draw_flags = bbox.draw_flags; if tag_word == DRAWTAG_FILL_LIN_GRADIENT || tag_word == DRAWTAG_FILL_RAD_GRADIENT || - tag_word == DRAWTAG_FILL_SWEEP_GRADIENT || tag_word == DRAWTAG_FILL_IMAGE + tag_word == DRAWTAG_FILL_SWEEP_GRADIENT || tag_word == DRAWTAG_FILL_IMAGE || + tag_word == DRAWTAG_BLURRED_ROUNDED_RECT { transform = read_transform(config.transform_base, bbox.trans_ix); } @@ -253,6 +254,20 @@ fn main( info[di + 7u] = scene[dd]; info[di + 8u] = scene[dd + 1u]; } + case DRAWTAG_BLURRED_ROUNDED_RECT: { + info[di] = draw_flags; + let inv = transform_inverse(transform); + info[di + 1u] = bitcast(inv.matrx.x); + info[di + 2u] = bitcast(inv.matrx.y); + info[di + 3u] = bitcast(inv.matrx.z); + info[di + 4u] = bitcast(inv.matrx.w); + info[di + 5u] = bitcast(inv.translate.x); + info[di + 6u] = bitcast(inv.translate.y); + info[di + 7u] = scene[dd + 1u]; + info[di + 8u] = scene[dd + 2u]; + info[di + 9u] = scene[dd + 3u]; + info[di + 10u] = scene[dd + 4u]; + } default: {} } } diff --git a/vello_shaders/shader/fine.wgsl b/vello_shaders/shader/fine.wgsl index 810f41661..91b0dddac 100644 --- a/vello_shaders/shader/fine.wgsl +++ b/vello_shaders/shader/fine.wgsl @@ -720,6 +720,22 @@ fn fill_path_ms_evenodd(fill: CmdFill, local_id: vec2, result: ptr f32 { + // Clamp to prevent overflow. + // Intermediate steps calculate pow(x, 14). + let y = clamp(x * 1.1283791671, -100.0, 100.0); + let yy = y * y; + let z = y + (0.24295 + (0.03395 + 0.0104 * yy) * yy) * (y * yy); + return z / sqrt(1.0 + z * z); +} + +fn hypot(a: f32, b: f32) -> f32 { + return sqrt(a * a + b * b); +} + fn read_fill(cmd_ix: u32) -> CmdFill { let size_and_rule = ptcl[cmd_ix + 1u]; let seg_data = ptcl[cmd_ix + 2u]; @@ -732,6 +748,24 @@ fn read_color(cmd_ix: u32) -> CmdColor { return CmdColor(rgba_color); } +fn read_blur_rect(cmd_ix: u32) -> CmdBlurRect { + let info_offset = ptcl[cmd_ix + 1u]; + let rgba_color = ptcl[cmd_ix + 2u]; + + let m0 = bitcast(info[info_offset]); + let m1 = bitcast(info[info_offset + 1u]); + let m2 = bitcast(info[info_offset + 2u]); + let m3 = bitcast(info[info_offset + 3u]); + let matrx = vec4(m0, m1, m2, m3); + let xlat = vec2(bitcast(info[info_offset + 4u]), bitcast(info[info_offset + 5u])); + let width = bitcast(info[info_offset + 6u]); + let height = bitcast(info[info_offset + 7u]); + let radius = bitcast(info[info_offset + 8u]); + let std_dev = bitcast(info[info_offset + 9u]); + + return CmdBlurRect(rgba_color, matrx, xlat, width, height, radius, std_dev); +} + fn read_lin_grad(cmd_ix: u32) -> CmdLinGrad { let index_mode = ptcl[cmd_ix + 1u]; let index = index_mode >> 2u; @@ -983,6 +1017,56 @@ fn main( case CMD_JUMP: { cmd_ix = ptcl[cmd_ix + 1u]; } + case CMD_BLUR_RECT: { + /// Approximation for the convolution of a gaussian filter with a rounded rectangle. + /// + /// See https://raphlinus.github.io/graphics/2020/04/21/blurred-rounded-rects.html + + let blur = read_blur_rect(cmd_ix); + + // Avoid division by 0 + let std_dev = max(blur.std_dev, 1e-5); + let inv_std_dev = 1.0 / std_dev; + + let min_edge = min(blur.width, blur.height); + let radius_max = 0.5 * min_edge; + let r0 = min(hypot(blur.radius, std_dev * 1.15), radius_max); + let r1 = min(hypot(blur.radius, std_dev * 2.0), radius_max); + + let exponent = 2.0 * r1 / r0; + let inv_exponent = 1.0 / exponent; + + // Pull in long end (make less eccentric). + let delta = 1.25 * std_dev * (exp(-pow(0.5 * inv_std_dev * blur.width, 2.0)) - exp(-pow(0.5 * inv_std_dev * blur.height, 2.0))); + let width = blur.width + min(delta, 0.0); + let height = blur.height - max(delta, 0.0); + + let scale = 0.5 * erf7(inv_std_dev * 0.5 * (max(width, height) - 0.5 * blur.radius)); + + for (var i = 0u; i < PIXELS_PER_THREAD; i += 1u) { + // Transform fragment location to local 'uv' space of the rounded rectangle. + let my_xy = vec2(xy.x + f32(i), xy.y); + let local_xy = blur.matrx.xy * my_xy.x + blur.matrx.zw * my_xy.y + blur.xlat; + let x = local_xy.x; + let y = local_xy.y; + + let y0 = abs(y) - (height * 0.5 - r1); + let y1 = max(y0, 0.0); + + let x0 = abs(x) - (width * 0.5 - r1); + let x1 = max(x0, 0.0); + + let d_pos = pow(pow(x1, exponent) + pow(y1, exponent), inv_exponent); + let d_neg = min(max(x0, y0), 0.0); + let d = d_pos + d_neg - r1; + let alpha = scale * (erf7(inv_std_dev * (min_edge + d)) - erf7(inv_std_dev * d)); + + let fg_rgba = unpack4x8unorm(blur.rgba_color).wzyx * alpha; + let fg_i = fg_rgba * area[i]; + rgba[i] = rgba[i] * (1.0 - fg_i.a) + fg_i; + } + cmd_ix += 3u; + } #ifdef full case CMD_LIN_GRAD: { let lin = read_lin_grad(cmd_ix); diff --git a/vello_shaders/shader/shared/drawtag.wgsl b/vello_shaders/shader/shared/drawtag.wgsl index 97ab0c3a7..9d887be3a 100644 --- a/vello_shaders/shader/shared/drawtag.wgsl +++ b/vello_shaders/shader/shared/drawtag.wgsl @@ -22,6 +22,7 @@ let DRAWTAG_FILL_LIN_GRADIENT = 0x114u; let DRAWTAG_FILL_RAD_GRADIENT = 0x29cu; let DRAWTAG_FILL_SWEEP_GRADIENT = 0x254u; let DRAWTAG_FILL_IMAGE = 0x248u; +let DRAWTAG_BLURRED_ROUNDED_RECT = 0x2d4u; let DRAWTAG_BEGIN_CLIP = 0x9u; let DRAWTAG_END_CLIP = 0x21u; diff --git a/vello_shaders/shader/shared/ptcl.wgsl b/vello_shaders/shader/shared/ptcl.wgsl index 801819206..e6d20a0a0 100644 --- a/vello_shaders/shader/shared/ptcl.wgsl +++ b/vello_shaders/shader/shared/ptcl.wgsl @@ -22,6 +22,7 @@ let CMD_IMAGE = 9u; let CMD_BEGIN_CLIP = 10u; let CMD_END_CLIP = 11u; let CMD_JUMP = 12u; +let CMD_BLUR_RECT = 13u; // The individual PTCL structs are written here, but read/write is by // hand in the relevant shaders @@ -45,6 +46,24 @@ struct CmdColor { rgba_color: u32, } +struct CmdBlurRect { + // Solid fill color. + rgba_color: u32, + + // 2x2 transformation matrix (inverse). + matrx: vec4, + // 2D translation (inverse) + xlat: vec2, + + // Rounded rectangle properties. + width: f32, + height: f32, + radius: f32, + + // Gaussian filter standard deviation + std_dev: f32, +} + struct CmdLinGrad { index: u32, extend_mode: u32, diff --git a/vello_shaders/src/cpu.rs b/vello_shaders/src/cpu.rs index a129fce59..dde7928fc 100644 --- a/vello_shaders/src/cpu.rs +++ b/vello_shaders/src/cpu.rs @@ -182,6 +182,7 @@ const CMD_IMAGE: u32 = 9; const CMD_BEGIN_CLIP: u32 = 10; const CMD_END_CLIP: u32 = 11; const CMD_JUMP: u32 = 12; +const CMD_BLUR_RECT: u32 = 13; // The following are computed in draw_leaf from the generic gradient parameters // encoded in the scene, and stored in the gradient's info struct, for diff --git a/vello_shaders/src/cpu/coarse.rs b/vello_shaders/src/cpu/coarse.rs index 88ec6036d..bb75bc28b 100644 --- a/vello_shaders/src/cpu/coarse.rs +++ b/vello_shaders/src/cpu/coarse.rs @@ -9,8 +9,8 @@ use vello_encoding::{ }; use super::{ - CpuBinding, CMD_BEGIN_CLIP, CMD_COLOR, CMD_END, CMD_END_CLIP, CMD_FILL, CMD_IMAGE, CMD_JUMP, - CMD_LIN_GRAD, CMD_RAD_GRAD, CMD_SOLID, CMD_SWEEP_GRAD, PTCL_INITIAL_ALLOC, + CpuBinding, CMD_BEGIN_CLIP, CMD_BLUR_RECT, CMD_COLOR, CMD_END, CMD_END_CLIP, CMD_FILL, + CMD_IMAGE, CMD_JUMP, CMD_LIN_GRAD, CMD_RAD_GRAD, CMD_SOLID, CMD_SWEEP_GRAD, PTCL_INITIAL_ALLOC, }; // Tiles per bin @@ -138,6 +138,21 @@ impl TileState { self.cmd_offset += 3; } + fn write_blur_rect( + &mut self, + config: &ConfigUniform, + bump: &mut BumpAllocators, + ptcl: &mut [u32], + rgba_color: u32, + info_offset: u32, + ) { + self.alloc_cmd(3, config, bump, ptcl); + self.write(ptcl, 0, CMD_BLUR_RECT); + self.write(ptcl, 1, info_offset); + self.write(ptcl, 2, rgba_color); + self.cmd_offset += 3; + } + fn write_begin_clip( &mut self, config: &ConfigUniform, @@ -313,6 +328,11 @@ fn coarse_main( di + 1, ); } + DrawTag::BLUR_RECT => { + tile_state.write_path(config, bump, ptcl, tile, draw_flags); + let rgba_color = scene[dd as usize]; + tile_state.write_blur_rect(config, bump, ptcl, rgba_color, di + 1); + } DrawTag::BEGIN_CLIP => { if tile.segment_count_or_ix == 0 && tile.backdrop == 0 { clip_zero_depth = clip_depth + 1; diff --git a/vello_shaders/src/cpu/draw_leaf.rs b/vello_shaders/src/cpu/draw_leaf.rs index f84fabee2..6457be4f0 100644 --- a/vello_shaders/src/cpu/draw_leaf.rs +++ b/vello_shaders/src/cpu/draw_leaf.rs @@ -46,6 +46,7 @@ fn draw_leaf_main( || tag_word == DrawTag::SWEEP_GRADIENT || tag_word == DrawTag::IMAGE || tag_word == DrawTag::BEGIN_CLIP + || tag_word == DrawTag::BLUR_RECT { let bbox = path_bbox[m.path_ix as usize]; let transform = Transform::read(config.layout.transform_base, bbox.trans_ix, scene); @@ -175,6 +176,20 @@ fn draw_leaf_main( info[di + 7] = scene[dd as usize]; info[di + 8] = scene[dd as usize + 1]; } + DrawTag::BLUR_RECT => { + info[di] = draw_flags; + let xform = transform.inverse(); + info[di + 1] = f32::to_bits(xform.0[0]); + info[di + 2] = f32::to_bits(xform.0[1]); + info[di + 3] = f32::to_bits(xform.0[2]); + info[di + 4] = f32::to_bits(xform.0[3]); + info[di + 5] = f32::to_bits(xform.0[4]); + info[di + 6] = f32::to_bits(xform.0[5]); + info[di + 7] = scene[dd as usize + 1]; + info[di + 8] = scene[dd as usize + 2]; + info[di + 9] = scene[dd as usize + 3]; + info[di + 10] = scene[dd as usize + 4]; + } DrawTag::BEGIN_CLIP => (), _ => todo!("unhandled draw tag {:x}", tag_word.0), } diff --git a/vello_tests/snapshots/blurred_rounded_rect.png b/vello_tests/snapshots/blurred_rounded_rect.png new file mode 100644 index 000000000..fac0ea096 --- /dev/null +++ b/vello_tests/snapshots/blurred_rounded_rect.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:31045b3af3ada20e0a0763f453a69c9f6e9a6963a024c11603490ad6e036e68a +size 766382 diff --git a/vello_tests/tests/compare_gpu_cpu.rs b/vello_tests/tests/compare_gpu_cpu.rs index 860728ff0..14af5c15b 100644 --- a/vello_tests/tests/compare_gpu_cpu.rs +++ b/vello_tests/tests/compare_gpu_cpu.rs @@ -89,3 +89,12 @@ fn compare_deep_blend() { let params = TestParams::new("compare_deep_blend", 150, 150); compare_test_scene(test_scene, params); } + +#[test] +#[cfg_attr(skip_gpu_tests, ignore)] +fn compare_blurred_rounded_rect() { + let test_scene = test_scenes::blurred_rounded_rect(); + assert_eq!(test_scene.config.name, "blurred_rounded_rect"); + let params = TestParams::new("compare_blurred_rounded_rect", 1200, 1200); + compare_test_scene(test_scene, params); +} diff --git a/vello_tests/tests/snapshot_test_scenes.rs b/vello_tests/tests/snapshot_test_scenes.rs index 97090c81e..126d80451 100644 --- a/vello_tests/tests/snapshot_test_scenes.rs +++ b/vello_tests/tests/snapshot_test_scenes.rs @@ -89,3 +89,11 @@ fn snapshot_many_clips() { let params = TestParams::new("many_clips", 200, 200); snapshot_test_scene(test_scene, params); } + +#[test] +#[cfg_attr(skip_gpu_tests, ignore)] +fn snapshot_blurred_rounded_rect() { + let test_scene = test_scenes::blurred_rounded_rect(); + let params = TestParams::new("blurred_rounded_rect", 1200, 1200); + snapshot_test_scene(test_scene, params); +} From ede0e475c65157cdb0fe54a827780979e260d4bd Mon Sep 17 00:00:00 2001 From: TimTom Date: Thu, 29 Aug 2024 07:22:42 -0600 Subject: [PATCH 3/7] Fix panic caused by improperly aligned read (#675) Under certain circumstances, Vello could attempt an improperly aligned read, which would cause bytemuck to panic. This uses `bytemuck::pod_read_unaligned` instead of `bytemuck::from_bytes` to achieve the same thing without the possibility of a panic. --- vello_encoding/src/path.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/vello_encoding/src/path.rs b/vello_encoding/src/path.rs index c4c2fa596..f5518d030 100644 --- a/vello_encoding/src/path.rs +++ b/vello_encoding/src/path.rs @@ -723,8 +723,10 @@ impl<'a> PathEncoder<'a> { if len < 8 { return None; } - let pts: &[f32; 2] = bytemuck::from_bytes(&self.data[len - 8..len]); - Some((pts[0], pts[1])) + Some(( + bytemuck::pod_read_unaligned::(&self.data[len - 8..len - 4]), + bytemuck::pod_read_unaligned::(&self.data[len - 4..len]), + )) } fn is_zero_length_segment( From bf97b51bf933ebde183bf9c34b3261aea1f7f953 Mon Sep 17 00:00:00 2001 From: Bruce Mitchener Date: Sat, 31 Aug 2024 19:12:38 +0700 Subject: [PATCH 4/7] Fix `Cargo.lock` (#679) This picked up some `[patch.unused]` sections that want to be removed. This was introduced in #671 / 5a7c34e2672c50b41ad5011c7bf626f13c766ff3. --- Cargo.lock | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a93f968ee..d2c1bc4c6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3410,11 +3410,3 @@ checksum = "ec866b44a2a1fd6133d363f073ca1b179f438f99e7e5bfb1e33f7181facfe448" dependencies = [ "zune-core", ] - -[[patch.unused]] -name = "bevy" -version = "0.15.0-dev" - -[[patch.unused]] -name = "bevy_vello" -version = "0.5.1" From f08c2a828848e75db144d6a082c5a0818b84f561 Mon Sep 17 00:00:00 2001 From: Bruce Mitchener Date: Mon, 2 Sep 2024 22:25:48 +0700 Subject: [PATCH 5/7] wgpu: Prefix WGPU labels with "vello." (#677) This makes them easier to identify as being from Vello when embedding into an application. --- vello/src/debug/renderer.rs | 22 ++++++------- vello/src/lib.rs | 2 +- vello/src/render.rs | 62 +++++++++++++++++++++---------------- vello/src/shaders.rs | 2 +- 4 files changed, 48 insertions(+), 40 deletions(-) diff --git a/vello/src/debug/renderer.rs b/vello/src/debug/renderer.rs index 534607894..adc8380e9 100644 --- a/vello/src/debug/renderer.rs +++ b/vello/src/debug/renderer.rs @@ -38,7 +38,7 @@ impl DebugRenderer { let clear_tint = engine.add_render_shader( device, - "clear-tint", + "vello.debug.clear_tint", &module, "full_screen_quad_vert", "solid_color_frag", @@ -60,7 +60,7 @@ impl DebugRenderer { ); let bboxes = engine.add_render_shader( device, - "bbox-debug", + "vello.debug.bbox", &module, "bbox_vert", "solid_color_frag", @@ -91,7 +91,7 @@ impl DebugRenderer { ); let linesoup = engine.add_render_shader( device, - "linesoup-debug", + "vello.debug.linesoup", &module, "linesoup_vert", "solid_color_frag", @@ -122,7 +122,7 @@ impl DebugRenderer { ); let linesoup_points = engine.add_render_shader( device, - "linepoints-debug", + "vello.debug.linesoup_points", &module, "linepoints_vert", "sdf_circle_frag", @@ -162,7 +162,7 @@ impl DebugRenderer { ); let unpaired_points = engine.add_render_shader( device, - "linepoints-debug", + "vello.debug.unpaired_points", &module, "linepoints_vert", "sdf_circle_frag", @@ -230,10 +230,10 @@ impl DebugRenderer { } else { ( unpaired_pts.len(), - Some( - recording - .upload("unpaired points", bytemuck::cast_slice(&unpaired_pts[..])), - ), + Some(recording.upload( + "vello.debug.unpaired_points", + bytemuck::cast_slice(&unpaired_pts[..]), + )), ) } } else { @@ -245,7 +245,7 @@ impl DebugRenderer { height: params.height, }; let uniforms_buf = ResourceProxy::Buffer( - recording.upload_uniform("uniforms", bytemuck::bytes_of(&uniforms)), + recording.upload_uniform("vello.debug_uniforms", bytemuck::bytes_of(&uniforms)), ); let linepoints_uniforms = [ @@ -253,7 +253,7 @@ impl DebugRenderer { LinepointsUniforms::new(Color::RED, 80.), ]; let linepoints_uniforms_buf = recording.upload_uniform( - "linepoints uniforms", + "vello.debug.linepoints_uniforms", bytemuck::bytes_of(&linepoints_uniforms), ); diff --git a/vello/src/lib.rs b/vello/src/lib.rs index 419b5ad93..c2f4d1d53 100644 --- a/vello/src/lib.rs +++ b/vello/src/lib.rs @@ -806,7 +806,7 @@ impl BlitPipeline { }); let shader_id = engine.add_render_shader( device, - "blit", + "vello.blit", &module, "vs_main", "fs_main", diff --git a/vello/src/render.rs b/vello/src/render.rs index 2cca8e6b2..4e2c4c484 100644 --- a/vello/src/render.rs +++ b/vello/src/render.rs @@ -178,22 +178,25 @@ impl Render { // is zero. packed.resize(size_of::(), u8::MAX); } - let scene_buf = ResourceProxy::Buffer(recording.upload("scene", packed)); + let scene_buf = ResourceProxy::Buffer(recording.upload("vello.scene", packed)); let config_buf = ResourceProxy::Buffer( - recording.upload_uniform("config", bytemuck::bytes_of(&cpu_config.gpu)), + recording.upload_uniform("vello.config", bytemuck::bytes_of(&cpu_config.gpu)), ); let info_bin_data_buf = ResourceProxy::new_buf( buffer_sizes.bin_data.size_in_bytes() as u64, - "info_bin_data_buf", + "vello.info_bin_data_buf", ); let tile_buf = - ResourceProxy::new_buf(buffer_sizes.tiles.size_in_bytes().into(), "tile_buf"); - let segments_buf = - ResourceProxy::new_buf(buffer_sizes.segments.size_in_bytes().into(), "segments_buf"); - let ptcl_buf = ResourceProxy::new_buf(buffer_sizes.ptcl.size_in_bytes().into(), "ptcl_buf"); + ResourceProxy::new_buf(buffer_sizes.tiles.size_in_bytes().into(), "vello.tile_buf"); + let segments_buf = ResourceProxy::new_buf( + buffer_sizes.segments.size_in_bytes().into(), + "vello.segments_buf", + ); + let ptcl_buf = + ResourceProxy::new_buf(buffer_sizes.ptcl.size_in_bytes().into(), "vello.ptcl_buf"); let reduced_buf = ResourceProxy::new_buf( buffer_sizes.path_reduced.size_in_bytes().into(), - "reduced_buf", + "vello.reduced_buf", ); // TODO: really only need pathtag_wgs - 1 recording.dispatch( @@ -207,7 +210,7 @@ impl Render { if use_large_path_scan { let reduced2_buf = ResourceProxy::new_buf( buffer_sizes.path_reduced2.size_in_bytes().into(), - "reduced2_buf", + "vello.reduced2_buf", ); recording.dispatch( shaders.pathtag_reduce2, @@ -229,7 +232,7 @@ impl Render { let tagmonoid_buf = ResourceProxy::new_buf( buffer_sizes.path_monoids.size_in_bytes().into(), - "tagmonoid_buf", + "vello.tagmonoid_buf", ); let pathtag_scan = if use_large_path_scan { shaders.pathtag_scan_large @@ -248,18 +251,21 @@ impl Render { } let path_bbox_buf = ResourceProxy::new_buf( buffer_sizes.path_bboxes.size_in_bytes().into(), - "path_bbox_buf", + "vello.path_bbox_buf", ); recording.dispatch( shaders.bbox_clear, wg_counts.bbox_clear, [config_buf, path_bbox_buf], ); - let bump_buf = BufferProxy::new(buffer_sizes.bump_alloc.size_in_bytes().into(), "bump_buf"); + let bump_buf = BufferProxy::new( + buffer_sizes.bump_alloc.size_in_bytes().into(), + "vello.bump_buf", + ); recording.clear_all(bump_buf); let bump_buf = ResourceProxy::Buffer(bump_buf); let lines_buf = - ResourceProxy::new_buf(buffer_sizes.lines.size_in_bytes().into(), "lines_buf"); + ResourceProxy::new_buf(buffer_sizes.lines.size_in_bytes().into(), "vello.lines_buf"); recording.dispatch( shaders.flatten, wg_counts.flatten, @@ -274,7 +280,7 @@ impl Render { ); let draw_reduced_buf = ResourceProxy::new_buf( buffer_sizes.draw_reduced.size_in_bytes().into(), - "draw_reduced_buf", + "vello.draw_reduced_buf", ); recording.dispatch( shaders.draw_reduce, @@ -283,11 +289,11 @@ impl Render { ); let draw_monoid_buf = ResourceProxy::new_buf( buffer_sizes.draw_monoids.size_in_bytes().into(), - "draw_monoid_buf", + "vello.draw_monoid_buf", ); let clip_inp_buf = ResourceProxy::new_buf( buffer_sizes.clip_inps.size_in_bytes().into(), - "clip_inp_buf", + "vello.clip_inp_buf", ); recording.dispatch( shaders.draw_leaf, @@ -303,11 +309,13 @@ impl Render { ], ); recording.free_resource(draw_reduced_buf); - let clip_el_buf = - ResourceProxy::new_buf(buffer_sizes.clip_els.size_in_bytes().into(), "clip_el_buf"); + let clip_el_buf = ResourceProxy::new_buf( + buffer_sizes.clip_els.size_in_bytes().into(), + "vello.clip_el_buf", + ); let clip_bic_buf = ResourceProxy::new_buf( buffer_sizes.clip_bics.size_in_bytes().into(), - "clip_bic_buf", + "vello.clip_bic_buf", ); if wg_counts.clip_reduce.0 > 0 { recording.dispatch( @@ -318,7 +326,7 @@ impl Render { } let clip_bbox_buf = ResourceProxy::new_buf( buffer_sizes.clip_bboxes.size_in_bytes().into(), - "clip_bbox_buf", + "vello.clip_bbox_buf", ); if wg_counts.clip_leaf.0 > 0 { recording.dispatch( @@ -340,11 +348,11 @@ impl Render { recording.free_resource(clip_el_buf); let draw_bbox_buf = ResourceProxy::new_buf( buffer_sizes.draw_bboxes.size_in_bytes().into(), - "draw_bbox_buf", + "vello.draw_bbox_buf", ); let bin_header_buf = ResourceProxy::new_buf( buffer_sizes.bin_headers.size_in_bytes().into(), - "bin_header_buf", + "vello.bin_header_buf", ); recording.dispatch( shaders.binning, @@ -365,7 +373,7 @@ impl Render { // Note: this only needs to be rounded up because of the workaround to store the tile_offset // in storage rather than workgroup memory. let path_buf = - ResourceProxy::new_buf(buffer_sizes.paths.size_in_bytes().into(), "path_buf"); + ResourceProxy::new_buf(buffer_sizes.paths.size_in_bytes().into(), "vello.path_buf"); recording.dispatch( shaders.tile_alloc, wg_counts.tile_alloc, @@ -382,7 +390,7 @@ impl Render { recording.free_resource(tagmonoid_buf); let indirect_count_buf = BufferProxy::new( buffer_sizes.indirect_count.size_in_bytes().into(), - "indirect_count", + "vello.indirect_count", ); recording.dispatch( shaders.path_count_setup, @@ -391,7 +399,7 @@ impl Render { ); let seg_counts_buf = ResourceProxy::new_buf( buffer_sizes.seg_counts.size_in_bytes().into(), - "seg_counts_buf", + "vello.seg_counts_buf", ); recording.dispatch_indirect( shaders.path_count, @@ -453,7 +461,7 @@ impl Render { let out_image = ImageProxy::new(params.width, params.height, ImageFormat::Rgba8); let blend_spill_buf = BufferProxy::new( buffer_sizes.blend_spill.size_in_bytes().into(), - "blend_spill", + "vello.blend_spill", ); self.fine_wg_count = Some(wg_counts.fine); self.fine_resources = Some(FineResources { @@ -530,7 +538,7 @@ impl Render { AaConfig::Msaa8 => make_mask_lut(), _ => unreachable!(), }; - let buf = recording.upload("mask lut", mask_lut); + let buf = recording.upload("vello.mask_lut", mask_lut); self.mask_buf = Some(buf.into()); } let fine_shader = match fine.aa_config { diff --git a/vello/src/shaders.rs b/vello/src/shaders.rs index a58e0edfe..f4694e8b2 100644 --- a/vello/src/shaders.rs +++ b/vello/src/shaders.rs @@ -79,7 +79,7 @@ pub(crate) fn full_shaders( let source = shaders.$name.wgsl.code; engine.add_compute_shader( device, - $label, + concat!("vello.", $label), source, &$bindings, if force_gpu { From 71b484c6795f476253775010bd84770562558024 Mon Sep 17 00:00:00 2001 From: Bruce Mitchener Date: Thu, 5 Sep 2024 21:57:50 +0700 Subject: [PATCH 6/7] Update `image` dep, fix deprecation (#682) --- Cargo.lock | 12 ++++++------ Cargo.toml | 2 +- examples/scenes/src/images.rs | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d2c1bc4c6..11b703411 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -284,10 +284,10 @@ dependencies = [ ] [[package]] -name = "byteorder" -version = "1.5.0" +name = "byteorder-lite" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" [[package]] name = "bytes" @@ -1003,12 +1003,12 @@ checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" [[package]] name = "image" -version = "0.25.1" +version = "0.25.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd54d660e773627692c524beaad361aca785a4f9f5730ce91f42aabe5bce3d11" +checksum = "99314c8a2152b8ddb211f924cdae532d8c5e4c8bb54728e12fff1b0cd5963a10" dependencies = [ "bytemuck", - "byteorder", + "byteorder-lite", "num-traits", "png", "zune-core", diff --git a/Cargo.toml b/Cargo.toml index a881b64bc..3626a800b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,7 +53,7 @@ thiserror = "1.0.61" # NOTE: Make sure to keep this in sync with the version badge in README.md and vello/README.md wgpu = { version = "22.0.0" } log = "0.4.21" -image = { version = "0.25.1", default-features = false } +image = { version = "0.25.2", default-features = false } # Used for examples clap = "4.5.4" diff --git a/examples/scenes/src/images.rs b/examples/scenes/src/images.rs index 83f43c46e..95b6a263a 100644 --- a/examples/scenes/src/images.rs +++ b/examples/scenes/src/images.rs @@ -43,7 +43,7 @@ impl ImageCache { } fn decode_image(data: &[u8]) -> anyhow::Result { - let image = image::io::Reader::new(std::io::Cursor::new(data)) + let image = image::ImageReader::new(std::io::Cursor::new(data)) .with_guessed_format()? .decode()?; let width = image.width(); From 3c9343b54a50d27029b87b1d318cbcea2a0dc8f0 Mon Sep 17 00:00:00 2001 From: Bruce Mitchener Date: Fri, 6 Sep 2024 20:05:19 +0700 Subject: [PATCH 7/7] Fix some typos, backticks, new clippy lint. (#683) --- vello_encoding/src/mask.rs | 4 ++-- vello_encoding/src/math.rs | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/vello_encoding/src/mask.rs b/vello_encoding/src/mask.rs index eb5e9c9eb..1ea0246bc 100644 --- a/vello_encoding/src/mask.rs +++ b/vello_encoding/src/mask.rs @@ -31,7 +31,7 @@ fn one_mask(slope: f64, mut translation: f64, is_pos: bool) -> u8 { /// Make a lookup table of half-plane masks. /// /// The table is organized into two blocks each with `MASK_HEIGHT/2` slopes. -/// The first block is negative slopes (x decreases as y increates), +/// The first block is negative slopes (x decreases as y increases), /// the second as positive. pub fn make_mask_lut() -> Vec { (0..MASK_WIDTH * MASK_HEIGHT) @@ -78,7 +78,7 @@ fn one_mask_16(slope: f64, mut translation: f64, is_pos: bool) -> u16 { /// Make a lookup table of half-plane masks. /// /// The table is organized into two blocks each with `MASK16_HEIGHT/2` slopes. -/// The first block is negative slopes (x decreases as y increates), +/// The first block is negative slopes (x decreases as y increases), /// the second as positive. pub fn make_mask_lut_16() -> Vec { let v16 = (0..MASK16_WIDTH * MASK16_HEIGHT) diff --git a/vello_encoding/src/math.rs b/vello_encoding/src/math.rs index 212b50fb5..14432bed4 100644 --- a/vello_encoding/src/math.rs +++ b/vello_encoding/src/math.rs @@ -77,7 +77,8 @@ pub fn point_to_f32(point: kurbo::Point) -> [f32; 2] { [point.x as f32, point.y as f32] } -/// Converts an f32 to IEEE-754 binary16 format represented as the bits of a u16. +/// Converts an `f32` to IEEE-754 binary16 format represented as the bits of a `u16`. +/// /// This implementation was adapted from Fabian Giesen's `float_to_half_fast3`() /// function which can be found at /// @@ -122,7 +123,8 @@ pub(crate) fn f32_to_f16(val: f32) -> u16 { output | (sign >> 16) as u16 } -/// Convertes a 16-bit precision IEEE-754 binary16 float to a f32. +/// Converts a 16-bit precision IEEE-754 binary16 float to a `f32`. +/// /// This implementation was adapted from Fabian Giesen's `half_to_float()` /// function which can be found at pub fn f16_to_f32(bits: u16) -> f32 {