render: add direct buffer mapping/unmapping
This commit is contained in:
parent
cb1ffb42c4
commit
6d58a5a033
@ -58,10 +58,8 @@ impl SystemNode for LightsNode {
|
||||
LightsNodeSystemState {
|
||||
command_queue: self.command_queue.clone(),
|
||||
max_lights: self.max_lights,
|
||||
tmp_count_buffer: None,
|
||||
tmp_light_buffer: None,
|
||||
light_buffer: None,
|
||||
lights_are_dirty: true,
|
||||
staging_buffer: None,
|
||||
},
|
||||
);
|
||||
system
|
||||
@ -71,10 +69,7 @@ impl SystemNode for LightsNode {
|
||||
#[derive(Default)]
|
||||
pub struct LightsNodeSystemState {
|
||||
light_buffer: Option<BufferId>,
|
||||
lights_are_dirty: bool,
|
||||
// TODO: merge these
|
||||
tmp_count_buffer: Option<BufferId>,
|
||||
tmp_light_buffer: Option<BufferId>,
|
||||
staging_buffer: Option<BufferId>,
|
||||
command_queue: CommandQueue,
|
||||
max_lights: usize,
|
||||
}
|
||||
@ -82,22 +77,30 @@ pub struct LightsNodeSystemState {
|
||||
pub fn lights_node_system(
|
||||
mut state: Local<LightsNodeSystemState>,
|
||||
render_resource_context: Res<Box<dyn RenderResourceContext>>,
|
||||
// TODO: this write on RenderResourceAssignments will prevent this system from running in parallel with other systems that do the same
|
||||
// TODO: this write on RenderResourceBindings will prevent this system from running in parallel with other systems that do the same
|
||||
mut render_resource_bindings: ResMut<RenderResourceBindings>,
|
||||
mut query: Query<(&Light, &Transform, &Translation)>,
|
||||
) {
|
||||
let state = &mut state;
|
||||
if !state.lights_are_dirty {
|
||||
return;
|
||||
}
|
||||
|
||||
let render_resource_context = &**render_resource_context;
|
||||
if state.light_buffer.is_none() {
|
||||
let light_uniform_size =
|
||||
std::mem::size_of::<LightCount>() + state.max_lights * std::mem::size_of::<LightRaw>();
|
||||
|
||||
let light_count = query.iter().iter().count();
|
||||
let size = std::mem::size_of::<LightRaw>();
|
||||
let light_count_size = std::mem::size_of::<LightCount>();
|
||||
let light_array_size = size * light_count;
|
||||
let light_array_max_size = size * state.max_lights;
|
||||
let current_light_uniform_size = light_count_size + light_array_size;
|
||||
let max_light_uniform_size = light_count_size + light_array_max_size;
|
||||
|
||||
if let Some(staging_buffer) = state.staging_buffer {
|
||||
if light_count == 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
render_resource_context.map_buffer(staging_buffer);
|
||||
} else {
|
||||
let buffer = render_resource_context.create_buffer(BufferInfo {
|
||||
size: light_uniform_size,
|
||||
size: max_light_uniform_size,
|
||||
buffer_usage: BufferUsage::UNIFORM | BufferUsage::COPY_SRC | BufferUsage::COPY_DST,
|
||||
..Default::default()
|
||||
});
|
||||
@ -105,74 +108,45 @@ pub fn lights_node_system(
|
||||
uniform::LIGHTS,
|
||||
RenderResourceBinding::Buffer {
|
||||
buffer,
|
||||
range: 0..light_uniform_size as u64,
|
||||
range: 0..max_light_uniform_size as u64,
|
||||
dynamic_index: None,
|
||||
},
|
||||
);
|
||||
state.light_buffer = Some(buffer);
|
||||
|
||||
let staging_buffer = render_resource_context.create_buffer(BufferInfo {
|
||||
size: max_light_uniform_size,
|
||||
buffer_usage: BufferUsage::COPY_SRC | BufferUsage::MAP_WRITE,
|
||||
mapped_at_creation: true,
|
||||
});
|
||||
state.staging_buffer = Some(staging_buffer);
|
||||
}
|
||||
|
||||
let light_count = query.iter().iter().count();
|
||||
|
||||
if light_count == 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
state.lights_are_dirty = false;
|
||||
let size = std::mem::size_of::<LightRaw>();
|
||||
let total_size = size * light_count;
|
||||
let light_count_size = std::mem::size_of::<LightCount>();
|
||||
|
||||
if let Some(old_tmp_light_buffer) = state.tmp_light_buffer {
|
||||
render_resource_context.remove_buffer(old_tmp_light_buffer);
|
||||
}
|
||||
|
||||
if let Some(old_tmp_count_buffer) = state.tmp_count_buffer {
|
||||
render_resource_context.remove_buffer(old_tmp_count_buffer);
|
||||
}
|
||||
|
||||
state.tmp_light_buffer = Some(render_resource_context.create_buffer_mapped(
|
||||
BufferInfo {
|
||||
size: total_size,
|
||||
buffer_usage: BufferUsage::COPY_SRC,
|
||||
..Default::default()
|
||||
},
|
||||
let staging_buffer = state.staging_buffer.unwrap();
|
||||
render_resource_context.write_mapped_buffer(
|
||||
staging_buffer,
|
||||
0..current_light_uniform_size as u64,
|
||||
&mut |data, _renderer| {
|
||||
// light count
|
||||
data[0..light_count_size].copy_from_slice([light_count as u32, 0, 0, 0].as_bytes());
|
||||
|
||||
// light array
|
||||
for ((light, transform, translation), slot) in
|
||||
query.iter().iter().zip(data.chunks_exact_mut(size))
|
||||
query.iter().iter().zip(data[light_count_size..current_light_uniform_size].chunks_exact_mut(size))
|
||||
{
|
||||
slot.copy_from_slice(
|
||||
LightRaw::from(&light, &transform.value, &translation).as_bytes(),
|
||||
);
|
||||
}
|
||||
},
|
||||
));
|
||||
state.tmp_count_buffer = Some(render_resource_context.create_buffer_mapped(
|
||||
BufferInfo {
|
||||
size: light_count_size,
|
||||
buffer_usage: BufferUsage::COPY_SRC,
|
||||
..Default::default()
|
||||
},
|
||||
&mut |data, _renderer| {
|
||||
data.copy_from_slice([light_count as u32, 0, 0, 0].as_bytes());
|
||||
},
|
||||
));
|
||||
let tmp_count_buffer = state.tmp_count_buffer.unwrap();
|
||||
);
|
||||
render_resource_context.unmap_buffer(staging_buffer);
|
||||
let light_buffer = state.light_buffer.unwrap();
|
||||
state.command_queue.copy_buffer_to_buffer(
|
||||
tmp_count_buffer,
|
||||
staging_buffer,
|
||||
0,
|
||||
light_buffer,
|
||||
0,
|
||||
light_count_size as u64,
|
||||
);
|
||||
|
||||
let tmp_light_buffer = state.tmp_light_buffer.unwrap();
|
||||
state.command_queue.copy_buffer_to_buffer(
|
||||
tmp_light_buffer,
|
||||
0,
|
||||
light_buffer,
|
||||
light_count_size as u64,
|
||||
total_size as u64,
|
||||
max_light_uniform_size as u64,
|
||||
);
|
||||
}
|
||||
|
||||
@ -51,6 +51,7 @@ impl SystemNode for CameraNode {
|
||||
camera_name: self.camera_name.clone(),
|
||||
command_queue: self.command_queue.clone(),
|
||||
camera_buffer: None,
|
||||
staging_buffer: None,
|
||||
},
|
||||
);
|
||||
system
|
||||
@ -62,6 +63,7 @@ pub struct CameraNodeState {
|
||||
command_queue: CommandQueue,
|
||||
camera_name: Cow<'static, str>,
|
||||
camera_buffer: Option<BufferId>,
|
||||
staging_buffer: Option<BufferId>,
|
||||
}
|
||||
|
||||
pub fn camera_node_system(
|
||||
@ -74,27 +76,7 @@ pub fn camera_node_system(
|
||||
query: Query<(&Camera, &Transform)>,
|
||||
) {
|
||||
let render_resource_context = &**render_resource_context;
|
||||
state.camera_buffer = Some(match state.camera_buffer {
|
||||
Some(buffer) => buffer,
|
||||
None => {
|
||||
let size = std::mem::size_of::<[[f32; 4]; 4]>();
|
||||
let buffer = render_resource_context.create_buffer(BufferInfo {
|
||||
size,
|
||||
buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM,
|
||||
..Default::default()
|
||||
});
|
||||
render_resource_bindings.set(
|
||||
&state.camera_name,
|
||||
RenderResourceBinding::Buffer {
|
||||
buffer,
|
||||
range: 0..size as u64,
|
||||
dynamic_index: None,
|
||||
},
|
||||
);
|
||||
state.camera_buffer = Some(buffer);
|
||||
buffer
|
||||
}
|
||||
});
|
||||
|
||||
let (camera, transform) = if let Some(camera_entity) = active_cameras.get(&state.camera_name) {
|
||||
(
|
||||
query.get::<Camera>(camera_entity).unwrap(),
|
||||
@ -104,24 +86,55 @@ pub fn camera_node_system(
|
||||
return;
|
||||
};
|
||||
|
||||
let staging_buffer = if let Some(staging_buffer) = state.staging_buffer {
|
||||
render_resource_context.map_buffer(staging_buffer);
|
||||
staging_buffer
|
||||
} else {
|
||||
let size = std::mem::size_of::<[[f32; 4]; 4]>();
|
||||
let buffer = render_resource_context.create_buffer(BufferInfo {
|
||||
size,
|
||||
buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM,
|
||||
..Default::default()
|
||||
});
|
||||
render_resource_bindings.set(
|
||||
&state.camera_name,
|
||||
RenderResourceBinding::Buffer {
|
||||
buffer,
|
||||
range: 0..size as u64,
|
||||
dynamic_index: None,
|
||||
},
|
||||
);
|
||||
state.camera_buffer = Some(buffer);
|
||||
|
||||
let staging_buffer = render_resource_context.create_buffer(BufferInfo {
|
||||
size,
|
||||
buffer_usage: BufferUsage::COPY_SRC | BufferUsage::MAP_WRITE,
|
||||
mapped_at_creation: true,
|
||||
});
|
||||
|
||||
state.staging_buffer = Some(staging_buffer);
|
||||
staging_buffer
|
||||
};
|
||||
|
||||
let matrix_size = std::mem::size_of::<[[f32; 4]; 4]>();
|
||||
let camera_matrix: [f32; 16] =
|
||||
(camera.projection_matrix * transform.value.inverse()).to_cols_array();
|
||||
|
||||
let tmp_buffer = render_resource_context.create_buffer_mapped(
|
||||
BufferInfo {
|
||||
size: matrix_size,
|
||||
buffer_usage: BufferUsage::COPY_SRC,
|
||||
..Default::default()
|
||||
},
|
||||
render_resource_context.write_mapped_buffer(
|
||||
staging_buffer,
|
||||
0..matrix_size as u64,
|
||||
&mut |data, _renderer| {
|
||||
data[0..matrix_size].copy_from_slice(camera_matrix.as_bytes());
|
||||
},
|
||||
);
|
||||
render_resource_context.unmap_buffer(staging_buffer);
|
||||
|
||||
let camera_buffer = state.camera_buffer.unwrap();
|
||||
state
|
||||
.command_queue
|
||||
.copy_buffer_to_buffer(tmp_buffer, 0, camera_buffer, 0, matrix_size as u64);
|
||||
state.command_queue.free_buffer(tmp_buffer);
|
||||
state.command_queue.copy_buffer_to_buffer(
|
||||
staging_buffer,
|
||||
0,
|
||||
camera_buffer,
|
||||
0,
|
||||
matrix_size as u64,
|
||||
);
|
||||
}
|
||||
|
||||
@ -63,6 +63,8 @@ where
|
||||
T: render_resource::RenderResources,
|
||||
{
|
||||
uniform_arrays: Vec<Option<(String, BufferArrayStatus)>>,
|
||||
staging_buffer: Option<BufferId>,
|
||||
staging_buffer_size: usize,
|
||||
_marker: PhantomData<T>,
|
||||
}
|
||||
|
||||
@ -73,6 +75,8 @@ where
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
uniform_arrays: Default::default(),
|
||||
staging_buffer: Default::default(),
|
||||
staging_buffer_size: 0,
|
||||
_marker: Default::default(),
|
||||
}
|
||||
}
|
||||
@ -166,6 +170,7 @@ where
|
||||
let buffer = render_resource_context.create_buffer(BufferInfo {
|
||||
size: total_size,
|
||||
buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM,
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
buffer_array_status.current_item_capacity = new_capacity;
|
||||
@ -181,7 +186,7 @@ where
|
||||
buffer_array_status.buffer = Some(buffer);
|
||||
}
|
||||
}
|
||||
fn update_staging_buffer_offsets(&mut self) -> usize {
|
||||
fn update_staging_buffer(&mut self, render_resource_context: &dyn RenderResourceContext) {
|
||||
let mut size = 0;
|
||||
for dynamic_buffer_array_status in self.uniform_arrays.iter_mut() {
|
||||
if let Some((_name, ref mut buffer_array_status)) = dynamic_buffer_array_status {
|
||||
@ -190,7 +195,24 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
size
|
||||
if self.staging_buffer_size != size {
|
||||
if let Some(staging_buffer) = self.staging_buffer {
|
||||
render_resource_context.remove_buffer(staging_buffer);
|
||||
}
|
||||
|
||||
if size > 0 {
|
||||
let staging_buffer = render_resource_context.create_buffer(BufferInfo {
|
||||
buffer_usage: BufferUsage::COPY_SRC | BufferUsage::MAP_WRITE,
|
||||
size,
|
||||
..Default::default()
|
||||
});
|
||||
self.staging_buffer = Some(staging_buffer);
|
||||
} else {
|
||||
self.staging_buffer = None;
|
||||
}
|
||||
|
||||
self.staging_buffer_size = size;
|
||||
}
|
||||
}
|
||||
|
||||
fn setup_uniform_buffer_resources(
|
||||
@ -412,7 +434,9 @@ fn render_resources_node_system<T: RenderResources>(
|
||||
state
|
||||
.uniform_buffer_arrays
|
||||
.setup_buffer_arrays(render_resource_context, state.dynamic_uniforms);
|
||||
let staging_buffer_size = state.uniform_buffer_arrays.update_staging_buffer_offsets();
|
||||
state
|
||||
.uniform_buffer_arrays
|
||||
.update_staging_buffer(render_resource_context);
|
||||
|
||||
for (uniforms, draw, render_pipelines) in &mut query.iter() {
|
||||
if !draw.is_visible {
|
||||
@ -426,28 +450,11 @@ fn render_resources_node_system<T: RenderResources>(
|
||||
)
|
||||
}
|
||||
|
||||
if staging_buffer_size == 0 {
|
||||
let mut staging_buffer: [u8; 0] = [];
|
||||
for (uniforms, draw, render_pipelines) in &mut query.iter() {
|
||||
if !draw.is_visible {
|
||||
return;
|
||||
}
|
||||
|
||||
state.uniform_buffer_arrays.setup_uniform_buffer_resources(
|
||||
&uniforms,
|
||||
state.dynamic_uniforms,
|
||||
render_resource_context,
|
||||
&mut render_pipelines.bindings,
|
||||
&mut staging_buffer,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
let staging_buffer = render_resource_context.create_buffer_mapped(
|
||||
BufferInfo {
|
||||
buffer_usage: BufferUsage::COPY_SRC,
|
||||
size: staging_buffer_size,
|
||||
..Default::default()
|
||||
},
|
||||
if let Some(staging_buffer) = state.uniform_buffer_arrays.staging_buffer {
|
||||
render_resource_context.map_buffer(staging_buffer);
|
||||
render_resource_context.write_mapped_buffer(
|
||||
staging_buffer,
|
||||
0..state.uniform_buffer_arrays.staging_buffer_size as u64,
|
||||
&mut |mut staging_buffer, _render_resource_context| {
|
||||
for (uniforms, draw, render_pipelines) in &mut query.iter() {
|
||||
if !draw.is_visible {
|
||||
@ -464,11 +471,27 @@ fn render_resources_node_system<T: RenderResources>(
|
||||
}
|
||||
},
|
||||
);
|
||||
render_resource_context.unmap_buffer(staging_buffer);
|
||||
|
||||
state
|
||||
.uniform_buffer_arrays
|
||||
.copy_staging_buffer_to_final_buffers(&mut state.command_queue, staging_buffer);
|
||||
state.command_queue.free_buffer(staging_buffer);
|
||||
} else {
|
||||
// TODO: can we just remove this?
|
||||
let mut staging_buffer: [u8; 0] = [];
|
||||
for (uniforms, draw, render_pipelines) in &mut query.iter() {
|
||||
if !draw.is_visible {
|
||||
return;
|
||||
}
|
||||
|
||||
state.uniform_buffer_arrays.setup_uniform_buffer_resources(
|
||||
&uniforms,
|
||||
state.dynamic_uniforms,
|
||||
render_resource_context,
|
||||
&mut render_pipelines.bindings,
|
||||
&mut staging_buffer,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -576,7 +599,7 @@ fn asset_render_resources_node_system<T: RenderResources>(
|
||||
state
|
||||
.uniform_buffer_arrays
|
||||
.setup_buffer_arrays(render_resource_context, state.dynamic_uniforms);
|
||||
let staging_buffer_size = state.uniform_buffer_arrays.update_staging_buffer_offsets();
|
||||
state.uniform_buffer_arrays.update_staging_buffer(render_resource_context);
|
||||
|
||||
for asset_handle in modified_assets.iter() {
|
||||
let asset = assets.get(&asset_handle).expect(EXPECT_ASSET_MESSAGE);
|
||||
@ -589,28 +612,11 @@ fn asset_render_resources_node_system<T: RenderResources>(
|
||||
);
|
||||
}
|
||||
|
||||
if staging_buffer_size == 0 {
|
||||
let mut staging_buffer: [u8; 0] = [];
|
||||
for asset_handle in modified_assets.iter() {
|
||||
let asset = assets.get(&asset_handle).expect(EXPECT_ASSET_MESSAGE);
|
||||
let mut render_resource_bindings =
|
||||
asset_render_resource_bindings.get_or_insert_mut(*asset_handle);
|
||||
// TODO: only setup buffer if we haven't seen this handle before
|
||||
state.uniform_buffer_arrays.setup_uniform_buffer_resources(
|
||||
&asset,
|
||||
state.dynamic_uniforms,
|
||||
render_resource_context,
|
||||
&mut render_resource_bindings,
|
||||
&mut staging_buffer,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
let staging_buffer = render_resource_context.create_buffer_mapped(
|
||||
BufferInfo {
|
||||
buffer_usage: BufferUsage::COPY_SRC,
|
||||
size: staging_buffer_size,
|
||||
..Default::default()
|
||||
},
|
||||
if let Some(staging_buffer) = state.uniform_buffer_arrays.staging_buffer {
|
||||
render_resource_context.map_buffer(staging_buffer);
|
||||
render_resource_context.write_mapped_buffer(
|
||||
staging_buffer,
|
||||
0..state.uniform_buffer_arrays.staging_buffer_size as u64,
|
||||
&mut |mut staging_buffer, _render_resource_context| {
|
||||
for asset_handle in modified_assets.iter() {
|
||||
let asset = assets.get(&asset_handle).expect(EXPECT_ASSET_MESSAGE);
|
||||
@ -627,11 +633,26 @@ fn asset_render_resources_node_system<T: RenderResources>(
|
||||
}
|
||||
},
|
||||
);
|
||||
render_resource_context.unmap_buffer(staging_buffer);
|
||||
|
||||
state
|
||||
.uniform_buffer_arrays
|
||||
.copy_staging_buffer_to_final_buffers(&mut state.command_queue, staging_buffer);
|
||||
state.command_queue.free_buffer(staging_buffer);
|
||||
} else {
|
||||
let mut staging_buffer: [u8; 0] = [];
|
||||
for asset_handle in modified_assets.iter() {
|
||||
let asset = assets.get(&asset_handle).expect(EXPECT_ASSET_MESSAGE);
|
||||
let mut render_resource_bindings =
|
||||
asset_render_resource_bindings.get_or_insert_mut(*asset_handle);
|
||||
// TODO: only setup buffer if we haven't seen this handle before
|
||||
state.uniform_buffer_arrays.setup_uniform_buffer_resources(
|
||||
&asset,
|
||||
state.dynamic_uniforms,
|
||||
render_resource_context,
|
||||
&mut render_resource_bindings,
|
||||
&mut staging_buffer,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
for (asset_handle, _draw, render_pipelines) in &mut query.iter() {
|
||||
|
||||
@ -13,6 +13,7 @@ impl BufferId {
|
||||
pub struct BufferInfo {
|
||||
pub size: usize,
|
||||
pub buffer_usage: BufferUsage,
|
||||
pub mapped_at_creation: bool,
|
||||
}
|
||||
|
||||
impl Default for BufferInfo {
|
||||
@ -20,6 +21,7 @@ impl Default for BufferInfo {
|
||||
BufferInfo {
|
||||
size: 0,
|
||||
buffer_usage: BufferUsage::empty(),
|
||||
mapped_at_creation: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,19 +30,26 @@ impl SharedBuffers {
|
||||
) -> Option<RenderResourceBinding> {
|
||||
if let Some(size) = render_resource.buffer_byte_len() {
|
||||
// PERF: this buffer will be slow
|
||||
let staging_buffer = self.render_resource_context.create_buffer_mapped(
|
||||
BufferInfo {
|
||||
size,
|
||||
buffer_usage: BufferUsage::COPY_SRC,
|
||||
},
|
||||
let staging_buffer = self.render_resource_context.create_buffer(BufferInfo {
|
||||
size,
|
||||
buffer_usage: BufferUsage::COPY_SRC | BufferUsage::MAP_WRITE,
|
||||
mapped_at_creation: true,
|
||||
});
|
||||
|
||||
self.render_resource_context.write_mapped_buffer(
|
||||
staging_buffer,
|
||||
0..size as u64,
|
||||
&mut |data, _renderer| {
|
||||
render_resource.write_buffer_bytes(data);
|
||||
},
|
||||
);
|
||||
|
||||
self.render_resource_context.unmap_buffer(staging_buffer);
|
||||
|
||||
let destination_buffer = self.render_resource_context.create_buffer(BufferInfo {
|
||||
size,
|
||||
buffer_usage: BufferUsage::COPY_DST | buffer_usage,
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
let mut command_queue = self.command_queue.write().unwrap();
|
||||
|
||||
@ -9,6 +9,7 @@ use bevy_asset::{Assets, Handle, HandleUntyped};
|
||||
use bevy_window::{Window, WindowId};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
ops::Range,
|
||||
sync::{Arc, RwLock},
|
||||
};
|
||||
|
||||
@ -52,15 +53,18 @@ impl RenderResourceContext for HeadlessRenderResourceContext {
|
||||
self.add_buffer_info(buffer, buffer_info);
|
||||
buffer
|
||||
}
|
||||
fn create_buffer_mapped(
|
||||
fn write_mapped_buffer(
|
||||
&self,
|
||||
buffer_info: BufferInfo,
|
||||
setup_data: &mut dyn FnMut(&mut [u8], &dyn RenderResourceContext),
|
||||
) -> BufferId {
|
||||
let mut buffer = vec![0; buffer_info.size];
|
||||
setup_data(&mut buffer, self);
|
||||
BufferId::new()
|
||||
id: BufferId,
|
||||
_range: Range<u64>,
|
||||
write: &mut dyn FnMut(&mut [u8], &dyn RenderResourceContext),
|
||||
) {
|
||||
let size = self.buffer_info.read().unwrap().get(&id).unwrap().size;
|
||||
let mut buffer = vec![0; size];
|
||||
write(&mut buffer, self);
|
||||
}
|
||||
fn map_buffer(&self, _id: BufferId) {}
|
||||
fn unmap_buffer(&self, _id: BufferId) {}
|
||||
fn create_buffer_with_data(&self, buffer_info: BufferInfo, _data: &[u8]) -> BufferId {
|
||||
let buffer = BufferId::new();
|
||||
self.add_buffer_info(buffer, buffer_info);
|
||||
|
||||
@ -7,6 +7,7 @@ use crate::{
|
||||
use bevy_asset::{Assets, Handle, HandleUntyped};
|
||||
use bevy_window::{Window, WindowId};
|
||||
use downcast_rs::{impl_downcast, Downcast};
|
||||
use std::ops::Range;
|
||||
|
||||
pub trait RenderResourceContext: Downcast + Send + Sync + 'static {
|
||||
fn create_swap_chain(&self, window: &Window);
|
||||
@ -17,11 +18,20 @@ pub trait RenderResourceContext: Downcast + Send + Sync + 'static {
|
||||
fn create_texture(&self, texture_descriptor: TextureDescriptor) -> TextureId;
|
||||
fn create_buffer(&self, buffer_info: BufferInfo) -> BufferId;
|
||||
// TODO: remove RenderResourceContext here
|
||||
fn create_buffer_mapped(
|
||||
fn write_mapped_buffer(
|
||||
&self,
|
||||
buffer_info: BufferInfo,
|
||||
setup_data: &mut dyn FnMut(&mut [u8], &dyn RenderResourceContext),
|
||||
) -> BufferId;
|
||||
id: BufferId,
|
||||
range: Range<u64>,
|
||||
write: &mut dyn FnMut(&mut [u8], &dyn RenderResourceContext),
|
||||
);
|
||||
fn map_buffer(
|
||||
&self,
|
||||
id: BufferId,
|
||||
);
|
||||
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<Shader>, shaders: &Assets<Shader>);
|
||||
fn create_shader_module_from_source(&self, shader_handle: Handle<Shader>, shader: &Shader);
|
||||
|
||||
@ -15,7 +15,7 @@ use bevy_render::{
|
||||
texture::{Extent3d, SamplerDescriptor, TextureDescriptor},
|
||||
};
|
||||
use bevy_window::{Window, WindowId};
|
||||
use std::sync::Arc;
|
||||
use std::{ops::Range, sync::Arc};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct WgpuRenderResourceContext {
|
||||
@ -167,43 +167,12 @@ impl RenderResourceContext for WgpuRenderResourceContext {
|
||||
label: None,
|
||||
size: buffer_info.size as u64,
|
||||
usage: buffer_info.buffer_usage.wgpu_into(),
|
||||
mapped_at_creation: false,
|
||||
mapped_at_creation: buffer_info.mapped_at_creation,
|
||||
});
|
||||
|
||||
let id = BufferId::new();
|
||||
buffer_infos.insert(id, buffer_info);
|
||||
buffers.insert(id, buffer);
|
||||
id
|
||||
}
|
||||
|
||||
fn create_buffer_mapped(
|
||||
&self,
|
||||
buffer_info: BufferInfo,
|
||||
setup_data: &mut dyn FnMut(&mut [u8], &dyn RenderResourceContext),
|
||||
) -> BufferId {
|
||||
let usage: wgpu::BufferUsage = buffer_info.buffer_usage.wgpu_into();
|
||||
let buffer = self.device.create_buffer(&wgpu::BufferDescriptor {
|
||||
size: buffer_info.size as u64,
|
||||
usage: usage | wgpu::BufferUsage::MAP_WRITE,
|
||||
label: None,
|
||||
mapped_at_creation: false,
|
||||
});
|
||||
let buffer_slice = buffer.slice(..);
|
||||
let data = buffer_slice.map_async(wgpu::MapMode::Write);
|
||||
self.device.poll(wgpu::Maintain::Wait);
|
||||
if let Ok(()) = pollster::block_on(data) {
|
||||
let mut data = buffer_slice.get_mapped_range_mut();
|
||||
setup_data(&mut data, self);
|
||||
} else {
|
||||
panic!("failed to map buffer to host");
|
||||
}
|
||||
|
||||
buffer.unmap();
|
||||
let id = BufferId::new();
|
||||
let mut buffer_infos = self.resources.buffer_infos.write().unwrap();
|
||||
let mut buffers = self.resources.buffers.write().unwrap();
|
||||
buffer_infos.insert(id, buffer_info);
|
||||
buffers.insert(id, buffer);
|
||||
buffers.insert(id, Arc::new(buffer));
|
||||
id
|
||||
}
|
||||
|
||||
@ -219,7 +188,7 @@ impl RenderResourceContext for WgpuRenderResourceContext {
|
||||
|
||||
let id = BufferId::new();
|
||||
buffer_infos.insert(id, buffer_info);
|
||||
buffers.insert(id, buffer);
|
||||
buffers.insert(id, Arc::new(buffer));
|
||||
id
|
||||
}
|
||||
|
||||
@ -522,4 +491,34 @@ impl RenderResourceContext for WgpuRenderResourceContext {
|
||||
.get(&buffer)
|
||||
.cloned()
|
||||
}
|
||||
fn write_mapped_buffer(
|
||||
&self,
|
||||
id: BufferId,
|
||||
range: Range<u64>,
|
||||
write: &mut dyn FnMut(&mut [u8], &dyn RenderResourceContext),
|
||||
) {
|
||||
let buffer = {
|
||||
let buffers = self.resources.buffers.read().unwrap();
|
||||
buffers.get(&id).unwrap().clone()
|
||||
};
|
||||
let buffer_slice = buffer.slice(range);
|
||||
let mut data = buffer_slice.get_mapped_range_mut();
|
||||
write(&mut data, self);
|
||||
}
|
||||
|
||||
fn map_buffer(&self, id: BufferId) {
|
||||
let buffers = self.resources.buffers.read().unwrap();
|
||||
let buffer = buffers.get(&id).unwrap();
|
||||
let buffer_slice = buffer.slice(..);
|
||||
let data = buffer_slice.map_async(wgpu::MapMode::Write);
|
||||
self.device.poll(wgpu::Maintain::Wait);
|
||||
if let Err(_) = pollster::block_on(data) {
|
||||
panic!("failed to map buffer to host");
|
||||
}
|
||||
}
|
||||
fn unmap_buffer(&self, id: BufferId) {
|
||||
let buffers = self.resources.buffers.read().unwrap();
|
||||
let buffer = buffers.get(&id).unwrap();
|
||||
buffer.unmap();
|
||||
}
|
||||
}
|
||||
|
||||
@ -39,7 +39,7 @@ pub struct WgpuBindGroupInfo {
|
||||
/// Single threaded implementations don't need to worry about these lifetimes constraints at all. RenderPasses can use a RenderContext's
|
||||
/// WgpuResources directly. RenderContext already has a lifetime greater than the RenderPass.
|
||||
pub struct WgpuResourcesReadLock<'a> {
|
||||
pub buffers: RwLockReadGuard<'a, HashMap<BufferId, wgpu::Buffer>>,
|
||||
pub buffers: RwLockReadGuard<'a, HashMap<BufferId, Arc<wgpu::Buffer>>>,
|
||||
pub textures: RwLockReadGuard<'a, HashMap<TextureId, wgpu::TextureView>>,
|
||||
pub swap_chain_frames: RwLockReadGuard<'a, HashMap<TextureId, wgpu::SwapChainFrame>>,
|
||||
pub render_pipelines:
|
||||
@ -61,7 +61,7 @@ impl<'a> WgpuResourcesReadLock<'a> {
|
||||
|
||||
/// Stores read only references to WgpuResource collections. See WgpuResourcesReadLock docs for context on why this exists
|
||||
pub struct WgpuResourceRefs<'a> {
|
||||
pub buffers: &'a HashMap<BufferId, wgpu::Buffer>,
|
||||
pub buffers: &'a HashMap<BufferId, Arc<wgpu::Buffer>>,
|
||||
pub textures: &'a HashMap<TextureId, wgpu::TextureView>,
|
||||
pub swap_chain_frames: &'a HashMap<TextureId, wgpu::SwapChainFrame>,
|
||||
pub render_pipelines: &'a HashMap<Handle<PipelineDescriptor>, wgpu::RenderPipeline>,
|
||||
@ -75,7 +75,7 @@ pub struct WgpuResources {
|
||||
pub window_surfaces: Arc<RwLock<HashMap<WindowId, wgpu::Surface>>>,
|
||||
pub window_swap_chains: Arc<RwLock<HashMap<WindowId, wgpu::SwapChain>>>,
|
||||
pub swap_chain_frames: Arc<RwLock<HashMap<TextureId, wgpu::SwapChainFrame>>>,
|
||||
pub buffers: Arc<RwLock<HashMap<BufferId, wgpu::Buffer>>>,
|
||||
pub buffers: Arc<RwLock<HashMap<BufferId, Arc<wgpu::Buffer>>>>,
|
||||
pub texture_views: Arc<RwLock<HashMap<TextureId, wgpu::TextureView>>>,
|
||||
pub textures: Arc<RwLock<HashMap<TextureId, wgpu::Texture>>>,
|
||||
pub samplers: Arc<RwLock<HashMap<SamplerId, wgpu::Sampler>>>,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user