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