diff --git a/crates/bevy_legion/legion_systems/src/system_fn_types.rs b/crates/bevy_legion/legion_systems/src/system_fn_types.rs index c2576aca1a..b2f77c9f60 100644 --- a/crates/bevy_legion/legion_systems/src/system_fn_types.rs +++ b/crates/bevy_legion/legion_systems/src/system_fn_types.rs @@ -33,7 +33,7 @@ impl<'a, T: 'a> Clone for Res<'a, T> { impl<'a, T: 'a> Res<'a, T> { #[inline(always)] - fn new(resource: *const T) -> Self { + pub fn new(resource: *const T) -> Self { Self { value: resource, _marker: PhantomData::default(), @@ -120,7 +120,7 @@ impl<'a, T: 'a> Clone for ResMut<'a, T> { impl<'a, T: 'a> ResMut<'a, T> { #[inline(always)] - fn new(resource: *mut T) -> Self { + pub fn new(resource: *mut T) -> Self { Self { value: resource, _marker: PhantomData::default(), diff --git a/crates/bevy_render/src/draw.rs b/crates/bevy_render/src/draw.rs index 214f7eec27..e8a7fb9e2e 100644 --- a/crates/bevy_render/src/draw.rs +++ b/crates/bevy_render/src/draw.rs @@ -1,18 +1,25 @@ use crate::{ - pipeline::{PipelineDescriptor, PipelineLayout}, + pipeline::{ + PipelineCompiler, PipelineDescriptor, PipelineLayout, PipelineSpecialization, + VertexBufferDescriptors, + }, render_resource::{ AssetRenderResourceBindings, BindGroup, BindGroupId, BufferId, BufferUsage, RenderResource, RenderResourceBinding, RenderResourceBindings, SharedBuffers, }, renderer::RenderResourceContext, + shader::Shader, }; use bevy_asset::{Assets, Handle}; use bevy_property::Properties; use legion::{ - prelude::{ComMut, Res}, - storage::Component, + prelude::{ComMut, Res, ResourceSet}, + systems::{resource::ResourceTypeId, ResMut}, +}; +use std::{ + ops::{Deref, DerefMut, Range}, + sync::Arc, }; -use std::{ops::Range, sync::Arc}; use thiserror::Error; #[derive(Debug, Clone, Eq, PartialEq)] @@ -58,84 +65,12 @@ impl Default for Draw { } impl Draw { - pub fn get_context<'a>( - &'a mut self, - pipelines: &'a Assets, - render_resource_context: &'a dyn RenderResourceContext, - render_resource_bindings: &'a RenderResourceBindings, - asset_render_resource_bindings: &'a AssetRenderResourceBindings, - shared_buffers: &'a SharedBuffers, - ) -> DrawContext { - DrawContext { - draw: self, - pipelines, - render_resource_context, - render_resource_bindings, - asset_render_resource_bindings, - shared_buffers, - current_pipeline: None, - } - } - pub fn clear_render_commands(&mut self) { self.render_commands.clear(); } -} -#[derive(Debug, Error)] -pub enum DrawError { - #[error("Pipeline does not exist.")] - NonExistentPipeline, - #[error("No pipeline set")] - NoPipelineSet, - #[error("Pipeline has no layout")] - PipelineHasNoLayout, - #[error("A BindGroup with the given index does not exist")] - BindGroupDescriptorDoesNotExist { index: u32 }, - #[error("Failed to get a buffer for the given RenderResource.")] - BufferAllocationFailure, -} - -pub struct DrawContext<'a> { - pub draw: &'a mut Draw, - pub pipelines: &'a Assets, - pub render_resource_context: &'a dyn RenderResourceContext, - pub render_resource_bindings: &'a RenderResourceBindings, - pub asset_render_resource_bindings: &'a AssetRenderResourceBindings, - pub shared_buffers: &'a SharedBuffers, - pub current_pipeline: Option<&'a PipelineDescriptor>, -} - -impl<'a> DrawContext<'a> { - pub fn get_uniform_buffer( - &self, - render_resource: &T, - ) -> Result { - self.get_buffer(render_resource, BufferUsage::UNIFORM) - } - pub fn get_buffer( - &self, - render_resource: &T, - buffer_usage: BufferUsage, - ) -> Result { - self.shared_buffers - .get_buffer(render_resource, buffer_usage) - .ok_or_else(|| DrawError::BufferAllocationFailure) - } - - pub fn set_pipeline( - &mut self, - pipeline_handle: Handle, - ) -> Result<(), DrawError> { - let pipeline = self - .pipelines - .get(&pipeline_handle) - .ok_or_else(|| DrawError::NonExistentPipeline)?; - self.current_pipeline = Some(pipeline); - self.render_command(RenderCommand::SetPipeline { - pipeline: pipeline_handle, - }); - Ok(()) + pub fn set_pipeline(&mut self, pipeline: Handle) { + self.render_command(RenderCommand::SetPipeline { pipeline }); } pub fn set_vertex_buffer(&mut self, slot: u32, buffer: BufferId, offset: u64) { @@ -166,8 +101,139 @@ impl<'a> DrawContext<'a> { }); } + #[inline] + pub fn render_command(&mut self, render_command: RenderCommand) { + self.render_commands.push(render_command); + } +} + +#[derive(Debug, Error)] +pub enum DrawError { + #[error("Pipeline does not exist.")] + NonExistentPipeline, + #[error("No pipeline set")] + NoPipelineSet, + #[error("Pipeline has no layout")] + PipelineHasNoLayout, + #[error("Failed to get a buffer for the given RenderResource.")] + BufferAllocationFailure, +} + +#[derive(Clone)] +pub struct DrawContext<'a> { + pub pipelines: ResMut<'a, Assets>, + pub shaders: ResMut<'a, Assets>, + pub pipeline_compiler: ResMut<'a, PipelineCompiler>, + pub render_resource_context: Res<'a, Box>, + pub vertex_buffer_descriptors: Res<'a, VertexBufferDescriptors>, + pub asset_render_resource_bindings: Res<'a, AssetRenderResourceBindings>, + pub shared_buffers: Res<'a, SharedBuffers>, + pub current_pipeline: Option>, +} + +impl<'a> ResourceSet for DrawContext<'a> { + type PreparedResources = DrawContext<'a>; + unsafe fn fetch_unchecked(resources: &legion::prelude::Resources) -> Self::PreparedResources { + DrawContext { + render_resource_context: Res::new( + resources + .get::>() + .unwrap() + .deref() as *const Box, + ), + vertex_buffer_descriptors: Res::new( + resources.get::().unwrap().deref() + as *const VertexBufferDescriptors, + ), + asset_render_resource_bindings: Res::new( + resources + .get::() + .unwrap() + .deref() as *const AssetRenderResourceBindings, + ), + shared_buffers: Res::new( + resources.get::().unwrap().deref() as *const SharedBuffers + ), + pipelines: ResMut::new( + resources + .get_mut::>() + .unwrap() + .deref_mut() as *mut Assets, + ), + shaders: ResMut::new( + resources.get_mut::>().unwrap().deref_mut() as *mut Assets + ), + pipeline_compiler: ResMut::new( + resources.get_mut::().unwrap().deref_mut() + as *mut PipelineCompiler, + ), + current_pipeline: None, + } + } + fn read_types() -> Vec { + vec![ + ResourceTypeId::of::>(), + ResourceTypeId::of::(), + ResourceTypeId::of::(), + ResourceTypeId::of::(), + ] + } + fn write_types() -> Vec { + vec![ + ResourceTypeId::of::>(), + ResourceTypeId::of::>(), + ResourceTypeId::of::(), + ] + } +} + +impl<'a> DrawContext<'a> { + pub fn get_uniform_buffer( + &self, + render_resource: &T, + ) -> Result { + self.get_buffer(render_resource, BufferUsage::UNIFORM) + } + + pub fn get_buffer( + &self, + render_resource: &T, + buffer_usage: BufferUsage, + ) -> Result { + self.shared_buffers + .get_buffer(render_resource, buffer_usage) + .ok_or_else(|| DrawError::BufferAllocationFailure) + } + + pub fn set_pipeline( + &mut self, + draw: &mut Draw, + pipeline_handle: Handle, + specialization: &PipelineSpecialization, + ) -> Result<(), DrawError> { + let specialized_pipeline = if let Some(specialized_pipeline) = self + .pipeline_compiler + .get_specialized_pipeline(pipeline_handle, specialization) + { + specialized_pipeline + } else { + self.pipeline_compiler.compile_pipeline( + &**self.render_resource_context, + &mut self.pipelines, + &mut self.shaders, + pipeline_handle, + &self.vertex_buffer_descriptors, + specialization, + ) + }; + draw.set_pipeline(specialized_pipeline); + self.current_pipeline = Some(specialized_pipeline); + Ok(()) + } + pub fn get_pipeline_descriptor(&self) -> Result<&PipelineDescriptor, DrawError> { self.current_pipeline + .and_then(|handle| self.pipelines.get(&handle)) .ok_or_else(|| DrawError::NoPipelineSet) } @@ -180,57 +246,82 @@ impl<'a> DrawContext<'a> { } pub fn set_bind_groups_from_bindings( - &mut self, - render_resource_bindings: &RenderResourceBindings, + &self, + draw: &mut Draw, + render_resource_bindings: &mut [&mut RenderResourceBindings], ) -> Result<(), DrawError> { let pipeline = self .current_pipeline .ok_or_else(|| DrawError::NoPipelineSet)?; - let layout = pipeline + let pipeline_descriptor = self + .pipelines + .get(&pipeline) + .ok_or_else(|| DrawError::NonExistentPipeline)?; + let layout = pipeline_descriptor .get_layout() .ok_or_else(|| DrawError::PipelineHasNoLayout)?; + for bindings in render_resource_bindings.iter_mut() { + bindings.update_bind_groups(pipeline_descriptor, &**self.render_resource_context); + } for bind_group_descriptor in layout.bind_groups.iter() { - if let Some(local_bind_group) = - render_resource_bindings.get_descriptor_bind_group(bind_group_descriptor.id) - { - self.set_bind_group(bind_group_descriptor.index, local_bind_group); + for bindings in render_resource_bindings.iter_mut() { + if let Some(bind_group) = + bindings.get_descriptor_bind_group(bind_group_descriptor.id) + { + draw.set_bind_group(bind_group_descriptor.index, bind_group); + break; + } } } Ok(()) } - #[inline] - pub fn render_command(&mut self, render_command: RenderCommand) { - self.draw.render_commands.push(render_command); - } + pub fn set_vertex_buffers_from_bindings( + &self, + draw: &mut Draw, + render_resource_bindings: &[&RenderResourceBindings], + ) -> Result>, DrawError> { + let mut indices = None; + let pipeline = self + .current_pipeline + .ok_or_else(|| DrawError::NoPipelineSet)?; + let pipeline_descriptor = self + .pipelines + .get(&pipeline) + .ok_or_else(|| DrawError::NonExistentPipeline)?; + let layout = pipeline_descriptor + .get_layout() + .ok_or_else(|| DrawError::PipelineHasNoLayout)?; + for (slot, vertex_buffer_descriptor) in layout.vertex_buffer_descriptors.iter().enumerate() + { + for bindings in render_resource_bindings.iter() { + if let Some((vertex_buffer, index_buffer)) = + bindings.get_vertex_buffer(&vertex_buffer_descriptor.name) + { + draw.set_vertex_buffer(slot as u32, vertex_buffer, 0); + if let Some(index_buffer) = index_buffer { + if let Some(buffer_info) = + self.render_resource_context.get_buffer_info(index_buffer) + { + indices = Some(0..(buffer_info.size / 2) as u32); + } else { + panic!("expected buffer type"); + } + draw.set_index_buffer(index_buffer, 0); + } - pub fn draw(&mut self, drawable: &mut T) -> Result<(), DrawError> { - drawable.draw(self) + break; + } + } + } + + Ok(indices) } } pub trait Drawable { - fn draw(&mut self, draw: &mut DrawContext) -> Result<(), DrawError>; -} - -pub fn draw_system( - pipelines: Res>, - render_resource_bindings: Res, - render_resource_context: Res>, - asset_render_resource_bindings: Res, - shared_buffers: Res, - mut draw: ComMut, - mut drawable: ComMut, -) { - let mut draw_context = draw.get_context( - &pipelines, - &**render_resource_context, - &render_resource_bindings, - &asset_render_resource_bindings, - &shared_buffers, - ); - draw_context.draw(drawable.as_mut()).unwrap(); + fn draw(&mut self, draw: &mut Draw, context: &mut DrawContext) -> Result<(), DrawError>; } pub fn clear_draw_system(mut draw: ComMut) { diff --git a/crates/bevy_render/src/lib.rs b/crates/bevy_render/src/lib.rs index 3a4fe6b8b2..1a35646bba 100644 --- a/crates/bevy_render/src/lib.rs +++ b/crates/bevy_render/src/lib.rs @@ -35,12 +35,12 @@ use base_render_graph::{BaseRenderGraphBuilder, BaseRenderGraphConfig}; use bevy_app::{AppBuilder, AppPlugin}; use bevy_asset::AddAsset; use bevy_type_registry::RegisterType; -use draw::{clear_draw_system, draw_system, Draw}; +use draw::{clear_draw_system, Draw}; use legion::prelude::IntoSystem; use mesh::mesh_resource_provider_system; -use pipeline::{compile_pipelines_system, RenderPipelines}; +use pipeline::{draw_render_pipelines_system, RenderPipelines}; use render_graph::{system::render_graph_schedule_executor_system, RenderGraph}; -use render_resource::{bind_groups_system, AssetRenderResourceBindings}; +use render_resource::AssetRenderResourceBindings; use std::ops::Range; use texture::{PngTextureLoader, TextureResourceSystemState}; @@ -112,12 +112,7 @@ impl AppPlugin for RenderPlugin { stage::RENDER_GRAPH_SYSTEMS, render_graph_schedule_executor_system, ) - .add_system_to_stage( - stage::RENDER_GRAPH_SYSTEMS, - compile_pipelines_system.system(), - ) - .add_system_to_stage(stage::RENDER_GRAPH_SYSTEMS, bind_groups_system.system()) - .add_system_to_stage(stage::DRAW, draw_system::.system()); + .add_system_to_stage(stage::DRAW, draw_render_pipelines_system.system()); if let Some(ref config) = self.base_render_graph_config { let resources = app.resources(); diff --git a/crates/bevy_render/src/pipeline/pipeline_compiler.rs b/crates/bevy_render/src/pipeline/pipeline_compiler.rs index 94eb38ce60..0513255b6d 100644 --- a/crates/bevy_render/src/pipeline/pipeline_compiler.rs +++ b/crates/bevy_render/src/pipeline/pipeline_compiler.rs @@ -1,15 +1,11 @@ -use super::{ - state_descriptors::PrimitiveTopology, PipelineDescriptor, RenderPipelines, - VertexBufferDescriptors, -}; +use super::{state_descriptors::PrimitiveTopology, PipelineDescriptor, VertexBufferDescriptors}; use crate::{ renderer::RenderResourceContext, shader::{Shader, ShaderSource}, }; -use bevy_asset::{Assets, Handle, AssetEvent}; -use legion::prelude::*; +use bevy_asset::{Assets, Handle}; +use once_cell::sync::Lazy; use std::collections::{HashMap, HashSet}; -use bevy_app::Events; #[derive(Clone, Eq, PartialEq, Debug, Default)] pub struct PipelineSpecialization { @@ -18,6 +14,14 @@ pub struct PipelineSpecialization { pub dynamic_bindings: Vec, } +impl PipelineSpecialization { + pub fn empty() -> &'static PipelineSpecialization { + pub static EMPTY: Lazy = + Lazy::new(|| PipelineSpecialization::default()); + &EMPTY + } +} + #[derive(Clone, Eq, PartialEq, Debug, Default)] pub struct ShaderSpecialization { pub shader_defs: HashSet, @@ -90,7 +94,24 @@ impl PipelineCompiler { } } - fn compile_pipeline( + pub fn get_specialized_pipeline( + &self, + pipeline: Handle, + specialization: &PipelineSpecialization, + ) -> Option> { + self.specialized_pipelines + .get(&pipeline) + .and_then(|specialized_pipelines| { + specialized_pipelines + .iter() + .find(|current_specialized_pipeline| { + ¤t_specialized_pipeline.specialization == specialization + }) + }) + .map(|specialized_pipeline| specialized_pipeline.pipeline) + } + + pub fn compile_pipeline( &mut self, render_resource_context: &dyn RenderResourceContext, pipelines: &mut Assets, @@ -152,48 +173,16 @@ impl PipelineCompiler { specialized_pipeline_handle } - fn compile_render_pipelines( - &mut self, - vertex_buffer_descriptors: &VertexBufferDescriptors, - pipelines: &mut Assets, - shaders: &mut Assets, - render_pipelines: &mut RenderPipelines, - render_resource_context: &dyn RenderResourceContext, - ) { - for render_pipeline in render_pipelines.pipelines.iter_mut() { - let source_pipeline = render_pipeline.pipeline; - let compiled_pipeline_handle = if let Some(specialized_pipeline) = - self.specialized_pipelines - .get_mut(&source_pipeline) - .and_then(|specialized_pipelines| { - specialized_pipelines.iter().find( - |current_specialized_pipeline| { - current_specialized_pipeline.specialization == render_pipeline.specialization - }, - ) - }) { - specialized_pipeline.pipeline - } else { - self.compile_pipeline( - render_resource_context, - pipelines, - shaders, - source_pipeline, - vertex_buffer_descriptors, - &render_pipeline.specialization, - ) - }; - - render_pipeline.specialized_pipeline = Some(compiled_pipeline_handle); - } - } - pub fn iter_compiled_pipelines( &self, pipeline_handle: Handle, ) -> Option>> { if let Some(compiled_pipelines) = self.specialized_pipelines.get(&pipeline_handle) { - Some(compiled_pipelines.iter().map(|specialized_pipeline| &specialized_pipeline.pipeline)) + Some( + compiled_pipelines + .iter() + .map(|specialized_pipeline| &specialized_pipeline.pipeline), + ) } else { None } @@ -210,65 +199,3 @@ impl PipelineCompiler { .flatten() } } - -// TODO: make this a system -pub fn compile_pipelines_system( - world: &mut SubWorld, - mut pipeline_compiler: ResMut, - mut shaders: ResMut>, - mut pipelines: ResMut>, - _pipeline_asset_events: Res>>, - vertex_buffer_descriptors: Res, - render_resource_context: Res>, - query: &mut Query>, -) { - let render_resource_context = &**render_resource_context; - // NOTE: this intentionally only handles events that happened prior to this system during this frame. this results in - // "new specialized pipeline" events being ignored. - // let default_specialization = PipelineSpecialization::default(); - // for event in pipeline_asset_events.iter_current_update_events() { - // let handle_to_compile = match event { - // AssetEvent::Created { handle } => Some(*handle), - // AssetEvent::Modified { handle } => { - // // TODO: clean up old pipelines - // Some(*handle) - // } - // AssetEvent::Removed { .. } => { - // // TODO: clean up old pipelines - // None - // } - // }; - - // if let Some(handle_to_compile) = handle_to_compile { - // // TODO: try updating specialization here. - // pipeline_compiler.compile_pipeline( - // render_resource_context, - // &mut pipelines, - // &mut shaders, - // handle_to_compile, - // &vertex_buffer_descriptors, - // &default_specialization, - // ); - // } - // } - - // TODO: only update when RenderPipelines is changed - for mut render_pipelines in query.iter_mut(world) { - pipeline_compiler.compile_render_pipelines( - &vertex_buffer_descriptors, - &mut pipelines, - &mut shaders, - &mut render_pipelines, - render_resource_context, - ); - - // reset shader_defs so they can be changed next frame - for render_pipeline in render_pipelines.pipelines.iter_mut() { - render_pipeline - .specialization - .shader_specialization - .shader_defs - .clear(); - } - } -} diff --git a/crates/bevy_render/src/pipeline/render_pipelines.rs b/crates/bevy_render/src/pipeline/render_pipelines.rs index bec68040c0..e05addabf9 100644 --- a/crates/bevy_render/src/pipeline/render_pipelines.rs +++ b/crates/bevy_render/src/pipeline/render_pipelines.rs @@ -1,16 +1,15 @@ use super::{PipelineDescriptor, PipelineSpecialization}; use crate::{ - draw::{DrawContext, DrawError, Drawable}, + draw::{Draw, DrawContext, DrawError, Drawable}, render_resource::RenderResourceBindings, }; use bevy_asset::Handle; use bevy_property::Properties; +use legion::{prelude::ComMut, systems::ResMut}; #[derive(Properties, Default, Clone)] pub struct RenderPipeline { pub pipeline: Handle, #[property(ignore)] - pub specialized_pipeline: Option>, - #[property(ignore)] pub specialization: PipelineSpecialization, } @@ -22,7 +21,10 @@ impl RenderPipeline { } } - pub fn specialized(pipeline: Handle, specialization: PipelineSpecialization) -> Self { + pub fn specialized( + pipeline: Handle, + specialization: PipelineSpecialization, + ) -> Self { RenderPipeline { pipeline, specialization, @@ -68,55 +70,46 @@ impl Default for RenderPipelines { } } -impl Drawable for RenderPipelines { - fn draw(&mut self, draw: &mut DrawContext) -> Result<(), DrawError> { - for render_pipeline in self.pipelines.iter() { - let specialized_handle = if let Some(handle) = render_pipeline.specialized_pipeline { - handle - } else { - continue; - }; - let pipeline = draw.pipelines.get(&specialized_handle).unwrap(); - let layout = pipeline.get_layout().unwrap(); - draw.set_pipeline(specialized_handle)?; - for bind_group_descriptor in layout.bind_groups.iter() { - if let Some(local_bind_group) = self - .bindings - .get_descriptor_bind_group(bind_group_descriptor.id) - { - draw.set_bind_group(bind_group_descriptor.index, local_bind_group); - } else if let Some(global_bind_group) = draw - .render_resource_bindings - .get_descriptor_bind_group(bind_group_descriptor.id) - { - draw.set_bind_group(bind_group_descriptor.index, global_bind_group); - } - } - let mut indices = 0..0; - for (slot, vertex_buffer_descriptor) in - layout.vertex_buffer_descriptors.iter().enumerate() - { - if let Some((vertex_buffer, index_buffer)) = self - .bindings - .get_vertex_buffer(&vertex_buffer_descriptor.name) - { - draw.set_vertex_buffer(slot as u32, vertex_buffer, 0); - if let Some(index_buffer) = index_buffer { - if let Some(buffer_info) = - draw.render_resource_context.get_buffer_info(index_buffer) - { - indices = 0..(buffer_info.size / 2) as u32; - } else { - panic!("expected buffer type"); - } - draw.set_index_buffer(index_buffer, 0); - } - } - } +pub struct DrawableRenderPipelines<'a> { + pub render_pipelines: &'a mut RenderPipelines, + pub render_resource_bindings: &'a mut RenderResourceBindings, +} - draw.draw_indexed(indices, 0, 0..1); +impl<'a> Drawable for DrawableRenderPipelines<'a> { + fn draw(&mut self, draw: &mut Draw, context: &mut DrawContext) -> Result<(), DrawError> { + for render_pipeline in self.render_pipelines.pipelines.iter() { + context.set_pipeline( + draw, + render_pipeline.pipeline, + &render_pipeline.specialization, + )?; + context.set_bind_groups_from_bindings( + draw, + &mut [ + &mut self.render_pipelines.bindings, + self.render_resource_bindings, + ], + )?; + let indices = context + .set_vertex_buffers_from_bindings(draw, &[&self.render_pipelines.bindings])?; + if let Some(indices) = indices { + draw.draw_indexed(indices, 0, 0..1); + } } Ok(()) } } + +pub fn draw_render_pipelines_system( + mut draw_context: DrawContext, + mut render_resource_bindings: ResMut, + mut draw: ComMut, + mut render_pipelines: ComMut, +) { + let mut drawable = DrawableRenderPipelines { + render_pipelines: &mut render_pipelines, + render_resource_bindings: &mut render_resource_bindings, + }; + drawable.draw(&mut draw, &mut draw_context).unwrap(); +} diff --git a/crates/bevy_render/src/render_resource/mod.rs b/crates/bevy_render/src/render_resource/mod.rs index a2a295423f..7810a87147 100644 --- a/crates/bevy_render/src/render_resource/mod.rs +++ b/crates/bevy_render/src/render_resource/mod.rs @@ -3,7 +3,6 @@ mod buffer; mod render_resource; mod render_resource_bindings; mod shared_buffers; -mod systems; mod texture; pub use bind_group::*; @@ -11,5 +10,4 @@ pub use buffer::*; pub use render_resource::*; pub use render_resource_bindings::*; pub use shared_buffers::*; -pub use systems::*; pub use texture::*; diff --git a/crates/bevy_render/src/render_resource/render_resource_bindings.rs b/crates/bevy_render/src/render_resource/render_resource_bindings.rs index 946072fa0b..9104c9c7f3 100644 --- a/crates/bevy_render/src/render_resource/render_resource_bindings.rs +++ b/crates/bevy_render/src/render_resource/render_resource_bindings.rs @@ -1,5 +1,8 @@ use super::{BindGroup, BindGroupId, BufferId, RenderResourceId, SamplerId, TextureId}; -use crate::{renderer::RenderResourceContext, pipeline::{BindGroupDescriptor, BindGroupDescriptorId, PipelineDescriptor}}; +use crate::{ + pipeline::{BindGroupDescriptor, BindGroupDescriptorId, PipelineDescriptor}, + renderer::RenderResourceContext, +}; use bevy_asset::{Handle, HandleUntyped}; use std::{ collections::{HashMap, HashSet}, @@ -82,10 +85,8 @@ pub struct RenderResourceBindings { // TODO: remove this vertex_buffers: HashMap)>, bind_groups: HashMap, - bind_group_descriptors: HashMap, + bind_group_descriptors: HashMap>, dirty_bind_groups: HashSet, - // TODO: remove this - // pub pipeline_specialization: PipelineSpecialization, } impl RenderResourceBindings { @@ -139,7 +140,7 @@ impl RenderResourceBindings { if let Some(bind_group) = bind_group { let id = bind_group.id; self.bind_groups.insert(id, bind_group); - self.bind_group_descriptors.insert(descriptor.id, id); + self.bind_group_descriptors.insert(descriptor.id, Some(id)); BindGroupStatus::Changed(id) } else { BindGroupStatus::NoMatch @@ -151,18 +152,26 @@ impl RenderResourceBindings { bind_group_descriptor: &BindGroupDescriptor, ) -> BindGroupStatus { if let Some(id) = self.bind_group_descriptors.get(&bind_group_descriptor.id) { - if self.dirty_bind_groups.contains(id) { - self.dirty_bind_groups.remove(id); - self.create_bind_group(bind_group_descriptor) + if let Some(id) = id { + if self.dirty_bind_groups.contains(id) { + self.dirty_bind_groups.remove(id); + self.create_bind_group(bind_group_descriptor) + } else { + BindGroupStatus::Unchanged(*id) + } } else { - BindGroupStatus::Unchanged(*id) + BindGroupStatus::NoMatch } } else { self.create_bind_group(bind_group_descriptor) } } - pub fn update_bind_groups(&mut self, pipeline: &PipelineDescriptor, render_resource_context: &dyn RenderResourceContext) { + pub fn update_bind_groups( + &mut self, + pipeline: &PipelineDescriptor, + render_resource_context: &dyn RenderResourceContext, + ) { let layout = pipeline.get_layout().unwrap(); for bind_group_descriptor in layout.bind_groups.iter() { match self.update_bind_group(bind_group_descriptor) { @@ -195,7 +204,13 @@ impl RenderResourceBindings { pub fn get_descriptor_bind_group(&self, id: BindGroupDescriptorId) -> Option<&BindGroup> { self.bind_group_descriptors .get(&id) - .and_then(|bind_group_id| self.get_bind_group(*bind_group_id)) + .and_then(|bind_group_id| { + if let Some(bind_group_id) = bind_group_id { + self.get_bind_group(*bind_group_id) + } else { + None + } + }) } fn build_bind_group(&self, bind_group_descriptor: &BindGroupDescriptor) -> Option { @@ -228,6 +243,10 @@ impl AssetRenderResourceBindings { .entry(HandleUntyped::from(handle)) .or_insert_with(|| RenderResourceBindings::default()) } + + pub fn get_mut(&mut self, handle: Handle) -> Option<&mut RenderResourceBindings> { + self.bindings.get_mut(&HandleUntyped::from(handle)) + } } #[derive(Hash, Eq, PartialEq, Debug, Copy, Clone)] diff --git a/crates/bevy_render/src/render_resource/systems.rs b/crates/bevy_render/src/render_resource/systems.rs deleted file mode 100644 index af8685a197..0000000000 --- a/crates/bevy_render/src/render_resource/systems.rs +++ /dev/null @@ -1,31 +0,0 @@ -use crate::{ - pipeline::{PipelineCompiler, PipelineDescriptor, RenderPipelines}, - render_resource::RenderResourceBindings, - renderer::RenderResourceContext, -}; -use bevy_asset::Assets; -use legion::prelude::*; - -pub fn bind_groups_system( - world: &mut SubWorld, - pipelines: Res>, - pipeline_compiler: Res, - render_resource_context: Res>, - mut render_resource_bindings: ResMut, - query: &mut Query>, -) { - let render_resource_context = &**render_resource_context; - for compiled_pipeline_handle in pipeline_compiler.iter_all_compiled_pipelines() { - let pipeline = pipelines.get(compiled_pipeline_handle).unwrap(); - render_resource_bindings.update_bind_groups(pipeline, render_resource_context); - } - for mut render_pipelines in query.iter_mut(world) { - let render_pipelines = render_pipelines.as_mut(); - for render_pipeline in render_pipelines.pipelines.iter_mut() { - let pipeline = pipelines - .get(&render_pipeline.specialized_pipeline.unwrap()) - .unwrap(); - render_pipelines.bindings.update_bind_groups(pipeline, render_resource_context); - } - } -} diff --git a/crates/bevy_text/src/draw.rs b/crates/bevy_text/src/draw.rs index 0fda810fe1..fda77dab5c 100644 --- a/crates/bevy_text/src/draw.rs +++ b/crates/bevy_text/src/draw.rs @@ -1,10 +1,10 @@ use crate::{Font, FontAtlasSet}; use bevy_asset::Assets; use bevy_render::{ - draw::{DrawContext, DrawError, Drawable}, + draw::{DrawContext, DrawError, Drawable, Draw}, mesh, render_resource::{BindGroup, BufferUsage, RenderResourceId}, - Color, + Color, pipeline::PipelineSpecialization, }; use bevy_sprite::{TextureAtlas, TextureAtlasSprite}; use glam::{Vec2, Vec3}; @@ -45,10 +45,9 @@ impl<'a> DrawableText<'a> { } impl<'a> Drawable for DrawableText<'a> { - fn draw(&mut self, draw: &mut DrawContext) -> Result<(), DrawError> { - draw.set_pipeline(bevy_sprite::SPRITE_SHEET_PIPELINE_HANDLE)?; - let render_resource_context = draw.render_resource_context; - // TODO: add draw.set_mesh(slot) + fn draw(&mut self, draw: &mut Draw, context: &mut DrawContext) -> Result<(), DrawError> { + context.set_pipeline(draw, bevy_sprite::SPRITE_SHEET_PIPELINE_HANDLE, PipelineSpecialization::empty())?; + let render_resource_context = &**context.render_resource_context; if let Some(RenderResourceId::Buffer(quad_vertex_buffer)) = render_resource_context .get_asset_resource(bevy_sprite::QUAD_HANDLE, mesh::VERTEX_BUFFER_ASSET_INDEX) { @@ -59,8 +58,7 @@ impl<'a> Drawable for DrawableText<'a> { .get_asset_resource(bevy_sprite::QUAD_HANDLE, mesh::INDEX_BUFFER_ASSET_INDEX) { draw.set_index_buffer(quad_index_buffer, 0); - if let Some(buffer_info) = draw - .render_resource_context + if let Some(buffer_info) = render_resource_context .get_buffer_info(quad_index_buffer) { indices = 0..(buffer_info.size / 2) as u32; @@ -70,7 +68,7 @@ impl<'a> Drawable for DrawableText<'a> { } // set global bindings - draw.set_bind_groups_from_bindings(&draw.render_resource_bindings)?; + // context.set_bind_groups_from_bindings(draw, &mut[context.render_resource_bindings])?; // set local per-character bindings for character in self.text.chars() { @@ -78,17 +76,17 @@ impl<'a> Drawable for DrawableText<'a> { .font_atlas_set .get_glyph_atlas_info(self.style.font_size, character) { - let atlas_render_resource_bindings = draw - .asset_render_resource_bindings - .get(glyph_atlas_info.texture_atlas) - .unwrap(); - draw.set_bind_groups_from_bindings(&atlas_render_resource_bindings)?; + // let atlas_render_resource_bindings = context + // .asset_render_resource_bindings + // .get_mut(glyph_atlas_info.texture_atlas) + // .unwrap(); + // context.set_bind_groups_from_bindings(draw, &mut[atlas_render_resource_bindings])?; let sprite_buffer = TextureAtlasSprite { index: glyph_atlas_info.char_index, position: Vec3::new(300.0, 300.0, 0.0), scale: 5.0, }; - let sprite_buffer = draw + let sprite_buffer = context .shared_buffers .get_buffer(&sprite_buffer, BufferUsage::UNIFORM) .unwrap(); diff --git a/crates/bevy_ui/src/widget/label.rs b/crates/bevy_ui/src/widget/label.rs index 3ac8bb5557..9920c0f6d9 100644 --- a/crates/bevy_ui/src/widget/label.rs +++ b/crates/bevy_ui/src/widget/label.rs @@ -1,12 +1,5 @@ use bevy_asset::{Assets, Handle}; -use bevy_render::{ - draw::Draw, - pipeline::PipelineDescriptor, - render_resource::{AssetRenderResourceBindings, RenderResourceBindings, SharedBuffers}, - renderer::RenderResourceContext, - texture::Texture, - Color, -}; +use bevy_render::{draw::{DrawContext, Draw}, texture::Texture, Color}; use bevy_sprite::{ColorMaterial, ComMut, Quad, TextureAtlas}; use bevy_text::{Font, FontAtlasSet, TextStyle}; use legion::prelude::{Com, Res, ResMut}; @@ -78,11 +71,7 @@ impl Label { } pub fn draw_label_system( - _pipelines: Res>, - _render_resource_bindings: Res, - _asset_render_resource_bindings: Res, - _render_resource_context: Res>, - _shared_buffers: Res, + mut _draw_context: DrawContext, _fonts: Res>, _font_atlas_sets: Res>, _texture_atlases: Res>, @@ -90,23 +79,16 @@ impl Label { _label: Com