RenderResourceSet builder pattern

This commit is contained in:
Carter Anderson 2020-06-10 15:45:33 -07:00
parent e8e3e3c20f
commit 3c3449b719
4 changed files with 126 additions and 53 deletions

View file

@ -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>) {

View file

@ -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::*;

View file

@ -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::*;

View 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))
},
}
}
}