RenderResourceSet builder pattern
This commit is contained in:
		
							parent
							
								
									e8e3e3c20f
								
							
						
					
					
						commit
						3c3449b719
					
				@ -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 New Issue
	
	Block a user