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 |     // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 | ||||||
|     "version": "0.2.0", |     "version": "0.2.0", | ||||||
|     "configurations": [ |     "configurations": [ | ||||||
|  | 
 | ||||||
|         { |         { | ||||||
|             "type": "lldb", |             "type": "lldb", | ||||||
|             "request": "launch", |             "request": "launch", | ||||||
| @ -30,11 +31,11 @@ | |||||||
|             "cargo": { |             "cargo": { | ||||||
|                 "args": [ |                 "args": [ | ||||||
|                     "build", |                     "build", | ||||||
|                     "--example=simple_new", |                     "--example=scene", | ||||||
|                     "--package=bevy" |                     "--package=bevy" | ||||||
|                 ], |                 ], | ||||||
|                 "filter": { |                 "filter": { | ||||||
|                     "name": "simple_new", |                     "name": "scene", | ||||||
|                     "kind": "example" |                     "kind": "example" | ||||||
|                 } |                 } | ||||||
|             }, |             }, | ||||||
| @ -48,9 +49,8 @@ | |||||||
|             "cargo": { |             "cargo": { | ||||||
|                 "args": [ |                 "args": [ | ||||||
|                     "run", |                     "run", | ||||||
|                     "--example=simple_new", |                     "--example=scene", | ||||||
|                     "--package=bevy", |                     "--package=bevy", | ||||||
|                     "--release" |  | ||||||
|                 ], |                 ], | ||||||
|                 "filter": { |                 "filter": { | ||||||
|                     "name": "simple_new", |                     "name": "simple_new", | ||||||
|  | |||||||
| @ -58,15 +58,15 @@ impl DrawTarget for AssignedMeshesDrawTarget { | |||||||
|                     { |                     { | ||||||
|                         let index_buffer_resource = |                         let index_buffer_resource = | ||||||
|                             render_resources.get_mesh_indices_resource(mesh).unwrap(); |                             render_resources.get_mesh_indices_resource(mesh).unwrap(); | ||||||
|                         match render_resources |                         render_resources.get_resource_info( | ||||||
|                             .get_resource_info(index_buffer_resource) |                             index_buffer_resource, | ||||||
|                             .unwrap() |                             &mut |resource_info| match resource_info { | ||||||
|                         { |                                 Some(ResourceInfo::Buffer(buffer_info)) => { | ||||||
|                             ResourceInfo::Buffer(buffer_info) => { |                                     current_mesh_index_len = (buffer_info.size / 2) as u32 | ||||||
|                                 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_index_buffer(index_buffer_resource, 0); | ||||||
|                         render_pass.set_vertex_buffer(0, vertex_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
 |                 // 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); |                 render_pass.draw_indexed(0..current_mesh_index_len, 0, 0..1); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | |||||||
| @ -37,15 +37,14 @@ impl DrawTarget for MeshesDrawTarget { | |||||||
|                 { |                 { | ||||||
|                     let index_buffer_resource = |                     let index_buffer_resource = | ||||||
|                         render_resources.get_mesh_indices_resource(*mesh).unwrap(); |                         render_resources.get_mesh_indices_resource(*mesh).unwrap(); | ||||||
|                     match render_resources |                     render_resources.get_resource_info(index_buffer_resource, &mut |resource_info| { | ||||||
|                         .get_resource_info(index_buffer_resource) |                         match resource_info { | ||||||
|                         .unwrap() |                             Some(ResourceInfo::Buffer(buffer_info)) => { | ||||||
|                     { |                                 current_mesh_index_len = (buffer_info.size / 2) as u32 | ||||||
|                         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_index_buffer(index_buffer_resource, 0); | ||||||
|                     render_pass.set_vertex_buffer(0, vertex_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
 |             // 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); |             render_pass.draw_indexed(0..current_mesh_index_len, 0, 0..1); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -40,18 +40,20 @@ impl DrawTarget for UiDrawTarget { | |||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         let index_count = { |         let index_count = { | ||||||
|  |             let mut index_count = None; | ||||||
|             let render_context = render_pass.get_render_context(); |             let render_context = render_pass.get_render_context(); | ||||||
|             if let Some(ResourceInfo::Buffer(BufferInfo { |             render_context | ||||||
|                 array_info: Some(array_info), |  | ||||||
|                 .. |  | ||||||
|             })) = render_context |  | ||||||
|                 .resources() |                 .resources() | ||||||
|                 .get_resource_info(ui_instances_buffer) |                 .get_resource_info(ui_instances_buffer, &mut |resource_info| { | ||||||
|             { |                     if let Some(ResourceInfo::Buffer(BufferInfo { | ||||||
|                 Some(array_info.item_capacity) |                         array_info: Some(array_info), | ||||||
|             } else { |                         .. | ||||||
|                 None |                     })) = resource_info | ||||||
|             } |                     { | ||||||
|  |                         index_count = Some(array_info.item_capacity); | ||||||
|  |                     } | ||||||
|  |                 }); | ||||||
|  |             index_count | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         let global_render_resource_assignments = |         let global_render_resource_assignments = | ||||||
|  | |||||||
| @ -60,18 +60,22 @@ impl PipelineCompiler { | |||||||
|         for bind_group in layout.bind_groups.iter_mut() { |         for bind_group in layout.bind_groups.iter_mut() { | ||||||
|             for binding in bind_group.bindings.iter_mut() { |             for binding in bind_group.bindings.iter_mut() { | ||||||
|                 if let Some(render_resource) = render_resource_assignments.get(&binding.name) { |                 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_context |                             render_resource, | ||||||
|                             .resources() |                             &mut |resource_info| { | ||||||
|                             .get_resource_info(render_resource) |                                 if let Some(ResourceInfo::Buffer(BufferInfo { | ||||||
|                     { |                                     is_dynamic, .. | ||||||
|                         if let BindType::Uniform { |                                 })) = resource_info | ||||||
|                             ref mut dynamic, .. |                                 { | ||||||
|                         } = binding.bind_type |                                     if let BindType::Uniform { | ||||||
|                         { |                                         ref mut dynamic, .. | ||||||
|                             *dynamic = *is_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
 | // TODO: consider scoping breaking these mappings up by type: Texture, Sampler, etc
 | ||||||
| // the overlap could cause accidents.
 | // the overlap could cause accidents.
 | ||||||
| #[derive(Default)] | #[derive(Default, Clone)] | ||||||
| pub struct AssetResources { | pub struct AssetResources { | ||||||
|     texture_to_resource: HashMap<Handle<Texture>, RenderResource>, |     texture_to_resource: HashMap<Handle<Texture>, RenderResource>, | ||||||
|     texture_to_sampler_resource: HashMap<Handle<Texture>, RenderResource>, |     texture_to_sampler_resource: HashMap<Handle<Texture>, RenderResource>, | ||||||
|  | |||||||
| @ -1,12 +1,12 @@ | |||||||
| use crate::render_resource::BufferUsage; | use crate::render_resource::BufferUsage; | ||||||
| 
 | 
 | ||||||
| #[derive(Default, Debug)] | #[derive(Default, Debug, Clone)] | ||||||
| pub struct BufferArrayInfo { | pub struct BufferArrayInfo { | ||||||
|     pub item_size: usize, |     pub item_size: usize, | ||||||
|     pub item_capacity: usize, |     pub item_capacity: usize, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug, Clone)] | ||||||
| pub struct BufferInfo { | pub struct BufferInfo { | ||||||
|     pub size: usize, |     pub size: usize, | ||||||
|     pub buffer_usage: BufferUsage, |     pub buffer_usage: BufferUsage, | ||||||
| @ -25,7 +25,7 @@ impl Default for BufferInfo { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug, Clone)] | ||||||
| pub enum ResourceInfo { | pub enum ResourceInfo { | ||||||
|     Buffer(BufferInfo), |     Buffer(BufferInfo), | ||||||
|     Texture, |     Texture, | ||||||
|  | |||||||
| @ -281,23 +281,27 @@ where | |||||||
|                         self.uniform_buffer_status[i].as_mut().unwrap(); |                         self.uniform_buffer_status[i].as_mut().unwrap(); | ||||||
|                     let (target_buffer, target_offset) = if self.use_dynamic_uniforms { |                     let (target_buffer, target_offset) = if self.use_dynamic_uniforms { | ||||||
|                         let buffer = uniform_buffer_status.buffer.unwrap(); |                         let buffer = uniform_buffer_status.buffer.unwrap(); | ||||||
|                         if let Some(ResourceInfo::Buffer(BufferInfo { |                         let mut offset = 0; | ||||||
|                             array_info: Some(ref array_info), |                         render_resources.get_resource_info(buffer, &mut |resource_info| { | ||||||
|                             is_dynamic: true, |                             if let Some(ResourceInfo::Buffer(BufferInfo { | ||||||
|                             .. |                                 array_info: Some(ref array_info), | ||||||
|                         })) = render_resources.get_resource_info(buffer) |                                 is_dynamic: true, | ||||||
|                         { |                                 .. | ||||||
|                             let index = uniform_buffer_status |                             })) = resource_info | ||||||
|                                 .get_or_assign_index(render_resource_assignments.id); |                             { | ||||||
|                             render_resource_assignments.set_indexed( |                                 let index = uniform_buffer_status | ||||||
|                                 &field_info.uniform_name, |                                     .get_or_assign_index(render_resource_assignments.id); | ||||||
|                                 buffer, |                                 render_resource_assignments.set_indexed( | ||||||
|                                 (index * array_info.item_size) as u32, |                                     &field_info.uniform_name, | ||||||
|                             ); |                                     buffer, | ||||||
|                             (buffer, index * uniform_buffer_status.aligned_size) |                                     (index * array_info.item_size) as u32, | ||||||
|                         } else { |                                 ); | ||||||
|                             panic!("Expected a dynamic uniform buffer"); |                                 offset = index * uniform_buffer_status.aligned_size; | ||||||
|                         } |                             } else { | ||||||
|  |                                 panic!("Expected a dynamic uniform buffer"); | ||||||
|  |                             } | ||||||
|  |                         }); | ||||||
|  |                         (buffer, offset) | ||||||
|                     } else { |                     } else { | ||||||
|                         let resource = match render_resource_assignments |                         let resource = match render_resource_assignments | ||||||
|                             .get(field_info.uniform_name) |                             .get(field_info.uniform_name) | ||||||
| @ -597,24 +601,31 @@ where | |||||||
|         align: bool, |         align: bool, | ||||||
|     ) { |     ) { | ||||||
|         let new_capacity = if let Some(buffer) = buffer_array_status.buffer { |         let new_capacity = if let Some(buffer) = buffer_array_status.buffer { | ||||||
|             if let Some(ResourceInfo::Buffer(BufferInfo { |             let mut new_capacity = None; | ||||||
|                 array_info: Some(array_info), |             render_context | ||||||
|                 .. |                 .resources() | ||||||
|             })) = render_context.resources().get_resource_info(buffer) |                 .get_resource_info(buffer, &mut |resource_info| { | ||||||
|             { |                     new_capacity = if let Some(ResourceInfo::Buffer(BufferInfo { | ||||||
|                 if array_info.item_capacity < buffer_array_status.new_item_count { |                         array_info: Some(array_info), | ||||||
|                     // over capacity. lets resize
 |                         .. | ||||||
|                     Some( |                     })) = resource_info | ||||||
|                         buffer_array_status.new_item_count + buffer_array_status.new_item_count / 2, |                     { | ||||||
|                     ) |                         if array_info.item_capacity < buffer_array_status.new_item_count { | ||||||
|                 } else { |                             // over capacity. lets resize
 | ||||||
|                     // under capacity. no change needed
 |                             Some( | ||||||
|                     None |                                 buffer_array_status.new_item_count | ||||||
|                 } |                                     + buffer_array_status.new_item_count / 2, | ||||||
|             } else { |                             ) | ||||||
|                 // incorrect resource type. overwrite with new buffer
 |                         } else { | ||||||
|                 Some(buffer_array_status.new_item_count) |                             // under capacity. no change needed
 | ||||||
|             } |                             None | ||||||
|  |                         } | ||||||
|  |                     } else { | ||||||
|  |                         // incorrect resource type. overwrite with new buffer
 | ||||||
|  |                         Some(buffer_array_status.new_item_count) | ||||||
|  |                     }; | ||||||
|  |                 }); | ||||||
|  |             new_capacity | ||||||
|         } else { |         } else { | ||||||
|             // buffer does not exist. create it now.
 |             // buffer does not exist. create it now.
 | ||||||
|             Some(buffer_array_status.new_item_count) |             Some(buffer_array_status.new_item_count) | ||||||
|  | |||||||
| @ -9,7 +9,9 @@ use bevy_window::{Window, WindowId}; | |||||||
| use std::any::Any; | use std::any::Any; | ||||||
| 
 | 
 | ||||||
| pub struct GlobalRenderResourceContext { | 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 { | impl GlobalRenderResourceContext { | ||||||
| @ -53,7 +55,7 @@ pub trait RenderResourceContext: Any { | |||||||
|     fn remove_buffer(&mut self, resource: RenderResource); |     fn remove_buffer(&mut self, resource: RenderResource); | ||||||
|     fn remove_texture(&mut self, resource: RenderResource); |     fn remove_texture(&mut self, resource: RenderResource); | ||||||
|     fn remove_sampler(&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(&self) -> &AssetResources; | ||||||
|     fn asset_resources_mut(&mut self) -> &mut AssetResources; |     fn asset_resources_mut(&mut self) -> &mut AssetResources; | ||||||
|     fn get_texture_resource(&self, texture: Handle<Texture>) -> Option<RenderResource>; |     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
 |                 // PERF: consider doing a par-iter over all renderable components so this can be parallelized
 | ||||||
|                 for handle in render_graph.pipeline_descriptors.iter() { |                 for handle in render_graph.pipeline_descriptors.iter() { | ||||||
|                     for compiled_pipeline_handle in |                     if let Some(compiled_pipelines) = | ||||||
|                         pipeline_compiler.iter_compiled_pipelines(*handle).unwrap() |                         pipeline_compiler.iter_compiled_pipelines(*handle) | ||||||
|                     { |                     { | ||||||
|                         if let Some(compiled_pipeline_assignments) = pipeline_assignments |                         for compiled_pipeline_handle in compiled_pipelines { | ||||||
|                             .assignments |                             if let Some(compiled_pipeline_assignments) = pipeline_assignments | ||||||
|                             .get(compiled_pipeline_handle) |                                 .assignments | ||||||
|                         { |                                 .get(compiled_pipeline_handle) | ||||||
|                             let compiled_pipeline = |                             { | ||||||
|                                 pipelines.get(compiled_pipeline_handle).unwrap(); |                                 let compiled_pipeline = | ||||||
|                             let pipeline_layout = compiled_pipeline.get_layout().unwrap(); |                                     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 bind_group in pipeline_layout.bind_groups.iter() { |                                 for bind_group in pipeline_layout.bind_groups.iter() { | ||||||
|                                     renderable |                                     global_render_resource_assignments | ||||||
|                                         .render_resource_assignments |  | ||||||
|                                         .update_render_resource_set_id(bind_group); |                                         .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 super::WgpuRenderResourceContext; | ||||||
| use crate::{ | use crate::{ | ||||||
|     wgpu_type_converter::{OwnedWgpuVertexBufferDescriptor, WgpuInto}, |     wgpu_type_converter::{OwnedWgpuVertexBufferDescriptor, WgpuInto}, | ||||||
|     WgpuRenderPass, |     WgpuRenderPass, WgpuResourceRefs, | ||||||
| }; | }; | ||||||
| use bevy_asset::{AssetStorage, Handle}; | use bevy_asset::{AssetStorage, Handle}; | ||||||
| use bevy_render::{ | use bevy_render::{ | ||||||
| @ -127,10 +127,10 @@ impl RenderContext for WgpuRenderContext { | |||||||
|         if let Some((render_resource_set_id, _indices)) = |         if let Some((render_resource_set_id, _indices)) = | ||||||
|             render_resource_assignments.get_render_resource_set_id(bind_group_descriptor.id) |             render_resource_assignments.get_render_resource_set_id(bind_group_descriptor.id) | ||||||
|         { |         { | ||||||
|             if let None = self |             if !self | ||||||
|                 .render_resources |                 .render_resources | ||||||
|                 .wgpu_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!( |                 log::trace!( | ||||||
|                     "start creating bind group for RenderResourceSet {:?}", |                     "start creating bind group for RenderResourceSet {:?}", | ||||||
| @ -155,48 +155,54 @@ impl RenderContext for WgpuRenderContext { | |||||||
|                         .iter() |                         .iter() | ||||||
|                         .map(|binding| { |                         .map(|binding| { | ||||||
|                             if let Some(resource) = render_resource_assignments.get(&binding.name) { |                             if let Some(resource) = render_resource_assignments.get(&binding.name) { | ||||||
|                                 let resource_info = |                                 let mut wgpu_resource = None; | ||||||
|                                     self.resources().get_resource_info(resource).unwrap(); |                                 self.resources().get_resource_info( | ||||||
|                                 log::trace!( |  | ||||||
|                                     "found binding {} ({}) resource: {:?} {:?}", |  | ||||||
|                                     binding.index, |  | ||||||
|                                     binding.name, |  | ||||||
|                                     resource, |                                     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 { |                                 wgpu::Binding { | ||||||
|                                     binding: binding.index, |                                     binding: binding.index, | ||||||
|                                     resource: match &binding.bind_type { |                                     resource: wgpu_resource.expect("No resource binding found"), | ||||||
|                                         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"), |  | ||||||
|                                     }, |  | ||||||
|                                 } |                                 } | ||||||
|                             } else { |                             } else { | ||||||
|                                 panic!( |                                 panic!( | ||||||
| @ -256,13 +262,13 @@ impl RenderContext for WgpuRenderContext { | |||||||
| 
 | 
 | ||||||
|         let layout = pipeline_descriptor.get_layout().unwrap(); |         let layout = pipeline_descriptor.get_layout().unwrap(); | ||||||
|         for bind_group in layout.bind_groups.iter() { |         for bind_group in layout.bind_groups.iter() { | ||||||
|             if let None = self |             if self | ||||||
|                 .render_resources |                 .render_resources | ||||||
|                 .wgpu_resources |                 .wgpu_resources | ||||||
|                 .bind_group_layouts |                 .bind_group_layouts | ||||||
|                 .read() |                 .read() | ||||||
|                 .unwrap() |                 .unwrap() | ||||||
|                 .get(&bind_group.id) |                 .get(&bind_group.id).is_none() | ||||||
|             { |             { | ||||||
|                 let bind_group_layout_binding = bind_group |                 let bind_group_layout_binding = bind_group | ||||||
|                     .bindings |                     .bindings | ||||||
| @ -412,18 +418,21 @@ impl RenderContext for WgpuRenderContext { | |||||||
|         if !self.command_encoder.is_some() { |         if !self.command_encoder.is_some() { | ||||||
|             self.command_encoder.create(&self.device); |             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 mut encoder = self.command_encoder.take().unwrap(); | ||||||
|         { |         { | ||||||
|             let render_pass = create_render_pass( |             let render_pass = create_render_pass( | ||||||
|                 self, |                 self, | ||||||
|                 pass_descriptor, |                 pass_descriptor, | ||||||
|                 render_resource_assignments, |                 render_resource_assignments, | ||||||
|  |                 &refs, | ||||||
|                 &mut encoder, |                 &mut encoder, | ||||||
|             ); |             ); | ||||||
|             let mut wgpu_render_pass = WgpuRenderPass { |             let mut wgpu_render_pass = WgpuRenderPass { | ||||||
|                 render_context: self, |                 render_context: self, | ||||||
|                 render_pass, |                 render_pass, | ||||||
|  |                 render_resources: refs, | ||||||
|                 bound_bind_groups: HashMap::default(), |                 bound_bind_groups: HashMap::default(), | ||||||
|             }; |             }; | ||||||
| 
 | 
 | ||||||
| @ -438,6 +447,7 @@ pub fn create_render_pass<'a, 'b>( | |||||||
|     render_context: &'a WgpuRenderContext, |     render_context: &'a WgpuRenderContext, | ||||||
|     pass_descriptor: &PassDescriptor, |     pass_descriptor: &PassDescriptor, | ||||||
|     global_render_resource_assignments: &'b RenderResourceAssignments, |     global_render_resource_assignments: &'b RenderResourceAssignments, | ||||||
|  |     refs: &WgpuResourceRefs<'a>, | ||||||
|     encoder: &'a mut wgpu::CommandEncoder, |     encoder: &'a mut wgpu::CommandEncoder, | ||||||
| ) -> wgpu::RenderPass<'a> { | ) -> wgpu::RenderPass<'a> { | ||||||
|     encoder.begin_render_pass(&wgpu::RenderPassDescriptor { |     encoder.begin_render_pass(&wgpu::RenderPassDescriptor { | ||||||
| @ -448,6 +458,7 @@ pub fn create_render_pass<'a, 'b>( | |||||||
|                 create_wgpu_color_attachment_descriptor( |                 create_wgpu_color_attachment_descriptor( | ||||||
|                     render_context, |                     render_context, | ||||||
|                     global_render_resource_assignments, |                     global_render_resource_assignments, | ||||||
|  |                     refs, | ||||||
|                     c, |                     c, | ||||||
|                 ) |                 ) | ||||||
|             }) |             }) | ||||||
| @ -456,6 +467,7 @@ pub fn create_render_pass<'a, 'b>( | |||||||
|             create_wgpu_depth_stencil_attachment_descriptor( |             create_wgpu_depth_stencil_attachment_descriptor( | ||||||
|                 render_context, |                 render_context, | ||||||
|                 global_render_resource_assignments, |                 global_render_resource_assignments, | ||||||
|  |                 refs, | ||||||
|                 d, |                 d, | ||||||
|             ) |             ) | ||||||
|         }), |         }), | ||||||
| @ -465,16 +477,13 @@ pub fn create_render_pass<'a, 'b>( | |||||||
| fn get_texture_view<'a>( | fn get_texture_view<'a>( | ||||||
|     render_context: &'a WgpuRenderContext, |     render_context: &'a WgpuRenderContext, | ||||||
|     global_render_resource_assignments: &RenderResourceAssignments, |     global_render_resource_assignments: &RenderResourceAssignments, | ||||||
|  |     refs: &WgpuResourceRefs<'a>, | ||||||
|     name: &str, |     name: &str, | ||||||
| ) -> &'a wgpu::TextureView { | ) -> &'a wgpu::TextureView { | ||||||
|     match name { |     match name { | ||||||
|         resource_name::texture::SWAP_CHAIN => { |         resource_name::texture::SWAP_CHAIN => { | ||||||
|             if let Some(primary_swap_chain) = render_context |             if let Some(primary_swap_chain) = refs | ||||||
|                 .render_resources |  | ||||||
|                 .wgpu_resources |  | ||||||
|                 .swap_chain_outputs |                 .swap_chain_outputs | ||||||
|                 .read() |  | ||||||
|                 .unwrap() |  | ||||||
|                 .get(render_context.primary_window.as_ref().unwrap()) |                 .get(render_context.primary_window.as_ref().unwrap()) | ||||||
|                 .map(|output| &output.view) |                 .map(|output| &output.view) | ||||||
|             { |             { | ||||||
| @ -484,14 +493,7 @@ fn get_texture_view<'a>( | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         _ => match global_render_resource_assignments.get(name) { |         _ => match global_render_resource_assignments.get(name) { | ||||||
|             Some(resource) => render_context |             Some(resource) => refs.textures.get(&resource).unwrap(), | ||||||
|                 .render_resources |  | ||||||
|                 .wgpu_resources |  | ||||||
|                 .textures |  | ||||||
|                 .read() |  | ||||||
|                 .unwrap() |  | ||||||
|                 .get(&resource) |  | ||||||
|                 .unwrap(), |  | ||||||
|             None => { |             None => { | ||||||
|                 // if let Some(swap_chain_output) = swap_chain_outputs.get(name) {
 |                 // if let Some(swap_chain_output) = swap_chain_outputs.get(name) {
 | ||||||
|                 //     &swap_chain_output.view
 |                 //     &swap_chain_output.view
 | ||||||
| @ -506,11 +508,13 @@ fn get_texture_view<'a>( | |||||||
| fn create_wgpu_color_attachment_descriptor<'a>( | fn create_wgpu_color_attachment_descriptor<'a>( | ||||||
|     render_context: &'a WgpuRenderContext, |     render_context: &'a WgpuRenderContext, | ||||||
|     global_render_resource_assignments: &RenderResourceAssignments, |     global_render_resource_assignments: &RenderResourceAssignments, | ||||||
|  |     refs: &WgpuResourceRefs<'a>, | ||||||
|     color_attachment_descriptor: &RenderPassColorAttachmentDescriptor, |     color_attachment_descriptor: &RenderPassColorAttachmentDescriptor, | ||||||
| ) -> wgpu::RenderPassColorAttachmentDescriptor<'a> { | ) -> wgpu::RenderPassColorAttachmentDescriptor<'a> { | ||||||
|     let attachment = get_texture_view( |     let attachment = get_texture_view( | ||||||
|         render_context, |         render_context, | ||||||
|         global_render_resource_assignments, |         global_render_resource_assignments, | ||||||
|  |         refs, | ||||||
|         color_attachment_descriptor.attachment.as_str(), |         color_attachment_descriptor.attachment.as_str(), | ||||||
|     ); |     ); | ||||||
| 
 | 
 | ||||||
| @ -521,6 +525,7 @@ fn create_wgpu_color_attachment_descriptor<'a>( | |||||||
|             get_texture_view( |             get_texture_view( | ||||||
|                 render_context, |                 render_context, | ||||||
|                 global_render_resource_assignments, |                 global_render_resource_assignments, | ||||||
|  |                 refs, | ||||||
|                 target.as_str(), |                 target.as_str(), | ||||||
|             ) |             ) | ||||||
|         }); |         }); | ||||||
| @ -537,11 +542,13 @@ fn create_wgpu_color_attachment_descriptor<'a>( | |||||||
| fn create_wgpu_depth_stencil_attachment_descriptor<'a>( | fn create_wgpu_depth_stencil_attachment_descriptor<'a>( | ||||||
|     render_context: &'a WgpuRenderContext, |     render_context: &'a WgpuRenderContext, | ||||||
|     global_render_resource_assignments: &RenderResourceAssignments, |     global_render_resource_assignments: &RenderResourceAssignments, | ||||||
|  |     refs: &WgpuResourceRefs<'a>, | ||||||
|     depth_stencil_attachment_descriptor: &RenderPassDepthStencilAttachmentDescriptor, |     depth_stencil_attachment_descriptor: &RenderPassDepthStencilAttachmentDescriptor, | ||||||
| ) -> wgpu::RenderPassDepthStencilAttachmentDescriptor<'a> { | ) -> wgpu::RenderPassDepthStencilAttachmentDescriptor<'a> { | ||||||
|     let attachment = get_texture_view( |     let attachment = get_texture_view( | ||||||
|         render_context, |         render_context, | ||||||
|         global_render_resource_assignments, |         global_render_resource_assignments, | ||||||
|  |         refs, | ||||||
|         depth_stencil_attachment_descriptor.attachment.as_str(), |         depth_stencil_attachment_descriptor.attachment.as_str(), | ||||||
|     ); |     ); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -16,7 +16,7 @@ use bevy_window::{WindowId, Window}; | |||||||
| #[derive(Clone)] | #[derive(Clone)] | ||||||
| pub struct WgpuRenderResourceContext { | pub struct WgpuRenderResourceContext { | ||||||
|     pub device: Arc<wgpu::Device>, |     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 { |     pub fn new(device: Arc<wgpu::Device>) -> Self { | ||||||
|         WgpuRenderResourceContext { |         WgpuRenderResourceContext { | ||||||
|             device, |             device, | ||||||
|             wgpu_resources: Arc::new(WgpuResources::default()), |             wgpu_resources: WgpuResources::default(), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -95,8 +95,8 @@ impl RenderResourceContext for WgpuRenderResourceContext { | |||||||
|             .get_mesh_indices_resource(mesh) |             .get_mesh_indices_resource(mesh) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn get_resource_info(&self, resource: RenderResource) -> Option<&ResourceInfo> { |     fn get_resource_info(&self, resource: RenderResource, handle_info: &mut dyn FnMut(Option<&ResourceInfo>)) { | ||||||
|         self.wgpu_resources.get_resource_info(resource) |         self.wgpu_resources.get_resource_info(resource, handle_info); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn asset_resources(&self) -> &AssetResources { |     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_asset::Handle; | ||||||
| use bevy_render::{ | use bevy_render::{ | ||||||
|     pass::RenderPass, |     pass::RenderPass, | ||||||
| @ -13,6 +13,7 @@ use std::{collections::HashMap, ops::Range}; | |||||||
| pub struct WgpuRenderPass<'a> { | pub struct WgpuRenderPass<'a> { | ||||||
|     pub render_pass: wgpu::RenderPass<'a>, |     pub render_pass: wgpu::RenderPass<'a>, | ||||||
|     pub render_context: &'a WgpuRenderContext, |     pub render_context: &'a WgpuRenderContext, | ||||||
|  |     pub render_resources: WgpuResourceRefs<'a>, | ||||||
|     pub bound_bind_groups: HashMap<u32, RenderResourceSetId>, |     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) { |     fn set_vertex_buffer(&mut self, start_slot: u32, resource: RenderResource, offset: u64) { | ||||||
|         let buffers = self |         let buffer = self | ||||||
|             .render_context |  | ||||||
|             .render_resources |             .render_resources | ||||||
|             .wgpu_resources |  | ||||||
|             .buffers |             .buffers | ||||||
|             .read() |             .get(&resource) | ||||||
|             .unwrap(); |             .unwrap(); | ||||||
|         let buffer = buffers.get(&resource).unwrap(); |  | ||||||
|         self.render_pass |         self.render_pass | ||||||
|             .set_vertex_buffer(start_slot, &buffer, offset, 0); |             .set_vertex_buffer(start_slot, &buffer, offset, 0); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn set_index_buffer(&mut self, resource: RenderResource, offset: u64) { |     fn set_index_buffer(&mut self, resource: RenderResource, offset: u64) { | ||||||
|         let buffers = self |         let buffer = self | ||||||
|             .render_context |  | ||||||
|             .render_resources |             .render_resources | ||||||
|             .wgpu_resources |  | ||||||
|             .buffers |             .buffers | ||||||
|             .read() |             .get(&resource) | ||||||
|             .unwrap(); |             .unwrap(); | ||||||
|         let buffer = buffers.get(&resource).unwrap(); |  | ||||||
|         self.render_pass.set_index_buffer(&buffer, offset, 0); |         self.render_pass.set_index_buffer(&buffer, offset, 0); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -80,17 +75,15 @@ impl<'a> RenderPass for WgpuRenderPass<'a> { | |||||||
|                         index_buffer |                         index_buffer | ||||||
|                     ); |                     ); | ||||||
|                     self.set_index_buffer(index_buffer, 0); |                     self.set_index_buffer(index_buffer, 0); | ||||||
|                     match self |                     self.render_context.resources().get_resource_info( | ||||||
|                         .render_context |                         index_buffer, | ||||||
|                         .resources() |                         &mut |resource_info| match resource_info { | ||||||
|                         .get_resource_info(index_buffer) |                             Some(ResourceInfo::Buffer(buffer_info)) => { | ||||||
|                         .unwrap() |                                 indices = Some(0..(buffer_info.size / 2) as u32) | ||||||
|                     { |                             } | ||||||
|                         ResourceInfo::Buffer(buffer_info) => { |                             _ => panic!("expected a buffer type"), | ||||||
|                             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)) = |             if let Some((render_resource_set_id, dynamic_uniform_indices)) = | ||||||
|                 render_resource_assignments.get_render_resource_set_id(bind_group.id) |                 render_resource_assignments.get_render_resource_set_id(bind_group.id) | ||||||
|             { |             { | ||||||
|                 if let Some(wgpu_bind_group) = self |                 if let Some(bind_group_info) = self | ||||||
|                     .render_context |  | ||||||
|                     .render_resources |                     .render_resources | ||||||
|                     .wgpu_resources |                     .bind_groups | ||||||
|                     .get_bind_group(bind_group.id, *render_resource_set_id) |                     .get(&bind_group.id) | ||||||
|                 { |                 { | ||||||
|                     const EMPTY: &'static [u32] = &[]; |                     if let Some(wgpu_bind_group) = | ||||||
|                     let dynamic_uniform_indices = |                         bind_group_info.bind_groups.get(render_resource_set_id) | ||||||
|                         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 *bound_render_resource_set == *render_resource_set_id |                         const EMPTY: &'static [u32] = &[]; | ||||||
|                             && dynamic_uniform_indices.len() == 0 |                         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 { |                         if dynamic_uniform_indices.len() == 0 { | ||||||
|                         self.bound_bind_groups |                             self.bound_bind_groups | ||||||
|                             .insert(bind_group.index, *render_resource_set_id); |                                 .insert(bind_group.index, *render_resource_set_id); | ||||||
|                     } else { |                         } else { | ||||||
|                         self.bound_bind_groups.remove(&bind_group.index); |                             self.bound_bind_groups.remove(&bind_group.index); | ||||||
|                     } |                         } | ||||||
| 
 | 
 | ||||||
|                     log::trace!( |                         log::trace!( | ||||||
|                         "set bind group {} {:?}: {:?}", |                             "set bind group {} {:?}: {:?}", | ||||||
|                         bind_group.index, |                             bind_group.index, | ||||||
|                         dynamic_uniform_indices, |                             dynamic_uniform_indices, | ||||||
|                         render_resource_set_id |                             render_resource_set_id | ||||||
|                     ); |                         ); | ||||||
|                     self.render_pass.set_bind_group( |                         self.render_pass.set_bind_group( | ||||||
|                         bind_group.index, |                             bind_group.index, | ||||||
|                         &wgpu_bind_group, |                             wgpu_bind_group, | ||||||
|                         dynamic_uniform_indices, |                             dynamic_uniform_indices, | ||||||
|                     ); |                         ); | ||||||
|  |                     } | ||||||
|                 }; |                 }; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @ -150,14 +146,7 @@ impl<'a> RenderPass for WgpuRenderPass<'a> { | |||||||
|         indices |         indices | ||||||
|     } |     } | ||||||
|     fn set_pipeline(&mut self, pipeline_handle: Handle<PipelineDescriptor>) { |     fn set_pipeline(&mut self, pipeline_handle: Handle<PipelineDescriptor>) { | ||||||
|         let render_pipelines = self |         let pipeline = self.render_resources.render_pipelines.get(&pipeline_handle).expect( | ||||||
|             .render_context |  | ||||||
|             .render_resources |  | ||||||
|             .wgpu_resources |  | ||||||
|             .render_pipelines |  | ||||||
|             .read() |  | ||||||
|             .unwrap(); |  | ||||||
|         let pipeline = render_pipelines.get(&pipeline_handle).expect( |  | ||||||
|             "Attempted to use a pipeline that does not exist in this RenderPass's RenderContext", |             "Attempted to use a pipeline that does not exist in this RenderPass's RenderContext", | ||||||
|         ); |         ); | ||||||
|         self.render_pass.set_pipeline(pipeline); |         self.render_pass.set_pipeline(pipeline); | ||||||
|  | |||||||
| @ -11,7 +11,7 @@ use bevy_render::{ | |||||||
| }; | }; | ||||||
| use bevy_window::{WindowCreated, WindowResized, Windows}; | use bevy_window::{WindowCreated, WindowResized, Windows}; | ||||||
| use legion::prelude::*; | 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 struct WgpuRenderer { | ||||||
|     pub device: Arc<wgpu::Device>, |     pub device: Arc<wgpu::Device>, | ||||||
| @ -131,7 +131,6 @@ impl WgpuRenderer { | |||||||
|         for resource_provider_chunk in render_graph.resource_providers.chunks_mut(chunk_size) { |         for resource_provider_chunk in render_graph.resource_providers.chunks_mut(chunk_size) { | ||||||
|             // TODO: try to unify this Device usage
 |             // TODO: try to unify this Device usage
 | ||||||
|             let device = self.device.clone(); |             let device = self.device.clone(); | ||||||
|             let resource_device = device.clone(); |  | ||||||
|             // let sender = sender.clone();
 |             // let sender = sender.clone();
 | ||||||
|             // s.spawn(|_| {
 |             // s.spawn(|_| {
 | ||||||
|             // TODO: replace WgpuResources with Global+Local resources
 |             // TODO: replace WgpuResources with Global+Local resources
 | ||||||
| @ -241,17 +240,11 @@ impl WgpuRenderer { | |||||||
| 
 | 
 | ||||||
|         let mut encoder = { |         let mut encoder = { | ||||||
|             let mut global_context = resources.get_mut::<GlobalRenderResourceContext>().unwrap(); |             let mut global_context = resources.get_mut::<GlobalRenderResourceContext>().unwrap(); | ||||||
|             let mut any_context = (&mut global_context.context) as &mut dyn Any; |             let render_resource_context = global_context | ||||||
|             // let mut any_context = (&mut global_context.context);
 |                 .context | ||||||
|             // println!("{}", std::any::type_name_of_val(any_context));
 |  | ||||||
|             let mut render_resource_context = any_context |  | ||||||
|                 .downcast_mut::<WgpuRenderResourceContext>() |                 .downcast_mut::<WgpuRenderResourceContext>() | ||||||
|                 .unwrap(); |                 .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_created_events(resources, render_resource_context); | ||||||
| 
 | 
 | ||||||
|             self.handle_window_resized_events(resources, render_resource_context); |             self.handle_window_resized_events(resources, render_resource_context); | ||||||
| @ -266,11 +259,7 @@ impl WgpuRenderer { | |||||||
|                 self.intialized = true; |                 self.intialized = true; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             self.update_resource_providers( |             self.update_resource_providers(world, resources, render_resource_context); | ||||||
|                 world, |  | ||||||
|                 resources, |  | ||||||
|                 render_resource_context, |  | ||||||
|             ); |  | ||||||
| 
 | 
 | ||||||
|             update_shader_assignments(world, resources, &render_context); |             update_shader_assignments(world, resources, &render_context); | ||||||
|             self.create_queued_textures(resources, &mut render_context.render_resources); |             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
 |         // TODO: add to POST_UPDATE and remove redundant global_context
 | ||||||
|         render_resource_sets_system().run(world, resources); |         render_resource_sets_system().run(world, resources); | ||||||
|         let mut global_context = resources.get_mut::<GlobalRenderResourceContext>().unwrap(); |         let mut global_context = resources.get_mut::<GlobalRenderResourceContext>().unwrap(); | ||||||
|         let mut any_context = (&mut global_context.context) as &mut dyn Any; |         let render_resource_context = global_context | ||||||
|         // let mut any_context = (&mut global_context.context);
 |             .context | ||||||
|         // println!("{}", std::any::type_name_of_val(any_context));
 |  | ||||||
|         let mut render_resource_context = any_context |  | ||||||
|             .downcast_mut::<WgpuRenderResourceContext>() |             .downcast_mut::<WgpuRenderResourceContext>() | ||||||
|             .unwrap(); |             .unwrap(); | ||||||
|         let mut render_context = |         let mut render_context = | ||||||
|  | |||||||
| @ -20,12 +20,56 @@ pub struct WgpuBindGroupInfo { | |||||||
|     pub bind_groups: HashMap<RenderResourceSetId, wgpu::BindGroup>, |     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 struct WgpuResourcesReadLock<'a> { | ||||||
|     pub buffers: RwLockReadGuard<'a, HashMap<RenderResource, wgpu::Buffer>>, |     pub buffers: RwLockReadGuard<'a, HashMap<RenderResource, wgpu::Buffer>>, | ||||||
|     pub textures: RwLockReadGuard<'a, HashMap<RenderResource, wgpu::TextureView>>, |     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 { | pub struct WgpuResources { | ||||||
|     // TODO: remove this from WgpuResources. it doesn't need to be here
 |     // TODO: remove this from WgpuResources. it doesn't need to be here
 | ||||||
|     pub asset_resources: AssetResources, |     pub asset_resources: AssetResources, | ||||||
| @ -43,10 +87,13 @@ pub struct WgpuResources { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl WgpuResources { | impl WgpuResources { | ||||||
|     pub fn read(&self) -> WgpuResourcesReadLock { |     pub fn read<'a>(&'a self) -> WgpuResourcesReadLock<'a> { | ||||||
|         WgpuResourcesReadLock { |         WgpuResourcesReadLock { | ||||||
|             buffers: self.buffers.read().unwrap(), |             buffers: self.buffers.read().unwrap(), | ||||||
|             textures: self.textures.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); |             .insert(resource, resource_info); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn get_bind_group( |     pub fn has_bind_group( | ||||||
|         &self, |         &self, | ||||||
|         bind_group_descriptor_id: BindGroupDescriptorId, |         bind_group_descriptor_id: BindGroupDescriptorId, | ||||||
|         render_resource_set_id: RenderResourceSetId, |         render_resource_set_id: RenderResourceSetId, | ||||||
|     ) -> Option<&wgpu::BindGroup> { |     ) -> bool { | ||||||
|         if let Some(bind_group_info) = self |         if let Some(bind_group_info) = self | ||||||
|             .bind_groups |             .bind_groups | ||||||
|             .read() |             .read() | ||||||
|             .unwrap() |             .unwrap() | ||||||
|             .get(&bind_group_descriptor_id) |             .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 { |         } else { | ||||||
|             None |             false | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -174,8 +221,11 @@ impl WgpuResources { | |||||||
|         self.assign_buffer(buffer, buffer_info) |         self.assign_buffer(buffer, buffer_info) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn get_resource_info(&self, resource: RenderResource) -> Option<&ResourceInfo> { |     // TODO: taking a closure isn't fantastic. is there any way to make this better without exposing the lock in the interface?
 | ||||||
|         self.resource_info.read().unwrap().get(&resource) |     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) { |     pub fn remove_buffer(&self, resource: RenderResource) { | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Carter Anderson
						Carter Anderson