validate VertexBufferDescriptors and fill in blanks when possible
This commit is contained in:
		
							parent
							
								
									a4eed18800
								
							
						
					
					
						commit
						fb496a6172
					
				| @ -9,7 +9,6 @@ Here is the current list of planned features. All items are sorted in approximat | |||||||
|     * Textures |     * Textures | ||||||
|     * Physically based rendering |     * Physically based rendering | ||||||
|     * Skeletal animation |     * Skeletal animation | ||||||
|     * Macro to produce vertex buffer attributes (and maybe descriptors) from structs |  | ||||||
|     * Add runtime type safety to uniform bindings (and maybe compile time) |     * Add runtime type safety to uniform bindings (and maybe compile time) | ||||||
|     * Inject layout set/bindings into shader source so they don't need to be defined in-shader. Specify set / binding indices in resource providers? |     * Inject layout set/bindings into shader source so they don't need to be defined in-shader. Specify set / binding indices in resource providers? | ||||||
|     * Pull as much logic as possible from wgpu_renderer into a "render orchestrator" struct/trait |     * Pull as much logic as possible from wgpu_renderer into a "render orchestrator" struct/trait | ||||||
|  | |||||||
| @ -334,7 +334,11 @@ pub fn derive_uniforms(input: TokenStream) -> TokenStream { | |||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             fn get_vertex_buffer_descriptor() -> Option<&'static bevy::render::pipeline::VertexBufferDescriptor> { |             fn get_vertex_buffer_descriptor() -> Option<&'static bevy::render::pipeline::VertexBufferDescriptor> { | ||||||
|                 Some(&#vertex_buffer_descriptor_ident) |                 if #vertex_buffer_descriptor_ident.attributes.len() == 0 { | ||||||
|  |                     None | ||||||
|  |                 } else { | ||||||
|  |                     Some(&#vertex_buffer_descriptor_ident) | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     }) |     }) | ||||||
|  | |||||||
| @ -26,8 +26,6 @@ fn main() { | |||||||
|                             r#" |                             r#" | ||||||
|                                 #version 450 |                                 #version 450 | ||||||
|                                 layout(location = 0) in vec4 Vertex_Position; |                                 layout(location = 0) in vec4 Vertex_Position; | ||||||
|                                 layout(location = 1) in vec4 Vertex_Normal; |  | ||||||
|                                 layout(location = 2) in vec2 Vertex_Uv; |  | ||||||
|                                 layout(location = 0) out vec4 v_Position; |                                 layout(location = 0) out vec4 v_Position; | ||||||
|                                 layout(set = 0, binding = 0) uniform Camera { |                                 layout(set = 0, binding = 0) uniform Camera { | ||||||
|                                     mat4 ViewProj; |                                     mat4 ViewProj; | ||||||
|  | |||||||
| @ -6,6 +6,15 @@ pub trait GetBytes { | |||||||
|     fn get_bytes_ref(&self) -> Option<&[u8]>; |     fn get_bytes_ref(&self) -> Option<&[u8]>; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | impl GetBytes for f32 { | ||||||
|  |     fn get_bytes(&self) -> Vec<u8> { | ||||||
|  |         self.as_bytes().to_vec() | ||||||
|  |     } | ||||||
|  |     fn get_bytes_ref(&self) -> Option<&[u8]> { | ||||||
|  |         Some(self.as_bytes()) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| impl GetBytes for [f32; 2] { | impl GetBytes for [f32; 2] { | ||||||
|     fn get_bytes(&self) -> Vec<u8> { |     fn get_bytes(&self) -> Vec<u8> { | ||||||
|         self.as_bytes().to_vec() |         self.as_bytes().to_vec() | ||||||
|  | |||||||
| @ -8,6 +8,26 @@ pub struct VertexBufferDescriptor { | |||||||
|     pub attributes: Vec<VertexAttributeDescriptor>, |     pub attributes: Vec<VertexAttributeDescriptor>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | impl VertexBufferDescriptor { | ||||||
|  |     pub fn sync_with_descriptor(&mut self, descriptor: &VertexBufferDescriptor) { | ||||||
|  |         for attribute in self.attributes.iter_mut() { | ||||||
|  |             let descriptor_attribute = descriptor | ||||||
|  |                 .attributes | ||||||
|  |                 .iter() | ||||||
|  |                 .find(|a| a.name == attribute.name) | ||||||
|  |                 .unwrap_or_else(|| { | ||||||
|  |                     panic!( | ||||||
|  |                         "Encountered unsupported Vertex Buffer Attribute: {}", | ||||||
|  |                         attribute.name | ||||||
|  |                     ); | ||||||
|  |                 }); | ||||||
|  |             attribute.offset = descriptor_attribute.offset; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         self.stride = descriptor.stride; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] | #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] | ||||||
| pub enum InputStepMode { | pub enum InputStepMode { | ||||||
|     Vertex = 0, |     Vertex = 0, | ||||||
|  | |||||||
| @ -3,8 +3,11 @@ use crate::{ | |||||||
|     prelude::Renderable, |     prelude::Renderable, | ||||||
|     render::{ |     render::{ | ||||||
|         mesh::Mesh, |         mesh::Mesh, | ||||||
|  |         render_graph::RenderGraph, | ||||||
|         render_resource::{AssetBatchers, BufferInfo, BufferUsage, ResourceProvider}, |         render_resource::{AssetBatchers, BufferInfo, BufferUsage, ResourceProvider}, | ||||||
|         renderer::Renderer, |         renderer::Renderer, | ||||||
|  |         shader::AsUniforms, | ||||||
|  |         Vertex, | ||||||
|     }, |     }, | ||||||
| }; | }; | ||||||
| use legion::{filter::*, prelude::*}; | use legion::{filter::*, prelude::*}; | ||||||
| @ -39,6 +42,16 @@ impl MeshResourceProvider { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl ResourceProvider for MeshResourceProvider { | impl ResourceProvider for MeshResourceProvider { | ||||||
|  |     fn initialize( | ||||||
|  |         &mut self, | ||||||
|  |         _renderer: &mut dyn Renderer, | ||||||
|  |         _world: &mut World, | ||||||
|  |         resources: &Resources, | ||||||
|  |     ) { | ||||||
|  |         let mut render_graph = resources.get_mut::<RenderGraph>().unwrap(); | ||||||
|  |         render_graph.set_vertex_buffer_descriptor(Vertex::get_vertex_buffer_descriptor().cloned().unwrap()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     fn update(&mut self, renderer: &mut dyn Renderer, world: &mut World, resources: &Resources) { |     fn update(&mut self, renderer: &mut dyn Renderer, world: &mut World, resources: &Resources) { | ||||||
|         let mesh_storage = resources.get_mut::<AssetStorage<Mesh>>().unwrap(); |         let mesh_storage = resources.get_mut::<AssetStorage<Mesh>>().unwrap(); | ||||||
|         let mut asset_batchers = resources.get_mut::<AssetBatchers>().unwrap(); |         let mut asset_batchers = resources.get_mut::<AssetBatchers>().unwrap(); | ||||||
|  | |||||||
| @ -1,24 +1,32 @@ | |||||||
|  | use crate as bevy; | ||||||
| use crate::{ | use crate::{ | ||||||
|     ecs, |     ecs, | ||||||
|     prelude::Node, |     prelude::Node, | ||||||
|     render::{ |     render::{ | ||||||
|  |         render_graph::RenderGraph, | ||||||
|         render_resource::{ |         render_resource::{ | ||||||
|             resource_name, BufferArrayInfo, BufferInfo, BufferUsage, RenderResource, |             resource_name, BufferArrayInfo, BufferInfo, BufferUsage, RenderResource, | ||||||
|             ResourceProvider, |             ResourceProvider, | ||||||
|         }, |         }, | ||||||
|         renderer::Renderer, |         renderer::Renderer, | ||||||
|  |         shader::AsUniforms, | ||||||
|     }, |     }, | ||||||
| }; | }; | ||||||
|  | use bevy_derive::Uniforms; | ||||||
| use bevy_transform::prelude::Parent; | use bevy_transform::prelude::Parent; | ||||||
| use legion::prelude::*; | use legion::prelude::*; | ||||||
| use zerocopy::{AsBytes, FromBytes}; | use zerocopy::{AsBytes, FromBytes}; | ||||||
| 
 | 
 | ||||||
| #[repr(C)] | #[repr(C)] | ||||||
| #[derive(Clone, Copy, Debug, AsBytes, FromBytes)] | #[derive(Clone, Copy, Debug, AsBytes, FromBytes, Uniforms)] | ||||||
| pub struct RectData { | pub struct Rect { | ||||||
|  |     #[uniform(instance)] | ||||||
|     pub position: [f32; 2], |     pub position: [f32; 2], | ||||||
|  |     #[uniform(instance)] | ||||||
|     pub size: [f32; 2], |     pub size: [f32; 2], | ||||||
|  |     #[uniform(instance)] | ||||||
|     pub color: [f32; 4], |     pub color: [f32; 4], | ||||||
|  |     #[uniform(instance)] | ||||||
|     pub z_index: f32, |     pub z_index: f32, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -44,7 +52,7 @@ impl UiResourceProvider { | |||||||
|                 let mut add_data: Box<dyn FnMut(&World, Entity, ()) -> Option<()>> = |                 let mut add_data: Box<dyn FnMut(&World, Entity, ()) -> Option<()>> = | ||||||
|                     Box::new(|world, entity, _| { |                     Box::new(|world, entity, _| { | ||||||
|                         let node = world.get_component::<Node>(entity).unwrap(); |                         let node = world.get_component::<Node>(entity).unwrap(); | ||||||
|                         data.push(RectData { |                         data.push(Rect { | ||||||
|                             position: node.global_position.into(), |                             position: node.global_position.into(), | ||||||
|                             size: node.size.into(), |                             size: node.size.into(), | ||||||
|                             color: node.color.into(), |                             color: node.color.into(), | ||||||
| @ -69,7 +77,7 @@ impl UiResourceProvider { | |||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         let size = std::mem::size_of::<RectData>() as u64; |         let size = std::mem::size_of::<Rect>() as u64; | ||||||
|         let data_len = data.len() as u64; |         let data_len = data.len() as u64; | ||||||
| 
 | 
 | ||||||
|         if let Some(old_instance_buffer) = self.instance_buffer { |         if let Some(old_instance_buffer) = self.instance_buffer { | ||||||
| @ -102,8 +110,10 @@ impl ResourceProvider for UiResourceProvider { | |||||||
|         &mut self, |         &mut self, | ||||||
|         _renderer: &mut dyn Renderer, |         _renderer: &mut dyn Renderer, | ||||||
|         _world: &mut World, |         _world: &mut World, | ||||||
|         _resources: &Resources, |         resources: &Resources, | ||||||
|     ) { |     ) { | ||||||
|  |         let mut render_graph = resources.get_mut::<RenderGraph>().unwrap(); | ||||||
|  |         render_graph.set_vertex_buffer_descriptor(Rect::get_vertex_buffer_descriptor().cloned().unwrap()); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn update(&mut self, renderer: &mut dyn Renderer, world: &mut World, _resources: &Resources) { |     fn update(&mut self, renderer: &mut dyn Renderer, world: &mut World, _resources: &Resources) { | ||||||
|  | |||||||
| @ -444,7 +444,6 @@ where | |||||||
|         if let Some(vertex_buffer_descriptor) = vertex_buffer_descriptor { |         if let Some(vertex_buffer_descriptor) = vertex_buffer_descriptor { | ||||||
|             if let None = render_graph.get_vertex_buffer_descriptor(&vertex_buffer_descriptor.name) |             if let None = render_graph.get_vertex_buffer_descriptor(&vertex_buffer_descriptor.name) | ||||||
|             { |             { | ||||||
|                 println!("{:#?}", vertex_buffer_descriptor); |  | ||||||
|                 render_graph.set_vertex_buffer_descriptor(vertex_buffer_descriptor.clone()); |                 render_graph.set_vertex_buffer_descriptor(vertex_buffer_descriptor.clone()); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @ -461,13 +460,12 @@ where | |||||||
|         world: &mut World, |         world: &mut World, | ||||||
|         resources: &Resources, |         resources: &Resources, | ||||||
|     ) { |     ) { | ||||||
|  |         let mut render_graph = resources.get_mut::<RenderGraph>().unwrap(); | ||||||
|  |         self.initialize_vertex_buffer_descriptor(&mut render_graph); | ||||||
|         self.update(renderer, world, resources); |         self.update(renderer, world, resources); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn update(&mut self, renderer: &mut dyn Renderer, world: &mut World, resources: &Resources) { |     fn update(&mut self, renderer: &mut dyn Renderer, world: &mut World, resources: &Resources) { | ||||||
|         let mut render_graph = resources.get_mut::<RenderGraph>().unwrap(); |  | ||||||
|         self.initialize_vertex_buffer_descriptor(&mut render_graph); |  | ||||||
| 
 |  | ||||||
|         // TODO: this breaks down in multiple ways:
 |         // TODO: this breaks down in multiple ways:
 | ||||||
|         // (SOLVED 1) resource_info will be set after the first run so this won't update.
 |         // (SOLVED 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
 |         // (2) if we create new buffers, the old bind groups will be invalid
 | ||||||
|  | |||||||
| @ -67,10 +67,46 @@ impl WgpuRenderer { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     pub fn setup_vertex_buffer_descriptors( | ||||||
|  |         render_graph: &RenderGraph, | ||||||
|  |         vertex_spirv: &Shader, | ||||||
|  |         pipeline_descriptor: &PipelineDescriptor, | ||||||
|  |     ) -> Vec<OwnedWgpuVertexBufferDescriptor> { | ||||||
|  |         let mut reflected_vertex_layout = if pipeline_descriptor.reflect_vertex_buffer_descriptors { | ||||||
|  |             Some(vertex_spirv.reflect_layout().unwrap()) | ||||||
|  |         } else { | ||||||
|  |             None | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         let vertex_buffer_descriptors = if let Some(ref mut layout) = reflected_vertex_layout { | ||||||
|  |             for vertex_buffer_descriptor in layout.vertex_buffer_descriptors.iter_mut() { | ||||||
|  |                 if let Some(graph_descriptor) = | ||||||
|  |                     render_graph.get_vertex_buffer_descriptor(&vertex_buffer_descriptor.name) | ||||||
|  |                 { | ||||||
|  |                     vertex_buffer_descriptor.sync_with_descriptor(graph_descriptor); | ||||||
|  |                 } else { | ||||||
|  |                     panic!( | ||||||
|  |                         "Encountered unsupported Vertex Buffer: {}", | ||||||
|  |                         vertex_buffer_descriptor.name | ||||||
|  |                     ); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             &layout.vertex_buffer_descriptors | ||||||
|  |         } else { | ||||||
|  |             &pipeline_descriptor.vertex_buffer_descriptors | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         vertex_buffer_descriptors | ||||||
|  |             .iter() | ||||||
|  |             .map(|v| v.into()) | ||||||
|  |             .collect::<Vec<OwnedWgpuVertexBufferDescriptor>>() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     pub fn create_render_pipeline( |     pub fn create_render_pipeline( | ||||||
|         wgpu_resources: &mut WgpuResources, |         wgpu_resources: &mut WgpuResources, | ||||||
|         pipeline_descriptor: &mut PipelineDescriptor, |         pipeline_descriptor: &mut PipelineDescriptor, | ||||||
|         device: &wgpu::Device, |         device: &wgpu::Device, | ||||||
|  |         render_graph: &RenderGraph, | ||||||
|         vertex_shader: &Shader, |         vertex_shader: &Shader, | ||||||
|         fragment_shader: Option<&Shader>, |         fragment_shader: Option<&Shader>, | ||||||
|     ) -> wgpu::RenderPipeline { |     ) -> wgpu::RenderPipeline { | ||||||
| @ -166,22 +202,8 @@ impl WgpuRenderer { | |||||||
|             bind_group_layouts: bind_group_layouts.as_slice(), |             bind_group_layouts: bind_group_layouts.as_slice(), | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         let reflected_vertex_layout = if pipeline_descriptor.reflect_vertex_buffer_descriptors { |         let owned_vertex_buffer_descriptors = | ||||||
|             Some(vertex_spirv.reflect_layout().unwrap()) |             Self::setup_vertex_buffer_descriptors(render_graph, &vertex_spirv, pipeline_descriptor); | ||||||
|         } else { |  | ||||||
|             None |  | ||||||
|         }; |  | ||||||
| 
 |  | ||||||
|         let vertex_buffer_descriptors = if let Some(ref layout) = reflected_vertex_layout { |  | ||||||
|             &layout.vertex_buffer_descriptors |  | ||||||
|         } else { |  | ||||||
|             &pipeline_descriptor.vertex_buffer_descriptors |  | ||||||
|         }; |  | ||||||
| 
 |  | ||||||
|         let owned_vertex_buffer_descriptors = vertex_buffer_descriptors |  | ||||||
|             .iter() |  | ||||||
|             .map(|v| v.into()) |  | ||||||
|             .collect::<Vec<OwnedWgpuVertexBufferDescriptor>>(); |  | ||||||
| 
 | 
 | ||||||
|         let color_states = pipeline_descriptor |         let color_states = pipeline_descriptor | ||||||
|             .color_states |             .color_states | ||||||
| @ -462,6 +484,7 @@ impl Renderer for WgpuRenderer { | |||||||
|                     &mut self.wgpu_resources, |                     &mut self.wgpu_resources, | ||||||
|                     pipeline_descriptor, |                     pipeline_descriptor, | ||||||
|                     &self.device, |                     &self.device, | ||||||
|  |                     &render_graph, | ||||||
|                     vertex_shader, |                     vertex_shader, | ||||||
|                     fragment_shader, |                     fragment_shader, | ||||||
|                 ); |                 ); | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Carter Anderson
						Carter Anderson