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 | ||||
|     * Physically based rendering | ||||
|     * Skeletal animation | ||||
|     * Macro to produce vertex buffer attributes (and maybe descriptors) from structs | ||||
|     * 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? | ||||
|     * 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> { | ||||
|                 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#" | ||||
|                                 #version 450 | ||||
|                                 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(set = 0, binding = 0) uniform Camera { | ||||
|                                     mat4 ViewProj; | ||||
|  | ||||
| @ -6,6 +6,15 @@ pub trait GetBytes { | ||||
|     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] { | ||||
|     fn get_bytes(&self) -> Vec<u8> { | ||||
|         self.as_bytes().to_vec() | ||||
|  | ||||
| @ -8,6 +8,26 @@ pub struct VertexBufferDescriptor { | ||||
|     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)] | ||||
| pub enum InputStepMode { | ||||
|     Vertex = 0, | ||||
|  | ||||
| @ -3,8 +3,11 @@ use crate::{ | ||||
|     prelude::Renderable, | ||||
|     render::{ | ||||
|         mesh::Mesh, | ||||
|         render_graph::RenderGraph, | ||||
|         render_resource::{AssetBatchers, BufferInfo, BufferUsage, ResourceProvider}, | ||||
|         renderer::Renderer, | ||||
|         shader::AsUniforms, | ||||
|         Vertex, | ||||
|     }, | ||||
| }; | ||||
| use legion::{filter::*, prelude::*}; | ||||
| @ -39,6 +42,16 @@ impl 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) { | ||||
|         let mesh_storage = resources.get_mut::<AssetStorage<Mesh>>().unwrap(); | ||||
|         let mut asset_batchers = resources.get_mut::<AssetBatchers>().unwrap(); | ||||
|  | ||||
| @ -1,24 +1,32 @@ | ||||
| use crate as bevy; | ||||
| use crate::{ | ||||
|     ecs, | ||||
|     prelude::Node, | ||||
|     render::{ | ||||
|         render_graph::RenderGraph, | ||||
|         render_resource::{ | ||||
|             resource_name, BufferArrayInfo, BufferInfo, BufferUsage, RenderResource, | ||||
|             ResourceProvider, | ||||
|         }, | ||||
|         renderer::Renderer, | ||||
|         shader::AsUniforms, | ||||
|     }, | ||||
| }; | ||||
| use bevy_derive::Uniforms; | ||||
| use bevy_transform::prelude::Parent; | ||||
| use legion::prelude::*; | ||||
| use zerocopy::{AsBytes, FromBytes}; | ||||
| 
 | ||||
| #[repr(C)] | ||||
| #[derive(Clone, Copy, Debug, AsBytes, FromBytes)] | ||||
| pub struct RectData { | ||||
| #[derive(Clone, Copy, Debug, AsBytes, FromBytes, Uniforms)] | ||||
| pub struct Rect { | ||||
|     #[uniform(instance)] | ||||
|     pub position: [f32; 2], | ||||
|     #[uniform(instance)] | ||||
|     pub size: [f32; 2], | ||||
|     #[uniform(instance)] | ||||
|     pub color: [f32; 4], | ||||
|     #[uniform(instance)] | ||||
|     pub z_index: f32, | ||||
| } | ||||
| 
 | ||||
| @ -44,7 +52,7 @@ impl UiResourceProvider { | ||||
|                 let mut add_data: Box<dyn FnMut(&World, Entity, ()) -> Option<()>> = | ||||
|                     Box::new(|world, entity, _| { | ||||
|                         let node = world.get_component::<Node>(entity).unwrap(); | ||||
|                         data.push(RectData { | ||||
|                         data.push(Rect { | ||||
|                             position: node.global_position.into(), | ||||
|                             size: node.size.into(), | ||||
|                             color: node.color.into(), | ||||
| @ -69,7 +77,7 @@ impl UiResourceProvider { | ||||
|             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; | ||||
| 
 | ||||
|         if let Some(old_instance_buffer) = self.instance_buffer { | ||||
| @ -102,8 +110,10 @@ impl ResourceProvider for UiResourceProvider { | ||||
|         &mut self, | ||||
|         _renderer: &mut dyn Renderer, | ||||
|         _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) { | ||||
|  | ||||
| @ -444,7 +444,6 @@ where | ||||
|         if let Some(vertex_buffer_descriptor) = vertex_buffer_descriptor { | ||||
|             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()); | ||||
|             } | ||||
|         } | ||||
| @ -461,13 +460,12 @@ where | ||||
|         world: &mut World, | ||||
|         resources: &Resources, | ||||
|     ) { | ||||
|         let mut render_graph = resources.get_mut::<RenderGraph>().unwrap(); | ||||
|         self.initialize_vertex_buffer_descriptor(&mut render_graph); | ||||
|         self.update(renderer, world, 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:
 | ||||
|         // (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
 | ||||
|  | ||||
| @ -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( | ||||
|         wgpu_resources: &mut WgpuResources, | ||||
|         pipeline_descriptor: &mut PipelineDescriptor, | ||||
|         device: &wgpu::Device, | ||||
|         render_graph: &RenderGraph, | ||||
|         vertex_shader: &Shader, | ||||
|         fragment_shader: Option<&Shader>, | ||||
|     ) -> wgpu::RenderPipeline { | ||||
| @ -166,22 +202,8 @@ impl WgpuRenderer { | ||||
|             bind_group_layouts: bind_group_layouts.as_slice(), | ||||
|         }); | ||||
| 
 | ||||
|         let 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 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 owned_vertex_buffer_descriptors = | ||||
|             Self::setup_vertex_buffer_descriptors(render_graph, &vertex_spirv, pipeline_descriptor); | ||||
| 
 | ||||
|         let color_states = pipeline_descriptor | ||||
|             .color_states | ||||
| @ -462,6 +484,7 @@ impl Renderer for WgpuRenderer { | ||||
|                     &mut self.wgpu_resources, | ||||
|                     pipeline_descriptor, | ||||
|                     &self.device, | ||||
|                     &render_graph, | ||||
|                     vertex_shader, | ||||
|                     fragment_shader, | ||||
|                 ); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Carter Anderson
						Carter Anderson