From a1837760398827fa15f6cdb76c5858f2f1c23e4e Mon Sep 17 00:00:00 2001 From: Renato Caldas Date: Wed, 20 Jan 2021 23:59:58 +0000 Subject: [PATCH 1/2] Add support for mapping buffers for reading. --- crates/bevy_pbr/src/render_graph/lights_node.rs | 4 ++-- .../src/render_graph/nodes/camera_node.rs | 4 ++-- .../src/render_graph/nodes/render_resources_node.rs | 6 +++--- .../src/renderer/headless_render_resource_context.rs | 6 ++++-- .../src/renderer/render_resource/buffer.rs | 6 ++++++ .../src/renderer/render_resource/shared_buffers.rs | 4 ++-- .../src/renderer/render_resource_context.rs | 6 ++++-- .../src/renderer/wgpu_render_resource_context.rs | 12 ++++++++---- 8 files changed, 31 insertions(+), 17 deletions(-) diff --git a/crates/bevy_pbr/src/render_graph/lights_node.rs b/crates/bevy_pbr/src/render_graph/lights_node.rs index d327d56c2fffe..94ad213f4fbfc 100644 --- a/crates/bevy_pbr/src/render_graph/lights_node.rs +++ b/crates/bevy_pbr/src/render_graph/lights_node.rs @@ -9,7 +9,7 @@ use bevy_ecs::{ use bevy_render::{ render_graph::{CommandQueue, Node, ResourceSlots, SystemNode}, renderer::{ - BufferId, BufferInfo, BufferUsage, RenderContext, RenderResourceBinding, + BufferId, BufferInfo, BufferMapMode, BufferUsage, RenderContext, RenderResourceBinding, RenderResourceBindings, RenderResourceContext, }, }; @@ -103,7 +103,7 @@ pub fn lights_node_system( return; } - render_resource_context.map_buffer(staging_buffer); + render_resource_context.map_buffer(staging_buffer, BufferMapMode::Write); } else { let buffer = render_resource_context.create_buffer(BufferInfo { size: max_light_uniform_size, diff --git a/crates/bevy_render/src/render_graph/nodes/camera_node.rs b/crates/bevy_render/src/render_graph/nodes/camera_node.rs index 245b890d92042..54d119c13a4b4 100644 --- a/crates/bevy_render/src/render_graph/nodes/camera_node.rs +++ b/crates/bevy_render/src/render_graph/nodes/camera_node.rs @@ -2,7 +2,7 @@ use crate::{ camera::{ActiveCameras, Camera}, render_graph::{CommandQueue, Node, ResourceSlots, SystemNode}, renderer::{ - BufferId, BufferInfo, BufferUsage, RenderContext, RenderResourceBinding, + BufferId, BufferInfo, BufferMapMode, BufferUsage, RenderContext, RenderResourceBinding, RenderResourceBindings, RenderResourceContext, }, }; @@ -87,7 +87,7 @@ pub fn camera_node_system( }; let staging_buffer = if let Some(staging_buffer) = state.staging_buffer { - render_resource_context.map_buffer(staging_buffer); + render_resource_context.map_buffer(staging_buffer, BufferMapMode::Write); staging_buffer } else { let size = std::mem::size_of::<[[f32; 4]; 4]>(); diff --git a/crates/bevy_render/src/render_graph/nodes/render_resources_node.rs b/crates/bevy_render/src/render_graph/nodes/render_resources_node.rs index 68422596b07ff..141d8bfc9d757 100644 --- a/crates/bevy_render/src/render_graph/nodes/render_resources_node.rs +++ b/crates/bevy_render/src/render_graph/nodes/render_resources_node.rs @@ -3,7 +3,7 @@ use crate::{ prelude::Visible, render_graph::{CommandQueue, Node, ResourceSlots, SystemNode}, renderer::{ - self, BufferInfo, BufferUsage, RenderContext, RenderResourceBinding, + self, BufferInfo, BufferMapMode, BufferUsage, RenderContext, RenderResourceBinding, RenderResourceBindings, RenderResourceContext, RenderResourceHints, }, texture, @@ -490,7 +490,7 @@ fn render_resources_node_system( uniform_buffer_arrays.resize_staging_buffer(render_resource_context); if let Some(staging_buffer) = state.uniform_buffer_arrays.staging_buffer { - render_resource_context.map_buffer(staging_buffer); + render_resource_context.map_buffer(staging_buffer, BufferMapMode::Write); render_resource_context.write_mapped_buffer( staging_buffer, 0..state.uniform_buffer_arrays.staging_buffer_size as u64, @@ -703,7 +703,7 @@ fn asset_render_resources_node_system( uniform_buffer_arrays.resize_staging_buffer(render_resource_context); if let Some(staging_buffer) = state.uniform_buffer_arrays.staging_buffer { - render_resource_context.map_buffer(staging_buffer); + render_resource_context.map_buffer(staging_buffer, BufferMapMode::Write); render_resource_context.write_mapped_buffer( staging_buffer, 0..state.uniform_buffer_arrays.staging_buffer_size as u64, diff --git a/crates/bevy_render/src/renderer/headless_render_resource_context.rs b/crates/bevy_render/src/renderer/headless_render_resource_context.rs index ed182a51bb1d3..987119849cf2c 100644 --- a/crates/bevy_render/src/renderer/headless_render_resource_context.rs +++ b/crates/bevy_render/src/renderer/headless_render_resource_context.rs @@ -1,7 +1,9 @@ use super::RenderResourceContext; use crate::{ pipeline::{BindGroupDescriptorId, PipelineDescriptor}, - renderer::{BindGroup, BufferId, BufferInfo, RenderResourceId, SamplerId, TextureId}, + renderer::{ + BindGroup, BufferId, BufferInfo, BufferMapMode, RenderResourceId, SamplerId, TextureId, + }, shader::{Shader, ShaderError}, texture::{SamplerDescriptor, TextureDescriptor}, }; @@ -66,7 +68,7 @@ impl RenderResourceContext for HeadlessRenderResourceContext { write(&mut buffer, self); } - fn map_buffer(&self, _id: BufferId) {} + fn map_buffer(&self, _id: BufferId, _mode: BufferMapMode) {} fn unmap_buffer(&self, _id: BufferId) {} diff --git a/crates/bevy_render/src/renderer/render_resource/buffer.rs b/crates/bevy_render/src/renderer/render_resource/buffer.rs index c254e228f17d1..00252ffa9e2d6 100644 --- a/crates/bevy_render/src/renderer/render_resource/buffer.rs +++ b/crates/bevy_render/src/renderer/render_resource/buffer.rs @@ -43,3 +43,9 @@ bitflags::bitflags! { const INDIRECT = 256; } } + +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum BufferMapMode { + Read, + Write, +} diff --git a/crates/bevy_render/src/renderer/render_resource/shared_buffers.rs b/crates/bevy_render/src/renderer/render_resource/shared_buffers.rs index bf2e399e19938..82dfc231bb800 100644 --- a/crates/bevy_render/src/renderer/render_resource/shared_buffers.rs +++ b/crates/bevy_render/src/renderer/render_resource/shared_buffers.rs @@ -1,7 +1,7 @@ use super::{BufferId, BufferInfo, RenderResource, RenderResourceBinding}; use crate::{ render_graph::CommandQueue, - renderer::{BufferUsage, RenderContext, RenderResourceContext}, + renderer::{BufferMapMode, BufferUsage, RenderContext, RenderResourceContext}, }; use bevy_ecs::{Res, ResMut}; @@ -115,7 +115,7 @@ impl SharedBuffers { } if let Some(staging_buffer) = self.staging_buffer { - render_resource_context.map_buffer(staging_buffer); + render_resource_context.map_buffer(staging_buffer, BufferMapMode::Write); } } diff --git a/crates/bevy_render/src/renderer/render_resource_context.rs b/crates/bevy_render/src/renderer/render_resource_context.rs index 365595fac7816..7d6a6018c7686 100644 --- a/crates/bevy_render/src/renderer/render_resource_context.rs +++ b/crates/bevy_render/src/renderer/render_resource_context.rs @@ -1,6 +1,8 @@ use crate::{ pipeline::{BindGroupDescriptorId, PipelineDescriptor, PipelineLayout}, - renderer::{BindGroup, BufferId, BufferInfo, RenderResourceId, SamplerId, TextureId}, + renderer::{ + BindGroup, BufferId, BufferInfo, BufferMapMode, RenderResourceId, SamplerId, TextureId, + }, shader::{Shader, ShaderError, ShaderLayout, ShaderStages}, texture::{SamplerDescriptor, TextureDescriptor}, }; @@ -24,7 +26,7 @@ pub trait RenderResourceContext: Downcast + Send + Sync + 'static { range: Range, write: &mut dyn FnMut(&mut [u8], &dyn RenderResourceContext), ); - fn map_buffer(&self, id: BufferId); + fn map_buffer(&self, id: BufferId, mode: BufferMapMode); fn unmap_buffer(&self, id: BufferId); fn create_buffer_with_data(&self, buffer_info: BufferInfo, data: &[u8]) -> BufferId; fn create_shader_module(&self, shader_handle: &Handle, shaders: &Assets); diff --git a/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs b/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs index bd1be8db72260..27afefff69f82 100644 --- a/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs +++ b/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs @@ -9,8 +9,8 @@ use bevy_render::{ BindGroupDescriptor, BindGroupDescriptorId, BindingShaderStage, PipelineDescriptor, }, renderer::{ - BindGroup, BufferId, BufferInfo, RenderResourceBinding, RenderResourceContext, - RenderResourceId, SamplerId, TextureId, + BindGroup, BufferId, BufferInfo, BufferMapMode, RenderResourceBinding, + RenderResourceContext, RenderResourceId, SamplerId, TextureId, }, shader::{glsl_to_spirv, Shader, ShaderError, ShaderSource}, texture::{Extent3d, SamplerDescriptor, TextureDescriptor}, @@ -622,11 +622,15 @@ impl RenderResourceContext for WgpuRenderResourceContext { write(&mut data, self); } - fn map_buffer(&self, id: BufferId) { + fn map_buffer(&self, id: BufferId, mode: BufferMapMode) { let buffers = self.resources.buffers.read(); let buffer = buffers.get(&id).unwrap(); let buffer_slice = buffer.slice(..); - let data = buffer_slice.map_async(wgpu::MapMode::Write); + let wgpu_mode = match mode { + BufferMapMode::Read => wgpu::MapMode::Read, + BufferMapMode::Write => wgpu::MapMode::Write, + }; + let data = buffer_slice.map_async(wgpu_mode); self.device.poll(wgpu::Maintain::Wait); if future::block_on(data).is_err() { panic!("Failed to map buffer to host."); From ab5620b7eeef45a5c1bbe4e95f0d0027678b646f Mon Sep 17 00:00:00 2001 From: Renato Caldas Date: Thu, 21 Jan 2021 00:06:06 +0000 Subject: [PATCH 2/2] Add support for reading from a mapped buffer. --- .../renderer/headless_render_resource_context.rs | 11 +++++++++++ .../src/renderer/render_resource_context.rs | 6 ++++++ .../src/renderer/wgpu_render_resource_context.rs | 15 +++++++++++++++ 3 files changed, 32 insertions(+) diff --git a/crates/bevy_render/src/renderer/headless_render_resource_context.rs b/crates/bevy_render/src/renderer/headless_render_resource_context.rs index 987119849cf2c..738c065966b1c 100644 --- a/crates/bevy_render/src/renderer/headless_render_resource_context.rs +++ b/crates/bevy_render/src/renderer/headless_render_resource_context.rs @@ -68,6 +68,17 @@ impl RenderResourceContext for HeadlessRenderResourceContext { write(&mut buffer, self); } + fn read_mapped_buffer( + &self, + id: BufferId, + _range: Range, + read: &dyn Fn(&[u8], &dyn RenderResourceContext), + ) { + let size = self.buffer_info.read().get(&id).unwrap().size; + let buffer = vec![0; size]; + read(&buffer, self); + } + fn map_buffer(&self, _id: BufferId, _mode: BufferMapMode) {} fn unmap_buffer(&self, _id: BufferId) {} diff --git a/crates/bevy_render/src/renderer/render_resource_context.rs b/crates/bevy_render/src/renderer/render_resource_context.rs index 7d6a6018c7686..87d3e21a0603c 100644 --- a/crates/bevy_render/src/renderer/render_resource_context.rs +++ b/crates/bevy_render/src/renderer/render_resource_context.rs @@ -26,6 +26,12 @@ pub trait RenderResourceContext: Downcast + Send + Sync + 'static { range: Range, write: &mut dyn FnMut(&mut [u8], &dyn RenderResourceContext), ); + fn read_mapped_buffer( + &self, + id: BufferId, + range: Range, + read: &dyn Fn(&[u8], &dyn RenderResourceContext), + ); fn map_buffer(&self, id: BufferId, mode: BufferMapMode); fn unmap_buffer(&self, id: BufferId); fn create_buffer_with_data(&self, buffer_info: BufferInfo, data: &[u8]) -> BufferId; diff --git a/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs b/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs index 27afefff69f82..6bbaf74eb44b9 100644 --- a/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs +++ b/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs @@ -622,6 +622,21 @@ impl RenderResourceContext for WgpuRenderResourceContext { write(&mut data, self); } + fn read_mapped_buffer( + &self, + id: BufferId, + range: Range, + read: &dyn Fn(&[u8], &dyn RenderResourceContext), + ) { + let buffer = { + let buffers = self.resources.buffers.read(); + buffers.get(&id).unwrap().clone() + }; + let buffer_slice = buffer.slice(range); + let data = buffer_slice.get_mapped_range(); + read(&data, self); + } + fn map_buffer(&self, id: BufferId, mode: BufferMapMode) { let buffers = self.resources.buffers.read(); let buffer = buffers.get(&id).unwrap();