diff --git a/crates/bevy_pbr/src/forward_pbr_render_graph.rs b/crates/bevy_pbr/src/forward_pbr_render_graph.rs index 7ef2b51568..a25dbf44cf 100644 --- a/crates/bevy_pbr/src/forward_pbr_render_graph.rs +++ b/crates/bevy_pbr/src/forward_pbr_render_graph.rs @@ -2,7 +2,6 @@ use crate::{material::StandardMaterial, nodes::LightsNode, pipelines::build_forw use bevy_asset::Assets; use bevy_render::{ base_render_graph, - draw_target::AssignedMeshesDrawTarget, pipeline::PipelineDescriptor, render_graph::{ nodes::{AssetUniformNode, PassNode, UniformNode}, @@ -41,10 +40,7 @@ impl ForwardPbrRenderGraphBuilder for RenderGraph { let main_pass: &mut PassNode = self .get_node_mut(base_render_graph::node::MAIN_PASS) .unwrap(); - main_pass.add_pipeline( - pipelines.add_default(build_forward_pipeline(&mut shaders)), - vec![Box::new(AssignedMeshesDrawTarget)], - ); + main_pass.add_pipeline(pipelines.add_default(build_forward_pipeline(&mut shaders))); } // TODO: replace these with "autowire" groups diff --git a/crates/bevy_render/src/draw.rs b/crates/bevy_render/src/draw.rs new file mode 100644 index 0000000000..0aaa64cda7 --- /dev/null +++ b/crates/bevy_render/src/draw.rs @@ -0,0 +1,41 @@ +use crate::{render_resource::RenderResourceId, pipeline::PipelineDescriptor}; +use bevy_asset::Handle; +use std::ops::Range; + +#[derive(Debug, Clone, Eq, PartialEq)] +pub enum DrawType { + Instanced { + indices: Range, + base_vertex: i32, + instances: Range, + } +} + +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct VertexBufferBinding { + pub slot: u32, + pub vertex_buffer: RenderResourceId, + pub offset: u64, +} + +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct IndexBufferBinding { + pub vertex_buffer: RenderResourceId, + pub offset: u64, +} + +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct BindGroupBinding { + pub vertex_buffer: RenderResourceId, + pub offset: u64, +} + +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct DrawCall { + pub pipeline: Handle, + pub draw_type: DrawType, + pub vertex_buffers: Vec, + pub index_buffer: Option, +} + +pub struct Draw {} diff --git a/crates/bevy_render/src/draw_target/draw_target.rs b/crates/bevy_render/src/draw_target/draw_target.rs deleted file mode 100644 index 46aa6ca681..0000000000 --- a/crates/bevy_render/src/draw_target/draw_target.rs +++ /dev/null @@ -1,25 +0,0 @@ -use crate::{pass::RenderPass, pipeline::PipelineDescriptor, renderer::RenderContext}; -use bevy_asset::Handle; -use legion::prelude::{Resources, World}; - -// A set of draw calls. ex: get + draw meshes, get + draw instanced meshes, draw ui meshes, etc -pub trait DrawTarget: Send + Sync + 'static { - fn draw( - &self, - world: &World, - resources: &Resources, - render_pass: &mut dyn RenderPass, - pipeline_handle: Handle, - pipeline_descriptor: &PipelineDescriptor, - ); - fn setup( - &mut self, - _world: &World, - _resources: &Resources, - _render_context: &mut dyn RenderContext, - _pipeline_handle: Handle, - _pipeline_descriptor: &PipelineDescriptor, - ) { - } - fn get_name(&self) -> String; -} diff --git a/crates/bevy_render/src/draw_target/draw_targets/assigned_meshes_draw_target.rs b/crates/bevy_render/src/draw_target/draw_targets/assigned_meshes_draw_target.rs deleted file mode 100644 index a4df385c5e..0000000000 --- a/crates/bevy_render/src/draw_target/draw_targets/assigned_meshes_draw_target.rs +++ /dev/null @@ -1,106 +0,0 @@ -use bevy_asset::Handle; -use legion::prelude::*; - -use crate::{ - draw_target::DrawTarget, - pass::RenderPass, - pipeline::{PipelineAssignments, PipelineDescriptor}, - render_resource::{ - EntitiesWaitingForAssets, EntityRenderResourceAssignments, RenderResourceAssignments, - }, - renderer::RenderContext, - Renderable, -}; - -#[derive(Default)] -pub struct AssignedMeshesDrawTarget; - -impl AssignedMeshesDrawTarget { - pub const NAME: &'static str = "AssignedMeshes"; -} - -impl DrawTarget for AssignedMeshesDrawTarget { - fn draw( - &self, - world: &World, - resources: &Resources, - render_pass: &mut dyn RenderPass, - pipeline_handle: Handle, - pipeline_descriptor: &PipelineDescriptor, - ) { - let shader_pipeline_assignments = resources.get::().unwrap(); - let entity_render_resource_assignments = - resources.get::().unwrap(); - let entities_waiting_for_assets = resources.get::().unwrap(); - let global_render_resource_assignments = - resources.get::().unwrap(); - render_pass.set_render_resources(pipeline_descriptor, &global_render_resource_assignments); - - let assigned_render_resource_assignments = shader_pipeline_assignments - .assignments - .get(&pipeline_handle); - - if let Some(assigned_render_resource_assignments) = assigned_render_resource_assignments { - for assignment_id in assigned_render_resource_assignments.iter() { - // TODO: hopefully legion has better random access apis that are more like queries? - let entity = entity_render_resource_assignments - .get(*assignment_id) - .unwrap(); - let renderable = world.get_component::(*entity).unwrap(); - if !renderable.is_visible - || renderable.is_instanced - || entities_waiting_for_assets.contains(entity) - { - continue; - } - - if let Some(indices) = render_pass.set_render_resources( - pipeline_descriptor, - &renderable.render_resource_assignments, - ) { - render_pass.draw_indexed(indices, 0, 0..1); - } - } - } - } - - fn setup( - &mut self, - world: &World, - resources: &Resources, - render_context: &mut dyn RenderContext, - pipeline_handle: Handle, - pipeline_descriptor: &PipelineDescriptor, - ) { - let pipeline_assignments = resources.get::().unwrap(); - let entity_render_resource_assignments = - resources.get::().unwrap(); - let assigned_render_resource_assignments = - pipeline_assignments.assignments.get(&pipeline_handle); - let global_render_resource_assignments = - resources.get::().unwrap(); - render_context - .resources() - .setup_bind_groups(pipeline_descriptor, &global_render_resource_assignments); - if let Some(assigned_render_resource_assignments) = assigned_render_resource_assignments { - for assignment_id in assigned_render_resource_assignments.iter() { - let entity = entity_render_resource_assignments - .get(*assignment_id) - .unwrap(); - let renderable = world.get_component::(*entity).unwrap(); - if !renderable.is_visible || renderable.is_instanced { - continue; - } - - render_context.resources().setup_bind_groups( - pipeline_descriptor, - &renderable.render_resource_assignments, - ); - } - } - } - - fn get_name(&self) -> String { - AssignedMeshesDrawTarget::NAME.to_string() - } -} diff --git a/crates/bevy_render/src/draw_target/draw_targets/meshes_draw_target.rs b/crates/bevy_render/src/draw_target/draw_targets/meshes_draw_target.rs deleted file mode 100644 index f05f70d119..0000000000 --- a/crates/bevy_render/src/draw_target/draw_targets/meshes_draw_target.rs +++ /dev/null @@ -1,71 +0,0 @@ -use crate::{ - draw_target::DrawTarget, - mesh::{self, Mesh}, - pass::RenderPass, - pipeline::PipelineDescriptor, - render_resource::ResourceInfo, - Renderable, -}; -use bevy_asset::Handle; -use legion::prelude::*; - -#[derive(Default)] -pub struct MeshesDrawTarget; - -impl MeshesDrawTarget { - pub const NAME: &'static str = "Meshes"; -} - -impl DrawTarget for MeshesDrawTarget { - fn draw( - &self, - world: &World, - _resources: &Resources, - render_pass: &mut dyn RenderPass, - _pipeline_handle: Handle, - pipeline_descriptor: &PipelineDescriptor, - ) { - let mut current_mesh_handle = None; - let mut current_mesh_index_len = 0; - let mesh_query = <(Read>, Read)>::query(); - for (mesh_handle, renderable) in mesh_query.iter(world) { - if !renderable.is_visible || renderable.is_instanced { - continue; - } - - let render_context = render_pass.get_render_context(); - let render_resources = render_context.resources(); - if current_mesh_handle != Some(*mesh_handle) { - if let Some(vertex_buffer_resource) = render_resources - .get_asset_resource(*mesh_handle, mesh::VERTEX_BUFFER_ASSET_INDEX) - { - let index_buffer_resource = render_resources - .get_asset_resource(*mesh_handle, mesh::INDEX_BUFFER_ASSET_INDEX) - .unwrap(); - render_resources.get_resource_info( - index_buffer_resource, - &mut |resource_info| match resource_info { - Some(ResourceInfo::Buffer(Some(buffer_info))) => { - current_mesh_index_len = (buffer_info.size / 2) as u32 - } - _ => panic!("expected a buffer type"), - }, - ); - render_pass.set_index_buffer(index_buffer_resource, 0); - render_pass.set_vertex_buffer(0, vertex_buffer_resource, 0); - } - // TODO: Verify buffer format matches render pass - current_mesh_handle = Some(*mesh_handle); - } - - // TODO: validate bind group properties against shader uniform properties at least once - render_pass - .set_render_resources(pipeline_descriptor, &renderable.render_resource_assignments); - render_pass.draw_indexed(0..current_mesh_index_len, 0, 0..1); - } - } - - fn get_name(&self) -> String { - MeshesDrawTarget::NAME.to_string() - } -} diff --git a/crates/bevy_render/src/draw_target/draw_targets/mod.rs b/crates/bevy_render/src/draw_target/draw_targets/mod.rs deleted file mode 100644 index fd9e76a0ca..0000000000 --- a/crates/bevy_render/src/draw_target/draw_targets/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod assigned_meshes_draw_target; -mod meshes_draw_target; - -pub use assigned_meshes_draw_target::*; -pub use meshes_draw_target::*; diff --git a/crates/bevy_render/src/draw_target/mod.rs b/crates/bevy_render/src/draw_target/mod.rs deleted file mode 100644 index a9f5357463..0000000000 --- a/crates/bevy_render/src/draw_target/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod draw_target; -mod draw_targets; - -pub use draw_target::*; -pub use draw_targets::*; diff --git a/crates/bevy_render/src/lib.rs b/crates/bevy_render/src/lib.rs index 5c17b1333c..4f7264b3b3 100644 --- a/crates/bevy_render/src/lib.rs +++ b/crates/bevy_render/src/lib.rs @@ -1,5 +1,6 @@ pub mod batch; mod camera; +pub mod draw; pub mod entity; pub mod mesh; pub mod render_graph; @@ -16,7 +17,6 @@ pub use renderable::*; pub use vertex::Vertex; pub mod base_render_graph; -pub mod draw_target; pub mod pass; pub mod pipeline; pub mod render_resource; diff --git a/crates/bevy_render/src/pass/render_pass.rs b/crates/bevy_render/src/pass/render_pass.rs index a6062a8ef9..a53fd653d5 100644 --- a/crates/bevy_render/src/pass/render_pass.rs +++ b/crates/bevy_render/src/pass/render_pass.rs @@ -1,6 +1,6 @@ use crate::{ - pipeline::PipelineDescriptor, - render_resource::{RenderResourceId, RenderResourceAssignments}, + pipeline::{BindGroupDescriptor, PipelineDescriptor}, + render_resource::{RenderResourceId, RenderResourceSet}, renderer::RenderContext, }; use bevy_asset::Handle; @@ -15,10 +15,9 @@ pub trait RenderPass { fn set_stencil_reference(&mut self, reference: u32); fn draw(&mut self, vertices: Range, instances: Range); fn draw_indexed(&mut self, indices: Range, base_vertex: i32, instances: Range); - // TODO: try to somehow take into account the "set" pipeline instead of passing it in here - fn set_render_resources( + fn set_bind_group( &mut self, - pipeline_descriptor: &PipelineDescriptor, - render_resource_assignments: &RenderResourceAssignments, - ) -> Option>; + bind_group_descriptor: &BindGroupDescriptor, + render_resource_set: &RenderResourceSet, + ); } 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 b5e808c69c..a78b0c56de 100644 --- a/crates/bevy_render/src/render_graph/nodes/pass_node.rs +++ b/crates/bevy_render/src/render_graph/nodes/pass_node.rs @@ -1,18 +1,22 @@ use crate::{ - draw_target::DrawTarget, - pass::{PassDescriptor, TextureAttachment}, - pipeline::{PipelineCompiler, PipelineDescriptor}, + pass::{PassDescriptor, RenderPass, TextureAttachment}, + pipeline::{PipelineAssignments, PipelineCompiler, PipelineDescriptor}, render_graph::{Node, ResourceSlotInfo, ResourceSlots}, - render_resource::{ResourceInfo, RenderResourceAssignments}, + render_resource::{ + EntitiesWaitingForAssets, EntityRenderResourceAssignments, RenderResourceAssignments, + ResourceInfo, + }, renderer::RenderContext, shader::Shader, + Renderable, }; use bevy_asset::{Assets, Handle}; use legion::prelude::*; +use std::ops::Range; pub struct PassNode { descriptor: PassDescriptor, - pipelines: Vec<(Handle, Vec>)>, + pipelines: Vec>, inputs: Vec, color_attachment_input_indices: Vec>, depth_stencil_attachment_input_index: Option, @@ -54,12 +58,64 @@ impl PassNode { } } - pub fn add_pipeline( - &mut self, - pipeline_handle: Handle, - draw_targets: Vec>, - ) { - self.pipelines.push((pipeline_handle, draw_targets)); + pub fn add_pipeline(&mut self, pipeline_handle: Handle) { + self.pipelines.push(pipeline_handle); + } + + fn set_render_resources( + render_pass: &mut dyn RenderPass, + pipeline_descriptor: &PipelineDescriptor, + render_resource_assignments: &RenderResourceAssignments, + ) -> Option> { + let pipeline_layout = pipeline_descriptor.get_layout().unwrap(); + // PERF: vertex buffer lookup comes at a cost when vertex buffers aren't in render_resource_assignments. iterating over render_resource_assignment vertex buffers + // would likely be faster + let mut indices = None; + for (i, vertex_buffer_descriptor) in + pipeline_layout.vertex_buffer_descriptors.iter().enumerate() + { + if let Some((vertex_buffer, index_buffer)) = + render_resource_assignments.get_vertex_buffer(&vertex_buffer_descriptor.name) + { + log::trace!( + "set vertex buffer {}: {} ({:?})", + i, + vertex_buffer_descriptor.name, + vertex_buffer + ); + render_pass.set_vertex_buffer(i as u32, vertex_buffer, 0); + if let Some(index_buffer) = index_buffer { + log::trace!( + "set index buffer: {} ({:?})", + vertex_buffer_descriptor.name, + index_buffer + ); + render_pass.set_index_buffer(index_buffer, 0); + render_pass + .get_render_context() + .resources() + .get_resource_info( + index_buffer, + &mut |resource_info| match resource_info { + Some(ResourceInfo::Buffer(Some(buffer_info))) => { + indices = Some(0..(buffer_info.size / 2) as u32) + } + _ => panic!("expected a buffer type"), + }, + ); + } + } + } + + for bind_group in pipeline_layout.bind_groups.iter() { + if let Some(render_resource_set) = + render_resource_assignments.get_render_resource_set(bind_group.id) + { + render_pass.set_bind_group(bind_group, &render_resource_set); + } + } + + indices } } @@ -78,6 +134,12 @@ impl Node for PassNode { ) { let pipeline_compiler = resources.get::().unwrap(); let pipelines = resources.get::>().unwrap(); + let shader_pipeline_assignments = resources.get::().unwrap(); + let entity_render_resource_assignments = + resources.get::().unwrap(); + let entities_waiting_for_assets = resources.get::().unwrap(); + let mut render_resource_assignments = + resources.get_mut::().unwrap(); for (i, color_attachment) in self.descriptor.color_attachments.iter_mut().enumerate() { if let Some(input_index) = self.color_attachment_input_indices[i] { @@ -94,50 +156,71 @@ impl Node for PassNode { .attachment = TextureAttachment::RenderResource(input.get(input_index).unwrap()); } - let shaders = resources.get::>().unwrap(); - for (pipeline_handle, draw_targets) in self.pipelines.iter_mut() { - if let Some(compiled_pipelines_iter) = - pipeline_compiler.iter_compiled_pipelines(*pipeline_handle) - { - for compiled_pipeline_handle in compiled_pipelines_iter { - let compiled_pipeline_descriptor = - pipelines.get(compiled_pipeline_handle).unwrap(); + { + let render_resource_context = render_context.resources(); - let pipeline_layout = compiled_pipeline_descriptor.get_layout().unwrap(); - { - // TODO: this breaks down in a parallel setting. it needs to change. ideally in a way that - // doesn't require modifying RenderResourceAssignments - let mut render_resource_assignments = - resources.get_mut::().unwrap(); - for bind_group in pipeline_layout.bind_groups.iter() { - render_resource_assignments.update_render_resource_set_id(bind_group); + // TODO: try merging the two pipeline loops below + let shaders = resources.get::>().unwrap(); + for pipeline_handle in self.pipelines.iter() { + if let Some(compiled_pipelines_iter) = + pipeline_compiler.iter_compiled_pipelines(*pipeline_handle) + { + for compiled_pipeline_handle in compiled_pipelines_iter { + let compiled_pipeline_descriptor = + pipelines.get(compiled_pipeline_handle).unwrap(); + + let pipeline_layout = compiled_pipeline_descriptor.get_layout().unwrap(); + { + // TODO: this breaks down in a parallel setting. it needs to change. ideally in a way that + // doesn't require modifying RenderResourceAssignments + for bind_group in pipeline_layout.bind_groups.iter() { + render_resource_assignments + .update_render_resource_set_id(bind_group); + } } - } - render_context.resources().create_render_pipeline( - *compiled_pipeline_handle, - &compiled_pipeline_descriptor, - &shaders, - ); - for draw_target in draw_targets.iter_mut() { - draw_target.setup( - world, - resources, - render_context, + render_resource_context.create_render_pipeline( *compiled_pipeline_handle, - compiled_pipeline_descriptor, + &compiled_pipeline_descriptor, + &shaders, ); + + render_resource_context.setup_bind_groups( + compiled_pipeline_descriptor, + &render_resource_assignments, + ); + let assigned_render_resource_assignments = shader_pipeline_assignments + .assignments + .get(&compiled_pipeline_handle); + if let Some(assigned_render_resource_assignments) = + assigned_render_resource_assignments + { + for assignment_id in assigned_render_resource_assignments.iter() { + let entity = entity_render_resource_assignments + .get(*assignment_id) + .unwrap(); + let renderable = + world.get_component::(*entity).unwrap(); + if !renderable.is_visible || renderable.is_instanced { + continue; + } + + render_resource_context.setup_bind_groups( + compiled_pipeline_descriptor, + &renderable.render_resource_assignments, + ); + } + } } } } } - let render_resource_assignments = resources.get::().unwrap(); render_context.begin_pass( &self.descriptor, &render_resource_assignments, &mut |render_pass| { - for (pipeline_handle, draw_targets) in self.pipelines.iter() { + for pipeline_handle in self.pipelines.iter() { if let Some(compiled_pipelines_iter) = pipeline_compiler.iter_compiled_pipelines(*pipeline_handle) { @@ -145,14 +228,45 @@ impl Node for PassNode { let compiled_pipeline_descriptor = pipelines.get(compiled_pipeline_handle).unwrap(); render_pass.set_pipeline(*compiled_pipeline_handle); - for draw_target in draw_targets.iter() { - draw_target.draw( - world, - resources, - render_pass, - *compiled_pipeline_handle, - compiled_pipeline_descriptor, - ); + + // set global render resources + Self::set_render_resources( + render_pass, + compiled_pipeline_descriptor, + &render_resource_assignments, + ); + + // draw entities assigned to this pipeline + let assigned_render_resource_assignments = shader_pipeline_assignments + .assignments + .get(&compiled_pipeline_handle); + + if let Some(assigned_render_resource_assignments) = + assigned_render_resource_assignments + { + for assignment_id in assigned_render_resource_assignments.iter() { + // TODO: hopefully legion has better random access apis that are more like queries? + let entity = entity_render_resource_assignments + .get(*assignment_id) + .unwrap(); + let renderable = + world.get_component::(*entity).unwrap(); + if !renderable.is_visible + || renderable.is_instanced + || entities_waiting_for_assets.contains(entity) + { + continue; + } + + // set local render resources + if let Some(indices) = Self::set_render_resources( + render_pass, + compiled_pipeline_descriptor, + &renderable.render_resource_assignments, + ) { + render_pass.draw_indexed(indices, 0, 0..1); + } + } } } } diff --git a/crates/bevy_sprite/src/render/mod.rs b/crates/bevy_sprite/src/render/mod.rs index 7465786a1b..910ea4354c 100644 --- a/crates/bevy_sprite/src/render/mod.rs +++ b/crates/bevy_sprite/src/render/mod.rs @@ -2,7 +2,6 @@ use crate::{ColorMaterial, Quad, TextureAtlas, TextureAtlasSprite}; use bevy_asset::{Assets, Handle}; use bevy_render::{ base_render_graph, - draw_target::AssignedMeshesDrawTarget, pipeline::{state_descriptors::*, PipelineDescriptor}, render_graph::{ nodes::{AssetUniformNode, PassNode, UniformNode}, @@ -153,14 +152,8 @@ impl SpriteRenderGraphBuilder for RenderGraph { let main_pass: &mut PassNode = self .get_node_mut(base_render_graph::node::MAIN_PASS) .unwrap(); - main_pass.add_pipeline( - SPRITE_PIPELINE_HANDLE, - vec![Box::new(AssignedMeshesDrawTarget)], - ); - main_pass.add_pipeline( - SPRITE_SHEET_PIPELINE_HANDLE, - vec![Box::new(AssignedMeshesDrawTarget)], - ); + main_pass.add_pipeline(SPRITE_PIPELINE_HANDLE); + main_pass.add_pipeline(SPRITE_SHEET_PIPELINE_HANDLE); self } } diff --git a/crates/bevy_ui/src/render/mod.rs b/crates/bevy_ui/src/render/mod.rs index fe4bff7a61..244853b9f6 100644 --- a/crates/bevy_ui/src/render/mod.rs +++ b/crates/bevy_ui/src/render/mod.rs @@ -1,7 +1,6 @@ use bevy_asset::{Assets, Handle}; use bevy_render::{ base_render_graph, - draw_target::AssignedMeshesDrawTarget, pipeline::{state_descriptors::*, PipelineDescriptor}, render_graph::{ nodes::{CameraNode, PassNode}, @@ -83,7 +82,7 @@ impl UiRenderGraphBuilder for RenderGraph { let main_pass: &mut PassNode = self .get_node_mut(base_render_graph::node::MAIN_PASS) .unwrap(); - main_pass.add_pipeline(UI_PIPELINE_HANDLE, vec![Box::new(AssignedMeshesDrawTarget)]); + main_pass.add_pipeline(UI_PIPELINE_HANDLE); self } } diff --git a/crates/bevy_wgpu/src/renderer/wgpu_render_context.rs b/crates/bevy_wgpu/src/renderer/wgpu_render_context.rs index bbb2286e20..b63a6dae2c 100644 --- a/crates/bevy_wgpu/src/renderer/wgpu_render_context.rs +++ b/crates/bevy_wgpu/src/renderer/wgpu_render_context.rs @@ -6,12 +6,12 @@ use bevy_render::{ PassDescriptor, RenderPass, RenderPassColorAttachmentDescriptor, RenderPassDepthStencilAttachmentDescriptor, TextureAttachment, }, - render_resource::{RenderResourceId, RenderResourceAssignment, RenderResourceAssignments}, + render_resource::{RenderResourceAssignment, RenderResourceAssignments, RenderResourceId}, renderer::{RenderContext, RenderResourceContext}, texture::Extent3d, }; -use std::{collections::HashMap, sync::Arc}; +use std::sync::Arc; #[derive(Default)] pub struct LazyCommandEncoder { @@ -138,10 +138,10 @@ impl RenderContext for WgpuRenderContext { &mut encoder, ); let mut wgpu_render_pass = WgpuRenderPass { - render_context: self, render_pass, + render_context: self, render_resources: refs, - bound_bind_groups: HashMap::default(), + pipeline_descriptor: None, }; run_pass(&mut wgpu_render_pass); diff --git a/crates/bevy_wgpu/src/wgpu_render_pass.rs b/crates/bevy_wgpu/src/wgpu_render_pass.rs index 6a005fd07c..0a5387c326 100644 --- a/crates/bevy_wgpu/src/wgpu_render_pass.rs +++ b/crates/bevy_wgpu/src/wgpu_render_pass.rs @@ -2,19 +2,17 @@ use crate::{renderer::WgpuRenderContext, WgpuResourceRefs}; use bevy_asset::Handle; use bevy_render::{ pass::RenderPass, - pipeline::PipelineDescriptor, - render_resource::{ - RenderResourceId, RenderResourceAssignments, RenderResourceSetId, ResourceInfo, - }, + pipeline::{BindGroupDescriptor, PipelineDescriptor}, + render_resource::{RenderResourceId, RenderResourceSet}, renderer::RenderContext, }; -use std::{collections::HashMap, ops::Range}; +use std::ops::Range; pub struct WgpuRenderPass<'a> { pub render_pass: wgpu::RenderPass<'a>, pub render_context: &'a WgpuRenderContext, pub render_resources: WgpuResourceRefs<'a>, - pub bound_bind_groups: HashMap, + pub pipeline_descriptor: Option<&'a PipelineDescriptor>, } impl<'a> RenderPass for WgpuRenderPass<'a> { @@ -51,102 +49,42 @@ impl<'a> RenderPass for WgpuRenderPass<'a> { self.render_pass.draw(vertices, instances); } - fn set_render_resources( + fn set_bind_group( &mut self, - pipeline_descriptor: &PipelineDescriptor, - render_resource_assignments: &RenderResourceAssignments, - ) -> Option> { - let pipeline_layout = pipeline_descriptor.get_layout().unwrap(); - // PERF: vertex buffer lookup comes at a cost when vertex buffers aren't in render_resource_assignments. iterating over render_resource_assignment vertex buffers - // would likely be faster - let mut indices = None; - for (i, vertex_buffer_descriptor) in - pipeline_layout.vertex_buffer_descriptors.iter().enumerate() + bind_group_descriptor: &BindGroupDescriptor, + render_resource_set: &RenderResourceSet, + ) { + if let Some(bind_group_info) = self + .render_resources + .bind_groups + .get(&bind_group_descriptor.id) { - if let Some((vertex_buffer, index_buffer)) = - render_resource_assignments.get_vertex_buffer(&vertex_buffer_descriptor.name) + if let Some(wgpu_bind_group) = bind_group_info.bind_groups.get(&render_resource_set.id) { - log::trace!( - "set vertex buffer {}: {} ({:?})", - i, - vertex_buffer_descriptor.name, - vertex_buffer - ); - self.set_vertex_buffer(i as u32, vertex_buffer, 0); - if let Some(index_buffer) = index_buffer { - log::trace!( - "set index buffer: {} ({:?})", - vertex_buffer_descriptor.name, - index_buffer - ); - self.set_index_buffer(index_buffer, 0); - self.render_context.resources().get_resource_info( - index_buffer, - &mut |resource_info| match resource_info { - Some(ResourceInfo::Buffer(Some(buffer_info))) => { - indices = Some(0..(buffer_info.size / 2) as u32) - } - _ => panic!("expected a buffer type"), - }, - ); - } - } - } - - for bind_group in pipeline_layout.bind_groups.iter() { - if let Some(resource_set) = - render_resource_assignments.get_render_resource_set(bind_group.id) - { - if let Some(bind_group_info) = self.render_resources.bind_groups.get(&bind_group.id) + const EMPTY: &'static [u32] = &[]; + let dynamic_uniform_indices = if let Some(ref dynamic_uniform_indices) = + render_resource_set.dynamic_uniform_indices { - if let Some(wgpu_bind_group) = bind_group_info.bind_groups.get(&resource_set.id) - { - const EMPTY: &'static [u32] = &[]; - let dynamic_uniform_indices = if let Some(ref dynamic_uniform_indices) = - resource_set.dynamic_uniform_indices - { - dynamic_uniform_indices.as_slice() - } else { - EMPTY - }; - - // don't bind bind groups if they are already set - // TODO: these checks come at a performance cost. make sure it's worth it! - if let Some(bound_render_resource_set) = - self.bound_bind_groups.get(&bind_group.index) - { - if *bound_render_resource_set == resource_set.id - && dynamic_uniform_indices.len() == 0 - { - continue; - } - } - - if dynamic_uniform_indices.len() == 0 { - self.bound_bind_groups - .insert(bind_group.index, resource_set.id); - } else { - self.bound_bind_groups.remove(&bind_group.index); - } - - log::trace!( - "set bind group {} {:?}: {:?}", - bind_group.index, - dynamic_uniform_indices, - resource_set.id - ); - self.render_pass.set_bind_group( - bind_group.index, - wgpu_bind_group, - dynamic_uniform_indices, - ); - } + dynamic_uniform_indices.as_slice() + } else { + EMPTY }; + + log::trace!( + "set bind group {:?} {:?}: {:?}", + bind_group_descriptor.id, + dynamic_uniform_indices, + render_resource_set.id + ); + self.render_pass.set_bind_group( + bind_group_descriptor.index, + wgpu_bind_group, + dynamic_uniform_indices, + ); } } - - indices } + fn set_pipeline(&mut self, pipeline_handle: Handle) { let pipeline = self.render_resources.render_pipelines.get(&pipeline_handle).expect( "Attempted to use a pipeline that does not exist in this RenderPass's RenderContext", diff --git a/examples/shader/shader_custom_material.rs b/examples/shader/shader_custom_material.rs index e24512398c..f0a36e1b11 100644 --- a/examples/shader/shader_custom_material.rs +++ b/examples/shader/shader_custom_material.rs @@ -55,10 +55,7 @@ fn setup( render_graph.add_system_node("my_material", AssetUniformNode::::new(true)); let main_pass: &mut PassNode = render_graph.get_node_mut("main_pass").unwrap(); - main_pass.add_pipeline( - pipeline_handle, - vec![Box::new(draw_target::AssignedMeshesDrawTarget)], - ); + main_pass.add_pipeline(pipeline_handle); pipeline_handle }; diff --git a/examples/shader/shader_defs.rs b/examples/shader/shader_defs.rs index e25454c888..d099879e20 100644 --- a/examples/shader/shader_defs.rs +++ b/examples/shader/shader_defs.rs @@ -65,10 +65,7 @@ fn setup( })); render_graph.add_system_node("my_material", AssetUniformNode::::new(true)); let main_pass: &mut PassNode = render_graph.get_node_mut("main_pass").unwrap(); - main_pass.add_pipeline( - pipeline_handle, - vec![Box::new(draw_target::AssignedMeshesDrawTarget)], - ); + main_pass.add_pipeline(pipeline_handle); pipeline_handle }; diff --git a/src/prelude.rs b/src/prelude.rs index 72fc269605..d6830a2335 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -14,7 +14,6 @@ pub use crate::{ pbr::{entity::*, light::Light, material::StandardMaterial}, property::{DynamicProperties, Properties, PropertiesVal, Property, PropertyVal}, render::{ - draw_target, entity::*, mesh::{shape, Mesh}, pipeline::PipelineDescriptor,