pipeline specialization (support different primitive topologies within the same pipeline)
This commit is contained in:
		
							parent
							
								
									86d0ae6470
								
							
						
					
					
						commit
						7fe2288814
					
				| @ -118,7 +118,7 @@ impl<T> AssetStorage<T> { | |||||||
|         AssetStorage { |         AssetStorage { | ||||||
|             assets: HashMap::new(), |             assets: HashMap::new(), | ||||||
|             names: HashMap::new(), |             names: HashMap::new(), | ||||||
|             current_index: 1, |             current_index: DEFAULT_HANDLE_ID + 1, // ensure we don't start on the default handle id
 | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -39,7 +39,7 @@ use self::{ | |||||||
|     }, |     }, | ||||||
|     render_graph::RenderGraph, |     render_graph::RenderGraph, | ||||||
|     render_resource::{ |     render_resource::{ | ||||||
|         build_entity_render_resource_assignments_system, |         entity_render_resource_assignments_system, | ||||||
|         resource_providers::{ |         resource_providers::{ | ||||||
|             Camera2dResourceProvider, CameraResourceProvider, LightResourceProvider, |             Camera2dResourceProvider, CameraResourceProvider, LightResourceProvider, | ||||||
|             UniformResourceProvider, |             UniformResourceProvider, | ||||||
| @ -111,8 +111,12 @@ impl AppPlugin for RenderPlugin { | |||||||
|             .add_resource(EntityRenderResourceAssignments::default()) |             .add_resource(EntityRenderResourceAssignments::default()) | ||||||
|             .add_resource(asset_batchers) |             .add_resource(asset_batchers) | ||||||
|             // core systems
 |             // core systems
 | ||||||
|             .add_system(build_entity_render_resource_assignments_system()) |             .add_system(entity_render_resource_assignments_system()) | ||||||
|             .add_system_to_stage_init(stage::POST_UPDATE, camera::camera_update_system) |             .add_system_to_stage_init(stage::POST_UPDATE, camera::camera_update_system) | ||||||
|  |             .add_system_to_stage( | ||||||
|  |                 stage::POST_UPDATE, | ||||||
|  |                 mesh::mesh_specializer_system(), | ||||||
|  |             ) | ||||||
|             .add_system_to_stage(stage::POST_UPDATE, mesh::mesh_batcher_system()) |             .add_system_to_stage(stage::POST_UPDATE, mesh::mesh_batcher_system()) | ||||||
|             .add_system_to_stage( |             .add_system_to_stage( | ||||||
|                 stage::POST_UPDATE, |                 stage::POST_UPDATE, | ||||||
|  | |||||||
| @ -6,7 +6,7 @@ use crate::{ | |||||||
|     render_resource::AssetBatchers, |     render_resource::AssetBatchers, | ||||||
|     Renderable, |     Renderable, | ||||||
| }; | }; | ||||||
| use bevy_asset::Handle; | use bevy_asset::{AssetStorage, Handle}; | ||||||
| use glam::*; | use glam::*; | ||||||
| use legion::prelude::*; | use legion::prelude::*; | ||||||
| use std::borrow::Cow; | use std::borrow::Cow; | ||||||
| @ -224,7 +224,7 @@ pub mod shape { | |||||||
|             ]; |             ]; | ||||||
| 
 | 
 | ||||||
|             Mesh { |             Mesh { | ||||||
|                 primitive_topology: PrimitiveTopology::TriangleStrip, |                 primitive_topology: PrimitiveTopology::TriangleList, | ||||||
|                 attributes: vec![ |                 attributes: vec![ | ||||||
|                     VertexAttribute::position(positions), |                     VertexAttribute::position(positions), | ||||||
|                     VertexAttribute::normal(normals), |                     VertexAttribute::normal(normals), | ||||||
| @ -283,7 +283,7 @@ pub mod shape { | |||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             Mesh { |             Mesh { | ||||||
|                 primitive_topology: PrimitiveTopology::TriangleStrip, |                 primitive_topology: PrimitiveTopology::TriangleList, | ||||||
|                 attributes: vec![ |                 attributes: vec![ | ||||||
|                     VertexAttribute::position(positions), |                     VertexAttribute::position(positions), | ||||||
|                     VertexAttribute::normal(normals), |                     VertexAttribute::normal(normals), | ||||||
| @ -321,6 +321,20 @@ pub fn mesh_batcher_system() -> Box<dyn Schedulable> { | |||||||
|         }) |         }) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | pub fn mesh_specializer_system() -> Box<dyn Schedulable> { | ||||||
|  |     SystemBuilder::new("mesh_batcher") | ||||||
|  |         .read_resource::<AssetStorage<Mesh>>() | ||||||
|  |         .with_query( | ||||||
|  |             <(Read<Handle<Mesh>>, Write<Renderable>)>::query().filter(changed::<Handle<Mesh>>() | changed::<Renderable>()), | ||||||
|  |         ) | ||||||
|  |         .build(|_, world, meshes, query| { | ||||||
|  |             for (mesh_handle, mut renderable) in query.iter_mut(world) { | ||||||
|  |                 let mesh = meshes.get(&mesh_handle).unwrap(); | ||||||
|  |                 renderable.render_resource_assignments.pipeline_specialization.primitive_topology = mesh.primitive_topology; | ||||||
|  |             } | ||||||
|  |         }) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| #[cfg(test)] | #[cfg(test)] | ||||||
| mod tests { | mod tests { | ||||||
|     use crate::{Vertex, pipeline::state_descriptors::PrimitiveTopology, shader::AsUniforms}; |     use crate::{Vertex, pipeline::state_descriptors::PrimitiveTopology, shader::AsUniforms}; | ||||||
|  | |||||||
| @ -1,5 +1,6 @@ | |||||||
| use super::{ | use super::{ | ||||||
|     BindType, PipelineDescriptor, PipelineLayout, PipelineLayoutType, VertexBufferDescriptors, |     state_descriptors::PrimitiveTopology, BindType, PipelineDescriptor, PipelineLayout, | ||||||
|  |     PipelineLayoutType, VertexBufferDescriptors, | ||||||
| }; | }; | ||||||
| use crate::{ | use crate::{ | ||||||
|     render_resource::{ |     render_resource::{ | ||||||
| @ -14,11 +15,25 @@ use std::collections::{HashMap, HashSet}; | |||||||
| 
 | 
 | ||||||
| use legion::prelude::*; | use legion::prelude::*; | ||||||
| 
 | 
 | ||||||
|  | #[derive(Clone, Eq, PartialEq, Debug, Default)] | ||||||
|  | pub struct PipelineSpecialization { | ||||||
|  |     pub shader_specialization: ShaderSpecialization, | ||||||
|  |     pub primitive_topology: PrimitiveTopology, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Clone, Eq, PartialEq, Debug, Default)] | ||||||
|  | pub struct ShaderSpecialization { | ||||||
|  |     pub shader_defs: HashSet<String>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // TODO: consider using (Typeid, fieldinfo.index) in place of string for hashes
 | // TODO: consider using (Typeid, fieldinfo.index) in place of string for hashes
 | ||||||
| pub struct PipelineCompiler { | pub struct PipelineCompiler { | ||||||
|     pub shader_source_to_compiled: HashMap<Handle<Shader>, Vec<(HashSet<String>, Handle<Shader>)>>, |     pub shader_source_to_compiled: | ||||||
|     pub pipeline_source_to_compiled: |         HashMap<Handle<Shader>, Vec<(ShaderSpecialization, Handle<Shader>)>>, | ||||||
|         HashMap<Handle<PipelineDescriptor>, Vec<(HashSet<String>, Handle<PipelineDescriptor>)>>, |     pub pipeline_source_to_compiled: HashMap< | ||||||
|  |         Handle<PipelineDescriptor>, | ||||||
|  |         Vec<(PipelineSpecialization, Handle<PipelineDescriptor>)>, | ||||||
|  |     >, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl PipelineCompiler { | impl PipelineCompiler { | ||||||
| @ -86,7 +101,7 @@ impl PipelineCompiler { | |||||||
|         &mut self, |         &mut self, | ||||||
|         shader_storage: &mut AssetStorage<Shader>, |         shader_storage: &mut AssetStorage<Shader>, | ||||||
|         shader_handle: &Handle<Shader>, |         shader_handle: &Handle<Shader>, | ||||||
|         shader_defs: &HashSet<String>, |         shader_specialization: &ShaderSpecialization, | ||||||
|     ) -> Handle<Shader> { |     ) -> Handle<Shader> { | ||||||
|         let compiled_shaders = self |         let compiled_shaders = self | ||||||
|             .shader_source_to_compiled |             .shader_source_to_compiled | ||||||
| @ -100,18 +115,26 @@ impl PipelineCompiler { | |||||||
|             return *shader_handle; |             return *shader_handle; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if let Some((_compiled_shader_defs, compiled_shader)) = compiled_shaders |         if let Some((_shader_specialization, compiled_shader)) = | ||||||
|             .iter() |             compiled_shaders | ||||||
|             .find(|(compiled_shader_defs, _compiled_shader)| *compiled_shader_defs == *shader_defs) |                 .iter() | ||||||
|  |                 .find(|(current_shader_specialization, _compiled_shader)| { | ||||||
|  |                     *current_shader_specialization == *shader_specialization | ||||||
|  |                 }) | ||||||
|         { |         { | ||||||
|             // if shader has already been compiled with current configuration, use existing shader
 |             // if shader has already been compiled with current configuration, use existing shader
 | ||||||
|             *compiled_shader |             *compiled_shader | ||||||
|         } else { |         } else { | ||||||
|             // if no shader exists with the current configuration, create new shader and compile
 |             // if no shader exists with the current configuration, create new shader and compile
 | ||||||
|             let shader_def_vec = shader_defs.iter().cloned().collect::<Vec<String>>(); |             let shader_def_vec = shader_specialization | ||||||
|  |                 .shader_defs | ||||||
|  |                 .iter() | ||||||
|  |                 .cloned() | ||||||
|  |                 .collect::<Vec<String>>(); | ||||||
|             let compiled_shader = shader.get_spirv_shader(Some(&shader_def_vec)); |             let compiled_shader = shader.get_spirv_shader(Some(&shader_def_vec)); | ||||||
|             compiled_shaders.push((shader_defs.clone(), *shader_handle)); |             let compiled_handle = shader_storage.add(compiled_shader); | ||||||
|             shader_storage.add(compiled_shader) |             compiled_shaders.push((shader_specialization.clone(), compiled_handle)); | ||||||
|  |             compiled_handle | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -128,7 +151,9 @@ impl PipelineCompiler { | |||||||
|         compiled_pipeline_descriptor.shader_stages.vertex = self.compile_shader( |         compiled_pipeline_descriptor.shader_stages.vertex = self.compile_shader( | ||||||
|             shader_storage, |             shader_storage, | ||||||
|             &pipeline_descriptor.shader_stages.vertex, |             &pipeline_descriptor.shader_stages.vertex, | ||||||
|             &render_resource_assignments.shader_defs, |             &render_resource_assignments | ||||||
|  |                 .pipeline_specialization | ||||||
|  |                 .shader_specialization, | ||||||
|         ); |         ); | ||||||
|         compiled_pipeline_descriptor.shader_stages.fragment = pipeline_descriptor |         compiled_pipeline_descriptor.shader_stages.fragment = pipeline_descriptor | ||||||
|             .shader_stages |             .shader_stages | ||||||
| @ -138,7 +163,9 @@ impl PipelineCompiler { | |||||||
|                 self.compile_shader( |                 self.compile_shader( | ||||||
|                     shader_storage, |                     shader_storage, | ||||||
|                     fragment, |                     fragment, | ||||||
|                     &render_resource_assignments.shader_defs, |                     &render_resource_assignments | ||||||
|  |                         .pipeline_specialization | ||||||
|  |                         .shader_specialization, | ||||||
|                 ) |                 ) | ||||||
|             }); |             }); | ||||||
| 
 | 
 | ||||||
| @ -150,6 +177,9 @@ impl PipelineCompiler { | |||||||
|             render_resource_assignments, |             render_resource_assignments, | ||||||
|         ); |         ); | ||||||
| 
 | 
 | ||||||
|  |         compiled_pipeline_descriptor.primitive_topology = render_resource_assignments | ||||||
|  |             .pipeline_specialization | ||||||
|  |             .primitive_topology; | ||||||
|         compiled_pipeline_descriptor |         compiled_pipeline_descriptor | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -174,8 +204,8 @@ impl PipelineCompiler { | |||||||
|                 .get_mut(pipeline_handle) |                 .get_mut(pipeline_handle) | ||||||
|                 .unwrap() |                 .unwrap() | ||||||
|                 .iter() |                 .iter() | ||||||
|                 .find(|(shader_defs, _macroed_pipeline_handle)| { |                 .find(|(pipeline_specialization, _macroed_pipeline_handle)| { | ||||||
|                     *shader_defs == render_resource_assignments.shader_defs |                     *pipeline_specialization == render_resource_assignments.pipeline_specialization | ||||||
|                 }) { |                 }) { | ||||||
|                 *macroed_pipeline_handle |                 *macroed_pipeline_handle | ||||||
|             } else { |             } else { | ||||||
| @ -194,7 +224,7 @@ impl PipelineCompiler { | |||||||
|                     .get_mut(pipeline_handle) |                     .get_mut(pipeline_handle) | ||||||
|                     .unwrap(); |                     .unwrap(); | ||||||
|                 macro_pipelines.push(( |                 macro_pipelines.push(( | ||||||
|                     render_resource_assignments.shader_defs.clone(), |                     render_resource_assignments.pipeline_specialization.clone(), | ||||||
|                     compiled_pipeline_handle, |                     compiled_pipeline_handle, | ||||||
|                 )); |                 )); | ||||||
|                 compiled_pipeline_handle |                 compiled_pipeline_handle | ||||||
| @ -277,7 +307,12 @@ pub fn update_shader_assignments( | |||||||
|             ); |             ); | ||||||
| 
 | 
 | ||||||
|             // reset shader_defs so they can be changed next frame
 |             // reset shader_defs so they can be changed next frame
 | ||||||
|             renderable.render_resource_assignments.shader_defs.clear(); |             renderable | ||||||
|  |                 .render_resource_assignments | ||||||
|  |                 .pipeline_specialization | ||||||
|  |                 .shader_specialization | ||||||
|  |                 .shader_defs | ||||||
|  |                 .clear(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -55,7 +55,7 @@ impl<'a, 'b, 'c> ForwardPipelineBuilder for RenderGraphBuilder<'a, 'b, 'c> { | |||||||
|                     }, |                     }, | ||||||
|                     write_mask: ColorWrite::ALL, |                     write_mask: ColorWrite::ALL, | ||||||
|                 }) |                 }) | ||||||
|                 .add_draw_target(resource_name::draw_target::ASSIGNED_BATCHES); |                 .add_draw_target(resource_name::draw_target::ASSIGNED_MESHES); | ||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -60,6 +60,12 @@ pub enum PrimitiveTopology { | |||||||
|     TriangleStrip = 4, |     TriangleStrip = 4, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | impl Default for PrimitiveTopology { | ||||||
|  |     fn default() -> Self { | ||||||
|  |         PrimitiveTopology::TriangleList | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] | #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] | ||||||
| pub enum FrontFace { | pub enum FrontFace { | ||||||
|     Ccw = 0, |     Ccw = 0, | ||||||
| @ -172,3 +178,9 @@ pub enum IndexFormat { | |||||||
|     Uint16 = 0, |     Uint16 = 0, | ||||||
|     Uint32 = 1, |     Uint32 = 1, | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | impl Default for IndexFormat { | ||||||
|  |     fn default() -> Self { | ||||||
|  |         IndexFormat::Uint16 | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | |||||||
| @ -19,7 +19,7 @@ impl EntityRenderResourceAssignments { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // TODO: make sure this runs right before rendering
 | // TODO: make sure this runs right before rendering
 | ||||||
| pub fn build_entity_render_resource_assignments_system() -> Box<dyn Schedulable> { | pub fn entity_render_resource_assignments_system() -> Box<dyn Schedulable> { | ||||||
|     SystemBuilder::new("entity_render_resource_assignments") |     SystemBuilder::new("entity_render_resource_assignments") | ||||||
|         .write_resource::<EntityRenderResourceAssignments>() |         .write_resource::<EntityRenderResourceAssignments>() | ||||||
|         .with_query(<Write<Renderable>>::query().filter(changed::<Renderable>())) |         .with_query(<Write<Renderable>>::query().filter(changed::<Renderable>())) | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| use super::RenderResource; | use super::RenderResource; | ||||||
| use crate::pipeline::{BindGroupDescriptor, BindGroupDescriptorId}; | use crate::pipeline::{BindGroupDescriptor, BindGroupDescriptorId, PipelineSpecialization}; | ||||||
| use std::{ | use std::{ | ||||||
|     collections::{hash_map::DefaultHasher, HashMap, HashSet}, |     collections::{hash_map::DefaultHasher, HashMap, HashSet}, | ||||||
|     hash::{Hash, Hasher}, |     hash::{Hash, Hasher}, | ||||||
| @ -15,7 +15,7 @@ pub struct RenderResourceAssignments { | |||||||
|     bind_group_resource_sets: |     bind_group_resource_sets: | ||||||
|         HashMap<BindGroupDescriptorId, (RenderResourceSetId, Option<Vec<u32>>)>, |         HashMap<BindGroupDescriptorId, (RenderResourceSetId, Option<Vec<u32>>)>, | ||||||
|     dirty_bind_groups: HashSet<BindGroupDescriptorId>, |     dirty_bind_groups: HashSet<BindGroupDescriptorId>, | ||||||
|     pub(crate) shader_defs: HashSet<String>, |     pub pipeline_specialization: PipelineSpecialization, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl RenderResourceAssignments { | impl RenderResourceAssignments { | ||||||
|  | |||||||
| @ -1,80 +1,96 @@ | |||||||
| use crate::{ | use crate::{ | ||||||
|     mesh::{self, Mesh}, |     mesh::{self, Mesh}, | ||||||
|     pipeline::{state_descriptors::IndexFormat, VertexBufferDescriptors}, |     pipeline::{state_descriptors::IndexFormat, VertexBufferDescriptor, VertexBufferDescriptors}, | ||||||
|     render_resource::{AssetBatchers, BufferInfo, BufferUsage}, |     render_resource::{AssetBatchers, BufferInfo, BufferUsage, RenderResourceAssignments}, | ||||||
|     renderer_2::GlobalRenderResourceContext, |     renderer_2::{GlobalRenderResourceContext, RenderResourceContext}, | ||||||
|     shader::AsUniforms, |     shader::AsUniforms, | ||||||
|     Vertex, |     Renderable, Vertex, | ||||||
| }; | }; | ||||||
| use bevy_asset::AssetStorage; | use bevy_asset::{AssetStorage, Handle}; | ||||||
| use legion::prelude::*; | use legion::prelude::*; | ||||||
| 
 | 
 | ||||||
|  | fn setup_mesh_resource( | ||||||
|  |     render_resources: &dyn RenderResourceContext, | ||||||
|  |     render_resource_assignments: &mut RenderResourceAssignments, | ||||||
|  |     vertex_buffer_descriptor: &VertexBufferDescriptor, | ||||||
|  |     handle: Handle<Mesh>, | ||||||
|  |     meshes: &AssetStorage<Mesh>, | ||||||
|  | ) { | ||||||
|  |     log::trace!("setup mesh for {:?}", render_resource_assignments.id); | ||||||
|  |     let index_format = IndexFormat::Uint16; | ||||||
|  |     let (vertex_buffer, index_buffer) = if let Some(vertex_buffer) = | ||||||
|  |         render_resources.get_asset_resource(handle, mesh::VERTEX_BUFFER_ASSET_INDEX) | ||||||
|  |     { | ||||||
|  |         ( | ||||||
|  |             vertex_buffer, | ||||||
|  |             render_resources.get_asset_resource(handle, mesh::INDEX_BUFFER_ASSET_INDEX), | ||||||
|  |         ) | ||||||
|  |     } else { | ||||||
|  |         let mesh_asset = meshes.get(&handle).unwrap(); | ||||||
|  |         let vertex_bytes = mesh_asset | ||||||
|  |             .get_vertex_buffer_bytes(&vertex_buffer_descriptor) | ||||||
|  |             .unwrap(); | ||||||
|  |         // TODO: use a staging buffer here
 | ||||||
|  |         let vertex_buffer = render_resources.create_buffer_with_data( | ||||||
|  |             BufferInfo { | ||||||
|  |                 buffer_usage: BufferUsage::VERTEX, | ||||||
|  |                 ..Default::default() | ||||||
|  |             }, | ||||||
|  |             &vertex_bytes, | ||||||
|  |         ); | ||||||
|  |         let index_bytes = mesh_asset.get_index_buffer_bytes(index_format).unwrap(); | ||||||
|  |         let index_buffer = render_resources.create_buffer_with_data( | ||||||
|  |             BufferInfo { | ||||||
|  |                 buffer_usage: BufferUsage::INDEX, | ||||||
|  |                 ..Default::default() | ||||||
|  |             }, | ||||||
|  |             &index_bytes, | ||||||
|  |         ); | ||||||
|  | 
 | ||||||
|  |         render_resources.set_asset_resource(handle, vertex_buffer, mesh::VERTEX_BUFFER_ASSET_INDEX); | ||||||
|  |         render_resources.set_asset_resource(handle, index_buffer, mesh::INDEX_BUFFER_ASSET_INDEX); | ||||||
|  |         (vertex_buffer, Some(index_buffer)) | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     render_resource_assignments.set_vertex_buffer("Vertex", vertex_buffer, index_buffer); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| pub fn mesh_resource_provider_system(resources: &mut Resources) -> Box<dyn Schedulable> { | pub fn mesh_resource_provider_system(resources: &mut Resources) -> Box<dyn Schedulable> { | ||||||
|     let mut vertex_buffer_descriptors = resources.get_mut::<VertexBufferDescriptors>().unwrap(); |     let mut vertex_buffer_descriptors = resources.get_mut::<VertexBufferDescriptors>().unwrap(); | ||||||
|     // TODO: allow pipelines to specialize on vertex_buffer_descriptor and index_format
 |     // TODO: allow pipelines to specialize on vertex_buffer_descriptor and index_format
 | ||||||
|     let vertex_buffer_descriptor = Vertex::get_vertex_buffer_descriptor().unwrap(); |     let vertex_buffer_descriptor = Vertex::get_vertex_buffer_descriptor().unwrap(); | ||||||
|     let index_format = IndexFormat::Uint16; |  | ||||||
|     vertex_buffer_descriptors.set(vertex_buffer_descriptor.clone()); |     vertex_buffer_descriptors.set(vertex_buffer_descriptor.clone()); | ||||||
|     SystemBuilder::new("mesh_resource_provider") |     SystemBuilder::new("mesh_resource_provider") | ||||||
|         .read_resource::<GlobalRenderResourceContext>() |         .read_resource::<GlobalRenderResourceContext>() | ||||||
|         .read_resource::<AssetStorage<Mesh>>() |         .read_resource::<AssetStorage<Mesh>>() | ||||||
|         .write_resource::<AssetBatchers>() |         .write_resource::<AssetBatchers>() | ||||||
|  |         .with_query(<(Read<Handle<Mesh>>, Write<Renderable>)>::query()) | ||||||
|         .build( |         .build( | ||||||
|             move |_, _, (render_resource_context, meshes, asset_batchers), _| { |             move |_, world, (render_resource_context, meshes, asset_batchers), query| { | ||||||
|                 let render_resources = &render_resource_context.context; |                 let render_resources = &*render_resource_context.context; | ||||||
|                 if let Some(batches) = asset_batchers.get_handle_batches_mut::<Mesh>() { |                 if let Some(batches) = asset_batchers.get_handle_batches_mut::<Mesh>() { | ||||||
|                     for batch in batches { |                     for batch in batches { | ||||||
|                         let handle = batch.get_handle::<Mesh>().unwrap(); |                         let handle = batch.get_handle::<Mesh>().unwrap(); | ||||||
|                         log::trace!("setup mesh for {:?}", batch.render_resource_assignments.id); |                         setup_mesh_resource( | ||||||
|                         let (vertex_buffer, index_buffer) = if let Some(vertex_buffer) = |                             render_resources, | ||||||
|                             render_resources |                             &mut batch.render_resource_assignments, | ||||||
|                                 .get_asset_resource(handle, mesh::VERTEX_BUFFER_ASSET_INDEX) |                             &vertex_buffer_descriptor, | ||||||
|                         { |                             handle, | ||||||
|                             ( |                             &meshes, | ||||||
|                                 vertex_buffer, |  | ||||||
|                                 render_resources |  | ||||||
|                                     .get_asset_resource(handle, mesh::INDEX_BUFFER_ASSET_INDEX), |  | ||||||
|                             ) |  | ||||||
|                         } else { |  | ||||||
|                             let mesh_asset = meshes.get(&handle).unwrap(); |  | ||||||
|                             let vertex_bytes = mesh_asset.get_vertex_buffer_bytes(&vertex_buffer_descriptor).unwrap(); |  | ||||||
|                             // TODO: use a staging buffer here
 |  | ||||||
|                             let vertex_buffer = render_resources.create_buffer_with_data( |  | ||||||
|                                 BufferInfo { |  | ||||||
|                                     buffer_usage: BufferUsage::VERTEX, |  | ||||||
|                                     ..Default::default() |  | ||||||
|                                 }, |  | ||||||
|                                 &vertex_bytes, |  | ||||||
|                             ); |  | ||||||
|                             let index_bytes = mesh_asset.get_index_buffer_bytes(index_format).unwrap(); |  | ||||||
|                             let index_buffer = render_resources.create_buffer_with_data( |  | ||||||
|                                 BufferInfo { |  | ||||||
|                                     buffer_usage: BufferUsage::INDEX, |  | ||||||
|                                     ..Default::default() |  | ||||||
|                                 }, |  | ||||||
|                                 &index_bytes, |  | ||||||
|                             ); |  | ||||||
| 
 |  | ||||||
|                             render_resources.set_asset_resource( |  | ||||||
|                                 handle, |  | ||||||
|                                 vertex_buffer, |  | ||||||
|                                 mesh::VERTEX_BUFFER_ASSET_INDEX, |  | ||||||
|                             ); |  | ||||||
|                             render_resources.set_asset_resource( |  | ||||||
|                                 handle, |  | ||||||
|                                 index_buffer, |  | ||||||
|                                 mesh::INDEX_BUFFER_ASSET_INDEX, |  | ||||||
|                             ); |  | ||||||
|                             (vertex_buffer, Some(index_buffer)) |  | ||||||
|                         }; |  | ||||||
| 
 |  | ||||||
|                         batch.render_resource_assignments.set_vertex_buffer( |  | ||||||
|                             "Vertex", |  | ||||||
|                             vertex_buffer, |  | ||||||
|                             index_buffer, |  | ||||||
|                         ); |                         ); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|  | 
 | ||||||
|  |                 // TODO: remove this once batches are pipeline specific and deprecate assigned_meshes draw target
 | ||||||
|  |                 for (handle, mut renderable) in query.iter_mut(world) { | ||||||
|  |                     setup_mesh_resource( | ||||||
|  |                         render_resources, | ||||||
|  |                         &mut renderable.render_resource_assignments, | ||||||
|  |                         &vertex_buffer_descriptor, | ||||||
|  |                         *handle, | ||||||
|  |                         &meshes, | ||||||
|  |                     ); | ||||||
|  |                 } | ||||||
|             }, |             }, | ||||||
|         ) |         ) | ||||||
| } | } | ||||||
|  | |||||||
| @ -31,6 +31,8 @@ where | |||||||
|                 if let Some(shader_defs) = uniforms.get_shader_defs() { |                 if let Some(shader_defs) = uniforms.get_shader_defs() { | ||||||
|                     renderable |                     renderable | ||||||
|                         .render_resource_assignments |                         .render_resource_assignments | ||||||
|  |                         .pipeline_specialization | ||||||
|  |                         .shader_specialization | ||||||
|                         .shader_defs |                         .shader_defs | ||||||
|                         .extend(shader_defs) |                         .extend(shader_defs) | ||||||
|                 } |                 } | ||||||
| @ -58,6 +60,8 @@ where | |||||||
|             if let Some(shader_defs) = uniforms.get_shader_defs() { |             if let Some(shader_defs) = uniforms.get_shader_defs() { | ||||||
|                 renderable |                 renderable | ||||||
|                     .render_resource_assignments |                     .render_resource_assignments | ||||||
|  |                     .pipeline_specialization | ||||||
|  |                     .shader_specialization | ||||||
|                     .shader_defs |                     .shader_defs | ||||||
|                     .extend(shader_defs) |                     .extend(shader_defs) | ||||||
|             } |             } | ||||||
|  | |||||||
| @ -10,7 +10,6 @@ fn main() { | |||||||
| 
 | 
 | ||||||
| /// set up a simple scene
 | /// set up a simple scene
 | ||||||
| fn setup(world: &mut World, resources: &mut Resources) { | fn setup(world: &mut World, resources: &mut Resources) { | ||||||
|     env_logger::init(); |  | ||||||
|     // create a cube and a plane mesh
 |     // create a cube and a plane mesh
 | ||||||
|     let mut mesh_storage = resources.get_mut::<AssetStorage<Mesh>>().unwrap(); |     let mut mesh_storage = resources.get_mut::<AssetStorage<Mesh>>().unwrap(); | ||||||
|     let cube_handle = mesh_storage.add(Mesh::from(shape::Cube)); |     let cube_handle = mesh_storage.add(Mesh::from(shape::Cube)); | ||||||
| @ -45,13 +44,6 @@ fn setup(world: &mut World, resources: &mut Resources) { | |||||||
|             translation: Translation::new(0.0, 0.0, 1.0), |             translation: Translation::new(0.0, 0.0, 1.0), | ||||||
|             ..Default::default() |             ..Default::default() | ||||||
|         }) |         }) | ||||||
|         // cube
 |  | ||||||
|         .add_entity(MeshEntity { |  | ||||||
|             mesh: cube_handle, |  | ||||||
|             material: cube_material_handle, |  | ||||||
|             translation: Translation::new(2.0, 0.0, 1.0), |  | ||||||
|             ..Default::default() |  | ||||||
|         }) |  | ||||||
|         // light
 |         // light
 | ||||||
|         .add_entity(LightEntity { |         .add_entity(LightEntity { | ||||||
|             translation: Translation::new(4.0, -4.0, 5.0), |             translation: Translation::new(4.0, -4.0, 5.0), | ||||||
|  | |||||||
| @ -1,13 +1,9 @@ | |||||||
| use bevy::{prelude::*, render::shader}; | use bevy::prelude::*; | ||||||
| 
 | 
 | ||||||
| fn main() { | fn main() { | ||||||
|     App::build() |     App::build() | ||||||
|         .add_default_plugins() |         .add_default_plugins() | ||||||
|         .add_startup_system(setup) |         .add_startup_system(setup) | ||||||
|         .add_system_to_stage( |  | ||||||
|             stage::POST_UPDATE, |  | ||||||
|             shader::asset_handle_batcher_system::<MyMaterial>(), |  | ||||||
|         ) |  | ||||||
|         .run(); |         .run(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -32,8 +28,7 @@ fn add_shader_to_render_graph(resources: &mut Resources) { | |||||||
|                     ShaderStage::Vertex, |                     ShaderStage::Vertex, | ||||||
|                     r#" |                     r#" | ||||||
|                     #version 450 |                     #version 450 | ||||||
|                     layout(location = 0) in vec4 Vertex_Position; |                     layout(location = 0) in vec3 Vertex_Position; | ||||||
|                     layout(location = 0) out vec4 v_Position; |  | ||||||
|                     layout(set = 0, binding = 0) uniform Camera { |                     layout(set = 0, binding = 0) uniform Camera { | ||||||
|                         mat4 ViewProj; |                         mat4 ViewProj; | ||||||
|                     }; |                     }; | ||||||
| @ -41,8 +36,7 @@ fn add_shader_to_render_graph(resources: &mut Resources) { | |||||||
|                         mat4 Model; |                         mat4 Model; | ||||||
|                     }; |                     }; | ||||||
|                     void main() { |                     void main() { | ||||||
|                         v_Position = Model * Vertex_Position; |                         gl_Position = ViewProj * Model * vec4(Vertex_Position, 1.0); | ||||||
|                         gl_Position = ViewProj * v_Position; |  | ||||||
|                     } |                     } | ||||||
|                 "#,
 |                 "#,
 | ||||||
|                 )) |                 )) | ||||||
| @ -50,7 +44,6 @@ fn add_shader_to_render_graph(resources: &mut Resources) { | |||||||
|                     ShaderStage::Fragment, |                     ShaderStage::Fragment, | ||||||
|                     r#" |                     r#" | ||||||
|                     #version 450 |                     #version 450 | ||||||
|                     layout(location = 0) in vec4 v_Position; |  | ||||||
|                     layout(location = 0) out vec4 o_Target; |                     layout(location = 0) out vec4 o_Target; | ||||||
|                     layout(set = 1, binding = 1) uniform MyMaterial_color { |                     layout(set = 1, binding = 1) uniform MyMaterial_color { | ||||||
|                         vec4 color; |                         vec4 color; | ||||||
| @ -73,13 +66,8 @@ fn setup(world: &mut World, resources: &mut Resources) { | |||||||
|     let material = material_storage.add(MyMaterial { |     let material = material_storage.add(MyMaterial { | ||||||
|         color: Color::rgb(0.0, 0.8, 0.0), |         color: Color::rgb(0.0, 0.8, 0.0), | ||||||
|     }); |     }); | ||||||
| 
 |  | ||||||
|     resources.insert(material_storage); |     resources.insert(material_storage); | ||||||
| 
 | 
 | ||||||
|     // batch materials to improve performance
 |  | ||||||
|     let mut asset_batchers = resources.get_mut::<AssetBatchers>().unwrap(); |  | ||||||
|     asset_batchers.batch_types2::<Mesh, MyMaterial>(); |  | ||||||
| 
 |  | ||||||
|     // get a handle to our newly created shader pipeline
 |     // get a handle to our newly created shader pipeline
 | ||||||
|     let mut pipeline_storage = resources |     let mut pipeline_storage = resources | ||||||
|         .get_mut::<AssetStorage<PipelineDescriptor>>() |         .get_mut::<AssetStorage<PipelineDescriptor>>() | ||||||
|  | |||||||
| @ -4,10 +4,6 @@ fn main() { | |||||||
|     App::build() |     App::build() | ||||||
|         .add_default_plugins() |         .add_default_plugins() | ||||||
|         .add_startup_system(setup) |         .add_startup_system(setup) | ||||||
|         .add_system_to_stage( |  | ||||||
|             stage::POST_UPDATE, |  | ||||||
|             shader::asset_handle_batcher_system::<MyMaterial>(), |  | ||||||
|         ) |  | ||||||
|         .add_system_to_stage( |         .add_system_to_stage( | ||||||
|             stage::POST_UPDATE, |             stage::POST_UPDATE, | ||||||
|             shader::asset_handle_shader_def_system::<MyMaterial>(), |             shader::asset_handle_shader_def_system::<MyMaterial>(), | ||||||
| @ -38,8 +34,7 @@ fn add_shader_to_render_graph(resources: &mut Resources) { | |||||||
|                     ShaderStage::Vertex, |                     ShaderStage::Vertex, | ||||||
|                     r#" |                     r#" | ||||||
|                     #version 450 |                     #version 450 | ||||||
|                     layout(location = 0) in vec4 Vertex_Position; |                     layout(location = 0) in vec3 Vertex_Position; | ||||||
|                     layout(location = 0) out vec4 v_Position; |  | ||||||
|                     layout(set = 0, binding = 0) uniform Camera { |                     layout(set = 0, binding = 0) uniform Camera { | ||||||
|                         mat4 ViewProj; |                         mat4 ViewProj; | ||||||
|                     }; |                     }; | ||||||
| @ -47,8 +42,7 @@ fn add_shader_to_render_graph(resources: &mut Resources) { | |||||||
|                         mat4 Model; |                         mat4 Model; | ||||||
|                     }; |                     }; | ||||||
|                     void main() { |                     void main() { | ||||||
|                         v_Position = Model * Vertex_Position; |                         gl_Position = ViewProj * Model * vec4(Vertex_Position, 1.0); | ||||||
|                         gl_Position = ViewProj * v_Position; |  | ||||||
|                     } |                     } | ||||||
|                 "#,
 |                 "#,
 | ||||||
|                 )) |                 )) | ||||||
| @ -56,7 +50,6 @@ fn add_shader_to_render_graph(resources: &mut Resources) { | |||||||
|                     ShaderStage::Fragment, |                     ShaderStage::Fragment, | ||||||
|                     r#" |                     r#" | ||||||
|                     #version 450 |                     #version 450 | ||||||
|                     layout(location = 0) in vec4 v_Position; |  | ||||||
|                     layout(location = 0) out vec4 o_Target; |                     layout(location = 0) out vec4 o_Target; | ||||||
|                     layout(set = 1, binding = 1) uniform MyMaterial_color { |                     layout(set = 1, binding = 1) uniform MyMaterial_color { | ||||||
|                         vec4 color; |                         vec4 color; | ||||||
| @ -92,10 +85,6 @@ fn setup(world: &mut World, resources: &mut Resources) { | |||||||
| 
 | 
 | ||||||
|     resources.insert(material_storage); |     resources.insert(material_storage); | ||||||
| 
 | 
 | ||||||
|     // batch materials to improve performance
 |  | ||||||
|     let mut asset_batchers = resources.get_mut::<AssetBatchers>().unwrap(); |  | ||||||
|     asset_batchers.batch_types2::<Mesh, MyMaterial>(); |  | ||||||
| 
 |  | ||||||
|     // get a handle to our newly created shader pipeline
 |     // get a handle to our newly created shader pipeline
 | ||||||
|     let mut pipeline_storage = resources |     let mut pipeline_storage = resources | ||||||
|         .get_mut::<AssetStorage<PipelineDescriptor>>() |         .get_mut::<AssetStorage<PipelineDescriptor>>() | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Carter Anderson
						Carter Anderson