Make PipelineDescriptor an Asset that references Handle<Shader>
This commit is contained in:
		
							parent
							
								
									478d475219
								
							
						
					
					
						commit
						4de039eb71
					
				| @ -16,7 +16,7 @@ use crate::{ | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| use bevy_transform::{prelude::LocalToWorld, transform_system_bundle}; | use bevy_transform::{prelude::LocalToWorld, transform_system_bundle}; | ||||||
| use render_graph_2::CompiledShaderMap; | use render_graph_2::{CompiledShaderMap, PipelineDescriptor}; | ||||||
| use std::collections::HashMap; | use std::collections::HashMap; | ||||||
| 
 | 
 | ||||||
| pub struct AppBuilder { | pub struct AppBuilder { | ||||||
| @ -166,6 +166,7 @@ impl AppBuilder { | |||||||
|         resources.insert(AssetStorage::<Mesh>::new()); |         resources.insert(AssetStorage::<Mesh>::new()); | ||||||
|         resources.insert(AssetStorage::<Texture>::new()); |         resources.insert(AssetStorage::<Texture>::new()); | ||||||
|         resources.insert(AssetStorage::<Shader>::new()); |         resources.insert(AssetStorage::<Shader>::new()); | ||||||
|  |         resources.insert(AssetStorage::<PipelineDescriptor>::new()); | ||||||
|         resources.insert(ShaderAssignments::new()); |         resources.insert(ShaderAssignments::new()); | ||||||
|         resources.insert(CompiledShaderMap::new()); |         resources.insert(CompiledShaderMap::new()); | ||||||
|         self |         self | ||||||
| @ -181,6 +182,17 @@ impl AppBuilder { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn add_render_graph_defaults(mut self) -> Self { |     pub fn add_render_graph_defaults(mut self) -> Self { | ||||||
|  |         { | ||||||
|  |             let mut pipeline_storage = self | ||||||
|  |                 .world | ||||||
|  |                 .resources | ||||||
|  |                 .get_mut::<AssetStorage<PipelineDescriptor>>() | ||||||
|  |                 .unwrap(); | ||||||
|  |             let mut shader_storage = self | ||||||
|  |                 .world | ||||||
|  |                 .resources | ||||||
|  |                 .get_mut::<AssetStorage<Shader>>() | ||||||
|  |                 .unwrap(); | ||||||
|             self.render_graph_builder = self |             self.render_graph_builder = self | ||||||
|                 .render_graph_builder |                 .render_graph_builder | ||||||
|                 .add_resource_provider(Box::new(CameraResourceProvider)) |                 .add_resource_provider(Box::new(CameraResourceProvider)) | ||||||
| @ -190,8 +202,9 @@ impl AppBuilder { | |||||||
|                 .add_resource_provider(Box::new(UniformResourceProvider::<StandardMaterial>::new())) |                 .add_resource_provider(Box::new(UniformResourceProvider::<StandardMaterial>::new())) | ||||||
|                 .add_resource_provider(Box::new(UniformResourceProvider::<LocalToWorld>::new())) |                 .add_resource_provider(Box::new(UniformResourceProvider::<LocalToWorld>::new())) | ||||||
|                 .add_forward_pass() |                 .add_forward_pass() | ||||||
|             .add_forward_pipeline() |                 .add_forward_pipeline(&mut pipeline_storage, &mut shader_storage) | ||||||
|             .add_ui_pipeline(); |                 .add_ui_pipeline(&mut pipeline_storage, &mut shader_storage); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         self |         self | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -3,17 +3,31 @@ mod mesh; | |||||||
| mod texture; | mod texture; | ||||||
| 
 | 
 | ||||||
| pub use self::gltf::load_gltf; | pub use self::gltf::load_gltf; | ||||||
|  | use std::hash::{Hash, Hasher}; | ||||||
| pub use mesh::*; | pub use mesh::*; | ||||||
| pub use texture::*; | pub use texture::*; | ||||||
| 
 | 
 | ||||||
| use std::{collections::HashMap, marker::PhantomData}; | use std::{collections::HashMap, marker::PhantomData}; | ||||||
| 
 | 
 | ||||||
| #[derive(Hash, Eq, PartialEq)] |  | ||||||
| pub struct Handle<T> { | pub struct Handle<T> { | ||||||
|     pub id: usize, |     pub id: usize, | ||||||
|     marker: PhantomData<T>, |     marker: PhantomData<T>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | impl<T> Hash for Handle<T> { | ||||||
|  |     fn hash<H: Hasher>(&self, state: &mut H) { | ||||||
|  |         self.id.hash(state); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl<T> PartialEq for Handle<T> { | ||||||
|  |     fn eq(&self, other: &Self) -> bool { | ||||||
|  |         self.id == other.id | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl<T> Eq for Handle<T> {} | ||||||
|  | 
 | ||||||
| // TODO: somehow handle this gracefully in asset managers. or alternatively remove Default
 | // TODO: somehow handle this gracefully in asset managers. or alternatively remove Default
 | ||||||
| impl<T> Default for Handle<T> { | impl<T> Default for Handle<T> { | ||||||
|     fn default() -> Self { |     fn default() -> Self { | ||||||
| @ -75,11 +89,19 @@ impl<T> AssetStorage<T> { | |||||||
|         handle |         handle | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn get_id(&mut self, id: usize) -> Option<&mut T> { |     pub fn get_id(&self, id: usize) -> Option<&T> { | ||||||
|  |         self.assets.get(&id) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn get_id_mut(&mut self, id: usize) -> Option<&mut T> { | ||||||
|         self.assets.get_mut(&id) |         self.assets.get_mut(&id) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn get(&mut self, handle: &Handle<T>) -> Option<&mut T> { |     pub fn get(&self, handle: &Handle<T>) -> Option<&T> { | ||||||
|  |         self.assets.get(&handle.id) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn get_mut(&mut self, handle: &Handle<T>) -> Option<&mut T> { | ||||||
|         self.assets.get_mut(&handle.id) |         self.assets.get_mut(&handle.id) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -157,7 +157,7 @@ impl Pipeline for ForwardPipeline { | |||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if should_load_mesh { |             if should_load_mesh { | ||||||
|                 if let Some(mesh_asset) = mesh_storage.get_id(mesh.id) { |                 if let Some(mesh_asset) = mesh_storage.get_id_mut(mesh.id) { | ||||||
|                     mesh_asset.setup_buffers(&render_graph.device); |                     mesh_asset.setup_buffers(&render_graph.device); | ||||||
|                     pass.set_index_buffer(mesh_asset.index_buffer.as_ref().unwrap(), 0); |                     pass.set_index_buffer(mesh_asset.index_buffer.as_ref().unwrap(), 0); | ||||||
|                     pass.set_vertex_buffers(0, &[(&mesh_asset.vertex_buffer.as_ref().unwrap(), 0)]); |                     pass.set_vertex_buffers(0, &[(&mesh_asset.vertex_buffer.as_ref().unwrap(), 0)]); | ||||||
|  | |||||||
| @ -285,7 +285,7 @@ impl Pipeline for ForwardInstancedPipeline { | |||||||
| 
 | 
 | ||||||
|         let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap(); |         let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap(); | ||||||
|         for instance_buffer_info in self.instance_buffer_infos.as_ref().unwrap().iter() { |         for instance_buffer_info in self.instance_buffer_infos.as_ref().unwrap().iter() { | ||||||
|             if let Some(mesh_asset) = mesh_storage.get_id(instance_buffer_info.mesh_id) { |             if let Some(mesh_asset) = mesh_storage.get_id_mut(instance_buffer_info.mesh_id) { | ||||||
|                 mesh_asset.setup_buffers(&render_graph.device); |                 mesh_asset.setup_buffers(&render_graph.device); | ||||||
|                 pass.set_index_buffer(mesh_asset.index_buffer.as_ref().unwrap(), 0); |                 pass.set_index_buffer(mesh_asset.index_buffer.as_ref().unwrap(), 0); | ||||||
|                 pass.set_vertex_buffers(0, &[(&mesh_asset.vertex_buffer.as_ref().unwrap(), 0)]); |                 pass.set_vertex_buffers(0, &[(&mesh_asset.vertex_buffer.as_ref().unwrap(), 0)]); | ||||||
|  | |||||||
| @ -176,7 +176,7 @@ impl Pipeline for ForwardShadowPassNew { | |||||||
| 
 | 
 | ||||||
|         let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap(); |         let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap(); | ||||||
|         for (material, mesh) in mesh_query.iter(world) { |         for (material, mesh) in mesh_query.iter(world) { | ||||||
|             if let Some(mesh_asset) = mesh_storage.get_id(mesh.id) { |             if let Some(mesh_asset) = mesh_storage.get_id_mut(mesh.id) { | ||||||
|                 mesh_asset.setup_buffers(&render_graph.device); |                 mesh_asset.setup_buffers(&render_graph.device); | ||||||
|                 pass.set_bind_group(1, material.bind_group.as_ref().unwrap(), &[]); |                 pass.set_bind_group(1, material.bind_group.as_ref().unwrap(), &[]); | ||||||
|                 pass.set_index_buffer(mesh_asset.index_buffer.as_ref().unwrap(), 0); |                 pass.set_index_buffer(mesh_asset.index_buffer.as_ref().unwrap(), 0); | ||||||
|  | |||||||
| @ -166,7 +166,7 @@ impl Pipeline for ShadowPipeline { | |||||||
| 
 | 
 | ||||||
|         let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap(); |         let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap(); | ||||||
|         for (material, mesh) in mesh_query.iter(world) { |         for (material, mesh) in mesh_query.iter(world) { | ||||||
|             if let Some(mesh_asset) = mesh_storage.get_id(mesh.id) { |             if let Some(mesh_asset) = mesh_storage.get_id_mut(mesh.id) { | ||||||
|                 mesh_asset.setup_buffers(&render_graph.device); |                 mesh_asset.setup_buffers(&render_graph.device); | ||||||
| 
 | 
 | ||||||
|                 pass.set_bind_group(1, material.bind_group.as_ref().unwrap(), &[]); |                 pass.set_bind_group(1, material.bind_group.as_ref().unwrap(), &[]); | ||||||
|  | |||||||
| @ -242,7 +242,7 @@ impl Pipeline for UiPipeline { | |||||||
| 
 | 
 | ||||||
|         let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap(); |         let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap(); | ||||||
|         for instance_buffer_info in instance_buffer_infos.as_ref().unwrap().iter() { |         for instance_buffer_info in instance_buffer_infos.as_ref().unwrap().iter() { | ||||||
|             if let Some(mesh_asset) = mesh_storage.get_id(instance_buffer_info.mesh_id) { |             if let Some(mesh_asset) = mesh_storage.get_id_mut(instance_buffer_info.mesh_id) { | ||||||
|                 mesh_asset.setup_buffers(&render_graph.device); |                 mesh_asset.setup_buffers(&render_graph.device); | ||||||
|                 pass.set_index_buffer(mesh_asset.index_buffer.as_ref().unwrap(), 0); |                 pass.set_index_buffer(mesh_asset.index_buffer.as_ref().unwrap(), 0); | ||||||
|                 pass.set_vertex_buffers(0, &[(&mesh_asset.vertex_buffer.as_ref().unwrap(), 0)]); |                 pass.set_vertex_buffers(0, &[(&mesh_asset.vertex_buffer.as_ref().unwrap(), 0)]); | ||||||
|  | |||||||
| @ -10,7 +10,7 @@ use crate::{ | |||||||
| use zerocopy::AsBytes; | use zerocopy::AsBytes; | ||||||
| 
 | 
 | ||||||
| pub fn mesh_draw_target(world: &World, render_pass: &mut dyn RenderPass) { | pub fn mesh_draw_target(world: &World, render_pass: &mut dyn RenderPass) { | ||||||
|     let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap(); |     let mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap(); | ||||||
|     let mut current_mesh_id = None; |     let mut current_mesh_id = None; | ||||||
|     let mut current_mesh_index_length = 0; |     let mut current_mesh_index_length = 0; | ||||||
|     let mesh_query = <(Read<ShaderUniforms>, Read<Handle<Mesh>>, Read<Renderable>)>::query() |     let mesh_query = <(Read<ShaderUniforms>, Read<Handle<Mesh>>, Read<Renderable>)>::query() | ||||||
|  | |||||||
| @ -7,7 +7,7 @@ use crate::{ | |||||||
| use zerocopy::AsBytes; | use zerocopy::AsBytes; | ||||||
| 
 | 
 | ||||||
| pub fn ui_draw_target(world: &World, render_pass: &mut dyn RenderPass) { | pub fn ui_draw_target(world: &World, render_pass: &mut dyn RenderPass) { | ||||||
|     let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap(); |     let mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap(); | ||||||
|     // NOTE: this is ugly and borrowing is stupid
 |     // NOTE: this is ugly and borrowing is stupid
 | ||||||
|     let result = { |     let result = { | ||||||
|         let renderer = render_pass.get_renderer(); |         let renderer = render_pass.get_renderer(); | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| use crate::render::{ | use crate::{asset::{AssetStorage, Handle}, render::{ | ||||||
|     render_graph_2::{BindGroup, DrawTarget, PipelineLayout}, |     render_graph_2::{BindGroup, DrawTarget, PipelineLayout}, | ||||||
|     shader::{Shader, ShaderStages}, |     shader::{Shader, ShaderStages}, | ||||||
| }; | }}; | ||||||
| 
 | 
 | ||||||
| pub struct VertexBufferDescriptor { | pub struct VertexBufferDescriptor { | ||||||
|     pub stride: wgpu::BufferAddress, |     pub stride: wgpu::BufferAddress, | ||||||
| @ -55,7 +55,7 @@ pub struct PipelineDescriptor { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl PipelineDescriptor { | impl PipelineDescriptor { | ||||||
|     fn new(vertex_shader: Shader) -> Self { |     fn new(vertex_shader: Handle<Shader>) -> Self { | ||||||
|         PipelineDescriptor { |         PipelineDescriptor { | ||||||
|             pipeline_layout: PipelineLayout::new(), |             pipeline_layout: PipelineLayout::new(), | ||||||
|             color_states: Vec::new(), |             color_states: Vec::new(), | ||||||
| @ -80,19 +80,22 @@ impl PipelineDescriptor { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl PipelineDescriptor { | impl PipelineDescriptor { | ||||||
|     pub fn build(vertex_shader: Shader) -> PipelineBuilder { |     pub fn build(shader_storage: &mut AssetStorage<Shader>, vertex_shader: Shader) -> PipelineBuilder { | ||||||
|         PipelineBuilder::new(vertex_shader) |         PipelineBuilder::new(shader_storage, vertex_shader) | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub struct PipelineBuilder { | pub struct PipelineBuilder<'a> { | ||||||
|     pipeline: PipelineDescriptor, |     pipeline: PipelineDescriptor, | ||||||
|  |     shader_storage: &'a mut AssetStorage<Shader>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl PipelineBuilder { | impl<'a> PipelineBuilder<'a> { | ||||||
|     pub fn new(vertex_shader: Shader) -> Self { |     pub fn new(shader_storage: &'a mut AssetStorage<Shader>, vertex_shader: Shader) -> Self { | ||||||
|  |         let vertex_shader_handle = shader_storage.add(vertex_shader); | ||||||
|         PipelineBuilder { |         PipelineBuilder { | ||||||
|             pipeline: PipelineDescriptor::new(vertex_shader), |             pipeline: PipelineDescriptor::new(vertex_shader_handle), | ||||||
|  |             shader_storage, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -101,7 +104,8 @@ impl PipelineBuilder { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn with_fragment_shader(mut self, fragment_shader: Shader) -> Self { |     pub fn with_fragment_shader(mut self, fragment_shader: Shader) -> Self { | ||||||
|         self.pipeline.shader_stages.fragment = Some(fragment_shader); |         let fragment_shader_handle = self.shader_storage.add(fragment_shader); | ||||||
|  |         self.pipeline.shader_stages.fragment = Some(fragment_shader_handle); | ||||||
|         self |         self | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,22 +1,22 @@ | |||||||
| use crate::render::{ | use crate::{asset::AssetStorage, render::{ | ||||||
|     render_graph_2::{ |     render_graph_2::{ | ||||||
|         draw_targets::mesh_draw_target, pipeline_layout::*, PipelineDescriptor, RenderGraphBuilder, |         draw_targets::mesh_draw_target, pipeline_layout::*, PipelineDescriptor, RenderGraphBuilder, | ||||||
|     }, |     }, | ||||||
|     shader::{Shader, ShaderStage}, |     shader::{Shader, ShaderStage}, | ||||||
|     Vertex, |     Vertex, | ||||||
| }; | }}; | ||||||
| pub trait ForwardPipelineBuilder { | pub trait ForwardPipelineBuilder { | ||||||
|     fn add_forward_pipeline(self) -> Self; |     fn add_forward_pipeline(self, pipeline_descriptor_storage: &mut AssetStorage<PipelineDescriptor>, shader_storage: &mut AssetStorage<Shader>) -> Self; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl ForwardPipelineBuilder for RenderGraphBuilder { | impl ForwardPipelineBuilder for RenderGraphBuilder { | ||||||
|     fn add_forward_pipeline(self) -> Self { |     fn add_forward_pipeline(self, pipeline_descriptor_storage: &mut AssetStorage<PipelineDescriptor>, shader_storage: &mut AssetStorage<Shader>) -> Self { | ||||||
|         self.add_pipeline( |         self.add_pipeline( | ||||||
|             "forward", |             pipeline_descriptor_storage, | ||||||
|             PipelineDescriptor::build(Shader::from_glsl( |             PipelineDescriptor::build( | ||||||
|                 include_str!("forward.vert"), |                 shader_storage, | ||||||
|                 ShaderStage::Vertex, |                 Shader::from_glsl(include_str!("forward.vert"), ShaderStage::Vertex), | ||||||
|             )) |             ) | ||||||
|             .with_fragment_shader(Shader::from_glsl( |             .with_fragment_shader(Shader::from_glsl( | ||||||
|                 include_str!("forward.frag"), |                 include_str!("forward.frag"), | ||||||
|                 ShaderStage::Fragment, |                 ShaderStage::Fragment, | ||||||
|  | |||||||
| @ -1,22 +1,35 @@ | |||||||
| use crate::render::{ | use crate::{ | ||||||
|  |     asset::AssetStorage, | ||||||
|  |     render::{ | ||||||
|         render_graph_2::{ |         render_graph_2::{ | ||||||
|         draw_targets::mesh_draw_target, pipeline_layout::*, PipelineDescriptor, RenderGraphBuilder, |             draw_targets::mesh_draw_target, pipeline_layout::*, PipelineDescriptor, | ||||||
|  |             RenderGraphBuilder, | ||||||
|         }, |         }, | ||||||
|         shader::{Shader, ShaderStage}, |         shader::{Shader, ShaderStage}, | ||||||
|         Vertex, |         Vertex, | ||||||
|  |     }, | ||||||
| }; | }; | ||||||
|  | 
 | ||||||
| pub trait ForwardFlatPipelineBuilder { | pub trait ForwardFlatPipelineBuilder { | ||||||
|     fn add_forward_flat_pipeline(self) -> Self; |     fn add_forward_flat_pipeline( | ||||||
|  |         self, | ||||||
|  |         pipeline_descriptor_storage: &mut AssetStorage<PipelineDescriptor>, | ||||||
|  |         shader_storage: &mut AssetStorage<Shader>, | ||||||
|  |     ) -> Self; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl ForwardFlatPipelineBuilder for RenderGraphBuilder { | impl ForwardFlatPipelineBuilder for RenderGraphBuilder { | ||||||
|     fn add_forward_flat_pipeline(self) -> Self { |     fn add_forward_flat_pipeline( | ||||||
|  |         self, | ||||||
|  |         pipeline_descriptor_storage: &mut AssetStorage<PipelineDescriptor>, | ||||||
|  |         shader_storage: &mut AssetStorage<Shader>, | ||||||
|  |     ) -> Self { | ||||||
|         self.add_pipeline( |         self.add_pipeline( | ||||||
|             "forward_flat", |             pipeline_descriptor_storage, | ||||||
|             PipelineDescriptor::build(Shader::from_glsl( |             PipelineDescriptor::build( | ||||||
|                 include_str!("forward_flat.vert"), |                 shader_storage, | ||||||
|                 ShaderStage::Vertex, |                 Shader::from_glsl(include_str!("forward_flat.vert"), ShaderStage::Vertex), | ||||||
|             )) |             ) | ||||||
|             .with_fragment_shader(Shader::from_glsl( |             .with_fragment_shader(Shader::from_glsl( | ||||||
|                 include_str!("forward_flat.frag"), |                 include_str!("forward_flat.frag"), | ||||||
|                 ShaderStage::Fragment, |                 ShaderStage::Fragment, | ||||||
|  | |||||||
| @ -1,23 +1,34 @@ | |||||||
| use crate::render::{ | use crate::{ | ||||||
|  |     asset::AssetStorage, | ||||||
|  |     render::{ | ||||||
|         render_graph_2::{ |         render_graph_2::{ | ||||||
|             draw_targets::ui_draw_target, pipeline_layout::*, resource_providers::RectData, |             draw_targets::ui_draw_target, pipeline_layout::*, resource_providers::RectData, | ||||||
|             PipelineDescriptor, RenderGraphBuilder, VertexBufferDescriptor, |             PipelineDescriptor, RenderGraphBuilder, VertexBufferDescriptor, | ||||||
|         }, |         }, | ||||||
|         shader::{Shader, ShaderStage}, |         shader::{Shader, ShaderStage}, | ||||||
|         Vertex, |         Vertex, | ||||||
|  |     }, | ||||||
| }; | }; | ||||||
| pub trait UiPipelineBuilder { | pub trait UiPipelineBuilder { | ||||||
|     fn add_ui_pipeline(self) -> Self; |     fn add_ui_pipeline( | ||||||
|  |         self, | ||||||
|  |         pipeline_descriptor_storage: &mut AssetStorage<PipelineDescriptor>, | ||||||
|  |         shader_storage: &mut AssetStorage<Shader>, | ||||||
|  |     ) -> Self; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl UiPipelineBuilder for RenderGraphBuilder { | impl UiPipelineBuilder for RenderGraphBuilder { | ||||||
|     fn add_ui_pipeline(self) -> Self { |     fn add_ui_pipeline( | ||||||
|  |         self, | ||||||
|  |         pipeline_descriptor_storage: &mut AssetStorage<PipelineDescriptor>, | ||||||
|  |         shader_storage: &mut AssetStorage<Shader>, | ||||||
|  |     ) -> Self { | ||||||
|         self.add_pipeline( |         self.add_pipeline( | ||||||
|             "ui", |             pipeline_descriptor_storage, | ||||||
|             PipelineDescriptor::build(Shader::from_glsl( |             PipelineDescriptor::build( | ||||||
|                 include_str!("ui.vert"), |                 shader_storage, | ||||||
|                 ShaderStage::Vertex, |                 Shader::from_glsl(include_str!("ui.vert"), ShaderStage::Vertex), | ||||||
|             )) |             ) | ||||||
|             .with_fragment_shader(Shader::from_glsl( |             .with_fragment_shader(Shader::from_glsl( | ||||||
|                 include_str!("ui.frag"), |                 include_str!("ui.frag"), | ||||||
|                 ShaderStage::Fragment, |                 ShaderStage::Fragment, | ||||||
|  | |||||||
| @ -1,13 +1,16 @@ | |||||||
| use crate::render::render_graph_2::{ | use crate::{ | ||||||
|     PassDescriptor, PipelineDescriptor, ResourceProvider, TextureDescriptor, |     asset::{AssetStorage, Handle}, | ||||||
|  |     render::{ | ||||||
|  |         render_graph_2::{PassDescriptor, PipelineDescriptor, ResourceProvider, TextureDescriptor}, | ||||||
|  |     }, | ||||||
| }; | }; | ||||||
| use std::collections::HashMap; | use std::collections::{HashMap, HashSet}; | ||||||
| 
 | 
 | ||||||
| pub struct RenderGraph { | pub struct RenderGraph { | ||||||
|     pub pipeline_descriptors: HashMap<String, PipelineDescriptor>, |     pub pipeline_descriptors: HashSet<Handle<PipelineDescriptor>>, | ||||||
|     // TODO: make this ordered
 |     // TODO: make this ordered
 | ||||||
|     pub pass_descriptors: HashMap<String, PassDescriptor>, |     pub pass_descriptors: HashMap<String, PassDescriptor>, | ||||||
|     pub pass_pipelines: HashMap<String, Vec<String>>, |     pub pass_pipelines: HashMap<String, Vec<Handle<PipelineDescriptor>>>, | ||||||
|     pub resource_providers: Vec<Box<dyn ResourceProvider>>, |     pub resource_providers: Vec<Box<dyn ResourceProvider>>, | ||||||
|     pub queued_textures: Vec<(String, TextureDescriptor)>, |     pub queued_textures: Vec<(String, TextureDescriptor)>, | ||||||
| } | } | ||||||
| @ -15,7 +18,7 @@ pub struct RenderGraph { | |||||||
| impl Default for RenderGraph { | impl Default for RenderGraph { | ||||||
|     fn default() -> Self { |     fn default() -> Self { | ||||||
|         RenderGraph { |         RenderGraph { | ||||||
|             pipeline_descriptors: HashMap::new(), |             pipeline_descriptors: HashSet::new(), | ||||||
|             pass_descriptors: HashMap::new(), |             pass_descriptors: HashMap::new(), | ||||||
|             pass_pipelines: HashMap::new(), |             pass_pipelines: HashMap::new(), | ||||||
|             resource_providers: Vec::new(), |             resource_providers: Vec::new(), | ||||||
| @ -24,9 +27,23 @@ impl Default for RenderGraph { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | impl RenderGraph { | ||||||
|  |     pub fn add_pipeline(&mut self, pass: &str, pipeline: Handle<PipelineDescriptor>) { | ||||||
|  |         self.pipeline_descriptors.insert(pipeline.clone()); | ||||||
|  | 
 | ||||||
|  |         if let None = self.pass_pipelines.get(pass) { | ||||||
|  |             self.pass_pipelines.insert(pass.to_string(), Vec::new()); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         let pass_pipelines = self.pass_pipelines.get_mut(pass).unwrap(); | ||||||
|  |         pass_pipelines.push(pipeline); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| pub struct RenderGraphBuilder { | pub struct RenderGraphBuilder { | ||||||
|     render_graph: RenderGraph, |     render_graph: RenderGraph, | ||||||
|     current_pass: Option<String>, |     current_pass: Option<String>, | ||||||
|  | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl RenderGraphBuilder { | impl RenderGraphBuilder { | ||||||
| @ -45,24 +62,10 @@ impl RenderGraphBuilder { | |||||||
|         self |         self | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn add_pipeline(mut self, name: &str, pipeline: PipelineDescriptor) -> Self { |     pub fn add_pipeline(mut self, pipeline_descriptor_storage: &mut AssetStorage<PipelineDescriptor>, pipeline: PipelineDescriptor) -> Self { | ||||||
|         self.render_graph |         if let Some(ref pass) = self.current_pass { | ||||||
|             .pipeline_descriptors |             let pipeline_descriptor_handle = pipeline_descriptor_storage.add(pipeline); | ||||||
|             .insert(name.to_string(), pipeline); |             self.render_graph.add_pipeline(&pass, pipeline_descriptor_handle); | ||||||
| 
 |  | ||||||
|         if let Some(current_pass) = self.current_pass.as_ref() { |  | ||||||
|             if let None = self.render_graph.pass_pipelines.get(current_pass) { |  | ||||||
|                 self.render_graph |  | ||||||
|                     .pass_pipelines |  | ||||||
|                     .insert(current_pass.to_string(), Vec::new()); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             let pass_pipelines = self |  | ||||||
|                 .render_graph |  | ||||||
|                 .pass_pipelines |  | ||||||
|                 .get_mut(current_pass) |  | ||||||
|                 .unwrap(); |  | ||||||
|             pass_pipelines.push(name.to_string()); |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         self |         self | ||||||
|  | |||||||
| @ -1,13 +1,14 @@ | |||||||
| use crate::{ | use crate::{ | ||||||
|     asset::{AssetStorage, Handle}, |     asset::{AssetStorage, Handle}, | ||||||
|     render::{render_graph_2::RenderGraph, Shader}, |     render::{render_graph_2::RenderGraph, Shader, ShaderStages}, | ||||||
| }; | }; | ||||||
| use legion::prelude::*; | use legion::prelude::*; | ||||||
| use std::collections::{HashMap, HashSet}; | use std::collections::{HashMap, HashSet}; | ||||||
|  | use super::PipelineDescriptor; | ||||||
| 
 | 
 | ||||||
| pub struct Renderable { | pub struct Renderable { | ||||||
|     pub is_visible: bool, |     pub is_visible: bool, | ||||||
|     pub shaders: Vec<Handle<Shader>>, |     pub pipelines: Vec<Handle<PipelineDescriptor>>, | ||||||
|     pub shader_defs: HashSet<String>, |     pub shader_defs: HashSet<String>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -15,7 +16,7 @@ impl Default for Renderable { | |||||||
|     fn default() -> Self { |     fn default() -> Self { | ||||||
|         Renderable { |         Renderable { | ||||||
|             is_visible: true, |             is_visible: true, | ||||||
|             shaders: Vec::new(), |             pipelines: Vec::new(), | ||||||
|             shader_defs: HashSet::new(), |             shader_defs: HashSet::new(), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -53,20 +54,23 @@ pub fn update_shader_assignments(world: &mut World, render_graph: &mut RenderGra | |||||||
|         let shader_assignments = world.resources.get_mut::<ShaderAssignments>().unwrap(); |         let shader_assignments = world.resources.get_mut::<ShaderAssignments>().unwrap(); | ||||||
|         let mut compiled_shader_map = world.resources.get_mut::<CompiledShaderMap>().unwrap(); |         let mut compiled_shader_map = world.resources.get_mut::<CompiledShaderMap>().unwrap(); | ||||||
|         let mut shader_storage = world.resources.get_mut::<AssetStorage<Shader>>().unwrap(); |         let mut shader_storage = world.resources.get_mut::<AssetStorage<Shader>>().unwrap(); | ||||||
|  |         let pipeline_descriptor_storage = world.resources.get_mut::<AssetStorage<PipelineDescriptor>>().unwrap(); | ||||||
|         for (entity, renderable) in <Read<Renderable>>::query().iter_entities(world) { |         for (entity, renderable) in <Read<Renderable>>::query().iter_entities(world) { | ||||||
|             for shader in renderable.shaders.iter() { |             for pipeline_handle in renderable.pipelines.iter() { | ||||||
|                 if let None = compiled_shader_map.source_to_compiled.get(shader) { |                 let pipeline_descriptor = pipeline_descriptor_storage.get(pipeline_handle).unwrap(); | ||||||
|  |                 for shader_handle in pipeline_descriptor.shader_stages.iter() { | ||||||
|  |                     if let None = compiled_shader_map.source_to_compiled.get(shader_handle) { | ||||||
|                         compiled_shader_map |                         compiled_shader_map | ||||||
|                             .source_to_compiled |                             .source_to_compiled | ||||||
|                         .insert(shader.clone(), Vec::new()); |                             .insert(shader_handle.clone(), Vec::new()); | ||||||
|                     } |                     } | ||||||
| 
 | 
 | ||||||
|                 let compiled_shaders = compiled_shader_map.source_to_compiled.get_mut(shader).unwrap(); |                     let compiled_shaders = compiled_shader_map.source_to_compiled.get_mut(shader_handle).unwrap(); | ||||||
|                     if let None = compiled_shaders.iter().find(|(shader_defs, _shader)| *shader_defs == renderable.shader_defs) { |                     if let None = compiled_shaders.iter().find(|(shader_defs, _shader)| *shader_defs == renderable.shader_defs) { | ||||||
|                     let shader_resource = shader_storage.get(shader).unwrap(); |                         let shader_resource = shader_storage.get(shader_handle).unwrap(); | ||||||
|                         let shader_def_vec = renderable.shader_defs.iter().cloned().collect::<Vec<String>>(); |                         let shader_def_vec = renderable.shader_defs.iter().cloned().collect::<Vec<String>>(); | ||||||
|                         let compiled_shader = shader_resource.get_spirv_shader(Some(&shader_def_vec)); |                         let compiled_shader = shader_resource.get_spirv_shader(Some(&shader_def_vec)); | ||||||
|                     compiled_shaders.push((renderable.shader_defs.clone(), shader.clone())); |                         compiled_shaders.push((renderable.shader_defs.clone(), shader_handle.clone())); | ||||||
|                         let compiled_shader_handle = shader_storage.add(compiled_shader); |                         let compiled_shader_handle = shader_storage.add(compiled_shader); | ||||||
|                         // TODO: collecting assigments in a map means they won't be removed when the macro changes
 |                         // TODO: collecting assigments in a map means they won't be removed when the macro changes
 | ||||||
|                         // TODO: need to somehow grab base shader's pipeline, then copy it 
 |                         // TODO: need to somehow grab base shader's pipeline, then copy it 
 | ||||||
| @ -75,6 +79,7 @@ pub fn update_shader_assignments(world: &mut World, render_graph: &mut RenderGra | |||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     // cleanup entity shader_defs so next frame they can be refreshed
 |     // cleanup entity shader_defs so next frame they can be refreshed
 | ||||||
|     for mut renderable in <Write<Renderable>>::query().iter_mut(world) { |     for mut renderable in <Write<Renderable>>::query().iter_mut(world) { | ||||||
|  | |||||||
| @ -1,11 +1,15 @@ | |||||||
| use crate::{ | use crate::{ | ||||||
|  |     asset::{AssetStorage, Handle}, | ||||||
|     legion::prelude::*, |     legion::prelude::*, | ||||||
|     render::{Shader, render_graph_2::{ |     render::{ | ||||||
|         resource_name, update_shader_assignments, BindGroup, BindType, DynamicUniformBufferInfo, |         render_graph_2::{ | ||||||
|         PassDescriptor, PipelineDescriptor, RenderGraph, RenderPass, |             resource_name, update_shader_assignments, BindGroup, BindType, | ||||||
|         RenderPassColorAttachmentDescriptor, RenderPassDepthStencilAttachmentDescriptor, Renderer, |             DynamicUniformBufferInfo, PassDescriptor, PipelineDescriptor, RenderGraph, RenderPass, | ||||||
|         ResourceInfo, ShaderUniforms, TextureDescriptor, |             RenderPassColorAttachmentDescriptor, RenderPassDepthStencilAttachmentDescriptor, | ||||||
|     }}, |             Renderer, ResourceInfo, TextureDescriptor, | ||||||
|  |         }, | ||||||
|  |         Shader, | ||||||
|  |     }, | ||||||
| }; | }; | ||||||
| use std::{collections::HashMap, ops::Deref}; | use std::{collections::HashMap, ops::Deref}; | ||||||
| 
 | 
 | ||||||
| @ -15,7 +19,7 @@ pub struct WgpuRenderer { | |||||||
|     pub surface: Option<wgpu::Surface>, |     pub surface: Option<wgpu::Surface>, | ||||||
|     pub encoder: Option<wgpu::CommandEncoder>, |     pub encoder: Option<wgpu::CommandEncoder>, | ||||||
|     pub swap_chain_descriptor: wgpu::SwapChainDescriptor, |     pub swap_chain_descriptor: wgpu::SwapChainDescriptor, | ||||||
|     pub render_pipelines: HashMap<String, wgpu::RenderPipeline>, |     pub render_pipelines: HashMap<Handle<PipelineDescriptor>, wgpu::RenderPipeline>, | ||||||
|     pub buffers: HashMap<String, wgpu::Buffer>, |     pub buffers: HashMap<String, wgpu::Buffer>, | ||||||
|     pub textures: HashMap<String, wgpu::TextureView>, |     pub textures: HashMap<String, wgpu::TextureView>, | ||||||
|     pub resource_info: HashMap<String, ResourceInfo>, |     pub resource_info: HashMap<String, ResourceInfo>, | ||||||
| @ -69,12 +73,14 @@ impl WgpuRenderer { | |||||||
|         pipeline_descriptor: &mut PipelineDescriptor, |         pipeline_descriptor: &mut PipelineDescriptor, | ||||||
|         bind_group_layouts: &mut HashMap<u64, wgpu::BindGroupLayout>, |         bind_group_layouts: &mut HashMap<u64, wgpu::BindGroupLayout>, | ||||||
|         device: &wgpu::Device, |         device: &wgpu::Device, | ||||||
|  |         vertex_shader: &Shader, | ||||||
|  |         fragment_shader: Option<&Shader>, | ||||||
|     ) -> wgpu::RenderPipeline { |     ) -> wgpu::RenderPipeline { | ||||||
|         let vertex_shader_module = Self::create_shader_module(device, &pipeline_descriptor |         let vertex_shader_module = Self::create_shader_module(device, vertex_shader, None); | ||||||
|             .shader_stages |         let fragment_shader_module = match fragment_shader { | ||||||
|             .vertex, None); |             Some(fragment_shader) => { | ||||||
|         let fragment_shader_module = match pipeline_descriptor.shader_stages.fragment { |                 Some(Self::create_shader_module(device, fragment_shader, None)) | ||||||
|             Some(ref fragment_shader) => Some(Self::create_shader_module(device, fragment_shader, None)), |             } | ||||||
|             None => None, |             None => None, | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
| @ -121,10 +127,10 @@ impl WgpuRenderer { | |||||||
|             layout: &pipeline_layout, |             layout: &pipeline_layout, | ||||||
|             vertex_stage: wgpu::ProgrammableStageDescriptor { |             vertex_stage: wgpu::ProgrammableStageDescriptor { | ||||||
|                 module: &vertex_shader_module, |                 module: &vertex_shader_module, | ||||||
|                 entry_point: &pipeline_descriptor.shader_stages.vertex.entry_point, |                 entry_point: &vertex_shader.entry_point, | ||||||
|             }, |             }, | ||||||
|             fragment_stage: match pipeline_descriptor.shader_stages.fragment { |             fragment_stage: match fragment_shader { | ||||||
|                 Some(ref fragment_shader) => Some(wgpu::ProgrammableStageDescriptor { |                 Some(fragment_shader) => Some(wgpu::ProgrammableStageDescriptor { | ||||||
|                     entry_point: &fragment_shader.entry_point, |                     entry_point: &fragment_shader.entry_point, | ||||||
|                     module: fragment_shader_module.as_ref().unwrap(), |                     module: fragment_shader_module.as_ref().unwrap(), | ||||||
|                 }), |                 }), | ||||||
| @ -303,115 +309,11 @@ impl WgpuRenderer { | |||||||
|         bind_group_id |         bind_group_id | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // TODO: remove me
 |     pub fn create_shader_module( | ||||||
|     #[allow(dead_code)] |         device: &wgpu::Device, | ||||||
|     fn setup_dynamic_entity_shader_uniforms( |         shader: &Shader, | ||||||
|         &mut self, |         macros: Option<&[String]>, | ||||||
|         world: &World, |     ) -> wgpu::ShaderModule { | ||||||
|         render_graph: &RenderGraph, |  | ||||||
|         encoder: &mut wgpu::CommandEncoder, |  | ||||||
|     ) { |  | ||||||
|         // retrieve all uniforms buffers that aren't aleady set. these are "dynamic" uniforms, which are set by the user in ShaderUniforms
 |  | ||||||
|         // TODO: this breaks down in multiple ways:
 |  | ||||||
|         // (1) resource_info will be set after the first run so this won't update.
 |  | ||||||
|         // (2) if we create new buffers, the old bind groups will be invalid
 |  | ||||||
|         for pipeline in render_graph.pipeline_descriptors.values() { |  | ||||||
|             for bind_group in pipeline.pipeline_layout.bind_groups.iter() { |  | ||||||
|                 for binding in bind_group.bindings.iter() { |  | ||||||
|                     // if let None = self.resource_info.get(&binding.name) {
 |  | ||||||
|                     if let BindType::Uniform { dynamic: true, .. } = &binding.bind_type { |  | ||||||
|                         if self.dynamic_uniform_buffer_info.contains_key(&binding.name) { |  | ||||||
|                             continue; |  | ||||||
|                         } |  | ||||||
| 
 |  | ||||||
|                         self.dynamic_uniform_buffer_info.insert( |  | ||||||
|                             binding.name.to_string(), |  | ||||||
|                             DynamicUniformBufferInfo { |  | ||||||
|                                 capacity: 0, |  | ||||||
|                                 count: 0, |  | ||||||
|                                 size: binding.bind_type.get_uniform_size().unwrap(), |  | ||||||
|                                 indices: HashMap::new(), |  | ||||||
|                                 offsets: HashMap::new(), |  | ||||||
|                             }, |  | ||||||
|                         ); |  | ||||||
|                     } |  | ||||||
|                     // }
 |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // count the number of entities providing each uniform
 |  | ||||||
|         for (name, info) in self.dynamic_uniform_buffer_info.iter_mut() { |  | ||||||
|             info.count = 0; |  | ||||||
|             for (entity, shader_uniforms) in <Read<ShaderUniforms>>::query().iter_entities(world) { |  | ||||||
|                 if let Some(_) = shader_uniforms.get_uniform_info(world, entity, name) { |  | ||||||
|                     info.count += 1; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // allocate uniform buffers
 |  | ||||||
|         for (name, info) in self.dynamic_uniform_buffer_info.iter_mut() { |  | ||||||
|             if self.buffers.contains_key(name) && info.count < info.capacity { |  | ||||||
|                 continue; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             if info.count >= info.capacity && info.capacity != 0 { |  | ||||||
|                 panic!("resizing dynamic uniform buffers isn't supported yet. we still need to support updating bind groups"); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             // allocate enough space for twice as many entities as there are currently;
 |  | ||||||
|             info.capacity = info.count * 2; |  | ||||||
|             let size = wgpu::BIND_BUFFER_ALIGNMENT * info.capacity; |  | ||||||
| 
 |  | ||||||
|             // TODO: remove this code duplication in favor of self.create_buffer(). this will likely require a refactor
 |  | ||||||
|             // the following is a flattening of the content in self.create_buffer(), which can't be called because
 |  | ||||||
|             // of rust's ownership rules. sometimes rust makes me unhappy
 |  | ||||||
| 
 |  | ||||||
|             let buffer_usage = wgpu::BufferUsage::COPY_DST | wgpu::BufferUsage::UNIFORM; |  | ||||||
|             let buffer = self.device.create_buffer(&wgpu::BufferDescriptor { |  | ||||||
|                 size, |  | ||||||
|                 usage: buffer_usage, |  | ||||||
|             }); |  | ||||||
| 
 |  | ||||||
|             self.resource_info.insert( |  | ||||||
|                 name.to_string(), |  | ||||||
|                 ResourceInfo::Buffer { buffer_usage, size }, |  | ||||||
|             ); |  | ||||||
| 
 |  | ||||||
|             self.buffers.insert(name.to_string(), buffer); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // copy entity uniform data to buffers
 |  | ||||||
|         for (name, info) in self.dynamic_uniform_buffer_info.iter_mut() { |  | ||||||
|             let size = wgpu::BIND_BUFFER_ALIGNMENT * info.count; |  | ||||||
|             let mapped = self |  | ||||||
|                 .device |  | ||||||
|                 .create_buffer_mapped(size as usize, wgpu::BufferUsage::COPY_SRC); |  | ||||||
|             let alignment = wgpu::BIND_BUFFER_ALIGNMENT as usize; |  | ||||||
|             let mut offset = 0usize; |  | ||||||
| 
 |  | ||||||
|             for (i, (entity, shader_uniforms)) in <Read<ShaderUniforms>>::query() |  | ||||||
|                 .iter_entities(world) |  | ||||||
|                 .enumerate() |  | ||||||
|             { |  | ||||||
|                 // TODO: check if index has changed. if it has, then entity should be updated
 |  | ||||||
|                 // TODO: only mem-map entities if their data has changed
 |  | ||||||
|                 info.offsets.insert(entity, offset as u64); |  | ||||||
|                 info.indices.insert(i, entity); |  | ||||||
|                 if let Some(bytes) = shader_uniforms.get_uniform_bytes(world, entity, name) { |  | ||||||
|                     mapped.data[offset..(offset + bytes.len())].copy_from_slice(bytes.as_slice()); |  | ||||||
|                     offset += alignment; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             let temp_buffer = mapped.finish(); |  | ||||||
|             let uniform_buffer = self.buffers.get(name); |  | ||||||
|             encoder.copy_buffer_to_buffer(&temp_buffer, 0, uniform_buffer.unwrap(), 0, size); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     pub fn create_shader_module(device: &wgpu::Device, shader: &Shader, macros: Option<&[String]>) -> wgpu::ShaderModule { |  | ||||||
|         device.create_shader_module(&shader.get_spirv(macros)) |         device.create_shader_module(&shader.get_spirv(macros)) | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -489,16 +391,38 @@ impl Renderer for WgpuRenderer { | |||||||
|         // self.setup_dynamic_entity_shader_uniforms(world, render_graph, &mut encoder);
 |         // self.setup_dynamic_entity_shader_uniforms(world, render_graph, &mut encoder);
 | ||||||
| 
 | 
 | ||||||
|         // setup, pipelines, bind groups, and resources
 |         // setup, pipelines, bind groups, and resources
 | ||||||
|         for (pipeline_name, pipeline_descriptor) in render_graph.pipeline_descriptors.iter_mut() { |         let mut pipeline_storage = world | ||||||
|  |             .resources | ||||||
|  |             .get_mut::<AssetStorage<PipelineDescriptor>>() | ||||||
|  |             .unwrap(); | ||||||
|  |         let shader_storage = world.resources.get::<AssetStorage<Shader>>().unwrap(); | ||||||
|  | 
 | ||||||
|  |         for pipeline_descriptor_handle in render_graph.pipeline_descriptors.iter() { | ||||||
|  |             let pipeline_descriptor = pipeline_storage | ||||||
|  |                 .get_mut(pipeline_descriptor_handle) | ||||||
|  |                 .unwrap(); | ||||||
|             // create pipelines
 |             // create pipelines
 | ||||||
|             if let None = self.render_pipelines.get(pipeline_name) { |             if !self | ||||||
|  |                 .render_pipelines | ||||||
|  |                 .contains_key(pipeline_descriptor_handle) | ||||||
|  |             { | ||||||
|  |                 let vertex_shader = shader_storage | ||||||
|  |                     .get(&pipeline_descriptor.shader_stages.vertex) | ||||||
|  |                     .unwrap(); | ||||||
|  |                 let fragment_shader = pipeline_descriptor | ||||||
|  |                     .shader_stages | ||||||
|  |                     .fragment | ||||||
|  |                     .as_ref() | ||||||
|  |                     .map(|handle| &*shader_storage.get(&handle).unwrap()); | ||||||
|                 let render_pipeline = WgpuRenderer::create_render_pipeline( |                 let render_pipeline = WgpuRenderer::create_render_pipeline( | ||||||
|                     pipeline_descriptor, |                     pipeline_descriptor, | ||||||
|                     &mut self.bind_group_layouts, |                     &mut self.bind_group_layouts, | ||||||
|                     &self.device, |                     &self.device, | ||||||
|  |                     vertex_shader, | ||||||
|  |                     fragment_shader, | ||||||
|                 ); |                 ); | ||||||
|                 self.render_pipelines |                 self.render_pipelines | ||||||
|                     .insert(pipeline_name.to_string(), render_pipeline); |                     .insert(pipeline_descriptor_handle.clone(), render_pipeline); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             // create bind groups
 |             // create bind groups
 | ||||||
| @ -512,9 +436,7 @@ impl Renderer for WgpuRenderer { | |||||||
|             let mut render_pass = self.create_render_pass(pass_descriptor, &mut encoder, &frame); |             let mut render_pass = self.create_render_pass(pass_descriptor, &mut encoder, &frame); | ||||||
|             if let Some(pass_pipelines) = render_graph.pass_pipelines.get(pass_name) { |             if let Some(pass_pipelines) = render_graph.pass_pipelines.get(pass_name) { | ||||||
|                 for pass_pipeline in pass_pipelines.iter() { |                 for pass_pipeline in pass_pipelines.iter() { | ||||||
|                     if let Some(pipeline_descriptor) = |                     let pipeline_descriptor = pipeline_storage.get(pass_pipeline).unwrap(); | ||||||
|                         render_graph.pipeline_descriptors.get(pass_pipeline) |  | ||||||
|                     { |  | ||||||
|                     let render_pipeline = self.render_pipelines.get(pass_pipeline).unwrap(); |                     let render_pipeline = self.render_pipelines.get(pass_pipeline).unwrap(); | ||||||
|                     render_pass.set_pipeline(render_pipeline); |                     render_pass.set_pipeline(render_pipeline); | ||||||
| 
 | 
 | ||||||
| @ -530,7 +452,6 @@ impl Renderer for WgpuRenderer { | |||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         let command_buffer = encoder.finish(); |         let command_buffer = encoder.finish(); | ||||||
|         self.queue.submit(&[command_buffer]); |         self.queue.submit(&[command_buffer]); | ||||||
|  | |||||||
| @ -1,3 +1,4 @@ | |||||||
|  | use crate::asset::Handle; | ||||||
| use std::marker::Copy; | use std::marker::Copy; | ||||||
| 
 | 
 | ||||||
| #[derive(Hash, Eq, PartialEq, Copy, Clone)] | #[derive(Hash, Eq, PartialEq, Copy, Clone)] | ||||||
| @ -69,9 +70,7 @@ impl Shader { | |||||||
|     pub fn get_spirv(&self, macros: Option<&[String]>) -> Vec<u32> { |     pub fn get_spirv(&self, macros: Option<&[String]>) -> Vec<u32> { | ||||||
|         match self.source { |         match self.source { | ||||||
|             ShaderSource::Spirv(ref bytes) => bytes.clone(), |             ShaderSource::Spirv(ref bytes) => bytes.clone(), | ||||||
|             ShaderSource::Glsl(ref source) => { |             ShaderSource::Glsl(ref source) => glsl_to_spirv(&source, self.stage, macros), | ||||||
|                 glsl_to_spirv(&source, self.stage, macros) |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -85,15 +84,44 @@ impl Shader { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub struct ShaderStages { | pub struct ShaderStages { | ||||||
|     pub vertex: Shader, |     pub vertex: Handle<Shader>, | ||||||
|     pub fragment: Option<Shader>, |     pub fragment: Option<Handle<Shader>>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl ShaderStages { | impl ShaderStages { | ||||||
|     pub fn new(vertex_shader: Shader) -> Self { |     pub fn new(vertex_shader: Handle<Shader>) -> Self { | ||||||
|         ShaderStages { |         ShaderStages { | ||||||
|             vertex: vertex_shader, |             vertex: vertex_shader, | ||||||
|             fragment: None, |             fragment: None, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     pub fn iter(&self) -> ShaderStagesIter { | ||||||
|  |         ShaderStagesIter { | ||||||
|  |             shader_stages: self, | ||||||
|  |             index: 0, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | pub struct ShaderStagesIter<'a> { | ||||||
|  |     pub shader_stages: &'a ShaderStages, | ||||||
|  |     pub index: usize, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl<'a> Iterator for ShaderStagesIter<'a> { | ||||||
|  |     type Item = &'a Handle<Shader>; | ||||||
|  |     fn next(&mut self) -> Option<&'a Handle<Shader>> { | ||||||
|  |         match self.index { | ||||||
|  |             0 => Some(&self.shader_stages.vertex), | ||||||
|  |             1 => { | ||||||
|  |                 if let Some(ref fragment) = self.shader_stages.fragment { | ||||||
|  |                     Some(fragment) | ||||||
|  |                 } else { | ||||||
|  |                     None | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             _ => None, | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Carter Anderson
						Carter Anderson