fix uniform providers with different field sets
This commit is contained in:
		
							parent
							
								
									5154320f70
								
							
						
					
					
						commit
						ca563ea1b3
					
				| @ -1,4 +1,4 @@ | |||||||
| use bevy::prelude::*; | use bevy::{asset, prelude::*}; | ||||||
| use rand::{rngs::StdRng, Rng, SeedableRng}; | use rand::{rngs::StdRng, Rng, SeedableRng}; | ||||||
| use std::collections::VecDeque; | use std::collections::VecDeque; | ||||||
| 
 | 
 | ||||||
| @ -69,6 +69,11 @@ fn setup(world: &mut World) { | |||||||
|         let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap(); |         let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap(); | ||||||
|         (mesh_storage.add(cube), mesh_storage.add(plane)) |         (mesh_storage.add(cube), mesh_storage.add(plane)) | ||||||
|     }; |     }; | ||||||
|  |     // let texture_handle = {
 | ||||||
|  |     //     let mut texture_storage = world.resources.get_mut::<AssetStorage<Texture>>().unwrap();
 | ||||||
|  |     //     let texture = Texture::load(TextureType::Data(asset::create_texels(256), 256, 256));
 | ||||||
|  |     //     texture_storage.add(texture)
 | ||||||
|  |     // };
 | ||||||
| 
 | 
 | ||||||
