fix dynamic uniforms and unit tests
This commit is contained in:
		
							parent
							
								
									92c421b5e1
								
							
						
					
					
						commit
						78de2fe2a1
					
				| @ -232,8 +232,8 @@ impl AppBuilder { | |||||||
|                 .add_resource_provider(LightResourceProvider::new(10)) |                 .add_resource_provider(LightResourceProvider::new(10)) | ||||||
|                 .add_resource_provider(UiResourceProvider::new()) |                 .add_resource_provider(UiResourceProvider::new()) | ||||||
|                 .add_resource_provider(MeshResourceProvider::new()) |                 .add_resource_provider(MeshResourceProvider::new()) | ||||||
|                 .add_resource_provider(UniformResourceProvider::<StandardMaterial>::new(false)) |                 .add_resource_provider(UniformResourceProvider::<StandardMaterial>::new(true)) | ||||||
|                 .add_resource_provider(UniformResourceProvider::<LocalToWorld>::new(false)) |                 .add_resource_provider(UniformResourceProvider::<LocalToWorld>::new(true)) | ||||||
|                 .add_forward_pass() |                 .add_forward_pass() | ||||||
|                 .add_forward_pipeline(); |                 .add_forward_pipeline(); | ||||||
|             // .add_ui_pipeline();
 |             // .add_ui_pipeline();
 | ||||||
|  | |||||||
| @ -1,13 +1,13 @@ | |||||||
| use super::BindingDescriptor; | use super::BindingDescriptor; | ||||||
| use std::{ | use std::{ | ||||||
|     collections::{hash_map::DefaultHasher, BTreeSet}, |     collections::hash_map::DefaultHasher, | ||||||
|     hash::{Hash, Hasher}, |     hash::{Hash, Hasher}, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #[derive(Clone, Debug)] | #[derive(Clone, Debug, PartialEq, Eq)] | ||||||
| pub struct BindGroupDescriptor { | pub struct BindGroupDescriptor { | ||||||
|     pub index: u32, |     pub index: u32, | ||||||
|     pub bindings: BTreeSet<BindingDescriptor>, |     pub bindings: Vec<BindingDescriptor>, | ||||||
|     pub id: BindGroupDescriptorId, |     pub id: BindGroupDescriptorId, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -18,7 +18,7 @@ impl BindGroupDescriptor { | |||||||
|     pub fn new(index: u32, bindings: Vec<BindingDescriptor>) -> Self { |     pub fn new(index: u32, bindings: Vec<BindingDescriptor>) -> Self { | ||||||
|         let mut descriptor = BindGroupDescriptor { |         let mut descriptor = BindGroupDescriptor { | ||||||
|             index, |             index, | ||||||
|             bindings: bindings.iter().cloned().collect(), |             bindings, | ||||||
|             id: BindGroupDescriptorId(0), |             id: BindGroupDescriptorId(0), | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
| @ -42,11 +42,3 @@ impl Hash for BindGroupDescriptor { | |||||||
|         self.bindings.hash(state); |         self.bindings.hash(state); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 |  | ||||||
| impl PartialEq for BindGroupDescriptor { |  | ||||||
|     fn eq(&self, other: &BindGroupDescriptor) -> bool { |  | ||||||
|         self.index == other.index && self.bindings == other.bindings |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl Eq for BindGroupDescriptor {} |  | ||||||
|  | |||||||
| @ -1,10 +1,13 @@ | |||||||
| use super::{PipelineDescriptor, PipelineLayout, PipelineLayoutType}; | use super::{BindType, PipelineDescriptor, PipelineLayout, PipelineLayoutType}; | ||||||
| use crate::{ | use crate::{ | ||||||
|     asset::{AssetStorage, Handle}, |     asset::{AssetStorage, Handle}, | ||||||
|     prelude::{Renderable, Resources, Shader, World}, |     prelude::{Renderable, Resources, Shader, World}, | ||||||
|     render::{ |     render::{ | ||||||
|         render_graph::RenderGraph, |         render_graph::RenderGraph, | ||||||
|         render_resource::{RenderResourceAssignments, RenderResourceAssignmentsId}, |         render_resource::{ | ||||||
|  |             BufferInfo, RenderResourceAssignments, RenderResourceAssignmentsId, ResourceInfo, | ||||||
|  |         }, | ||||||
|  |         renderer::Renderer, | ||||||
|         shader::ShaderSource, |         shader::ShaderSource, | ||||||
|     }, |     }, | ||||||
| }; | }; | ||||||
| @ -31,6 +34,8 @@ impl PipelineCompiler { | |||||||
|         shader_storage: &AssetStorage<Shader>, |         shader_storage: &AssetStorage<Shader>, | ||||||
|         render_graph: &RenderGraph, |         render_graph: &RenderGraph, | ||||||
|         pipeline_descriptor: &mut PipelineDescriptor, |         pipeline_descriptor: &mut PipelineDescriptor, | ||||||
|  |         renderer: &dyn Renderer, | ||||||
|  |         render_resource_assignments: &RenderResourceAssignments, | ||||||
|     ) { |     ) { | ||||||
|         let vertex_spirv = shader_storage |         let vertex_spirv = shader_storage | ||||||
|             .get(&pipeline_descriptor.shader_stages.vertex) |             .get(&pipeline_descriptor.shader_stages.vertex) | ||||||
| @ -49,8 +54,25 @@ impl PipelineCompiler { | |||||||
|         let mut layout = PipelineLayout::from_shader_layouts(&mut layouts); |         let mut layout = PipelineLayout::from_shader_layouts(&mut layouts); | ||||||
|         layout.sync_vertex_buffer_descriptors_with_render_graph(render_graph); |         layout.sync_vertex_buffer_descriptors_with_render_graph(render_graph); | ||||||
| 
 | 
 | ||||||
|         for mut _bind_group in layout.bind_groups.iter_mut() { |         // set binding uniforms to dynamic if render resource assignments use dynamic
 | ||||||
|             // TODO: set dynamic here
 |         // TODO: this breaks down if different assignments have different "dynamic" status or if the dynamic status changes.
 | ||||||
|  |         // the fix would be to add "dynamic bindings" to the existing shader_def sets. this would ensure new pipelines are generated
 | ||||||
|  |         // for all permutations of dynamic/non-dynamic 
 | ||||||
|  |         for bind_group in layout.bind_groups.iter_mut() { | ||||||
|  |             for binding in bind_group.bindings.iter_mut() { | ||||||
|  |                 if let Some(render_resource) = render_resource_assignments.get(&binding.name) { | ||||||
|  |                     if let Some(ResourceInfo::Buffer(BufferInfo { is_dynamic, .. })) = | ||||||
|  |                         renderer.get_resource_info(render_resource) | ||||||
|  |                     { | ||||||
|  |                         if let BindType::Uniform { | ||||||
|  |                             ref mut dynamic, .. | ||||||
|  |                         } = binding.bind_type | ||||||
|  |                         { | ||||||
|  |                             *dynamic = *is_dynamic | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         pipeline_descriptor.layout = PipelineLayoutType::Reflected(Some(layout)); |         pipeline_descriptor.layout = PipelineLayoutType::Reflected(Some(layout)); | ||||||
| @ -93,26 +115,35 @@ impl PipelineCompiler { | |||||||
|         &mut self, |         &mut self, | ||||||
|         render_graph: &RenderGraph, |         render_graph: &RenderGraph, | ||||||
|         shader_storage: &mut AssetStorage<Shader>, |         shader_storage: &mut AssetStorage<Shader>, | ||||||
|  |         renderer: &dyn Renderer, | ||||||
|         pipeline_descriptor: &PipelineDescriptor, |         pipeline_descriptor: &PipelineDescriptor, | ||||||
|         shader_defs: &HashSet<String>, |         render_resource_assignments: &RenderResourceAssignments, | ||||||
|     ) -> PipelineDescriptor { |     ) -> PipelineDescriptor { | ||||||
|         let mut compiled_pipeline_descriptor = pipeline_descriptor.clone(); |         let mut compiled_pipeline_descriptor = pipeline_descriptor.clone(); | ||||||
| 
 | 
 | ||||||
|         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, | ||||||
|             &shader_defs, |             &render_resource_assignments.shader_defs, | ||||||
|         ); |         ); | ||||||
|         compiled_pipeline_descriptor.shader_stages.fragment = pipeline_descriptor |         compiled_pipeline_descriptor.shader_stages.fragment = pipeline_descriptor | ||||||
|             .shader_stages |             .shader_stages | ||||||
|             .fragment |             .fragment | ||||||
|             .as_ref() |             .as_ref() | ||||||
|             .map(|fragment| self.compile_shader(shader_storage, fragment, &shader_defs)); |             .map(|fragment| { | ||||||
|  |                 self.compile_shader( | ||||||
|  |                     shader_storage, | ||||||
|  |                     fragment, | ||||||
|  |                     &render_resource_assignments.shader_defs, | ||||||
|  |                 ) | ||||||
|  |             }); | ||||||
| 
 | 
 | ||||||
|         Self::reflect_layout( |         Self::reflect_layout( | ||||||
|             shader_storage, |             shader_storage, | ||||||
|             render_graph, |             render_graph, | ||||||
|             &mut compiled_pipeline_descriptor, |             &mut compiled_pipeline_descriptor, | ||||||
|  |             renderer, | ||||||
|  |             render_resource_assignments, | ||||||
|         ); |         ); | ||||||
| 
 | 
 | ||||||
|         compiled_pipeline_descriptor |         compiled_pipeline_descriptor | ||||||
| @ -122,6 +153,7 @@ impl PipelineCompiler { | |||||||
|         &mut self, |         &mut self, | ||||||
|         render_graph: &RenderGraph, |         render_graph: &RenderGraph, | ||||||
|         shader_pipeline_assignments: &mut ShaderPipelineAssignments, |         shader_pipeline_assignments: &mut ShaderPipelineAssignments, | ||||||
|  |         renderer: &dyn Renderer, | ||||||
|         pipeline_storage: &mut AssetStorage<PipelineDescriptor>, |         pipeline_storage: &mut AssetStorage<PipelineDescriptor>, | ||||||
|         shader_storage: &mut AssetStorage<Shader>, |         shader_storage: &mut AssetStorage<Shader>, | ||||||
|         pipelines: &[Handle<PipelineDescriptor>], |         pipelines: &[Handle<PipelineDescriptor>], | ||||||
| @ -147,8 +179,9 @@ impl PipelineCompiler { | |||||||
|                 let compiled_pipeline = self.compile_pipeline( |                 let compiled_pipeline = self.compile_pipeline( | ||||||
|                     render_graph, |                     render_graph, | ||||||
|                     shader_storage, |                     shader_storage, | ||||||
|  |                     renderer, | ||||||
|                     pipeline_descriptor, |                     pipeline_descriptor, | ||||||
|                     &render_resource_assignments.shader_defs, |                     render_resource_assignments, | ||||||
|                 ); |                 ); | ||||||
|                 let compiled_pipeline_handle = pipeline_storage.add(compiled_pipeline); |                 let compiled_pipeline_handle = pipeline_storage.add(compiled_pipeline); | ||||||
| 
 | 
 | ||||||
| @ -203,7 +236,7 @@ impl ShaderPipelineAssignments { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // TODO: make this a system
 | // TODO: make this a system
 | ||||||
| pub fn update_shader_assignments(world: &mut World, resources: &mut Resources) { | pub fn update_shader_assignments(world: &mut World, resources: &mut Resources, renderer: &dyn Renderer) { | ||||||
|     // PERF: this seems like a lot of work for things that don't change that often.
 |     // PERF: this seems like a lot of work for things that don't change that often.
 | ||||||
|     // lots of string + hashset allocations. sees uniform_resource_provider for more context
 |     // lots of string + hashset allocations. sees uniform_resource_provider for more context
 | ||||||
|     { |     { | ||||||
| @ -229,6 +262,7 @@ pub fn update_shader_assignments(world: &mut World, resources: &mut Resources) { | |||||||
|             pipeline_compiler.update_shader_assignments( |             pipeline_compiler.update_shader_assignments( | ||||||
|                 &mut render_graph, |                 &mut render_graph, | ||||||
|                 &mut shader_pipeline_assignments, |                 &mut shader_pipeline_assignments, | ||||||
|  |                 renderer, | ||||||
|                 &mut pipeline_descriptor_storage, |                 &mut pipeline_descriptor_storage, | ||||||
|                 &mut shader_storage, |                 &mut shader_storage, | ||||||
|                 &renderable.pipelines, |                 &renderable.pipelines, | ||||||
|  | |||||||
| @ -26,7 +26,7 @@ impl PipelineLayout { | |||||||
|                                     panic!("Binding {} in BindGroup {} does not match across all shader types: {:?} {:?}", binding.index, bind_group.index, binding, shader_binding); |                                     panic!("Binding {} in BindGroup {} does not match across all shader types: {:?} {:?}", binding.index, bind_group.index, binding, shader_binding); | ||||||
|                                 } |                                 } | ||||||
|                             } else { |                             } else { | ||||||
|                                 bind_group.bindings.insert(shader_binding.clone()); |                                 bind_group.bindings.push(shader_binding.clone()); | ||||||
|                             } |                             } | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|  | |||||||
| @ -183,7 +183,9 @@ mod tests { | |||||||
|             ..Default::default() |             ..Default::default() | ||||||
|         }; |         }; | ||||||
|         expected_batch.add_entity(entities[0]); |         expected_batch.add_entity(entities[0]); | ||||||
|         assert_eq!(asset_batchers.get_batch2(a1, b1).unwrap(), &expected_batch); |         let actual_batch = asset_batchers.get_batch2(a1, b1).unwrap(); | ||||||
|  |         copy_ignored_fields(actual_batch, &mut expected_batch); | ||||||
|  |         assert_eq!(actual_batch, &expected_batch); | ||||||
|         asset_batchers.set_entity_handle(entities[0], c1); |         asset_batchers.set_entity_handle(entities[0], c1); | ||||||
| 
 | 
 | ||||||
|         asset_batchers.set_entity_handle(entities[1], a1); |         asset_batchers.set_entity_handle(entities[1], a1); | ||||||
| @ -196,7 +198,9 @@ mod tests { | |||||||
|         }; |         }; | ||||||
|         expected_batch.add_entity(entities[0]); |         expected_batch.add_entity(entities[0]); | ||||||
|         expected_batch.add_entity(entities[1]); |         expected_batch.add_entity(entities[1]); | ||||||
|         assert_eq!(asset_batchers.get_batch2(a1, b1).unwrap(), &expected_batch); |         let actual_batch = asset_batchers.get_batch2(a1, b1).unwrap(); | ||||||
|  |         copy_ignored_fields(actual_batch, &mut expected_batch); | ||||||
|  |         assert_eq!(actual_batch, &expected_batch); | ||||||
| 
 | 
 | ||||||
|         // uncreated batches are empty
 |         // uncreated batches are empty
 | ||||||
|         assert_eq!(asset_batchers.get_batch2(a1, c1), None); |         assert_eq!(asset_batchers.get_batch2(a1, c1), None); | ||||||
| @ -239,6 +243,11 @@ mod tests { | |||||||
|             ), |             ), | ||||||
|         ]; |         ]; | ||||||
|         expected_batches.sort_by(|a, b| a.0.cmp(&b.0)); |         expected_batches.sort_by(|a, b| a.0.cmp(&b.0)); | ||||||
|  |         // copy ignored fields
 | ||||||
|  |         batches | ||||||
|  |             .iter() | ||||||
|  |             .zip(expected_batches.iter_mut()) | ||||||
|  |             .for_each(|((_, ref actual), (_, ref mut expected))| copy_ignored_fields(actual, expected)); | ||||||
|         assert_eq!( |         assert_eq!( | ||||||
|             batches, |             batches, | ||||||
|             expected_batches |             expected_batches | ||||||
| @ -247,4 +256,8 @@ mod tests { | |||||||
|                 .collect::<Vec<(&BatchKey2, &Batch)>>() |                 .collect::<Vec<(&BatchKey2, &Batch)>>() | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     fn copy_ignored_fields(source: &Batch, destination: &mut Batch) { | ||||||
|  |         destination.render_resource_assignments.id = source.render_resource_assignments.id; | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -49,7 +49,6 @@ pub trait Renderer { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub trait RenderPass { | pub trait RenderPass { | ||||||
|     // TODO: consider using static dispatch for the renderer: Renderer<WgpuBackend>. compare compile times
 |  | ||||||
|     fn get_renderer(&self) -> &dyn Renderer; |     fn get_renderer(&self) -> &dyn Renderer; | ||||||
|     fn get_pipeline_descriptor(&self) -> &PipelineDescriptor; |     fn get_pipeline_descriptor(&self) -> &PipelineDescriptor; | ||||||
|     fn set_index_buffer(&mut self, resource: RenderResource, offset: u64); |     fn set_index_buffer(&mut self, resource: RenderResource, offset: u64); | ||||||
|  | |||||||
| @ -384,7 +384,7 @@ impl Renderer for WgpuRenderer { | |||||||
|         ); |         ); | ||||||
| 
 | 
 | ||||||
|         self.update_resource_providers(world, resources); |         self.update_resource_providers(world, resources); | ||||||
|         update_shader_assignments(world, resources); |         update_shader_assignments(world, resources, self); | ||||||
|         self.create_queued_textures(resources); |         self.create_queued_textures(resources); | ||||||
| 
 | 
 | ||||||
|         let mut encoder = self.encoder.take().unwrap(); |         let mut encoder = self.encoder.take().unwrap(); | ||||||
|  | |||||||
| @ -28,7 +28,7 @@ use zerocopy::AsBytes; | |||||||
| //     println!("{:?}", structured.types);
 | //     println!("{:?}", structured.types);
 | ||||||
| // }
 | // }
 | ||||||
| 
 | 
 | ||||||
| #[derive(Debug, Clone, Eq, PartialEq)] | #[derive(Debug, Clone, PartialEq, Eq)] | ||||||
| pub struct ShaderLayout { | pub struct ShaderLayout { | ||||||
|     pub bind_groups: Vec<BindGroupDescriptor>, |     pub bind_groups: Vec<BindGroupDescriptor>, | ||||||
|     pub vertex_buffer_descriptors: Vec<VertexBufferDescriptor>, |     pub vertex_buffer_descriptors: Vec<VertexBufferDescriptor>, | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Carter Anderson
						Carter Anderson