use staging buffer and add command encoder for resize events

This commit is contained in:
Carter Anderson 2020-02-04 22:07:02 -08:00
parent c3a388b1b9
commit 48e8967acc
2 changed files with 51 additions and 20 deletions

View file

@ -15,24 +15,29 @@ pub trait ResourceProvider {
pub struct CameraResourceProvider;
impl ResourceProvider for CameraResourceProvider {
fn initialize(&mut self, _renderer: &mut dyn Renderer, _world: &mut World) {
// TODO: create real buffer here
fn initialize(&mut self, renderer: &mut dyn Renderer, _world: &mut World) {
renderer.create_buffer(
resource_name::uniform::CAMERA,
std::mem::size_of::<[[f32; 4]; 4]>() as u64,
wgpu::BufferUsage::COPY_DST | wgpu::BufferUsage::UNIFORM,
);
}
fn update(&mut self, _renderer: &mut dyn Renderer, _world: &mut World) {}
fn resize(&mut self, renderer: &mut dyn Renderer, world: &mut World, width: u32, height: u32) {
let matrix_size = std::mem::size_of::<[[f32; 4]; 4]>();
for (mut camera, local_to_world, _) in
<(Write<Camera>, Read<LocalToWorld>, Read<ActiveCamera>)>::query().iter_mut(world)
{
// TODO: consider using staging buffer
camera.update(width, height);
let camera_matrix: [[f32; 4]; 4] =
(camera.view_matrix * local_to_world.0).to_cols_array_2d();
renderer.create_buffer_with_data(
resource_name::uniform::CAMERA,
camera_matrix.as_bytes(),
wgpu::BufferUsage::UNIFORM,
);
renderer.create_buffer_mapped("camera_tmp", matrix_size, wgpu::BufferUsage::COPY_SRC, &mut |data| {
data[0..matrix_size].copy_from_slice(camera_matrix.as_bytes());
});
renderer.copy_buffer_to_buffer("camera_tmp", 0, resource_name::uniform::CAMERA, 0, matrix_size as u64);
}
}
}
}

View file

@ -441,10 +441,11 @@ impl Renderer for WgpuRenderer {
};
self.surface = Some(surface);
self.resize(world, render_graph, window_size.width, window_size.height);
for resource_provider in render_graph.resource_providers.iter_mut() {
resource_provider.initialize(self, world);
}
self.resize(world, render_graph, window_size.width, window_size.height);
}
fn resize(
@ -454,6 +455,10 @@ impl Renderer for WgpuRenderer {
width: u32,
height: u32,
) {
self.encoder = Some(
self.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 }),
);
self.swap_chain_descriptor.width = width;
self.swap_chain_descriptor.height = height;
let swap_chain = self
@ -465,14 +470,19 @@ impl Renderer for WgpuRenderer {
for resource_provider in render_graph.resource_providers.iter_mut() {
resource_provider.resize(self, world, width, height);
}
// consume current encoder
let command_buffer = self.encoder.take().unwrap().finish();
self.queue.submit(&[command_buffer]);
}
fn process_render_graph(&mut self, render_graph: &mut RenderGraph, world: &mut World) {
// TODO: this self.encoder handoff is a bit gross, but its here to give resource providers access to buffer copies without
// exposing the wgpu renderer internals to ResourceProvider traits. if this can be made cleaner that would be pretty cool.
self.encoder = Some(self
.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 }));
self.encoder = Some(
self.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 }),
);
for resource_provider in render_graph.resource_providers.iter_mut() {
resource_provider.update(self, world);
@ -485,7 +495,6 @@ impl Renderer for WgpuRenderer {
.get_next_texture()
.expect("Timeout when acquiring next swap chain texture");
// self.setup_dynamic_entity_shader_uniforms(world, render_graph, &mut encoder);
// setup, pipelines, bind groups, and resources
@ -579,11 +588,17 @@ impl Renderer for WgpuRenderer {
self.buffers.remove(name);
}
fn create_buffer_mapped(&mut self, name: &str, size: usize, buffer_usage: wgpu::BufferUsage, setup_data: &mut dyn FnMut(&mut [u8])) {
fn create_buffer_mapped(
&mut self,
name: &str,
size: usize,
buffer_usage: wgpu::BufferUsage,
setup_data: &mut dyn FnMut(&mut [u8]),
) {
let mut mapped = self.device.create_buffer_mapped(size, buffer_usage);
setup_data(&mut mapped.data);
let buffer = mapped.finish();
self.add_resource_info(
name,
ResourceInfo::Buffer {
@ -595,7 +610,14 @@ impl Renderer for WgpuRenderer {
self.buffers.insert(name.to_string(), buffer);
}
fn copy_buffer_to_buffer(&mut self, source_buffer: &str, source_offset: u64, destination_buffer: &str, destination_offset: u64, size: u64) {
fn copy_buffer_to_buffer(
&mut self,
source_buffer: &str,
source_offset: u64,
destination_buffer: &str,
destination_offset: u64,
size: u64,
) {
let source = self.buffers.get(source_buffer).unwrap();
let destination = self.buffers.get(destination_buffer).unwrap();
let encoder = self.encoder.as_mut().unwrap();
@ -605,12 +627,16 @@ impl Renderer for WgpuRenderer {
self.dynamic_uniform_buffer_info.get(name)
}
fn get_dynamic_uniform_buffer_info_mut(&mut self, name: &str) -> Option<&mut DynamicUniformBufferInfo> {
fn get_dynamic_uniform_buffer_info_mut(
&mut self,
name: &str,
) -> Option<&mut DynamicUniformBufferInfo> {
self.dynamic_uniform_buffer_info.get_mut(name)
}
fn add_dynamic_uniform_buffer_info(&mut self, name: &str, info: DynamicUniformBufferInfo) {
self.dynamic_uniform_buffer_info.insert(name.to_string(), info);
self.dynamic_uniform_buffer_info
.insert(name.to_string(), info);
}
}
@ -667,7 +693,7 @@ impl<'a, 'b, 'c, 'd> RenderPass for WgpuRenderPass<'a, 'b, 'c, 'd> {
if !dynamic {
continue;
}
// PERF: This hashmap get is pretty expensive (10 fps per 10000 entities)
if let Some(dynamic_uniform_buffer_info) =
self.renderer.dynamic_uniform_buffer_info.get(&binding.name)