mirror of
https://github.com/bevyengine/bevy
synced 2024-11-22 20:53:53 +00:00
render: support arbitrary RenderResource byte lengths and temporarily disable RenderResource asset change events
This commit is contained in:
parent
8803bcd92e
commit
6362b2a516
1 changed files with 100 additions and 62 deletions
|
@ -9,20 +9,18 @@ use crate::{
|
|||
texture,
|
||||
};
|
||||
|
||||
use bevy_app::{EventReader, Events};
|
||||
use bevy_asset::{AssetEvent, Assets, Handle};
|
||||
use bevy_asset::{Assets, Handle};
|
||||
use legion::prelude::*;
|
||||
use render_resource::ResourceInfo;
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
marker::PhantomData,
|
||||
};
|
||||
use std::{collections::HashMap, marker::PhantomData};
|
||||
|
||||
pub const BIND_BUFFER_ALIGNMENT: usize = 256;
|
||||
#[derive(Debug)]
|
||||
struct QueuedBufferWrite {
|
||||
buffer: RenderResourceId,
|
||||
offset: usize,
|
||||
target_offset: usize,
|
||||
source_offset: usize,
|
||||
size: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -37,6 +35,9 @@ struct BufferArrayStatus {
|
|||
current_item_capacity: usize,
|
||||
indices: HashMap<RenderResourceAssignmentsId, usize>,
|
||||
current_index: usize,
|
||||
// TODO: this is a hack to workaround RenderResources without a fixed length
|
||||
changed_size: usize,
|
||||
current_offset: usize,
|
||||
}
|
||||
|
||||
impl BufferArrayStatus {
|
||||
|
@ -84,6 +85,8 @@ where
|
|||
for buffer_status in self.uniform_arrays.iter_mut() {
|
||||
if let Some((_name, buffer_status)) = buffer_status {
|
||||
buffer_status.changed_item_count = 0;
|
||||
buffer_status.current_offset = 0;
|
||||
buffer_status.changed_size = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -99,6 +102,7 @@ where
|
|||
let size = render_resource.buffer_byte_len().unwrap();
|
||||
if let Some((ref _name, ref mut buffer_array_status)) = self.uniform_arrays[i] {
|
||||
buffer_array_status.changed_item_count += 1;
|
||||
buffer_array_status.changed_size += size;
|
||||
} else {
|
||||
self.uniform_arrays[i] = Some((
|
||||
render_resource_name.to_string(),
|
||||
|
@ -113,6 +117,8 @@ where
|
|||
current_item_count: 0,
|
||||
current_item_capacity: 0,
|
||||
indices: HashMap::new(),
|
||||
changed_size: size,
|
||||
current_offset: 0,
|
||||
},
|
||||
))
|
||||
}
|
||||
|
@ -179,7 +185,7 @@ where
|
|||
for dynamic_buffer_array_status in self.uniform_arrays.iter_mut() {
|
||||
if let Some((_name, ref mut buffer_array_status)) = dynamic_buffer_array_status {
|
||||
buffer_array_status.staging_buffer_offset = size;
|
||||
size += buffer_array_status.item_size * buffer_array_status.changed_item_count;
|
||||
size += buffer_array_status.changed_size;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -217,44 +223,67 @@ where
|
|||
);
|
||||
(buffer, index * uniform_buffer_status.aligned_size)
|
||||
} else {
|
||||
let resource = match render_resource_assignments.get(render_resource_name) {
|
||||
Some(assignment) => assignment.get_resource(),
|
||||
None => {
|
||||
// TODO: RE-ADD support for BufferUsage::STORAGE type
|
||||
let mut usage = BufferUsage::UNIFORM;
|
||||
|
||||
if let Some(render_resource_hints) =
|
||||
uniforms.get_render_resource_hints(i)
|
||||
let mut matching_buffer = None;
|
||||
let mut buffer_to_remove = None;
|
||||
if let Some(assignment) =
|
||||
render_resource_assignments.get(render_resource_name)
|
||||
{
|
||||
let resource = assignment.get_resource();
|
||||
render_resources.get_resource_info(resource, &mut |info| {
|
||||
if let Some(ResourceInfo::Buffer(Some(BufferInfo {
|
||||
size: current_size,
|
||||
..
|
||||
}))) = info
|
||||
{
|
||||
if render_resource_hints.contains(RenderResourceHints::BUFFER) {
|
||||
usage = BufferUsage::STORAGE
|
||||
if size == *current_size {
|
||||
matching_buffer = Some(resource);
|
||||
} else {
|
||||
// TODO: if get_resource_info returns a type instead of taking a closure, move buffer free here
|
||||
buffer_to_remove = Some(resource);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
let resource = render_resources.create_buffer(BufferInfo {
|
||||
size,
|
||||
buffer_usage: BufferUsage::COPY_DST | usage,
|
||||
..Default::default()
|
||||
});
|
||||
if let Some(buffer) = buffer_to_remove {
|
||||
render_resources.remove_buffer(buffer);
|
||||
}
|
||||
|
||||
render_resource_assignments.set(
|
||||
render_resource_name,
|
||||
RenderResourceAssignment::Buffer {
|
||||
resource,
|
||||
range,
|
||||
dynamic_index: None,
|
||||
},
|
||||
);
|
||||
resource
|
||||
let resource = if let Some(matching_buffer) = matching_buffer {
|
||||
matching_buffer
|
||||
} else {
|
||||
let mut usage = BufferUsage::UNIFORM;
|
||||
if let Some(render_resource_hints) =
|
||||
uniforms.get_render_resource_hints(i)
|
||||
{
|
||||
if render_resource_hints.contains(RenderResourceHints::BUFFER) {
|
||||
usage = BufferUsage::STORAGE
|
||||
}
|
||||
}
|
||||
|
||||
let resource = render_resources.create_buffer(BufferInfo {
|
||||
size,
|
||||
buffer_usage: BufferUsage::COPY_DST | usage,
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
render_resource_assignments.set(
|
||||
render_resource_name,
|
||||
RenderResourceAssignment::Buffer {
|
||||
resource,
|
||||
range,
|
||||
dynamic_index: None,
|
||||
},
|
||||
);
|
||||
resource
|
||||
};
|
||||
|
||||
(resource, 0)
|
||||
};
|
||||
|
||||
let staging_buffer_start = uniform_buffer_status.staging_buffer_offset
|
||||
+ (uniform_buffer_status.queued_buffer_writes.len()
|
||||
* uniform_buffer_status.item_size);
|
||||
+ uniform_buffer_status.current_offset;
|
||||
|
||||
render_resource.write_buffer_bytes(
|
||||
&mut staging_buffer[staging_buffer_start..(staging_buffer_start + size)],
|
||||
);
|
||||
|
@ -263,8 +292,11 @@ where
|
|||
.queued_buffer_writes
|
||||
.push(QueuedBufferWrite {
|
||||
buffer: target_buffer,
|
||||
offset: target_offset,
|
||||
target_offset,
|
||||
source_offset: uniform_buffer_status.current_offset,
|
||||
size,
|
||||
});
|
||||
uniform_buffer_status.current_offset += size;
|
||||
}
|
||||
Some(ResourceInfo::Texture(_)) => { /* ignore textures */ }
|
||||
Some(ResourceInfo::Sampler) => { /* ignore samplers */ }
|
||||
|
@ -281,17 +313,13 @@ where
|
|||
for uniform_buffer_status in self.uniform_arrays.iter_mut() {
|
||||
if let Some((_name, buffer_array_status)) = uniform_buffer_status {
|
||||
let start = buffer_array_status.staging_buffer_offset;
|
||||
for (i, queued_buffer_write) in buffer_array_status
|
||||
.queued_buffer_writes
|
||||
.drain(..)
|
||||
.enumerate()
|
||||
{
|
||||
for queued_buffer_write in buffer_array_status.queued_buffer_writes.drain(..) {
|
||||
command_queue.copy_buffer_to_buffer(
|
||||
staging_buffer,
|
||||
(start + (i * buffer_array_status.item_size)) as u64,
|
||||
(start + queued_buffer_write.source_offset) as u64,
|
||||
queued_buffer_write.buffer,
|
||||
queued_buffer_write.offset as u64,
|
||||
buffer_array_status.item_size as u64,
|
||||
queued_buffer_write.target_offset as u64,
|
||||
queued_buffer_write.size as u64,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -473,33 +501,38 @@ where
|
|||
fn get_system(&self) -> Box<dyn Schedulable> {
|
||||
let mut command_queue = self.command_queue.clone();
|
||||
let mut uniform_buffer_arrays = UniformBufferArrays::<T>::default();
|
||||
let mut asset_event_reader = EventReader::<AssetEvent<T>>::default();
|
||||
// let mut asset_event_reader = EventReader::<AssetEvent<T>>::default();
|
||||
let mut asset_render_resource_assignments =
|
||||
HashMap::<Handle<T>, RenderResourceAssignments>::default();
|
||||
let dynamic_uniforms = self.dynamic_uniforms;
|
||||
(move |world: &mut SubWorld,
|
||||
assets: Res<Assets<T>>,
|
||||
asset_events: Res<Events<AssetEvent<T>>>,
|
||||
// asset_events: Res<Events<AssetEvent<T>>>,
|
||||
render_resources: Res<RenderResources>,
|
||||
query: &mut Query<(Read<Handle<T>>, Read<Draw>, Write<RenderPipelines>)>| {
|
||||
let render_resource_context = &*render_resources.context;
|
||||
uniform_buffer_arrays.reset_changed_item_counts();
|
||||
|
||||
let mut modified_assets = HashSet::new();
|
||||
for event in asset_event_reader.iter(&asset_events) {
|
||||
match event {
|
||||
AssetEvent::Created { handle } => {
|
||||
modified_assets.insert(*handle);
|
||||
}
|
||||
AssetEvent::Modified { handle } => {
|
||||
modified_assets.insert(*handle);
|
||||
}
|
||||
AssetEvent::Removed { handle } => {
|
||||
// TODO: handle removals
|
||||
modified_assets.remove(handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
let modified_assets = assets
|
||||
.iter()
|
||||
.map(|(handle, _)| handle)
|
||||
.collect::<Vec<Handle<T>>>();
|
||||
// TODO: uncomment this when asset dependency events are added https://github.com/bevyengine/bevy/issues/26
|
||||
// let mut modified_assets = HashSet::new();
|
||||
// for event in asset_event_reader.iter(&asset_events) {
|
||||
// match event {
|
||||
// AssetEvent::Created { handle } => {
|
||||
// modified_assets.insert(*handle);
|
||||
// }
|
||||
// AssetEvent::Modified { handle } => {
|
||||
// modified_assets.insert(*handle);
|
||||
// }
|
||||
// AssetEvent::Removed { handle } => {
|
||||
// // TODO: handle removals
|
||||
// modified_assets.remove(handle);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// update uniform handles info
|
||||
for asset_handle in modified_assets.iter() {
|
||||
|
@ -569,8 +602,12 @@ where
|
|||
}
|
||||
|
||||
for (asset_handle, _draw, mut render_pipelines) in query.iter_mut(world) {
|
||||
if let Some(asset_assignments) = asset_render_resource_assignments.get(&asset_handle) {
|
||||
render_pipelines.render_resource_assignments.extend(asset_assignments);
|
||||
if let Some(asset_assignments) =
|
||||
asset_render_resource_assignments.get(&asset_handle)
|
||||
{
|
||||
render_pipelines
|
||||
.render_resource_assignments
|
||||
.extend(asset_assignments);
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -596,6 +633,7 @@ fn setup_uniform_texture_resources<T>(
|
|||
let sampler_resource = render_resource_context
|
||||
.get_asset_resource(texture_handle, texture::SAMPLER_ASSET_INDEX)
|
||||
.unwrap();
|
||||
|
||||
render_resource_assignments.set(
|
||||
render_resource_name,
|
||||
RenderResourceAssignment::Texture(texture_resource),
|
||||
|
|
Loading…
Reference in a new issue