Add support for reading from mapped buffers (#1274)
* Add support for mapping buffers for reading. * Add support for reading from a mapped buffer.
This commit is contained in:
parent
18e4fa8cdf
commit
0a39c81be6
@ -9,7 +9,7 @@ use bevy_ecs::{
|
|||||||
use bevy_render::{
|
use bevy_render::{
|
||||||
render_graph::{CommandQueue, Node, ResourceSlots, SystemNode},
|
render_graph::{CommandQueue, Node, ResourceSlots, SystemNode},
|
||||||
renderer::{
|
renderer::{
|
||||||
BufferId, BufferInfo, BufferUsage, RenderContext, RenderResourceBinding,
|
BufferId, BufferInfo, BufferMapMode, BufferUsage, RenderContext, RenderResourceBinding,
|
||||||
RenderResourceBindings, RenderResourceContext,
|
RenderResourceBindings, RenderResourceContext,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -103,7 +103,7 @@ pub fn lights_node_system(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
render_resource_context.map_buffer(staging_buffer);
|
render_resource_context.map_buffer(staging_buffer, BufferMapMode::Write);
|
||||||
} else {
|
} else {
|
||||||
let buffer = render_resource_context.create_buffer(BufferInfo {
|
let buffer = render_resource_context.create_buffer(BufferInfo {
|
||||||
size: max_light_uniform_size,
|
size: max_light_uniform_size,
|
||||||
|
|||||||
@ -2,7 +2,7 @@ use crate::{
|
|||||||
camera::{ActiveCameras, Camera},
|
camera::{ActiveCameras, Camera},
|
||||||
render_graph::{CommandQueue, Node, ResourceSlots, SystemNode},
|
render_graph::{CommandQueue, Node, ResourceSlots, SystemNode},
|
||||||
renderer::{
|
renderer::{
|
||||||
BufferId, BufferInfo, BufferUsage, RenderContext, RenderResourceBinding,
|
BufferId, BufferInfo, BufferMapMode, BufferUsage, RenderContext, RenderResourceBinding,
|
||||||
RenderResourceBindings, RenderResourceContext,
|
RenderResourceBindings, RenderResourceContext,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -87,7 +87,7 @@ pub fn camera_node_system(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let staging_buffer = if let Some(staging_buffer) = state.staging_buffer {
|
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
|
staging_buffer
|
||||||
} else {
|
} else {
|
||||||
let size = std::mem::size_of::<[[f32; 4]; 4]>();
|
let size = std::mem::size_of::<[[f32; 4]; 4]>();
|
||||||
|
|||||||
@ -3,7 +3,7 @@ use crate::{
|
|||||||
prelude::Visible,
|
prelude::Visible,
|
||||||
render_graph::{CommandQueue, Node, ResourceSlots, SystemNode},
|
render_graph::{CommandQueue, Node, ResourceSlots, SystemNode},
|
||||||
renderer::{
|
renderer::{
|
||||||
self, BufferInfo, BufferUsage, RenderContext, RenderResourceBinding,
|
self, BufferInfo, BufferMapMode, BufferUsage, RenderContext, RenderResourceBinding,
|
||||||
RenderResourceBindings, RenderResourceContext, RenderResourceHints,
|
RenderResourceBindings, RenderResourceContext, RenderResourceHints,
|
||||||
},
|
},
|
||||||
texture,
|
texture,
|
||||||
@ -490,7 +490,7 @@ fn render_resources_node_system<T: RenderResources>(
|
|||||||
uniform_buffer_arrays.resize_staging_buffer(render_resource_context);
|
uniform_buffer_arrays.resize_staging_buffer(render_resource_context);
|
||||||
|
|
||||||
if let Some(staging_buffer) = state.uniform_buffer_arrays.staging_buffer {
|
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(
|
render_resource_context.write_mapped_buffer(
|
||||||
staging_buffer,
|
staging_buffer,
|
||||||
0..state.uniform_buffer_arrays.staging_buffer_size as u64,
|
0..state.uniform_buffer_arrays.staging_buffer_size as u64,
|
||||||
@ -703,7 +703,7 @@ fn asset_render_resources_node_system<T: RenderResources + Asset>(
|
|||||||
uniform_buffer_arrays.resize_staging_buffer(render_resource_context);
|
uniform_buffer_arrays.resize_staging_buffer(render_resource_context);
|
||||||
|
|
||||||
if let Some(staging_buffer) = state.uniform_buffer_arrays.staging_buffer {
|
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(
|
render_resource_context.write_mapped_buffer(
|
||||||
staging_buffer,
|
staging_buffer,
|
||||||
0..state.uniform_buffer_arrays.staging_buffer_size as u64,
|
0..state.uniform_buffer_arrays.staging_buffer_size as u64,
|
||||||
|
|||||||
@ -1,7 +1,9 @@
|
|||||||
use super::RenderResourceContext;
|
use super::RenderResourceContext;
|
||||||
use crate::{
|
use crate::{
|
||||||
pipeline::{BindGroupDescriptorId, PipelineDescriptor},
|
pipeline::{BindGroupDescriptorId, PipelineDescriptor},
|
||||||
renderer::{BindGroup, BufferId, BufferInfo, RenderResourceId, SamplerId, TextureId},
|
renderer::{
|
||||||
|
BindGroup, BufferId, BufferInfo, BufferMapMode, RenderResourceId, SamplerId, TextureId,
|
||||||
|
},
|
||||||
shader::{Shader, ShaderError},
|
shader::{Shader, ShaderError},
|
||||||
texture::{SamplerDescriptor, TextureDescriptor},
|
texture::{SamplerDescriptor, TextureDescriptor},
|
||||||
};
|
};
|
||||||
@ -66,7 +68,18 @@ impl RenderResourceContext for HeadlessRenderResourceContext {
|
|||||||
write(&mut buffer, self);
|
write(&mut buffer, self);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn map_buffer(&self, _id: BufferId) {}
|
fn read_mapped_buffer(
|
||||||
|
&self,
|
||||||
|
id: BufferId,
|
||||||
|
_range: Range<u64>,
|
||||||
|
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) {}
|
fn unmap_buffer(&self, _id: BufferId) {}
|
||||||
|
|
||||||
|
|||||||
@ -43,3 +43,9 @@ bitflags::bitflags! {
|
|||||||
const INDIRECT = 256;
|
const INDIRECT = 256;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
|
pub enum BufferMapMode {
|
||||||
|
Read,
|
||||||
|
Write,
|
||||||
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use super::{BufferId, BufferInfo, RenderResource, RenderResourceBinding};
|
use super::{BufferId, BufferInfo, RenderResource, RenderResourceBinding};
|
||||||
use crate::{
|
use crate::{
|
||||||
render_graph::CommandQueue,
|
render_graph::CommandQueue,
|
||||||
renderer::{BufferUsage, RenderContext, RenderResourceContext},
|
renderer::{BufferMapMode, BufferUsage, RenderContext, RenderResourceContext},
|
||||||
};
|
};
|
||||||
use bevy_ecs::{Res, ResMut};
|
use bevy_ecs::{Res, ResMut};
|
||||||
|
|
||||||
@ -115,7 +115,7 @@ impl SharedBuffers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(staging_buffer) = self.staging_buffer {
|
if let Some(staging_buffer) = self.staging_buffer {
|
||||||
render_resource_context.map_buffer(staging_buffer);
|
render_resource_context.map_buffer(staging_buffer, BufferMapMode::Write);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
pipeline::{BindGroupDescriptorId, PipelineDescriptor, PipelineLayout},
|
pipeline::{BindGroupDescriptorId, PipelineDescriptor, PipelineLayout},
|
||||||
renderer::{BindGroup, BufferId, BufferInfo, RenderResourceId, SamplerId, TextureId},
|
renderer::{
|
||||||
|
BindGroup, BufferId, BufferInfo, BufferMapMode, RenderResourceId, SamplerId, TextureId,
|
||||||
|
},
|
||||||
shader::{Shader, ShaderError, ShaderLayout, ShaderStages},
|
shader::{Shader, ShaderError, ShaderLayout, ShaderStages},
|
||||||
texture::{SamplerDescriptor, TextureDescriptor},
|
texture::{SamplerDescriptor, TextureDescriptor},
|
||||||
};
|
};
|
||||||
@ -24,7 +26,13 @@ pub trait RenderResourceContext: Downcast + Send + Sync + 'static {
|
|||||||
range: Range<u64>,
|
range: Range<u64>,
|
||||||
write: &mut dyn FnMut(&mut [u8], &dyn RenderResourceContext),
|
write: &mut dyn FnMut(&mut [u8], &dyn RenderResourceContext),
|
||||||
);
|
);
|
||||||
fn map_buffer(&self, id: BufferId);
|
fn read_mapped_buffer(
|
||||||
|
&self,
|
||||||
|
id: BufferId,
|
||||||
|
range: Range<u64>,
|
||||||
|
read: &dyn Fn(&[u8], &dyn RenderResourceContext),
|
||||||
|
);
|
||||||
|
fn map_buffer(&self, id: BufferId, mode: BufferMapMode);
|
||||||
fn unmap_buffer(&self, id: BufferId);
|
fn unmap_buffer(&self, id: BufferId);
|
||||||
fn create_buffer_with_data(&self, buffer_info: BufferInfo, data: &[u8]) -> BufferId;
|
fn create_buffer_with_data(&self, buffer_info: BufferInfo, data: &[u8]) -> BufferId;
|
||||||
fn create_shader_module(&self, shader_handle: &Handle<Shader>, shaders: &Assets<Shader>);
|
fn create_shader_module(&self, shader_handle: &Handle<Shader>, shaders: &Assets<Shader>);
|
||||||
|
|||||||
@ -9,8 +9,8 @@ use bevy_render::{
|
|||||||
BindGroupDescriptor, BindGroupDescriptorId, BindingShaderStage, PipelineDescriptor,
|
BindGroupDescriptor, BindGroupDescriptorId, BindingShaderStage, PipelineDescriptor,
|
||||||
},
|
},
|
||||||
renderer::{
|
renderer::{
|
||||||
BindGroup, BufferId, BufferInfo, RenderResourceBinding, RenderResourceContext,
|
BindGroup, BufferId, BufferInfo, BufferMapMode, RenderResourceBinding,
|
||||||
RenderResourceId, SamplerId, TextureId,
|
RenderResourceContext, RenderResourceId, SamplerId, TextureId,
|
||||||
},
|
},
|
||||||
shader::{glsl_to_spirv, Shader, ShaderError, ShaderSource},
|
shader::{glsl_to_spirv, Shader, ShaderError, ShaderSource},
|
||||||
texture::{Extent3d, SamplerDescriptor, TextureDescriptor},
|
texture::{Extent3d, SamplerDescriptor, TextureDescriptor},
|
||||||
@ -622,11 +622,30 @@ impl RenderResourceContext for WgpuRenderResourceContext {
|
|||||||
write(&mut data, self);
|
write(&mut data, self);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn map_buffer(&self, id: BufferId) {
|
fn read_mapped_buffer(
|
||||||
|
&self,
|
||||||
|
id: BufferId,
|
||||||
|
range: Range<u64>,
|
||||||
|
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 buffers = self.resources.buffers.read();
|
||||||
let buffer = buffers.get(&id).unwrap();
|
let buffer = buffers.get(&id).unwrap();
|
||||||
let buffer_slice = buffer.slice(..);
|
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);
|
self.device.poll(wgpu::Maintain::Wait);
|
||||||
if future::block_on(data).is_err() {
|
if future::block_on(data).is_err() {
|
||||||
panic!("Failed to map buffer to host.");
|
panic!("Failed to map buffer to host.");
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user