From 08a11bd78a50d5f17353ffc57ccb8bb20a9035d4 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 30 Dec 2024 11:26:00 +0100 Subject: [PATCH] WGPU: Changed flush_to_surface() to return a command buffer This allows the application to control when to submit. Fixes #227 --- CHANGELOG.md | 5 +++++ examples/helpers/wgpu.rs | 10 ++++++++-- src/lib.rs | 6 ++++-- src/renderer.rs | 5 ++++- src/renderer/opengl.rs | 1 + src/renderer/void.rs | 1 + src/renderer/wgpu.rs | 7 +++++-- 7 files changed, 28 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0364974e..66c8bf6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog All notable changes to this project will be documented in this file. +## UNRELEASED + + - WGPU renderer: Changed `flush_to_surface()` API to return a command buffer, + to let the application decide when to submit. + ## [0.11.3] - 2024-12-26 - WGPU renderer: Fix crash when rendering without always calling `set_size()`. (#226) diff --git a/examples/helpers/wgpu.rs b/examples/helpers/wgpu.rs index ff9c639d..2cbe53db 100644 --- a/examples/helpers/wgpu.rs +++ b/examples/helpers/wgpu.rs @@ -7,6 +7,7 @@ use super::{run, WindowSurface}; pub struct DemoSurface { device: Arc, + queue: Arc, surface_config: wgpu::SurfaceConfiguration, surface: wgpu::Surface<'static>, } @@ -26,7 +27,9 @@ impl WindowSurface for DemoSurface { .get_current_texture() .expect("unable to get next texture from swapchain"); - canvas.flush_to_surface(&frame.texture); + let commands = canvas.flush_to_surface(&frame.texture); + + self.queue.submit(Some(commands)); frame.present(); } @@ -131,13 +134,16 @@ pub async fn start_wgpu( let device = Arc::new(device); + let queue = Arc::new(queue); + let demo_surface = DemoSurface { device: device.clone(), + queue: queue.clone(), surface_config, surface, }; - let renderer = WGPURenderer::new(device, Arc::new(queue)); + let renderer = WGPURenderer::new(device, queue); let mut canvas = Canvas::new(renderer).expect("Cannot create canvas"); canvas.set_size(width, height, window.scale_factor() as f32); diff --git a/src/lib.rs b/src/lib.rs index 3c0cfcca..e0119708 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -418,8 +418,8 @@ where /// Tells the renderer to execute all drawing commands and clears the current internal state /// /// Call this at the end of each frame. - pub fn flush_to_surface(&mut self, surface: &T::Surface) { - self.renderer.render( + pub fn flush_to_surface(&mut self, surface: &T::Surface) -> T::CommandBuffer { + let command_buffer = self.renderer.render( surface, &mut self.images, &self.verts, @@ -431,6 +431,7 @@ where if let Some(atlas) = self.ephemeral_glyph_atlas.take() { atlas.clear(self); } + command_buffer } /// Returns a screenshot of the current canvas. @@ -1536,6 +1537,7 @@ impl Renderer for RecordingRenderer { type Image = DummyImage; type NativeTexture = (); type Surface = (); + type CommandBuffer = (); fn set_size(&mut self, _width: u32, _height: u32, _dpi: f32) {} diff --git a/src/renderer.rs b/src/renderer.rs index 653c3308..7dafdc86 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -124,6 +124,9 @@ pub trait Renderer { /// Associated surface type. type Surface; + /// Associated type to hold commands created via flush_to_surface. + type CommandBuffer; + /// Set the size of the renderer. fn set_size(&mut self, width: u32, height: u32, dpi: f32); @@ -134,7 +137,7 @@ pub trait Renderer { images: &mut ImageStore, verts: &[Vertex], commands: Vec, - ); + ) -> Self::CommandBuffer; /// Allocate a new image with the specified image info. fn alloc_image(&mut self, info: ImageInfo) -> Result; diff --git a/src/renderer/opengl.rs b/src/renderer/opengl.rs index af4af00c..7fd4c4e0 100644 --- a/src/renderer/opengl.rs +++ b/src/renderer/opengl.rs @@ -685,6 +685,7 @@ impl Renderer for OpenGl { type Image = GlTexture; type NativeTexture = ::Texture; type Surface = (); + type CommandBuffer = (); fn set_size(&mut self, width: u32, height: u32, _dpi: f32) { self.view[0] = width as f32; diff --git a/src/renderer/void.rs b/src/renderer/void.rs index 60af6574..0faccd94 100644 --- a/src/renderer/void.rs +++ b/src/renderer/void.rs @@ -14,6 +14,7 @@ impl Renderer for Void { type Image = VoidImage; type NativeTexture = (); type Surface = (); + type CommandBuffer = (); fn set_size(&mut self, width: u32, height: u32, dpi: f32) {} diff --git a/src/renderer/wgpu.rs b/src/renderer/wgpu.rs index 988fc2ce..13ab11f5 100644 --- a/src/renderer/wgpu.rs +++ b/src/renderer/wgpu.rs @@ -292,6 +292,7 @@ impl Renderer for WGPURenderer { type Image = Image; type NativeTexture = wgpu::Texture; type Surface = wgpu::Texture; + type CommandBuffer = wgpu::CommandBuffer; fn set_size(&mut self, _width: u32, _height: u32, _dpi: f32) {} @@ -301,7 +302,7 @@ impl Renderer for WGPURenderer { images: &mut crate::image::ImageStore, verts: &[super::Vertex], commands: Vec, - ) { + ) -> Self::CommandBuffer { self.screen_view[0] = surface_texture.width() as f32; self.screen_view[1] = surface_texture.height() as f32; @@ -459,11 +460,13 @@ impl Renderer for WGPURenderer { drop(render_pass_builder); - self.queue.submit(Some(encoder.finish())); + let command_buffer = encoder.finish(); self.pipeline_cache .borrow_mut() .retain(|_, cached_pipeline| std::mem::replace(&mut cached_pipeline.accessed, false)); + + command_buffer } fn alloc_image(&mut self, info: crate::ImageInfo) -> Result {