wgpu: Keep a CommandEncoder for the duration of a frame, extract out a struct to hold it with a StagingBelt

This commit is contained in:
Nathan Adams 2024-01-25 16:14:53 +01:00
parent 5ae3be3ac9
commit 1a5dff5d12
1 changed files with 63 additions and 47 deletions

View File

@ -45,7 +45,6 @@ const TEXTURE_READS_BEFORE_PROMOTION: u8 = 5;
pub struct WgpuRenderBackend<T: RenderTarget> { pub struct WgpuRenderBackend<T: RenderTarget> {
pub(crate) descriptors: Arc<Descriptors>, pub(crate) descriptors: Arc<Descriptors>,
staging_belt: wgpu::util::StagingBelt,
target: T, target: T,
surface: Surface, surface: Surface,
meshes: Vec<Mesh>, meshes: Vec<Mesh>,
@ -57,6 +56,7 @@ pub struct WgpuRenderBackend<T: RenderTarget> {
offscreen_texture_pool: TexturePool, offscreen_texture_pool: TexturePool,
pub(crate) offscreen_buffer_pool: Arc<BufferPool<wgpu::Buffer, BufferDimensions>>, pub(crate) offscreen_buffer_pool: Arc<BufferPool<wgpu::Buffer, BufferDimensions>>,
dynamic_transforms: DynamicTransforms, dynamic_transforms: DynamicTransforms,
active_frame: ActiveFrame,
} }
impl WgpuRenderBackend<SwapChainTarget> { impl WgpuRenderBackend<SwapChainTarget> {
@ -219,10 +219,10 @@ impl<T: RenderTarget> WgpuRenderBackend<T> {
)); ));
let transforms = DynamicTransforms::new(&descriptors); let transforms = DynamicTransforms::new(&descriptors);
let active_frame = ActiveFrame::new(&descriptors);
Ok(Self { Ok(Self {
descriptors, descriptors,
staging_belt: wgpu::util::StagingBelt::new(65536),
target, target,
surface, surface,
meshes: Vec::new(), meshes: Vec::new(),
@ -232,6 +232,7 @@ impl<T: RenderTarget> WgpuRenderBackend<T> {
offscreen_texture_pool: TexturePool::new(), offscreen_texture_pool: TexturePool::new(),
offscreen_buffer_pool: Arc::new(offscreen_buffer_pool), offscreen_buffer_pool: Arc::new(offscreen_buffer_pool),
dynamic_transforms: transforms, dynamic_transforms: transforms,
active_frame,
}) })
} }
@ -534,14 +535,6 @@ impl<T: RenderTarget + 'static> RenderBackend for WgpuRenderBackend<T> {
} }
}; };
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 { for entry in cache_entries {
let texture = as_texture(&entry.handle); let texture = as_texture(&entry.handle);
let mut surface = Surface::new( let mut surface = Surface::new(
@ -565,9 +558,9 @@ impl<T: RenderTarget + 'static> RenderBackend for WgpuRenderBackend<T> {
&self.descriptors, &self.descriptors,
&self.meshes, &self.meshes,
entry.commands, entry.commands,
&mut self.staging_belt, &mut self.active_frame.staging_belt,
&self.dynamic_transforms, &self.dynamic_transforms,
&mut draw_encoder, &mut self.active_frame.command_encoder,
LayerRef::None, LayerRef::None,
&mut self.offscreen_texture_pool, &mut self.offscreen_texture_pool,
); );
@ -589,18 +582,18 @@ impl<T: RenderTarget + 'static> RenderBackend for WgpuRenderBackend<T> {
&self.descriptors, &self.descriptors,
&self.meshes, &self.meshes,
entry.commands, entry.commands,
&mut self.staging_belt, &mut self.active_frame.staging_belt,
&self.dynamic_transforms, &self.dynamic_transforms,
&mut draw_encoder, &mut self.active_frame.command_encoder,
LayerRef::None, LayerRef::None,
&mut self.offscreen_texture_pool, &mut self.offscreen_texture_pool,
); );
for filter in entry.filters { for filter in entry.filters {
target = self.descriptors.filters.apply( target = self.descriptors.filters.apply(
&self.descriptors, &self.descriptors,
&mut draw_encoder, &mut self.active_frame.command_encoder,
&mut self.offscreen_texture_pool, &mut self.offscreen_texture_pool,
&mut self.staging_belt, &mut self.active_frame.staging_belt,
FilterSource::for_entire_texture(target.color_texture()), FilterSource::for_entire_texture(target.color_texture()),
filter, filter,
); );
@ -614,7 +607,7 @@ impl<T: RenderTarget + 'static> RenderBackend for WgpuRenderBackend<T> {
target.whole_frame_bind_group(&self.descriptors), target.whole_frame_bind_group(&self.descriptors),
target.globals(), target.globals(),
target.color_texture().sample_count(), target.color_texture().sample_count(),
&mut draw_encoder, &mut self.active_frame.command_encoder,
); );
} }
} }
@ -628,23 +621,18 @@ impl<T: RenderTarget + 'static> RenderBackend for WgpuRenderBackend<T> {
a: f64::from(clear.a) / 255.0, a: f64::from(clear.a) / 255.0,
}), }),
&self.descriptors, &self.descriptors,
&mut self.staging_belt, &mut self.active_frame.staging_belt,
&self.dynamic_transforms, &self.dynamic_transforms,
&mut draw_encoder, &mut self.active_frame.command_encoder,
&self.meshes, &self.meshes,
commands, commands,
LayerRef::None, LayerRef::None,
&mut self.texture_pool, &mut self.texture_pool,
); );
self.staging_belt.finish(); self.active_frame.staging_belt.finish();
self.target.submit( self.active_frame
&self.descriptors.device, .submit(&self.descriptors, &self.target, frame_output);
&self.descriptors.queue,
Some(draw_encoder.finish()),
frame_output,
);
self.staging_belt.recall();
self.offscreen_texture_pool = TexturePool::new(); self.offscreen_texture_pool = TexturePool::new();
} }
@ -786,33 +774,22 @@ impl<T: RenderTarget + 'static> RenderBackend for WgpuRenderBackend<T> {
texture.texture.height(), texture.texture.height(),
wgpu::TextureFormat::Rgba8Unorm, 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( surface.draw_commands_and_copy_to(
frame_output.view(), frame_output.view(),
RenderTargetMode::FreshWithTexture(target.get_texture()), RenderTargetMode::FreshWithTexture(target.get_texture()),
&self.descriptors, &self.descriptors,
&mut self.staging_belt, &mut self.active_frame.staging_belt,
&self.dynamic_transforms, &self.dynamic_transforms,
&mut draw_encoder, &mut self.active_frame.command_encoder,
&self.meshes, &self.meshes,
commands, commands,
LayerRef::Current, LayerRef::Current,
&mut self.offscreen_texture_pool, &mut self.offscreen_texture_pool,
); );
self.staging_belt.finish();
let index = target.submit( let index = self
&self.descriptors.device, .active_frame
&self.descriptors.queue, .submit(&self.descriptors, &target, frame_output);
Some(draw_encoder.finish()),
frame_output,
);
self.staging_belt.recall();
Some(self.make_queue_sync_handle(target, Some(index), handle, bounds)) Some(self.make_queue_sync_handle(target, Some(index), handle, bounds))
} }
@ -878,7 +855,7 @@ impl<T: RenderTarget + 'static> RenderBackend for WgpuRenderBackend<T> {
&self.descriptors, &self.descriptors,
&mut draw_encoder, &mut draw_encoder,
&mut self.offscreen_texture_pool, &mut self.offscreen_texture_pool,
&mut self.staging_belt, &mut self.active_frame.staging_belt,
FilterSource { FilterSource {
texture: &source_texture.texture, texture: &source_texture.texture,
point: source_point, point: source_point,
@ -909,14 +886,14 @@ impl<T: RenderTarget + 'static> RenderBackend for WgpuRenderBackend<T> {
depth_or_array_layers: 1, depth_or_array_layers: 1,
}, },
); );
self.staging_belt.finish(); self.active_frame.staging_belt.finish();
let index = target.submit( let index = target.submit(
&self.descriptors.device, &self.descriptors.device,
&self.descriptors.queue, &self.descriptors.queue,
Some(draw_encoder.finish()), Some(draw_encoder.finish()),
frame_output, frame_output,
); );
self.staging_belt.recall(); self.active_frame.staging_belt.recall();
Some(self.make_queue_sync_handle(target, Some(index), destination, copy_area)) 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<T: RenderTarget>(
&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
}
}