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(crate) descriptors: Arc<Descriptors>,
staging_belt: wgpu::util::StagingBelt,
target: T,
surface: Surface,
meshes: Vec<Mesh>,
@ -57,6 +56,7 @@ pub struct WgpuRenderBackend<T: RenderTarget> {
offscreen_texture_pool: TexturePool,
pub(crate) offscreen_buffer_pool: Arc<BufferPool<wgpu::Buffer, BufferDimensions>>,
dynamic_transforms: DynamicTransforms,
active_frame: ActiveFrame,
}
impl WgpuRenderBackend<SwapChainTarget> {
@ -219,10 +219,10 @@ impl<T: RenderTarget> WgpuRenderBackend<T> {
));
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<T: RenderTarget> WgpuRenderBackend<T> {
offscreen_texture_pool: TexturePool::new(),
offscreen_buffer_pool: Arc::new(offscreen_buffer_pool),
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 {
let texture = as_texture(&entry.handle);
let mut surface = Surface::new(
@ -565,9 +558,9 @@ impl<T: RenderTarget + 'static> RenderBackend for WgpuRenderBackend<T> {
&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<T: RenderTarget + 'static> RenderBackend for WgpuRenderBackend<T> {
&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<T: RenderTarget + 'static> RenderBackend for WgpuRenderBackend<T> {
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<T: RenderTarget + 'static> RenderBackend for WgpuRenderBackend<T> {
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<T: RenderTarget + 'static> RenderBackend for WgpuRenderBackend<T> {
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<T: RenderTarget + 'static> RenderBackend for WgpuRenderBackend<T> {
&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<T: RenderTarget + 'static> RenderBackend for WgpuRenderBackend<T> {
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<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
}
}