mirror of
https://github.com/bevyengine/bevy
synced 2024-11-22 04:33:37 +00:00
refactor render resource assignments
This commit is contained in:
parent
e523dc92d8
commit
64cd924413
17 changed files with 249 additions and 224 deletions
|
@ -20,7 +20,7 @@ rand = "0.7.2"
|
|||
gltf = "0.14.0"
|
||||
serde = { version = "1", features = ["derive"]}
|
||||
serde_json = "1.0"
|
||||
uuid = { version = "0.8", features = ["v4"] }
|
||||
uuid = { version = "0.8", features = ["v4", "serde"] }
|
||||
erased-serde = "0.3"
|
||||
type-uuid = "0.1"
|
||||
shaderc = "0.6"
|
||||
|
|
|
@ -16,8 +16,7 @@ use bevy_transform::{prelude::LocalToWorld, transform_system_bundle};
|
|||
use pipeline::PipelineDescriptor;
|
||||
use render_graph::{RenderGraph, RenderGraphBuilder};
|
||||
use render_resource::{
|
||||
build_entity_render_resource_assignments_system, AssetBatchers,
|
||||
EntityRenderResourceAssignments, RenderResourceAssignmentsProvider,
|
||||
build_entity_render_resource_assignments_system, AssetBatchers, EntityRenderResourceAssignments,
|
||||
};
|
||||
use shader::Shader;
|
||||
use std::collections::HashMap;
|
||||
|
@ -158,8 +157,6 @@ impl AppBuilder {
|
|||
}
|
||||
|
||||
pub fn add_default_resources(&mut self) -> &mut Self {
|
||||
let mut asset_batchers = AssetBatchers::default();
|
||||
asset_batchers.batch_types2::<Mesh, StandardMaterial>();
|
||||
let resources = self.resources.as_mut().unwrap();
|
||||
resources.insert(Time::new());
|
||||
resources.insert(AssetStorage::<Mesh>::new());
|
||||
|
@ -169,9 +166,25 @@ impl AppBuilder {
|
|||
resources.insert(AssetStorage::<PipelineDescriptor>::new());
|
||||
resources.insert(ShaderPipelineAssignments::new());
|
||||
resources.insert(CompiledShaderMap::new());
|
||||
resources.insert(RenderResourceAssignmentsProvider::default());
|
||||
resources.insert(EntityRenderResourceAssignments::default());
|
||||
resources.insert(asset_batchers);
|
||||
self.batch_types2::<Mesh, StandardMaterial>();
|
||||
self
|
||||
}
|
||||
|
||||
pub fn batch_types2<T1, T2>(&mut self) -> &mut Self
|
||||
where
|
||||
T1: 'static,
|
||||
T2: 'static,
|
||||
{
|
||||
{
|
||||
let resources = self.resources.as_mut().unwrap();
|
||||
let mut asset_batchers = resources
|
||||
.get_mut_or_insert_with(|| AssetBatchers::default())
|
||||
.unwrap();
|
||||
|
||||
asset_batchers.batch_types2::<T1, T2>();
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ impl DrawTarget for AssignedMeshesDrawTarget {
|
|||
}
|
||||
|
||||
// TODO: validate bind group properties against shader uniform properties at least once
|
||||
render_pass.set_bind_groups(renderable.render_resource_assignments.as_ref());
|
||||
render_pass.set_render_resource_assignments(Some(&renderable.render_resource_assignments));
|
||||
render_pass.draw_indexed(0..current_mesh_index_len, 0, 0..1);
|
||||
}
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ impl DrawTarget for AssignedMeshesDrawTarget {
|
|||
}
|
||||
|
||||
renderer.setup_bind_groups(
|
||||
renderable.render_resource_assignments.as_ref().unwrap(),
|
||||
&renderable.render_resource_assignments,
|
||||
pipeline_descriptor,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ impl DrawTarget for MeshesDrawTarget {
|
|||
}
|
||||
|
||||
// TODO: validate bind group properties against shader uniform properties at least once
|
||||
render_pass.set_bind_groups(renderable.render_resource_assignments.as_ref());
|
||||
render_pass.set_render_resource_assignments(Some(&renderable.render_resource_assignments));
|
||||
render_pass.draw_indexed(0..current_mesh_index_len, 0, 0..1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ impl DrawTarget for UiDrawTarget {
|
|||
}
|
||||
};
|
||||
|
||||
render_pass.set_bind_groups(None);
|
||||
render_pass.set_render_resource_assignments(None);
|
||||
render_pass.set_index_buffer(self.mesh_index_buffer.unwrap(), 0);
|
||||
render_pass.set_vertex_buffer(0, self.mesh_vertex_buffer.unwrap(), 0);
|
||||
render_pass.set_vertex_buffer(1, ui_instances_buffer, 0);
|
||||
|
|
|
@ -55,8 +55,8 @@ impl<'a> ForwardPipelineBuilder for RenderGraphBuilder<'a> {
|
|||
},
|
||||
write_mask: ColorWrite::ALL,
|
||||
})
|
||||
.add_draw_target(resource_name::draw_target::ASSIGNED_MESHES)
|
||||
.add_draw_target(resource_name::draw_target::ASSIGNED_BATCHES);
|
||||
.add_draw_target(resource_name::draw_target::ASSIGNED_MESHES);
|
||||
// .add_draw_target(resource_name::draw_target::ASSIGNED_BATCHES);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,162 +1,7 @@
|
|||
use super::RenderResourceAssignments;
|
||||
use crate::asset::{Handle, HandleId, HandleUntyped};
|
||||
use super::{AssetSetBatcher2, AssetSetBatcherKey2, Batch, BatchKey2};
|
||||
use crate::asset::{Handle, HandleId};
|
||||
use legion::prelude::Entity;
|
||||
use std::{any::TypeId, collections::HashMap, hash::Hash};
|
||||
|
||||
// TODO: if/when const generics land, revisit this design
|
||||
|
||||
#[derive(Hash, Eq, PartialEq, Debug, Ord, PartialOrd)]
|
||||
pub struct BatchKey2 {
|
||||
pub handle1: HandleId,
|
||||
pub handle2: HandleId,
|
||||
}
|
||||
|
||||
#[derive(Hash, Eq, PartialEq, Clone, Debug)]
|
||||
pub struct AssetSetBatcherKey2 {
|
||||
handle1_type: TypeId,
|
||||
handle2_type: TypeId,
|
||||
}
|
||||
|
||||
struct EntitySetState2 {
|
||||
handle1: Option<HandleId>,
|
||||
handle2: Option<HandleId>,
|
||||
}
|
||||
|
||||
impl EntitySetState2 {
|
||||
fn is_full(&self) -> bool {
|
||||
self.handle1.is_some() && self.handle2.is_some()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Default)]
|
||||
pub struct Batch {
|
||||
pub handles: Vec<HandleUntyped>,
|
||||
pub entity_indices: HashMap<Entity, usize>,
|
||||
pub current_index: usize,
|
||||
pub render_resource_assignments: Option<RenderResourceAssignments>,
|
||||
}
|
||||
|
||||
impl Batch {
|
||||
pub fn add_entity(&mut self, entity: Entity) {
|
||||
if let None = self.entity_indices.get(&entity) {
|
||||
self.entity_indices.insert(entity, self.current_index);
|
||||
self.current_index += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AssetSetBatcher2 {
|
||||
key: AssetSetBatcherKey2,
|
||||
set_batches: HashMap<BatchKey2, Batch>,
|
||||
entity_set_states: HashMap<Entity, EntitySetState2>,
|
||||
}
|
||||
|
||||
impl AssetSetBatcher2 {
|
||||
fn new(key: AssetSetBatcherKey2) -> Self {
|
||||
AssetSetBatcher2 {
|
||||
key,
|
||||
set_batches: HashMap::new(),
|
||||
entity_set_states: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn add_entity_to_set(&mut self, entity: Entity) {
|
||||
// these unwraps are safe because this function is only called from set_entity_handle on a "full" state
|
||||
let state = self.entity_set_states.get(&entity).unwrap();
|
||||
let key = BatchKey2 {
|
||||
handle1: state.handle1.unwrap(),
|
||||
handle2: state.handle2.unwrap(),
|
||||
};
|
||||
|
||||
match self.set_batches.get_mut(&key) {
|
||||
Some(batch) => {
|
||||
batch.add_entity(entity);
|
||||
}
|
||||
None => {
|
||||
let mut batch = Batch::default();
|
||||
|
||||
batch.handles.push(HandleUntyped {
|
||||
id: key.handle1,
|
||||
type_id: self.key.handle1_type,
|
||||
});
|
||||
batch.handles.push(HandleUntyped {
|
||||
id: key.handle2,
|
||||
type_id: self.key.handle2_type,
|
||||
});
|
||||
|
||||
batch.add_entity(entity);
|
||||
self.set_batches.insert(key, batch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_entity_handle1(&mut self, entity: Entity, handle_id: HandleId) {
|
||||
match self.entity_set_states.get_mut(&entity) {
|
||||
None => {
|
||||
// TODO: when generalizing to set size 1, ensure you treat set as "full" here
|
||||
self.entity_set_states.insert(
|
||||
entity,
|
||||
EntitySetState2 {
|
||||
handle1: Some(handle_id),
|
||||
handle2: None,
|
||||
},
|
||||
);
|
||||
}
|
||||
Some(state) => {
|
||||
state.handle1 = Some(handle_id);
|
||||
if state.is_full() {
|
||||
self.add_entity_to_set(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_entity_handle2(&mut self, entity: Entity, handle_id: HandleId) {
|
||||
match self.entity_set_states.get_mut(&entity) {
|
||||
None => {
|
||||
// TODO: when generalizing to set size 1, ensure you treat set as "full" here
|
||||
self.entity_set_states.insert(
|
||||
entity,
|
||||
EntitySetState2 {
|
||||
handle1: None,
|
||||
handle2: Some(handle_id),
|
||||
},
|
||||
);
|
||||
}
|
||||
Some(state) => {
|
||||
state.handle2 = Some(handle_id);
|
||||
if state.is_full() {
|
||||
self.add_entity_to_set(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AssetBatcher for AssetSetBatcher2 {
|
||||
fn set_entity_handle(&mut self, entity: Entity, handle_type: TypeId, handle_id: HandleId) {
|
||||
if handle_type == self.key.handle1_type {
|
||||
self.set_entity_handle1(entity, handle_id);
|
||||
} else if handle_type == self.key.handle2_type {
|
||||
self.set_entity_handle2(entity, handle_id);
|
||||
}
|
||||
}
|
||||
fn get_batch2(&self, key: &BatchKey2) -> Option<&Batch> {
|
||||
self.set_batches.get(key)
|
||||
}
|
||||
|
||||
fn get_batches2(&self) -> std::collections::hash_map::Iter<'_, BatchKey2, Batch> {
|
||||
self.set_batches.iter()
|
||||
}
|
||||
|
||||
fn get_batches<'a>(&'a self) -> Box<dyn Iterator<Item = &'a Batch> + 'a> {
|
||||
Box::new(self.set_batches.values())
|
||||
}
|
||||
|
||||
fn get_batches_mut<'a>(&'a mut self) -> Box<dyn Iterator<Item = &'a mut Batch> + 'a> {
|
||||
Box::new(self.set_batches.values_mut())
|
||||
}
|
||||
}
|
||||
use std::{any::TypeId, collections::HashMap};
|
||||
|
||||
pub trait AssetBatcher {
|
||||
fn set_entity_handle(&mut self, entity: Entity, handle_type: TypeId, handle_id: HandleId);
|
144
src/render/render_resource/batching/asset_batcher2.rs
Normal file
144
src/render/render_resource/batching/asset_batcher2.rs
Normal file
|
@ -0,0 +1,144 @@
|
|||
use crate::{
|
||||
asset::{HandleId, HandleUntyped},
|
||||
};
|
||||
use legion::prelude::Entity;
|
||||
use std::{any::TypeId, collections::HashMap, hash::Hash};
|
||||
use super::{AssetBatcher, Batch};
|
||||
|
||||
// TODO: if/when const generics land, revisit this design in favor of generic array lengths
|
||||
|
||||
#[derive(Hash, Eq, PartialEq, Debug, Ord, PartialOrd)]
|
||||
pub struct BatchKey2 {
|
||||
pub handle1: HandleId,
|
||||
pub handle2: HandleId,
|
||||
}
|
||||
|
||||
#[derive(Hash, Eq, PartialEq, Clone, Debug)]
|
||||
pub struct AssetSetBatcherKey2 {
|
||||
pub handle1_type: TypeId,
|
||||
pub handle2_type: TypeId,
|
||||
}
|
||||
|
||||
struct EntitySetState2 {
|
||||
handle1: Option<HandleId>,
|
||||
handle2: Option<HandleId>,
|
||||
}
|
||||
|
||||
impl EntitySetState2 {
|
||||
fn is_full(&self) -> bool {
|
||||
self.handle1.is_some() && self.handle2.is_some()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AssetSetBatcher2 {
|
||||
key: AssetSetBatcherKey2,
|
||||
set_batches: HashMap<BatchKey2, Batch>,
|
||||
entity_set_states: HashMap<Entity, EntitySetState2>,
|
||||
}
|
||||
|
||||
impl AssetSetBatcher2 {
|
||||
pub fn new(key: AssetSetBatcherKey2) -> Self {
|
||||
AssetSetBatcher2 {
|
||||
key,
|
||||
set_batches: HashMap::new(),
|
||||
entity_set_states: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_entity_to_set(&mut self, entity: Entity) {
|
||||
// these unwraps are safe because this function is only called from set_entity_handle on a "full" state
|
||||
let state = self.entity_set_states.get(&entity).unwrap();
|
||||
let key = BatchKey2 {
|
||||
handle1: state.handle1.unwrap(),
|
||||
handle2: state.handle2.unwrap(),
|
||||
};
|
||||
|
||||
match self.set_batches.get_mut(&key) {
|
||||
Some(batch) => {
|
||||
batch.add_entity(entity);
|
||||
}
|
||||
None => {
|
||||
let mut batch = Batch::default();
|
||||
|
||||
batch.handles.push(HandleUntyped {
|
||||
id: key.handle1,
|
||||
type_id: self.key.handle1_type,
|
||||
});
|
||||
batch.handles.push(HandleUntyped {
|
||||
id: key.handle2,
|
||||
type_id: self.key.handle2_type,
|
||||
});
|
||||
|
||||
batch.add_entity(entity);
|
||||
self.set_batches.insert(key, batch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_entity_handle1(&mut self, entity: Entity, handle_id: HandleId) {
|
||||
match self.entity_set_states.get_mut(&entity) {
|
||||
None => {
|
||||
// TODO: when generalizing to set size 1, ensure you treat set as "full" here
|
||||
self.entity_set_states.insert(
|
||||
entity,
|
||||
EntitySetState2 {
|
||||
handle1: Some(handle_id),
|
||||
handle2: None,
|
||||
},
|
||||
);
|
||||
}
|
||||
Some(state) => {
|
||||
state.handle1 = Some(handle_id);
|
||||
if state.is_full() {
|
||||
self.add_entity_to_set(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_entity_handle2(&mut self, entity: Entity, handle_id: HandleId) {
|
||||
match self.entity_set_states.get_mut(&entity) {
|
||||
None => {
|
||||
// TODO: when generalizing to set size 1, ensure you treat set as "full" here
|
||||
self.entity_set_states.insert(
|
||||
entity,
|
||||
EntitySetState2 {
|
||||
handle1: None,
|
||||
handle2: Some(handle_id),
|
||||
},
|
||||
);
|
||||
}
|
||||
Some(state) => {
|
||||
state.handle2 = Some(handle_id);
|
||||
if state.is_full() {
|
||||
self.add_entity_to_set(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AssetBatcher for AssetSetBatcher2 {
|
||||
fn set_entity_handle(&mut self, entity: Entity, handle_type: TypeId, handle_id: HandleId) {
|
||||
if handle_type == self.key.handle1_type {
|
||||
self.set_entity_handle1(entity, handle_id);
|
||||
} else if handle_type == self.key.handle2_type {
|
||||
self.set_entity_handle2(entity, handle_id);
|
||||
}
|
||||
}
|
||||
fn get_batch2(&self, key: &BatchKey2) -> Option<&Batch> {
|
||||
self.set_batches.get(key)
|
||||
}
|
||||
|
||||
fn get_batches2(&self) -> std::collections::hash_map::Iter<'_, BatchKey2, Batch> {
|
||||
self.set_batches.iter()
|
||||
}
|
||||
|
||||
fn get_batches<'a>(&'a self) -> Box<dyn Iterator<Item = &'a Batch> + 'a> {
|
||||
Box::new(self.set_batches.values())
|
||||
}
|
||||
|
||||
fn get_batches_mut<'a>(&'a mut self) -> Box<dyn Iterator<Item = &'a mut Batch> + 'a> {
|
||||
Box::new(self.set_batches.values_mut())
|
||||
}
|
||||
}
|
25
src/render/render_resource/batching/batch.rs
Normal file
25
src/render/render_resource/batching/batch.rs
Normal file
|
@ -0,0 +1,25 @@
|
|||
use crate::{asset::HandleUntyped, render::render_resource::RenderResourceAssignments};
|
||||
use legion::prelude::Entity;
|
||||
use std::collections::{HashSet, HashMap};
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Default)]
|
||||
pub struct Batch {
|
||||
pub handles: Vec<HandleUntyped>,
|
||||
pub entities: HashSet<Entity>,
|
||||
pub instanced_entity_indices: HashMap<Entity, usize>,
|
||||
pub current_instanced_entity_index: usize,
|
||||
pub render_resource_assignments: RenderResourceAssignments,
|
||||
}
|
||||
|
||||
impl Batch {
|
||||
pub fn add_entity(&mut self, entity: Entity) {
|
||||
self.entities.insert(entity);
|
||||
}
|
||||
|
||||
pub fn add_instanced_entity(&mut self, entity: Entity) {
|
||||
if let None = self.instanced_entity_indices.get(&entity) {
|
||||
self.instanced_entity_indices.insert(entity, self.current_instanced_entity_index);
|
||||
self.current_instanced_entity_index += 1;
|
||||
}
|
||||
}
|
||||
}
|
7
src/render/render_resource/batching/mod.rs
Normal file
7
src/render/render_resource/batching/mod.rs
Normal file
|
@ -0,0 +1,7 @@
|
|||
mod asset_batcher;
|
||||
mod asset_batcher2;
|
||||
mod batch;
|
||||
|
||||
pub use asset_batcher::*;
|
||||
pub use asset_batcher2::*;
|
||||
pub use batch::*;
|
|
@ -1,4 +1,4 @@
|
|||
use super::{RenderResourceAssignmentsId, RenderResourceAssignmentsProvider};
|
||||
use super::RenderResourceAssignmentsId;
|
||||
use crate::prelude::Renderable;
|
||||
use legion::prelude::*;
|
||||
use std::collections::HashMap;
|
||||
|
@ -18,20 +18,14 @@ impl EntityRenderResourceAssignments {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: make sure this runs right before rendering
|
||||
pub fn build_entity_render_resource_assignments_system() -> Box<dyn Schedulable> {
|
||||
SystemBuilder::new("EntityRenderResourceAssignments")
|
||||
.write_resource::<EntityRenderResourceAssignments>()
|
||||
.write_resource::<RenderResourceAssignmentsProvider>()
|
||||
.with_query(<Write<Renderable>>::query().filter(changed::<Renderable>()))
|
||||
.build(|_, world, (entity_assignments, provider), query| {
|
||||
.build(|_, world, entity_assignments, query| {
|
||||
for (entity, mut renderable) in query.iter_entities_mut(world) {
|
||||
if renderable.is_instanced {
|
||||
renderable.render_resource_assignments = None;
|
||||
} else if let None = renderable.render_resource_assignments {
|
||||
let render_resource_assignments = provider.next();
|
||||
entity_assignments.set(render_resource_assignments.get_id(), entity);
|
||||
renderable.render_resource_assignments = Some(render_resource_assignments);
|
||||
}
|
||||
entity_assignments.set(renderable.render_resource_assignments.get_id(), entity);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
mod asset_batcher;
|
||||
mod batching;
|
||||
mod buffer;
|
||||
mod entity_render_resource_assignments;
|
||||
mod render_resource;
|
||||
|
@ -8,7 +8,7 @@ pub mod resource_name;
|
|||
mod resource_provider;
|
||||
pub mod resource_providers;
|
||||
|
||||
pub use asset_batcher::*;
|
||||
pub use batching::*;
|
||||
pub use buffer::*;
|
||||
pub use entity_render_resource_assignments::*;
|
||||
pub use render_resource::*;
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
use super::RenderResource;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use uuid::Uuid;
|
||||
|
||||
// PERF: if the assignments are scoped to a specific pipeline layout, then names could be replaced with indices here for a perf boost
|
||||
#[derive(Eq, PartialEq, Debug)]
|
||||
#[derive(Eq, PartialEq, Debug, Default)]
|
||||
pub struct RenderResourceAssignments {
|
||||
id: RenderResourceAssignmentsId,
|
||||
render_resources: HashMap<String, RenderResource>,
|
||||
vertex_buffers: HashMap<String, (RenderResource, Option<RenderResource>)>,
|
||||
pub(crate) shader_defs: HashSet<String>,
|
||||
// TODO: move offsets here to reduce hashing costs?
|
||||
// render_resource_offsets: HashMap<String, >,
|
||||
|
@ -20,28 +22,24 @@ impl RenderResourceAssignments {
|
|||
self.render_resources.insert(name.to_string(), resource);
|
||||
}
|
||||
|
||||
pub fn get_vertex_buffer(&self, name: &str) -> Option<(RenderResource, Option<RenderResource>)> {
|
||||
self.vertex_buffers.get(name).cloned()
|
||||
}
|
||||
|
||||
pub fn set_vertex_buffer(&mut self, name: &str, vertices_resource: RenderResource, indices_resource: Option<RenderResource>) {
|
||||
self.vertex_buffers.insert(name.to_string(), (vertices_resource, indices_resource));
|
||||
}
|
||||
|
||||
pub fn get_id(&self) -> RenderResourceAssignmentsId {
|
||||
self.id
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Hash, Eq, PartialEq, Debug, Copy, Clone)]
|
||||
pub struct RenderResourceAssignmentsId(usize);
|
||||
pub struct RenderResourceAssignmentsId(Uuid);
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct RenderResourceAssignmentsProvider {
|
||||
pub current_id: usize,
|
||||
}
|
||||
|
||||
impl RenderResourceAssignmentsProvider {
|
||||
pub fn next(&mut self) -> RenderResourceAssignments {
|
||||
let assignments = RenderResourceAssignments {
|
||||
id: RenderResourceAssignmentsId(self.current_id),
|
||||
render_resources: HashMap::new(),
|
||||
shader_defs: HashSet::new(),
|
||||
};
|
||||
|
||||
self.current_id += 1;
|
||||
assignments
|
||||
impl Default for RenderResourceAssignmentsId {
|
||||
fn default() -> Self {
|
||||
RenderResourceAssignmentsId(Uuid::new_v4())
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,7 +4,7 @@ use crate::{
|
|||
render_graph::RenderGraph,
|
||||
render_resource::{
|
||||
AssetBatchers, BufferArrayInfo, BufferInfo, BufferUsage, RenderResource,
|
||||
RenderResourceAssignments, RenderResourceAssignmentsProvider, ResourceInfo,
|
||||
RenderResourceAssignments, ResourceInfo,
|
||||
ResourceProvider,
|
||||
},
|
||||
renderer::Renderer,
|
||||
|
@ -51,6 +51,7 @@ type UniformHandleQuery<T> = Query<
|
|||
>,
|
||||
>;
|
||||
|
||||
// TODO: rename to RenderResourceProvider
|
||||
pub struct UniformResourceProvider<T>
|
||||
where
|
||||
T: AsUniforms + Send + Sync + 'static,
|
||||
|
@ -123,7 +124,7 @@ where
|
|||
|
||||
Self::update_shader_defs(
|
||||
&uniforms,
|
||||
renderable.render_resource_assignments.as_mut().unwrap(),
|
||||
&mut renderable.render_resource_assignments,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -142,7 +143,6 @@ where
|
|||
|
||||
if renderable.is_instanced {
|
||||
if self.is_instanceable {
|
||||
asset_batchers.set_entity_handle(entity, *handle);
|
||||
self.increment_instance_count(|| {
|
||||
let uniforms = assets.get(&handle).unwrap();
|
||||
Self::get_instance_size(uniforms)
|
||||
|
@ -154,12 +154,13 @@ where
|
|||
);
|
||||
}
|
||||
} else {
|
||||
asset_batchers.set_entity_handle(entity, *handle);
|
||||
let uniforms = assets
|
||||
.get(&handle)
|
||||
.expect("Handle points to a non-existent resource");
|
||||
Self::update_shader_defs(
|
||||
uniforms,
|
||||
renderable.render_resource_assignments.as_mut().unwrap(),
|
||||
&mut renderable.render_resource_assignments,
|
||||
);
|
||||
|
||||
self.increment_uniform_counts(&uniforms);
|
||||
|
@ -391,7 +392,7 @@ where
|
|||
&uniforms,
|
||||
renderer,
|
||||
resources,
|
||||
renderable.render_resource_assignments.as_mut().unwrap(),
|
||||
&mut renderable.render_resource_assignments,
|
||||
staging_buffer,
|
||||
)
|
||||
}
|
||||
|
@ -422,7 +423,7 @@ where
|
|||
&uniforms,
|
||||
renderer,
|
||||
resources,
|
||||
renderable.render_resource_assignments.as_mut().unwrap(),
|
||||
&mut renderable.render_resource_assignments,
|
||||
staging_buffer,
|
||||
)
|
||||
}
|
||||
|
@ -443,9 +444,6 @@ where
|
|||
// all members of the batch until "UniformResourceProvider.update" has run for all members of the batch
|
||||
if let Some(asset_storage) = resources.get::<AssetStorage<T>>() {
|
||||
let mut asset_batchers = resources.get_mut::<AssetBatchers>().unwrap();
|
||||
let mut render_resource_assignments_provider = resources
|
||||
.get_mut::<RenderResourceAssignmentsProvider>()
|
||||
.unwrap();
|
||||
let handle_type = std::any::TypeId::of::<T>();
|
||||
for batch in asset_batchers.get_handle_batches_mut::<T>().unwrap() {
|
||||
let handle: Handle<T> = batch
|
||||
|
@ -455,19 +453,16 @@ where
|
|||
.map(|h| (*h).into())
|
||||
.unwrap();
|
||||
|
||||
let render_resource_assignments = batch
|
||||
.render_resource_assignments
|
||||
.get_or_insert_with(|| render_resource_assignments_provider.next());
|
||||
if let Some(uniforms) = asset_storage.get(&handle) {
|
||||
self.setup_uniform_resources(
|
||||
uniforms,
|
||||
renderer,
|
||||
resources,
|
||||
render_resource_assignments,
|
||||
&mut batch.render_resource_assignments,
|
||||
staging_buffer,
|
||||
);
|
||||
|
||||
Self::update_shader_defs(&uniforms, render_resource_assignments);
|
||||
Self::update_shader_defs(&uniforms, &mut batch.render_resource_assignments);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -628,7 +623,7 @@ where
|
|||
let mut staging_buffer: [u8; 0] = [];
|
||||
self.setup_uniforms_resources(world, resources, renderer, &mut staging_buffer);
|
||||
self.setup_handles_resources(world, resources, renderer, &mut staging_buffer);
|
||||
// self.setup_batched_resources(world, resources, renderer, &mut staging_buffer);
|
||||
// self.setup_batched_resources(world, resources, renderer, &mut staging_buffer);
|
||||
} else {
|
||||
let staging_buffer = renderer.create_buffer_mapped(
|
||||
BufferInfo {
|
||||
|
@ -643,7 +638,8 @@ where
|
|||
},
|
||||
);
|
||||
|
||||
self.copy_staging_buffer_to_final_buffers(renderer, staging_buffer)
|
||||
self.copy_staging_buffer_to_final_buffers(renderer, staging_buffer);
|
||||
renderer.remove_buffer(staging_buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ pub struct Renderable {
|
|||
|
||||
// TODO: make these hidden if possible
|
||||
pub pipelines: Vec<Handle<PipelineDescriptor>>,
|
||||
pub render_resource_assignments: Option<RenderResourceAssignments>,
|
||||
pub render_resource_assignments: RenderResourceAssignments,
|
||||
}
|
||||
|
||||
impl Renderable {
|
||||
|
@ -35,7 +35,7 @@ impl Default for Renderable {
|
|||
pipelines: vec![
|
||||
Handle::new(0), // TODO: this could be better
|
||||
],
|
||||
render_resource_assignments: None,
|
||||
render_resource_assignments: RenderResourceAssignments::default(),
|
||||
is_instanced: false,
|
||||
}
|
||||
}
|
||||
|
@ -232,14 +232,12 @@ pub fn update_shader_assignments(world: &mut World, resources: &mut Resources) {
|
|||
&mut pipeline_descriptor_storage,
|
||||
&mut shader_storage,
|
||||
&renderable.pipelines,
|
||||
renderable.render_resource_assignments.as_ref().unwrap(),
|
||||
&renderable.render_resource_assignments,
|
||||
);
|
||||
|
||||
// reset shader_defs so they can be changed next frame
|
||||
renderable
|
||||
.render_resource_assignments
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.shader_defs
|
||||
.clear();
|
||||
}
|
||||
|
|
|
@ -55,5 +55,5 @@ pub trait RenderPass {
|
|||
fn set_index_buffer(&mut self, resource: RenderResource, offset: u64);
|
||||
fn set_vertex_buffer(&mut self, start_slot: u32, resource: RenderResource, offset: u64);
|
||||
fn draw_indexed(&mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>);
|
||||
fn set_bind_groups(&mut self, render_resource_assignments: Option<&RenderResourceAssignments>);
|
||||
fn set_render_resource_assignments(&mut self, render_resource_assignments: Option<&RenderResourceAssignments>) -> Option<Range<u32>>;
|
||||
}
|
||||
|
|
|
@ -38,7 +38,10 @@ impl<'a, 'b, 'c, 'd> RenderPass for WgpuRenderPass<'a, 'b, 'c, 'd> {
|
|||
.draw_indexed(indices, base_vertex, instances);
|
||||
}
|
||||
|
||||
fn set_bind_groups(&mut self, render_resource_assignments: Option<&RenderResourceAssignments>) {
|
||||
fn set_render_resource_assignments(
|
||||
&mut self,
|
||||
render_resource_assignments: Option<&RenderResourceAssignments>,
|
||||
) -> Option<Range<u32>> {
|
||||
let pipeline_layout = self.pipeline_descriptor.get_layout().unwrap();
|
||||
for bind_group in pipeline_layout.bind_groups.iter() {
|
||||
let bind_group_id = bind_group.get_hash().unwrap();
|
||||
|
@ -96,5 +99,7 @@ impl<'a, 'b, 'c, 'd> RenderPass for WgpuRenderPass<'a, 'b, 'c, 'd> {
|
|||
dynamic_uniform_indices.as_slice(),
|
||||
);
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue