From 1c6fd87facff6997c914c19e58095e07e5a57102 Mon Sep 17 00:00:00 2001 From: Daniel McNab <36049421+DJMcNab@users.noreply.github.com> Date: Fri, 19 Jul 2024 16:37:10 +0100 Subject: [PATCH 1/3] Add minimal infrastructure for overriding an `Image` --- vello/src/lib.rs | 14 +++++++++ vello/src/recording.rs | 17 +++------- vello/src/render.rs | 9 +----- vello/src/wgpu_engine.rs | 67 ++++++++++++++++++++++++++++------------ 4 files changed, 67 insertions(+), 40 deletions(-) diff --git a/vello/src/lib.rs b/vello/src/lib.rs index 689dbc532..3e8b5b4ee 100644 --- a/vello/src/lib.rs +++ b/vello/src/lib.rs @@ -329,6 +329,20 @@ impl Renderer { }) } + /// Overwrite the `Image` with the `Texture` texture. + /// + /// If texture is `None`, removes the override. + pub fn override_image( + &mut self, + image: peniko::Image, + texture: Option>, + ) -> Option> { + match texture { + Some(texture) => self.engine.image_overrides.insert(image.data.id(), texture), + None => self.engine.image_overrides.remove(&image.data.id()), + } + } + /// Renders a scene to the target texture. /// /// The texture is assumed to be of the specified dimensions and have been created with diff --git a/vello/src/recording.rs b/vello/src/recording.rs index 0adb0f34d..cb489b851 100644 --- a/vello/src/recording.rs +++ b/vello/src/recording.rs @@ -4,6 +4,8 @@ use std::num::NonZeroU64; use std::sync::atomic::{AtomicU64, Ordering}; +use peniko::Image; + #[derive(Clone, Copy, PartialEq, Eq, Hash, Default)] pub struct ShaderId(pub usize); @@ -61,7 +63,7 @@ pub enum Command { UploadUniform(BufferProxy, Vec), /// Commands the data to be uploaded to the given image. UploadImage(ImageProxy, Vec), - WriteImage(ImageProxy, [u32; 4], Vec), + WriteImage(ImageProxy, [u32; 2], Image), // Discussion question: third argument is vec of resources? // Maybe use tricks to make more ergonomic? // Alternative: provide bufs & images as separate sequences @@ -133,17 +135,8 @@ impl Recording { image_proxy } - pub fn write_image( - &mut self, - image: ImageProxy, - x: u32, - y: u32, - width: u32, - height: u32, - data: impl Into>, - ) { - let data = data.into(); - self.push(Command::WriteImage(image, [x, y, width, height], data)); + pub fn write_image(&mut self, proxy: ImageProxy, x: u32, y: u32, image: Image) { + self.push(Command::WriteImage(proxy, [x, y], image)); } pub fn dispatch(&mut self, shader: ShaderId, wg_size: (u32, u32, u32), resources: R) diff --git a/vello/src/render.rs b/vello/src/render.rs index af6afda50..51336d329 100644 --- a/vello/src/render.rs +++ b/vello/src/render.rs @@ -113,14 +113,7 @@ impl Render { ImageProxy::new(images.width, images.height, ImageFormat::Rgba8) }; for image in images.images { - recording.write_image( - image_atlas, - image.1, - image.2, - image.0.width, - image.0.height, - image.0.data.data(), - ); + recording.write_image(image_atlas, image.1, image.2, image.0.clone()); } let cpu_config = RenderConfig::new(&layout, params.width, params.height, ¶ms.base_color); diff --git a/vello/src/wgpu_engine.rs b/vello/src/wgpu_engine.rs index c175f0d7a..e6e83420c 100644 --- a/vello/src/wgpu_engine.rs +++ b/vello/src/wgpu_engine.rs @@ -8,6 +8,7 @@ use std::collections::{HashMap, HashSet}; use vello_shaders::cpu::CpuBinding; +use wgpu::naga::Override; use wgpu::{ BindGroup, BindGroupLayout, Buffer, BufferUsages, CommandEncoder, CommandEncoderDescriptor, ComputePipeline, Device, PipelineCompilationOptions, Queue, Texture, TextureAspect, @@ -36,6 +37,10 @@ pub struct WgpuEngine { #[cfg(not(target_arch = "wasm32"))] shaders_to_initialise: Option>, pub(crate) use_cpu: bool, + /// Overrides from a specific `Image`'s [`id`](peniko::Image::id) to a wgpu `Texture`. + /// + /// The `Texture` should have the same size as the `Image`. + pub(crate) image_overrides: HashMap>, } struct WgpuShader { @@ -433,31 +438,53 @@ impl WgpuEngine { self.bind_map .insert_image(image_proxy.id, texture, texture_view); } - Command::WriteImage(proxy, [x, y, width, height], data) => { + Command::WriteImage(proxy, [x, y], image) => { let (texture, _) = self.bind_map.get_or_create_image(*proxy, device); let format = proxy.format.to_wgpu(); let block_size = format .block_copy_size(None) .expect("ImageFormat must have a valid block size"); - queue.write_texture( - wgpu::ImageCopyTexture { - texture, - mip_level: 0, - origin: wgpu::Origin3d { x: *x, y: *y, z: 0 }, - aspect: TextureAspect::All, - }, - &data[..], - wgpu::ImageDataLayout { - offset: 0, - bytes_per_row: Some(*width * block_size), - rows_per_image: None, - }, - wgpu::Extent3d { - width: *width, - height: *height, - depth_or_array_layers: 1, - }, - ); + if let Some(overrider) = self.image_overrides.get(&image.data.id()) { + encoder.copy_texture_to_texture( + wgpu::ImageCopyTexture { + texture: &overrider.texture, + mip_level: overrider.mip_level, + origin: overrider.origin, + aspect: overrider.aspect, + }, + wgpu::ImageCopyTexture { + texture, + mip_level: 0, + origin: wgpu::Origin3d { x: *x, y: *y, z: 0 }, + aspect: TextureAspect::All, + }, + wgpu::Extent3d { + width: image.width, + height: image.height, + depth_or_array_layers: 1, + }, + ); + } else { + queue.write_texture( + wgpu::ImageCopyTexture { + texture, + mip_level: 0, + origin: wgpu::Origin3d { x: *x, y: *y, z: 0 }, + aspect: TextureAspect::All, + }, + image.data.data(), + wgpu::ImageDataLayout { + offset: 0, + bytes_per_row: Some(image.width * block_size), + rows_per_image: None, + }, + wgpu::Extent3d { + width: image.width, + height: image.height, + depth_or_array_layers: 1, + }, + ); + } } Command::Dispatch(shader_id, wg_size, bindings) => { // println!("dispatching {:?} with {} bindings", wg_size, bindings.len()); From bb15e4425968403e78cba7dfbb9760bfc8026f1f Mon Sep 17 00:00:00 2001 From: Daniel McNab <36049421+DJMcNab@users.noreply.github.com> Date: Fri, 19 Jul 2024 16:45:38 +0100 Subject: [PATCH 2/3] Remove unused import Was hidden by https://github.com/linebender/vello/pull/617 --- vello/src/wgpu_engine.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/vello/src/wgpu_engine.rs b/vello/src/wgpu_engine.rs index e6e83420c..ae5247685 100644 --- a/vello/src/wgpu_engine.rs +++ b/vello/src/wgpu_engine.rs @@ -8,7 +8,6 @@ use std::collections::{HashMap, HashSet}; use vello_shaders::cpu::CpuBinding; -use wgpu::naga::Override; use wgpu::{ BindGroup, BindGroupLayout, Buffer, BufferUsages, CommandEncoder, CommandEncoderDescriptor, ComputePipeline, Device, PipelineCompilationOptions, Queue, Texture, TextureAspect, From dc0fe3348569d7971342411625f9fe083f92384d Mon Sep 17 00:00:00 2001 From: Daniel McNab <36049421+DJMcNab@users.noreply.github.com> Date: Fri, 19 Jul 2024 17:49:55 +0100 Subject: [PATCH 3/3] Use `&Image` and `Arc` --- vello/src/lib.rs | 8 ++++---- vello/src/wgpu_engine.rs | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/vello/src/lib.rs b/vello/src/lib.rs index 3e8b5b4ee..aa7728c7c 100644 --- a/vello/src/lib.rs +++ b/vello/src/lib.rs @@ -89,7 +89,7 @@ mod shaders; mod wgpu_engine; #[cfg(feature = "wgpu")] -use std::num::NonZeroUsize; +use std::{num::NonZeroUsize, sync::Arc}; /// Styling and composition primitives. pub use peniko; @@ -334,9 +334,9 @@ impl Renderer { /// If texture is `None`, removes the override. pub fn override_image( &mut self, - image: peniko::Image, - texture: Option>, - ) -> Option> { + image: &peniko::Image, + texture: Option>>, + ) -> Option>> { match texture { Some(texture) => self.engine.image_overrides.insert(image.data.id(), texture), None => self.engine.image_overrides.remove(&image.data.id()), diff --git a/vello/src/wgpu_engine.rs b/vello/src/wgpu_engine.rs index ae5247685..789484d58 100644 --- a/vello/src/wgpu_engine.rs +++ b/vello/src/wgpu_engine.rs @@ -5,6 +5,7 @@ use std::borrow::Cow; use std::cell::RefCell; use std::collections::hash_map::Entry; use std::collections::{HashMap, HashSet}; +use std::sync::Arc; use vello_shaders::cpu::CpuBinding; @@ -39,7 +40,7 @@ pub struct WgpuEngine { /// Overrides from a specific `Image`'s [`id`](peniko::Image::id) to a wgpu `Texture`. /// /// The `Texture` should have the same size as the `Image`. - pub(crate) image_overrides: HashMap>, + pub(crate) image_overrides: HashMap>>, } struct WgpuShader {