|     let mut builder = world |     let mut builder = world | ||||||
|         .build() |         .build() | ||||||
| @ -123,6 +128,7 @@ fn setup(world: &mut World) { | |||||||
|         builder = builder.add_archetype(MeshEntity { |         builder = builder.add_archetype(MeshEntity { | ||||||
|             mesh: cube_handle, |             mesh: cube_handle, | ||||||
|             material: StandardMaterial { |             material: StandardMaterial { | ||||||
|  |                 // albedo: texture_handle.into(),
 | ||||||
|                 albedo: math::vec4( |                 albedo: math::vec4( | ||||||
|                     rng.gen_range(0.0, 1.0), |                     rng.gen_range(0.0, 1.0), | ||||||
|                     rng.gen_range(0.0, 1.0), |                     rng.gen_range(0.0, 1.0), | ||||||
|  | |||||||
| @ -24,9 +24,17 @@ fn setup(world: &mut World) { | |||||||
|             material: StandardMaterial { |             material: StandardMaterial { | ||||||
|                 albedo: texture_handle.into(), |                 albedo: texture_handle.into(), | ||||||
|             }, |             }, | ||||||
|             translation: Translation::new(0.0, 0.0, 1.0), |             translation: Translation::new(0.0, 0.0, 0.0), | ||||||
|             ..Default::default() |             ..Default::default() | ||||||
|         }) |         }) | ||||||
|  |         // .add_archetype(MeshEntity {
 | ||||||
|  |         //     mesh: cube_handle,
 | ||||||
|  |         //     material: StandardMaterial {
 | ||||||
|  |         //         albedo: Vec4::new(1.0, 0.0, 0.0, 1.0).into(),
 | ||||||
|  |         //     },
 | ||||||
|  |         //     translation: Translation::new(2.0, 0.0, 0.0),
 | ||||||
|  |         //     ..Default::default()
 | ||||||
|  |         // })
 | ||||||
|         // light
 |         // light
 | ||||||
|         .add_archetype(LightEntity { |         .add_archetype(LightEntity { | ||||||
|             translation: Translation::new(4.0, -4.0, 5.0), |             translation: Translation::new(4.0, -4.0, 5.0), | ||||||
|  | |||||||
| @ -429,6 +429,7 @@ impl WgpuRenderer { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn create_entity_bind_group(&mut self, bind_group: &BindGroup, entity: Entity) { |     pub fn create_entity_bind_group(&mut self, bind_group: &BindGroup, entity: Entity) { | ||||||
|  |         // TODO: don't make this per-entity. bind groups should be re-used across the same resource when possible
 | ||||||
|         let bind_group_id = bind_group.get_hash().unwrap(); |         let bind_group_id = bind_group.get_hash().unwrap(); | ||||||
|         let bindings = bind_group.bindings.iter().map(|binding| { |         let bindings = bind_group.bindings.iter().map(|binding| { | ||||||
|             if let Some(resource) = self.get_entity_uniform_resource(entity, &binding.name) { |             if let Some(resource) = self.get_entity_uniform_resource(entity, &binding.name) { | ||||||
|  | |||||||
| @ -6,14 +6,15 @@ use crate::{ | |||||||
|     }, |     }, | ||||||
| }; | }; | ||||||
| use legion::prelude::*; | use legion::prelude::*; | ||||||
| use std::{marker::PhantomData, ops::Deref}; | use std::{marker::PhantomData, ops::Deref, collections::{HashSet, HashMap}}; | ||||||
| 
 | 
 | ||||||
| pub struct UniformResourceProvider<T> | pub struct UniformResourceProvider<T> | ||||||
| where | where | ||||||
|     T: AsUniforms + Send + Sync, |     T: AsUniforms + Send + Sync, | ||||||
| { | { | ||||||
|     _marker: PhantomData<T>, |     _marker: PhantomData<T>, | ||||||
|     uniform_buffer_info_resources: Vec<(String, Option<RenderResource>)>, |     // PERF: somehow remove this HashSet
 | ||||||
|  |     uniform_buffer_info_resources: HashMap<String, (Option<RenderResource>, usize, HashSet<Entity>)>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl<T> UniformResourceProvider<T> | impl<T> UniformResourceProvider<T> | ||||||
| @ -22,7 +23,7 @@ where | |||||||
| { | { | ||||||
|     pub fn new() -> Self { |     pub fn new() -> Self { | ||||||
|         UniformResourceProvider { |         UniformResourceProvider { | ||||||
|             uniform_buffer_info_resources: Vec::new(), |             uniform_buffer_info_resources: HashMap::new(), | ||||||
|             _marker: PhantomData, |             _marker: PhantomData, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -43,32 +44,27 @@ where | |||||||
|         // (2) if we create new buffers, the old bind groups will be invalid
 |         // (2) if we create new buffers, the old bind groups will be invalid
 | ||||||
| 
 | 
 | ||||||
|         // reset all uniform buffer info counts
 |         // reset all uniform buffer info counts
 | ||||||
|         for (_name, resource) in self.uniform_buffer_info_resources.iter() { |         for (_name, (resource, _count, entities)) in self.uniform_buffer_info_resources.iter() { | ||||||
|             renderer |             renderer | ||||||
|                 .get_dynamic_uniform_buffer_info_mut(resource.unwrap()) |                 .get_dynamic_uniform_buffer_info_mut(resource.unwrap()) | ||||||
|                 .unwrap() |                 .unwrap() | ||||||
|                 .count = 0; |                 .count = 0; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         let mut counts = Vec::new(); |  | ||||||
|         for (entity, (uniforms, _renderable)) in query.iter_entities(world) { |         for (entity, (uniforms, _renderable)) in query.iter_entities(world) { | ||||||
|             let mut uniform_index = 0; |  | ||||||
|             let field_uniform_names = uniforms.get_field_uniform_names(); |             let field_uniform_names = uniforms.get_field_uniform_names(); | ||||||
|             for uniform_info in UniformInfoIter::new(field_uniform_names, uniforms.deref()) { |             for uniform_info in UniformInfoIter::new(field_uniform_names, uniforms.deref()) { | ||||||
|                 match uniform_info.bind_type { |                 match uniform_info.bind_type { | ||||||
|                     BindType::Uniform { .. } => { |                     BindType::Uniform { .. } => { | ||||||
|                         // only add the first time a uniform info is processed
 |                         // only add the first time a uniform info is processed
 | ||||||
|                         if self.uniform_buffer_info_resources.len() <= uniform_index { |                         if let None = self.uniform_buffer_info_resources.get(uniform_info.name) { | ||||||
|                             self.uniform_buffer_info_resources |                             self.uniform_buffer_info_resources | ||||||
|                                 .push((uniform_info.name.to_string(), None)); |                                 .insert(uniform_info.name.to_string(), (None, 0, HashSet::new())); | ||||||
|                         } |                         } | ||||||
| 
 | 
 | ||||||
|                         if counts.len() <= uniform_index { |                         let (resource, counts, entities) = self.uniform_buffer_info_resources.get_mut(uniform_info.name).unwrap(); | ||||||
|                             counts.push(0); |                         entities.insert(entity); | ||||||
|                         } |                         *counts += 1; | ||||||
| 
 |  | ||||||
|                         counts[uniform_index] += 1; |  | ||||||
|                         uniform_index += 1; |  | ||||||
|                     } |                     } | ||||||
|                     BindType::SampledTexture { .. } => { |                     BindType::SampledTexture { .. } => { | ||||||
|                         let texture_handle = |                         let texture_handle = | ||||||
| @ -115,17 +111,18 @@ where | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // allocate uniform buffers
 |         // allocate uniform buffers
 | ||||||
|         for (i, (name, resource)) in self.uniform_buffer_info_resources.iter_mut().enumerate() { |         for (name, (resource, count, entities)) in self.uniform_buffer_info_resources.iter_mut() { | ||||||
|  |             let count = *count as u64; | ||||||
|             if let Some(resource) = resource { |             if let Some(resource) = resource { | ||||||
|                 let mut info = renderer |                 let mut info = renderer | ||||||
|                     .get_dynamic_uniform_buffer_info_mut(*resource) |                     .get_dynamic_uniform_buffer_info_mut(*resource) | ||||||
|                     .unwrap(); |                     .unwrap(); | ||||||
|                 info.count = counts[i]; |                 info.count = count; | ||||||
|                 continue; |                 continue; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             // allocate enough space for twice as many entities as there are currently;
 |             // allocate enough space for twice as many entities as there are currently;
 | ||||||
|             let capacity = counts[i] * 2; |             let capacity = count * 2; | ||||||
|             let size = wgpu::BIND_BUFFER_ALIGNMENT * capacity; |             let size = wgpu::BIND_BUFFER_ALIGNMENT * capacity; | ||||||
|             let created_resource = renderer.create_buffer( |             let created_resource = renderer.create_buffer( | ||||||
|                 size, |                 size, | ||||||
| @ -133,7 +130,7 @@ where | |||||||
|             ); |             ); | ||||||
| 
 | 
 | ||||||
|             let mut info = DynamicUniformBufferInfo::new(); |             let mut info = DynamicUniformBufferInfo::new(); | ||||||
|             info.count = counts[i]; |             info.count = count; | ||||||
|             info.capacity = capacity; |             info.capacity = capacity; | ||||||
|             renderer.add_dynamic_uniform_buffer_info(created_resource, info); |             renderer.add_dynamic_uniform_buffer_info(created_resource, info); | ||||||
|             *resource = Some(created_resource); |             *resource = Some(created_resource); | ||||||
| @ -141,7 +138,7 @@ where | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // copy entity uniform data to buffers
 |         // copy entity uniform data to buffers
 | ||||||
|         for (name, resource) in self.uniform_buffer_info_resources.iter() { |         for (name, (resource, _count, entities)) in self.uniform_buffer_info_resources.iter() { | ||||||
|             let resource = resource.unwrap(); |             let resource = resource.unwrap(); | ||||||
|             let size = { |             let size = { | ||||||
|                 let info = renderer.get_dynamic_uniform_buffer_info(resource).unwrap(); |                 let info = renderer.get_dynamic_uniform_buffer_info(resource).unwrap(); | ||||||
| @ -153,24 +150,28 @@ where | |||||||
|             let info = renderer |             let info = renderer | ||||||
|                 .get_dynamic_uniform_buffer_info_mut(resource) |                 .get_dynamic_uniform_buffer_info_mut(resource) | ||||||
|                 .unwrap(); |                 .unwrap(); | ||||||
|             for (i, (entity, _)) in query.iter_entities(world).enumerate() { |             for (entity, _) in query.iter_entities(world) { | ||||||
|  |                 if !entities.contains(&entity) { | ||||||
|  |                    continue; 
 | ||||||
|  |                 } | ||||||
|                 // TODO: check if index has changed. if it has, then entity should be updated
 |                 // TODO: check if index has changed. if it has, then entity should be updated
 | ||||||
|                 // TODO: only mem-map entities if their data has changed
 |                 // TODO: only mem-map entities if their data has changed
 | ||||||
|                 // PERF: These hashmap inserts are pretty expensive (10 fps for 10000 entities)
 |                 // PERF: These hashmap inserts are pretty expensive (10 fps for 10000 entities)
 | ||||||
|                 info.offsets.insert(entity, offset as u64); |                 info.offsets.insert(entity, offset as u64); | ||||||
|                 info.indices.insert(i, entity); |  | ||||||
|                 // TODO: try getting ref first
 |                 // TODO: try getting ref first
 | ||||||
|                 offset += alignment; |                 offset += alignment; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             // let mut data = vec![Default::default(); size as usize];
 |  | ||||||
|             let mapped_buffer_resource = renderer.create_buffer_mapped( |             let mapped_buffer_resource = renderer.create_buffer_mapped( | ||||||
|                 size as usize, |                 size as usize, | ||||||
|                 wgpu::BufferUsage::COPY_SRC, |                 wgpu::BufferUsage::COPY_SRC, | ||||||
|                 &mut |mapped| { |                 &mut |mapped| { | ||||||
|                     let alignment = wgpu::BIND_BUFFER_ALIGNMENT as usize; |                     let alignment = wgpu::BIND_BUFFER_ALIGNMENT as usize; | ||||||
|                     let mut offset = 0usize; |                     let mut offset = 0usize; | ||||||
|                     for (uniforms, _renderable) in query.iter(world) { |                     for (entity, (uniforms, _renderable)) in query.iter_entities(world) { | ||||||
|  |                         if !entities.contains(&entity) { | ||||||
|  |                             continue; 
 | ||||||
|  |                         } | ||||||
|                         // TODO: check if index has changed. if it has, then entity should be updated
 |                         // TODO: check if index has changed. if it has, then entity should be updated
 | ||||||
|                         // TODO: only mem-map entities if their data has changed
 |                         // TODO: only mem-map entities if their data has changed
 | ||||||
|                         // TODO: try getting bytes ref first
 |                         // TODO: try getting bytes ref first
 | ||||||
|  | |||||||
| @ -171,7 +171,6 @@ pub struct UniformInfo<'a> { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub struct DynamicUniformBufferInfo { | pub struct DynamicUniformBufferInfo { | ||||||
|     pub indices: HashMap<usize, Entity>, |  | ||||||
|     pub offsets: HashMap<Entity, u64>, |     pub offsets: HashMap<Entity, u64>, | ||||||
|     pub capacity: u64, |     pub capacity: u64, | ||||||
|     pub count: u64, |     pub count: u64, | ||||||
| @ -182,7 +181,6 @@ impl DynamicUniformBufferInfo { | |||||||
|         DynamicUniformBufferInfo { |         DynamicUniformBufferInfo { | ||||||
|             capacity: 0, |             capacity: 0, | ||||||
|             count: 0, |             count: 0, | ||||||
|             indices: HashMap::new(), |  | ||||||
|             offsets: HashMap::new(), |             offsets: HashMap::new(), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Carter Anderson
						Carter Anderson