From 1a5dff5d126816fbcd9b51838a69a4373aaba146 Mon Sep 17 00:00:00 2001 From: Nathan Adams Date: Thu, 25 Jan 2024 16:14:53 +0100 Subject: [PATCH] wgpu: Keep a CommandEncoder for the duration of a frame, extract out a struct to hold it with a StagingBelt --- render/wgpu/src/backend.rs | 110 +++++++++++++++++++++---------------- 1 file changed, 63 insertions(+), 47 deletions(-) diff --git a/render/wgpu/src/backend.rs b/render/wgpu/src/backend.rs index c32428665..0216f53dc 100644 --- a/render/wgpu/src/backend.rs +++ b/render/wgpu/src/backend.rs @@ -45,7 +45,6 @@ const TEXTURE_READS_BEFORE_PROMOTION: u8 = 5; pub struct WgpuRenderBackend { pub(crate) descriptors: Arc, - staging_belt: wgpu::util::StagingBelt, target: T, surface: Surface, meshes: Vec, @@ -57,6 +56,7 @@ pub struct WgpuRenderBackend { offscreen_texture_pool: TexturePool, pub(crate) offscreen_buffer_pool: Arc>, dynamic_transforms: DynamicTransforms, + active_frame: ActiveFrame, } impl WgpuRenderBackend { @@ -219,10 +219,10 @@ impl WgpuRenderBackend { )); let transforms = DynamicTransforms::new(&descriptors); + let active_frame = ActiveFrame::new(&descriptors); Ok(Self { descriptors, - staging_belt: wgpu::util::StagingBelt::new(65536), target, surface, meshes: Vec::new(), @@ -232,6 +232,7 @@ impl WgpuRenderBackend { offscreen_texture_pool: TexturePool::new(), offscreen_buffer_pool: Arc::new(offscreen_buffer_pool), dynamic_transforms: transforms, + active_frame, }) } @@ -534,14 +535,6 @@ impl RenderBackend for WgpuRenderBackend { } }; - let label = create_debug_label!("Draw encoder"); - let mut draw_encoder = - self.descriptors - .device - .create_command_encoder(&wgpu::CommandEncoderDescriptor { - label: label.as_deref(), - }); - for entry in cache_entries { let texture = as_texture(&entry.handle); let mut surface = Surface::new( @@ -565,9 +558,9 @@ impl RenderBackend for WgpuRenderBackend { &self.descriptors, &self.meshes, entry.commands, - &mut self.staging_belt, + &mut self.active_frame.staging_belt, &self.dynamic_transforms, - &mut draw_encoder, + &mut self.active_frame.command_encoder, LayerRef::None, &mut self.offscreen_texture_pool, ); @@ -589,18 +582,18 @@ impl RenderBackend for WgpuRenderBackend { &self.descriptors, &self.meshes, entry.commands, - &mut self.staging_belt, + &mut self.active_frame.staging_belt, &self.dynamic_transforms, - &mut draw_encoder, + &mut self.active_frame.command_encoder, LayerRef::None, &mut self.offscreen_texture_pool, ); for filter in entry.filters { target = self.descriptors.filters.apply( &self.descriptors, - &mut draw_encoder, + &mut self.active_frame.command_encoder, &mut self.offscreen_texture_pool, - &mut self.staging_belt, + &mut self.active_frame.staging_belt, FilterSource::for_entire_texture(target.color_texture()), filter, ); @@ -614,7 +607,7 @@ impl RenderBackend for WgpuRenderBackend { target.whole_frame_bind_group(&self.descriptors), target.globals(), target.color_texture().sample_count(), - &mut draw_encoder, + &mut self.active_frame.command_encoder, ); } } @@ -628,23 +621,18 @@ impl RenderBackend for WgpuRenderBackend { a: f64::from(clear.a) / 255.0, }), &self.descriptors, - &mut self.staging_belt, + &mut self.active_frame.staging_belt, &self.dynamic_transforms, - &mut draw_encoder, + &mut self.active_frame.command_encoder, &self.meshes, commands, LayerRef::None, &mut self.texture_pool, ); - self.staging_belt.finish(); + self.active_frame.staging_belt.finish(); - self.target.submit( - &self.descriptors.device, - &self.descriptors.queue, - Some(draw_encoder.finish()), - frame_output, - ); - self.staging_belt.recall(); + self.active_frame + .submit(&self.descriptors, &self.target, frame_output); self.offscreen_texture_pool = TexturePool::new(); } @@ -786,33 +774,22 @@ impl RenderBackend for WgpuRenderBackend { texture.texture.height(), wgpu::TextureFormat::Rgba8Unorm, ); - let label = create_debug_label!("Draw encoder"); - let mut draw_encoder = - self.descriptors - .device - .create_command_encoder(&wgpu::CommandEncoderDescriptor { - label: label.as_deref(), - }); surface.draw_commands_and_copy_to( frame_output.view(), RenderTargetMode::FreshWithTexture(target.get_texture()), &self.descriptors, - &mut self.staging_belt, + &mut self.active_frame.staging_belt, &self.dynamic_transforms, - &mut draw_encoder, + &mut self.active_frame.command_encoder, &self.meshes, commands, LayerRef::Current, &mut self.offscreen_texture_pool, ); - self.staging_belt.finish(); - let index = target.submit( - &self.descriptors.device, - &self.descriptors.queue, - Some(draw_encoder.finish()), - frame_output, - ); - self.staging_belt.recall(); + + let index = self + .active_frame + .submit(&self.descriptors, &target, frame_output); Some(self.make_queue_sync_handle(target, Some(index), handle, bounds)) } @@ -878,7 +855,7 @@ impl RenderBackend for WgpuRenderBackend { &self.descriptors, &mut draw_encoder, &mut self.offscreen_texture_pool, - &mut self.staging_belt, + &mut self.active_frame.staging_belt, FilterSource { texture: &source_texture.texture, point: source_point, @@ -909,14 +886,14 @@ impl RenderBackend for WgpuRenderBackend { depth_or_array_layers: 1, }, ); - self.staging_belt.finish(); + self.active_frame.staging_belt.finish(); let index = target.submit( &self.descriptors.device, &self.descriptors.queue, Some(draw_encoder.finish()), frame_output, ); - self.staging_belt.recall(); + self.active_frame.staging_belt.recall(); Some(self.make_queue_sync_handle(target, Some(index), destination, copy_area)) } @@ -1240,3 +1217,42 @@ impl RenderTargetMode { } } } + +pub struct ActiveFrame { + staging_belt: wgpu::util::StagingBelt, + command_encoder: wgpu::CommandEncoder, +} + +impl ActiveFrame { + pub fn new(descriptors: &Descriptors) -> Self { + Self { + command_encoder: descriptors + .device + .create_command_encoder(&Default::default()), + staging_belt: wgpu::util::StagingBelt::new(65536), + } + } + + pub fn submit( + &mut self, + descriptors: &Descriptors, + target: &T, + frame: T::Frame, + ) -> SubmissionIndex { + self.staging_belt.finish(); + let draw_encoder = std::mem::replace( + &mut self.command_encoder, + descriptors + .device + .create_command_encoder(&Default::default()), + ); + let index = target.submit( + &descriptors.device, + &descriptors.queue, + Some(draw_encoder.finish()), + frame, + ); + self.staging_belt.recall(); + index + } +}