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_asset::{Assets, Handle};
|
||||||
use bevy_property::Properties;
|
use bevy_property::Properties;
|
||||||
use legion::{
|
use legion::{
|
||||||
prelude::{Com, ComMut, Res},
|
prelude::{ComMut, Res},
|
||||||
storage::Component,
|
storage::Component,
|
||||||
};
|
};
|
||||||
use std::{ops::Range, sync::Arc};
|
use std::{ops::Range, sync::Arc};
|
||||||
|
@ -146,17 +146,17 @@ impl<'a> DrawContext<'a> {
|
||||||
self.draw.render_commands.push(render_command);
|
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);
|
drawable.draw(self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Drawable {
|
pub trait Drawable {
|
||||||
fn draw(&self, draw: &mut DrawContext);
|
fn draw(&mut self, draw: &mut DrawContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drawable for RenderPipelines {
|
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() {
|
for pipeline_handle in self.compiled_pipelines.iter() {
|
||||||
let pipeline = draw.pipelines.get(pipeline_handle).unwrap();
|
let pipeline = draw.pipelines.get(pipeline_handle).unwrap();
|
||||||
let layout = pipeline.get_layout().unwrap();
|
let layout = pipeline.get_layout().unwrap();
|
||||||
|
@ -209,11 +209,11 @@ pub fn draw_system<T: Drawable + Component>(
|
||||||
render_resource_assignments: Res<RenderResourceAssignments>,
|
render_resource_assignments: Res<RenderResourceAssignments>,
|
||||||
render_resources: Res<RenderResources>,
|
render_resources: Res<RenderResources>,
|
||||||
mut draw: ComMut<Draw>,
|
mut draw: ComMut<Draw>,
|
||||||
drawable: Com<T>,
|
mut drawable: ComMut<T>,
|
||||||
) {
|
) {
|
||||||
let context = &*render_resources.context;
|
let context = &*render_resources.context;
|
||||||
let mut draw_context = draw.get_context(&pipelines, context, &render_resource_assignments);
|
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>) {
|
pub fn clear_draw_system(mut draw: ComMut<Draw>) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
mod buffer;
|
mod buffer;
|
||||||
mod entities_waiting_for_assets;
|
mod entities_waiting_for_assets;
|
||||||
mod render_resource;
|
mod render_resource;
|
||||||
|
mod render_resource_set;
|
||||||
mod render_resource_assignments;
|
mod render_resource_assignments;
|
||||||
mod resource_info;
|
mod resource_info;
|
||||||
mod systems;
|
mod systems;
|
||||||
|
@ -8,6 +9,7 @@ mod systems;
|
||||||
pub use buffer::*;
|
pub use buffer::*;
|
||||||
pub use entities_waiting_for_assets::*;
|
pub use entities_waiting_for_assets::*;
|
||||||
pub use render_resource::*;
|
pub use render_resource::*;
|
||||||
|
pub use render_resource_set::*;
|
||||||
pub use render_resource_assignments::*;
|
pub use render_resource_assignments::*;
|
||||||
pub use resource_info::*;
|
pub use resource_info::*;
|
||||||
pub use systems::*;
|
pub use systems::*;
|
|
@ -1,10 +1,9 @@
|
||||||
use super::RenderResourceId;
|
use super::{RenderResourceId, RenderResourceSet, RenderResourceSetId};
|
||||||
use crate::pipeline::{BindGroupDescriptor, BindGroupDescriptorId, PipelineSpecialization};
|
use crate::pipeline::{BindGroupDescriptor, BindGroupDescriptorId, PipelineSpecialization};
|
||||||
use std::{
|
use std::{
|
||||||
collections::{hash_map::DefaultHasher, HashMap, HashSet},
|
collections::{HashMap, HashSet},
|
||||||
hash::{Hash, Hasher},
|
hash::{Hash, Hasher},
|
||||||
ops::Range,
|
ops::Range,
|
||||||
sync::Arc,
|
|
||||||
};
|
};
|
||||||
use uuid::Uuid;
|
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)]
|
#[derive(Eq, PartialEq, Debug)]
|
||||||
pub enum RenderResourceSetStatus {
|
pub enum RenderResourceSetStatus {
|
||||||
Changed(RenderResourceSetId),
|
Changed(RenderResourceSetId),
|
||||||
|
@ -103,7 +88,7 @@ impl RenderResourceAssignments {
|
||||||
&mut self,
|
&mut self,
|
||||||
bind_group_descriptor: &BindGroupDescriptor,
|
bind_group_descriptor: &BindGroupDescriptor,
|
||||||
) -> RenderResourceSetStatus {
|
) -> 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 {
|
if let Some(resource_set) = resource_set {
|
||||||
let id = resource_set.id;
|
let id = resource_set.id;
|
||||||
self.render_resource_sets.insert(id, resource_set);
|
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,
|
&self,
|
||||||
bind_group_descriptor: &BindGroupDescriptor,
|
bind_group_descriptor: &BindGroupDescriptor,
|
||||||
) -> Option<RenderResourceSet> {
|
) -> Option<RenderResourceSet> {
|
||||||
let mut hasher = DefaultHasher::new();
|
let mut render_resource_set_builder = RenderResourceSet::build();
|
||||||
let mut indices = Vec::new();
|
|
||||||
let mut indexed_assignments = Vec::new();
|
|
||||||
for binding_descriptor in bind_group_descriptor.bindings.iter() {
|
for binding_descriptor in bind_group_descriptor.bindings.iter() {
|
||||||
if let Some(assignment) = self.get(&binding_descriptor.name) {
|
if let Some(assignment) = self.get(&binding_descriptor.name) {
|
||||||
indexed_assignments.push(IndexedRenderResourceAssignment {
|
render_resource_set_builder = render_resource_set_builder
|
||||||
assignment: assignment.clone(),
|
.add_assignment(binding_descriptor.index, 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);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(RenderResourceSet {
|
Some(render_resource_set_builder.finish())
|
||||||
id: RenderResourceSetId(hasher.finish()),
|
|
||||||
indexed_assignments,
|
|
||||||
dynamic_uniform_indices: if indices.is_empty() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(Arc::new(indices))
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,9 +161,6 @@ impl Default for RenderResourceAssignmentsId {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Hash, Eq, PartialEq, Debug, Copy, Clone)]
|
|
||||||
pub struct RenderResourceSetId(u64);
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
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