RwLock WgpuResources works now!
This commit is contained in:
		
							parent
							
								
									b53f198b99
								
							
						
					
					
						commit
						318b7dee1a
					
				
							
								
								
									
										8
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
								
							| @ -4,6 +4,7 @@ | ||||
|     // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 | ||||
|     "version": "0.2.0", | ||||
|     "configurations": [ | ||||
| 
 | ||||
|         { | ||||
|             "type": "lldb", | ||||
|             "request": "launch", | ||||
| @ -30,11 +31,11 @@ | ||||
|             "cargo": { | ||||
|                 "args": [ | ||||
|                     "build", | ||||
|                     "--example=simple_new", | ||||
|                     "--example=scene", | ||||
|                     "--package=bevy" | ||||
|                 ], | ||||
|                 "filter": { | ||||
|                     "name": "simple_new", | ||||
|                     "name": "scene", | ||||
|                     "kind": "example" | ||||
|                 } | ||||
|             }, | ||||
| @ -48,9 +49,8 @@ | ||||
|             "cargo": { | ||||
|                 "args": [ | ||||
|                     "run", | ||||
|                     "--example=simple_new", | ||||
|                     "--example=scene", | ||||
|                     "--package=bevy", | ||||
|                     "--release" | ||||
|                 ], | ||||
|                 "filter": { | ||||
|                     "name": "simple_new", | ||||
|  | ||||
| @ -58,15 +58,15 @@ impl DrawTarget for AssignedMeshesDrawTarget { | ||||
|                     { | ||||
|                         let index_buffer_resource = | ||||
|                             render_resources.get_mesh_indices_resource(mesh).unwrap(); | ||||
|                         match render_resources | ||||
|                             .get_resource_info(index_buffer_resource) | ||||
|                             .unwrap() | ||||
|                         { | ||||
|                             ResourceInfo::Buffer(buffer_info) => { | ||||
|                                 current_mesh_index_len = (buffer_info.size / 2) as u32 | ||||
|                             } | ||||
|                             _ => panic!("expected a buffer type"), | ||||
|                         } | ||||
|                         render_resources.get_resource_info( | ||||
|                             index_buffer_resource, | ||||
|                             &mut |resource_info| match resource_info { | ||||
|                                 Some(ResourceInfo::Buffer(buffer_info)) => { | ||||
|                                     current_mesh_index_len = (buffer_info.size / 2) as u32 | ||||
|                                 } | ||||
|                                 _ => panic!("expected a buffer type"), | ||||
|                             }, | ||||
|                         ); | ||||
|                         render_pass.set_index_buffer(index_buffer_resource, 0); | ||||
|                         render_pass.set_vertex_buffer(0, vertex_buffer_resource, 0); | ||||
|                     } | ||||
| @ -75,7 +75,10 @@ impl DrawTarget for AssignedMeshesDrawTarget { | ||||
|                 } | ||||
| 
 | ||||
|                 // TODO: validate bind group properties against shader uniform properties at least once
 | ||||
|                 render_pass.set_render_resources(pipeline_descriptor, &renderable.render_resource_assignments); | ||||
|                 render_pass.set_render_resources( | ||||
|                     pipeline_descriptor, | ||||
|                     &renderable.render_resource_assignments, | ||||
|                 ); | ||||
|                 render_pass.draw_indexed(0..current_mesh_index_len, 0, 0..1); | ||||
|             } | ||||
|         } | ||||
|  | ||||
| @ -37,15 +37,14 @@ impl DrawTarget for MeshesDrawTarget { | ||||
|                 { | ||||
|                     let index_buffer_resource = | ||||
|                         render_resources.get_mesh_indices_resource(*mesh).unwrap(); | ||||
|                     match render_resources | ||||
|                         .get_resource_info(index_buffer_resource) | ||||
|                         .unwrap() | ||||
|                     { | ||||
|                         ResourceInfo::Buffer(buffer_info) => { | ||||
|                             current_mesh_index_len = (buffer_info.size / 2) as u32 | ||||
|                     render_resources.get_resource_info(index_buffer_resource, &mut |resource_info| { | ||||
|                         match resource_info { | ||||
|                             Some(ResourceInfo::Buffer(buffer_info)) => { | ||||
|                                 current_mesh_index_len = (buffer_info.size / 2) as u32 | ||||
|                             } | ||||
|                             _ => panic!("expected a buffer type"), | ||||
|                         } | ||||
|                         _ => panic!("expected a buffer type"), | ||||
|                     } | ||||
|                     }); | ||||
|                     render_pass.set_index_buffer(index_buffer_resource, 0); | ||||
|                     render_pass.set_vertex_buffer(0, vertex_buffer_resource, 0); | ||||
|                 } | ||||
| @ -54,7 +53,8 @@ impl DrawTarget for MeshesDrawTarget { | ||||
|             } | ||||
| 
 | ||||
|             // TODO: validate bind group properties against shader uniform properties at least once
 | ||||
|             render_pass.set_render_resources(pipeline_descriptor, &renderable.render_resource_assignments); | ||||
|             render_pass | ||||
|                 .set_render_resources(pipeline_descriptor, &renderable.render_resource_assignments); | ||||
|             render_pass.draw_indexed(0..current_mesh_index_len, 0, 0..1); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @ -40,18 +40,20 @@ impl DrawTarget for UiDrawTarget { | ||||
|         }; | ||||
| 
 | ||||
|         let index_count = { | ||||
|             let mut index_count = None; | ||||
|             let render_context = render_pass.get_render_context(); | ||||
|             if let Some(ResourceInfo::Buffer(BufferInfo { | ||||
|                 array_info: Some(array_info), | ||||
|                 .. | ||||
|             })) = render_context | ||||
|             render_context | ||||
|                 .resources() | ||||
|                 .get_resource_info(ui_instances_buffer) | ||||
|             { | ||||
|                 Some(array_info.item_capacity) | ||||
|             } else { | ||||
|                 None | ||||
|             } | ||||
|                 .get_resource_info(ui_instances_buffer, &mut |resource_info| { | ||||
|                     if let Some(ResourceInfo::Buffer(BufferInfo { | ||||
|                         array_info: Some(array_info), | ||||
|                         .. | ||||
|                     })) = resource_info | ||||
|                     { | ||||
|                         index_count = Some(array_info.item_capacity); | ||||
|                     } | ||||
|                 }); | ||||
|             index_count | ||||
|         }; | ||||
| 
 | ||||
|         let global_render_resource_assignments = | ||||
|  | ||||
| @ -60,18 +60,22 @@ impl PipelineCompiler { | ||||
|         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, .. })) = | ||||
|                         render_context | ||||
|                             .resources() | ||||
|                             .get_resource_info(render_resource) | ||||
|                     { | ||||
|                         if let BindType::Uniform { | ||||
|                             ref mut dynamic, .. | ||||
|                         } = binding.bind_type | ||||
|                         { | ||||
|                             *dynamic = *is_dynamic | ||||
|                         } | ||||
|                     } | ||||
|                         render_context.resources().get_resource_info( | ||||
|                             render_resource, | ||||
|                             &mut |resource_info| { | ||||
|                                 if let Some(ResourceInfo::Buffer(BufferInfo { | ||||
|                                     is_dynamic, .. | ||||
|                                 })) = resource_info | ||||
|                                 { | ||||
|                                     if let BindType::Uniform { | ||||
|                                         ref mut dynamic, .. | ||||
|                                     } = binding.bind_type | ||||
|                                     { | ||||
|                                         *dynamic = *is_dynamic | ||||
|                                     } | ||||
|                                 } | ||||
|                             } | ||||
|                         ); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
| @ -15,7 +15,7 @@ impl RenderResource { | ||||
| 
 | ||||
| // TODO: consider scoping breaking these mappings up by type: Texture, Sampler, etc
 | ||||
| // the overlap could cause accidents.
 | ||||
| #[derive(Default)] | ||||
| #[derive(Default, Clone)] | ||||
| pub struct AssetResources { | ||||
|     texture_to_resource: HashMap<Handle<Texture>, RenderResource>, | ||||
|     texture_to_sampler_resource: HashMap<Handle<Texture>, RenderResource>, | ||||
|  | ||||
| @ -1,12 +1,12 @@ | ||||
| use crate::render_resource::BufferUsage; | ||||
| 
 | ||||
| #[derive(Default, Debug)] | ||||
| #[derive(Default, Debug, Clone)] | ||||
| pub struct BufferArrayInfo { | ||||
|     pub item_size: usize, | ||||
|     pub item_capacity: usize, | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| #[derive(Debug, Clone)] | ||||
| pub struct BufferInfo { | ||||
|     pub size: usize, | ||||
|     pub buffer_usage: BufferUsage, | ||||
| @ -25,7 +25,7 @@ impl Default for BufferInfo { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| #[derive(Debug, Clone)] | ||||
| pub enum ResourceInfo { | ||||
|     Buffer(BufferInfo), | ||||
|     Texture, | ||||
|  | ||||
| @ -281,23 +281,27 @@ where | ||||
|                         self.uniform_buffer_status[i].as_mut().unwrap(); | ||||
|                     let (target_buffer, target_offset) = if self.use_dynamic_uniforms { | ||||
|                         let buffer = uniform_buffer_status.buffer.unwrap(); | ||||
|                         if let Some(ResourceInfo::Buffer(BufferInfo { | ||||
|                             array_info: Some(ref array_info), | ||||
|                             is_dynamic: true, | ||||
|                             .. | ||||
|                         })) = render_resources.get_resource_info(buffer) | ||||
|                         { | ||||
|                             let index = uniform_buffer_status | ||||
|                                 .get_or_assign_index(render_resource_assignments.id); | ||||
|                             render_resource_assignments.set_indexed( | ||||
|                                 &field_info.uniform_name, | ||||
|                                 buffer, | ||||
|                                 (index * array_info.item_size) as u32, | ||||
|                             ); | ||||
|                             (buffer, index * uniform_buffer_status.aligned_size) | ||||
|                         } else { | ||||
|                             panic!("Expected a dynamic uniform buffer"); | ||||
|                         } | ||||
|                         let mut offset = 0; | ||||
|                         render_resources.get_resource_info(buffer, &mut |resource_info| { | ||||
|                             if let Some(ResourceInfo::Buffer(BufferInfo { | ||||
|                                 array_info: Some(ref array_info), | ||||
|                                 is_dynamic: true, | ||||
|                                 .. | ||||
|                             })) = resource_info | ||||
|                             { | ||||
|                                 let index = uniform_buffer_status | ||||
|                                     .get_or_assign_index(render_resource_assignments.id); | ||||
|                                 render_resource_assignments.set_indexed( | ||||
|                                     &field_info.uniform_name, | ||||
|                                     buffer, | ||||
|                                     (index * array_info.item_size) as u32, | ||||
|                                 ); | ||||
|                                 offset = index * uniform_buffer_status.aligned_size; | ||||
|                             } else { | ||||
|                                 panic!("Expected a dynamic uniform buffer"); | ||||
|                             } | ||||
|                         }); | ||||
|                         (buffer, offset) | ||||
|                     } else { | ||||
|                         let resource = match render_resource_assignments | ||||
|                             .get(field_info.uniform_name) | ||||
| @ -597,24 +601,31 @@ where | ||||
|         align: bool, | ||||
|     ) { | ||||
|         let new_capacity = if let Some(buffer) = buffer_array_status.buffer { | ||||
|             if let Some(ResourceInfo::Buffer(BufferInfo { | ||||
|                 array_info: Some(array_info), | ||||
|                 .. | ||||
|             })) = render_context.resources().get_resource_info(buffer) | ||||
|             { | ||||
|                 if array_info.item_capacity < buffer_array_status.new_item_count { | ||||
|                     // over capacity. lets resize
 | ||||
|                     Some( | ||||
|                         buffer_array_status.new_item_count + buffer_array_status.new_item_count / 2, | ||||
|                     ) | ||||
|                 } else { | ||||
|                     // under capacity. no change needed
 | ||||
|                     None | ||||
|                 } | ||||
|             } else { | ||||
|                 // incorrect resource type. overwrite with new buffer
 | ||||
|                 Some(buffer_array_status.new_item_count) | ||||
|             } | ||||
|             let mut new_capacity = None; | ||||
|             render_context | ||||
|                 .resources() | ||||
|                 .get_resource_info(buffer, &mut |resource_info| { | ||||
|                     new_capacity = if let Some(ResourceInfo::Buffer(BufferInfo { | ||||
|                         array_info: Some(array_info), | ||||
|                         .. | ||||
|                     })) = resource_info | ||||
|                     { | ||||
|                         if array_info.item_capacity < buffer_array_status.new_item_count { | ||||
|                             // over capacity. lets resize
 | ||||
|                             Some( | ||||
|                                 buffer_array_status.new_item_count | ||||
|                                     + buffer_array_status.new_item_count / 2, | ||||
|                             ) | ||||
|                         } else { | ||||
|                             // under capacity. no change needed
 | ||||
|                             None | ||||
|                         } | ||||
|                     } else { | ||||
|                         // incorrect resource type. overwrite with new buffer
 | ||||
|                         Some(buffer_array_status.new_item_count) | ||||
|                     }; | ||||
|                 }); | ||||
|             new_capacity | ||||
|         } else { | ||||
|             // buffer does not exist. create it now.
 | ||||
|             Some(buffer_array_status.new_item_count) | ||||
|  | ||||
| @ -9,7 +9,9 @@ use bevy_window::{Window, WindowId}; | ||||
| use std::any::Any; | ||||
| 
 | ||||
| pub struct GlobalRenderResourceContext { | ||||
|     pub context: Box<dyn RenderResourceContext + Send + Sync + 'static>, | ||||
|     pub context: Box<dyn Any + Send + Sync + 'static>, | ||||
|     // TODO: why doesn't this work?
 | ||||
|     // pub context: Box<dyn RenderResourceContext + Send + Sync + 'static>,
 | ||||
| } | ||||
| 
 | ||||
| impl GlobalRenderResourceContext { | ||||
| @ -53,7 +55,7 @@ pub trait RenderResourceContext: Any { | ||||
|     fn remove_buffer(&mut self, resource: RenderResource); | ||||
|     fn remove_texture(&mut self, resource: RenderResource); | ||||
|     fn remove_sampler(&mut self, resource: RenderResource); | ||||
|     fn get_resource_info(&self, resource: RenderResource) -> Option<&ResourceInfo>; | ||||
|     fn get_resource_info(&self, resource: RenderResource, handle_info: &mut dyn FnMut(Option<&ResourceInfo>)); | ||||
|     fn asset_resources(&self) -> &AssetResources; | ||||
|     fn asset_resources_mut(&mut self) -> &mut AssetResources; | ||||
|     fn get_texture_resource(&self, texture: Handle<Texture>) -> Option<RenderResource>; | ||||
|  | ||||
| @ -30,37 +30,39 @@ pub fn render_resource_sets_system() -> Box<dyn Schedulable> { | ||||
|              _| { | ||||
|                 // PERF: consider doing a par-iter over all renderable components so this can be parallelized
 | ||||
|                 for handle in render_graph.pipeline_descriptors.iter() { | ||||
|                     for compiled_pipeline_handle in | ||||
|                         pipeline_compiler.iter_compiled_pipelines(*handle).unwrap() | ||||
|                     if let Some(compiled_pipelines) = | ||||
|                         pipeline_compiler.iter_compiled_pipelines(*handle) | ||||
|                     { | ||||
|                         if let Some(compiled_pipeline_assignments) = pipeline_assignments | ||||
|                             .assignments | ||||
|                             .get(compiled_pipeline_handle) | ||||
|                         { | ||||
|                             let compiled_pipeline = | ||||
|                                 pipelines.get(compiled_pipeline_handle).unwrap(); | ||||
|                             let pipeline_layout = compiled_pipeline.get_layout().unwrap(); | ||||
| 
 | ||||
|                             for bind_group in pipeline_layout.bind_groups.iter() { | ||||
|                                 global_render_resource_assignments | ||||
|                                     .update_render_resource_set_id(bind_group); | ||||
|                             } | ||||
| 
 | ||||
|                             for assignment_id in compiled_pipeline_assignments.iter() { | ||||
|                                 let entity = entity_render_resource_assignments | ||||
|                                     .get(*assignment_id) | ||||
|                                     .unwrap(); | ||||
|                                 let mut renderable = | ||||
|                                     world.get_component_mut::<Renderable>(*entity).unwrap(); | ||||
|                                 if !renderable.is_visible || renderable.is_instanced { | ||||
|                                     continue; | ||||
|                                 } | ||||
|                         for compiled_pipeline_handle in compiled_pipelines { | ||||
|                             if let Some(compiled_pipeline_assignments) = pipeline_assignments | ||||
|                                 .assignments | ||||
|                                 .get(compiled_pipeline_handle) | ||||
|                             { | ||||
|                                 let compiled_pipeline = | ||||
|                                     pipelines.get(compiled_pipeline_handle).unwrap(); | ||||
|                                 let pipeline_layout = compiled_pipeline.get_layout().unwrap(); | ||||
| 
 | ||||
|                                 for bind_group in pipeline_layout.bind_groups.iter() { | ||||
|                                     renderable | ||||
|                                         .render_resource_assignments | ||||
|                                     global_render_resource_assignments | ||||
|                                         .update_render_resource_set_id(bind_group); | ||||
|                                     // TODO: also setup bind groups here if possible
 | ||||
|                                 } | ||||
| 
 | ||||
|                                 for assignment_id in compiled_pipeline_assignments.iter() { | ||||
|                                     let entity = entity_render_resource_assignments | ||||
|                                         .get(*assignment_id) | ||||
|                                         .unwrap(); | ||||
|                                     let mut renderable = | ||||
|                                         world.get_component_mut::<Renderable>(*entity).unwrap(); | ||||
|                                     if !renderable.is_visible || renderable.is_instanced { | ||||
|                                         continue; | ||||
|                                     } | ||||
| 
 | ||||
|                                     for bind_group in pipeline_layout.bind_groups.iter() { | ||||
|                                         renderable | ||||
|                                             .render_resource_assignments | ||||
|                                             .update_render_resource_set_id(bind_group); | ||||
|                                         // TODO: also setup bind groups here if possible
 | ||||
|                                     } | ||||
|                                 } | ||||
|                             } | ||||
|                         } | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| use super::WgpuRenderResourceContext; | ||||
| use crate::{ | ||||
|     wgpu_type_converter::{OwnedWgpuVertexBufferDescriptor, WgpuInto}, | ||||
|     WgpuRenderPass, | ||||
|     WgpuRenderPass, WgpuResourceRefs, | ||||
| }; | ||||
| use bevy_asset::{AssetStorage, Handle}; | ||||
| use bevy_render::{ | ||||
| @ -127,10 +127,10 @@ impl RenderContext for WgpuRenderContext { | ||||
|         if let Some((render_resource_set_id, _indices)) = | ||||
|             render_resource_assignments.get_render_resource_set_id(bind_group_descriptor.id) | ||||
|         { | ||||
|             if let None = self | ||||
|             if !self | ||||
|                 .render_resources | ||||
|                 .wgpu_resources | ||||
|                 .get_bind_group(bind_group_descriptor.id, *render_resource_set_id) | ||||
|                 .has_bind_group(bind_group_descriptor.id, *render_resource_set_id) | ||||
|             { | ||||
|                 log::trace!( | ||||
|                     "start creating bind group for RenderResourceSet {:?}", | ||||
| @ -155,48 +155,54 @@ impl RenderContext for WgpuRenderContext { | ||||
|                         .iter() | ||||
|                         .map(|binding| { | ||||
|                             if let Some(resource) = render_resource_assignments.get(&binding.name) { | ||||
|                                 let resource_info = | ||||
|                                     self.resources().get_resource_info(resource).unwrap(); | ||||
|                                 log::trace!( | ||||
|                                     "found binding {} ({}) resource: {:?} {:?}", | ||||
|                                     binding.index, | ||||
|                                     binding.name, | ||||
|                                 let mut wgpu_resource = None; | ||||
|                                 self.resources().get_resource_info( | ||||
|                                     resource, | ||||
|                                     resource_info | ||||
|                                     &mut |resource_info| { | ||||
|                                         log::trace!( | ||||
|                                             "found binding {} ({}) resource: {:?} {:?}", | ||||
|                                             binding.index, | ||||
|                                             binding.name, | ||||
|                                             resource, | ||||
|                                             resource_info | ||||
|                                         ); | ||||
|                                         wgpu_resource = match &binding.bind_type { | ||||
|                                             BindType::SampledTexture { .. } => { | ||||
|                                                 if let Some(ResourceInfo::Texture) = resource_info { | ||||
|                                                     let texture = textures.get(&resource).unwrap(); | ||||
|                                                     Some(wgpu::BindingResource::TextureView(texture)) | ||||
|                                                 } else { | ||||
|                                                     panic!("expected a Texture resource"); | ||||
|                                                 } | ||||
|                                             } | ||||
|                                             BindType::Sampler { .. } => { | ||||
|                                                 if let Some(ResourceInfo::Sampler) = resource_info { | ||||
|                                                     let sampler = samplers.get(&resource).unwrap(); | ||||
|                                                     Some(wgpu::BindingResource::Sampler(sampler)) | ||||
|                                                 } else { | ||||
|                                                     panic!("expected a Sampler resource"); | ||||
|                                                 } | ||||
|                                             } | ||||
|                                             BindType::Uniform { .. } => { | ||||
|                                                 if let Some(ResourceInfo::Buffer(buffer_info)) = | ||||
|                                                     resource_info | ||||
|                                                 { | ||||
|                                                     let buffer = buffers.get(&resource).unwrap(); | ||||
|                                                     Some(wgpu::BindingResource::Buffer { | ||||
|                                                         buffer, | ||||
|                                                         range: 0..buffer_info.size as u64, | ||||
|                                                     }) | ||||
|                                                 } else { | ||||
|                                                     panic!("expected a Buffer resource"); | ||||
|                                                 } | ||||
|                                             } | ||||
|                                             _ => panic!("unsupported bind type"), | ||||
|                                         } | ||||
|                                     }, | ||||
|                                 ); | ||||
|                                 wgpu::Binding { | ||||
|                                     binding: binding.index, | ||||
|                                     resource: match &binding.bind_type { | ||||
|                                         BindType::SampledTexture { .. } => { | ||||
|                                             if let ResourceInfo::Texture = resource_info { | ||||
|                                                 let texture = textures.get(&resource).unwrap(); | ||||
|                                                 wgpu::BindingResource::TextureView(texture) | ||||
|                                             } else { | ||||
|                                                 panic!("expected a Texture resource"); | ||||
|                                             } | ||||
|                                         } | ||||
|                                         BindType::Sampler { .. } => { | ||||
|                                             if let ResourceInfo::Sampler = resource_info { | ||||
|                                                 let sampler = samplers.get(&resource).unwrap(); | ||||
|                                                 wgpu::BindingResource::Sampler(sampler) | ||||
|                                             } else { | ||||
|                                                 panic!("expected a Sampler resource"); | ||||
|                                             } | ||||
|                                         } | ||||
|                                         BindType::Uniform { .. } => { | ||||
|                                             if let ResourceInfo::Buffer(buffer_info) = resource_info | ||||
|                                             { | ||||
|                                                 let buffer = buffers.get(&resource).unwrap(); | ||||
|                                                 wgpu::BindingResource::Buffer { | ||||
|                                                     buffer, | ||||
|                                                     range: 0..buffer_info.size as u64, | ||||
|                                                 } | ||||
|                                             } else { | ||||
|                                                 panic!("expected a Buffer resource"); | ||||
|                                             } | ||||
|                                         } | ||||
|                                         _ => panic!("unsupported bind type"), | ||||
|                                     }, | ||||
|                                     resource: wgpu_resource.expect("No resource binding found"), | ||||
|                                 } | ||||
|                             } else { | ||||
|                                 panic!( | ||||
| @ -256,13 +262,13 @@ impl RenderContext for WgpuRenderContext { | ||||
| 
 | ||||
|         let layout = pipeline_descriptor.get_layout().unwrap(); | ||||
|         for bind_group in layout.bind_groups.iter() { | ||||
|             if let None = self | ||||
|             if self | ||||
|                 .render_resources | ||||
|                 .wgpu_resources | ||||
|                 .bind_group_layouts | ||||
|                 .read() | ||||
|                 .unwrap() | ||||
|                 .get(&bind_group.id) | ||||
|                 .get(&bind_group.id).is_none() | ||||
|             { | ||||
|                 let bind_group_layout_binding = bind_group | ||||
|                     .bindings | ||||
| @ -412,18 +418,21 @@ impl RenderContext for WgpuRenderContext { | ||||
|         if !self.command_encoder.is_some() { | ||||
|             self.command_encoder.create(&self.device); | ||||
|         } | ||||
| 
 | ||||
|         let resource_lock = self.render_resources.wgpu_resources.read(); | ||||
|         let refs = resource_lock.refs(); | ||||
|         let mut encoder = self.command_encoder.take().unwrap(); | ||||
|         { | ||||
|             let render_pass = create_render_pass( | ||||
|                 self, | ||||
|                 pass_descriptor, | ||||
|                 render_resource_assignments, | ||||
|                 &refs, | ||||
|                 &mut encoder, | ||||
|             ); | ||||
|             let mut wgpu_render_pass = WgpuRenderPass { | ||||
|                 render_context: self, | ||||
|                 render_pass, | ||||
|                 render_resources: refs, | ||||
|                 bound_bind_groups: HashMap::default(), | ||||
|             }; | ||||
| 
 | ||||
| @ -438,6 +447,7 @@ pub fn create_render_pass<'a, 'b>( | ||||
|     render_context: &'a WgpuRenderContext, | ||||
|     pass_descriptor: &PassDescriptor, | ||||
|     global_render_resource_assignments: &'b RenderResourceAssignments, | ||||
|     refs: &WgpuResourceRefs<'a>, | ||||
|     encoder: &'a mut wgpu::CommandEncoder, | ||||
| ) -> wgpu::RenderPass<'a> { | ||||
|     encoder.begin_render_pass(&wgpu::RenderPassDescriptor { | ||||
| @ -448,6 +458,7 @@ pub fn create_render_pass<'a, 'b>( | ||||
|                 create_wgpu_color_attachment_descriptor( | ||||
|                     render_context, | ||||
|                     global_render_resource_assignments, | ||||
|                     refs, | ||||
|                     c, | ||||
|                 ) | ||||
|             }) | ||||
| @ -456,6 +467,7 @@ pub fn create_render_pass<'a, 'b>( | ||||
|             create_wgpu_depth_stencil_attachment_descriptor( | ||||
|                 render_context, | ||||
|                 global_render_resource_assignments, | ||||
|                 refs, | ||||
|                 d, | ||||
|             ) | ||||
|         }), | ||||
| @ -465,16 +477,13 @@ pub fn create_render_pass<'a, 'b>( | ||||
| fn get_texture_view<'a>( | ||||
|     render_context: &'a WgpuRenderContext, | ||||
|     global_render_resource_assignments: &RenderResourceAssignments, | ||||
|     refs: &WgpuResourceRefs<'a>, | ||||
|     name: &str, | ||||
| ) -> &'a wgpu::TextureView { | ||||
|     match name { | ||||
|         resource_name::texture::SWAP_CHAIN => { | ||||
|             if let Some(primary_swap_chain) = render_context | ||||
|                 .render_resources | ||||
|                 .wgpu_resources | ||||
|             if let Some(primary_swap_chain) = refs | ||||
|                 .swap_chain_outputs | ||||
|                 .read() | ||||
|                 .unwrap() | ||||
|                 .get(render_context.primary_window.as_ref().unwrap()) | ||||
|                 .map(|output| &output.view) | ||||
|             { | ||||
| @ -484,14 +493,7 @@ fn get_texture_view<'a>( | ||||
|             } | ||||
|         } | ||||
|         _ => match global_render_resource_assignments.get(name) { | ||||
|             Some(resource) => render_context | ||||
|                 .render_resources | ||||
|                 .wgpu_resources | ||||
|                 .textures | ||||
|                 .read() | ||||
|                 .unwrap() | ||||
|                 .get(&resource) | ||||
|                 .unwrap(), | ||||
|             Some(resource) => refs.textures.get(&resource).unwrap(), | ||||
|             None => { | ||||
|                 // if let Some(swap_chain_output) = swap_chain_outputs.get(name) {
 | ||||
|                 //     &swap_chain_output.view
 | ||||
| @ -506,11 +508,13 @@ fn get_texture_view<'a>( | ||||
| fn create_wgpu_color_attachment_descriptor<'a>( | ||||
|     render_context: &'a WgpuRenderContext, | ||||
|     global_render_resource_assignments: &RenderResourceAssignments, | ||||
|     refs: &WgpuResourceRefs<'a>, | ||||
|     color_attachment_descriptor: &RenderPassColorAttachmentDescriptor, | ||||
| ) -> wgpu::RenderPassColorAttachmentDescriptor<'a> { | ||||
|     let attachment = get_texture_view( | ||||
|         render_context, | ||||
|         global_render_resource_assignments, | ||||
|         refs, | ||||
|         color_attachment_descriptor.attachment.as_str(), | ||||
|     ); | ||||
| 
 | ||||
| @ -521,6 +525,7 @@ fn create_wgpu_color_attachment_descriptor<'a>( | ||||
|             get_texture_view( | ||||
|                 render_context, | ||||
|                 global_render_resource_assignments, | ||||
|                 refs, | ||||
|                 target.as_str(), | ||||
|             ) | ||||
|         }); | ||||
| @ -537,11 +542,13 @@ fn create_wgpu_color_attachment_descriptor<'a>( | ||||
| fn create_wgpu_depth_stencil_attachment_descriptor<'a>( | ||||
|     render_context: &'a WgpuRenderContext, | ||||
|     global_render_resource_assignments: &RenderResourceAssignments, | ||||
|     refs: &WgpuResourceRefs<'a>, | ||||
|     depth_stencil_attachment_descriptor: &RenderPassDepthStencilAttachmentDescriptor, | ||||
| ) -> wgpu::RenderPassDepthStencilAttachmentDescriptor<'a> { | ||||
|     let attachment = get_texture_view( | ||||
|         render_context, | ||||
|         global_render_resource_assignments, | ||||
|         refs, | ||||
|         depth_stencil_attachment_descriptor.attachment.as_str(), | ||||
|     ); | ||||
| 
 | ||||
|  | ||||
| @ -16,7 +16,7 @@ use bevy_window::{WindowId, Window}; | ||||
| #[derive(Clone)] | ||||
| pub struct WgpuRenderResourceContext { | ||||
|     pub device: Arc<wgpu::Device>, | ||||
|     pub wgpu_resources: Arc<WgpuResources>, | ||||
|     pub wgpu_resources: WgpuResources, | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| @ -24,7 +24,7 @@ impl WgpuRenderResourceContext { | ||||
|     pub fn new(device: Arc<wgpu::Device>) -> Self { | ||||
|         WgpuRenderResourceContext { | ||||
|             device, | ||||
|             wgpu_resources: Arc::new(WgpuResources::default()), | ||||
|             wgpu_resources: WgpuResources::default(), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -95,8 +95,8 @@ impl RenderResourceContext for WgpuRenderResourceContext { | ||||
|             .get_mesh_indices_resource(mesh) | ||||
|     } | ||||
| 
 | ||||
|     fn get_resource_info(&self, resource: RenderResource) -> Option<&ResourceInfo> { | ||||
|         self.wgpu_resources.get_resource_info(resource) | ||||
|     fn get_resource_info(&self, resource: RenderResource, handle_info: &mut dyn FnMut(Option<&ResourceInfo>)) { | ||||
|         self.wgpu_resources.get_resource_info(resource, handle_info); | ||||
|     } | ||||
| 
 | ||||
|     fn asset_resources(&self) -> &AssetResources { | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| use crate::renderer_2::WgpuRenderContext; | ||||
| use crate::{renderer_2::WgpuRenderContext, WgpuResourceRefs}; | ||||
| use bevy_asset::Handle; | ||||
| use bevy_render::{ | ||||
|     pass::RenderPass, | ||||
| @ -13,6 +13,7 @@ use std::{collections::HashMap, ops::Range}; | ||||
| pub struct WgpuRenderPass<'a> { | ||||
|     pub render_pass: wgpu::RenderPass<'a>, | ||||
|     pub render_context: &'a WgpuRenderContext, | ||||
|     pub render_resources: WgpuResourceRefs<'a>, | ||||
|     pub bound_bind_groups: HashMap<u32, RenderResourceSetId>, | ||||
| } | ||||
| 
 | ||||
| @ -22,27 +23,21 @@ impl<'a> RenderPass for WgpuRenderPass<'a> { | ||||
|     } | ||||
| 
 | ||||
|     fn set_vertex_buffer(&mut self, start_slot: u32, resource: RenderResource, offset: u64) { | ||||
|         let buffers = self | ||||
|             .render_context | ||||
|         let buffer = self | ||||
|             .render_resources | ||||
|             .wgpu_resources | ||||
|             .buffers | ||||
|             .read() | ||||
|             .get(&resource) | ||||
|             .unwrap(); | ||||
|         let buffer = buffers.get(&resource).unwrap(); | ||||
|         self.render_pass | ||||
|             .set_vertex_buffer(start_slot, &buffer, offset, 0); | ||||
|     } | ||||
| 
 | ||||
|     fn set_index_buffer(&mut self, resource: RenderResource, offset: u64) { | ||||
|         let buffers = self | ||||
|             .render_context | ||||
|         let buffer = self | ||||
|             .render_resources | ||||
|             .wgpu_resources | ||||
|             .buffers | ||||
|             .read() | ||||
|             .get(&resource) | ||||
|             .unwrap(); | ||||
|         let buffer = buffers.get(&resource).unwrap(); | ||||
|         self.render_pass.set_index_buffer(&buffer, offset, 0); | ||||
|     } | ||||
| 
 | ||||
| @ -80,17 +75,15 @@ impl<'a> RenderPass for WgpuRenderPass<'a> { | ||||
|                         index_buffer | ||||
|                     ); | ||||
|                     self.set_index_buffer(index_buffer, 0); | ||||
|                     match self | ||||
|                         .render_context | ||||
|                         .resources() | ||||
|                         .get_resource_info(index_buffer) | ||||
|                         .unwrap() | ||||
|                     { | ||||
|                         ResourceInfo::Buffer(buffer_info) => { | ||||
|                             indices = Some(0..(buffer_info.size / 2) as u32) | ||||
|                         } | ||||
|                         _ => panic!("expected a buffer type"), | ||||
|                     } | ||||
|                     self.render_context.resources().get_resource_info( | ||||
|                         index_buffer, | ||||
|                         &mut |resource_info| match resource_info { | ||||
|                             Some(ResourceInfo::Buffer(buffer_info)) => { | ||||
|                                 indices = Some(0..(buffer_info.size / 2) as u32) | ||||
|                             } | ||||
|                             _ => panic!("expected a buffer type"), | ||||
|                         }, | ||||
|                     ); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| @ -99,50 +92,53 @@ impl<'a> RenderPass for WgpuRenderPass<'a> { | ||||
|             if let Some((render_resource_set_id, dynamic_uniform_indices)) = | ||||
|                 render_resource_assignments.get_render_resource_set_id(bind_group.id) | ||||
|             { | ||||
|                 if let Some(wgpu_bind_group) = self | ||||
|                     .render_context | ||||
|                 if let Some(bind_group_info) = self | ||||
|                     .render_resources | ||||
|                     .wgpu_resources | ||||
|                     .get_bind_group(bind_group.id, *render_resource_set_id) | ||||
|                     .bind_groups | ||||
|                     .get(&bind_group.id) | ||||
|                 { | ||||
|                     const EMPTY: &'static [u32] = &[]; | ||||
|                     let dynamic_uniform_indices = | ||||
|                         if let Some(dynamic_uniform_indices) = dynamic_uniform_indices { | ||||
|                             dynamic_uniform_indices.as_slice() | ||||
|                         } else { | ||||
|                             EMPTY | ||||
|                         }; | ||||
| 
 | ||||
|                     // don't bind bind groups if they are already set
 | ||||
|                     // TODO: these checks come at a performance cost. make sure its worth it!
 | ||||
|                     if let Some(bound_render_resource_set) = | ||||
|                         self.bound_bind_groups.get(&bind_group.index) | ||||
|                     if let Some(wgpu_bind_group) = | ||||
|                         bind_group_info.bind_groups.get(render_resource_set_id) | ||||
|                     { | ||||
|                         if *bound_render_resource_set == *render_resource_set_id | ||||
|                             && dynamic_uniform_indices.len() == 0 | ||||
|                         const EMPTY: &'static [u32] = &[]; | ||||
|                         let dynamic_uniform_indices = | ||||
|                             if let Some(dynamic_uniform_indices) = dynamic_uniform_indices { | ||||
|                                 dynamic_uniform_indices.as_slice() | ||||
|                             } else { | ||||
|                                 EMPTY | ||||
|                             }; | ||||
| 
 | ||||
|                         // don't bind bind groups if they are already set
 | ||||
|                         // TODO: these checks come at a performance cost. make sure its worth it!
 | ||||
|                         if let Some(bound_render_resource_set) = | ||||
|                             self.bound_bind_groups.get(&bind_group.index) | ||||
|                         { | ||||
|                             continue; | ||||
|                             if *bound_render_resource_set == *render_resource_set_id | ||||
|                                 && dynamic_uniform_indices.len() == 0 | ||||
|                             { | ||||
|                                 continue; | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
| 
 | ||||
|                     if dynamic_uniform_indices.len() == 0 { | ||||
|                         self.bound_bind_groups | ||||
|                             .insert(bind_group.index, *render_resource_set_id); | ||||
|                     } else { | ||||
|                         self.bound_bind_groups.remove(&bind_group.index); | ||||
|                     } | ||||
|                         if dynamic_uniform_indices.len() == 0 { | ||||
|                             self.bound_bind_groups | ||||
|                                 .insert(bind_group.index, *render_resource_set_id); | ||||
|                         } else { | ||||
|                             self.bound_bind_groups.remove(&bind_group.index); | ||||
|                         } | ||||
| 
 | ||||
|                     log::trace!( | ||||
|                         "set bind group {} {:?}: {:?}", | ||||
|                         bind_group.index, | ||||
|                         dynamic_uniform_indices, | ||||
|                         render_resource_set_id | ||||
|                     ); | ||||
|                     self.render_pass.set_bind_group( | ||||
|                         bind_group.index, | ||||
|                         &wgpu_bind_group, | ||||
|                         dynamic_uniform_indices, | ||||
|                     ); | ||||
|                         log::trace!( | ||||
|                             "set bind group {} {:?}: {:?}", | ||||
|                             bind_group.index, | ||||
|                             dynamic_uniform_indices, | ||||
|                             render_resource_set_id | ||||
|                         ); | ||||
|                         self.render_pass.set_bind_group( | ||||
|                             bind_group.index, | ||||
|                             wgpu_bind_group, | ||||
|                             dynamic_uniform_indices, | ||||
|                         ); | ||||
|                     } | ||||
|                 }; | ||||
|             } | ||||
|         } | ||||
| @ -150,14 +146,7 @@ impl<'a> RenderPass for WgpuRenderPass<'a> { | ||||
|         indices | ||||
|     } | ||||
|     fn set_pipeline(&mut self, pipeline_handle: Handle<PipelineDescriptor>) { | ||||
|         let render_pipelines = self | ||||
|             .render_context | ||||
|             .render_resources | ||||
|             .wgpu_resources | ||||
|             .render_pipelines | ||||
|             .read() | ||||
|             .unwrap(); | ||||
|         let pipeline = render_pipelines.get(&pipeline_handle).expect( | ||||
|         let pipeline = self.render_resources.render_pipelines.get(&pipeline_handle).expect( | ||||
|             "Attempted to use a pipeline that does not exist in this RenderPass's RenderContext", | ||||
|         ); | ||||
|         self.render_pass.set_pipeline(pipeline); | ||||
|  | ||||
| @ -11,7 +11,7 @@ use bevy_render::{ | ||||
| }; | ||||
| use bevy_window::{WindowCreated, WindowResized, Windows}; | ||||
| use legion::prelude::*; | ||||
| use std::{any::Any, collections::HashSet, ops::Deref, sync::Arc}; | ||||
| use std::{collections::HashSet, ops::Deref, sync::Arc}; | ||||
| 
 | ||||
| pub struct WgpuRenderer { | ||||
|     pub device: Arc<wgpu::Device>, | ||||
| @ -131,7 +131,6 @@ impl WgpuRenderer { | ||||
|         for resource_provider_chunk in render_graph.resource_providers.chunks_mut(chunk_size) { | ||||
|             // TODO: try to unify this Device usage
 | ||||
|             let device = self.device.clone(); | ||||
|             let resource_device = device.clone(); | ||||
|             // let sender = sender.clone();
 | ||||
|             // s.spawn(|_| {
 | ||||
|             // TODO: replace WgpuResources with Global+Local resources
 | ||||
| @ -241,17 +240,11 @@ impl WgpuRenderer { | ||||
| 
 | ||||
|         let mut encoder = { | ||||
|             let mut global_context = resources.get_mut::<GlobalRenderResourceContext>().unwrap(); | ||||
|             let mut any_context = (&mut global_context.context) as &mut dyn Any; | ||||
|             // let mut any_context = (&mut global_context.context);
 | ||||
|             // println!("{}", std::any::type_name_of_val(any_context));
 | ||||
|             let mut render_resource_context = any_context | ||||
|             let render_resource_context = global_context | ||||
|                 .context | ||||
|                 .downcast_mut::<WgpuRenderResourceContext>() | ||||
|                 .unwrap(); | ||||
|             panic!("ahh"); | ||||
| 
 | ||||
|             // let mut render_resource_context = any_context
 | ||||
|             //     .downcast_mut::<WgpuRenderResourceContext>()
 | ||||
|             //     .unwrap();
 | ||||
|             self.handle_window_created_events(resources, render_resource_context); | ||||
| 
 | ||||
|             self.handle_window_resized_events(resources, render_resource_context); | ||||
| @ -266,11 +259,7 @@ impl WgpuRenderer { | ||||
|                 self.intialized = true; | ||||
|             } | ||||
| 
 | ||||
|             self.update_resource_providers( | ||||
|                 world, | ||||
|                 resources, | ||||
|                 render_resource_context, | ||||
|             ); | ||||
|             self.update_resource_providers(world, resources, render_resource_context); | ||||
| 
 | ||||
|             update_shader_assignments(world, resources, &render_context); | ||||
|             self.create_queued_textures(resources, &mut render_context.render_resources); | ||||
| @ -280,10 +269,8 @@ impl WgpuRenderer { | ||||
|         // TODO: add to POST_UPDATE and remove redundant global_context
 | ||||
|         render_resource_sets_system().run(world, resources); | ||||
|         let mut global_context = resources.get_mut::<GlobalRenderResourceContext>().unwrap(); | ||||
|         let mut any_context = (&mut global_context.context) as &mut dyn Any; | ||||
|         // let mut any_context = (&mut global_context.context);
 | ||||
|         // println!("{}", std::any::type_name_of_val(any_context));
 | ||||
|         let mut render_resource_context = any_context | ||||
|         let render_resource_context = global_context | ||||
|             .context | ||||
|             .downcast_mut::<WgpuRenderResourceContext>() | ||||
|             .unwrap(); | ||||
|         let mut render_context = | ||||
|  | ||||
| @ -20,12 +20,56 @@ pub struct WgpuBindGroupInfo { | ||||
|     pub bind_groups: HashMap<RenderResourceSetId, wgpu::BindGroup>, | ||||
| } | ||||
| 
 | ||||
| /// Grabs a read lock on all wgpu resources. When paired with WgpuResourceRefs, this allows 
 | ||||
| /// us to pass in wgpu resources to wgpu::RenderPass<'a> with the appropriate lifetime. This is accomplished by
 | ||||
| /// grabbing a WgpuResourcesReadLock _before_ creating a wgpu::RenderPass, getting a WgpuResourcesRefs, and storing that
 | ||||
| /// in the pass. 
 | ||||
| /// 
 | ||||
| /// This is only a problem because RwLockReadGuard.read() erases the guard's lifetime and creates a new anonymous lifetime. If
 | ||||
| /// you call RwLockReadGuard.read() during a pass, the reference will have an anonymous lifetime that lives for less than the
 | ||||
| /// pass. 
 | ||||
| /// 
 | ||||
| /// The biggest implication of this design (other than the additional boilerplate here) is that beginning a render pass
 | ||||
| /// blocks writes to these resources. This means that if the pass attempts to write any resource, a deadlock will occur. It also means
 | ||||
| /// that other threads attempting to write resources will need to wait for pass encoding to finish. Almost all writes should occur before
 | ||||
| /// passes start, so this hopefully won't be a problem.
 | ||||
| /// 
 | ||||
| /// It is worth comparing the performance of this to transactional / copy-based approach. This design lock based design guarantees
 | ||||
| /// consistency, doesn't perform redundant allocations, and only blocks when a write is occurring. A copy based approach would 
 | ||||
| /// never block, but would require more allocations / state-synchronization, which I expect will be more expensive.
 | ||||
| /// 
 | ||||
| /// Single threaded implementations don't need to worry about these lifetimes constraints at all. RenderPasses can use a RenderContext's
 | ||||
| /// WgpuResources directly. RenderContext already has a lifetime greater than the RenderPass.
 | ||||
| pub struct WgpuResourcesReadLock<'a> { | ||||
|     pub buffers: RwLockReadGuard<'a, HashMap<RenderResource, wgpu::Buffer>>, | ||||
|     pub textures: RwLockReadGuard<'a, HashMap<RenderResource, wgpu::TextureView>>, | ||||
|     pub swap_chain_outputs: RwLockReadGuard<'a, HashMap<WindowId, wgpu::SwapChainOutput>>, | ||||
|     pub render_pipelines: RwLockReadGuard<'a, HashMap<Handle<PipelineDescriptor>, wgpu::RenderPipeline>>, | ||||
|     pub bind_groups: RwLockReadGuard<'a, HashMap<BindGroupDescriptorId, WgpuBindGroupInfo>>, | ||||
| } | ||||
| 
 | ||||
| #[derive(Default)] | ||||
| impl<'a> WgpuResourcesReadLock<'a> { | ||||
|     pub fn refs(&'a self) -> WgpuResourceRefs<'a> { | ||||
|         WgpuResourceRefs { | ||||
|             buffers: &self.buffers, | ||||
|             textures: &self.textures, | ||||
|             swap_chain_outputs: &self.swap_chain_outputs, | ||||
|             render_pipelines: &self.render_pipelines, | ||||
|             bind_groups: &self.bind_groups, | ||||
|         } | ||||
|     } 
 | ||||
| } | ||||
| 
 | ||||
| /// Stores read only references to WgpuResource collections. See WgpuResourcesReadLock docs for context on why this exists 
 | ||||
| pub struct WgpuResourceRefs<'a> { | ||||
|     pub buffers: &'a HashMap<RenderResource, wgpu::Buffer>, | ||||
|     pub textures: &'a HashMap<RenderResource, wgpu::TextureView>, | ||||
|     pub swap_chain_outputs: &'a HashMap<WindowId, wgpu::SwapChainOutput>, | ||||
|     pub render_pipelines: &'a HashMap<Handle<PipelineDescriptor>, wgpu::RenderPipeline>, | ||||
|     pub bind_groups: &'a HashMap<BindGroupDescriptorId, WgpuBindGroupInfo>, | ||||
| } | ||||
| 
 | ||||
| #[derive(Default, Clone)] | ||||
| pub struct WgpuResources { | ||||
|     // TODO: remove this from WgpuResources. it doesn't need to be here
 | ||||
|     pub asset_resources: AssetResources, | ||||
| @ -43,10 +87,13 @@ pub struct WgpuResources { | ||||
| } | ||||
| 
 | ||||
| impl WgpuResources { | ||||
|     pub fn read(&self) -> WgpuResourcesReadLock { | ||||
|     pub fn read<'a>(&'a self) -> WgpuResourcesReadLock<'a> { | ||||
|         WgpuResourcesReadLock { | ||||
|             buffers: self.buffers.read().unwrap(), | ||||
|             textures: self.textures.read().unwrap(), | ||||
|             swap_chain_outputs: self.swap_chain_outputs.read().unwrap(), | ||||
|             render_pipelines: self.render_pipelines.read().unwrap(), | ||||
|             bind_groups: self.bind_groups.read().unwrap(), | ||||
|         } | ||||
|     } 
 | ||||
| 
 | ||||
| @ -100,20 +147,20 @@ impl WgpuResources { | ||||
|             .insert(resource, resource_info); | ||||
|     } | ||||
| 
 | ||||
|     pub fn get_bind_group( | ||||
|     pub fn has_bind_group( | ||||
|         &self, | ||||
|         bind_group_descriptor_id: BindGroupDescriptorId, | ||||
|         render_resource_set_id: RenderResourceSetId, | ||||
|     ) -> Option<&wgpu::BindGroup> { | ||||
|     ) -> bool { | ||||
|         if let Some(bind_group_info) = self | ||||
|             .bind_groups | ||||
|             .read() | ||||
|             .unwrap() | ||||
|             .get(&bind_group_descriptor_id) | ||||
|         { | ||||
|             bind_group_info.bind_groups.get(&render_resource_set_id) | ||||
|             bind_group_info.bind_groups.get(&render_resource_set_id).is_some() | ||||
|         } else { | ||||
|             None | ||||
|             false | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -174,8 +221,11 @@ impl WgpuResources { | ||||
|         self.assign_buffer(buffer, buffer_info) | ||||
|     } | ||||
| 
 | ||||
|     pub fn get_resource_info(&self, resource: RenderResource) -> Option<&ResourceInfo> { | ||||
|         self.resource_info.read().unwrap().get(&resource) | ||||
|     // TODO: taking a closure isn't fantastic. is there any way to make this better without exposing the lock in the interface?
 | ||||
|     pub fn get_resource_info(&self, resource: RenderResource, handle_info: &mut dyn FnMut(Option<&ResourceInfo>)) { | ||||
|         let resource_info = self.resource_info.read().unwrap(); | ||||
|         let info = resource_info.get(&resource); | ||||
|         handle_info(info); | ||||
|     } | ||||
| 
 | ||||
|     pub fn remove_buffer(&self, resource: RenderResource) { | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Carter Anderson
						Carter Anderson