From fc4160ea4116fc8bf26b33c2dc51bc7c2af03cf3 Mon Sep 17 00:00:00 2001 From: Carter Anderson Date: Wed, 10 Jun 2020 18:54:17 -0700 Subject: [PATCH] AssetRenderResourceNodes now consume asset change events. Remove EntitiesWaitingForAssets in favor of DrawState. --- crates/bevy_asset/src/assets.rs | 1 + .../bevy_pbr/src/forward_pbr_render_graph.rs | 6 +- crates/bevy_render/src/lib.rs | 6 - crates/bevy_render/src/render_graph/nodes.rs | 4 +- .../src/render_graph/nodes/pass_node.rs | 77 ++++++- ...iform_node.rs => render_resources_node.rs} | 205 +++++++++--------- .../entities_waiting_for_assets.rs | 31 --- crates/bevy_render/src/render_resource/mod.rs | 2 - .../render_resource_assignments.rs | 15 +- .../render_resource/render_resource_set.rs | 6 +- crates/bevy_sprite/src/render/mod.rs | 10 +- examples/shader/shader_custom_material.rs | 2 +- examples/shader/shader_defs.rs | 2 +- src/prelude.rs | 2 +- 14 files changed, 202 insertions(+), 167 deletions(-) rename crates/bevy_render/src/render_graph/nodes/{uniform_node.rs => render_resources_node.rs} (77%) delete mode 100644 crates/bevy_render/src/render_resource/entities_waiting_for_assets.rs diff --git a/crates/bevy_asset/src/assets.rs b/crates/bevy_asset/src/assets.rs index 0f4ad533c4..9f5d01d954 100644 --- a/crates/bevy_asset/src/assets.rs +++ b/crates/bevy_asset/src/assets.rs @@ -71,6 +71,7 @@ impl Assets { } pub fn get_mut(&mut self, handle: &Handle) -> Option<&mut T> { + self.events.send(AssetEvent::Modified { handle: *handle }); self.assets.get_mut(&handle) } diff --git a/crates/bevy_pbr/src/forward_pbr_render_graph.rs b/crates/bevy_pbr/src/forward_pbr_render_graph.rs index e6c3a3f36a..bebf7ea8a6 100644 --- a/crates/bevy_pbr/src/forward_pbr_render_graph.rs +++ b/crates/bevy_pbr/src/forward_pbr_render_graph.rs @@ -4,7 +4,7 @@ use bevy_render::{ base_render_graph, pipeline::PipelineDescriptor, render_graph::{ - nodes::{AssetUniformNode, UniformNode}, + nodes::{AssetRenderResourcesNode, RenderResourcesNode}, RenderGraph, }, shader::Shader, @@ -28,10 +28,10 @@ pub trait ForwardPbrRenderGraphBuilder { impl ForwardPbrRenderGraphBuilder for RenderGraph { fn add_pbr_graph(&mut self, resources: &Resources) -> &mut Self { - self.add_system_node(node::TRANSFORM, UniformNode::::new(true)); + self.add_system_node(node::TRANSFORM, RenderResourcesNode::::new(true)); self.add_system_node( node::STANDARD_MATERIAL, - AssetUniformNode::::new(true), + AssetRenderResourcesNode::::new(true), ); self.add_system_node(node::LIGHTS, LightsNode::new(10)); let mut shaders = resources.get_mut::>().unwrap(); diff --git a/crates/bevy_render/src/lib.rs b/crates/bevy_render/src/lib.rs index 62ddf1dc19..cc87e895c4 100644 --- a/crates/bevy_render/src/lib.rs +++ b/crates/bevy_render/src/lib.rs @@ -39,7 +39,6 @@ use draw::{clear_draw_system, Draw, RenderPipelines}; use legion::prelude::IntoSystem; use mesh::mesh_resource_provider_system; use render_graph::RenderGraph; -use render_resource::EntitiesWaitingForAssets; use std::ops::Range; use texture::{PngTextureLoader, TextureResourceSystemState}; @@ -83,7 +82,6 @@ impl AppPlugin for RenderPlugin { .init_resource::() .init_resource::() .init_resource::() - .init_resource::() .init_resource::() .add_system_to_stage(bevy_app::stage::PRE_UPDATE, clear_draw_system.system()) .init_system_to_stage( @@ -94,10 +92,6 @@ impl AppPlugin for RenderPlugin { bevy_app::stage::POST_UPDATE, camera::camera_system::, ) - .add_system_to_stage( - bevy_app::stage::PRE_UPDATE, - EntitiesWaitingForAssets::clear_system.system(), - ) .init_system_to_stage(stage::RENDER_RESOURCE, mesh_resource_provider_system) .add_system_to_stage( stage::RENDER_RESOURCE, diff --git a/crates/bevy_render/src/render_graph/nodes.rs b/crates/bevy_render/src/render_graph/nodes.rs index 685514b1f6..e449bdc8eb 100644 --- a/crates/bevy_render/src/render_graph/nodes.rs +++ b/crates/bevy_render/src/render_graph/nodes.rs @@ -1,13 +1,13 @@ mod camera_node; mod pass_node; mod texture_copy_node; -mod uniform_node; +mod render_resources_node; mod window_swapchain_node; mod window_texture_node; pub use camera_node::*; pub use pass_node::*; pub use texture_copy_node::*; -pub use uniform_node::*; +pub use render_resources_node::*; pub use window_swapchain_node::*; pub use window_texture_node::*; diff --git a/crates/bevy_render/src/render_graph/nodes/pass_node.rs b/crates/bevy_render/src/render_graph/nodes/pass_node.rs index 208dd8e3ac..7800ab7f66 100644 --- a/crates/bevy_render/src/render_graph/nodes/pass_node.rs +++ b/crates/bevy_render/src/render_graph/nodes/pass_node.rs @@ -1,10 +1,14 @@ use crate::{ draw::{Draw, RenderCommand}, pass::{PassDescriptor, TextureAttachment}, + pipeline::PipelineDescriptor, render_graph::{Node, ResourceSlotInfo, ResourceSlots}, - render_resource::{EntitiesWaitingForAssets, RenderResourceAssignments, ResourceInfo}, + render_resource::{ + RenderResourceAssignments, RenderResourceId, RenderResourceSetId, ResourceInfo, + }, renderer::RenderContext, }; +use bevy_asset::{Assets, Handle}; use legion::prelude::*; pub struct MainPassNode { @@ -63,8 +67,8 @@ impl Node for MainPassNode { input: &ResourceSlots, _output: &mut ResourceSlots, ) { - let entities_waiting_for_assets = resources.get::().unwrap(); let render_resource_assignments = resources.get::().unwrap(); + let pipelines = resources.get::>().unwrap(); for (i, color_attachment) in self.descriptor.color_attachments.iter_mut().enumerate() { if let Some(input_index) = self.color_attachment_input_indices[i] { @@ -85,8 +89,9 @@ impl Node for MainPassNode { &self.descriptor, &render_resource_assignments, &mut |render_pass| { - for (entity, draw) in >::query().iter_entities(&world) { - if !draw.is_visible || entities_waiting_for_assets.contains(&entity) { + let mut draw_state = DrawState::default(); + for draw in >::query().iter(&world) { + if !draw.is_visible { continue; } @@ -95,17 +100,23 @@ impl Node for MainPassNode { RenderCommand::SetPipeline { pipeline } => { // TODO: Filter pipelines render_pass.set_pipeline(*pipeline); + let descriptor = pipelines.get(pipeline).unwrap(); + draw_state.set_pipeline(*pipeline, descriptor); } RenderCommand::DrawIndexed { base_vertex, indices, instances, } => { - render_pass.draw_indexed( - indices.clone(), - *base_vertex, - instances.clone(), - ); + if draw_state.can_draw_indexed() { + render_pass.draw_indexed( + indices.clone(), + *base_vertex, + instances.clone(), + ); + } else { + log::info!("Could not draw indexed because the pipeline layout wasn't fully set for pipeline: {:?}", draw_state.pipeline); + } } RenderCommand::SetVertexBuffer { buffer, @@ -113,9 +124,11 @@ impl Node for MainPassNode { slot, } => { render_pass.set_vertex_buffer(*slot, *buffer, *offset); + draw_state.set_vertex_buffer(*slot, *buffer); } RenderCommand::SetIndexBuffer { buffer, offset } => { render_pass.set_index_buffer(*buffer, *offset); + draw_state.set_index_buffer(*buffer) } RenderCommand::SetBindGroup { index, @@ -131,6 +144,7 @@ impl Node for MainPassNode { .as_ref() .map(|indices| indices.as_slice()), ); + draw_state.set_bind_group(*index, *render_resource_set); } } } @@ -139,3 +153,48 @@ impl Node for MainPassNode { ); } } + +/// Tracks the current pipeline state to ensure draw calls are valid. +#[derive(Default)] +struct DrawState { + pipeline: Option>, + bind_groups: Vec>, + vertex_buffers: Vec>, + index_buffer: Option, +} + +impl DrawState { + pub fn set_bind_group(&mut self, index: u32, render_resource_set: RenderResourceSetId) { + self.bind_groups[index as usize] = Some(render_resource_set); + } + + pub fn set_vertex_buffer(&mut self, index: u32, buffer: RenderResourceId) { + self.vertex_buffers[index as usize] = Some(buffer); + } + + pub fn set_index_buffer(&mut self, buffer: RenderResourceId) { + self.index_buffer = Some(buffer); + } + + pub fn can_draw_indexed(&self) -> bool { + self.bind_groups.iter().all(|b| b.is_some()) + && self.vertex_buffers.iter().all(|v| v.is_some()) + && self.index_buffer.is_some() + } + + pub fn set_pipeline( + &mut self, + handle: Handle, + descriptor: &PipelineDescriptor, + ) { + self.bind_groups.clear(); + self.vertex_buffers.clear(); + self.index_buffer = None; + + self.pipeline = Some(handle); + let layout = descriptor.get_layout().unwrap(); + self.bind_groups.resize(layout.bind_groups.len(), None); + self.vertex_buffers + .resize(layout.vertex_buffer_descriptors.len(), None); + } +} diff --git a/crates/bevy_render/src/render_graph/nodes/uniform_node.rs b/crates/bevy_render/src/render_graph/nodes/render_resources_node.rs similarity index 77% rename from crates/bevy_render/src/render_graph/nodes/uniform_node.rs rename to crates/bevy_render/src/render_graph/nodes/render_resources_node.rs index b9ba3dc5ce..26cec0dc79 100644 --- a/crates/bevy_render/src/render_graph/nodes/uniform_node.rs +++ b/crates/bevy_render/src/render_graph/nodes/render_resources_node.rs @@ -2,19 +2,21 @@ use crate::{ draw::{Draw, RenderPipelines}, render_graph::{CommandQueue, Node, ResourceSlots, SystemNode}, render_resource::{ - self, BufferInfo, BufferUsage, EntitiesWaitingForAssets, RenderResourceAssignment, - RenderResourceAssignments, RenderResourceAssignmentsId, RenderResourceHints, - RenderResourceId, + self, BufferInfo, BufferUsage, RenderResourceAssignment, RenderResourceAssignments, + RenderResourceAssignmentsId, RenderResourceHints, RenderResourceId, }, renderer::{RenderContext, RenderResourceContext, RenderResources}, texture, }; -use bevy_app::EventReader; +use bevy_app::{EventReader, Events}; use bevy_asset::{AssetEvent, Assets, Handle}; use legion::prelude::*; use render_resource::ResourceInfo; -use std::{collections::HashMap, marker::PhantomData}; +use std::{ + collections::{HashMap, HashSet}, + marker::PhantomData, +}; pub const BIND_BUFFER_ALIGNMENT: usize = 256; #[derive(Debug)] @@ -25,7 +27,7 @@ struct QueuedBufferWrite { #[derive(Debug)] struct BufferArrayStatus { - new_item_count: usize, + changed_item_count: usize, item_size: usize, aligned_size: usize, staging_buffer_offset: usize, @@ -78,15 +80,15 @@ impl UniformBufferArrays where T: render_resource::RenderResources, { - fn reset_new_item_counts(&mut self) { + fn reset_changed_item_counts(&mut self) { for buffer_status in self.uniform_arrays.iter_mut() { if let Some((_name, buffer_status)) = buffer_status { - buffer_status.new_item_count = 0; + buffer_status.changed_item_count = 0; } } } - fn increment_uniform_counts(&mut self, uniforms: &T) { + fn increment_changed_item_counts(&mut self, uniforms: &T) { if self.uniform_arrays.len() != uniforms.render_resources_len() { self.uniform_arrays .resize_with(uniforms.render_resources_len(), || None); @@ -96,12 +98,12 @@ where let render_resource_name = uniforms.get_render_resource_name(i).unwrap(); let size = render_resource.buffer_byte_len().unwrap(); if let Some((ref _name, ref mut buffer_array_status)) = self.uniform_arrays[i] { - buffer_array_status.new_item_count += 1; + buffer_array_status.changed_item_count += 1; } else { self.uniform_arrays[i] = Some(( render_resource_name.to_string(), BufferArrayStatus { - new_item_count: 1, + changed_item_count: 1, queued_buffer_writes: Vec::new(), aligned_size: Self::get_aligned_dynamic_uniform_size(size), item_size: size, @@ -134,7 +136,7 @@ where } buffer_array_status.queued_buffer_writes = - Vec::with_capacity(buffer_array_status.new_item_count); + Vec::with_capacity(buffer_array_status.changed_item_count); } } } @@ -144,9 +146,9 @@ where render_resource_context: &dyn RenderResourceContext, align: bool, ) { - if buffer_array_status.current_item_capacity < buffer_array_status.new_item_count { + if buffer_array_status.current_item_capacity < buffer_array_status.changed_item_count { let new_capacity = - buffer_array_status.new_item_count + buffer_array_status.new_item_count / 2; + buffer_array_status.changed_item_count + buffer_array_status.changed_item_count / 2; let mut item_size = buffer_array_status.item_size; if align { item_size = Self::get_aligned_dynamic_uniform_size(item_size); @@ -177,7 +179,7 @@ where for dynamic_buffer_array_status in self.uniform_arrays.iter_mut() { if let Some((_name, ref mut buffer_array_status)) = dynamic_buffer_array_status { buffer_array_status.staging_buffer_offset = size; - size += buffer_array_status.item_size * buffer_array_status.new_item_count; + size += buffer_array_status.item_size * buffer_array_status.changed_item_count; } } @@ -298,7 +300,7 @@ where } #[derive(Default)] -pub struct UniformNode +pub struct RenderResourcesNode where T: render_resource::RenderResources, { @@ -307,12 +309,12 @@ where _marker: PhantomData, } -impl UniformNode +impl RenderResourcesNode where T: render_resource::RenderResources, { pub fn new(dynamic_uniforms: bool) -> Self { - UniformNode { + RenderResourcesNode { command_queue: CommandQueue::default(), dynamic_uniforms, _marker: PhantomData::default(), @@ -320,7 +322,7 @@ where } } -impl Node for UniformNode +impl Node for RenderResourcesNode where T: render_resource::RenderResources, { @@ -336,7 +338,7 @@ where } } -impl SystemNode for UniformNode +impl SystemNode for RenderResourcesNode where T: render_resource::RenderResources, { @@ -347,35 +349,30 @@ where // TODO: maybe run "update" here (move |world: &mut SubWorld, render_resources: Res, - entities_waiting_for_assets: Res, query: &mut Query<(Read, Read, Write)>| { let render_resource_context = &*render_resources.context; - uniform_buffer_arrays.reset_new_item_counts(); + uniform_buffer_arrays.reset_changed_item_counts(); // update uniforms info for (uniforms, draw, _render_pipelines) in query.iter_mut(world) { if !draw.is_visible { return; } - uniform_buffer_arrays.increment_uniform_counts(&uniforms); + uniform_buffer_arrays.increment_changed_item_counts(&uniforms); } uniform_buffer_arrays.setup_buffer_arrays(render_resource_context, dynamic_uniforms); let staging_buffer_size = uniform_buffer_arrays.update_staging_buffer_offsets(); - for (entity, (uniforms, draw, mut render_pipelines)) in - query.iter_entities_mut(world) - { + for (uniforms, draw, mut render_pipelines) in query.iter_mut(world) { if !draw.is_visible { return; } setup_uniform_texture_resources::( - entity, &uniforms, render_resource_context, - &entities_waiting_for_assets, &mut render_pipelines.render_resource_assignments, ) } @@ -403,9 +400,7 @@ where ..Default::default() }, &mut |mut staging_buffer, _render_resources| { - for (uniforms, draw, mut render_pipelines) in - query.iter_mut(world) - { + for (uniforms, draw, mut render_pipelines) in query.iter_mut(world) { if !draw.is_visible { return; } @@ -431,7 +426,7 @@ where } #[derive(Default)] -pub struct AssetUniformNode +pub struct AssetRenderResourcesNode where T: render_resource::RenderResources, { @@ -440,12 +435,12 @@ where _marker: PhantomData, } -impl AssetUniformNode +impl AssetRenderResourcesNode where T: render_resource::RenderResources, { pub fn new(dynamic_uniforms: bool) -> Self { - AssetUniformNode { + AssetRenderResourcesNode { dynamic_uniforms, command_queue: Default::default(), _marker: Default::default(), @@ -453,7 +448,7 @@ where } } -impl Node for AssetUniformNode +impl Node for AssetRenderResourcesNode where T: render_resource::RenderResources, { @@ -469,72 +464,79 @@ where } } -impl SystemNode for AssetUniformNode +const EXPECT_ASSET_MESSAGE: &str = "Only assets that exist should be in the modified assets list"; + +impl SystemNode for AssetRenderResourcesNode where T: render_resource::RenderResources, { fn get_system(&self) -> Box { let mut command_queue = self.command_queue.clone(); let mut uniform_buffer_arrays = UniformBufferArrays::::default(); + let mut asset_event_reader = EventReader::>::default(); + let mut asset_render_resource_assignments = + HashMap::, RenderResourceAssignments>::default(); let dynamic_uniforms = self.dynamic_uniforms; (move |world: &mut SubWorld, - assets: Res>, - render_resources: Res, - entities_waiting_for_assets: Res, - query: &mut Query<(Read>, Read, Write)>| { + assets: Res>, + asset_events: Res>>, + render_resources: Res, + query: &mut Query<(Read>, Read, Write)>| { let render_resource_context = &*render_resources.context; - uniform_buffer_arrays.reset_new_item_counts(); + uniform_buffer_arrays.reset_changed_item_counts(); + + let mut modified_assets = HashSet::new(); + for event in asset_event_reader.iter(&asset_events) { + match event { + AssetEvent::Created { handle } => { + modified_assets.insert(*handle); + } + AssetEvent::Modified { handle } => { + modified_assets.insert(*handle); + } + AssetEvent::Removed { handle } => { + // TODO: handle removals + modified_assets.remove(handle); + } + } + } // update uniform handles info - for (entity, (handle, draw, _render_pipelines)) in query.iter_entities_mut(world) { - if !draw.is_visible { - return; - } - - if let Some(uniforms) = assets.get(&handle) { - // TODO: only increment count if we haven't seen this uniform handle before - uniform_buffer_arrays.increment_uniform_counts(&uniforms); - } else { - entities_waiting_for_assets.add(entity) - } + for asset_handle in modified_assets.iter() { + let asset = assets.get(&asset_handle).expect(EXPECT_ASSET_MESSAGE); + uniform_buffer_arrays.increment_changed_item_counts(&asset); } uniform_buffer_arrays.setup_buffer_arrays(render_resource_context, dynamic_uniforms); let staging_buffer_size = uniform_buffer_arrays.update_staging_buffer_offsets(); - for (entity, (handle, draw, mut render_pipelines)) in - query.iter_entities_mut(world) - { - if !draw.is_visible { - return; - } - - if let Some(uniforms) = assets.get(&handle) { - setup_uniform_texture_resources::( - entity, - &uniforms, - render_resource_context, - &entities_waiting_for_assets, - &mut render_pipelines.render_resource_assignments, - ) - } + for asset_handle in modified_assets.iter() { + let asset = assets.get(&asset_handle).expect(EXPECT_ASSET_MESSAGE); + let mut render_resource_assignments = asset_render_resource_assignments + .entry(*asset_handle) + .or_insert_with(|| RenderResourceAssignments::default()); + setup_uniform_texture_resources::( + &asset, + render_resource_context, + &mut render_resource_assignments, + ); } + if staging_buffer_size == 0 { let mut staging_buffer: [u8; 0] = []; - for (handle, draw, mut render_pipelines) in query.iter_mut(world) { - if !draw.is_visible { - return; - } - if let Some(uniforms) = assets.get(&handle) { - // TODO: only setup buffer if we haven't seen this handle before - uniform_buffer_arrays.setup_uniform_buffer_resources( - &uniforms, - dynamic_uniforms, - render_resource_context, - &mut render_pipelines.render_resource_assignments, - &mut staging_buffer, - ); - } + for asset_handle in modified_assets.iter() { + let asset = assets.get(&asset_handle).expect(EXPECT_ASSET_MESSAGE); + let mut render_resource_assignments = asset_render_resource_assignments + .entry(*asset_handle) + .or_insert_with(|| RenderResourceAssignments::default()); + // TODO: only setup buffer if we haven't seen this handle before + uniform_buffer_arrays.setup_uniform_buffer_resources( + &asset, + dynamic_uniforms, + render_resource_context, + &mut render_resource_assignments, + &mut staging_buffer, + ); } } else { let staging_buffer = render_resource_context.create_buffer_mapped( @@ -544,20 +546,19 @@ where ..Default::default() }, &mut |mut staging_buffer, _render_resources| { - for (handle, draw, mut render_pipelines) in query.iter_mut(world) { - if !draw.is_visible { - return; - } - if let Some(uniforms) = assets.get(&handle) { - // TODO: only setup buffer if we haven't seen this handle before - uniform_buffer_arrays.setup_uniform_buffer_resources( - &uniforms, - dynamic_uniforms, - render_resource_context, - &mut render_pipelines.render_resource_assignments, - &mut staging_buffer, - ); - } + for asset_handle in modified_assets.iter() { + let asset = assets.get(&asset_handle).expect(EXPECT_ASSET_MESSAGE); + let mut render_resource_assignments = asset_render_resource_assignments + .entry(*asset_handle) + .or_insert_with(|| RenderResourceAssignments::default()); + // TODO: only setup buffer if we haven't seen this handle before + uniform_buffer_arrays.setup_uniform_buffer_resources( + &asset, + dynamic_uniforms, + render_resource_context, + &mut render_resource_assignments, + &mut staging_buffer, + ); } }, ); @@ -566,16 +567,20 @@ where .copy_staging_buffer_to_final_buffers(&mut command_queue, staging_buffer); command_queue.free_buffer(staging_buffer); } + + for (asset_handle, _draw, mut render_pipelines) in query.iter_mut(world) { + if let Some(asset_assignments) = asset_render_resource_assignments.get(&asset_handle) { + render_pipelines.render_resource_assignments.extend(asset_assignments); + } + } }) .system() } } fn setup_uniform_texture_resources( - entity: Entity, uniforms: &T, render_resource_context: &dyn RenderResourceContext, - entities_waiting_for_assets: &EntitiesWaitingForAssets, render_resource_assignments: &mut RenderResourceAssignments, ) where T: render_resource::RenderResources, @@ -600,11 +605,7 @@ fn setup_uniform_texture_resources( RenderResourceAssignment::Sampler(sampler_resource), ); continue; - } else { - entities_waiting_for_assets.add(entity); } - } else { - entities_waiting_for_assets.add(entity); } } } diff --git a/crates/bevy_render/src/render_resource/entities_waiting_for_assets.rs b/crates/bevy_render/src/render_resource/entities_waiting_for_assets.rs deleted file mode 100644 index 1442830e3a..0000000000 --- a/crates/bevy_render/src/render_resource/entities_waiting_for_assets.rs +++ /dev/null @@ -1,31 +0,0 @@ -use legion::prelude::{Entity, Res}; -use std::{collections::HashSet, sync::RwLock}; - -#[derive(Default)] -pub struct EntitiesWaitingForAssets { - pub entities: RwLock>, -} - -impl EntitiesWaitingForAssets { - pub fn add(&self, entity: Entity) { - self.entities - .write() - .expect("RwLock poisoned") - .insert(entity); - } - - pub fn contains(&self, entity: &Entity) -> bool { - self.entities - .read() - .expect("RwLock poisoned") - .contains(entity) - } - - pub fn clear(&self) { - self.entities.write().expect("RwLock poisoned").clear(); - } - - pub fn clear_system(entities_waiting_for_assets: Res) { - entities_waiting_for_assets.clear(); - } -} diff --git a/crates/bevy_render/src/render_resource/mod.rs b/crates/bevy_render/src/render_resource/mod.rs index 4b6b0621bc..1814ac6e50 100644 --- a/crates/bevy_render/src/render_resource/mod.rs +++ b/crates/bevy_render/src/render_resource/mod.rs @@ -1,5 +1,4 @@ mod buffer; -mod entities_waiting_for_assets; mod render_resource; mod render_resource_set; mod render_resource_assignments; @@ -7,7 +6,6 @@ mod resource_info; 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::*; diff --git a/crates/bevy_render/src/render_resource/render_resource_assignments.rs b/crates/bevy_render/src/render_resource/render_resource_assignments.rs index 75d3c7ae6c..3a03262a8a 100644 --- a/crates/bevy_render/src/render_resource/render_resource_assignments.rs +++ b/crates/bevy_render/src/render_resource/render_resource_assignments.rs @@ -2,7 +2,7 @@ use super::{RenderResourceId, RenderResourceSet, RenderResourceSetId}; use crate::pipeline::{BindGroupDescriptor, BindGroupDescriptorId, PipelineSpecialization}; use std::{ collections::{HashMap, HashSet}, - hash::{Hash, Hasher}, + hash::Hash, ops::Range, }; use uuid::Uuid; @@ -60,6 +60,7 @@ impl RenderResourceAssignments { fn try_set_dirty(&mut self, name: &str, assignment: &RenderResourceAssignment) { if let Some(current_assignment) = self.render_resources.get(name) { if current_assignment != assignment { + // TODO: this is crude. we shouldn't need to invalidate all render resource sets for id in self.render_resource_sets.keys() { self.dirty_render_resource_sets.insert(*id); } @@ -67,6 +68,18 @@ impl RenderResourceAssignments { } } + pub fn extend(&mut self, render_resource_assignments: &RenderResourceAssignments) { + for (name, assignment) in render_resource_assignments.render_resources.iter() { + self.set(name, assignment.clone()); + } + + for (name, (vertex_buffer, index_buffer)) in + render_resource_assignments.vertex_buffers.iter() + { + self.set_vertex_buffer(name, *vertex_buffer, index_buffer.clone()); + } + } + pub fn get_vertex_buffer( &self, name: &str, diff --git a/crates/bevy_render/src/render_resource/render_resource_set.rs b/crates/bevy_render/src/render_resource/render_resource_set.rs index 175c124c1b..8acb9e8dc0 100644 --- a/crates/bevy_render/src/render_resource/render_resource_set.rs +++ b/crates/bevy_render/src/render_resource/render_resource_set.rs @@ -16,10 +16,10 @@ pub struct IndexedRenderResourceAssignment { } // TODO: consider renaming this to BindGroup for parity with renderer terminology -#[derive(Eq, PartialEq, Debug)] +#[derive(Clone, Eq, PartialEq, Debug)] pub struct RenderResourceSet { pub id: RenderResourceSetId, - pub indexed_assignments: Vec, + pub indexed_assignments: Arc>, pub dynamic_uniform_indices: Option>>, } @@ -99,7 +99,7 @@ impl RenderResourceSetBuilder { self.indexed_assignments.sort_by_key(|i| i.index); RenderResourceSet { id: RenderResourceSetId(self.hasher.finish()), - indexed_assignments: self.indexed_assignments, + indexed_assignments: Arc::new(self.indexed_assignments), dynamic_uniform_indices: if self.dynamic_uniform_indices.is_empty() { None } else { diff --git a/crates/bevy_sprite/src/render/mod.rs b/crates/bevy_sprite/src/render/mod.rs index e70515d562..b88240c1c7 100644 --- a/crates/bevy_sprite/src/render/mod.rs +++ b/crates/bevy_sprite/src/render/mod.rs @@ -4,7 +4,7 @@ use bevy_render::{ base_render_graph, pipeline::{state_descriptors::*, PipelineDescriptor}, render_graph::{ - nodes::{AssetUniformNode, UniformNode}, + nodes::{AssetRenderResourcesNode, RenderResourcesNode}, RenderGraph, }, shader::{Shader, ShaderStage, ShaderStages}, @@ -123,23 +123,23 @@ impl SpriteRenderGraphBuilder for RenderGraph { fn add_sprite_graph(&mut self, resources: &Resources) -> &mut Self { self.add_system_node( node::COLOR_MATERIAL, - AssetUniformNode::::new(false), + AssetRenderResourcesNode::::new(false), ); self.add_node_edge(node::COLOR_MATERIAL, base_render_graph::node::MAIN_PASS) .unwrap(); - self.add_system_node(node::QUAD, UniformNode::::new(false)); + self.add_system_node(node::QUAD, RenderResourcesNode::::new(false)); self.add_node_edge(node::QUAD, base_render_graph::node::MAIN_PASS) .unwrap(); self.add_system_node( node::SPRITE_SHEET, - AssetUniformNode::::new(false), + AssetRenderResourcesNode::::new(false), ); self.add_system_node( node::SPRITE_SHEET_SPRITE, - UniformNode::::new(true), + RenderResourcesNode::::new(true), ); let mut pipelines = resources.get_mut::>().unwrap(); diff --git a/examples/shader/shader_custom_material.rs b/examples/shader/shader_custom_material.rs index 1c387f6b6f..9594597520 100644 --- a/examples/shader/shader_custom_material.rs +++ b/examples/shader/shader_custom_material.rs @@ -53,7 +53,7 @@ fn setup( fragment: Some(shaders.add(Shader::from_glsl(ShaderStage::Fragment, FRAGMENT_SHADER))), })); - render_graph.add_system_node("my_material", AssetUniformNode::::new(true)); + render_graph.add_system_node("my_material", AssetRenderResourcesNode::::new(true)); pipeline_handle }; diff --git a/examples/shader/shader_defs.rs b/examples/shader/shader_defs.rs index 3630ace2f3..e7fff7b67c 100644 --- a/examples/shader/shader_defs.rs +++ b/examples/shader/shader_defs.rs @@ -63,7 +63,7 @@ fn setup( vertex: shaders.add(Shader::from_glsl(ShaderStage::Vertex, VERTEX_SHADER)), fragment: Some(shaders.add(Shader::from_glsl(ShaderStage::Fragment, FRAGMENT_SHADER))), })); - render_graph.add_system_node("my_material", AssetUniformNode::::new(true)); + render_graph.add_system_node("my_material", AssetRenderResourcesNode::::new(true)); pipeline_handle }; diff --git a/src/prelude.rs b/src/prelude.rs index 5f4d0f963c..fec98d5de8 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -19,7 +19,7 @@ pub use crate::{ pipeline::PipelineDescriptor, render_graph::{ nodes::{ - AssetUniformNode, CameraNode, MainPassNode, UniformNode, WindowSwapChainNode, + AssetRenderResourcesNode, CameraNode, MainPassNode, RenderResourcesNode, WindowSwapChainNode, WindowTextureNode, }, RenderGraph,