mirror of
https://github.com/bevyengine/bevy
synced 2024-09-20 06:22:01 +00:00
RenderResourceSet builder pattern
This commit is contained in:
parent
e8e3e3c20f
commit
3c3449b719
4 changed files with 126 additions and 53 deletions
|
@ -9,7 +9,7 @@ use crate::{
|
|||
use bevy_asset::{Assets, Handle};
|
||||
use bevy_property::Properties;
|
||||
use legion::{
|
||||
prelude::{Com, ComMut, Res},
|
||||
prelude::{ComMut, Res},
|
||||
storage::Component,
|
||||
};
|
||||
use std::{ops::Range, sync::Arc};
|
||||
|
@ -146,17 +146,17 @@ impl<'a> DrawContext<'a> {
|
|||
self.draw.render_commands.push(render_command);
|
||||
}
|
||||
|
||||
pub fn draw<T: Drawable>(&mut self, drawable: &T) {
|
||||
pub fn draw<T: Drawable>(&mut self, drawable: &mut T) {
|
||||
drawable.draw(self);
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Drawable {
|
||||
fn draw(&self, draw: &mut DrawContext);
|
||||
fn draw(&mut self, draw: &mut DrawContext);
|
||||
}
|
||||
|
||||
impl Drawable for RenderPipelines {
|
||||
fn draw(&self, draw: &mut DrawContext) {
|
||||
fn draw(&mut self, draw: &mut DrawContext) {
|
||||
for pipeline_handle in self.compiled_pipelines.iter() {
|
||||
let pipeline = draw.pipelines.get(pipeline_handle).unwrap();
|
||||
let layout = pipeline.get_layout().unwrap();
|
||||
|
@ -209,11 +209,11 @@ pub fn draw_system<T: Drawable + Component>(
|
|||
render_resource_assignments: Res<RenderResourceAssignments>,
|
||||
render_resources: Res<RenderResources>,
|
||||
mut draw: ComMut<Draw>,
|
||||
drawable: Com<T>,
|
||||
mut drawable: ComMut<T>,
|
||||
) {
|
||||
let context = &*render_resources.context;
|
||||
let mut draw_context = draw.get_context(&pipelines, context, &render_resource_assignments);
|
||||
draw_context.draw(drawable.as_ref());
|
||||
draw_context.draw(drawable.as_mut());
|
||||
}
|
||||
|
||||
pub fn clear_draw_system(mut draw: ComMut<Draw>) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
mod buffer;
|
||||
mod entities_waiting_for_assets;
|
||||
mod render_resource;
|
||||
mod render_resource_set;
|
||||
mod render_resource_assignments;
|
||||
mod resource_info;
|
||||
mod systems;
|
||||
|
@ -8,6 +9,7 @@ mod systems;
|
|||
pub use buffer::*;
|
||||
pub use entities_waiting_for_assets::*;
|
||||
pub use render_resource::*;
|
||||
pub use render_resource_set::*;
|
||||
pub use render_resource_assignments::*;
|
||||
pub use resource_info::*;
|
||||
pub use systems::*;
|
|
@ -1,10 +1,9 @@
|
|||
use super::RenderResourceId;
|
||||
use super::{RenderResourceId, RenderResourceSet, RenderResourceSetId};
|
||||
use crate::pipeline::{BindGroupDescriptor, BindGroupDescriptorId, PipelineSpecialization};
|
||||
use std::{
|
||||
collections::{hash_map::DefaultHasher, HashMap, HashSet},
|
||||
collections::{HashMap, HashSet},
|
||||
hash::{Hash, Hasher},
|
||||
ops::Range,
|
||||
sync::Arc,
|
||||
};
|
||||
use uuid::Uuid;
|
||||
|
||||
|
@ -29,20 +28,6 @@ impl RenderResourceAssignment {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Debug)]
|
||||
pub struct IndexedRenderResourceAssignment {
|
||||
pub index: u32,
|
||||
pub assignment: RenderResourceAssignment,
|
||||
}
|
||||
|
||||
// TODO: consider renaming this to BindGroup for parity with renderer terminology
|
||||
#[derive(Eq, PartialEq, Debug)]
|
||||
pub struct RenderResourceSet {
|
||||
pub id: RenderResourceSetId,
|
||||
pub indexed_assignments: Vec<IndexedRenderResourceAssignment>,
|
||||
pub dynamic_uniform_indices: Option<Arc<Vec<u32>>>,
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Debug)]
|
||||
pub enum RenderResourceSetStatus {
|
||||
Changed(RenderResourceSetId),
|
||||
|
@ -103,7 +88,7 @@ impl RenderResourceAssignments {
|
|||
&mut self,
|
||||
bind_group_descriptor: &BindGroupDescriptor,
|
||||
) -> RenderResourceSetStatus {
|
||||
let resource_set = self.generate_render_resource_set(bind_group_descriptor);
|
||||
let resource_set = self.build_render_resource_set(bind_group_descriptor);
|
||||
if let Some(resource_set) = resource_set {
|
||||
let id = resource_set.id;
|
||||
self.render_resource_sets.insert(id, resource_set);
|
||||
|
@ -149,42 +134,21 @@ impl RenderResourceAssignments {
|
|||
})
|
||||
}
|
||||
|
||||
fn generate_render_resource_set(
|
||||
fn build_render_resource_set(
|
||||
&self,
|
||||
bind_group_descriptor: &BindGroupDescriptor,
|
||||
) -> Option<RenderResourceSet> {
|
||||
let mut hasher = DefaultHasher::new();
|
||||
let mut indices = Vec::new();
|
||||
let mut indexed_assignments = Vec::new();
|
||||
let mut render_resource_set_builder = RenderResourceSet::build();
|
||||
for binding_descriptor in bind_group_descriptor.bindings.iter() {
|
||||
if let Some(assignment) = self.get(&binding_descriptor.name) {
|
||||
indexed_assignments.push(IndexedRenderResourceAssignment {
|
||||
assignment: assignment.clone(),
|
||||
index: binding_descriptor.index,
|
||||
});
|
||||
let resource = assignment.get_resource();
|
||||
resource.hash(&mut hasher);
|
||||
if let RenderResourceAssignment::Buffer {
|
||||
dynamic_index: Some(index),
|
||||
..
|
||||
} = assignment
|
||||
{
|
||||
indices.push(*index);
|
||||
}
|
||||
render_resource_set_builder = render_resource_set_builder
|
||||
.add_assignment(binding_descriptor.index, assignment.clone());
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
Some(RenderResourceSet {
|
||||
id: RenderResourceSetId(hasher.finish()),
|
||||
indexed_assignments,
|
||||
dynamic_uniform_indices: if indices.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(Arc::new(indices))
|
||||
},
|
||||
})
|
||||
Some(render_resource_set_builder.finish())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -197,9 +161,6 @@ impl Default for RenderResourceAssignmentsId {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Hash, Eq, PartialEq, Debug, Copy, Clone)]
|
||||
pub struct RenderResourceSetId(u64);
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
110
crates/bevy_render/src/render_resource/render_resource_set.rs
Normal file
110
crates/bevy_render/src/render_resource/render_resource_set.rs
Normal file
|
@ -0,0 +1,110 @@
|
|||
use super::{RenderResourceAssignment, RenderResourceId};
|
||||
use std::{
|
||||
collections::hash_map::DefaultHasher,
|
||||
hash::{Hash, Hasher},
|
||||
ops::Range,
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
#[derive(Hash, Eq, PartialEq, Debug, Copy, Clone)]
|
||||
pub struct RenderResourceSetId(pub u64);
|
||||
|
||||
#[derive(Eq, PartialEq, Debug)]
|
||||
pub struct IndexedRenderResourceAssignment {
|
||||
pub index: u32,
|
||||
pub assignment: RenderResourceAssignment,
|
||||
}
|
||||
|
||||
// TODO: consider renaming this to BindGroup for parity with renderer terminology
|
||||
#[derive(Eq, PartialEq, Debug)]
|
||||
pub struct RenderResourceSet {
|
||||
pub id: RenderResourceSetId,
|
||||
pub indexed_assignments: Vec<IndexedRenderResourceAssignment>,
|
||||
pub dynamic_uniform_indices: Option<Arc<Vec<u32>>>,
|
||||
}
|
||||
|
||||
impl RenderResourceSet {
|
||||
pub fn build() -> RenderResourceSetBuilder {
|
||||
RenderResourceSetBuilder::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct RenderResourceSetBuilder {
|
||||
pub indexed_assignments: Vec<IndexedRenderResourceAssignment>,
|
||||
pub dynamic_uniform_indices: Vec<u32>,
|
||||
pub hasher: DefaultHasher,
|
||||
}
|
||||
|
||||
impl RenderResourceSetBuilder {
|
||||
pub fn add_assignment(mut self, index: u32, assignment: RenderResourceAssignment) -> Self {
|
||||
if let RenderResourceAssignment::Buffer {
|
||||
dynamic_index: Some(dynamic_index),
|
||||
..
|
||||
} = assignment
|
||||
{
|
||||
self.dynamic_uniform_indices.push(dynamic_index);
|
||||
}
|
||||
|
||||
let resource = assignment.get_resource();
|
||||
resource.hash(&mut self.hasher);
|
||||
self.indexed_assignments
|
||||
.push(IndexedRenderResourceAssignment { index, assignment });
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_texture(self, index: u32, render_resource: RenderResourceId) -> Self {
|
||||
self.add_assignment(index, RenderResourceAssignment::Texture(render_resource))
|
||||
}
|
||||
|
||||
pub fn add_sampler(self, index: u32, render_resource: RenderResourceId) -> Self {
|
||||
self.add_assignment(index, RenderResourceAssignment::Sampler(render_resource))
|
||||
}
|
||||
|
||||
pub fn add_buffer(
|
||||
self,
|
||||
index: u32,
|
||||
render_resource: RenderResourceId,
|
||||
range: Range<u64>,
|
||||
) -> Self {
|
||||
self.add_assignment(
|
||||
index,
|
||||
RenderResourceAssignment::Buffer {
|
||||
resource: render_resource,
|
||||
range,
|
||||
dynamic_index: None,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn add_dynamic_buffer(
|
||||
self,
|
||||
index: u32,
|
||||
render_resource: RenderResourceId,
|
||||
range: Range<u64>,
|
||||
dynamic_index: u32,
|
||||
) -> Self {
|
||||
self.add_assignment(
|
||||
index,
|
||||
RenderResourceAssignment::Buffer {
|
||||
resource: render_resource,
|
||||
range,
|
||||
dynamic_index: Some(dynamic_index),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn finish(mut self) -> RenderResourceSet {
|
||||
// this sort ensures that RenderResourceSets are insertion-order independent
|
||||
self.indexed_assignments.sort_by_key(|i| i.index);
|
||||
RenderResourceSet {
|
||||
id: RenderResourceSetId(self.hasher.finish()),
|
||||
indexed_assignments: self.indexed_assignments,
|
||||
dynamic_uniform_indices: if self.dynamic_uniform_indices.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(Arc::new(self.dynamic_uniform_indices))
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue