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(UiResourceProvider::new()) | ||||
|                 .add_resource_provider(MeshResourceProvider::new()) | ||||
|                 .add_resource_provider(UniformResourceProvider::<StandardMaterial>::new(false)) | ||||
|                 .add_resource_provider(UniformResourceProvider::<LocalToWorld>::new(false)) | ||||
|                 .add_resource_provider(UniformResourceProvider::<StandardMaterial>::new(true)) | ||||
|                 .add_resource_provider(UniformResourceProvider::<LocalToWorld>::new(true)) | ||||
|                 .add_forward_pass() | ||||
|                 .add_forward_pipeline(); | ||||
|             // .add_ui_pipeline();
 | ||||
|  | ||||
| @ -1,13 +1,13 @@ | ||||
| use super::BindingDescriptor; | ||||
| use std::{ | ||||
|     collections::{hash_map::DefaultHasher, BTreeSet}, | ||||
|     collections::hash_map::DefaultHasher, | ||||
|     hash::{Hash, Hasher}, | ||||
| }; | ||||
| 
 | ||||
| #[derive(Clone, Debug)] | ||||
| #[derive(Clone, Debug, PartialEq, Eq)] | ||||
| pub struct BindGroupDescriptor { | ||||
|     pub index: u32, | ||||
|     pub bindings: BTreeSet<BindingDescriptor>, | ||||
|     pub bindings: Vec<BindingDescriptor>, | ||||
|     pub id: BindGroupDescriptorId, | ||||
| } | ||||
| 
 | ||||
| @ -18,7 +18,7 @@ impl BindGroupDescriptor { | ||||
|     pub fn new(index: u32, bindings: Vec<BindingDescriptor>) -> Self { | ||||
|         let mut descriptor = BindGroupDescriptor { | ||||
|             index, | ||||
|             bindings: bindings.iter().cloned().collect(), | ||||
|             bindings, | ||||
|             id: BindGroupDescriptorId(0), | ||||
|         }; | ||||
| 
 | ||||
| @ -42,11 +42,3 @@ impl Hash for BindGroupDescriptor { | ||||
|         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::{ | ||||
|     asset::{AssetStorage, Handle}, | ||||
|     prelude::{Renderable, Resources, Shader, World}, | ||||
|     render::{ | ||||
|         render_graph::RenderGraph, | ||||
|         render_resource::{RenderResourceAssignments, RenderResourceAssignmentsId}, | ||||
|         render_resource::{ | ||||
|             BufferInfo, RenderResourceAssignments, RenderResourceAssignmentsId, ResourceInfo, | ||||
|         }, | ||||
|         renderer::Renderer, | ||||
|         shader::ShaderSource, | ||||
|     }, | ||||
| }; | ||||
| @ -31,6 +34,8 @@ impl PipelineCompiler { | ||||
|         shader_storage: &AssetStorage<Shader>, | ||||
|         render_graph: &RenderGraph, | ||||
|         pipeline_descriptor: &mut PipelineDescriptor, | ||||
|         renderer: &dyn Renderer, | ||||
|         render_resource_assignments: &RenderResourceAssignments, | ||||
|     ) { | ||||
|         let vertex_spirv = shader_storage | ||||
|             .get(&pipeline_descriptor.shader_stages.vertex) | ||||
| @ -49,8 +54,25 @@ impl PipelineCompiler { | ||||
|         let mut layout = PipelineLayout::from_shader_layouts(&mut layouts); | ||||
|         layout.sync_vertex_buffer_descriptors_with_render_graph(render_graph); | ||||
| 
 | ||||
|         for mut _bind_group in layout.bind_groups.iter_mut() { | ||||
|             // TODO: set dynamic here
 | ||||
|         // set binding uniforms to dynamic if render resource assignments use dynamic
 | ||||
|         // 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)); | ||||
| @ -93,26 +115,35 @@ impl PipelineCompiler { | ||||
|         &mut self, | ||||
|         render_graph: &RenderGraph, | ||||
|         shader_storage: &mut AssetStorage<Shader>, | ||||
|         renderer: &dyn Renderer, | ||||
|         pipeline_descriptor: &PipelineDescriptor, | ||||
|         shader_defs: &HashSet<String>, | ||||
|         render_resource_assignments: &RenderResourceAssignments, | ||||
|     ) -> PipelineDescriptor { | ||||
|         let mut compiled_pipeline_descriptor = pipeline_descriptor.clone(); | ||||
| 
 | ||||
|         compiled_pipeline_descriptor.shader_stages.vertex = self.compile_shader( | ||||
|             shader_storage, | ||||
|             &pipeline_descriptor.shader_stages.vertex, | ||||
|             &shader_defs, | ||||
|             &render_resource_assignments.shader_defs, | ||||
|         ); | ||||
|         compiled_pipeline_descriptor.shader_stages.fragment = pipeline_descriptor | ||||
|             .shader_stages | ||||
|             .fragment | ||||
|             .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( | ||||
|             shader_storage, | ||||
|             render_graph, | ||||
|             &mut compiled_pipeline_descriptor, | ||||
|             renderer, | ||||
|             render_resource_assignments, | ||||
|         ); | ||||
| 
 | ||||
|         compiled_pipeline_descriptor | ||||
| @ -122,6 +153,7 @@ impl PipelineCompiler { | ||||
|         &mut self, | ||||
|         render_graph: &RenderGraph, | ||||
|         shader_pipeline_assignments: &mut ShaderPipelineAssignments, | ||||
|         renderer: &dyn Renderer, | ||||
|         pipeline_storage: &mut AssetStorage<PipelineDescriptor>, | ||||
|         shader_storage: &mut AssetStorage<Shader>, | ||||
|         pipelines: &[Handle<PipelineDescriptor>], | ||||
| @ -147,8 +179,9 @@ impl PipelineCompiler { | ||||
|                 let compiled_pipeline = self.compile_pipeline( | ||||
|                     render_graph, | ||||
|                     shader_storage, | ||||
|                     renderer, | ||||
|                     pipeline_descriptor, | ||||
|                     &render_resource_assignments.shader_defs, | ||||
|                     render_resource_assignments, | ||||
|                 ); | ||||
|                 let compiled_pipeline_handle = pipeline_storage.add(compiled_pipeline); | ||||
| 
 | ||||
| @ -203,7 +236,7 @@ impl ShaderPipelineAssignments { | ||||
| } | ||||
| 
 | ||||
| // 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.
 | ||||
|     // 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( | ||||
|                 &mut render_graph, | ||||
|                 &mut shader_pipeline_assignments, | ||||
|                 renderer, | ||||
|                 &mut pipeline_descriptor_storage, | ||||
|                 &mut shader_storage, | ||||
|                 &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); | ||||
|                                 } | ||||
|                             } else { | ||||
|                                 bind_group.bindings.insert(shader_binding.clone()); | ||||
|                                 bind_group.bindings.push(shader_binding.clone()); | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
| @ -183,7 +183,9 @@ mod tests { | ||||
|             ..Default::default() | ||||
|         }; | ||||
|         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[1], a1); | ||||
| @ -196,7 +198,9 @@ mod tests { | ||||
|         }; | ||||
|         expected_batch.add_entity(entities[0]); | ||||
|         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
 | ||||
|         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)); | ||||
|         // copy ignored fields
 | ||||
|         batches | ||||
|             .iter() | ||||
|             .zip(expected_batches.iter_mut()) | ||||
|             .for_each(|((_, ref actual), (_, ref mut expected))| copy_ignored_fields(actual, expected)); | ||||
|         assert_eq!( | ||||
|             batches, | ||||
|             expected_batches | ||||
| @ -247,4 +256,8 @@ mod tests { | ||||
|                 .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 { | ||||
|     // TODO: consider using static dispatch for the renderer: Renderer<WgpuBackend>. compare compile times
 | ||||
|     fn get_renderer(&self) -> &dyn Renderer; | ||||
|     fn get_pipeline_descriptor(&self) -> &PipelineDescriptor; | ||||
|     fn set_index_buffer(&mut self, resource: RenderResource, offset: u64); | ||||
|  | ||||
| @ -384,7 +384,7 @@ impl Renderer for WgpuRenderer { | ||||
|         ); | ||||
| 
 | ||||
|         self.update_resource_providers(world, resources); | ||||
|         update_shader_assignments(world, resources); | ||||
|         update_shader_assignments(world, resources, self); | ||||
|         self.create_queued_textures(resources); | ||||
| 
 | ||||
|         let mut encoder = self.encoder.take().unwrap(); | ||||
|  | ||||
| @ -28,7 +28,7 @@ use zerocopy::AsBytes; | ||||
| //     println!("{:?}", structured.types);
 | ||||
| // }
 | ||||
| 
 | ||||
| #[derive(Debug, Clone, Eq, PartialEq)] | ||||
| #[derive(Debug, Clone, PartialEq, Eq)] | ||||
| pub struct ShaderLayout { | ||||
|     pub bind_groups: Vec<BindGroupDescriptor>, | ||||
|     pub vertex_buffer_descriptors: Vec<VertexBufferDescriptor>, | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Carter Anderson
						Carter Anderson