From 35a9bf8783643ca61308cf862680ab6b077d4d87 Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Tue, 29 Sep 2020 01:25:47 +0200 Subject: [PATCH 01/32] first draft --- crates/bevy_render/src/draw.rs | 23 +-- crates/bevy_render/src/mesh/mesh.rs | 146 ++++++++++++------ .../src/pipeline/pipeline_layout.rs | 1 + .../src/pipeline/vertex_buffer_descriptor.rs | 8 +- .../render_resource_bindings.rs | 32 ++-- .../bevy_render/src/shader/shader_reflect.rs | 57 +++---- 6 files changed, 164 insertions(+), 103 deletions(-) diff --git a/crates/bevy_render/src/draw.rs b/crates/bevy_render/src/draw.rs index a54db24fcee3c..69d1ebf188a6a 100644 --- a/crates/bevy_render/src/draw.rs +++ b/crates/bevy_render/src/draw.rs @@ -121,6 +121,8 @@ pub enum DrawError { PipelineHasNoLayout, #[error("Failed to get a buffer for the given RenderResource.")] BufferAllocationFailure, + #[error("Could not get buffer for Vertex Attribute")] + NoBufferForVertexAttribute, } pub struct DrawContext<'a> { @@ -350,21 +352,24 @@ impl<'a> DrawContext<'a> { let layout = pipeline_descriptor .get_layout() .ok_or(DrawError::PipelineHasNoLayout)?; + + println!("{:?}", layout.vertex_buffer_descriptors); for (slot, vertex_buffer_descriptor) in layout.vertex_buffer_descriptors.iter().enumerate() { + println!("trying to get buffer for slot {} -> {}", slot, &vertex_buffer_descriptor.name); for bindings in render_resource_bindings.iter() { - if let Some((vertex_buffer, index_buffer)) = - bindings.get_vertex_buffer(&vertex_buffer_descriptor.name) - { - draw.set_vertex_buffer(slot as u32, vertex_buffer, 0); - if let Some(index_buffer) = index_buffer { - draw.set_index_buffer(index_buffer, 0); - } - - break; + println!("\t binding {:?}", &bindings.id); + // TODO: fix this, it is setting the buffer multiply times + for vertex_buffer in &bindings.vertex_buffers{ + println!("\t \t set slot{:?}", &vertex_buffer.0); + draw.set_vertex_buffer(vertex_buffer.0.clone() as u32 - 1, vertex_buffer.1.clone(), 0); + } + if let Some(index_buffer) = bindings.index_buffer{ + draw.set_index_buffer(index_buffer, 0); } } } + println!("done with vertex_buffer_descriptors"); Ok(()) } } diff --git a/crates/bevy_render/src/mesh/mesh.rs b/crates/bevy_render/src/mesh/mesh.rs index 5f631f202f23e..964f1da73acea 100644 --- a/crates/bevy_render/src/mesh/mesh.rs +++ b/crates/bevy_render/src/mesh/mesh.rs @@ -14,9 +14,13 @@ use bevy_math::*; use bevy_utils::HashSet; use std::borrow::Cow; use thiserror::Error; +use crate::pipeline::VertexAttributeDescriptor; +use downcast_rs::Downcast; -pub const VERTEX_BUFFER_ASSET_INDEX: usize = 0; -pub const INDEX_BUFFER_ASSET_INDEX: usize = 1; +use crate::pipeline::InputStepMode; + +pub const VERTEX_BUFFER_ASSET_INDEX: usize = 1; +pub const INDEX_BUFFER_ASSET_INDEX: usize = 0; #[derive(Clone, Debug)] pub enum VertexAttributeValues { Float(Vec), @@ -127,6 +131,15 @@ impl Mesh { indices: None, } } + // pub fn get_vertex_attribute_bytes( + // &self, + // fill_missing_attributes: bool, + // attribute_index: u32, + // ) -> Result, MeshToVertexBufferError>{ + // let attribute + // let mut bytes = vec![0; vertex_buffer_descriptor.stride as usize]; + // + // } pub fn get_vertex_buffer_bytes( &self, @@ -502,16 +515,55 @@ pub fn mesh_resource_provider_system( mesh_events: Res>>, mut query: Query<(&Handle, &mut RenderPipelines)>, ) { - let vertex_buffer_descriptor = match state.vertex_buffer_descriptor { - Some(value) => value, - None => { - // TODO: allow pipelines to specialize on vertex_buffer_descriptor and index_format - let vertex_buffer_descriptor = Vertex::as_vertex_buffer_descriptor(); - vertex_buffer_descriptors.set(vertex_buffer_descriptor.clone()); - state.vertex_buffer_descriptor = Some(vertex_buffer_descriptor); - vertex_buffer_descriptor - } - }; + if state.vertex_buffer_descriptor.is_none() { + // TODO: allow pipelines to specialize on vertex_buffer_descriptor and index_format + let mut vertex_buffer_descriptors_: VertexBufferDescriptors = VertexBufferDescriptors{ + descriptors: Default::default() + }; + + // TODO: kinda messy + vertex_buffer_descriptors_.descriptors.insert( + "Vertex_Position".to_string(), + VertexBufferDescriptor{ + name: "Vertex_Position".into(), + stride: VertexFormat::Float3.get_size(), + step_mode: InputStepMode::Vertex, + attributes: vec![VertexAttributeDescriptor{ + name: "Vertex_Position".into(), + offset: 0, + format: VertexFormat::Float3, + shader_location: 0 + }] + }); + vertex_buffer_descriptors_.descriptors.insert( + "Vertex_Normal".to_string(), + VertexBufferDescriptor{ + name: "Vertex_Normal".into(), + stride: VertexFormat::Float3.get_size(), + step_mode: InputStepMode::Vertex, + attributes: vec![VertexAttributeDescriptor{ + name: "Vertex_Normal".into(), + offset: 0, + format: VertexFormat::Float3, + shader_location: 0 + }] + }); + vertex_buffer_descriptors_.descriptors.insert( + "Vertex_Uv".to_string(), + VertexBufferDescriptor{ + name: "Vertex_Uv".into(), + stride: VertexFormat::Float2.get_size(), + step_mode: InputStepMode::Vertex, + attributes: vec![VertexAttributeDescriptor{ + name: "Vertex_Uv".into(), + offset: 0, + format: VertexFormat::Float2, + shader_location: 0 + }] + }); + vertex_buffer_descriptors.set_many(vertex_buffer_descriptors_); + } + let mut changed_meshes = HashSet::>::default(); let render_resource_context = &**render_resource_context; for event in state.mesh_event_reader.iter(&mesh_events) { @@ -534,32 +586,35 @@ pub fn mesh_resource_provider_system( for changed_mesh_handle in changed_meshes.iter() { if let Some(mesh) = meshes.get(changed_mesh_handle) { - let vertex_bytes = mesh - .get_vertex_buffer_bytes(&vertex_buffer_descriptor, true) - .unwrap(); - // TODO: use a staging buffer here - let vertex_buffer = render_resource_context.create_buffer_with_data( - BufferInfo { - buffer_usage: BufferUsage::VERTEX, - ..Default::default() - }, - &vertex_bytes, - ); - let index_bytes = mesh.get_index_buffer_bytes().unwrap(); + let mut index = 1; // index 0 is reserved by INDEX_BUFFER_ASSET_INDEX + for attribute in &mesh.attributes{ + println!("insert index vertex buffer index {}", index); + // TODO: use a staging buffer here + let attribute_buffer = render_resource_context.create_buffer_with_data( + BufferInfo { + buffer_usage: BufferUsage::VERTEX, + ..Default::default() + }, + &attribute.values.get_bytes(), + ); + + render_resource_context.set_asset_resource( + *changed_mesh_handle, + RenderResourceId::Buffer(attribute_buffer), + index, + ); + index += 1; + } + let index_buffer = render_resource_context.create_buffer_with_data( BufferInfo { buffer_usage: BufferUsage::INDEX, ..Default::default() }, - &index_bytes, + &mesh.get_index_buffer_bytes().unwrap(), ); - render_resource_context.set_asset_resource( - *changed_mesh_handle, - RenderResourceId::Buffer(vertex_buffer), - VERTEX_BUFFER_ASSET_INDEX, - ); render_resource_context.set_asset_resource( *changed_mesh_handle, RenderResourceId::Buffer(index_buffer), @@ -576,23 +631,22 @@ pub fn mesh_resource_provider_system( } } - if let Some(RenderResourceId::Buffer(vertex_buffer)) = - render_resource_context.get_asset_resource(*handle, VERTEX_BUFFER_ASSET_INDEX) - { - render_pipelines.bindings.set_vertex_buffer( - "Vertex", - vertex_buffer, - render_resource_context - .get_asset_resource(*handle, INDEX_BUFFER_ASSET_INDEX) - .and_then(|r| { - if let RenderResourceId::Buffer(buffer) = r { - Some(buffer) - } else { - None - } - }), - ); + // set index buffer into binding + let index_buffer_resource = render_resource_context.get_asset_resource(*handle, INDEX_BUFFER_ASSET_INDEX) + .expect("no index buffer resource found.").get_buffer().expect("resource is not a buffer"); + + render_pipelines.bindings.set_index_buffer(index_buffer_resource); + + // set vertex buffers into bindings + for index in 1..4 { //TODO: use actual vertex buffer count + if let Some(RenderResourceId::Buffer(vertex_buffer)) = + render_resource_context.get_asset_resource(*handle, index) + { + println!("setup vertex buffer {}", index); + render_pipelines.bindings.set_vertex_buffer(index as u8, vertex_buffer); + } } + } } diff --git a/crates/bevy_render/src/pipeline/pipeline_layout.rs b/crates/bevy_render/src/pipeline/pipeline_layout.rs index 56861ed9058aa..02261fe554e60 100644 --- a/crates/bevy_render/src/pipeline/pipeline_layout.rs +++ b/crates/bevy_render/src/pipeline/pipeline_layout.rs @@ -50,6 +50,7 @@ impl PipelineLayout { } for vertex_buffer_descriptor in shader_layouts[0].vertex_buffer_descriptors.iter() { + println!("vertex_buffer_descriptor {:?}", vertex_buffer_descriptor.clone()); vertex_buffer_descriptors.push(vertex_buffer_descriptor.clone()); } diff --git a/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs b/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs index 1f30bcac0bb8e..926a7610bb1a3 100644 --- a/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs +++ b/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs @@ -9,12 +9,13 @@ pub struct VertexBufferDescriptor { pub name: Cow<'static, str>, pub stride: u64, pub step_mode: InputStepMode, - pub attributes: Vec, + pub attributes: Vec, //TODO: remove the vec? should it be ever possible to have multiple attributes per buffer? } impl VertexBufferDescriptor { pub fn sync_with_descriptor(&mut self, descriptor: &VertexBufferDescriptor) { for attribute in self.attributes.iter_mut() { + println!("sync attribute {} with reflection", attribute.name); let descriptor_attribute = descriptor .attributes .iter() @@ -52,6 +53,7 @@ pub struct VertexBufferDescriptors { } impl VertexBufferDescriptors { + //TODO: still needed? pub fn set(&mut self, vertex_buffer_descriptor: VertexBufferDescriptor) { self.descriptors.insert( vertex_buffer_descriptor.name.to_string(), @@ -59,6 +61,10 @@ impl VertexBufferDescriptors { ); } + pub fn set_many(&mut self, vertex_buffer_descriptor: VertexBufferDescriptors) { + self.descriptors.extend(vertex_buffer_descriptor.descriptors); + } + pub fn get(&self, name: &str) -> Option<&VertexBufferDescriptor> { self.descriptors.get(name) } diff --git a/crates/bevy_render/src/renderer/render_resource/render_resource_bindings.rs b/crates/bevy_render/src/renderer/render_resource/render_resource_bindings.rs index b9e95f580ff00..6580514c7675f 100644 --- a/crates/bevy_render/src/renderer/render_resource/render_resource_bindings.rs +++ b/crates/bevy_render/src/renderer/render_resource/render_resource_bindings.rs @@ -107,8 +107,8 @@ pub struct RenderResourceBindings { // TODO: remove this. it shouldn't be needed anymore pub id: RenderResourceBindingsId, bindings: HashMap, - // TODO: remove this - vertex_buffers: HashMap)>, + pub vertex_buffers: HashMap, + pub index_buffer: Option, bind_groups: HashMap, bind_group_descriptors: HashMap>, dirty_bind_groups: HashSet, @@ -140,24 +140,30 @@ impl RenderResourceBindings { self.set(name, binding.clone()); } - for (name, (vertex_buffer, index_buffer)) in render_resource_bindings.vertex_buffers.iter() - { - self.set_vertex_buffer(name, *vertex_buffer, *index_buffer); - } + // for (name, (vertex_buffer, index_buffer)) in render_resource_bindings.vertex_buffers.iter() + // { + // + // self.set_vertex_buffer(name, *vertex_buffer, *index_buffer); + // } } - pub fn get_vertex_buffer(&self, name: &str) -> Option<(BufferId, Option)> { - self.vertex_buffers.get(name).cloned() + pub fn get_vertex_buffer(&self, slot: u8) -> Option<(BufferId)> { + self.vertex_buffers.get(&slot).cloned() } pub fn set_vertex_buffer( &mut self, - name: &str, - vertex_buffer: BufferId, - index_buffer: Option, + slot: u8, + vertex_buffer: BufferId + ) { + self.vertex_buffers.insert(slot, vertex_buffer); + } + + pub fn set_index_buffer( + &mut self, + index_buffer: BufferId, ) { - self.vertex_buffers - .insert(name.to_string(), (vertex_buffer, index_buffer)); + self.index_buffer = Some(index_buffer); } fn create_bind_group(&mut self, descriptor: &BindGroupDescriptor) -> BindGroupStatus { diff --git a/crates/bevy_render/src/shader/shader_reflect.rs b/crates/bevy_render/src/shader/shader_reflect.rs index 9b926433f0566..c629f87e1b947 100644 --- a/crates/bevy_render/src/shader/shader_reflect.rs +++ b/crates/bevy_render/src/shader/shader_reflect.rs @@ -28,8 +28,11 @@ pub const GL_VERTEX_INDEX: &str = "gl_VertexIndex"; impl ShaderLayout { pub fn from_spirv(spirv_data: &[u32], bevy_conventions: bool) -> ShaderLayout { + match ShaderModule::load_u8_data(spirv_data.as_bytes()) { Ok(ref mut module) => { + + // init let entry_point_name = module.get_entry_point_name(); let shader_stage = module.get_shader_stage(); let mut bind_groups = Vec::new(); @@ -38,6 +41,7 @@ impl ShaderLayout { bind_groups.push(bind_group); } + // obtain attribute descriptors from reflection let mut vertex_attribute_descriptors = Vec::new(); for input_variable in module.enumerate_input_variables(None).unwrap() { let vertex_attribute_descriptor = @@ -45,17 +49,20 @@ impl ShaderLayout { if vertex_attribute_descriptor.name == GL_VERTEX_INDEX { continue; } + vertex_attribute_descriptors.push(vertex_attribute_descriptor); } vertex_attribute_descriptors .sort_by(|a, b| a.shader_location.cmp(&b.shader_location)); - let mut visited_buffer_descriptors = HashSet::default(); + //let mut visited_buffer_descriptors = HashSet::default(); let mut vertex_buffer_descriptors = Vec::new(); - let mut current_descriptor: Option = None; + + //let mut current_descriptor: Option = None; for vertex_attribute_descriptor in vertex_attribute_descriptors.drain(..) { let mut instance = false; + // obtain buffer name let current_buffer_name = { if bevy_conventions { if vertex_attribute_descriptor.name == GL_VERTEX_INDEX { @@ -82,40 +89,22 @@ impl ShaderLayout { "DefaultVertex".to_string() } }; + let current_buffer_name_pure = String::from(vertex_attribute_descriptor.name.clone()); - if let Some(current) = current_descriptor.as_mut() { - if current.name == current_buffer_name { - current.attributes.push(vertex_attribute_descriptor); - continue; - } else if visited_buffer_descriptors.contains(¤t_buffer_name) { - panic!("Vertex attribute buffer names must be consecutive.") - } - } - - if let Some(current) = current_descriptor.take() { - visited_buffer_descriptors.insert(current.name.to_string()); - vertex_buffer_descriptors.push(current); - } + println!("insert buffer {}", current_buffer_name); - current_descriptor = Some(VertexBufferDescriptor { - attributes: vec![vertex_attribute_descriptor], - name: current_buffer_name.into(), - step_mode: if instance { - InputStepMode::Instance - } else { - InputStepMode::Vertex - }, - stride: 0, - }) - } - - if let Some(current) = current_descriptor.take() { - visited_buffer_descriptors.insert(current.name.to_string()); - vertex_buffer_descriptors.push(current); - } - - for vertex_buffer_descriptor in vertex_buffer_descriptors.iter_mut() { - calculate_offsets(vertex_buffer_descriptor); + // create a new buffer descriptor per buffer + vertex_buffer_descriptors.push( + VertexBufferDescriptor { + attributes: vec![vertex_attribute_descriptor], + name: current_buffer_name_pure.into(), + step_mode: if instance { + InputStepMode::Instance + } else { + InputStepMode::Vertex + }, + stride: 0, + }); } ShaderLayout { From 4c5d883e83737fb7a5dea780992ce117f7ea5e5a Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Thu, 1 Oct 2020 02:28:41 +0200 Subject: [PATCH 02/32] clean up + format removed uncessary tests as they don't apply anymore for seperate buffers removed vertex.rs and as_vertex_buffer_descriptor.rs simplified ``VertexBufferDescriptor`` to use only one ``VertexAttributeDescriptor`` ran clippy and fmt --- .../src/as_vertex_buffer_descriptor.rs | 124 ------------ crates/bevy_derive/src/lib.rs | 7 - crates/bevy_render/src/draw.rs | 34 +--- crates/bevy_render/src/mesh/mesh.rs | 182 ++++-------------- crates/bevy_render/src/mesh/mod.rs | 2 - crates/bevy_render/src/mesh/vertex.rs | 14 -- crates/bevy_render/src/pipeline/pipeline.rs | 1 + .../src/pipeline/pipeline_layout.rs | 4 +- .../src/pipeline/vertex_buffer_descriptor.rs | 49 ++--- .../render_resource_bindings.rs | 13 +- .../bevy_render/src/shader/shader_reflect.rs | 126 ++++-------- crates/bevy_wgpu/src/wgpu_type_converter.rs | 7 +- 12 files changed, 112 insertions(+), 451 deletions(-) delete mode 100644 crates/bevy_derive/src/as_vertex_buffer_descriptor.rs delete mode 100644 crates/bevy_render/src/mesh/vertex.rs diff --git a/crates/bevy_derive/src/as_vertex_buffer_descriptor.rs b/crates/bevy_derive/src/as_vertex_buffer_descriptor.rs deleted file mode 100644 index fbe42bd422476..0000000000000 --- a/crates/bevy_derive/src/as_vertex_buffer_descriptor.rs +++ /dev/null @@ -1,124 +0,0 @@ -use crate::modules::{get_modules, get_path}; -use inflector::Inflector; -use proc_macro::TokenStream; -use quote::{format_ident, quote}; -use syn::{ - parse::ParseStream, parse_macro_input, Data, DataStruct, DeriveInput, Field, Fields, Path, -}; - -#[derive(Default)] -struct VertexAttributes { - pub ignore: bool, - pub instance: bool, -} - -static VERTEX_ATTRIBUTE_NAME: &str = "vertex"; - -pub fn derive_as_vertex_buffer_descriptor(input: TokenStream) -> TokenStream { - let ast = parse_macro_input!(input as DeriveInput); - let modules = get_modules(&ast.attrs); - - let bevy_render_path: Path = get_path(&modules.bevy_render); - let fields = match &ast.data { - Data::Struct(DataStruct { - fields: Fields::Named(fields), - .. - }) => &fields.named, - _ => panic!("expected a struct with named fields"), - }; - let field_attributes = fields - .iter() - .map(|field| { - ( - field, - field - .attrs - .iter() - .find(|a| *a.path.get_ident().as_ref().unwrap() == VERTEX_ATTRIBUTE_NAME) - .map_or_else(VertexAttributes::default, |a| { - syn::custom_keyword!(ignore); - let mut vertex_attributes = VertexAttributes::default(); - a.parse_args_with(|input: ParseStream| { - if input.parse::>()?.is_some() { - vertex_attributes.ignore = true; - return Ok(()); - } - Ok(()) - }) - .expect("invalid 'vertex' attribute format"); - - vertex_attributes - }), - ) - }) - .collect::>(); - - let struct_name = &ast.ident; - - let mut vertex_buffer_field_names_pascal = Vec::new(); - let mut vertex_buffer_field_types = Vec::new(); - for (f, attrs) in field_attributes.iter() { - if attrs.ignore { - continue; - } - - vertex_buffer_field_types.push(&f.ty); - let pascal_field = f.ident.as_ref().unwrap().to_string().to_pascal_case(); - vertex_buffer_field_names_pascal.push(if attrs.instance { - format!("I_{}_{}", struct_name, pascal_field) - } else { - format!("{}_{}", struct_name, pascal_field) - }); - } - - let struct_name_string = struct_name.to_string(); - let struct_name_uppercase = struct_name_string.to_uppercase(); - let vertex_buffer_descriptor_ident = - format_ident!("{}_VERTEX_BUFFER_DESCRIPTOR", struct_name_uppercase); - - TokenStream::from(quote! { - static #vertex_buffer_descriptor_ident: #bevy_render_path::once_cell::sync::Lazy<#bevy_render_path::pipeline::VertexBufferDescriptor> = - #bevy_render_path::once_cell::sync::Lazy::new(|| { - use #bevy_render_path::pipeline::{VertexFormat, AsVertexFormats, VertexAttributeDescriptor}; - - let mut vertex_formats: Vec<(&str,&[VertexFormat])> = vec![ - #((#vertex_buffer_field_names_pascal, <#vertex_buffer_field_types>::as_vertex_formats()),)* - ]; - - let mut shader_location = 0; - let mut offset = 0; - let vertex_attribute_descriptors = vertex_formats.drain(..).map(|(name, formats)| { - formats.iter().enumerate().map(|(i, format)| { - let size = format.get_size(); - let formatted_name = if formats.len() > 1 { - format!("{}_{}", name, i) - } else { - format!("{}", name) - }; - let descriptor = VertexAttributeDescriptor { - name: formatted_name.into(), - offset, - format: *format, - shader_location, - }; - offset += size; - shader_location += 1; - descriptor - }).collect::>() - }).flatten().collect::>(); - - #bevy_render_path::pipeline::VertexBufferDescriptor { - attributes: vertex_attribute_descriptors, - name: #struct_name_string.into(), - step_mode: #bevy_render_path::pipeline::InputStepMode::Instance, - stride: offset, - } - }); - - impl #bevy_render_path::pipeline::AsVertexBufferDescriptor for #struct_name { - fn as_vertex_buffer_descriptor() -> &'static #bevy_render_path::pipeline::VertexBufferDescriptor { - &#vertex_buffer_descriptor_ident - } - } - }) -} diff --git a/crates/bevy_derive/src/lib.rs b/crates/bevy_derive/src/lib.rs index 382f4265a13c7..7f0a2bb66836d 100644 --- a/crates/bevy_derive/src/lib.rs +++ b/crates/bevy_derive/src/lib.rs @@ -1,7 +1,6 @@ extern crate proc_macro; mod app_plugin; -mod as_vertex_buffer_descriptor; mod bytes; mod modules; mod render_resource; @@ -44,12 +43,6 @@ pub fn derive_shader_defs(input: TokenStream) -> TokenStream { shader_defs::derive_shader_defs(input) } -/// Derives the AsVertexBufferDescriptor trait. -#[proc_macro_derive(AsVertexBufferDescriptor, attributes(vertex, as_crate))] -pub fn derive_as_vertex_buffer_descriptor(input: TokenStream) -> TokenStream { - as_vertex_buffer_descriptor::derive_as_vertex_buffer_descriptor(input) -} - /// Generates a dynamic plugin entry point function for the given `Plugin` type. #[proc_macro_derive(DynamicPlugin)] pub fn derive_dynamic_plugin(input: TokenStream) -> TokenStream { diff --git a/crates/bevy_render/src/draw.rs b/crates/bevy_render/src/draw.rs index 69d1ebf188a6a..48284c5265f26 100644 --- a/crates/bevy_render/src/draw.rs +++ b/crates/bevy_render/src/draw.rs @@ -121,8 +121,6 @@ pub enum DrawError { PipelineHasNoLayout, #[error("Failed to get a buffer for the given RenderResource.")] BufferAllocationFailure, - #[error("Could not get buffer for Vertex Attribute")] - NoBufferForVertexAttribute, } pub struct DrawContext<'a> { @@ -344,32 +342,16 @@ impl<'a> DrawContext<'a> { draw: &mut Draw, render_resource_bindings: &[&RenderResourceBindings], ) -> Result<(), DrawError> { - let pipeline = self.current_pipeline.ok_or(DrawError::NoPipelineSet)?; - let pipeline_descriptor = self - .pipelines - .get(&pipeline) - .ok_or(DrawError::NonExistentPipeline)?; - let layout = pipeline_descriptor - .get_layout() - .ok_or(DrawError::PipelineHasNoLayout)?; - - println!("{:?}", layout.vertex_buffer_descriptors); - for (slot, vertex_buffer_descriptor) in layout.vertex_buffer_descriptors.iter().enumerate() - { - println!("trying to get buffer for slot {} -> {}", slot, &vertex_buffer_descriptor.name); - for bindings in render_resource_bindings.iter() { - println!("\t binding {:?}", &bindings.id); - // TODO: fix this, it is setting the buffer multiply times - for vertex_buffer in &bindings.vertex_buffers{ - println!("\t \t set slot{:?}", &vertex_buffer.0); - draw.set_vertex_buffer(vertex_buffer.0.clone() as u32 - 1, vertex_buffer.1.clone(), 0); - } - if let Some(index_buffer) = bindings.index_buffer{ - draw.set_index_buffer(index_buffer, 0); - } + for bindings in render_resource_bindings.iter() { + for vertex_buffer in &bindings.vertex_buffers { + // TODO: don't to the -1 thing, when VERTEX_BUFFER_ASSET_INDEX in mesh.rs is finally gone + draw.set_vertex_buffer(*vertex_buffer.0 as u32 - 1, *vertex_buffer.1, 0); + } + if let Some(index_buffer) = bindings.index_buffer { + draw.set_index_buffer(index_buffer, 0); } } - println!("done with vertex_buffer_descriptors"); + Ok(()) } } diff --git a/crates/bevy_render/src/mesh/mesh.rs b/crates/bevy_render/src/mesh/mesh.rs index 964f1da73acea..9f3c9ae640ffd 100644 --- a/crates/bevy_render/src/mesh/mesh.rs +++ b/crates/bevy_render/src/mesh/mesh.rs @@ -1,8 +1,8 @@ -use super::Vertex; +use crate::pipeline::VertexAttributeDescriptor; use crate::{ pipeline::{ - AsVertexBufferDescriptor, PrimitiveTopology, RenderPipelines, VertexBufferDescriptor, - VertexBufferDescriptors, VertexFormat, + PrimitiveTopology, RenderPipelines, VertexBufferDescriptor, VertexBufferDescriptors, + VertexFormat, }, renderer::{BufferInfo, BufferUsage, RenderResourceContext, RenderResourceId}, }; @@ -12,10 +12,9 @@ use bevy_core::AsBytes; use bevy_ecs::{Local, Query, Res, ResMut}; use bevy_math::*; use bevy_utils::HashSet; +use downcast_rs::Downcast; use std::borrow::Cow; use thiserror::Error; -use crate::pipeline::VertexAttributeDescriptor; -use downcast_rs::Downcast; use crate::pipeline::InputStepMode; @@ -131,52 +130,6 @@ impl Mesh { indices: None, } } - // pub fn get_vertex_attribute_bytes( - // &self, - // fill_missing_attributes: bool, - // attribute_index: u32, - // ) -> Result, MeshToVertexBufferError>{ - // let attribute - // let mut bytes = vec![0; vertex_buffer_descriptor.stride as usize]; - // - // } - - pub fn get_vertex_buffer_bytes( - &self, - vertex_buffer_descriptor: &VertexBufferDescriptor, - fill_missing_attributes: bool, - ) -> Result, MeshToVertexBufferError> { - let length = self.attributes.first().map(|a| a.values.len()).unwrap_or(0); - let mut bytes = vec![0; vertex_buffer_descriptor.stride as usize * length]; - - for vertex_attribute in vertex_buffer_descriptor.attributes.iter() { - match self - .attributes - .iter() - .find(|a| vertex_attribute.name == a.name) - { - Some(mesh_attribute) => { - let attribute_bytes = mesh_attribute.values.get_bytes(); - let attribute_size = vertex_attribute.format.get_size() as usize; - for (i, vertex_slice) in attribute_bytes.chunks(attribute_size).enumerate() { - let vertex_offset = vertex_buffer_descriptor.stride as usize * i; - let attribute_offset = vertex_offset + vertex_attribute.offset as usize; - bytes[attribute_offset..attribute_offset + attribute_size] - .copy_from_slice(vertex_slice); - } - } - None => { - if !fill_missing_attributes { - return Err(MeshToVertexBufferError::MissingVertexAttribute { - attribute_name: vertex_attribute.name.clone(), - }); - } - } - } - } - - Ok(bytes) - } pub fn get_index_buffer_bytes(&self) -> Option> { self.indices.as_ref().map(|indices| match &indices { @@ -517,51 +470,56 @@ pub fn mesh_resource_provider_system( ) { if state.vertex_buffer_descriptor.is_none() { // TODO: allow pipelines to specialize on vertex_buffer_descriptor and index_format - let mut vertex_buffer_descriptors_: VertexBufferDescriptors = VertexBufferDescriptors{ - descriptors: Default::default() + let mut vertex_buffer_descriptors_: VertexBufferDescriptors = VertexBufferDescriptors { + descriptors: Default::default(), }; // TODO: kinda messy vertex_buffer_descriptors_.descriptors.insert( "Vertex_Position".to_string(), - VertexBufferDescriptor{ + VertexBufferDescriptor { name: "Vertex_Position".into(), stride: VertexFormat::Float3.get_size(), step_mode: InputStepMode::Vertex, - attributes: vec![VertexAttributeDescriptor{ + attribute: VertexAttributeDescriptor { name: "Vertex_Position".into(), offset: 0, format: VertexFormat::Float3, - shader_location: 0 - }] - }); + shader_location: 0, + }, + }, + ); vertex_buffer_descriptors_.descriptors.insert( "Vertex_Normal".to_string(), - VertexBufferDescriptor{ + VertexBufferDescriptor { name: "Vertex_Normal".into(), stride: VertexFormat::Float3.get_size(), step_mode: InputStepMode::Vertex, - attributes: vec![VertexAttributeDescriptor{ + attribute: VertexAttributeDescriptor { name: "Vertex_Normal".into(), offset: 0, format: VertexFormat::Float3, - shader_location: 0 - }] - }); + shader_location: 0, + }, + }, + ); vertex_buffer_descriptors_.descriptors.insert( "Vertex_Uv".to_string(), - VertexBufferDescriptor{ + VertexBufferDescriptor { name: "Vertex_Uv".into(), stride: VertexFormat::Float2.get_size(), step_mode: InputStepMode::Vertex, - attributes: vec![VertexAttributeDescriptor{ + attribute: VertexAttributeDescriptor { name: "Vertex_Uv".into(), offset: 0, format: VertexFormat::Float2, - shader_location: 0 - }] - }); - vertex_buffer_descriptors.set_many(vertex_buffer_descriptors_); + shader_location: 0, + }, + }, + ); + vertex_buffer_descriptors + .descriptors + .extend(vertex_buffer_descriptors_.descriptors); } let mut changed_meshes = HashSet::>::default(); @@ -586,10 +544,8 @@ pub fn mesh_resource_provider_system( for changed_mesh_handle in changed_meshes.iter() { if let Some(mesh) = meshes.get(changed_mesh_handle) { - let mut index = 1; // index 0 is reserved by INDEX_BUFFER_ASSET_INDEX - for attribute in &mesh.attributes{ - println!("insert index vertex buffer index {}", index); + for attribute in &mesh.attributes { // TODO: use a staging buffer here let attribute_buffer = render_resource_context.create_buffer_with_data( BufferInfo { @@ -631,81 +587,25 @@ pub fn mesh_resource_provider_system( } } - // set index buffer into binding - let index_buffer_resource = render_resource_context.get_asset_resource(*handle, INDEX_BUFFER_ASSET_INDEX) - .expect("no index buffer resource found.").get_buffer().expect("resource is not a buffer"); - - render_pipelines.bindings.set_index_buffer(index_buffer_resource); + if let Some(RenderResourceId::Buffer(index_buffer_resource)) = + render_resource_context.get_asset_resource(*handle, INDEX_BUFFER_ASSET_INDEX) + { + // set index buffer into binding + render_pipelines + .bindings + .set_index_buffer(index_buffer_resource); + } // set vertex buffers into bindings - for index in 1..4 { //TODO: use actual vertex buffer count + for index in 1..4 { + //TODO: use actual vertex buffer count if let Some(RenderResourceId::Buffer(vertex_buffer)) = render_resource_context.get_asset_resource(*handle, index) { - println!("setup vertex buffer {}", index); - render_pipelines.bindings.set_vertex_buffer(index as u8, vertex_buffer); + render_pipelines + .bindings + .set_vertex_buffer(index as u8, vertex_buffer); } } - - } -} - -#[cfg(test)] -mod tests { - use super::{AsVertexBufferDescriptor, Mesh, VertexAttribute}; - use crate::{mesh::Vertex, pipeline::PrimitiveTopology}; - use bevy_core::AsBytes; - - #[test] - fn test_get_vertex_bytes() { - let vertices = &[ - ([0., 0., 0.], [1., 1., 1.], [2., 2.]), - ([3., 3., 3.], [4., 4., 4.], [5., 5.]), - ([6., 6., 6.], [7., 7., 7.], [8., 8.]), - ]; - - let mut positions = Vec::new(); - let mut normals = Vec::new(); - let mut uvs = Vec::new(); - for (position, normal, uv) in vertices.iter() { - positions.push(*position); - normals.push(*normal); - uvs.push(*uv); - } - - let mesh = Mesh { - primitive_topology: PrimitiveTopology::TriangleStrip, - attributes: vec![ - VertexAttribute::position(positions), - VertexAttribute::normal(normals), - VertexAttribute::uv(uvs), - ], - indices: None, - }; - - let expected_vertices = &[ - Vertex { - position: [0., 0., 0.], - normal: [1., 1., 1.], - uv: [2., 2.], - }, - Vertex { - position: [3., 3., 3.], - normal: [4., 4., 4.], - uv: [5., 5.], - }, - Vertex { - position: [6., 6., 6.], - normal: [7., 7., 7.], - uv: [8., 8.], - }, - ]; - - let descriptor = Vertex::as_vertex_buffer_descriptor(); - assert_eq!( - mesh.get_vertex_buffer_bytes(descriptor, true).unwrap(), - expected_vertices.as_bytes(), - "buffer bytes are equal" - ); } } diff --git a/crates/bevy_render/src/mesh/mod.rs b/crates/bevy_render/src/mesh/mod.rs index f9d33b4891c37..1db18c486545b 100644 --- a/crates/bevy_render/src/mesh/mod.rs +++ b/crates/bevy_render/src/mesh/mod.rs @@ -1,6 +1,4 @@ #[allow(clippy::module_inception)] mod mesh; -mod vertex; pub use mesh::*; -pub use vertex::*; diff --git a/crates/bevy_render/src/mesh/vertex.rs b/crates/bevy_render/src/mesh/vertex.rs deleted file mode 100644 index b711d39fb428b..0000000000000 --- a/crates/bevy_render/src/mesh/vertex.rs +++ /dev/null @@ -1,14 +0,0 @@ -use crate::pipeline::AsVertexBufferDescriptor; -use bevy_core::Byteable; - -#[repr(C)] -#[derive(Clone, Copy, AsVertexBufferDescriptor)] -#[as_crate(bevy_render)] -pub struct Vertex { - pub position: [f32; 3], - pub normal: [f32; 3], - pub uv: [f32; 2], -} - -// SAFE: Vertex is repr(C) containing primitives -unsafe impl Byteable for Vertex {} diff --git a/crates/bevy_render/src/pipeline/pipeline.rs b/crates/bevy_render/src/pipeline/pipeline.rs index 9f59ca82280dc..dbfcee93056d1 100644 --- a/crates/bevy_render/src/pipeline/pipeline.rs +++ b/crates/bevy_render/src/pipeline/pipeline.rs @@ -146,6 +146,7 @@ impl PipelineDescriptor { let mut layout = PipelineLayout::from_shader_layouts(&mut layouts); if let Some(vertex_buffer_descriptors) = vertex_buffer_descriptors { + // complete the layout with the user defined descriptors layout.sync_vertex_buffer_descriptors(vertex_buffer_descriptors); } diff --git a/crates/bevy_render/src/pipeline/pipeline_layout.rs b/crates/bevy_render/src/pipeline/pipeline_layout.rs index 02261fe554e60..8e8505873ffb9 100644 --- a/crates/bevy_render/src/pipeline/pipeline_layout.rs +++ b/crates/bevy_render/src/pipeline/pipeline_layout.rs @@ -50,7 +50,6 @@ impl PipelineLayout { } for vertex_buffer_descriptor in shader_layouts[0].vertex_buffer_descriptors.iter() { - println!("vertex_buffer_descriptor {:?}", vertex_buffer_descriptor.clone()); vertex_buffer_descriptors.push(vertex_buffer_descriptor.clone()); } @@ -77,7 +76,8 @@ impl PipelineLayout { if let Some(graph_descriptor) = vertex_buffer_descriptors.get(&vertex_buffer_descriptor.name) { - vertex_buffer_descriptor.sync_with_descriptor(graph_descriptor); + vertex_buffer_descriptor.attribute.offset = graph_descriptor.attribute.offset; + vertex_buffer_descriptor.stride = graph_descriptor.stride; } else if vertex_buffer_descriptor.name == GL_VERTEX_INDEX { // GL_VERTEX_INDEX is a special attribute set on our behalf continue; diff --git a/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs b/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs index 926a7610bb1a3..ef83270130644 100644 --- a/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs +++ b/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs @@ -2,37 +2,33 @@ use super::VertexFormat; use bevy_utils::HashMap; use std::borrow::Cow; -pub use bevy_derive::AsVertexBufferDescriptor; - #[derive(Clone, Debug, Eq, PartialEq)] pub struct VertexBufferDescriptor { pub name: Cow<'static, str>, pub stride: u64, pub step_mode: InputStepMode, - pub attributes: Vec, //TODO: remove the vec? should it be ever possible to have multiple attributes per buffer? + pub attribute: VertexAttributeDescriptor, } impl VertexBufferDescriptor { - pub fn sync_with_descriptor(&mut self, descriptor: &VertexBufferDescriptor) { - for attribute in self.attributes.iter_mut() { - println!("sync attribute {} with reflection", attribute.name); - 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; + pub fn new_from_attribute( + attribute: VertexAttributeDescriptor, + step_mode: InputStepMode, + ) -> VertexBufferDescriptor { + VertexBufferDescriptor { + name: attribute.name.clone(), + stride: attribute.format.get_size(), + step_mode, + attribute: attribute.clone(), } + } - self.stride = descriptor.stride; + // just for tests, since a reflected layout doesn't know about the stride + pub fn test_zero_stride(mut self) -> VertexBufferDescriptor { + self.stride = 0; + self } } - #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] pub enum InputStepMode { Vertex = 0, @@ -53,23 +49,12 @@ pub struct VertexBufferDescriptors { } impl VertexBufferDescriptors { - //TODO: still needed? - pub fn set(&mut self, vertex_buffer_descriptor: VertexBufferDescriptor) { - self.descriptors.insert( - vertex_buffer_descriptor.name.to_string(), - vertex_buffer_descriptor, - ); - } - pub fn set_many(&mut self, vertex_buffer_descriptor: VertexBufferDescriptors) { - self.descriptors.extend(vertex_buffer_descriptor.descriptors); + self.descriptors + .extend(vertex_buffer_descriptor.descriptors); } pub fn get(&self, name: &str) -> Option<&VertexBufferDescriptor> { self.descriptors.get(name) } } - -pub trait AsVertexBufferDescriptor { - fn as_vertex_buffer_descriptor() -> &'static VertexBufferDescriptor; -} diff --git a/crates/bevy_render/src/renderer/render_resource/render_resource_bindings.rs b/crates/bevy_render/src/renderer/render_resource/render_resource_bindings.rs index 6580514c7675f..a9a84362c04c0 100644 --- a/crates/bevy_render/src/renderer/render_resource/render_resource_bindings.rs +++ b/crates/bevy_render/src/renderer/render_resource/render_resource_bindings.rs @@ -147,22 +147,15 @@ impl RenderResourceBindings { // } } - pub fn get_vertex_buffer(&self, slot: u8) -> Option<(BufferId)> { + pub fn get_vertex_buffer(&self, slot: u8) -> Option { self.vertex_buffers.get(&slot).cloned() } - pub fn set_vertex_buffer( - &mut self, - slot: u8, - vertex_buffer: BufferId - ) { + pub fn set_vertex_buffer(&mut self, slot: u8, vertex_buffer: BufferId) { self.vertex_buffers.insert(slot, vertex_buffer); } - pub fn set_index_buffer( - &mut self, - index_buffer: BufferId, - ) { + pub fn set_index_buffer(&mut self, index_buffer: BufferId) { self.index_buffer = Some(index_buffer); } diff --git a/crates/bevy_render/src/shader/shader_reflect.rs b/crates/bevy_render/src/shader/shader_reflect.rs index c629f87e1b947..0883a9c21d541 100644 --- a/crates/bevy_render/src/shader/shader_reflect.rs +++ b/crates/bevy_render/src/shader/shader_reflect.rs @@ -28,10 +28,8 @@ pub const GL_VERTEX_INDEX: &str = "gl_VertexIndex"; impl ShaderLayout { pub fn from_spirv(spirv_data: &[u32], bevy_conventions: bool) -> ShaderLayout { - match ShaderModule::load_u8_data(spirv_data.as_bytes()) { Ok(ref mut module) => { - // init let entry_point_name = module.get_entry_point_name(); let shader_stage = module.get_shader_stage(); @@ -56,13 +54,10 @@ impl ShaderLayout { vertex_attribute_descriptors .sort_by(|a, b| a.shader_location.cmp(&b.shader_location)); - //let mut visited_buffer_descriptors = HashSet::default(); let mut vertex_buffer_descriptors = Vec::new(); - - //let mut current_descriptor: Option = None; for vertex_attribute_descriptor in vertex_attribute_descriptors.drain(..) { let mut instance = false; - // obtain buffer name + // obtain buffer name and instancing flag let current_buffer_name = { if bevy_conventions { if vertex_attribute_descriptor.name == GL_VERTEX_INDEX { @@ -72,15 +67,14 @@ impl ShaderLayout { .name .splitn(3, '_') .collect::>(); + if parts.len() == 3 { if parts[0] == "I" { instance = true; - parts[1].to_string() - } else { - parts[0].to_string() } + vertex_attribute_descriptor.name.to_string() } else if parts.len() == 2 { - parts[0].to_string() + vertex_attribute_descriptor.name.to_string() } else { panic!("Vertex attributes must follow the form BUFFERNAME_PROPERTYNAME. For example: Vertex_Position"); } @@ -89,21 +83,17 @@ impl ShaderLayout { "DefaultVertex".to_string() } }; - let current_buffer_name_pure = String::from(vertex_attribute_descriptor.name.clone()); - - println!("insert buffer {}", current_buffer_name); // create a new buffer descriptor per buffer - vertex_buffer_descriptors.push( - VertexBufferDescriptor { - attributes: vec![vertex_attribute_descriptor], - name: current_buffer_name_pure.into(), - step_mode: if instance { - InputStepMode::Instance - } else { - InputStepMode::Vertex - }, - stride: 0, + vertex_buffer_descriptors.push(VertexBufferDescriptor { + attribute: vertex_attribute_descriptor, + name: current_buffer_name.into(), + step_mode: if instance { + InputStepMode::Instance + } else { + InputStepMode::Vertex + }, + stride: 0, }); } @@ -118,16 +108,6 @@ impl ShaderLayout { } } -fn calculate_offsets(vertex_buffer_descriptor: &mut VertexBufferDescriptor) { - let mut offset = 0; - for attribute in vertex_buffer_descriptor.attributes.iter_mut() { - attribute.offset = offset; - offset += attribute.format.get_size(); - } - - vertex_buffer_descriptor.stride = offset; -} - fn reflect_vertex_attribute_descriptor( input_variable: &ReflectInterfaceVariable, ) -> VertexAttributeDescriptor { @@ -380,36 +360,36 @@ mod tests { ShaderLayout { entry_point: "main".into(), vertex_buffer_descriptors: vec![ - VertexBufferDescriptor { - name: "Vertex".into(), - attributes: vec![ - VertexAttributeDescriptor { - name: "Vertex_Position".into(), - format: VertexFormat::Float4, - offset: 0, - shader_location: 0, - }, - VertexAttributeDescriptor { - name: "Vertex_Normal".into(), - format: VertexFormat::Uint4, - offset: 16, - shader_location: 1, - } - ], - step_mode: InputStepMode::Vertex, - stride: 32, - }, - VertexBufferDescriptor { - name: "TestInstancing".into(), - attributes: vec![VertexAttributeDescriptor { + VertexBufferDescriptor::new_from_attribute( + VertexAttributeDescriptor { + name: "Vertex_Position".into(), + format: VertexFormat::Float4, + offset: 0, + shader_location: 0, + }, + InputStepMode::Vertex + ) + .test_zero_stride(), + VertexBufferDescriptor::new_from_attribute( + VertexAttributeDescriptor { + name: "Vertex_Normal".into(), + format: VertexFormat::Uint4, + offset: 0, + shader_location: 1, + }, + InputStepMode::Vertex + ) + .test_zero_stride(), + VertexBufferDescriptor::new_from_attribute( + VertexAttributeDescriptor { name: "I_TestInstancing_Property".into(), format: VertexFormat::Uint4, offset: 0, shader_location: 2, - },], - step_mode: InputStepMode::Instance, - stride: 16, - } + }, + InputStepMode::Instance + ) + .test_zero_stride(), ], bind_groups: vec![ BindGroupDescriptor::new( @@ -441,32 +421,4 @@ mod tests { } ); } - - #[test] - #[should_panic(expected = "Vertex attribute buffer names must be consecutive.")] - fn test_reflection_consecutive_buffer_validation() { - let vertex_shader = Shader::from_glsl( - ShaderStage::Vertex, - r#" - #version 450 - layout(location = 0) in vec4 Vertex_Position; - layout(location = 1) in uvec4 Other_Property; - layout(location = 2) in uvec4 Vertex_Normal; - - layout(location = 0) out vec4 v_Position; - layout(set = 0, binding = 0) uniform Camera { - mat4 ViewProj; - }; - layout(set = 1, binding = 0) uniform texture2D Texture; - - void main() { - v_Position = Vertex_Position; - gl_Position = ViewProj * v_Position; - } - "#, - ) - .get_spirv_shader(None); - - let _layout = vertex_shader.reflect_layout(true).unwrap(); - } } diff --git a/crates/bevy_wgpu/src/wgpu_type_converter.rs b/crates/bevy_wgpu/src/wgpu_type_converter.rs index 083c48a158c85..04dd94da6ea96 100644 --- a/crates/bevy_wgpu/src/wgpu_type_converter.rs +++ b/crates/bevy_wgpu/src/wgpu_type_converter.rs @@ -98,15 +98,10 @@ pub struct OwnedWgpuVertexBufferDescriptor { impl WgpuFrom<&VertexBufferDescriptor> for OwnedWgpuVertexBufferDescriptor { fn from(val: &VertexBufferDescriptor) -> OwnedWgpuVertexBufferDescriptor { - let attributes = val - .attributes - .iter() - .map(|a| a.wgpu_into()) - .collect::>(); OwnedWgpuVertexBufferDescriptor { step_mode: val.step_mode.wgpu_into(), stride: val.stride, - attributes, + attributes: vec![(&val.attribute).wgpu_into()], } } } From 92bae44e9ae076fd7440c9aad174c311c166ab0d Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Thu, 1 Oct 2020 02:36:08 +0200 Subject: [PATCH 03/32] Update mesh.rs --- crates/bevy_render/src/mesh/mesh.rs | 41 +++++++++++------------------ 1 file changed, 16 insertions(+), 25 deletions(-) diff --git a/crates/bevy_render/src/mesh/mesh.rs b/crates/bevy_render/src/mesh/mesh.rs index 9f3c9ae640ffd..6c06e58108c7a 100644 --- a/crates/bevy_render/src/mesh/mesh.rs +++ b/crates/bevy_render/src/mesh/mesh.rs @@ -1,8 +1,7 @@ -use crate::pipeline::VertexAttributeDescriptor; use crate::{ pipeline::{ - PrimitiveTopology, RenderPipelines, VertexBufferDescriptor, VertexBufferDescriptors, - VertexFormat, + PrimitiveTopology, RenderPipelines, VertexAttributeDescriptor, VertexBufferDescriptor, + VertexBufferDescriptors, VertexFormat, }, renderer::{BufferInfo, BufferUsage, RenderResourceContext, RenderResourceId}, }; @@ -473,49 +472,41 @@ pub fn mesh_resource_provider_system( let mut vertex_buffer_descriptors_: VertexBufferDescriptors = VertexBufferDescriptors { descriptors: Default::default(), }; - - // TODO: kinda messy vertex_buffer_descriptors_.descriptors.insert( "Vertex_Position".to_string(), - VertexBufferDescriptor { - name: "Vertex_Position".into(), - stride: VertexFormat::Float3.get_size(), - step_mode: InputStepMode::Vertex, - attribute: VertexAttributeDescriptor { + VertexBufferDescriptor::new_from_attribute( + VertexAttributeDescriptor { name: "Vertex_Position".into(), offset: 0, format: VertexFormat::Float3, shader_location: 0, }, - }, + InputStepMode::Vertex, + ), ); vertex_buffer_descriptors_.descriptors.insert( "Vertex_Normal".to_string(), - VertexBufferDescriptor { - name: "Vertex_Normal".into(), - stride: VertexFormat::Float3.get_size(), - step_mode: InputStepMode::Vertex, - attribute: VertexAttributeDescriptor { + VertexBufferDescriptor::new_from_attribute( + VertexAttributeDescriptor { name: "Vertex_Normal".into(), offset: 0, format: VertexFormat::Float3, - shader_location: 0, + shader_location: 1, }, - }, + InputStepMode::Vertex, + ), ); vertex_buffer_descriptors_.descriptors.insert( "Vertex_Uv".to_string(), - VertexBufferDescriptor { - name: "Vertex_Uv".into(), - stride: VertexFormat::Float2.get_size(), - step_mode: InputStepMode::Vertex, - attribute: VertexAttributeDescriptor { + VertexBufferDescriptor::new_from_attribute( + VertexAttributeDescriptor { name: "Vertex_Uv".into(), offset: 0, format: VertexFormat::Float2, - shader_location: 0, + shader_location: 2, }, - }, + InputStepMode::Vertex, + ), ); vertex_buffer_descriptors .descriptors From d47897cf0b2570153dd32336ca874dc8c1065c18 Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Thu, 1 Oct 2020 02:51:38 +0200 Subject: [PATCH 04/32] Update mesh.rs --- crates/bevy_render/src/mesh/mesh.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/bevy_render/src/mesh/mesh.rs b/crates/bevy_render/src/mesh/mesh.rs index 6c06e58108c7a..448760bd12349 100644 --- a/crates/bevy_render/src/mesh/mesh.rs +++ b/crates/bevy_render/src/mesh/mesh.rs @@ -10,8 +10,6 @@ use bevy_asset::{AssetEvent, Assets, Handle}; use bevy_core::AsBytes; use bevy_ecs::{Local, Query, Res, ResMut}; use bevy_math::*; -use bevy_utils::HashSet; -use downcast_rs::Downcast; use std::borrow::Cow; use thiserror::Error; From 6253a9504060f0254fc3ad41df33086fae07fffa Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Thu, 1 Oct 2020 03:00:07 +0200 Subject: [PATCH 05/32] clippy nightly --- crates/bevy_render/src/mesh/mesh.rs | 2 +- crates/bevy_render/src/shader/shader_reflect.rs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/bevy_render/src/mesh/mesh.rs b/crates/bevy_render/src/mesh/mesh.rs index 448760bd12349..4bae0dc24aaed 100644 --- a/crates/bevy_render/src/mesh/mesh.rs +++ b/crates/bevy_render/src/mesh/mesh.rs @@ -511,7 +511,7 @@ pub fn mesh_resource_provider_system( .extend(vertex_buffer_descriptors_.descriptors); } - let mut changed_meshes = HashSet::>::default(); + let mut changed_meshes = bevy_utils::HashSet::>::default(); let render_resource_context = &**render_resource_context; for event in state.mesh_event_reader.iter(&mesh_events) { match event { diff --git a/crates/bevy_render/src/shader/shader_reflect.rs b/crates/bevy_render/src/shader/shader_reflect.rs index 0883a9c21d541..680fad92eb117 100644 --- a/crates/bevy_render/src/shader/shader_reflect.rs +++ b/crates/bevy_render/src/shader/shader_reflect.rs @@ -6,7 +6,6 @@ use crate::{ texture::{TextureComponentType, TextureViewDimension}, }; use bevy_core::AsBytes; -use bevy_utils::HashSet; use spirv_reflect::{ types::{ ReflectDescriptorBinding, ReflectDescriptorSet, ReflectDescriptorType, ReflectDimension, From ccbc1bc9a9ad248b9952740781c012237c6b98ae Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Sun, 4 Oct 2020 13:46:27 +0200 Subject: [PATCH 06/32] changed vertex buffer slots now taken from binding; shader naming convetions; moved torwards naming based resources --- crates/bevy_gltf/src/loader.rs | 16 +- .../forward_pipeline/forward.frag | 12 +- .../forward_pipeline/forward.vert | 22 +- crates/bevy_render/Cargo.toml | 1 + crates/bevy_render/src/draw.rs | 19 +- crates/bevy_render/src/mesh/mesh.rs | 204 +++++++++++------- crates/bevy_render/src/pipeline/pipeline.rs | 1 + .../src/pipeline/render_pipelines.rs | 11 +- .../src/pipeline/vertex_buffer_descriptor.rs | 3 +- .../render_resource_bindings.rs | 24 +-- .../bevy_render/src/shader/shader_reflect.rs | 65 +++--- crates/bevy_sprite/src/render/sprite.frag | 4 +- crates/bevy_sprite/src/render/sprite.vert | 12 +- .../bevy_sprite/src/render/sprite_sheet.frag | 4 +- .../bevy_sprite/src/render/sprite_sheet.vert | 14 +- crates/bevy_ui/src/render/ui.frag | 4 +- crates/bevy_ui/src/render/ui.vert | 12 +- examples/shader/shader_custom_material.rs | 4 +- examples/shader/shader_defs.rs | 4 +- 19 files changed, 249 insertions(+), 187 deletions(-) diff --git a/crates/bevy_gltf/src/loader.rs b/crates/bevy_gltf/src/loader.rs index 7fb690ce39811..a19cf3ecb8cfa 100644 --- a/crates/bevy_gltf/src/loader.rs +++ b/crates/bevy_gltf/src/loader.rs @@ -1,5 +1,5 @@ use bevy_render::{ - mesh::{Indices, Mesh, VertexAttribute}, + mesh::{Indices, Mesh, VertexAttributeData}, pipeline::PrimitiveTopology, }; @@ -74,27 +74,27 @@ fn load_node(buffer_data: &[Vec], node: &gltf::Node, depth: i32) -> Result DrawContext<'a> { &self, draw: &mut Draw, render_resource_bindings: &[&RenderResourceBindings], + vertex_buffer_descriptors: Vec, ) -> Result<(), DrawError> { for bindings in render_resource_bindings.iter() { for vertex_buffer in &bindings.vertex_buffers { - // TODO: don't to the -1 thing, when VERTEX_BUFFER_ASSET_INDEX in mesh.rs is finally gone - draw.set_vertex_buffer(*vertex_buffer.0 as u32 - 1, *vertex_buffer.1, 0); + // TODO: big ooof but works + if let Some(vertex_attribute_descriptor) = &vertex_buffer_descriptors + .iter() + .find(|&x| *vertex_buffer.0 == crate::mesh::get_attribute_name_id(&x.name)) + { + draw.set_vertex_buffer( + vertex_attribute_descriptor + .attribute + .shader_location, + *vertex_buffer.1, + 0, + ); + } } + if let Some(index_buffer) = bindings.index_buffer { draw.set_index_buffer(index_buffer, 0); } } - Ok(()) } } diff --git a/crates/bevy_render/src/mesh/mesh.rs b/crates/bevy_render/src/mesh/mesh.rs index 4bae0dc24aaed..2941c56092efe 100644 --- a/crates/bevy_render/src/mesh/mesh.rs +++ b/crates/bevy_render/src/mesh/mesh.rs @@ -14,6 +14,8 @@ use std::borrow::Cow; use thiserror::Error; use crate::pipeline::InputStepMode; +use std::hash::{Hash, Hasher}; +use bevy_utils::HashMap; pub const VERTEX_BUFFER_ASSET_INDEX: usize = 1; pub const INDEX_BUFFER_ASSET_INDEX: usize = 0; @@ -62,32 +64,47 @@ impl From<&VertexAttributeValues> for VertexFormat { } #[derive(Debug)] -pub struct VertexAttribute { +pub struct VertexAttributeData { + //TODO: replace by tuple? pub name: Cow<'static, str>, - pub values: VertexAttributeValues, + pub values: VertexAttributeValues, //TODO: the values aren't necessarily needed after been submitted to the GPU } -impl VertexAttribute { - pub const NORMAL: &'static str = "Vertex_Normal"; - pub const POSITION: &'static str = "Vertex_Position"; - pub const UV: &'static str = "Vertex_Uv"; +impl PartialEq for VertexAttributeData { + fn eq(&self, other: &Self) -> bool { + self.name == other.name + } +} + +impl Hash for VertexAttributeData { + fn hash(&self, state: &mut H) { + self.name.hash(state); + } +} + +impl Eq for VertexAttributeData {} + +impl VertexAttributeData { + pub const NORMAL: &'static str = "normal_os"; + pub const POSITION: &'static str = "position_os"; + pub const UV: &'static str = "uv_vertex"; pub fn position(positions: Vec<[f32; 3]>) -> Self { - VertexAttribute { + VertexAttributeData { name: Self::POSITION.into(), values: VertexAttributeValues::Float3(positions), } } pub fn normal(normals: Vec<[f32; 3]>) -> Self { - VertexAttribute { + VertexAttributeData { name: Self::NORMAL.into(), values: VertexAttributeValues::Float3(normals), } } pub fn uv(uvs: Vec<[f32; 2]>) -> Self { - VertexAttribute { + VertexAttributeData { name: Self::UV.into(), values: VertexAttributeValues::Float2(uvs), } @@ -115,19 +132,48 @@ pub enum Indices { #[derive(Debug)] pub struct Mesh { pub primitive_topology: PrimitiveTopology, - pub attributes: Vec, + attributes: HashMap, VertexAttributeData>, pub indices: Option, } impl Mesh { - pub fn new(primitive_topology: PrimitiveTopology) -> Self { + pub fn new( + primitive_topology: PrimitiveTopology, + mut attributes: Vec, + indices: Option, + ) -> Self { + let mut mesh = Mesh { + primitive_topology, + attributes: HashMap::default(), + indices, + }; + for attribute in attributes.drain(..) { + mesh.insert_attribute(attribute); + } + mesh + } + + pub fn new_empty(primitive_topology: PrimitiveTopology) -> Self { Mesh { primitive_topology, - attributes: Vec::new(), + attributes: HashMap::default(), indices: None, } } + pub fn insert_attribute(&mut self, new_vertex_attribute: VertexAttributeData) { + self.attributes + .insert(new_vertex_attribute.name.clone(), new_vertex_attribute); //TODO: is .clone() correct? + } + + pub fn get_attribute(&mut self, name: Cow<'static, str>) -> Option<&VertexAttributeData> { + self.attributes.get(&name.clone()) //Todo julian: clone?? + } + + pub fn remove_attribute(&mut self, name: Cow<'static, str>) { + self.attributes.remove(&name); + } + pub fn get_index_buffer_bytes(&self) -> Option> { self.indices.as_ref().map(|indices| match &indices { Indices::U16(indices) => indices.as_slice().as_bytes().to_vec(), @@ -138,7 +184,7 @@ impl Mesh { /// Generation for some primitive shape meshes. pub mod shape { - use super::{Indices, Mesh, VertexAttribute}; + use super::{Indices, Mesh, VertexAttributeData}; use crate::pipeline::PrimitiveTopology; use bevy_math::*; use hexasphere::Hexasphere; @@ -209,15 +255,15 @@ pub mod shape { 20, 21, 22, 22, 23, 20, // back ]); - Mesh { - primitive_topology: PrimitiveTopology::TriangleList, - attributes: vec![ - VertexAttribute::position(positions), - VertexAttribute::normal(normals), - VertexAttribute::uv(uvs), + Mesh::new( + PrimitiveTopology::TriangleList, + vec![ + VertexAttributeData::position(positions), + VertexAttributeData::normal(normals), + VertexAttributeData::uv(uvs), ], - indices: Some(indices), - } + Some(indices), + ) } } @@ -307,15 +353,15 @@ pub mod shape { uvs.push(*uv); } - Mesh { - primitive_topology: PrimitiveTopology::TriangleList, - attributes: vec![ - VertexAttribute::position(positions), - VertexAttribute::normal(normals), - VertexAttribute::uv(uvs), + Mesh::new( + PrimitiveTopology::TriangleList, + vec![ + VertexAttributeData::position(positions), + VertexAttributeData::normal(normals), + VertexAttributeData::uv(uvs), ], - indices: Some(indices), - } + Some(indices), + ) } } @@ -347,15 +393,15 @@ pub mod shape { uvs.push(*uv); } - Mesh { - primitive_topology: PrimitiveTopology::TriangleList, - attributes: vec![ - VertexAttribute::position(positions), - VertexAttribute::normal(normals), - VertexAttribute::uv(uvs), + Mesh::new( + PrimitiveTopology::TriangleList, + vec![ + VertexAttributeData::position(positions), + VertexAttributeData::normal(normals), + VertexAttributeData::uv(uvs), ], - indices: Some(indices), - } + Some(indices), + ) } } @@ -420,15 +466,15 @@ pub mod shape { let indices = Indices::U32(indices); - Mesh { - primitive_topology: PrimitiveTopology::TriangleList, - attributes: vec![ - VertexAttribute::position(points), - VertexAttribute::normal(normals), - VertexAttribute::uv(uvs), + Mesh::new( + PrimitiveTopology::TriangleList, + vec![ + VertexAttributeData::position(points), + VertexAttributeData::normal(normals), + VertexAttributeData::uv(uvs), ], - indices: Some(indices), - } + Some(indices), + ) } } } @@ -437,6 +483,7 @@ fn remove_current_mesh_resources( render_resource_context: &dyn RenderResourceContext, handle: Handle, ) { + //TODO: julian, use correct ids if let Some(RenderResourceId::Buffer(buffer)) = render_resource_context.get_asset_resource(handle, VERTEX_BUFFER_ASSET_INDEX) { @@ -454,7 +501,14 @@ fn remove_current_mesh_resources( #[derive(Default)] pub struct MeshResourceProviderState { mesh_event_reader: EventReader>, - vertex_buffer_descriptor: Option<&'static VertexBufferDescriptor>, + vertex_buffer_descriptor: Option<&'static VertexBufferDescriptor>, //TODO: unused +} + +// TODO julian: embed into resource system +pub fn get_attribute_name_id(name: &str) -> usize { + let mut hasher = std::collections::hash_map::DefaultHasher::default(); + hasher.write(&name.as_bytes()); + hasher.finish() as usize //TODO: bad bad bad bad! this will likely break on 32 bit systems } pub fn mesh_resource_provider_system( @@ -466,15 +520,15 @@ pub fn mesh_resource_provider_system( mut query: Query<(&Handle, &mut RenderPipelines)>, ) { if state.vertex_buffer_descriptor.is_none() { - // TODO: allow pipelines to specialize on vertex_buffer_descriptor and index_format + // TODO: allow pipelines to specialize on vertex_buffer_descriptor let mut vertex_buffer_descriptors_: VertexBufferDescriptors = VertexBufferDescriptors { descriptors: Default::default(), }; vertex_buffer_descriptors_.descriptors.insert( - "Vertex_Position".to_string(), + Cow::from("position_os"), VertexBufferDescriptor::new_from_attribute( VertexAttributeDescriptor { - name: "Vertex_Position".into(), + name: "position_os".into(), offset: 0, format: VertexFormat::Float3, shader_location: 0, @@ -483,10 +537,10 @@ pub fn mesh_resource_provider_system( ), ); vertex_buffer_descriptors_.descriptors.insert( - "Vertex_Normal".to_string(), + Cow::from("normal_os"), VertexBufferDescriptor::new_from_attribute( VertexAttributeDescriptor { - name: "Vertex_Normal".into(), + name: "normal_os".into(), offset: 0, format: VertexFormat::Float3, shader_location: 1, @@ -495,10 +549,10 @@ pub fn mesh_resource_provider_system( ), ); vertex_buffer_descriptors_.descriptors.insert( - "Vertex_Uv".to_string(), + Cow::from("uv_vertex"), VertexBufferDescriptor::new_from_attribute( VertexAttributeDescriptor { - name: "Vertex_Uv".into(), + name: "uv_vertex".into(), offset: 0, format: VertexFormat::Float2, shader_location: 2, @@ -531,10 +585,25 @@ pub fn mesh_resource_provider_system( } } + // update changed mesh data for changed_mesh_handle in changed_meshes.iter() { if let Some(mesh) = meshes.get(changed_mesh_handle) { - let mut index = 1; // index 0 is reserved by INDEX_BUFFER_ASSET_INDEX - for attribute in &mesh.attributes { + // TODO: check for individual buffer changes + let index_buffer = render_resource_context.create_buffer_with_data( + BufferInfo { + buffer_usage: BufferUsage::INDEX, + ..Default::default() + }, + &mesh.get_index_buffer_bytes().unwrap(), + ); + + render_resource_context.set_asset_resource( + *changed_mesh_handle, + RenderResourceId::Buffer(index_buffer), + INDEX_BUFFER_ASSET_INDEX, + ); + + for attribute in mesh.attributes.values() { // TODO: use a staging buffer here let attribute_buffer = render_resource_context.create_buffer_with_data( BufferInfo { @@ -547,24 +616,9 @@ pub fn mesh_resource_provider_system( render_resource_context.set_asset_resource( *changed_mesh_handle, RenderResourceId::Buffer(attribute_buffer), - index, + get_attribute_name_id(&attribute.name), ); - index += 1; } - - let index_buffer = render_resource_context.create_buffer_with_data( - BufferInfo { - buffer_usage: BufferUsage::INDEX, - ..Default::default() - }, - &mesh.get_index_buffer_bytes().unwrap(), - ); - - render_resource_context.set_asset_resource( - *changed_mesh_handle, - RenderResourceId::Buffer(index_buffer), - INDEX_BUFFER_ASSET_INDEX, - ); } } @@ -586,14 +640,14 @@ pub fn mesh_resource_provider_system( } // set vertex buffers into bindings - for index in 1..4 { - //TODO: use actual vertex buffer count + for attribute in &vertex_buffer_descriptors.descriptors { + let attribute_name_id = get_attribute_name_id(&attribute.0); if let Some(RenderResourceId::Buffer(vertex_buffer)) = - render_resource_context.get_asset_resource(*handle, index) + render_resource_context.get_asset_resource(*handle, attribute_name_id) { render_pipelines .bindings - .set_vertex_buffer(index as u8, vertex_buffer); + .set_vertex_buffer(attribute_name_id, vertex_buffer); } } } diff --git a/crates/bevy_render/src/pipeline/pipeline.rs b/crates/bevy_render/src/pipeline/pipeline.rs index dbfcee93056d1..404ccf87d12bc 100644 --- a/crates/bevy_render/src/pipeline/pipeline.rs +++ b/crates/bevy_render/src/pipeline/pipeline.rs @@ -132,6 +132,7 @@ impl PipelineDescriptor { vertex_buffer_descriptors: Option<&VertexBufferDescriptors>, dynamic_bindings: &[DynamicBinding], ) { + println!("reflect layout"); let vertex_spirv = shaders.get(&self.shader_stages.vertex).unwrap(); let fragment_spirv = self .shader_stages diff --git a/crates/bevy_render/src/pipeline/render_pipelines.rs b/crates/bevy_render/src/pipeline/render_pipelines.rs index bc477a7bf6846..81d5ebc837a73 100644 --- a/crates/bevy_render/src/pipeline/render_pipelines.rs +++ b/crates/bevy_render/src/pipeline/render_pipelines.rs @@ -114,9 +114,18 @@ pub fn draw_render_pipelines_system( ], ) .unwrap(); + + // get pipeline layout to find binding spots for vertex buffer + let pipeline_descriptor = draw_context.get_pipeline_descriptor().unwrap(); + let pipeline_layout = pipeline_descriptor.layout.as_ref().unwrap(); draw_context - .set_vertex_buffers_from_bindings(&mut draw, &[&render_pipelines.bindings]) + .set_vertex_buffers_from_bindings( + &mut draw, + &[&render_pipelines.bindings], + pipeline_layout.vertex_buffer_descriptors.clone(), + ) //TODO julian: no clone? .unwrap(); + if let Some(indices) = index_range.clone() { draw.draw_indexed(indices, 0, 0..1); } diff --git a/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs b/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs index ef83270130644..361b3cbeaed66 100644 --- a/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs +++ b/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs @@ -1,6 +1,7 @@ use super::VertexFormat; use bevy_utils::HashMap; use std::borrow::Cow; +use std::hash::Hash; #[derive(Clone, Debug, Eq, PartialEq)] pub struct VertexBufferDescriptor { @@ -45,7 +46,7 @@ pub struct VertexAttributeDescriptor { #[derive(Default)] pub struct VertexBufferDescriptors { - pub descriptors: HashMap, + pub descriptors: HashMap, VertexBufferDescriptor>, } impl VertexBufferDescriptors { diff --git a/crates/bevy_render/src/renderer/render_resource/render_resource_bindings.rs b/crates/bevy_render/src/renderer/render_resource/render_resource_bindings.rs index a9a84362c04c0..c737854ea50ab 100644 --- a/crates/bevy_render/src/renderer/render_resource/render_resource_bindings.rs +++ b/crates/bevy_render/src/renderer/render_resource/render_resource_bindings.rs @@ -6,7 +6,6 @@ use crate::{ use bevy_asset::{Handle, HandleUntyped}; use bevy_utils::{HashMap, HashSet}; use std::{hash::Hash, ops::Range}; -use uuid::Uuid; #[derive(Clone, Eq, Debug)] pub enum RenderResourceBinding { @@ -104,10 +103,8 @@ pub enum BindGroupStatus { // PERF: if the bindings are scoped to a specific pipeline layout, then names could be replaced with indices here for a perf boost #[derive(Eq, PartialEq, Debug, Default, Clone)] pub struct RenderResourceBindings { - // TODO: remove this. it shouldn't be needed anymore - pub id: RenderResourceBindingsId, bindings: HashMap, - pub vertex_buffers: HashMap, + pub vertex_buffers: HashMap, pub index_buffer: Option, bind_groups: HashMap, bind_group_descriptors: HashMap>, @@ -139,19 +136,13 @@ impl RenderResourceBindings { for (name, binding) in render_resource_bindings.bindings.iter() { self.set(name, binding.clone()); } - - // for (name, (vertex_buffer, index_buffer)) in render_resource_bindings.vertex_buffers.iter() - // { - // - // self.set_vertex_buffer(name, *vertex_buffer, *index_buffer); - // } } - pub fn get_vertex_buffer(&self, slot: u8) -> Option { + pub fn get_vertex_buffer(&self, slot: usize) -> Option { self.vertex_buffers.get(&slot).cloned() } - pub fn set_vertex_buffer(&mut self, slot: u8, vertex_buffer: BufferId) { + pub fn set_vertex_buffer(&mut self, slot: usize, vertex_buffer: BufferId) { self.vertex_buffers.insert(slot, vertex_buffer); } @@ -273,15 +264,6 @@ impl AssetRenderResourceBindings { } } -#[derive(Hash, Eq, PartialEq, Debug, Copy, Clone)] -pub struct RenderResourceBindingsId(Uuid); - -impl Default for RenderResourceBindingsId { - fn default() -> Self { - RenderResourceBindingsId(Uuid::new_v4()) - } -} - #[cfg(test)] mod tests { use super::*; diff --git a/crates/bevy_render/src/shader/shader_reflect.rs b/crates/bevy_render/src/shader/shader_reflect.rs index 680fad92eb117..6bbbf19813040 100644 --- a/crates/bevy_render/src/shader/shader_reflect.rs +++ b/crates/bevy_render/src/shader/shader_reflect.rs @@ -9,7 +9,7 @@ use bevy_core::AsBytes; use spirv_reflect::{ types::{ ReflectDescriptorBinding, ReflectDescriptorSet, ReflectDescriptorType, ReflectDimension, - ReflectInterfaceVariable, ReflectShaderStageFlags, ReflectTypeDescription, + ReflectShaderStageFlags, ReflectTypeDescription, ReflectTypeFlags, }, ShaderModule, @@ -41,13 +41,18 @@ impl ShaderLayout { // obtain attribute descriptors from reflection let mut vertex_attribute_descriptors = Vec::new(); for input_variable in module.enumerate_input_variables(None).unwrap() { - let vertex_attribute_descriptor = - reflect_vertex_attribute_descriptor(&input_variable); - if vertex_attribute_descriptor.name == GL_VERTEX_INDEX { + if input_variable.name == GL_VERTEX_INDEX { continue; } - - vertex_attribute_descriptors.push(vertex_attribute_descriptor); + // reflect vertex attribute descriptor and record it + vertex_attribute_descriptors.push(VertexAttributeDescriptor { + name: input_variable.name.clone().into(), + format: reflect_vertex_format( + input_variable.type_description.as_ref().unwrap(), + ), + offset: 0, + shader_location: input_variable.location, + }); } vertex_attribute_descriptors @@ -64,18 +69,25 @@ impl ShaderLayout { } else { let parts = vertex_attribute_descriptor .name - .splitn(3, '_') + .splitn(2, '_') .collect::>(); - if parts.len() == 3 { - if parts[0] == "I" { - instance = true; + match parts.len() { + 2 => { + //instancing enabled due "I" prefix + if parts[0] == "I" { + instance = true; + } + vertex_attribute_descriptor.name.to_string() + } + 1 => { + // regular attribute + vertex_attribute_descriptor.name.to_string() + } + _ => { + // illegal attribute + panic!("Vertex attributes must follow the form PROPERTYNAME. For example: Position"); } - vertex_attribute_descriptor.name.to_string() - } else if parts.len() == 2 { - vertex_attribute_descriptor.name.to_string() - } else { - panic!("Vertex attributes must follow the form BUFFERNAME_PROPERTYNAME. For example: Vertex_Position"); } } } else { @@ -83,7 +95,7 @@ impl ShaderLayout { } }; - // create a new buffer descriptor per buffer + // create a new buffer descriptor per attribute vertex_buffer_descriptors.push(VertexBufferDescriptor { attribute: vertex_attribute_descriptor, name: current_buffer_name.into(), @@ -107,17 +119,6 @@ impl ShaderLayout { } } -fn reflect_vertex_attribute_descriptor( - input_variable: &ReflectInterfaceVariable, -) -> VertexAttributeDescriptor { - VertexAttributeDescriptor { - name: input_variable.name.clone().into(), - format: reflect_vertex_format(input_variable.type_description.as_ref().unwrap()), - offset: 0, - shader_location: input_variable.location, - } -} - fn reflect_bind_group( descriptor_set: &ReflectDescriptorSet, shader_stage: ReflectShaderStageFlags, @@ -335,8 +336,8 @@ mod tests { ShaderStage::Vertex, r#" #version 450 - layout(location = 0) in vec4 Vertex_Position; - layout(location = 1) in uvec4 Vertex_Normal; + layout(location = 0) in vec4 position_os; + layout(location = 1) in uvec4 normal_os; layout(location = 2) in uvec4 I_TestInstancing_Property; layout(location = 0) out vec4 v_Position; @@ -346,7 +347,7 @@ mod tests { layout(set = 1, binding = 0) uniform texture2D Texture; void main() { - v_Position = Vertex_Position; + v_Position = position_os; gl_Position = ViewProj * v_Position; } "#, @@ -361,7 +362,7 @@ mod tests { vertex_buffer_descriptors: vec![ VertexBufferDescriptor::new_from_attribute( VertexAttributeDescriptor { - name: "Vertex_Position".into(), + name: "position_os".into(), format: VertexFormat::Float4, offset: 0, shader_location: 0, @@ -371,7 +372,7 @@ mod tests { .test_zero_stride(), VertexBufferDescriptor::new_from_attribute( VertexAttributeDescriptor { - name: "Vertex_Normal".into(), + name: "normal_os".into(), format: VertexFormat::Uint4, offset: 0, shader_location: 1, diff --git a/crates/bevy_sprite/src/render/sprite.frag b/crates/bevy_sprite/src/render/sprite.frag index 9683598e2ed8c..d291b0e09a363 100644 --- a/crates/bevy_sprite/src/render/sprite.frag +++ b/crates/bevy_sprite/src/render/sprite.frag @@ -1,6 +1,6 @@ #version 450 -layout(location = 0) in vec2 v_Uv; +layout(location = 0) in vec2 v_uv; layout(location = 0) out vec4 o_Target; @@ -18,7 +18,7 @@ void main() { # ifdef COLORMATERIAL_TEXTURE color *= texture( sampler2D(ColorMaterial_texture, ColorMaterial_texture_sampler), - v_Uv); + v_uv); # endif o_Target = color; } diff --git a/crates/bevy_sprite/src/render/sprite.vert b/crates/bevy_sprite/src/render/sprite.vert index fe1619d14b7fc..81d73fff379c4 100644 --- a/crates/bevy_sprite/src/render/sprite.vert +++ b/crates/bevy_sprite/src/render/sprite.vert @@ -1,10 +1,10 @@ #version 450 -layout(location = 0) in vec3 Vertex_Position; -layout(location = 1) in vec3 Vertex_Normal; -layout(location = 2) in vec2 Vertex_Uv; +layout(location = 0) in vec3 position_os; +layout(location = 1) in vec3 normal_os; +layout(location = 2) in vec2 uv_vertex; -layout(location = 0) out vec2 v_Uv; +layout(location = 0) out vec2 v_uv; layout(set = 0, binding = 0) uniform Camera { mat4 ViewProj; @@ -18,7 +18,7 @@ layout(set = 2, binding = 1) uniform Sprite_size { }; void main() { - v_Uv = Vertex_Uv; - vec3 position = Vertex_Position * vec3(size, 1.0); + v_uv = uv_vertex; + vec3 position = position_os * vec3(size, 1.0); gl_Position = ViewProj * Model * vec4(position, 1.0); } \ No newline at end of file diff --git a/crates/bevy_sprite/src/render/sprite_sheet.frag b/crates/bevy_sprite/src/render/sprite_sheet.frag index 8c8d9217f08d1..83fbf99188ad5 100644 --- a/crates/bevy_sprite/src/render/sprite_sheet.frag +++ b/crates/bevy_sprite/src/render/sprite_sheet.frag @@ -1,6 +1,6 @@ #version 450 -layout(location = 0) in vec2 v_Uv; +layout(location = 0) in vec2 v_uv; layout(location = 1) in vec4 v_Color; layout(location = 0) out vec4 o_Target; @@ -11,5 +11,5 @@ layout(set = 1, binding = 3) uniform sampler TextureAtlas_texture_sampler; void main() { o_Target = v_Color * texture( sampler2D(TextureAtlas_texture, TextureAtlas_texture_sampler), - v_Uv); + v_uv); } diff --git a/crates/bevy_sprite/src/render/sprite_sheet.vert b/crates/bevy_sprite/src/render/sprite_sheet.vert index d967ac5411ba3..a3347b7601b8e 100644 --- a/crates/bevy_sprite/src/render/sprite_sheet.vert +++ b/crates/bevy_sprite/src/render/sprite_sheet.vert @@ -1,10 +1,10 @@ #version 450 -layout(location = 0) in vec3 Vertex_Position; -layout(location = 1) in vec3 Vertex_Normal; -layout(location = 2) in vec2 Vertex_Uv; +layout(location = 0) in vec3 position_os; +layout(location = 1) in vec3 normal_os; +layout(location = 2) in vec2 uv_vertex; -layout(location = 0) out vec2 v_Uv; +layout(location = 0) out vec2 v_uv; layout(location = 1) out vec4 v_Color; layout(set = 0, binding = 0) uniform Camera { @@ -38,14 +38,14 @@ layout(set = 2, binding = 1) uniform TextureAtlasSprite { void main() { Rect sprite_rect = Textures[TextureAtlasSprite_index]; vec2 sprite_dimensions = sprite_rect.end - sprite_rect.begin; - vec3 vertex_position = vec3(Vertex_Position.xy * sprite_dimensions, 0.0); + vec3 position_os = vec3(position_os.xy * sprite_dimensions, 0.0); vec2 atlas_positions[4] = vec2[]( vec2(sprite_rect.begin.x, sprite_rect.end.y), sprite_rect.begin, vec2(sprite_rect.end.x, sprite_rect.begin.y), sprite_rect.end ); - v_Uv = (atlas_positions[gl_VertexIndex] + vec2(0.01, 0.01)) / AtlasSize; + v_uv = (atlas_positions[gl_VertexIndex] + vec2(0.01, 0.01)) / AtlasSize; v_Color = TextureAtlasSprite_color; - gl_Position = ViewProj * SpriteTransform * vec4(ceil(vertex_position), 1.0); + gl_Position = ViewProj * SpriteTransform * vec4(ceil(position_os), 1.0); } \ No newline at end of file diff --git a/crates/bevy_ui/src/render/ui.frag b/crates/bevy_ui/src/render/ui.frag index 985f5006ed4d2..13b4c79a8c7d1 100644 --- a/crates/bevy_ui/src/render/ui.frag +++ b/crates/bevy_ui/src/render/ui.frag @@ -1,6 +1,6 @@ #version 450 -layout(location = 0) in vec2 v_Uv; +layout(location = 0) in vec2 v_uv; layout(location = 0) out vec4 o_Target; @@ -18,7 +18,7 @@ void main() { # ifdef COLORMATERIAL_TEXTURE color *= texture( sampler2D(ColorMaterial_texture, ColorMaterial_texture_sampler), - v_Uv); + v_uv); # endif o_Target = color; } diff --git a/crates/bevy_ui/src/render/ui.vert b/crates/bevy_ui/src/render/ui.vert index 2268af642b305..972446b462af0 100644 --- a/crates/bevy_ui/src/render/ui.vert +++ b/crates/bevy_ui/src/render/ui.vert @@ -1,10 +1,10 @@ #version 450 -layout(location = 0) in vec3 Vertex_Position; -layout(location = 1) in vec3 Vertex_Normal; -layout(location = 2) in vec2 Vertex_Uv; +layout(location = 0) in vec3 position_os; +layout(location = 1) in vec3 normal_os; +layout(location = 2) in vec2 uv_vertex; -layout(location = 0) out vec2 v_Uv; +layout(location = 0) out vec2 v_uv; layout(set = 0, binding = 0) uniform Camera { mat4 ViewProj; @@ -18,7 +18,7 @@ layout(set = 1, binding = 1) uniform Node_size { }; void main() { - v_Uv = Vertex_Uv; - vec3 position = Vertex_Position * vec3(NodeSize, 0.0); + v_uv = uv_vertex; + vec3 position = position_os * vec3(NodeSize, 0.0); gl_Position = ViewProj * Object * vec4(position, 1.0); } \ No newline at end of file diff --git a/examples/shader/shader_custom_material.rs b/examples/shader/shader_custom_material.rs index 784cdb7472674..4fd040e1dbd2a 100644 --- a/examples/shader/shader_custom_material.rs +++ b/examples/shader/shader_custom_material.rs @@ -25,7 +25,7 @@ struct MyMaterial { const VERTEX_SHADER: &str = r#" #version 450 -layout(location = 0) in vec3 Vertex_Position; +layout(location = 0) in vec3 position_os; layout(set = 0, binding = 0) uniform Camera { mat4 ViewProj; }; @@ -33,7 +33,7 @@ layout(set = 1, binding = 0) uniform Transform { mat4 Model; }; void main() { - gl_Position = ViewProj * Model * vec4(Vertex_Position, 1.0); + gl_Position = ViewProj * Model * vec4(position_os, 1.0); } "#; diff --git a/examples/shader/shader_defs.rs b/examples/shader/shader_defs.rs index b46ca1c5fb731..d237933d3b1cd 100644 --- a/examples/shader/shader_defs.rs +++ b/examples/shader/shader_defs.rs @@ -33,7 +33,7 @@ struct MyMaterial { const VERTEX_SHADER: &str = r#" #version 450 -layout(location = 0) in vec3 Vertex_Position; +layout(location = 0) in vec3 position_os; layout(set = 0, binding = 0) uniform Camera { mat4 ViewProj; }; @@ -41,7 +41,7 @@ layout(set = 1, binding = 0) uniform Transform { mat4 Model; }; void main() { - gl_Position = ViewProj * Model * vec4(Vertex_Position, 1.0); + gl_Position = ViewProj * Model * vec4(position_os, 1.0); } "#; From 66640b730eca38f8c9bc070652d1bb679f3763a9 Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Mon, 5 Oct 2020 00:19:06 +0200 Subject: [PATCH 07/32] simplified shader vertex attribute reflection, removed VertexBufferDescriptors --- .../forward_pipeline/forward.vert | 2 +- crates/bevy_render/src/draw.rs | 14 +-- crates/bevy_render/src/lib.rs | 3 +- crates/bevy_render/src/mesh/mesh.rs | 92 +++++-------------- crates/bevy_render/src/pipeline/pipeline.rs | 15 ++- .../src/pipeline/pipeline_compiler.rs | 4 +- .../src/pipeline/pipeline_layout.rs | 26 +----- .../src/pipeline/render_pipelines.rs | 9 +- .../src/pipeline/vertex_buffer_descriptor.rs | 17 ---- .../bevy_render/src/shader/shader_reflect.rs | 24 +---- 10 files changed, 49 insertions(+), 157 deletions(-) diff --git a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.vert b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.vert index 756f5409e1c81..f03c22cc73c17 100644 --- a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.vert +++ b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.vert @@ -21,5 +21,5 @@ void main() { normal_world = mat3(Model) * normal_os; position_world = (Model * vec4(position_os, 1.0)).xyz; v_uv = uv_vertex; - gl_Position = ViewProj * vec4(position_os, 1.0); + gl_Position = ViewProj * vec4(position_world, 1.0); } diff --git a/crates/bevy_render/src/draw.rs b/crates/bevy_render/src/draw.rs index 6599bd7b12fb5..774467a880db4 100644 --- a/crates/bevy_render/src/draw.rs +++ b/crates/bevy_render/src/draw.rs @@ -2,7 +2,6 @@ use crate::pipeline::VertexBufferDescriptor; use crate::{ pipeline::{ PipelineCompiler, PipelineDescriptor, PipelineLayout, PipelineSpecialization, - VertexBufferDescriptors, }, renderer::{ BindGroup, BindGroupId, BufferId, BufferUsage, RenderResource, RenderResourceBinding, @@ -129,7 +128,6 @@ pub struct DrawContext<'a> { pub shaders: ResMut<'a, Assets>, pub pipeline_compiler: ResMut<'a, PipelineCompiler>, pub render_resource_context: Res<'a, Box>, - pub vertex_buffer_descriptors: Res<'a, VertexBufferDescriptors>, pub shared_buffers: Res<'a, SharedBuffers>, pub current_pipeline: Option>, } @@ -141,7 +139,6 @@ impl<'a> UnsafeClone for DrawContext<'a> { shaders: self.shaders.unsafe_clone(), pipeline_compiler: self.pipeline_compiler.unsafe_clone(), render_resource_context: self.render_resource_context.unsafe_clone(), - vertex_buffer_descriptors: self.vertex_buffer_descriptors.unsafe_clone(), shared_buffers: self.shared_buffers.unsafe_clone(), current_pipeline: self.current_pipeline, } @@ -163,7 +160,6 @@ impl<'a> FetchResource<'a> for FetchDrawContext { resources.borrow_mut::>(); resources.borrow_mut::(); resources.borrow::>(); - resources.borrow::(); resources.borrow::(); } @@ -172,7 +168,6 @@ impl<'a> FetchResource<'a> for FetchDrawContext { resources.release_mut::>(); resources.release_mut::(); resources.release::>(); - resources.release::(); resources.release::(); } @@ -202,9 +197,6 @@ impl<'a> FetchResource<'a> for FetchDrawContext { render_resource_context: Res::new( resources.get_unsafe_ref::>(ResourceIndex::Global), ), - vertex_buffer_descriptors: Res::new( - resources.get_unsafe_ref::(ResourceIndex::Global), - ), shared_buffers: Res::new( resources.get_unsafe_ref::(ResourceIndex::Global), ), @@ -222,9 +214,6 @@ impl<'a> FetchResource<'a> for FetchDrawContext { access .immutable .insert(TypeId::of::>()); - access - .immutable - .insert(TypeId::of::()); access.immutable.insert(TypeId::of::()); access } @@ -265,7 +254,6 @@ impl<'a> DrawContext<'a> { &mut self.pipelines, &mut self.shaders, pipeline_handle, - &self.vertex_buffer_descriptors, specialization, ) }; @@ -342,7 +330,7 @@ impl<'a> DrawContext<'a> { &self, draw: &mut Draw, render_resource_bindings: &[&RenderResourceBindings], - vertex_buffer_descriptors: Vec, + vertex_buffer_descriptors: &[VertexBufferDescriptor], ) -> Result<(), DrawError> { for bindings in render_resource_bindings.iter() { for vertex_buffer in &bindings.vertex_buffers { diff --git a/crates/bevy_render/src/lib.rs b/crates/bevy_render/src/lib.rs index 0bdcf8a7bbde1..ce14af98b7d33 100644 --- a/crates/bevy_render/src/lib.rs +++ b/crates/bevy_render/src/lib.rs @@ -38,7 +38,7 @@ use camera::{ }; use pipeline::{ DynamicBinding, PipelineCompiler, PipelineDescriptor, PipelineSpecialization, - PrimitiveTopology, ShaderSpecialization, VertexBufferDescriptors, + PrimitiveTopology, ShaderSpecialization, }; use render_graph::{ base::{self, BaseRenderGraphBuilder, BaseRenderGraphConfig}, @@ -114,7 +114,6 @@ impl Plugin for RenderPlugin { .init_resource::() .init_resource::() .init_resource::() - .init_resource::() .init_resource::() .init_resource::() .init_resource::() diff --git a/crates/bevy_render/src/mesh/mesh.rs b/crates/bevy_render/src/mesh/mesh.rs index 2941c56092efe..7b7c77e799d04 100644 --- a/crates/bevy_render/src/mesh/mesh.rs +++ b/crates/bevy_render/src/mesh/mesh.rs @@ -1,19 +1,18 @@ use crate::{ pipeline::{ - PrimitiveTopology, RenderPipelines, VertexAttributeDescriptor, VertexBufferDescriptor, - VertexBufferDescriptors, VertexFormat, + PrimitiveTopology, RenderPipelines, + VertexFormat, }, renderer::{BufferInfo, BufferUsage, RenderResourceContext, RenderResourceId}, }; use bevy_app::prelude::{EventReader, Events}; use bevy_asset::{AssetEvent, Assets, Handle}; use bevy_core::AsBytes; -use bevy_ecs::{Local, Query, Res, ResMut}; +use bevy_ecs::{Local, Query, Res}; use bevy_math::*; use std::borrow::Cow; use thiserror::Error; -use crate::pipeline::InputStepMode; use std::hash::{Hash, Hasher}; use bevy_utils::HashMap; @@ -174,6 +173,10 @@ impl Mesh { self.attributes.remove(&name); } + pub fn iter_attribute(&self) -> std::collections::hash_map::Iter<'_, Cow<'static, str>, VertexAttributeData> { + self.attributes.iter() + } + pub fn get_index_buffer_bytes(&self) -> Option> { self.indices.as_ref().map(|indices| match &indices { Indices::U16(indices) => indices.as_slice().as_bytes().to_vec(), @@ -501,7 +504,6 @@ fn remove_current_mesh_resources( #[derive(Default)] pub struct MeshResourceProviderState { mesh_event_reader: EventReader>, - vertex_buffer_descriptor: Option<&'static VertexBufferDescriptor>, //TODO: unused } // TODO julian: embed into resource system @@ -515,56 +517,9 @@ pub fn mesh_resource_provider_system( mut state: Local, render_resource_context: Res>, meshes: Res>, - mut vertex_buffer_descriptors: ResMut, mesh_events: Res>>, mut query: Query<(&Handle, &mut RenderPipelines)>, ) { - if state.vertex_buffer_descriptor.is_none() { - // TODO: allow pipelines to specialize on vertex_buffer_descriptor - let mut vertex_buffer_descriptors_: VertexBufferDescriptors = VertexBufferDescriptors { - descriptors: Default::default(), - }; - vertex_buffer_descriptors_.descriptors.insert( - Cow::from("position_os"), - VertexBufferDescriptor::new_from_attribute( - VertexAttributeDescriptor { - name: "position_os".into(), - offset: 0, - format: VertexFormat::Float3, - shader_location: 0, - }, - InputStepMode::Vertex, - ), - ); - vertex_buffer_descriptors_.descriptors.insert( - Cow::from("normal_os"), - VertexBufferDescriptor::new_from_attribute( - VertexAttributeDescriptor { - name: "normal_os".into(), - offset: 0, - format: VertexFormat::Float3, - shader_location: 1, - }, - InputStepMode::Vertex, - ), - ); - vertex_buffer_descriptors_.descriptors.insert( - Cow::from("uv_vertex"), - VertexBufferDescriptor::new_from_attribute( - VertexAttributeDescriptor { - name: "uv_vertex".into(), - offset: 0, - format: VertexFormat::Float2, - shader_location: 2, - }, - InputStepMode::Vertex, - ), - ); - vertex_buffer_descriptors - .descriptors - .extend(vertex_buffer_descriptors_.descriptors); - } - let mut changed_meshes = bevy_utils::HashSet::>::default(); let render_resource_context = &**render_resource_context; for event in state.mesh_event_reader.iter(&mesh_events) { @@ -622,33 +577,36 @@ pub fn mesh_resource_provider_system( } } + // handover buffers to pipeline // TODO: remove this once batches are pipeline specific and deprecate assigned_meshes draw target for (handle, mut render_pipelines) in &mut query.iter() { if let Some(mesh) = meshes.get(&handle) { for render_pipeline in render_pipelines.pipelines.iter_mut() { render_pipeline.specialization.primitive_topology = mesh.primitive_topology; } - } - if let Some(RenderResourceId::Buffer(index_buffer_resource)) = + if let Some(RenderResourceId::Buffer(index_buffer_resource)) = render_resource_context.get_asset_resource(*handle, INDEX_BUFFER_ASSET_INDEX) - { - // set index buffer into binding - render_pipelines - .bindings - .set_index_buffer(index_buffer_resource); - } - - // set vertex buffers into bindings - for attribute in &vertex_buffer_descriptors.descriptors { - let attribute_name_id = get_attribute_name_id(&attribute.0); - if let Some(RenderResourceId::Buffer(vertex_buffer)) = - render_resource_context.get_asset_resource(*handle, attribute_name_id) { + // set index buffer into binding render_pipelines .bindings - .set_vertex_buffer(attribute_name_id, vertex_buffer); + .set_index_buffer(index_buffer_resource); + } + + // set vertex buffers into bindings + for attribute in mesh.iter_attribute() { + let attribute_name_id = get_attribute_name_id(&attribute.0); + if let Some(RenderResourceId::Buffer(vertex_buffer)) = + render_resource_context.get_asset_resource(*handle, attribute_name_id) + { + render_pipelines + .bindings + .set_vertex_buffer(attribute_name_id, vertex_buffer); + } } } + + } } diff --git a/crates/bevy_render/src/pipeline/pipeline.rs b/crates/bevy_render/src/pipeline/pipeline.rs index 404ccf87d12bc..3789a3aa07491 100644 --- a/crates/bevy_render/src/pipeline/pipeline.rs +++ b/crates/bevy_render/src/pipeline/pipeline.rs @@ -4,13 +4,14 @@ use super::{ CompareFunction, CullMode, DepthStencilStateDescriptor, FrontFace, IndexFormat, PrimitiveTopology, RasterizationStateDescriptor, StencilStateFaceDescriptor, }, - BindType, DynamicBinding, PipelineLayout, StencilStateDescriptor, VertexBufferDescriptors, + BindType, DynamicBinding, PipelineLayout, StencilStateDescriptor, }; use crate::{ shader::{Shader, ShaderStages}, texture::TextureFormat, }; use bevy_asset::Assets; +use crate::shader::GL_VERTEX_INDEX; #[derive(Clone, Debug)] pub struct PipelineDescriptor { @@ -129,7 +130,6 @@ impl PipelineDescriptor { &mut self, shaders: &Assets, bevy_conventions: bool, - vertex_buffer_descriptors: Option<&VertexBufferDescriptors>, dynamic_bindings: &[DynamicBinding], ) { println!("reflect layout"); @@ -146,9 +146,14 @@ impl PipelineDescriptor { } let mut layout = PipelineLayout::from_shader_layouts(&mut layouts); - if let Some(vertex_buffer_descriptors) = vertex_buffer_descriptors { - // complete the layout with the user defined descriptors - layout.sync_vertex_buffer_descriptors(vertex_buffer_descriptors); + + // just obtain the stride from the attribute itself, since we are always using float format + // TODO: support for different formats? + for vertex_buffer_descriptor in &mut layout.vertex_buffer_descriptors { + if vertex_buffer_descriptor.name == GL_VERTEX_INDEX { + continue; + } + vertex_buffer_descriptor.stride = vertex_buffer_descriptor.attribute.format.get_size(); } if !dynamic_bindings.is_empty() { diff --git a/crates/bevy_render/src/pipeline/pipeline_compiler.rs b/crates/bevy_render/src/pipeline/pipeline_compiler.rs index b696aa3182a32..79cf7f774b46e 100644 --- a/crates/bevy_render/src/pipeline/pipeline_compiler.rs +++ b/crates/bevy_render/src/pipeline/pipeline_compiler.rs @@ -1,5 +1,5 @@ use super::{ - state_descriptors::PrimitiveTopology, IndexFormat, PipelineDescriptor, VertexBufferDescriptors, + state_descriptors::PrimitiveTopology, IndexFormat, PipelineDescriptor, }; use crate::{ renderer::RenderResourceContext, @@ -134,7 +134,6 @@ impl PipelineCompiler { pipelines: &mut Assets, shaders: &mut Assets, source_pipeline: Handle, - vertex_buffer_descriptors: &VertexBufferDescriptors, pipeline_specialization: &PipelineSpecialization, ) -> Handle { let source_descriptor = pipelines.get(&source_pipeline).unwrap(); @@ -159,7 +158,6 @@ impl PipelineCompiler { specialized_descriptor.reflect_layout( shaders, true, - Some(vertex_buffer_descriptors), &pipeline_specialization.dynamic_bindings, ); diff --git a/crates/bevy_render/src/pipeline/pipeline_layout.rs b/crates/bevy_render/src/pipeline/pipeline_layout.rs index 8e8505873ffb9..7069e1dca411b 100644 --- a/crates/bevy_render/src/pipeline/pipeline_layout.rs +++ b/crates/bevy_render/src/pipeline/pipeline_layout.rs @@ -1,5 +1,5 @@ -use super::{BindGroupDescriptor, VertexBufferDescriptor, VertexBufferDescriptors}; -use crate::shader::{ShaderLayout, GL_VERTEX_INDEX}; +use super::{BindGroupDescriptor, VertexBufferDescriptor}; +use crate::shader::ShaderLayout; use bevy_utils::HashMap; use std::hash::Hash; @@ -67,28 +67,6 @@ impl PipelineLayout { vertex_buffer_descriptors, } } - - pub fn sync_vertex_buffer_descriptors( - &mut self, - vertex_buffer_descriptors: &VertexBufferDescriptors, - ) { - for vertex_buffer_descriptor in self.vertex_buffer_descriptors.iter_mut() { - if let Some(graph_descriptor) = - vertex_buffer_descriptors.get(&vertex_buffer_descriptor.name) - { - vertex_buffer_descriptor.attribute.offset = graph_descriptor.attribute.offset; - vertex_buffer_descriptor.stride = graph_descriptor.stride; - } else if vertex_buffer_descriptor.name == GL_VERTEX_INDEX { - // GL_VERTEX_INDEX is a special attribute set on our behalf - continue; - } else { - panic!( - "Encountered unsupported Vertex Buffer: {}", - vertex_buffer_descriptor.name - ); - } - } - } } #[derive(Hash, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] diff --git a/crates/bevy_render/src/pipeline/render_pipelines.rs b/crates/bevy_render/src/pipeline/render_pipelines.rs index 81d5ebc837a73..221b3045a83be 100644 --- a/crates/bevy_render/src/pipeline/render_pipelines.rs +++ b/crates/bevy_render/src/pipeline/render_pipelines.rs @@ -115,15 +115,18 @@ pub fn draw_render_pipelines_system( ) .unwrap(); - // get pipeline layout to find binding spots for vertex buffer + // get pipeline layout to find binding slots for vertex buffers let pipeline_descriptor = draw_context.get_pipeline_descriptor().unwrap(); let pipeline_layout = pipeline_descriptor.layout.as_ref().unwrap(); + + //TODO julian: check for unbound slots + //TODO julian: validate buffers for size? draw_context .set_vertex_buffers_from_bindings( &mut draw, &[&render_pipelines.bindings], - pipeline_layout.vertex_buffer_descriptors.clone(), - ) //TODO julian: no clone? + &pipeline_layout.vertex_buffer_descriptors, + ) .unwrap(); if let Some(indices) = index_range.clone() { diff --git a/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs b/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs index 361b3cbeaed66..889ad573815cd 100644 --- a/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs +++ b/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs @@ -1,5 +1,4 @@ use super::VertexFormat; -use bevy_utils::HashMap; use std::borrow::Cow; use std::hash::Hash; @@ -43,19 +42,3 @@ pub struct VertexAttributeDescriptor { pub format: VertexFormat, pub shader_location: u32, } - -#[derive(Default)] -pub struct VertexBufferDescriptors { - pub descriptors: HashMap, VertexBufferDescriptor>, -} - -impl VertexBufferDescriptors { - pub fn set_many(&mut self, vertex_buffer_descriptor: VertexBufferDescriptors) { - self.descriptors - .extend(vertex_buffer_descriptor.descriptors); - } - - pub fn get(&self, name: &str) -> Option<&VertexBufferDescriptor> { - self.descriptors.get(name) - } -} diff --git a/crates/bevy_render/src/shader/shader_reflect.rs b/crates/bevy_render/src/shader/shader_reflect.rs index 6bbbf19813040..31db938fbabc2 100644 --- a/crates/bevy_render/src/shader/shader_reflect.rs +++ b/crates/bevy_render/src/shader/shader_reflect.rs @@ -67,28 +67,8 @@ impl ShaderLayout { if vertex_attribute_descriptor.name == GL_VERTEX_INDEX { GL_VERTEX_INDEX.to_string() } else { - let parts = vertex_attribute_descriptor - .name - .splitn(2, '_') - .collect::>(); - - match parts.len() { - 2 => { - //instancing enabled due "I" prefix - if parts[0] == "I" { - instance = true; - } - vertex_attribute_descriptor.name.to_string() - } - 1 => { - // regular attribute - vertex_attribute_descriptor.name.to_string() - } - _ => { - // illegal attribute - panic!("Vertex attributes must follow the form PROPERTYNAME. For example: Position"); - } - } + instance = vertex_attribute_descriptor.name.starts_with("I_"); + vertex_attribute_descriptor.name.to_string() } } else { "DefaultVertex".to_string() From 519b6b0a99d8595a3b28a0b265928116242cd3b5 Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Mon, 5 Oct 2020 00:23:54 +0200 Subject: [PATCH 08/32] format --- crates/bevy_render/src/draw.rs | 8 ++------ crates/bevy_render/src/mesh/mesh.rs | 17 +++++++---------- crates/bevy_render/src/pipeline/pipeline.rs | 2 +- .../src/pipeline/pipeline_compiler.rs | 4 +--- crates/bevy_render/src/shader/shader_reflect.rs | 3 +-- 5 files changed, 12 insertions(+), 22 deletions(-) diff --git a/crates/bevy_render/src/draw.rs b/crates/bevy_render/src/draw.rs index 774467a880db4..db1ff40a65d7c 100644 --- a/crates/bevy_render/src/draw.rs +++ b/crates/bevy_render/src/draw.rs @@ -1,8 +1,6 @@ use crate::pipeline::VertexBufferDescriptor; use crate::{ - pipeline::{ - PipelineCompiler, PipelineDescriptor, PipelineLayout, PipelineSpecialization, - }, + pipeline::{PipelineCompiler, PipelineDescriptor, PipelineLayout, PipelineSpecialization}, renderer::{ BindGroup, BindGroupId, BufferId, BufferUsage, RenderResource, RenderResourceBinding, RenderResourceBindings, RenderResourceContext, SharedBuffers, @@ -340,9 +338,7 @@ impl<'a> DrawContext<'a> { .find(|&x| *vertex_buffer.0 == crate::mesh::get_attribute_name_id(&x.name)) { draw.set_vertex_buffer( - vertex_attribute_descriptor - .attribute - .shader_location, + vertex_attribute_descriptor.attribute.shader_location, *vertex_buffer.1, 0, ); diff --git a/crates/bevy_render/src/mesh/mesh.rs b/crates/bevy_render/src/mesh/mesh.rs index 7b7c77e799d04..e012abe734117 100644 --- a/crates/bevy_render/src/mesh/mesh.rs +++ b/crates/bevy_render/src/mesh/mesh.rs @@ -1,8 +1,5 @@ use crate::{ - pipeline::{ - PrimitiveTopology, RenderPipelines, - VertexFormat, - }, + pipeline::{PrimitiveTopology, RenderPipelines, VertexFormat}, renderer::{BufferInfo, BufferUsage, RenderResourceContext, RenderResourceId}, }; use bevy_app::prelude::{EventReader, Events}; @@ -13,8 +10,8 @@ use bevy_math::*; use std::borrow::Cow; use thiserror::Error; -use std::hash::{Hash, Hasher}; use bevy_utils::HashMap; +use std::hash::{Hash, Hasher}; pub const VERTEX_BUFFER_ASSET_INDEX: usize = 1; pub const INDEX_BUFFER_ASSET_INDEX: usize = 0; @@ -173,7 +170,9 @@ impl Mesh { self.attributes.remove(&name); } - pub fn iter_attribute(&self) -> std::collections::hash_map::Iter<'_, Cow<'static, str>, VertexAttributeData> { + pub fn iter_attribute( + &self, + ) -> std::collections::hash_map::Iter<'_, Cow<'static, str>, VertexAttributeData> { self.attributes.iter() } @@ -586,7 +585,7 @@ pub fn mesh_resource_provider_system( } if let Some(RenderResourceId::Buffer(index_buffer_resource)) = - render_resource_context.get_asset_resource(*handle, INDEX_BUFFER_ASSET_INDEX) + render_resource_context.get_asset_resource(*handle, INDEX_BUFFER_ASSET_INDEX) { // set index buffer into binding render_pipelines @@ -598,7 +597,7 @@ pub fn mesh_resource_provider_system( for attribute in mesh.iter_attribute() { let attribute_name_id = get_attribute_name_id(&attribute.0); if let Some(RenderResourceId::Buffer(vertex_buffer)) = - render_resource_context.get_asset_resource(*handle, attribute_name_id) + render_resource_context.get_asset_resource(*handle, attribute_name_id) { render_pipelines .bindings @@ -606,7 +605,5 @@ pub fn mesh_resource_provider_system( } } } - - } } diff --git a/crates/bevy_render/src/pipeline/pipeline.rs b/crates/bevy_render/src/pipeline/pipeline.rs index 3789a3aa07491..e7f7bdb275cc9 100644 --- a/crates/bevy_render/src/pipeline/pipeline.rs +++ b/crates/bevy_render/src/pipeline/pipeline.rs @@ -6,12 +6,12 @@ use super::{ }, BindType, DynamicBinding, PipelineLayout, StencilStateDescriptor, }; +use crate::shader::GL_VERTEX_INDEX; use crate::{ shader::{Shader, ShaderStages}, texture::TextureFormat, }; use bevy_asset::Assets; -use crate::shader::GL_VERTEX_INDEX; #[derive(Clone, Debug)] pub struct PipelineDescriptor { diff --git a/crates/bevy_render/src/pipeline/pipeline_compiler.rs b/crates/bevy_render/src/pipeline/pipeline_compiler.rs index 79cf7f774b46e..add4ce27321bb 100644 --- a/crates/bevy_render/src/pipeline/pipeline_compiler.rs +++ b/crates/bevy_render/src/pipeline/pipeline_compiler.rs @@ -1,6 +1,4 @@ -use super::{ - state_descriptors::PrimitiveTopology, IndexFormat, PipelineDescriptor, -}; +use super::{state_descriptors::PrimitiveTopology, IndexFormat, PipelineDescriptor}; use crate::{ renderer::RenderResourceContext, shader::{Shader, ShaderSource}, diff --git a/crates/bevy_render/src/shader/shader_reflect.rs b/crates/bevy_render/src/shader/shader_reflect.rs index 31db938fbabc2..a9256daf782c6 100644 --- a/crates/bevy_render/src/shader/shader_reflect.rs +++ b/crates/bevy_render/src/shader/shader_reflect.rs @@ -9,8 +9,7 @@ use bevy_core::AsBytes; use spirv_reflect::{ types::{ ReflectDescriptorBinding, ReflectDescriptorSet, ReflectDescriptorType, ReflectDimension, - ReflectShaderStageFlags, ReflectTypeDescription, - ReflectTypeFlags, + ReflectShaderStageFlags, ReflectTypeDescription, ReflectTypeFlags, }, ShaderModule, }; From ae2e6703a13be24552f3c8fd4c4cda1544ad4977 Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Mon, 5 Oct 2020 00:26:26 +0200 Subject: [PATCH 09/32] format nightly --- crates/bevy_render/src/draw.rs | 6 ++++-- crates/bevy_render/src/pipeline/pipeline.rs | 3 +-- crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs | 3 +-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/bevy_render/src/draw.rs b/crates/bevy_render/src/draw.rs index db1ff40a65d7c..443fcf1871898 100644 --- a/crates/bevy_render/src/draw.rs +++ b/crates/bevy_render/src/draw.rs @@ -1,6 +1,8 @@ -use crate::pipeline::VertexBufferDescriptor; use crate::{ - pipeline::{PipelineCompiler, PipelineDescriptor, PipelineLayout, PipelineSpecialization}, + pipeline::{ + PipelineCompiler, PipelineDescriptor, PipelineLayout, PipelineSpecialization, + VertexBufferDescriptor, + }, renderer::{ BindGroup, BindGroupId, BufferId, BufferUsage, RenderResource, RenderResourceBinding, RenderResourceBindings, RenderResourceContext, SharedBuffers, diff --git a/crates/bevy_render/src/pipeline/pipeline.rs b/crates/bevy_render/src/pipeline/pipeline.rs index e7f7bdb275cc9..baa0170e6e0ac 100644 --- a/crates/bevy_render/src/pipeline/pipeline.rs +++ b/crates/bevy_render/src/pipeline/pipeline.rs @@ -6,9 +6,8 @@ use super::{ }, BindType, DynamicBinding, PipelineLayout, StencilStateDescriptor, }; -use crate::shader::GL_VERTEX_INDEX; use crate::{ - shader::{Shader, ShaderStages}, + shader::{Shader, ShaderStages, GL_VERTEX_INDEX}, texture::TextureFormat, }; use bevy_asset::Assets; diff --git a/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs b/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs index 889ad573815cd..2ea866ceb87ec 100644 --- a/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs +++ b/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs @@ -1,6 +1,5 @@ use super::VertexFormat; -use std::borrow::Cow; -use std::hash::Hash; +use std::{borrow::Cow, hash::Hash}; #[derive(Clone, Debug, Eq, PartialEq)] pub struct VertexBufferDescriptor { From 049e5a93cd64999688cade01dbe21e6826655eec Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Mon, 5 Oct 2020 13:23:39 +0200 Subject: [PATCH 10/32] Draw panics now when vertex buffer is missing; Name based hashmap for vertex_buffers in RenderResourceBinding --- crates/bevy_render/src/draw.rs | 17 ++++++++++------- crates/bevy_render/src/mesh/mesh.rs | 6 +++--- .../render_resource/render_resource_bindings.rs | 16 ++++++++++------ 3 files changed, 23 insertions(+), 16 deletions(-) diff --git a/crates/bevy_render/src/draw.rs b/crates/bevy_render/src/draw.rs index 443fcf1871898..2f4010628935f 100644 --- a/crates/bevy_render/src/draw.rs +++ b/crates/bevy_render/src/draw.rs @@ -333,17 +333,20 @@ impl<'a> DrawContext<'a> { vertex_buffer_descriptors: &[VertexBufferDescriptor], ) -> Result<(), DrawError> { for bindings in render_resource_bindings.iter() { - for vertex_buffer in &bindings.vertex_buffers { - // TODO: big ooof but works - if let Some(vertex_attribute_descriptor) = &vertex_buffer_descriptors - .iter() - .find(|&x| *vertex_buffer.0 == crate::mesh::get_attribute_name_id(&x.name)) + for vertex_buffer_descriptor in vertex_buffer_descriptors { + if let Some(vertex_buffer) = + bindings.vertex_buffers.get(&vertex_buffer_descriptor.name) { draw.set_vertex_buffer( - vertex_attribute_descriptor.attribute.shader_location, - *vertex_buffer.1, + vertex_buffer_descriptor.attribute.shader_location, + *vertex_buffer, 0, ); + } else { + panic!( + "Attribute {} is required by shader, but no vertex buffer was found.", + &vertex_buffer_descriptor.name + ); } } diff --git a/crates/bevy_render/src/mesh/mesh.rs b/crates/bevy_render/src/mesh/mesh.rs index e012abe734117..209894efe41c3 100644 --- a/crates/bevy_render/src/mesh/mesh.rs +++ b/crates/bevy_render/src/mesh/mesh.rs @@ -594,14 +594,14 @@ pub fn mesh_resource_provider_system( } // set vertex buffers into bindings - for attribute in mesh.iter_attribute() { - let attribute_name_id = get_attribute_name_id(&attribute.0); + for (name, _attribute) in mesh.iter_attribute() { + let attribute_name_id = get_attribute_name_id(&name); if let Some(RenderResourceId::Buffer(vertex_buffer)) = render_resource_context.get_asset_resource(*handle, attribute_name_id) { render_pipelines .bindings - .set_vertex_buffer(attribute_name_id, vertex_buffer); + .set_vertex_buffer(name.clone(), vertex_buffer); } } } diff --git a/crates/bevy_render/src/renderer/render_resource/render_resource_bindings.rs b/crates/bevy_render/src/renderer/render_resource/render_resource_bindings.rs index c737854ea50ab..a3ac744853c79 100644 --- a/crates/bevy_render/src/renderer/render_resource/render_resource_bindings.rs +++ b/crates/bevy_render/src/renderer/render_resource/render_resource_bindings.rs @@ -5,7 +5,7 @@ use crate::{ }; use bevy_asset::{Handle, HandleUntyped}; use bevy_utils::{HashMap, HashSet}; -use std::{hash::Hash, ops::Range}; +use std::{borrow::Cow, hash::Hash, ops::Range}; #[derive(Clone, Eq, Debug)] pub enum RenderResourceBinding { @@ -104,7 +104,7 @@ pub enum BindGroupStatus { #[derive(Eq, PartialEq, Debug, Default, Clone)] pub struct RenderResourceBindings { bindings: HashMap, - pub vertex_buffers: HashMap, + pub vertex_buffers: HashMap, BufferId>, pub index_buffer: Option, bind_groups: HashMap, bind_group_descriptors: HashMap>, @@ -138,12 +138,16 @@ impl RenderResourceBindings { } } - pub fn get_vertex_buffer(&self, slot: usize) -> Option { - self.vertex_buffers.get(&slot).cloned() + pub fn get_vertex_buffer(&self, attribute_name: Cow<'static, str>) -> Option { + self.vertex_buffers.get(&attribute_name).cloned() } - pub fn set_vertex_buffer(&mut self, slot: usize, vertex_buffer: BufferId) { - self.vertex_buffers.insert(slot, vertex_buffer); + pub fn set_vertex_buffer( + &mut self, + attribute_name: Cow<'static, str>, + vertex_buffer: BufferId, + ) { + self.vertex_buffers.insert(attribute_name, vertex_buffer); } pub fn set_index_buffer(&mut self, index_buffer: BufferId) { From 21bd3244767a16c39452bad022a900043fcd3200 Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Tue, 6 Oct 2020 02:09:04 +0200 Subject: [PATCH 11/32] added proper clean up for mesh resources (untested) --- crates/bevy_render/src/mesh/mesh.rs | 33 ++++++++++++------- .../src/pipeline/render_pipelines.rs | 2 -- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/crates/bevy_render/src/mesh/mesh.rs b/crates/bevy_render/src/mesh/mesh.rs index 209894efe41c3..002e40f14e008 100644 --- a/crates/bevy_render/src/mesh/mesh.rs +++ b/crates/bevy_render/src/mesh/mesh.rs @@ -163,7 +163,7 @@ impl Mesh { } pub fn get_attribute(&mut self, name: Cow<'static, str>) -> Option<&VertexAttributeData> { - self.attributes.get(&name.clone()) //Todo julian: clone?? + self.attributes.get(&name) } pub fn remove_attribute(&mut self, name: Cow<'static, str>) { @@ -484,14 +484,18 @@ pub mod shape { fn remove_current_mesh_resources( render_resource_context: &dyn RenderResourceContext, handle: Handle, + mesh: &Mesh, ) { - //TODO: julian, use correct ids - if let Some(RenderResourceId::Buffer(buffer)) = - render_resource_context.get_asset_resource(handle, VERTEX_BUFFER_ASSET_INDEX) - { - render_resource_context.remove_buffer(buffer); - render_resource_context.remove_asset_resource(handle, VERTEX_BUFFER_ASSET_INDEX); + for attribute in mesh.attributes.iter() { + if let Some(RenderResourceId::Buffer(buffer)) = + render_resource_context.get_asset_resource(handle, get_attribute_name_id(attribute.0)) + { + render_resource_context.remove_buffer(buffer); + render_resource_context + .remove_asset_resource(handle, get_attribute_name_id(attribute.0)); + } } + if let Some(RenderResourceId::Buffer(buffer)) = render_resource_context.get_asset_resource(handle, INDEX_BUFFER_ASSET_INDEX) { @@ -505,11 +509,10 @@ pub struct MeshResourceProviderState { mesh_event_reader: EventReader>, } -// TODO julian: embed into resource system pub fn get_attribute_name_id(name: &str) -> usize { let mut hasher = std::collections::hash_map::DefaultHasher::default(); hasher.write(&name.as_bytes()); - hasher.finish() as usize //TODO: bad bad bad bad! this will likely break on 32 bit systems + hasher.finish() as usize //TODO: this will likely break on 32 bit systems } pub fn mesh_resource_provider_system( @@ -528,10 +531,18 @@ pub fn mesh_resource_provider_system( } AssetEvent::Modified { handle } => { changed_meshes.insert(*handle); - remove_current_mesh_resources(render_resource_context, *handle); + remove_current_mesh_resources( + render_resource_context, + *handle, + meshes.get(handle).unwrap(), + ); } AssetEvent::Removed { handle } => { - remove_current_mesh_resources(render_resource_context, *handle); + remove_current_mesh_resources( + render_resource_context, + *handle, + meshes.get(handle).unwrap(), + ); // if mesh was modified and removed in the same update, ignore the modification // events are ordered so future modification events are ok changed_meshes.remove(handle); diff --git a/crates/bevy_render/src/pipeline/render_pipelines.rs b/crates/bevy_render/src/pipeline/render_pipelines.rs index 221b3045a83be..8bdc83c5c29bd 100644 --- a/crates/bevy_render/src/pipeline/render_pipelines.rs +++ b/crates/bevy_render/src/pipeline/render_pipelines.rs @@ -119,8 +119,6 @@ pub fn draw_render_pipelines_system( let pipeline_descriptor = draw_context.get_pipeline_descriptor().unwrap(); let pipeline_layout = pipeline_descriptor.layout.as_ref().unwrap(); - //TODO julian: check for unbound slots - //TODO julian: validate buffers for size? draw_context .set_vertex_buffers_from_bindings( &mut draw, From 5a09a47d60759ed5b63635d5fa3728c5d795b9a9 Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Tue, 6 Oct 2020 02:55:09 +0200 Subject: [PATCH 12/32] fixed bevy_text to work with new vertex system --- crates/bevy_render/src/mesh/mesh.rs | 1 - crates/bevy_text/src/draw.rs | 18 ++++++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/crates/bevy_render/src/mesh/mesh.rs b/crates/bevy_render/src/mesh/mesh.rs index 002e40f14e008..1f5aa1ce8827c 100644 --- a/crates/bevy_render/src/mesh/mesh.rs +++ b/crates/bevy_render/src/mesh/mesh.rs @@ -13,7 +13,6 @@ use thiserror::Error; use bevy_utils::HashMap; use std::hash::{Hash, Hasher}; -pub const VERTEX_BUFFER_ASSET_INDEX: usize = 1; pub const INDEX_BUFFER_ASSET_INDEX: usize = 0; #[derive(Clone, Debug)] pub enum VertexAttributeValues { diff --git a/crates/bevy_text/src/draw.rs b/crates/bevy_text/src/draw.rs index 18696e41a07ae..501d7e5d9c048 100644 --- a/crates/bevy_text/src/draw.rs +++ b/crates/bevy_text/src/draw.rs @@ -55,11 +55,21 @@ impl<'a> Drawable for DrawableText<'a> { )?; let render_resource_context = &**context.render_resource_context; - if let Some(RenderResourceId::Buffer(quad_vertex_buffer)) = render_resource_context - .get_asset_resource(bevy_sprite::QUAD_HANDLE, mesh::VERTEX_BUFFER_ASSET_INDEX) - { - draw.set_vertex_buffer(0, quad_vertex_buffer, 0); + let pipeline_layout = context.get_pipeline_layout().unwrap(); + + for vertex_buffer_descriptor in &pipeline_layout.vertex_buffer_descriptors { + let name_id = mesh::get_attribute_name_id(&vertex_buffer_descriptor.name); + if let Some(RenderResourceId::Buffer(vertex_attr_buffer_id)) = + render_resource_context.get_asset_resource(bevy_sprite::QUAD_HANDLE, name_id) + { + draw.set_vertex_buffer( + vertex_buffer_descriptor.attribute.shader_location, + vertex_attr_buffer_id, + 0, + ); + } } + let mut indices = 0..0; if let Some(RenderResourceId::Buffer(quad_index_buffer)) = render_resource_context .get_asset_resource(bevy_sprite::QUAD_HANDLE, mesh::INDEX_BUFFER_ASSET_INDEX) From f59bacd06fb6cedbfe6d50da74efdc33a3459e4e Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Wed, 7 Oct 2020 02:20:20 +0200 Subject: [PATCH 13/32] using fnv hash for vertex attributes; refactor --- crates/bevy_render/Cargo.toml | 2 +- crates/bevy_render/src/mesh/mesh.rs | 19 +++++++------------ .../src/pipeline/vertex_buffer_descriptor.rs | 11 ++++++++++- crates/bevy_text/src/draw.rs | 4 ++-- 4 files changed, 20 insertions(+), 16 deletions(-) diff --git a/crates/bevy_render/Cargo.toml b/crates/bevy_render/Cargo.toml index 8f62f575736d5..61d0d4dbed7b4 100644 --- a/crates/bevy_render/Cargo.toml +++ b/crates/bevy_render/Cargo.toml @@ -44,7 +44,7 @@ anyhow = "1.0" hex = "0.4.2" hexasphere = "1.0.0" parking_lot = "0.11.0" -lazy_static = "1.*" +fnv = "1.0.7" [target.'cfg(not(target_os = "ios"))'.dependencies] bevy-glsl-to-spirv = "0.1.7" diff --git a/crates/bevy_render/src/mesh/mesh.rs b/crates/bevy_render/src/mesh/mesh.rs index 1f5aa1ce8827c..8d301e8915b19 100644 --- a/crates/bevy_render/src/mesh/mesh.rs +++ b/crates/bevy_render/src/mesh/mesh.rs @@ -1,4 +1,5 @@ use crate::{ + pipeline, pipeline::{PrimitiveTopology, RenderPipelines, VertexFormat}, renderer::{BufferInfo, BufferUsage, RenderResourceContext, RenderResourceId}, }; @@ -158,7 +159,7 @@ impl Mesh { pub fn insert_attribute(&mut self, new_vertex_attribute: VertexAttributeData) { self.attributes - .insert(new_vertex_attribute.name.clone(), new_vertex_attribute); //TODO: is .clone() correct? + .insert(new_vertex_attribute.name.clone(), new_vertex_attribute); } pub fn get_attribute(&mut self, name: Cow<'static, str>) -> Option<&VertexAttributeData> { @@ -486,12 +487,12 @@ fn remove_current_mesh_resources( mesh: &Mesh, ) { for attribute in mesh.attributes.iter() { - if let Some(RenderResourceId::Buffer(buffer)) = - render_resource_context.get_asset_resource(handle, get_attribute_name_id(attribute.0)) + if let Some(RenderResourceId::Buffer(buffer)) = render_resource_context + .get_asset_resource(handle, pipeline::get_vertex_attribute_name_id(attribute.0)) { render_resource_context.remove_buffer(buffer); render_resource_context - .remove_asset_resource(handle, get_attribute_name_id(attribute.0)); + .remove_asset_resource(handle, pipeline::get_vertex_attribute_name_id(attribute.0)); } } @@ -508,12 +509,6 @@ pub struct MeshResourceProviderState { mesh_event_reader: EventReader>, } -pub fn get_attribute_name_id(name: &str) -> usize { - let mut hasher = std::collections::hash_map::DefaultHasher::default(); - hasher.write(&name.as_bytes()); - hasher.finish() as usize //TODO: this will likely break on 32 bit systems -} - pub fn mesh_resource_provider_system( mut state: Local, render_resource_context: Res>, @@ -580,7 +575,7 @@ pub fn mesh_resource_provider_system( render_resource_context.set_asset_resource( *changed_mesh_handle, RenderResourceId::Buffer(attribute_buffer), - get_attribute_name_id(&attribute.name), + pipeline::get_vertex_attribute_name_id(&attribute.name), ); } } @@ -605,7 +600,7 @@ pub fn mesh_resource_provider_system( // set vertex buffers into bindings for (name, _attribute) in mesh.iter_attribute() { - let attribute_name_id = get_attribute_name_id(&name); + let attribute_name_id = pipeline::get_vertex_attribute_name_id(&name); if let Some(RenderResourceId::Buffer(vertex_buffer)) = render_resource_context.get_asset_resource(*handle, attribute_name_id) { diff --git a/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs b/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs index 2ea866ceb87ec..0472723d4dea3 100644 --- a/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs +++ b/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs @@ -1,5 +1,8 @@ use super::VertexFormat; -use std::{borrow::Cow, hash::Hash}; +use std::{ + borrow::Cow, + hash::{Hash, Hasher}, +}; #[derive(Clone, Debug, Eq, PartialEq)] pub struct VertexBufferDescriptor { @@ -41,3 +44,9 @@ pub struct VertexAttributeDescriptor { pub format: VertexFormat, pub shader_location: u32, } + +pub fn get_vertex_attribute_name_id(name: &str) -> usize { + let mut hasher = fnv::FnvHasher::default(); + hasher.write(&name.as_bytes()); + hasher.finish() as usize //TODO: good enough for 32 bit systems? +} diff --git a/crates/bevy_text/src/draw.rs b/crates/bevy_text/src/draw.rs index 501d7e5d9c048..8b337db8aaeda 100644 --- a/crates/bevy_text/src/draw.rs +++ b/crates/bevy_text/src/draw.rs @@ -5,7 +5,7 @@ use bevy_math::{Mat4, Vec2, Vec3}; use bevy_render::{ color::Color, draw::{Draw, DrawContext, DrawError, Drawable}, - mesh, + mesh, pipeline, pipeline::PipelineSpecialization, prelude::Msaa, renderer::{ @@ -58,7 +58,7 @@ impl<'a> Drawable for DrawableText<'a> { let pipeline_layout = context.get_pipeline_layout().unwrap(); for vertex_buffer_descriptor in &pipeline_layout.vertex_buffer_descriptors { - let name_id = mesh::get_attribute_name_id(&vertex_buffer_descriptor.name); + let name_id = pipeline::get_vertex_attribute_name_id(&vertex_buffer_descriptor.name); if let Some(RenderResourceId::Buffer(vertex_attr_buffer_id)) = render_resource_context.get_asset_resource(bevy_sprite::QUAD_HANDLE, name_id) { From 80eafc827e49ae0ca204023bbbd1e88ee4bb23f8 Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Wed, 7 Oct 2020 02:37:21 +0200 Subject: [PATCH 14/32] restored old vertex naming convention --- .../forward_pipeline/forward.frag | 12 +++++----- .../forward_pipeline/forward.vert | 22 +++++++++---------- crates/bevy_render/src/mesh/mesh.rs | 6 ++--- .../bevy_render/src/shader/shader_reflect.rs | 10 ++++----- crates/bevy_sprite/src/render/sprite.frag | 4 ++-- crates/bevy_sprite/src/render/sprite.vert | 12 +++++----- .../bevy_sprite/src/render/sprite_sheet.frag | 4 ++-- .../bevy_sprite/src/render/sprite_sheet.vert | 14 ++++++------ crates/bevy_ui/src/render/ui.frag | 4 ++-- crates/bevy_ui/src/render/ui.vert | 12 +++++----- examples/shader/shader_custom_material.rs | 4 ++-- examples/shader/shader_defs.rs | 4 ++-- 12 files changed, 54 insertions(+), 54 deletions(-) diff --git a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag index 731ac4682296f..9c869f29e7129 100644 --- a/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag +++ b/crates/bevy_pbr/src/render_graph/forward_pipeline/forward.frag @@ -8,9 +8,9 @@ struct Light { vec4 color; }; -layout(location = 0) in vec3 position_world; -layout(location = 1) in vec3 normal_world; -layout(location = 2) in vec2 v_uv; +layout(location = 0) in vec3 v_Position; +layout(location = 1) in vec3 v_Normal; +layout(location = 2) in vec2 v_Uv; layout(location = 0) out vec4 o_Target; @@ -37,18 +37,18 @@ void main() { # ifdef STANDARDMATERIAL_ALBEDO_TEXTURE output_color *= texture( sampler2D(StandardMaterial_albedo_texture, StandardMaterial_albedo_texture_sampler), - v_uv); + v_Uv); # endif # ifdef STANDARDMATERIAL_SHADED - vec3 normal = normalize(normal_world); + vec3 normal = normalize(v_Normal); vec3 ambient = vec3(0.05, 0.05, 0.05); // accumulate color vec3 color = ambient; for (int i=0; i) -> Self { VertexAttributeData { diff --git a/crates/bevy_render/src/shader/shader_reflect.rs b/crates/bevy_render/src/shader/shader_reflect.rs index a9256daf782c6..bae3d5bdbff2c 100644 --- a/crates/bevy_render/src/shader/shader_reflect.rs +++ b/crates/bevy_render/src/shader/shader_reflect.rs @@ -315,8 +315,8 @@ mod tests { ShaderStage::Vertex, r#" #version 450 - layout(location = 0) in vec4 position_os; - layout(location = 1) in uvec4 normal_os; + layout(location = 0) in vec4 Vertex_Position; + layout(location = 1) in uvec4 Vertex_Normal; layout(location = 2) in uvec4 I_TestInstancing_Property; layout(location = 0) out vec4 v_Position; @@ -326,7 +326,7 @@ mod tests { layout(set = 1, binding = 0) uniform texture2D Texture; void main() { - v_Position = position_os; + v_Position = Vertex_Position; gl_Position = ViewProj * v_Position; } "#, @@ -341,7 +341,7 @@ mod tests { vertex_buffer_descriptors: vec![ VertexBufferDescriptor::new_from_attribute( VertexAttributeDescriptor { - name: "position_os".into(), + name: "Vertex_Position".into(), format: VertexFormat::Float4, offset: 0, shader_location: 0, @@ -351,7 +351,7 @@ mod tests { .test_zero_stride(), VertexBufferDescriptor::new_from_attribute( VertexAttributeDescriptor { - name: "normal_os".into(), + name: "Vertex_Normal".into(), format: VertexFormat::Uint4, offset: 0, shader_location: 1, diff --git a/crates/bevy_sprite/src/render/sprite.frag b/crates/bevy_sprite/src/render/sprite.frag index d291b0e09a363..9683598e2ed8c 100644 --- a/crates/bevy_sprite/src/render/sprite.frag +++ b/crates/bevy_sprite/src/render/sprite.frag @@ -1,6 +1,6 @@ #version 450 -layout(location = 0) in vec2 v_uv; +layout(location = 0) in vec2 v_Uv; layout(location = 0) out vec4 o_Target; @@ -18,7 +18,7 @@ void main() { # ifdef COLORMATERIAL_TEXTURE color *= texture( sampler2D(ColorMaterial_texture, ColorMaterial_texture_sampler), - v_uv); + v_Uv); # endif o_Target = color; } diff --git a/crates/bevy_sprite/src/render/sprite.vert b/crates/bevy_sprite/src/render/sprite.vert index 81d73fff379c4..fe1619d14b7fc 100644 --- a/crates/bevy_sprite/src/render/sprite.vert +++ b/crates/bevy_sprite/src/render/sprite.vert @@ -1,10 +1,10 @@ #version 450 -layout(location = 0) in vec3 position_os; -layout(location = 1) in vec3 normal_os; -layout(location = 2) in vec2 uv_vertex; +layout(location = 0) in vec3 Vertex_Position; +layout(location = 1) in vec3 Vertex_Normal; +layout(location = 2) in vec2 Vertex_Uv; -layout(location = 0) out vec2 v_uv; +layout(location = 0) out vec2 v_Uv; layout(set = 0, binding = 0) uniform Camera { mat4 ViewProj; @@ -18,7 +18,7 @@ layout(set = 2, binding = 1) uniform Sprite_size { }; void main() { - v_uv = uv_vertex; - vec3 position = position_os * vec3(size, 1.0); + v_Uv = Vertex_Uv; + vec3 position = Vertex_Position * vec3(size, 1.0); gl_Position = ViewProj * Model * vec4(position, 1.0); } \ No newline at end of file diff --git a/crates/bevy_sprite/src/render/sprite_sheet.frag b/crates/bevy_sprite/src/render/sprite_sheet.frag index 83fbf99188ad5..8c8d9217f08d1 100644 --- a/crates/bevy_sprite/src/render/sprite_sheet.frag +++ b/crates/bevy_sprite/src/render/sprite_sheet.frag @@ -1,6 +1,6 @@ #version 450 -layout(location = 0) in vec2 v_uv; +layout(location = 0) in vec2 v_Uv; layout(location = 1) in vec4 v_Color; layout(location = 0) out vec4 o_Target; @@ -11,5 +11,5 @@ layout(set = 1, binding = 3) uniform sampler TextureAtlas_texture_sampler; void main() { o_Target = v_Color * texture( sampler2D(TextureAtlas_texture, TextureAtlas_texture_sampler), - v_uv); + v_Uv); } diff --git a/crates/bevy_sprite/src/render/sprite_sheet.vert b/crates/bevy_sprite/src/render/sprite_sheet.vert index a3347b7601b8e..ed0552fcb8cca 100644 --- a/crates/bevy_sprite/src/render/sprite_sheet.vert +++ b/crates/bevy_sprite/src/render/sprite_sheet.vert @@ -1,10 +1,10 @@ #version 450 -layout(location = 0) in vec3 position_os; -layout(location = 1) in vec3 normal_os; -layout(location = 2) in vec2 uv_vertex; +layout(location = 0) in vec3 Vertex_Position; +layout(location = 1) in vec3 Vertex_Normal; +layout(location = 2) in vec2 Vertex_Uv; -layout(location = 0) out vec2 v_uv; +layout(location = 0) out vec2 v_Uv; layout(location = 1) out vec4 v_Color; layout(set = 0, binding = 0) uniform Camera { @@ -38,14 +38,14 @@ layout(set = 2, binding = 1) uniform TextureAtlasSprite { void main() { Rect sprite_rect = Textures[TextureAtlasSprite_index]; vec2 sprite_dimensions = sprite_rect.end - sprite_rect.begin; - vec3 position_os = vec3(position_os.xy * sprite_dimensions, 0.0); + vec3 Vertex_Position = vec3(Vertex_Position.xy * sprite_dimensions, 0.0); vec2 atlas_positions[4] = vec2[]( vec2(sprite_rect.begin.x, sprite_rect.end.y), sprite_rect.begin, vec2(sprite_rect.end.x, sprite_rect.begin.y), sprite_rect.end ); - v_uv = (atlas_positions[gl_VertexIndex] + vec2(0.01, 0.01)) / AtlasSize; + v_Uv = (atlas_positions[gl_VertexIndex] + vec2(0.01, 0.01)) / AtlasSize; v_Color = TextureAtlasSprite_color; - gl_Position = ViewProj * SpriteTransform * vec4(ceil(position_os), 1.0); + gl_Position = ViewProj * SpriteTransform * vec4(ceil(Vertex_Position), 1.0); } \ No newline at end of file diff --git a/crates/bevy_ui/src/render/ui.frag b/crates/bevy_ui/src/render/ui.frag index 13b4c79a8c7d1..985f5006ed4d2 100644 --- a/crates/bevy_ui/src/render/ui.frag +++ b/crates/bevy_ui/src/render/ui.frag @@ -1,6 +1,6 @@ #version 450 -layout(location = 0) in vec2 v_uv; +layout(location = 0) in vec2 v_Uv; layout(location = 0) out vec4 o_Target; @@ -18,7 +18,7 @@ void main() { # ifdef COLORMATERIAL_TEXTURE color *= texture( sampler2D(ColorMaterial_texture, ColorMaterial_texture_sampler), - v_uv); + v_Uv); # endif o_Target = color; } diff --git a/crates/bevy_ui/src/render/ui.vert b/crates/bevy_ui/src/render/ui.vert index 972446b462af0..2268af642b305 100644 --- a/crates/bevy_ui/src/render/ui.vert +++ b/crates/bevy_ui/src/render/ui.vert @@ -1,10 +1,10 @@ #version 450 -layout(location = 0) in vec3 position_os; -layout(location = 1) in vec3 normal_os; -layout(location = 2) in vec2 uv_vertex; +layout(location = 0) in vec3 Vertex_Position; +layout(location = 1) in vec3 Vertex_Normal; +layout(location = 2) in vec2 Vertex_Uv; -layout(location = 0) out vec2 v_uv; +layout(location = 0) out vec2 v_Uv; layout(set = 0, binding = 0) uniform Camera { mat4 ViewProj; @@ -18,7 +18,7 @@ layout(set = 1, binding = 1) uniform Node_size { }; void main() { - v_uv = uv_vertex; - vec3 position = position_os * vec3(NodeSize, 0.0); + v_Uv = Vertex_Uv; + vec3 position = Vertex_Position * vec3(NodeSize, 0.0); gl_Position = ViewProj * Object * vec4(position, 1.0); } \ No newline at end of file diff --git a/examples/shader/shader_custom_material.rs b/examples/shader/shader_custom_material.rs index 4fd040e1dbd2a..784cdb7472674 100644 --- a/examples/shader/shader_custom_material.rs +++ b/examples/shader/shader_custom_material.rs @@ -25,7 +25,7 @@ struct MyMaterial { const VERTEX_SHADER: &str = r#" #version 450 -layout(location = 0) in vec3 position_os; +layout(location = 0) in vec3 Vertex_Position; layout(set = 0, binding = 0) uniform Camera { mat4 ViewProj; }; @@ -33,7 +33,7 @@ layout(set = 1, binding = 0) uniform Transform { mat4 Model; }; void main() { - gl_Position = ViewProj * Model * vec4(position_os, 1.0); + gl_Position = ViewProj * Model * vec4(Vertex_Position, 1.0); } "#; diff --git a/examples/shader/shader_defs.rs b/examples/shader/shader_defs.rs index d237933d3b1cd..b46ca1c5fb731 100644 --- a/examples/shader/shader_defs.rs +++ b/examples/shader/shader_defs.rs @@ -33,7 +33,7 @@ struct MyMaterial { const VERTEX_SHADER: &str = r#" #version 450 -layout(location = 0) in vec3 position_os; +layout(location = 0) in vec3 Vertex_Position; layout(set = 0, binding = 0) uniform Camera { mat4 ViewProj; }; @@ -41,7 +41,7 @@ layout(set = 1, binding = 0) uniform Transform { mat4 Model; }; void main() { - gl_Position = ViewProj * Model * vec4(position_os, 1.0); + gl_Position = ViewProj * Model * vec4(Vertex_Position, 1.0); } "#; From 8d548398b847a847eee31d0624166d76959a95ec Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Fri, 9 Oct 2020 22:26:21 +0200 Subject: [PATCH 15/32] reintroduced multiple attributes per buffer --- crates/bevy_render/src/draw.rs | 6 +++++- crates/bevy_render/src/pipeline/pipeline.rs | 7 ++++++- .../bevy_render/src/pipeline/vertex_buffer_descriptor.rs | 4 ++-- crates/bevy_render/src/shader/shader_reflect.rs | 2 +- crates/bevy_text/src/draw.rs | 6 +++++- crates/bevy_wgpu/src/wgpu_type_converter.rs | 8 +++++++- 6 files changed, 26 insertions(+), 7 deletions(-) diff --git a/crates/bevy_render/src/draw.rs b/crates/bevy_render/src/draw.rs index 2f4010628935f..dd99983e5725e 100644 --- a/crates/bevy_render/src/draw.rs +++ b/crates/bevy_render/src/draw.rs @@ -338,7 +338,11 @@ impl<'a> DrawContext<'a> { bindings.vertex_buffers.get(&vertex_buffer_descriptor.name) { draw.set_vertex_buffer( - vertex_buffer_descriptor.attribute.shader_location, + vertex_buffer_descriptor + .attributes + .get(0) + .unwrap() + .shader_location, *vertex_buffer, 0, ); diff --git a/crates/bevy_render/src/pipeline/pipeline.rs b/crates/bevy_render/src/pipeline/pipeline.rs index baa0170e6e0ac..8c8c2edb3abd3 100644 --- a/crates/bevy_render/src/pipeline/pipeline.rs +++ b/crates/bevy_render/src/pipeline/pipeline.rs @@ -152,7 +152,12 @@ impl PipelineDescriptor { if vertex_buffer_descriptor.name == GL_VERTEX_INDEX { continue; } - vertex_buffer_descriptor.stride = vertex_buffer_descriptor.attribute.format.get_size(); + vertex_buffer_descriptor.stride = vertex_buffer_descriptor + .attributes + .get(0) + .unwrap() + .format + .get_size(); } if !dynamic_bindings.is_empty() { diff --git a/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs b/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs index 0472723d4dea3..da0d2e0b070c9 100644 --- a/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs +++ b/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs @@ -9,7 +9,7 @@ pub struct VertexBufferDescriptor { pub name: Cow<'static, str>, pub stride: u64, pub step_mode: InputStepMode, - pub attribute: VertexAttributeDescriptor, + pub attributes: Vec, } impl VertexBufferDescriptor { @@ -21,7 +21,7 @@ impl VertexBufferDescriptor { name: attribute.name.clone(), stride: attribute.format.get_size(), step_mode, - attribute: attribute.clone(), + attributes: vec![attribute.clone()], } } diff --git a/crates/bevy_render/src/shader/shader_reflect.rs b/crates/bevy_render/src/shader/shader_reflect.rs index bae3d5bdbff2c..2d676e21e9f1a 100644 --- a/crates/bevy_render/src/shader/shader_reflect.rs +++ b/crates/bevy_render/src/shader/shader_reflect.rs @@ -76,7 +76,7 @@ impl ShaderLayout { // create a new buffer descriptor per attribute vertex_buffer_descriptors.push(VertexBufferDescriptor { - attribute: vertex_attribute_descriptor, + attributes: vec![vertex_attribute_descriptor], name: current_buffer_name.into(), step_mode: if instance { InputStepMode::Instance diff --git a/crates/bevy_text/src/draw.rs b/crates/bevy_text/src/draw.rs index 8b337db8aaeda..8f35c326470ed 100644 --- a/crates/bevy_text/src/draw.rs +++ b/crates/bevy_text/src/draw.rs @@ -63,7 +63,11 @@ impl<'a> Drawable for DrawableText<'a> { render_resource_context.get_asset_resource(bevy_sprite::QUAD_HANDLE, name_id) { draw.set_vertex_buffer( - vertex_buffer_descriptor.attribute.shader_location, + vertex_buffer_descriptor + .attributes + .get(0) + .unwrap() + .shader_location, vertex_attr_buffer_id, 0, ); diff --git a/crates/bevy_wgpu/src/wgpu_type_converter.rs b/crates/bevy_wgpu/src/wgpu_type_converter.rs index 04dd94da6ea96..88c7c86b80dc4 100644 --- a/crates/bevy_wgpu/src/wgpu_type_converter.rs +++ b/crates/bevy_wgpu/src/wgpu_type_converter.rs @@ -98,10 +98,16 @@ pub struct OwnedWgpuVertexBufferDescriptor { impl WgpuFrom<&VertexBufferDescriptor> for OwnedWgpuVertexBufferDescriptor { fn from(val: &VertexBufferDescriptor) -> OwnedWgpuVertexBufferDescriptor { + let attributes = val + .attributes + .iter() + .map(|a| a.wgpu_into()) + .collect::>(); + OwnedWgpuVertexBufferDescriptor { step_mode: val.step_mode.wgpu_into(), stride: val.stride, - attributes: vec![(&val.attribute).wgpu_into()], + attributes, } } } From ab376147e98a2cca9ef820400a126dca1b339454 Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Sat, 10 Oct 2020 00:48:05 +0200 Subject: [PATCH 16/32] changed internal resource id to u64; using AHasher for vertex attributes; fixed bug in sprite_sheet.vert --- crates/bevy_render/Cargo.toml | 1 - crates/bevy_render/src/mesh/mesh.rs | 2 +- crates/bevy_render/src/pipeline/pipeline.rs | 1 - .../src/pipeline/vertex_buffer_descriptor.rs | 7 ++++--- .../src/renderer/headless_render_resource_context.rs | 8 ++++---- .../src/renderer/render_resource_context.rs | 12 ++++++------ crates/bevy_render/src/texture/texture.rs | 4 ++-- crates/bevy_sprite/src/render/sprite_sheet.vert | 4 ++-- .../src/renderer/wgpu_render_resource_context.rs | 6 +++--- crates/bevy_wgpu/src/wgpu_resources.rs | 2 +- 10 files changed, 23 insertions(+), 24 deletions(-) diff --git a/crates/bevy_render/Cargo.toml b/crates/bevy_render/Cargo.toml index 61d0d4dbed7b4..3c1826cda2d1e 100644 --- a/crates/bevy_render/Cargo.toml +++ b/crates/bevy_render/Cargo.toml @@ -44,7 +44,6 @@ anyhow = "1.0" hex = "0.4.2" hexasphere = "1.0.0" parking_lot = "0.11.0" -fnv = "1.0.7" [target.'cfg(not(target_os = "ios"))'.dependencies] bevy-glsl-to-spirv = "0.1.7" diff --git a/crates/bevy_render/src/mesh/mesh.rs b/crates/bevy_render/src/mesh/mesh.rs index 1d320e6e7dd31..ac2add9bc14e7 100644 --- a/crates/bevy_render/src/mesh/mesh.rs +++ b/crates/bevy_render/src/mesh/mesh.rs @@ -14,7 +14,7 @@ use thiserror::Error; use bevy_utils::HashMap; use std::hash::{Hash, Hasher}; -pub const INDEX_BUFFER_ASSET_INDEX: usize = 0; +pub const INDEX_BUFFER_ASSET_INDEX: u64 = 0; #[derive(Clone, Debug)] pub enum VertexAttributeValues { Float(Vec), diff --git a/crates/bevy_render/src/pipeline/pipeline.rs b/crates/bevy_render/src/pipeline/pipeline.rs index 8c8c2edb3abd3..b84654c8bf812 100644 --- a/crates/bevy_render/src/pipeline/pipeline.rs +++ b/crates/bevy_render/src/pipeline/pipeline.rs @@ -131,7 +131,6 @@ impl PipelineDescriptor { bevy_conventions: bool, dynamic_bindings: &[DynamicBinding], ) { - println!("reflect layout"); let vertex_spirv = shaders.get(&self.shader_stages.vertex).unwrap(); let fragment_spirv = self .shader_stages diff --git a/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs b/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs index da0d2e0b070c9..090e8747f8e21 100644 --- a/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs +++ b/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs @@ -45,8 +45,9 @@ pub struct VertexAttributeDescriptor { pub shader_location: u32, } -pub fn get_vertex_attribute_name_id(name: &str) -> usize { - let mut hasher = fnv::FnvHasher::default(); +/// Internally, `bevy_render` uses hashes to identify vertex attribute names. +pub fn get_vertex_attribute_name_id(name: &str) -> u64 { + let mut hasher = bevy_utils::AHasher::default(); hasher.write(&name.as_bytes()); - hasher.finish() as usize //TODO: good enough for 32 bit systems? + hasher.finish() } diff --git a/crates/bevy_render/src/renderer/headless_render_resource_context.rs b/crates/bevy_render/src/renderer/headless_render_resource_context.rs index 0a467d0718e79..e65512300c8b5 100644 --- a/crates/bevy_render/src/renderer/headless_render_resource_context.rs +++ b/crates/bevy_render/src/renderer/headless_render_resource_context.rs @@ -15,7 +15,7 @@ use std::{ops::Range, sync::Arc}; pub struct HeadlessRenderResourceContext { buffer_info: Arc>>, texture_descriptors: Arc>>, - pub asset_resources: Arc>>, + pub asset_resources: Arc>>, } impl HeadlessRenderResourceContext { @@ -92,7 +92,7 @@ impl RenderResourceContext for HeadlessRenderResourceContext { &self, handle: HandleUntyped, render_resource: RenderResourceId, - index: usize, + index: u64, ) { self.asset_resources .write() @@ -102,7 +102,7 @@ impl RenderResourceContext for HeadlessRenderResourceContext { fn get_asset_resource_untyped( &self, handle: HandleUntyped, - index: usize, + index: u64, ) -> Option { self.asset_resources.write().get(&(handle, index)).cloned() } @@ -124,7 +124,7 @@ impl RenderResourceContext for HeadlessRenderResourceContext { fn create_shader_module_from_source(&self, _shader_handle: Handle, _shader: &Shader) {} - fn remove_asset_resource_untyped(&self, handle: HandleUntyped, index: usize) { + fn remove_asset_resource_untyped(&self, handle: HandleUntyped, index: u64) { self.asset_resources.write().remove(&(handle, index)); } diff --git a/crates/bevy_render/src/renderer/render_resource_context.rs b/crates/bevy_render/src/renderer/render_resource_context.rs index 95e1f21329831..866ab825ad9c2 100644 --- a/crates/bevy_render/src/renderer/render_resource_context.rs +++ b/crates/bevy_render/src/renderer/render_resource_context.rs @@ -38,14 +38,14 @@ pub trait RenderResourceContext: Downcast + Send + Sync + 'static { &self, handle: HandleUntyped, resource: RenderResourceId, - index: usize, + index: u64, ); fn get_asset_resource_untyped( &self, handle: HandleUntyped, - index: usize, + index: u64, ) -> Option; - fn remove_asset_resource_untyped(&self, handle: HandleUntyped, index: usize); + fn remove_asset_resource_untyped(&self, handle: HandleUntyped, index: u64); fn create_render_pipeline( &self, pipeline_handle: Handle, @@ -63,21 +63,21 @@ pub trait RenderResourceContext: Downcast + Send + Sync + 'static { } impl dyn RenderResourceContext { - pub fn set_asset_resource(&self, handle: Handle, resource: RenderResourceId, index: usize) + pub fn set_asset_resource(&self, handle: Handle, resource: RenderResourceId, index: u64) where T: 'static, { self.set_asset_resource_untyped(handle.into(), resource, index); } - pub fn get_asset_resource(&self, handle: Handle, index: usize) -> Option + pub fn get_asset_resource(&self, handle: Handle, index: u64) -> Option where T: 'static, { self.get_asset_resource_untyped(handle.into(), index) } - pub fn remove_asset_resource(&self, handle: Handle, index: usize) + pub fn remove_asset_resource(&self, handle: Handle, index: u64) where T: 'static, { diff --git a/crates/bevy_render/src/texture/texture.rs b/crates/bevy_render/src/texture/texture.rs index 714c89217109b..60b14e1583f7c 100644 --- a/crates/bevy_render/src/texture/texture.rs +++ b/crates/bevy_render/src/texture/texture.rs @@ -8,8 +8,8 @@ use bevy_ecs::{Res, ResMut}; use bevy_math::Vec2; use bevy_utils::HashSet; -pub const TEXTURE_ASSET_INDEX: usize = 0; -pub const SAMPLER_ASSET_INDEX: usize = 1; +pub const TEXTURE_ASSET_INDEX: u64 = 0; +pub const SAMPLER_ASSET_INDEX: u64 = 1; #[derive(Clone)] pub struct Texture { diff --git a/crates/bevy_sprite/src/render/sprite_sheet.vert b/crates/bevy_sprite/src/render/sprite_sheet.vert index ed0552fcb8cca..13bf874ec45f0 100644 --- a/crates/bevy_sprite/src/render/sprite_sheet.vert +++ b/crates/bevy_sprite/src/render/sprite_sheet.vert @@ -38,7 +38,7 @@ layout(set = 2, binding = 1) uniform TextureAtlasSprite { void main() { Rect sprite_rect = Textures[TextureAtlasSprite_index]; vec2 sprite_dimensions = sprite_rect.end - sprite_rect.begin; - vec3 Vertex_Position = vec3(Vertex_Position.xy * sprite_dimensions, 0.0); + vec3 vertex_Position = vec3(Vertex_Position.xy * sprite_dimensions, 0.0); vec2 atlas_positions[4] = vec2[]( vec2(sprite_rect.begin.x, sprite_rect.end.y), sprite_rect.begin, @@ -47,5 +47,5 @@ void main() { ); v_Uv = (atlas_positions[gl_VertexIndex] + vec2(0.01, 0.01)) / AtlasSize; v_Color = TextureAtlasSprite_color; - gl_Position = ViewProj * SpriteTransform * vec4(ceil(Vertex_Position), 1.0); + gl_Position = ViewProj * SpriteTransform * vec4(ceil(vertex_Position), 1.0); } \ No newline at end of file diff --git a/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs b/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs index 2f2e630c82b30..8df9f4d22f49b 100644 --- a/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs +++ b/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs @@ -308,7 +308,7 @@ impl RenderResourceContext for WgpuRenderResourceContext { &self, handle: HandleUntyped, render_resource: RenderResourceId, - index: usize, + index: u64, ) { let mut asset_resources = self.resources.asset_resources.write(); asset_resources.insert((handle, index), render_resource); @@ -317,13 +317,13 @@ impl RenderResourceContext for WgpuRenderResourceContext { fn get_asset_resource_untyped( &self, handle: HandleUntyped, - index: usize, + index: u64, ) -> Option { let asset_resources = self.resources.asset_resources.read(); asset_resources.get(&(handle, index)).cloned() } - fn remove_asset_resource_untyped(&self, handle: HandleUntyped, index: usize) { + fn remove_asset_resource_untyped(&self, handle: HandleUntyped, index: u64) { let mut asset_resources = self.resources.asset_resources.write(); asset_resources.remove(&(handle, index)); } diff --git a/crates/bevy_wgpu/src/wgpu_resources.rs b/crates/bevy_wgpu/src/wgpu_resources.rs index 5409534337524..64ae086a818e1 100644 --- a/crates/bevy_wgpu/src/wgpu_resources.rs +++ b/crates/bevy_wgpu/src/wgpu_resources.rs @@ -82,7 +82,7 @@ pub struct WgpuResources { pub render_pipelines: Arc, wgpu::RenderPipeline>>>, pub bind_groups: Arc>>, pub bind_group_layouts: Arc>>, - pub asset_resources: Arc>>, + pub asset_resources: Arc>>, } impl WgpuResources { From 9734db5ec6cdaf2755adc481ca256b9d4e60303d Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Tue, 13 Oct 2020 19:37:38 +0200 Subject: [PATCH 17/32] Reintroduced interleaved buffers, but flexible. :smile: Pipeline specialization for vertex buffer descriptor. Removed Properties from RenderPipeline. propertiesimplyfied renderresource bindings --- crates/bevy_render/src/draw.rs | 35 +--- crates/bevy_render/src/lib.rs | 7 +- crates/bevy_render/src/mesh/mesh.rs | 184 +++++++++++------- crates/bevy_render/src/pipeline/pipeline.rs | 26 +-- .../src/pipeline/pipeline_compiler.rs | 46 ++++- .../src/pipeline/render_pipelines.rs | 24 +-- .../src/pipeline/vertex_buffer_descriptor.rs | 10 +- .../render_resource_bindings.rs | 40 ++-- .../bevy_render/src/shader/shader_reflect.rs | 3 +- 9 files changed, 236 insertions(+), 139 deletions(-) diff --git a/crates/bevy_render/src/draw.rs b/crates/bevy_render/src/draw.rs index dd99983e5725e..b235c96684b18 100644 --- a/crates/bevy_render/src/draw.rs +++ b/crates/bevy_render/src/draw.rs @@ -1,8 +1,5 @@ use crate::{ - pipeline::{ - PipelineCompiler, PipelineDescriptor, PipelineLayout, PipelineSpecialization, - VertexBufferDescriptor, - }, + pipeline::{PipelineCompiler, PipelineDescriptor, PipelineLayout, PipelineSpecialization}, renderer::{ BindGroup, BindGroupId, BufferId, BufferUsage, RenderResource, RenderResourceBinding, RenderResourceBindings, RenderResourceContext, SharedBuffers, @@ -330,33 +327,19 @@ impl<'a> DrawContext<'a> { &self, draw: &mut Draw, render_resource_bindings: &[&RenderResourceBindings], - vertex_buffer_descriptors: &[VertexBufferDescriptor], ) -> Result<(), DrawError> { for bindings in render_resource_bindings.iter() { - for vertex_buffer_descriptor in vertex_buffer_descriptors { - if let Some(vertex_buffer) = - bindings.vertex_buffers.get(&vertex_buffer_descriptor.name) - { - draw.set_vertex_buffer( - vertex_buffer_descriptor - .attributes - .get(0) - .unwrap() - .shader_location, - *vertex_buffer, - 0, - ); - } else { - panic!( - "Attribute {} is required by shader, but no vertex buffer was found.", - &vertex_buffer_descriptor.name - ); - } - } - if let Some(index_buffer) = bindings.index_buffer { draw.set_index_buffer(index_buffer, 0); } + + //TODO: wip! actually figure out the binding slot? + if let Some(main_vertex_buffer) = bindings.vertex_attribute_buffer { + draw.set_vertex_buffer(0, main_vertex_buffer, 0); + } + if let Some(zeroed_vertex_buffer) = bindings.vertex_fallback_buffer { + draw.set_vertex_buffer(1, zeroed_vertex_buffer, 0); + } } Ok(()) } diff --git a/crates/bevy_render/src/lib.rs b/crates/bevy_render/src/lib.rs index ce14af98b7d33..7b189590b7b47 100644 --- a/crates/bevy_render/src/lib.rs +++ b/crates/bevy_render/src/lib.rs @@ -37,8 +37,7 @@ use camera::{ ActiveCameras, Camera, OrthographicProjection, PerspectiveProjection, VisibleEntities, }; use pipeline::{ - DynamicBinding, PipelineCompiler, PipelineDescriptor, PipelineSpecialization, - PrimitiveTopology, ShaderSpecialization, + DynamicBinding, PipelineCompiler, PipelineDescriptor, PrimitiveTopology, ShaderSpecialization, }; use render_graph::{ base::{self, BaseRenderGraphBuilder, BaseRenderGraphConfig}, @@ -100,7 +99,7 @@ impl Plugin for RenderPlugin { .add_asset::() .register_component::() .register_component::() - .register_component::() + //.register_component::()//TODO julian: why is this a property? .register_component::() .register_component::() .register_component::() @@ -110,7 +109,7 @@ impl Plugin for RenderPlugin { .register_property::() .register_property::() .register_property::() - .register_properties::() + //.register_properties::() //TODO julian: why is this a property? .init_resource::() .init_resource::() .init_resource::() diff --git a/crates/bevy_render/src/mesh/mesh.rs b/crates/bevy_render/src/mesh/mesh.rs index ac2add9bc14e7..2bfc15c557639 100644 --- a/crates/bevy_render/src/mesh/mesh.rs +++ b/crates/bevy_render/src/mesh/mesh.rs @@ -1,17 +1,16 @@ use crate::{ - pipeline, pipeline::{PrimitiveTopology, RenderPipelines, VertexFormat}, renderer::{BufferInfo, BufferUsage, RenderResourceContext, RenderResourceId}, }; use bevy_app::prelude::{EventReader, Events}; use bevy_asset::{AssetEvent, Assets, Handle}; use bevy_core::AsBytes; -use bevy_ecs::{Local, Query, Res}; +use bevy_ecs::{Local, Query, Res, ResMut}; use bevy_math::*; use std::borrow::Cow; use thiserror::Error; -use bevy_utils::HashMap; +use crate::pipeline::{InputStepMode, VertexAttributeDescriptor, VertexBufferDescriptor}; use std::hash::{Hash, Hasher}; pub const INDEX_BUFFER_ASSET_INDEX: u64 = 0; @@ -59,9 +58,9 @@ impl From<&VertexAttributeValues> for VertexFormat { } } +//TODO: replace by tuple? #[derive(Debug)] pub struct VertexAttributeData { - //TODO: replace by tuple? pub name: Cow<'static, str>, pub values: VertexAttributeValues, //TODO: the values aren't necessarily needed after been submitted to the GPU } @@ -128,8 +127,9 @@ pub enum Indices { #[derive(Debug)] pub struct Mesh { pub primitive_topology: PrimitiveTopology, - attributes: HashMap, VertexAttributeData>, + pub attributes: Vec, pub indices: Option, + pub attribute_vertex_buffer_descriptor: Option, //TODO julian: should not be Option } impl Mesh { @@ -140,8 +140,9 @@ impl Mesh { ) -> Self { let mut mesh = Mesh { primitive_topology, - attributes: HashMap::default(), + attributes: Vec::default(), indices, + attribute_vertex_buffer_descriptor: None, }; for attribute in attributes.drain(..) { mesh.insert_attribute(attribute); @@ -152,28 +153,22 @@ impl Mesh { pub fn new_empty(primitive_topology: PrimitiveTopology) -> Self { Mesh { primitive_topology, - attributes: HashMap::default(), + attributes: Vec::default(), indices: None, + attribute_vertex_buffer_descriptor: None, } } pub fn insert_attribute(&mut self, new_vertex_attribute: VertexAttributeData) { - self.attributes - .insert(new_vertex_attribute.name.clone(), new_vertex_attribute); + self.attributes.push(new_vertex_attribute); } pub fn get_attribute(&mut self, name: Cow<'static, str>) -> Option<&VertexAttributeData> { - self.attributes.get(&name) + self.attributes.iter().find(|x| x.name == name) } pub fn remove_attribute(&mut self, name: Cow<'static, str>) { - self.attributes.remove(&name); - } - - pub fn iter_attribute( - &self, - ) -> std::collections::hash_map::Iter<'_, Cow<'static, str>, VertexAttributeData> { - self.attributes.iter() + self.attributes.retain(|x| x.name != name); } pub fn get_index_buffer_bytes(&self) -> Option> { @@ -481,38 +476,38 @@ pub mod shape { } } -fn remove_current_mesh_resources( +fn remove_resource_save( render_resource_context: &dyn RenderResourceContext, handle: Handle, - mesh: &Mesh, + index: u64, ) { - for attribute in mesh.attributes.iter() { - if let Some(RenderResourceId::Buffer(buffer)) = render_resource_context - .get_asset_resource(handle, pipeline::get_vertex_attribute_name_id(attribute.0)) - { - render_resource_context.remove_buffer(buffer); - render_resource_context - .remove_asset_resource(handle, pipeline::get_vertex_attribute_name_id(attribute.0)); - } - } - if let Some(RenderResourceId::Buffer(buffer)) = - render_resource_context.get_asset_resource(handle, INDEX_BUFFER_ASSET_INDEX) + render_resource_context.get_asset_resource(handle, index) { render_resource_context.remove_buffer(buffer); - render_resource_context.remove_asset_resource(handle, INDEX_BUFFER_ASSET_INDEX); + render_resource_context.remove_asset_resource(handle, index); } } +fn remove_current_mesh_resources( + render_resource_context: &dyn RenderResourceContext, + handle: Handle, +) { + remove_resource_save(render_resource_context, handle, VERTEX_ATTRIBUTE_BUFFER_ID); + remove_resource_save(render_resource_context, handle, VERTEX_FALLBACK_BUFFER_ID); + remove_resource_save(render_resource_context, handle, INDEX_BUFFER_ASSET_INDEX); +} #[derive(Default)] pub struct MeshResourceProviderState { mesh_event_reader: EventReader>, } +const VERTEX_ATTRIBUTE_BUFFER_ID: u64 = 10; //TODO julian: remove +const VERTEX_FALLBACK_BUFFER_ID: u64 = 20; //TODO julian: remove pub fn mesh_resource_provider_system( mut state: Local, render_resource_context: Res>, - meshes: Res>, + mut meshes: ResMut>, //TODO julian: make res again? mesh_events: Res>>, mut query: Query<(&Handle, &mut RenderPipelines)>, ) { @@ -525,18 +520,10 @@ pub fn mesh_resource_provider_system( } AssetEvent::Modified { handle } => { changed_meshes.insert(*handle); - remove_current_mesh_resources( - render_resource_context, - *handle, - meshes.get(handle).unwrap(), - ); + remove_current_mesh_resources(render_resource_context, *handle); } AssetEvent::Removed { handle } => { - remove_current_mesh_resources( - render_resource_context, - *handle, - meshes.get(handle).unwrap(), - ); + remove_current_mesh_resources(render_resource_context, *handle); // if mesh was modified and removed in the same update, ignore the modification // events are ordered so future modification events are ok changed_meshes.remove(handle); @@ -546,8 +533,8 @@ pub fn mesh_resource_provider_system( // update changed mesh data for changed_mesh_handle in changed_meshes.iter() { - if let Some(mesh) = meshes.get(changed_mesh_handle) { - // TODO: check for individual buffer changes + if let Some(mesh) = meshes.get_mut(changed_mesh_handle) { + // TODO: check for individual buffer changes in non-interleaved mode let index_buffer = render_resource_context.create_buffer_with_data( BufferInfo { buffer_usage: BufferUsage::INDEX, @@ -562,22 +549,37 @@ pub fn mesh_resource_provider_system( INDEX_BUFFER_ASSET_INDEX, ); - for attribute in mesh.attributes.values() { - // TODO: use a staging buffer here - let attribute_buffer = render_resource_context.create_buffer_with_data( + // Vertex buffer + let vertex_count = mesh.attributes.first().unwrap().values.len(); //TODO julian: assert for different lengths of attributes, also move this somewhere else + let interleaved_buffer = + attributes_to_vertex_buffer_data(&mesh.attributes, vertex_count as u32); + + mesh.attribute_vertex_buffer_descriptor = Some(interleaved_buffer.1); + render_resource_context.set_asset_resource( + *changed_mesh_handle, + RenderResourceId::Buffer(render_resource_context.create_buffer_with_data( BufferInfo { buffer_usage: BufferUsage::VERTEX, ..Default::default() }, - &attribute.values.get_bytes(), - ); + &interleaved_buffer.0, + )), + VERTEX_ATTRIBUTE_BUFFER_ID, //TODO julian: pipeline::get_vertex_attribute_name_id(&attribute.name), + ); - render_resource_context.set_asset_resource( - *changed_mesh_handle, - RenderResourceId::Buffer(attribute_buffer), - pipeline::get_vertex_attribute_name_id(&attribute.name), - ); - } + // Fallback buffer + // TODO julian: can be done with a 1 byte buffer + zero stride? + render_resource_context.set_asset_resource( + *changed_mesh_handle, + RenderResourceId::Buffer(render_resource_context.create_buffer_with_data( + BufferInfo { + buffer_usage: BufferUsage::VERTEX, + ..Default::default() + }, + &vec![0; vertex_count * VertexFormat::Float4.get_size() as usize], + )), + VERTEX_FALLBACK_BUFFER_ID, //TODO julian: pipeline::get_vertex_attribute_name_id(&attribute.name), + ); } } @@ -598,17 +600,69 @@ pub fn mesh_resource_provider_system( .set_index_buffer(index_buffer_resource); } - // set vertex buffers into bindings - for (name, _attribute) in mesh.iter_attribute() { - let attribute_name_id = pipeline::get_vertex_attribute_name_id(&name); - if let Some(RenderResourceId::Buffer(vertex_buffer)) = - render_resource_context.get_asset_resource(*handle, attribute_name_id) - { - render_pipelines - .bindings - .set_vertex_buffer(name.clone(), vertex_buffer); - } + if let Some(RenderResourceId::Buffer(vertex_attribute_buffer_resource)) = + render_resource_context.get_asset_resource(*handle, VERTEX_ATTRIBUTE_BUFFER_ID) + { + // set index buffer into binding + render_pipelines.bindings.vertex_attribute_buffer = + Some(vertex_attribute_buffer_resource); + } + if let Some(RenderResourceId::Buffer(vertex_attribute_fallback_resource)) = + render_resource_context.get_asset_resource(*handle, VERTEX_FALLBACK_BUFFER_ID) + { + // set index buffer into binding + render_pipelines.bindings.vertex_fallback_buffer = + Some(vertex_attribute_fallback_resource); } } } } + +pub fn attributes_to_vertex_buffer_data( + attributes: &[VertexAttributeData], + vertex_count: u32, +) -> (Vec, VertexBufferDescriptor) { + // get existing attribute data as bytes and generate attribute descriptor + let mut attributes_gpu_ready = Vec::<(VertexAttributeDescriptor, Vec)>::default(); + let mut accumulated_offset = 0; + //TODO: sort attribute data first! different attribute orders will introduce more pipeline specialisation than necessary + for attribute_data in attributes { + // TODO: allow for custom converter here + let vertex_format = VertexFormat::from(&attribute_data.values); + attributes_gpu_ready.push(( + // this is not supposed to be used directly, as we don't know the shader location in advance + VertexAttributeDescriptor { + name: attribute_data.name.clone(), + offset: accumulated_offset, + format: vertex_format, + shader_location: 0, + }, + attribute_data.values.get_bytes().to_vec(), + )); + accumulated_offset += vertex_format.get_size(); + } + + // TODO: make interleaved configurable? or call this function for each interleaved buffer? + let mut interleaved_buffer = Vec::::default(); + + // bundle into interleaved buffers + for vertex_index in 0..vertex_count { + let vertex_index = vertex_index as usize; + for attribute in &attributes_gpu_ready { + let bytes = &attribute.1; + let stride = bytes.len() / vertex_count as usize; + // insert one element + interleaved_buffer + .extend(&bytes[vertex_index * stride..vertex_index * stride + stride]); + } + } + + let vertex_buffer_descriptor_reference = VertexBufferDescriptor { + name: Default::default(), //TODO: naming! + stride: accumulated_offset, + step_mode: InputStepMode::Vertex, + attributes: attributes_gpu_ready.iter().map(|x| x.0.clone()).collect(), //TODO: clone? + }; + + (interleaved_buffer, vertex_buffer_descriptor_reference) +} diff --git a/crates/bevy_render/src/pipeline/pipeline.rs b/crates/bevy_render/src/pipeline/pipeline.rs index b84654c8bf812..ff65c0b640f50 100644 --- a/crates/bevy_render/src/pipeline/pipeline.rs +++ b/crates/bevy_render/src/pipeline/pipeline.rs @@ -7,7 +7,7 @@ use super::{ BindType, DynamicBinding, PipelineLayout, StencilStateDescriptor, }; use crate::{ - shader::{Shader, ShaderStages, GL_VERTEX_INDEX}, + shader::{Shader, ShaderStages}, texture::TextureFormat, }; use bevy_asset::Assets; @@ -146,18 +146,18 @@ impl PipelineDescriptor { let mut layout = PipelineLayout::from_shader_layouts(&mut layouts); // just obtain the stride from the attribute itself, since we are always using float format - // TODO: support for different formats? - for vertex_buffer_descriptor in &mut layout.vertex_buffer_descriptors { - if vertex_buffer_descriptor.name == GL_VERTEX_INDEX { - continue; - } - vertex_buffer_descriptor.stride = vertex_buffer_descriptor - .attributes - .get(0) - .unwrap() - .format - .get_size(); - } + // // TODO: support for different formats? + // for vertex_buffer_descriptor in &mut layout.vertex_buffer_descriptors { + // if vertex_buffer_descriptor.name == GL_VERTEX_INDEX { + // continue; + // } + // vertex_buffer_descriptor.stride = vertex_buffer_descriptor + // .attributes + // .get(0) + // .unwrap() + // .format + // .get_size(); + // } if !dynamic_bindings.is_empty() { // set binding uniforms to dynamic if render resource bindings use dynamic diff --git a/crates/bevy_render/src/pipeline/pipeline_compiler.rs b/crates/bevy_render/src/pipeline/pipeline_compiler.rs index add4ce27321bb..2727f112b2071 100644 --- a/crates/bevy_render/src/pipeline/pipeline_compiler.rs +++ b/crates/bevy_render/src/pipeline/pipeline_compiler.rs @@ -1,20 +1,23 @@ use super::{state_descriptors::PrimitiveTopology, IndexFormat, PipelineDescriptor}; use crate::{ + pipeline::{VertexAttributeDescriptor, VertexBufferDescriptor, VertexFormat}, renderer::RenderResourceContext, shader::{Shader, ShaderSource}, }; use bevy_asset::{Assets, Handle}; -use bevy_property::{Properties, Property}; +use bevy_property::Property; use bevy_utils::{HashMap, HashSet}; use once_cell::sync::Lazy; use serde::{Deserialize, Serialize}; +use std::borrow::Cow; -#[derive(Clone, Eq, PartialEq, Debug, Properties)] +#[derive(Clone, Eq, PartialEq, Debug)] //TODO julian: derive Properties? pub struct PipelineSpecialization { pub shader_specialization: ShaderSpecialization, pub primitive_topology: PrimitiveTopology, pub dynamic_bindings: Vec, pub index_format: IndexFormat, + pub mesh_attribute_layout: VertexBufferDescriptor, pub sample_count: u32, } @@ -26,6 +29,7 @@ impl Default for PipelineSpecialization { primitive_topology: Default::default(), dynamic_bindings: Default::default(), index_format: IndexFormat::Uint32, + mesh_attribute_layout: Default::default(), } } } @@ -159,6 +163,44 @@ impl PipelineCompiler { &pipeline_specialization.dynamic_bindings, ); + // create a vertex layout that provides all attributes from either the specialized vertex buffers or a zero buffer + let mut pipeline_layout = specialized_descriptor.layout.as_mut().unwrap(); + let mut mutated_vertex_buffer_descriptor = + pipeline_specialization.mesh_attribute_layout.clone(); + + let mut fallback_vertex_buffer_descirptor = VertexBufferDescriptor { + name: Cow::from("Fallback"), //TODO julian: name acordingly + stride: VertexFormat::Float4.get_size(), //TODO julian: use smallest possible format! + ..Default::default() + }; + for shader_vertex_attribute in &mut pipeline_layout.vertex_buffer_descriptors.iter_mut() { + let shader_vertex_attribute = shader_vertex_attribute + .attributes + .get(0) + .expect("Reflected layout has no attributes."); + + if let Some(target_vertex_attribute) = mutated_vertex_buffer_descriptor + .attributes + .iter_mut() + .find(|x| x.name == shader_vertex_attribute.name) + { + // copy shader location from reflected layout + target_vertex_attribute.shader_location = shader_vertex_attribute.shader_location; + } else { + fallback_vertex_buffer_descirptor + .attributes + .push(VertexAttributeDescriptor { + name: Default::default(), + offset: 0, + format: shader_vertex_attribute.format, //TODO julian: use smallest possible format to minimalize bandwidth + shader_location: shader_vertex_attribute.shader_location, + }); + } + } //TODO julian: also add other buffers, like instancing?... + pipeline_layout.vertex_buffer_descriptors = vec![ + mutated_vertex_buffer_descriptor, + fallback_vertex_buffer_descirptor, + ]; specialized_descriptor.sample_count = pipeline_specialization.sample_count; specialized_descriptor.primitive_topology = pipeline_specialization.primitive_topology; specialized_descriptor.index_format = pipeline_specialization.index_format; diff --git a/crates/bevy_render/src/pipeline/render_pipelines.rs b/crates/bevy_render/src/pipeline/render_pipelines.rs index 8bdc83c5c29bd..41cc632af8c25 100644 --- a/crates/bevy_render/src/pipeline/render_pipelines.rs +++ b/crates/bevy_render/src/pipeline/render_pipelines.rs @@ -7,9 +7,8 @@ use crate::{ }; use bevy_asset::{Assets, Handle}; use bevy_ecs::{Query, Res, ResMut}; -use bevy_property::Properties; -#[derive(Properties, Default, Clone)] +#[derive(Default, Clone)] //TODO julian: no properties #[non_exhaustive] pub struct RenderPipeline { pub pipeline: Handle, @@ -35,10 +34,10 @@ impl RenderPipeline { } } -#[derive(Properties, Clone)] +#[derive(Clone)] //TODO julian: properties pub struct RenderPipelines { pub pipelines: Vec, - #[property(ignore)] + //#[property(ignore)] //TODO julian: properties pub bindings: RenderResourceBindings, } @@ -95,6 +94,12 @@ pub fn draw_render_pipelines_system( for pipeline in render_pipelines.pipelines.iter_mut() { pipeline.specialization.sample_count = msaa.samples; pipeline.specialization.index_format = index_format; + pipeline.specialization.mesh_attribute_layout = mesh + .attribute_vertex_buffer_descriptor + .as_ref() + .unwrap() + .clone(); + //TODO julian: is this a good idea? } for render_pipeline in render_pipelines.pipelines.iter() { @@ -114,17 +119,8 @@ pub fn draw_render_pipelines_system( ], ) .unwrap(); - - // get pipeline layout to find binding slots for vertex buffers - let pipeline_descriptor = draw_context.get_pipeline_descriptor().unwrap(); - let pipeline_layout = pipeline_descriptor.layout.as_ref().unwrap(); - draw_context - .set_vertex_buffers_from_bindings( - &mut draw, - &[&render_pipelines.bindings], - &pipeline_layout.vertex_buffer_descriptors, - ) + .set_vertex_buffers_from_bindings(&mut draw, &[&render_pipelines.bindings]) .unwrap(); if let Some(indices) = index_range.clone() { diff --git a/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs b/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs index 090e8747f8e21..54fb0d985aab7 100644 --- a/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs +++ b/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs @@ -4,7 +4,7 @@ use std::{ hash::{Hash, Hasher}, }; -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Default)] pub struct VertexBufferDescriptor { pub name: Cow<'static, str>, pub stride: u64, @@ -37,6 +37,12 @@ pub enum InputStepMode { Instance = 1, } +impl Default for InputStepMode { + fn default() -> Self { + InputStepMode::Vertex + } +} + #[derive(Clone, Debug, Hash, Eq, PartialEq)] pub struct VertexAttributeDescriptor { pub name: Cow<'static, str>, @@ -45,6 +51,8 @@ pub struct VertexAttributeDescriptor { pub shader_location: u32, } +//pub type StaticCowString = Cow<'static, str>; //TODO julian: use this? + /// Internally, `bevy_render` uses hashes to identify vertex attribute names. pub fn get_vertex_attribute_name_id(name: &str) -> u64 { let mut hasher = bevy_utils::AHasher::default(); diff --git a/crates/bevy_render/src/renderer/render_resource/render_resource_bindings.rs b/crates/bevy_render/src/renderer/render_resource/render_resource_bindings.rs index a3ac744853c79..90cc2d261a128 100644 --- a/crates/bevy_render/src/renderer/render_resource/render_resource_bindings.rs +++ b/crates/bevy_render/src/renderer/render_resource/render_resource_bindings.rs @@ -5,7 +5,7 @@ use crate::{ }; use bevy_asset::{Handle, HandleUntyped}; use bevy_utils::{HashMap, HashSet}; -use std::{borrow::Cow, hash::Hash, ops::Range}; +use std::{hash::Hash, ops::Range}; #[derive(Clone, Eq, Debug)] pub enum RenderResourceBinding { @@ -104,7 +104,10 @@ pub enum BindGroupStatus { #[derive(Eq, PartialEq, Debug, Default, Clone)] pub struct RenderResourceBindings { bindings: HashMap, - pub vertex_buffers: HashMap, BufferId>, + /// A Buffer that contains all attributes a mesh has defined + pub vertex_attribute_buffer: Option, + /// A Buffer that is filled with zeros that will be used for attributes required by the shader, but undefined by the mesh. + pub vertex_fallback_buffer: Option, pub index_buffer: Option, bind_groups: HashMap, bind_group_descriptors: HashMap>, @@ -138,17 +141,28 @@ impl RenderResourceBindings { } } - pub fn get_vertex_buffer(&self, attribute_name: Cow<'static, str>) -> Option { - self.vertex_buffers.get(&attribute_name).cloned() - } - - pub fn set_vertex_buffer( - &mut self, - attribute_name: Cow<'static, str>, - vertex_buffer: BufferId, - ) { - self.vertex_buffers.insert(attribute_name, vertex_buffer); - } + // TODO julian: needed? + // pub fn get_vertex_buffer(&self, attribute_name: Cow<'static, str>) -> Option { + // unimplemented!(); + // //TODO: + // // // TODO: hash based lookup? + // // for vertex_buffer in &self.vertex_buffers { + // // for attribute in &vertex_buffer.0.attributes { + // // if attribute.name == attribute_name { + // // Some(vertex_buffer.1.clone()) + // // } + // // } + // // } + // // + // // None + // } + // pub fn set_vertex_buffer( + // &mut self, + // buffer_descriptor: VertexBufferDescriptor, + // buffer_id: BufferId, + // ) { + // self.vertex_buffers.push((buffer_descriptor, buffer_id)); + // } pub fn set_index_buffer(&mut self, index_buffer: BufferId) { self.index_buffer = Some(index_buffer); diff --git a/crates/bevy_render/src/shader/shader_reflect.rs b/crates/bevy_render/src/shader/shader_reflect.rs index 2d676e21e9f1a..86188f24b85f7 100644 --- a/crates/bevy_render/src/shader/shader_reflect.rs +++ b/crates/bevy_render/src/shader/shader_reflect.rs @@ -74,7 +74,8 @@ impl ShaderLayout { } }; - // create a new buffer descriptor per attribute + // create a new buffer descriptor, per attribute! + // TODO julian: make a different struct for this kind of VertexBufferDescriptor (always 1 attribute, not intended for actually use) vertex_buffer_descriptors.push(VertexBufferDescriptor { attributes: vec![vertex_attribute_descriptor], name: current_buffer_name.into(), From 20d101b1e6bb3ccf7882f4ecbd2f8791b9398f70 Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Wed, 14 Oct 2020 23:27:48 +0200 Subject: [PATCH 18/32] made fallback buffer obtional. readded properties to rendering structs --- crates/bevy_render/src/draw.rs | 22 ++++++++++++++---- crates/bevy_render/src/lib.rs | 5 ++-- crates/bevy_render/src/pipeline/pipeline.rs | 14 ----------- .../src/pipeline/pipeline_compiler.rs | 20 +++++++++------- .../src/pipeline/render_pipelines.rs | 7 +++--- .../src/pipeline/vertex_buffer_descriptor.rs | 9 +++++--- .../bevy_render/src/pipeline/vertex_format.rs | 3 ++- .../render_resource_bindings.rs | 23 ------------------- 8 files changed, 45 insertions(+), 58 deletions(-) diff --git a/crates/bevy_render/src/draw.rs b/crates/bevy_render/src/draw.rs index b235c96684b18..48fc31099a747 100644 --- a/crates/bevy_render/src/draw.rs +++ b/crates/bevy_render/src/draw.rs @@ -1,3 +1,4 @@ +use crate::pipeline::VERTEX_FALLBACK_LAYOUT_NAME; use crate::{ pipeline::{PipelineCompiler, PipelineDescriptor, PipelineLayout, PipelineSpecialization}, renderer::{ @@ -328,17 +329,30 @@ impl<'a> DrawContext<'a> { draw: &mut Draw, render_resource_bindings: &[&RenderResourceBindings], ) -> Result<(), DrawError> { + let pipeline = self.current_pipeline.ok_or(DrawError::NoPipelineSet)?; + let pipeline_descriptor = self + .pipelines + .get(&pipeline) + .ok_or(DrawError::NonExistentPipeline)?; + let layout = pipeline_descriptor + .get_layout() + .ok_or(DrawError::PipelineHasNoLayout)?; + // figure out if the fallback buffer is needed + let need_fallback_buffer = layout + .vertex_buffer_descriptors + .iter() + .any(|x| x.name == VERTEX_FALLBACK_LAYOUT_NAME); for bindings in render_resource_bindings.iter() { if let Some(index_buffer) = bindings.index_buffer { draw.set_index_buffer(index_buffer, 0); } - - //TODO: wip! actually figure out the binding slot? if let Some(main_vertex_buffer) = bindings.vertex_attribute_buffer { draw.set_vertex_buffer(0, main_vertex_buffer, 0); } - if let Some(zeroed_vertex_buffer) = bindings.vertex_fallback_buffer { - draw.set_vertex_buffer(1, zeroed_vertex_buffer, 0); + if need_fallback_buffer { + if let Some(fallback_vertex_buffer) = bindings.vertex_fallback_buffer { + draw.set_vertex_buffer(1, fallback_vertex_buffer, 0); + } } } Ok(()) diff --git a/crates/bevy_render/src/lib.rs b/crates/bevy_render/src/lib.rs index 7b189590b7b47..f8fd8a479900d 100644 --- a/crates/bevy_render/src/lib.rs +++ b/crates/bevy_render/src/lib.rs @@ -27,6 +27,7 @@ pub mod prelude { }; } +use crate::pipeline::PipelineSpecialization; use crate::prelude::*; use base::{MainPass, Msaa}; use bevy_app::prelude::*; @@ -99,7 +100,7 @@ impl Plugin for RenderPlugin { .add_asset::() .register_component::() .register_component::() - //.register_component::()//TODO julian: why is this a property? + .register_component::() .register_component::() .register_component::() .register_component::() @@ -109,7 +110,7 @@ impl Plugin for RenderPlugin { .register_property::() .register_property::() .register_property::() - //.register_properties::() //TODO julian: why is this a property? + .register_properties::() .init_resource::() .init_resource::() .init_resource::() diff --git a/crates/bevy_render/src/pipeline/pipeline.rs b/crates/bevy_render/src/pipeline/pipeline.rs index ff65c0b640f50..9e1a0d040fe31 100644 --- a/crates/bevy_render/src/pipeline/pipeline.rs +++ b/crates/bevy_render/src/pipeline/pipeline.rs @@ -145,20 +145,6 @@ impl PipelineDescriptor { let mut layout = PipelineLayout::from_shader_layouts(&mut layouts); - // just obtain the stride from the attribute itself, since we are always using float format - // // TODO: support for different formats? - // for vertex_buffer_descriptor in &mut layout.vertex_buffer_descriptors { - // if vertex_buffer_descriptor.name == GL_VERTEX_INDEX { - // continue; - // } - // vertex_buffer_descriptor.stride = vertex_buffer_descriptor - // .attributes - // .get(0) - // .unwrap() - // .format - // .get_size(); - // } - if !dynamic_bindings.is_empty() { // set binding uniforms to dynamic if render resource bindings use dynamic for bind_group in layout.bind_groups.iter_mut() { diff --git a/crates/bevy_render/src/pipeline/pipeline_compiler.rs b/crates/bevy_render/src/pipeline/pipeline_compiler.rs index 2727f112b2071..a03cbdd310af4 100644 --- a/crates/bevy_render/src/pipeline/pipeline_compiler.rs +++ b/crates/bevy_render/src/pipeline/pipeline_compiler.rs @@ -1,17 +1,18 @@ use super::{state_descriptors::PrimitiveTopology, IndexFormat, PipelineDescriptor}; +use crate::pipeline::VERTEX_FALLBACK_LAYOUT_NAME; use crate::{ pipeline::{VertexAttributeDescriptor, VertexBufferDescriptor, VertexFormat}, renderer::RenderResourceContext, shader::{Shader, ShaderSource}, }; use bevy_asset::{Assets, Handle}; -use bevy_property::Property; +use bevy_property::{Properties, Property}; use bevy_utils::{HashMap, HashSet}; use once_cell::sync::Lazy; use serde::{Deserialize, Serialize}; use std::borrow::Cow; -#[derive(Clone, Eq, PartialEq, Debug)] //TODO julian: derive Properties? +#[derive(Clone, Eq, PartialEq, Debug, Properties)] pub struct PipelineSpecialization { pub shader_specialization: ShaderSpecialization, pub primitive_topology: PrimitiveTopology, @@ -169,7 +170,7 @@ impl PipelineCompiler { pipeline_specialization.mesh_attribute_layout.clone(); let mut fallback_vertex_buffer_descirptor = VertexBufferDescriptor { - name: Cow::from("Fallback"), //TODO julian: name acordingly + name: Cow::from(VERTEX_FALLBACK_LAYOUT_NAME), //TODO julian: name acordingly stride: VertexFormat::Float4.get_size(), //TODO julian: use smallest possible format! ..Default::default() }; @@ -196,11 +197,14 @@ impl PipelineCompiler { shader_location: shader_vertex_attribute.shader_location, }); } - } //TODO julian: also add other buffers, like instancing?... - pipeline_layout.vertex_buffer_descriptors = vec![ - mutated_vertex_buffer_descriptor, - fallback_vertex_buffer_descirptor, - ]; + } + //TODO julian: also add other buffers, like instancing?... + let mut vertex_buffer_descriptors = Vec::::default(); + vertex_buffer_descriptors.push(mutated_vertex_buffer_descriptor); + if !fallback_vertex_buffer_descirptor.attributes.is_empty() { + vertex_buffer_descriptors.push(fallback_vertex_buffer_descirptor); + } + pipeline_layout.vertex_buffer_descriptors = vertex_buffer_descriptors; specialized_descriptor.sample_count = pipeline_specialization.sample_count; specialized_descriptor.primitive_topology = pipeline_specialization.primitive_topology; specialized_descriptor.index_format = pipeline_specialization.index_format; diff --git a/crates/bevy_render/src/pipeline/render_pipelines.rs b/crates/bevy_render/src/pipeline/render_pipelines.rs index 41cc632af8c25..c8abc31914a70 100644 --- a/crates/bevy_render/src/pipeline/render_pipelines.rs +++ b/crates/bevy_render/src/pipeline/render_pipelines.rs @@ -7,8 +7,9 @@ use crate::{ }; use bevy_asset::{Assets, Handle}; use bevy_ecs::{Query, Res, ResMut}; +use bevy_property::Properties; -#[derive(Default, Clone)] //TODO julian: no properties +#[derive(Properties, Default, Clone)] #[non_exhaustive] pub struct RenderPipeline { pub pipeline: Handle, @@ -34,10 +35,10 @@ impl RenderPipeline { } } -#[derive(Clone)] //TODO julian: properties +#[derive(Properties, Clone)] pub struct RenderPipelines { pub pipelines: Vec, - //#[property(ignore)] //TODO julian: properties + #[property(ignore)] pub bindings: RenderResourceBindings, } diff --git a/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs b/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs index 54fb0d985aab7..26a6cff0d8a9a 100644 --- a/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs +++ b/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs @@ -1,10 +1,12 @@ use super::VertexFormat; +use bevy_property::Property; +use serde::{Deserialize, Serialize}; use std::{ borrow::Cow, hash::{Hash, Hasher}, }; -#[derive(Clone, Debug, Eq, PartialEq, Default)] +#[derive(Clone, Debug, Eq, PartialEq, Default, Property, Serialize, Deserialize)] pub struct VertexBufferDescriptor { pub name: Cow<'static, str>, pub stride: u64, @@ -12,6 +14,7 @@ pub struct VertexBufferDescriptor { pub attributes: Vec, } +pub const VERTEX_FALLBACK_LAYOUT_NAME: &str = "Fallback"; impl VertexBufferDescriptor { pub fn new_from_attribute( attribute: VertexAttributeDescriptor, @@ -31,7 +34,7 @@ impl VertexBufferDescriptor { self } } -#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)] pub enum InputStepMode { Vertex = 0, Instance = 1, @@ -43,7 +46,7 @@ impl Default for InputStepMode { } } -#[derive(Clone, Debug, Hash, Eq, PartialEq)] +#[derive(Clone, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)] pub struct VertexAttributeDescriptor { pub name: Cow<'static, str>, pub offset: u64, diff --git a/crates/bevy_render/src/pipeline/vertex_format.rs b/crates/bevy_render/src/pipeline/vertex_format.rs index b738e2858d983..750ea83c59a0e 100644 --- a/crates/bevy_render/src/pipeline/vertex_format.rs +++ b/crates/bevy_render/src/pipeline/vertex_format.rs @@ -1,6 +1,7 @@ use crate::Color; use bevy_math::{Mat4, Vec2, Vec3, Vec4}; -#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] +use serde::{Deserialize, Serialize}; +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)] pub enum VertexFormat { Uchar2 = 1, Uchar4 = 3, diff --git a/crates/bevy_render/src/renderer/render_resource/render_resource_bindings.rs b/crates/bevy_render/src/renderer/render_resource/render_resource_bindings.rs index 90cc2d261a128..bcd56a8d98f8c 100644 --- a/crates/bevy_render/src/renderer/render_resource/render_resource_bindings.rs +++ b/crates/bevy_render/src/renderer/render_resource/render_resource_bindings.rs @@ -141,29 +141,6 @@ impl RenderResourceBindings { } } - // TODO julian: needed? - // pub fn get_vertex_buffer(&self, attribute_name: Cow<'static, str>) -> Option { - // unimplemented!(); - // //TODO: - // // // TODO: hash based lookup? - // // for vertex_buffer in &self.vertex_buffers { - // // for attribute in &vertex_buffer.0.attributes { - // // if attribute.name == attribute_name { - // // Some(vertex_buffer.1.clone()) - // // } - // // } - // // } - // // - // // None - // } - // pub fn set_vertex_buffer( - // &mut self, - // buffer_descriptor: VertexBufferDescriptor, - // buffer_id: BufferId, - // ) { - // self.vertex_buffers.push((buffer_descriptor, buffer_id)); - // } - pub fn set_index_buffer(&mut self, index_buffer: BufferId) { self.index_buffer = Some(index_buffer); } From 8ff3bbb52fee3dec27cdcb9c62721ed580ac0f81 Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Fri, 16 Oct 2020 20:52:05 +0200 Subject: [PATCH 19/32] HashMap for attributes for consisten order and uniqueness. Removed VertexAttributeData/VertexAttribute --- crates/bevy_gltf/src/loader.rs | 22 +- crates/bevy_render/src/draw.rs | 6 +- crates/bevy_render/src/lib.rs | 3 +- crates/bevy_render/src/mesh/mesh.rs | 199 ++++++------------ .../src/pipeline/pipeline_compiler.rs | 8 +- .../bevy_render/src/shader/shader_reflect.rs | 1 - 6 files changed, 89 insertions(+), 150 deletions(-) diff --git a/crates/bevy_gltf/src/loader.rs b/crates/bevy_gltf/src/loader.rs index a19cf3ecb8cfa..97dbfb7606f55 100644 --- a/crates/bevy_gltf/src/loader.rs +++ b/crates/bevy_gltf/src/loader.rs @@ -1,12 +1,13 @@ use bevy_render::{ - mesh::{Indices, Mesh, VertexAttributeData}, + mesh::{Indices, Mesh}, pipeline::PrimitiveTopology, }; use anyhow::Result; use bevy_asset::AssetLoader; +use bevy_render::mesh::VertexAttributeValues; use gltf::{buffer::Source, mesh::Mode}; -use std::{fs, io, path::Path}; +use std::{borrow::Cow, fs, io, path::Path}; use thiserror::Error; /// Loads meshes from GLTF files into Mesh assets @@ -74,27 +75,30 @@ fn load_node(buffer_data: &[Vec], node: &gltf::Node, depth: i32) -> Result for VertexFormat { } } } - -//TODO: replace by tuple? -#[derive(Debug)] -pub struct VertexAttributeData { - pub name: Cow<'static, str>, - pub values: VertexAttributeValues, //TODO: the values aren't necessarily needed after been submitted to the GPU -} - -impl PartialEq for VertexAttributeData { - fn eq(&self, other: &Self) -> bool { - self.name == other.name +impl Into for Vec { + fn into(self) -> VertexAttributeValues { + VertexAttributeValues::Float(self) } } - -impl Hash for VertexAttributeData { - fn hash(&self, state: &mut H) { - self.name.hash(state); +impl Into for Vec<[f32; 2]> { + fn into(self) -> VertexAttributeValues { + VertexAttributeValues::Float2(self) } } - -impl Eq for VertexAttributeData {} - -impl VertexAttributeData { - pub const NORMAL: &'static str = "Vertex_Normal"; - pub const POSITION: &'static str = "Vertex_Position"; - pub const UV: &'static str = "Vertex_Uv"; - - pub fn position(positions: Vec<[f32; 3]>) -> Self { - VertexAttributeData { - name: Self::POSITION.into(), - values: VertexAttributeValues::Float3(positions), - } - } - - pub fn normal(normals: Vec<[f32; 3]>) -> Self { - VertexAttributeData { - name: Self::NORMAL.into(), - values: VertexAttributeValues::Float3(normals), - } - } - - pub fn uv(uvs: Vec<[f32; 2]>) -> Self { - VertexAttributeData { - name: Self::UV.into(), - values: VertexAttributeValues::Float2(uvs), - } +impl Into for Vec<[f32; 3]> { + fn into(self) -> VertexAttributeValues { + VertexAttributeValues::Float3(self) } } - -#[derive(Error, Debug)] -pub enum MeshToVertexBufferError { - #[error("VertexBufferDescriptor requires a VertexBufferAttribute this Mesh does not contain.")] - MissingVertexAttribute { attribute_name: Cow<'static, str> }, - #[error("Mesh VertexAttribute VertexFormat is incompatible with VertexBufferDescriptor VertexAttribute VertexFormat.")] - IncompatibleVertexAttributeFormat { - attribute_name: Cow<'static, str>, - descriptor_format: VertexFormat, - mesh_format: VertexFormat, - }, +impl Into for Vec<[f32; 4]> { + fn into(self) -> VertexAttributeValues { + VertexAttributeValues::Float4(self) + } } #[derive(Debug)] @@ -124,51 +83,32 @@ pub enum Indices { U32(Vec), } +pub type VertexAttributesMap = HashMap, VertexAttributeValues>; #[derive(Debug)] pub struct Mesh { pub primitive_topology: PrimitiveTopology, - pub attributes: Vec, + /// All defined attributes for this mesh. Attribute name (Case-sensitive) maps to attribute values. + pub attributes: VertexAttributesMap, pub indices: Option, pub attribute_vertex_buffer_descriptor: Option, //TODO julian: should not be Option } impl Mesh { - pub fn new( - primitive_topology: PrimitiveTopology, - mut attributes: Vec, - indices: Option, - ) -> Self { - let mut mesh = Mesh { - primitive_topology, - attributes: Vec::default(), - indices, - attribute_vertex_buffer_descriptor: None, - }; - for attribute in attributes.drain(..) { - mesh.insert_attribute(attribute); - } - mesh - } + pub const ATTRIBUTE_NORMAL: &'static str = "Vertex_Normal"; + pub const ATTRIBUTE_POSITION: &'static str = "Vertex_Position"; + pub const ATTRIBUTE_UV_0: &'static str = "Vertex_Uv"; - pub fn new_empty(primitive_topology: PrimitiveTopology) -> Self { + pub fn new(primitive_topology: PrimitiveTopology, indices: Option) -> Self { Mesh { primitive_topology, - attributes: Vec::default(), - indices: None, + attributes: Default::default(), + indices, attribute_vertex_buffer_descriptor: None, } } - pub fn insert_attribute(&mut self, new_vertex_attribute: VertexAttributeData) { - self.attributes.push(new_vertex_attribute); - } - - pub fn get_attribute(&mut self, name: Cow<'static, str>) -> Option<&VertexAttributeData> { - self.attributes.iter().find(|x| x.name == name) - } - - pub fn remove_attribute(&mut self, name: Cow<'static, str>) { - self.attributes.retain(|x| x.name != name); + pub fn insert_attribute(&mut self, name: Cow<'static, str>, values: VertexAttributeValues) { + self.attributes.insert(name.clone(), values); } pub fn get_index_buffer_bytes(&self) -> Option> { @@ -181,10 +121,11 @@ impl Mesh { /// Generation for some primitive shape meshes. pub mod shape { - use super::{Indices, Mesh, VertexAttributeData}; + use super::{Indices, Mesh}; use crate::pipeline::PrimitiveTopology; use bevy_math::*; use hexasphere::Hexasphere; + use std::borrow::Cow; /// A cube. pub struct Cube { @@ -252,15 +193,11 @@ pub mod shape { 20, 21, 22, 22, 23, 20, // back ]); - Mesh::new( - PrimitiveTopology::TriangleList, - vec![ - VertexAttributeData::position(positions), - VertexAttributeData::normal(normals), - VertexAttributeData::uv(uvs), - ], - Some(indices), - ) + let mut mesh = Mesh::new(PrimitiveTopology::TriangleList, Some(indices)); + mesh.insert_attribute(Cow::Borrowed(Mesh::ATTRIBUTE_POSITION), positions.into()); + mesh.insert_attribute(Cow::Borrowed(Mesh::ATTRIBUTE_NORMAL), normals.into()); + mesh.insert_attribute(Cow::Borrowed(Mesh::ATTRIBUTE_UV_0), uvs.into()); + mesh } } @@ -341,24 +278,20 @@ pub mod shape { let indices = Indices::U32(vec![0, 2, 1, 0, 3, 2]); - let mut positions = Vec::new(); - let mut normals = Vec::new(); - let mut uvs = Vec::new(); + let mut positions = Vec::<[f32; 3]>::new(); + let mut normals = Vec::<[f32; 3]>::new(); + let mut uvs = Vec::<[f32; 2]>::new(); for (position, normal, uv) in vertices.iter() { positions.push(*position); normals.push(*normal); uvs.push(*uv); } - Mesh::new( - PrimitiveTopology::TriangleList, - vec![ - VertexAttributeData::position(positions), - VertexAttributeData::normal(normals), - VertexAttributeData::uv(uvs), - ], - Some(indices), - ) + let mut mesh = Mesh::new(PrimitiveTopology::TriangleList, Some(indices)); + mesh.insert_attribute(Cow::Borrowed(Mesh::ATTRIBUTE_POSITION), positions.into()); + mesh.insert_attribute(Cow::Borrowed(Mesh::ATTRIBUTE_NORMAL), normals.into()); + mesh.insert_attribute(Cow::Borrowed(Mesh::ATTRIBUTE_UV_0), uvs.into()); + mesh } } @@ -390,15 +323,11 @@ pub mod shape { uvs.push(*uv); } - Mesh::new( - PrimitiveTopology::TriangleList, - vec![ - VertexAttributeData::position(positions), - VertexAttributeData::normal(normals), - VertexAttributeData::uv(uvs), - ], - Some(indices), - ) + let mut mesh = Mesh::new(PrimitiveTopology::TriangleList, Some(indices)); + mesh.insert_attribute(Cow::Borrowed(Mesh::ATTRIBUTE_POSITION), positions.into()); + mesh.insert_attribute(Cow::Borrowed(Mesh::ATTRIBUTE_NORMAL), normals.into()); + mesh.insert_attribute(Cow::Borrowed(Mesh::ATTRIBUTE_UV_0), uvs.into()); + mesh } } @@ -463,15 +392,11 @@ pub mod shape { let indices = Indices::U32(indices); - Mesh::new( - PrimitiveTopology::TriangleList, - vec![ - VertexAttributeData::position(points), - VertexAttributeData::normal(normals), - VertexAttributeData::uv(uvs), - ], - Some(indices), - ) + let mut mesh = Mesh::new(PrimitiveTopology::TriangleList, Some(indices)); + mesh.insert_attribute(Cow::Borrowed(Mesh::ATTRIBUTE_POSITION), points.into()); + mesh.insert_attribute(Cow::Borrowed(Mesh::ATTRIBUTE_NORMAL), normals.into()); + mesh.insert_attribute(Cow::Borrowed(Mesh::ATTRIBUTE_UV_0), uvs.into()); + mesh } } } @@ -550,9 +475,9 @@ pub fn mesh_resource_provider_system( ); // Vertex buffer - let vertex_count = mesh.attributes.first().unwrap().values.len(); //TODO julian: assert for different lengths of attributes, also move this somewhere else + let vertex_count = attributes_count_vertices(&mesh.attributes).unwrap(); let interleaved_buffer = - attributes_to_vertex_buffer_data(&mesh.attributes, vertex_count as u32); + attributes_to_vertex_buffer_data(&mesh.attributes, vertex_count); mesh.attribute_vertex_buffer_descriptor = Some(interleaved_buffer.1); render_resource_context.set_asset_resource( @@ -576,7 +501,7 @@ pub fn mesh_resource_provider_system( buffer_usage: BufferUsage::VERTEX, ..Default::default() }, - &vec![0; vertex_count * VertexFormat::Float4.get_size() as usize], + &vec![0; (vertex_count * VertexFormat::Float4.get_size() as u32) as usize], )), VERTEX_FALLBACK_BUFFER_ID, //TODO julian: pipeline::get_vertex_attribute_name_id(&attribute.name), ); @@ -618,26 +543,34 @@ pub fn mesh_resource_provider_system( } } +pub fn attributes_count_vertices(attributes: &VertexAttributesMap) -> Option { + let mut vertex_count: Option = None; + for attribute in attributes { + let attribute_len = attribute.1.len(); + //TODO julian: assert for different lengths of attributes, also move this somewhere else + vertex_count = Some(attribute_len as u32); + } + vertex_count +} pub fn attributes_to_vertex_buffer_data( - attributes: &[VertexAttributeData], + attributes: &VertexAttributesMap, vertex_count: u32, ) -> (Vec, VertexBufferDescriptor) { // get existing attribute data as bytes and generate attribute descriptor let mut attributes_gpu_ready = Vec::<(VertexAttributeDescriptor, Vec)>::default(); let mut accumulated_offset = 0; - //TODO: sort attribute data first! different attribute orders will introduce more pipeline specialisation than necessary for attribute_data in attributes { // TODO: allow for custom converter here - let vertex_format = VertexFormat::from(&attribute_data.values); + let vertex_format = VertexFormat::from(attribute_data.1); attributes_gpu_ready.push(( // this is not supposed to be used directly, as we don't know the shader location in advance VertexAttributeDescriptor { - name: attribute_data.name.clone(), + name: attribute_data.0.clone(), offset: accumulated_offset, format: vertex_format, shader_location: 0, }, - attribute_data.values.get_bytes().to_vec(), + attribute_data.1.get_bytes().to_vec(), )); accumulated_offset += vertex_format.get_size(); } diff --git a/crates/bevy_render/src/pipeline/pipeline_compiler.rs b/crates/bevy_render/src/pipeline/pipeline_compiler.rs index a03cbdd310af4..13c91da8c05df 100644 --- a/crates/bevy_render/src/pipeline/pipeline_compiler.rs +++ b/crates/bevy_render/src/pipeline/pipeline_compiler.rs @@ -1,7 +1,9 @@ use super::{state_descriptors::PrimitiveTopology, IndexFormat, PipelineDescriptor}; -use crate::pipeline::VERTEX_FALLBACK_LAYOUT_NAME; use crate::{ - pipeline::{VertexAttributeDescriptor, VertexBufferDescriptor, VertexFormat}, + pipeline::{ + VertexAttributeDescriptor, VertexBufferDescriptor, VertexFormat, + VERTEX_FALLBACK_LAYOUT_NAME, + }, renderer::RenderResourceContext, shader::{Shader, ShaderSource}, }; @@ -170,7 +172,7 @@ impl PipelineCompiler { pipeline_specialization.mesh_attribute_layout.clone(); let mut fallback_vertex_buffer_descirptor = VertexBufferDescriptor { - name: Cow::from(VERTEX_FALLBACK_LAYOUT_NAME), //TODO julian: name acordingly + name: Cow::Borrowed(VERTEX_FALLBACK_LAYOUT_NAME), //TODO julian: name acordingly stride: VertexFormat::Float4.get_size(), //TODO julian: use smallest possible format! ..Default::default() }; diff --git a/crates/bevy_render/src/shader/shader_reflect.rs b/crates/bevy_render/src/shader/shader_reflect.rs index 86188f24b85f7..22b806acbdb34 100644 --- a/crates/bevy_render/src/shader/shader_reflect.rs +++ b/crates/bevy_render/src/shader/shader_reflect.rs @@ -75,7 +75,6 @@ impl ShaderLayout { }; // create a new buffer descriptor, per attribute! - // TODO julian: make a different struct for this kind of VertexBufferDescriptor (always 1 attribute, not intended for actually use) vertex_buffer_descriptors.push(VertexBufferDescriptor { attributes: vec![vertex_attribute_descriptor], name: current_buffer_name.into(), From 5608eb2fab9bafc98e7fe26bc2cb1400a5fec651 Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Tue, 20 Oct 2020 00:10:17 +0200 Subject: [PATCH 20/32] fixed text. cleanup --- crates/bevy_render/src/mesh/mesh.rs | 26 +++++----- .../src/pipeline/pipeline_compiler.rs | 6 +-- .../src/pipeline/render_pipelines.rs | 1 - .../src/pipeline/vertex_buffer_descriptor.rs | 2 - crates/bevy_text/src/draw.rs | 52 +++++++++++++------ 5 files changed, 52 insertions(+), 35 deletions(-) diff --git a/crates/bevy_render/src/mesh/mesh.rs b/crates/bevy_render/src/mesh/mesh.rs index 2b84be8441e90..c3c6e6969f588 100644 --- a/crates/bevy_render/src/mesh/mesh.rs +++ b/crates/bevy_render/src/mesh/mesh.rs @@ -13,6 +13,8 @@ use crate::pipeline::{InputStepMode, VertexAttributeDescriptor, VertexBufferDesc use bevy_utils::HashMap; pub const INDEX_BUFFER_ASSET_INDEX: u64 = 0; +pub const VERTEX_ATTRIBUTE_BUFFER_ID: u64 = 10; +pub const VERTEX_FALLBACK_BUFFER_ID: u64 = 20; #[derive(Clone, Debug)] pub enum VertexAttributeValues { Float(Vec), @@ -90,7 +92,7 @@ pub struct Mesh { /// All defined attributes for this mesh. Attribute name (Case-sensitive) maps to attribute values. pub attributes: VertexAttributesMap, pub indices: Option, - pub attribute_vertex_buffer_descriptor: Option, //TODO julian: should not be Option + pub attribute_vertex_buffer_descriptor: Option, } impl Mesh { @@ -427,8 +429,6 @@ pub struct MeshResourceProviderState { mesh_event_reader: EventReader>, } -const VERTEX_ATTRIBUTE_BUFFER_ID: u64 = 10; //TODO julian: remove -const VERTEX_FALLBACK_BUFFER_ID: u64 = 20; //TODO julian: remove pub fn mesh_resource_provider_system( mut state: Local, render_resource_context: Res>, @@ -489,11 +489,11 @@ pub fn mesh_resource_provider_system( }, &interleaved_buffer.0, )), - VERTEX_ATTRIBUTE_BUFFER_ID, //TODO julian: pipeline::get_vertex_attribute_name_id(&attribute.name), + VERTEX_ATTRIBUTE_BUFFER_ID, ); // Fallback buffer - // TODO julian: can be done with a 1 byte buffer + zero stride? + // TODO: can be done with a 1 byte buffer + zero stride? render_resource_context.set_asset_resource( *changed_mesh_handle, RenderResourceId::Buffer(render_resource_context.create_buffer_with_data( @@ -503,7 +503,7 @@ pub fn mesh_resource_provider_system( }, &vec![0; (vertex_count * VertexFormat::Float4.get_size() as u32) as usize], )), - VERTEX_FALLBACK_BUFFER_ID, //TODO julian: pipeline::get_vertex_attribute_name_id(&attribute.name), + VERTEX_FALLBACK_BUFFER_ID, ); } } @@ -575,8 +575,7 @@ pub fn attributes_to_vertex_buffer_data( accumulated_offset += vertex_format.get_size(); } - // TODO: make interleaved configurable? or call this function for each interleaved buffer? - let mut interleaved_buffer = Vec::::default(); + let mut attributes_interleaved_buffer = Vec::::default(); // bundle into interleaved buffers for vertex_index in 0..vertex_count { @@ -585,17 +584,20 @@ pub fn attributes_to_vertex_buffer_data( let bytes = &attribute.1; let stride = bytes.len() / vertex_count as usize; // insert one element - interleaved_buffer + attributes_interleaved_buffer .extend(&bytes[vertex_index * stride..vertex_index * stride + stride]); } } let vertex_buffer_descriptor_reference = VertexBufferDescriptor { - name: Default::default(), //TODO: naming! + name: Default::default(), stride: accumulated_offset, step_mode: InputStepMode::Vertex, - attributes: attributes_gpu_ready.iter().map(|x| x.0.clone()).collect(), //TODO: clone? + attributes: attributes_gpu_ready.iter().map(|x| x.0.clone()).collect(), }; - (interleaved_buffer, vertex_buffer_descriptor_reference) + ( + attributes_interleaved_buffer, + vertex_buffer_descriptor_reference, + ) } diff --git a/crates/bevy_render/src/pipeline/pipeline_compiler.rs b/crates/bevy_render/src/pipeline/pipeline_compiler.rs index 13c91da8c05df..e51974be87ad5 100644 --- a/crates/bevy_render/src/pipeline/pipeline_compiler.rs +++ b/crates/bevy_render/src/pipeline/pipeline_compiler.rs @@ -172,8 +172,8 @@ impl PipelineCompiler { pipeline_specialization.mesh_attribute_layout.clone(); let mut fallback_vertex_buffer_descirptor = VertexBufferDescriptor { - name: Cow::Borrowed(VERTEX_FALLBACK_LAYOUT_NAME), //TODO julian: name acordingly - stride: VertexFormat::Float4.get_size(), //TODO julian: use smallest possible format! + name: Cow::Borrowed(VERTEX_FALLBACK_LAYOUT_NAME), + stride: VertexFormat::Float4.get_size(), //TODO: use smallest possible format ..Default::default() }; for shader_vertex_attribute in &mut pipeline_layout.vertex_buffer_descriptors.iter_mut() { @@ -200,7 +200,7 @@ impl PipelineCompiler { }); } } - //TODO julian: also add other buffers, like instancing?... + //TODO: add other buffers (like instancing) here let mut vertex_buffer_descriptors = Vec::::default(); vertex_buffer_descriptors.push(mutated_vertex_buffer_descriptor); if !fallback_vertex_buffer_descirptor.attributes.is_empty() { diff --git a/crates/bevy_render/src/pipeline/render_pipelines.rs b/crates/bevy_render/src/pipeline/render_pipelines.rs index c8abc31914a70..83885e247e85d 100644 --- a/crates/bevy_render/src/pipeline/render_pipelines.rs +++ b/crates/bevy_render/src/pipeline/render_pipelines.rs @@ -100,7 +100,6 @@ pub fn draw_render_pipelines_system( .as_ref() .unwrap() .clone(); - //TODO julian: is this a good idea? } for render_pipeline in render_pipelines.pipelines.iter() { diff --git a/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs b/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs index 26a6cff0d8a9a..40c3297319c63 100644 --- a/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs +++ b/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs @@ -54,8 +54,6 @@ pub struct VertexAttributeDescriptor { pub shader_location: u32, } -//pub type StaticCowString = Cow<'static, str>; //TODO julian: use this? - /// Internally, `bevy_render` uses hashes to identify vertex attribute names. pub fn get_vertex_attribute_name_id(name: &str) -> u64 { let mut hasher = bevy_utils::AHasher::default(); diff --git a/crates/bevy_text/src/draw.rs b/crates/bevy_text/src/draw.rs index 8f35c326470ed..972e01d19bdcc 100644 --- a/crates/bevy_text/src/draw.rs +++ b/crates/bevy_text/src/draw.rs @@ -2,10 +2,13 @@ use crate::{Font, FontAtlasSet}; use ab_glyph::{Glyph, PxScale, ScaleFont}; use bevy_asset::Assets; use bevy_math::{Mat4, Vec2, Vec3}; +use bevy_render::pipeline::{ + InputStepMode, VertexAttributeDescriptor, VertexBufferDescriptor, VertexFormat, +}; use bevy_render::{ color::Color, draw::{Draw, DrawContext, DrawError, Drawable}, - mesh, pipeline, + mesh, pipeline::PipelineSpecialization, prelude::Msaa, renderer::{ @@ -14,6 +17,7 @@ use bevy_render::{ }, }; use bevy_sprite::{TextureAtlas, TextureAtlasSprite}; +use std::borrow::Cow; #[derive(Clone)] pub struct TextStyle { @@ -50,28 +54,42 @@ impl<'a> Drawable for DrawableText<'a> { bevy_sprite::SPRITE_SHEET_PIPELINE_HANDLE, &PipelineSpecialization { sample_count: self.msaa.samples, + // TODO: hacky. find a way to get the actual VertexLayout from the QuadMesh + mesh_attribute_layout: VertexBufferDescriptor { + name: Default::default(), + stride: VertexFormat::Float3.get_size() * 2 + VertexFormat::Float2.get_size(), + step_mode: InputStepMode::Vertex, + attributes: vec![ + VertexAttributeDescriptor { + name: Cow::from("Vertex_Position"), + offset: 0, + format: VertexFormat::Float3, + shader_location: 0, + }, + VertexAttributeDescriptor { + name: Cow::from("Vertex_Normal"), + offset: VertexFormat::Float3.get_size(), + format: VertexFormat::Float3, + shader_location: 1, + }, + VertexAttributeDescriptor { + name: Cow::from("Vertex_Uv"), + offset: VertexFormat::Float3.get_size() * 2, + format: VertexFormat::Float2, + shader_location: 2, + }, + ], + }, ..Default::default() }, )?; let render_resource_context = &**context.render_resource_context; - let pipeline_layout = context.get_pipeline_layout().unwrap(); - for vertex_buffer_descriptor in &pipeline_layout.vertex_buffer_descriptors { - let name_id = pipeline::get_vertex_attribute_name_id(&vertex_buffer_descriptor.name); - if let Some(RenderResourceId::Buffer(vertex_attr_buffer_id)) = - render_resource_context.get_asset_resource(bevy_sprite::QUAD_HANDLE, name_id) - { - draw.set_vertex_buffer( - vertex_buffer_descriptor - .attributes - .get(0) - .unwrap() - .shader_location, - vertex_attr_buffer_id, - 0, - ); - } + if let Some(RenderResourceId::Buffer(vertex_attribute_buffer_id)) = render_resource_context + .get_asset_resource(bevy_sprite::QUAD_HANDLE, mesh::VERTEX_ATTRIBUTE_BUFFER_ID) + { + draw.set_vertex_buffer(0, vertex_attribute_buffer_id, 0); } let mut indices = 0..0; From 0d61e8114e29adea0c2b251acf61072c81e6f060 Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Wed, 21 Oct 2020 17:18:39 +0200 Subject: [PATCH 21/32] Removed mesh.insert_attribute. removed VertexBufferDescriptor hack in bevy_text. More comments! --- crates/bevy_render/src/mesh/mesh.rs | 68 +++++++++++-------- .../src/pipeline/render_pipelines.rs | 2 +- crates/bevy_text/src/draw.rs | 36 ++-------- crates/bevy_ui/src/widget/text.rs | 15 +++- 4 files changed, 61 insertions(+), 60 deletions(-) diff --git a/crates/bevy_render/src/mesh/mesh.rs b/crates/bevy_render/src/mesh/mesh.rs index c3c6e6969f588..0a55eb5336c23 100644 --- a/crates/bevy_render/src/mesh/mesh.rs +++ b/crates/bevy_render/src/mesh/mesh.rs @@ -84,15 +84,16 @@ pub enum Indices { U16(Vec), U32(Vec), } - -pub type VertexAttributesMap = HashMap, VertexAttributeValues>; +// TODO: allow values to be unloaded after been submitting to the GPU to conserve memory +pub type VertexAttributesHashMap = HashMap, VertexAttributeValues>; #[derive(Debug)] pub struct Mesh { pub primitive_topology: PrimitiveTopology, - /// All defined attributes for this mesh. Attribute name (Case-sensitive) maps to attribute values. - pub attributes: VertexAttributesMap, + /// `HashMap` with all defined vertex attributes (Positions, Normals, ...) for this mesh. Attribute name maps to attribute values. + pub attributes: VertexAttributesHashMap, pub indices: Option, - pub attribute_vertex_buffer_descriptor: Option, + /// The layout of the attributes in the GPU buffer without `shader_location`. `None` will indicate that no data has been uploaded to the GPU yet. + pub attribute_buffer_descriptor_reference: Option, } impl Mesh { @@ -105,14 +106,10 @@ impl Mesh { primitive_topology, attributes: Default::default(), indices, - attribute_vertex_buffer_descriptor: None, + attribute_buffer_descriptor_reference: Default::default(), } } - pub fn insert_attribute(&mut self, name: Cow<'static, str>, values: VertexAttributeValues) { - self.attributes.insert(name.clone(), values); - } - pub fn get_index_buffer_bytes(&self) -> Option> { self.indices.as_ref().map(|indices| match &indices { Indices::U16(indices) => indices.as_slice().as_bytes().to_vec(), @@ -196,9 +193,12 @@ pub mod shape { ]); let mut mesh = Mesh::new(PrimitiveTopology::TriangleList, Some(indices)); - mesh.insert_attribute(Cow::Borrowed(Mesh::ATTRIBUTE_POSITION), positions.into()); - mesh.insert_attribute(Cow::Borrowed(Mesh::ATTRIBUTE_NORMAL), normals.into()); - mesh.insert_attribute(Cow::Borrowed(Mesh::ATTRIBUTE_UV_0), uvs.into()); + mesh.attributes + .insert(Cow::Borrowed(Mesh::ATTRIBUTE_POSITION), positions.into()); + mesh.attributes + .insert(Cow::Borrowed(Mesh::ATTRIBUTE_NORMAL), normals.into()); + mesh.attributes + .insert(Cow::Borrowed(Mesh::ATTRIBUTE_UV_0), uvs.into()); mesh } } @@ -290,9 +290,12 @@ pub mod shape { } let mut mesh = Mesh::new(PrimitiveTopology::TriangleList, Some(indices)); - mesh.insert_attribute(Cow::Borrowed(Mesh::ATTRIBUTE_POSITION), positions.into()); - mesh.insert_attribute(Cow::Borrowed(Mesh::ATTRIBUTE_NORMAL), normals.into()); - mesh.insert_attribute(Cow::Borrowed(Mesh::ATTRIBUTE_UV_0), uvs.into()); + mesh.attributes + .insert(Cow::Borrowed(Mesh::ATTRIBUTE_POSITION), positions.into()); + mesh.attributes + .insert(Cow::Borrowed(Mesh::ATTRIBUTE_NORMAL), normals.into()); + mesh.attributes + .insert(Cow::Borrowed(Mesh::ATTRIBUTE_UV_0), uvs.into()); mesh } } @@ -326,9 +329,12 @@ pub mod shape { } let mut mesh = Mesh::new(PrimitiveTopology::TriangleList, Some(indices)); - mesh.insert_attribute(Cow::Borrowed(Mesh::ATTRIBUTE_POSITION), positions.into()); - mesh.insert_attribute(Cow::Borrowed(Mesh::ATTRIBUTE_NORMAL), normals.into()); - mesh.insert_attribute(Cow::Borrowed(Mesh::ATTRIBUTE_UV_0), uvs.into()); + mesh.attributes + .insert(Cow::Borrowed(Mesh::ATTRIBUTE_POSITION), positions.into()); + mesh.attributes + .insert(Cow::Borrowed(Mesh::ATTRIBUTE_NORMAL), normals.into()); + mesh.attributes + .insert(Cow::Borrowed(Mesh::ATTRIBUTE_UV_0), uvs.into()); mesh } } @@ -395,9 +401,12 @@ pub mod shape { let indices = Indices::U32(indices); let mut mesh = Mesh::new(PrimitiveTopology::TriangleList, Some(indices)); - mesh.insert_attribute(Cow::Borrowed(Mesh::ATTRIBUTE_POSITION), points.into()); - mesh.insert_attribute(Cow::Borrowed(Mesh::ATTRIBUTE_NORMAL), normals.into()); - mesh.insert_attribute(Cow::Borrowed(Mesh::ATTRIBUTE_UV_0), uvs.into()); + mesh.attributes + .insert(Cow::Borrowed(Mesh::ATTRIBUTE_POSITION), points.into()); + mesh.attributes + .insert(Cow::Borrowed(Mesh::ATTRIBUTE_NORMAL), normals.into()); + mesh.attributes + .insert(Cow::Borrowed(Mesh::ATTRIBUTE_UV_0), uvs.into()); mesh } } @@ -479,7 +488,7 @@ pub fn mesh_resource_provider_system( let interleaved_buffer = attributes_to_vertex_buffer_data(&mesh.attributes, vertex_count); - mesh.attribute_vertex_buffer_descriptor = Some(interleaved_buffer.1); + mesh.attribute_buffer_descriptor_reference = Some(interleaved_buffer.1); render_resource_context.set_asset_resource( *changed_mesh_handle, RenderResourceId::Buffer(render_resource_context.create_buffer_with_data( @@ -543,27 +552,30 @@ pub fn mesh_resource_provider_system( } } -pub fn attributes_count_vertices(attributes: &VertexAttributesMap) -> Option { +pub fn attributes_count_vertices(attributes: &VertexAttributesHashMap) -> Option { let mut vertex_count: Option = None; for attribute in attributes { let attribute_len = attribute.1.len(); - //TODO julian: assert for different lengths of attributes, also move this somewhere else + if let Some(previous_vertex_count) = vertex_count { + assert_eq!(previous_vertex_count, attribute_len as u32, + "Attribute {} has a different vertex count ({}) than other attributes ({}) in this mesh.", attribute.0, attribute_len, previous_vertex_count); + } vertex_count = Some(attribute_len as u32); } vertex_count } pub fn attributes_to_vertex_buffer_data( - attributes: &VertexAttributesMap, + attributes: &VertexAttributesHashMap, vertex_count: u32, ) -> (Vec, VertexBufferDescriptor) { // get existing attribute data as bytes and generate attribute descriptor let mut attributes_gpu_ready = Vec::<(VertexAttributeDescriptor, Vec)>::default(); let mut accumulated_offset = 0; - for attribute_data in attributes { + for attribute_data in attributes.iter() { // TODO: allow for custom converter here let vertex_format = VertexFormat::from(attribute_data.1); attributes_gpu_ready.push(( - // this is not supposed to be used directly, as we don't know the shader location in advance + // this serves as a reference and is not supposed to be used directly. VertexAttributeDescriptor { name: attribute_data.0.clone(), offset: accumulated_offset, diff --git a/crates/bevy_render/src/pipeline/render_pipelines.rs b/crates/bevy_render/src/pipeline/render_pipelines.rs index 83885e247e85d..80ae23b04af6b 100644 --- a/crates/bevy_render/src/pipeline/render_pipelines.rs +++ b/crates/bevy_render/src/pipeline/render_pipelines.rs @@ -96,7 +96,7 @@ pub fn draw_render_pipelines_system( pipeline.specialization.sample_count = msaa.samples; pipeline.specialization.index_format = index_format; pipeline.specialization.mesh_attribute_layout = mesh - .attribute_vertex_buffer_descriptor + .attribute_buffer_descriptor_reference .as_ref() .unwrap() .clone(); diff --git a/crates/bevy_text/src/draw.rs b/crates/bevy_text/src/draw.rs index 972e01d19bdcc..51fdab938dd0c 100644 --- a/crates/bevy_text/src/draw.rs +++ b/crates/bevy_text/src/draw.rs @@ -2,9 +2,7 @@ use crate::{Font, FontAtlasSet}; use ab_glyph::{Glyph, PxScale, ScaleFont}; use bevy_asset::Assets; use bevy_math::{Mat4, Vec2, Vec3}; -use bevy_render::pipeline::{ - InputStepMode, VertexAttributeDescriptor, VertexBufferDescriptor, VertexFormat, -}; +use bevy_render::pipeline::VertexBufferDescriptor; use bevy_render::{ color::Color, draw::{Draw, DrawContext, DrawError, Drawable}, @@ -17,7 +15,6 @@ use bevy_render::{ }, }; use bevy_sprite::{TextureAtlas, TextureAtlasSprite}; -use std::borrow::Cow; #[derive(Clone)] pub struct TextStyle { @@ -45,6 +42,7 @@ pub struct DrawableText<'a> { pub style: &'a TextStyle, pub text: &'a str, pub msaa: &'a Msaa, + pub font_quad_vertex_descriptor: &'a VertexBufferDescriptor, } impl<'a> Drawable for DrawableText<'a> { @@ -54,32 +52,7 @@ impl<'a> Drawable for DrawableText<'a> { bevy_sprite::SPRITE_SHEET_PIPELINE_HANDLE, &PipelineSpecialization { sample_count: self.msaa.samples, - // TODO: hacky. find a way to get the actual VertexLayout from the QuadMesh - mesh_attribute_layout: VertexBufferDescriptor { - name: Default::default(), - stride: VertexFormat::Float3.get_size() * 2 + VertexFormat::Float2.get_size(), - step_mode: InputStepMode::Vertex, - attributes: vec![ - VertexAttributeDescriptor { - name: Cow::from("Vertex_Position"), - offset: 0, - format: VertexFormat::Float3, - shader_location: 0, - }, - VertexAttributeDescriptor { - name: Cow::from("Vertex_Normal"), - offset: VertexFormat::Float3.get_size(), - format: VertexFormat::Float3, - shader_location: 1, - }, - VertexAttributeDescriptor { - name: Cow::from("Vertex_Uv"), - offset: VertexFormat::Float3.get_size() * 2, - format: VertexFormat::Float2, - shader_location: 2, - }, - ], - }, + mesh_attribute_layout: self.font_quad_vertex_descriptor.clone(), ..Default::default() }, )?; @@ -90,6 +63,8 @@ impl<'a> Drawable for DrawableText<'a> { .get_asset_resource(bevy_sprite::QUAD_HANDLE, mesh::VERTEX_ATTRIBUTE_BUFFER_ID) { draw.set_vertex_buffer(0, vertex_attribute_buffer_id, 0); + } else { + println!("could not find vertex buffer for bevy_sprite::QUAD_HANDLE") } let mut indices = 0..0; @@ -177,6 +152,7 @@ impl<'a> Drawable for DrawableText<'a> { .add_binding(0, transform_buffer) .add_binding(1, sprite_buffer) .finish(); + context.create_bind_group_resource(2, &sprite_bind_group)?; draw.set_bind_group(2, &sprite_bind_group); draw.draw_indexed(indices.clone(), 0, 0..1); diff --git a/crates/bevy_ui/src/widget/text.rs b/crates/bevy_ui/src/widget/text.rs index cb6d558c94694..982e30a4df732 100644 --- a/crates/bevy_ui/src/widget/text.rs +++ b/crates/bevy_ui/src/widget/text.rs @@ -2,13 +2,15 @@ use crate::{CalculatedSize, Node}; use bevy_asset::{Assets, Handle}; use bevy_ecs::{Changed, Entity, Local, Query, Res, ResMut}; use bevy_math::Size; +use bevy_render::mesh::Mesh; +use bevy_render::pipeline::VertexBufferDescriptor; use bevy_render::{ draw::{Draw, DrawContext, Drawable}, prelude::Msaa, renderer::{AssetRenderResourceBindings, RenderResourceBindings}, texture::Texture, }; -use bevy_sprite::TextureAtlas; +use bevy_sprite::{TextureAtlas, QUAD_HANDLE}; use bevy_text::{DrawableText, Font, FontAtlasSet, TextStyle}; use bevy_transform::prelude::GlobalTransform; @@ -98,10 +100,20 @@ pub fn draw_text_system( msaa: Res, font_atlas_sets: Res>, texture_atlases: Res>, + meshes: Res>, mut render_resource_bindings: ResMut, mut asset_render_resource_bindings: ResMut, mut query: Query<(&mut Draw, &Text, &Node, &GlobalTransform)>, ) { + let font_quad_vertex_descriptor = { + let font_quad = meshes.get(&QUAD_HANDLE).unwrap(); + font_quad + .attribute_buffer_descriptor_reference + .as_ref() + .unwrap() + .clone() + }; + for (mut draw, text, node, global_transform) in &mut query.iter() { if let Some(font) = fonts.get(&text.font) { let position = global_transform.translation() - (node.size / 2.0).extend(0.0); @@ -118,6 +130,7 @@ pub fn draw_text_system( style: &text.style, text: &text.value, container_size: node.size, + font_quad_vertex_descriptor: &font_quad_vertex_descriptor, }; drawable_text.draw(&mut draw, &mut draw_context).unwrap(); } From 1417b2c2e082d1c161b314fe7d217f433019cd80 Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Thu, 22 Oct 2020 16:07:32 +0200 Subject: [PATCH 22/32] post merge fixes --- crates/bevy_gltf/src/loader.rs | 19 ++++++++++++------- crates/bevy_render/src/lib.rs | 4 ++-- crates/bevy_render/src/mesh/mesh.rs | 5 ++--- .../src/pipeline/pipeline_compiler.rs | 1 - crates/bevy_ui/src/widget/text.rs | 1 - 5 files changed, 16 insertions(+), 14 deletions(-) diff --git a/crates/bevy_gltf/src/loader.rs b/crates/bevy_gltf/src/loader.rs index 60a0983c0b680..ba686d36def0e 100644 --- a/crates/bevy_gltf/src/loader.rs +++ b/crates/bevy_gltf/src/loader.rs @@ -3,6 +3,7 @@ use bevy_asset::{AssetIoError, AssetLoader, AssetPath, LoadContext, LoadedAsset} use bevy_ecs::{bevy_utils::BoxedFuture, World, WorldBuilderSource}; use bevy_math::Mat4; use bevy_pbr::prelude::{PbrComponents, StandardMaterial}; +use bevy_render::mesh::VertexAttributeValues; use bevy_render::{ mesh::{Indices, Mesh}, pipeline::PrimitiveTopology, @@ -16,6 +17,7 @@ use bevy_transform::{ }; use gltf::{mesh::Mode, Primitive}; use image::{GenericImageView, ImageFormat}; +use std::borrow::Cow; use std::path::Path; use thiserror::Error; @@ -78,27 +80,30 @@ async fn load_gltf<'a, 'b>( let reader = primitive.reader(|buffer| Some(&buffer_data[buffer.index()])); let primitive_topology = get_primitive_topology(primitive.mode())?; - let mut mesh = Mesh::new(primitive_topology); + let mut mesh = Mesh::new(primitive_topology, None); if let Some(vertex_attribute) = reader .read_positions() - .map(|v| VertexAttribute::position(v.collect())) + .map(|v| VertexAttributeValues::Float3(v.collect())) { - mesh.attributes.push(vertex_attribute); + mesh.attributes + .insert(Cow::Borrowed(Mesh::ATTRIBUTE_POSITION), vertex_attribute); } if let Some(vertex_attribute) = reader .read_normals() - .map(|v| VertexAttribute::normal(v.collect())) + .map(|v| VertexAttributeValues::Float3(v.collect())) { - mesh.attributes.push(vertex_attribute); + mesh.attributes + .insert(Cow::Borrowed(Mesh::ATTRIBUTE_NORMAL), vertex_attribute); } if let Some(vertex_attribute) = reader .read_tex_coords(0) - .map(|v| VertexAttribute::uv(v.into_f32().collect())) + .map(|v| VertexAttributeValues::Float2(v.into_f32().collect())) { - mesh.attributes.push(vertex_attribute); + mesh.attributes + .insert(Cow::Borrowed(Mesh::ATTRIBUTE_UV_0), vertex_attribute); } if let Some(indices) = reader.read_indices() { diff --git a/crates/bevy_render/src/lib.rs b/crates/bevy_render/src/lib.rs index 1e5d21ef94c46..c96d6416a77fa 100644 --- a/crates/bevy_render/src/lib.rs +++ b/crates/bevy_render/src/lib.rs @@ -28,7 +28,7 @@ pub mod prelude { }; } -use crate::{pipeline::PipelineSpecialization, prelude::*}; +use crate::prelude::*; use base::{MainPass, Msaa}; use bevy_app::prelude::*; use bevy_asset::AddAsset; @@ -38,7 +38,7 @@ use camera::{ }; use pipeline::{ DynamicBinding, IndexFormat, PipelineCompiler, PipelineDescriptor, PipelineSpecialization, - PrimitiveTopology, ShaderSpecialization, VertexBufferDescriptors, + PrimitiveTopology, ShaderSpecialization, }; use render_graph::{ base::{self, BaseRenderGraphBuilder, BaseRenderGraphConfig}, diff --git a/crates/bevy_render/src/mesh/mesh.rs b/crates/bevy_render/src/mesh/mesh.rs index ad948a1b00661..f00a426ed2233 100644 --- a/crates/bevy_render/src/mesh/mesh.rs +++ b/crates/bevy_render/src/mesh/mesh.rs @@ -8,7 +8,6 @@ use bevy_core::AsBytes; use bevy_ecs::{Local, Query, Res, ResMut}; use bevy_math::*; use bevy_type_registry::TypeUuid; -use bevy_utils::HashSet; use std::borrow::Cow; use crate::pipeline::{InputStepMode, VertexAttributeDescriptor, VertexBufferDescriptor}; @@ -434,7 +433,7 @@ fn remove_resource_save( } fn remove_current_mesh_resources( render_resource_context: &dyn RenderResourceContext, - handle: Handle, + handle: &Handle, ) { remove_resource_save(render_resource_context, handle, VERTEX_ATTRIBUTE_BUFFER_ID); remove_resource_save(render_resource_context, handle, VERTEX_FALLBACK_BUFFER_ID); @@ -486,7 +485,7 @@ pub fn mesh_resource_provider_system( ); render_resource_context.set_asset_resource( - *changed_mesh_handle, + changed_mesh_handle, RenderResourceId::Buffer(index_buffer), INDEX_BUFFER_ASSET_INDEX, ); diff --git a/crates/bevy_render/src/pipeline/pipeline_compiler.rs b/crates/bevy_render/src/pipeline/pipeline_compiler.rs index dde81f8775816..e1a46351b7599 100644 --- a/crates/bevy_render/src/pipeline/pipeline_compiler.rs +++ b/crates/bevy_render/src/pipeline/pipeline_compiler.rs @@ -142,7 +142,6 @@ impl PipelineCompiler { pipelines: &mut Assets, shaders: &mut Assets, source_pipeline: &Handle, - vertex_buffer_descriptors: &VertexBufferDescriptors, pipeline_specialization: &PipelineSpecialization, ) -> Handle { let source_descriptor = pipelines.get(source_pipeline).unwrap(); diff --git a/crates/bevy_ui/src/widget/text.rs b/crates/bevy_ui/src/widget/text.rs index 46d74f00f4588..060d0b64c285f 100644 --- a/crates/bevy_ui/src/widget/text.rs +++ b/crates/bevy_ui/src/widget/text.rs @@ -3,7 +3,6 @@ use bevy_asset::{Assets, Handle}; use bevy_ecs::{Changed, Entity, Local, Query, Res, ResMut}; use bevy_math::Size; use bevy_render::mesh::Mesh; -use bevy_render::pipeline::VertexBufferDescriptor; use bevy_render::{ draw::{Draw, DrawContext, Drawable}, prelude::Msaa, From 8fb38745ee01938216f3f1356c53b74dbfc95ac6 Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Thu, 22 Oct 2020 16:09:17 +0200 Subject: [PATCH 23/32] fmt --- crates/bevy_gltf/src/loader.rs | 6 ++---- .../src/renderer/render_resource_context.rs | 14 +++----------- crates/bevy_text/src/draw.rs | 3 +-- crates/bevy_ui/src/widget/text.rs | 2 +- 4 files changed, 7 insertions(+), 18 deletions(-) diff --git a/crates/bevy_gltf/src/loader.rs b/crates/bevy_gltf/src/loader.rs index ba686d36def0e..4826ae23cd748 100644 --- a/crates/bevy_gltf/src/loader.rs +++ b/crates/bevy_gltf/src/loader.rs @@ -3,9 +3,8 @@ use bevy_asset::{AssetIoError, AssetLoader, AssetPath, LoadContext, LoadedAsset} use bevy_ecs::{bevy_utils::BoxedFuture, World, WorldBuilderSource}; use bevy_math::Mat4; use bevy_pbr::prelude::{PbrComponents, StandardMaterial}; -use bevy_render::mesh::VertexAttributeValues; use bevy_render::{ - mesh::{Indices, Mesh}, + mesh::{Indices, Mesh, VertexAttributeValues}, pipeline::PrimitiveTopology, prelude::{Color, Texture}, texture::TextureFormat, @@ -17,8 +16,7 @@ use bevy_transform::{ }; use gltf::{mesh::Mode, Primitive}; use image::{GenericImageView, ImageFormat}; -use std::borrow::Cow; -use std::path::Path; +use std::{borrow::Cow, path::Path}; use thiserror::Error; /// An error that occurs when loading a GLTF file diff --git a/crates/bevy_render/src/renderer/render_resource_context.rs b/crates/bevy_render/src/renderer/render_resource_context.rs index d89b0d76ea976..bcaf0155ade80 100644 --- a/crates/bevy_render/src/renderer/render_resource_context.rs +++ b/crates/bevy_render/src/renderer/render_resource_context.rs @@ -63,22 +63,14 @@ pub trait RenderResourceContext: Downcast + Send + Sync + 'static { } impl dyn RenderResourceContext { - pub fn set_asset_resource( - &self, - handle: &Handle, - resource: RenderResourceId, - index: u64, - ) where + pub fn set_asset_resource(&self, handle: &Handle, resource: RenderResourceId, index: u64) + where T: Asset, { self.set_asset_resource_untyped(handle.clone_weak_untyped(), resource, index); } - pub fn get_asset_resource( - &self, - handle: &Handle, - index: u64, - ) -> Option + pub fn get_asset_resource(&self, handle: &Handle, index: u64) -> Option where T: Asset, { diff --git a/crates/bevy_text/src/draw.rs b/crates/bevy_text/src/draw.rs index 1f9bf4ca1d5ff..3b023f255e94b 100644 --- a/crates/bevy_text/src/draw.rs +++ b/crates/bevy_text/src/draw.rs @@ -2,12 +2,11 @@ use crate::{Font, FontAtlasSet}; use ab_glyph::{Glyph, PxScale, ScaleFont}; use bevy_asset::Assets; use bevy_math::{Mat4, Vec2, Vec3}; -use bevy_render::pipeline::VertexBufferDescriptor; use bevy_render::{ color::Color, draw::{Draw, DrawContext, DrawError, Drawable}, mesh, - pipeline::PipelineSpecialization, + pipeline::{PipelineSpecialization, VertexBufferDescriptor}, prelude::Msaa, renderer::{ AssetRenderResourceBindings, BindGroup, BufferUsage, RenderResourceBindings, diff --git a/crates/bevy_ui/src/widget/text.rs b/crates/bevy_ui/src/widget/text.rs index 060d0b64c285f..a224b782642eb 100644 --- a/crates/bevy_ui/src/widget/text.rs +++ b/crates/bevy_ui/src/widget/text.rs @@ -2,9 +2,9 @@ use crate::{CalculatedSize, Node}; use bevy_asset::{Assets, Handle}; use bevy_ecs::{Changed, Entity, Local, Query, Res, ResMut}; use bevy_math::Size; -use bevy_render::mesh::Mesh; use bevy_render::{ draw::{Draw, DrawContext, Drawable}, + mesh::Mesh, prelude::Msaa, renderer::{AssetRenderResourceBindings, RenderResourceBindings}, texture::Texture, From 01f79c73a31b3d954ad4b9207f7c76f5fe847bcc Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Fri, 23 Oct 2020 00:55:48 +0200 Subject: [PATCH 24/32] Update CHANGELOG.md --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 09163c618bfc6..6bf33e003bcd6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - [Touch Input][696] - [Do not depend on spirv on wasm32 target][689] - [Another fast compile flag for macOS][552] +- [Mesh overhaul with custom vertex attributes][599] ### Changed @@ -15,11 +16,18 @@ - This allows drop-in use of colors from most applications. - New methods `Color::rgb_linear` and `Color::rgba_linear` will accept colors already in linear sRGB (the old behavior) - Individual color-components must now be accessed through setters and getters: `.r`, `.g`, `.b`, `.a`, `.set_r`, `.set_g`, `.set_b`, `.set_a`, and the corresponding methods with the `*_linear` suffix. +- Breaking Change: [Mesh overhaul with custom vertex attributes][616] for `Mesh` + - Any attribute can now be added over `mesh.attributes.insert()`. For example: `mesh.attributes.insert(Cow::Borrowed(Mesh::ATTRIBUTE_POSITION), points.into())`. + - Attributes are matched over their names. For example, the attribute `Vertex_Position` will be bound for the attribute location that has the name `Vertex_Position`. + - For missing attributes (requested by shader, but not defined by mesh), Bevy will provide a zero-filled fallback buffer. + - Removed `VertexAttribute`, `Vertex`, `AsVertexBufferDescriptor`. + - Despawning an entity multiple times causes a debug-level log message to be emitted instead of a panic [649] [651] - Breaking Change: Migrated to rodio 0.12, this means: - Playing an mp3 no longer sometimes panics in debug mode - New method of playing audio can be found in the audio example (an intermediary `Audio` struct is used instead of `AudioOutput` directly) +[599]: https://github.com/bevyengine/bevy/pull/599 [696]: https://github.com/bevyengine/bevy/pull/696 [689]: https://github.com/bevyengine/bevy/pull/689 [552]: https://github.com/bevyengine/bevy/pull/552 From 1b39ca9f3ab147df6c96754ae9d303d74083d7ab Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Fri, 30 Oct 2020 15:44:58 +0100 Subject: [PATCH 25/32] Sort attributes before turning them into bytes. Removed indices from Mesh::new(). Typo fixes. feedback cart --- crates/bevy_gltf/src/loader.rs | 2 +- crates/bevy_render/src/mesh/mesh.rs | 71 +++++++++++-------- .../src/pipeline/pipeline_compiler.rs | 8 +-- .../src/pipeline/vertex_buffer_descriptor.rs | 6 -- .../bevy_render/src/shader/shader_reflect.rs | 6 ++ .../bevy_sprite/src/render/sprite_sheet.vert | 2 +- 6 files changed, 52 insertions(+), 43 deletions(-) diff --git a/crates/bevy_gltf/src/loader.rs b/crates/bevy_gltf/src/loader.rs index 4826ae23cd748..dc62d037450de 100644 --- a/crates/bevy_gltf/src/loader.rs +++ b/crates/bevy_gltf/src/loader.rs @@ -78,7 +78,7 @@ async fn load_gltf<'a, 'b>( let reader = primitive.reader(|buffer| Some(&buffer_data[buffer.index()])); let primitive_topology = get_primitive_topology(primitive.mode())?; - let mut mesh = Mesh::new(primitive_topology, None); + let mut mesh = Mesh::new(primitive_topology); if let Some(vertex_attribute) = reader .read_positions() diff --git a/crates/bevy_render/src/mesh/mesh.rs b/crates/bevy_render/src/mesh/mesh.rs index f00a426ed2233..9aa6df917ce81 100644 --- a/crates/bevy_render/src/mesh/mesh.rs +++ b/crates/bevy_render/src/mesh/mesh.rs @@ -12,6 +12,7 @@ use std::borrow::Cow; use crate::pipeline::{InputStepMode, VertexAttributeDescriptor, VertexBufferDescriptor}; use bevy_utils::HashMap; +use downcast_rs::__alloc::collections::BTreeMap; pub const INDEX_BUFFER_ASSET_INDEX: u64 = 0; pub const VERTEX_ATTRIBUTE_BUFFER_ID: u64 = 10; @@ -59,24 +60,28 @@ impl From<&VertexAttributeValues> for VertexFormat { } } } -impl Into for Vec { - fn into(self) -> VertexAttributeValues { - VertexAttributeValues::Float(self) + +impl From> for VertexAttributeValues { + fn from(vec: Vec) -> Self { + VertexAttributeValues::Float(vec) } } -impl Into for Vec<[f32; 2]> { - fn into(self) -> VertexAttributeValues { - VertexAttributeValues::Float2(self) + +impl From> for VertexAttributeValues { + fn from(vec: Vec<[f32; 2]>) -> Self { + VertexAttributeValues::Float2(vec) } } -impl Into for Vec<[f32; 3]> { - fn into(self) -> VertexAttributeValues { - VertexAttributeValues::Float3(self) + +impl From> for VertexAttributeValues { + fn from(vec: Vec<[f32; 3]>) -> Self { + VertexAttributeValues::Float3(vec) } } -impl Into for Vec<[f32; 4]> { - fn into(self) -> VertexAttributeValues { - VertexAttributeValues::Float4(self) + +impl From> for VertexAttributeValues { + fn from(vec: Vec<[f32; 4]>) -> Self { + VertexAttributeValues::Float4(vec) } } @@ -92,7 +97,7 @@ pub type VertexAttributesHashMap = HashMap, VertexAttributeVal #[uuid = "8ecbac0f-f545-4473-ad43-e1f4243af51e"] pub struct Mesh { pub primitive_topology: PrimitiveTopology, - /// `HashMap` with all defined vertex attributes (Positions, Normals, ...) for this mesh. Attribute name maps to attribute values. + /// `bevy_utils::HashMap` with all defined vertex attributes (Positions, Normals, ...) for this mesh. Attribute name maps to attribute values. pub attributes: VertexAttributesHashMap, pub indices: Option, /// The layout of the attributes in the GPU buffer without `shader_location`. `None` will indicate that no data has been uploaded to the GPU yet. @@ -104,11 +109,11 @@ impl Mesh { pub const ATTRIBUTE_POSITION: &'static str = "Vertex_Position"; pub const ATTRIBUTE_UV_0: &'static str = "Vertex_Uv"; - pub fn new(primitive_topology: PrimitiveTopology, indices: Option) -> Self { + pub fn new(primitive_topology: PrimitiveTopology) -> Self { Mesh { primitive_topology, attributes: Default::default(), - indices, + indices: None, attribute_buffer_descriptor_reference: Default::default(), } } @@ -196,13 +201,14 @@ pub mod shape { 20, 21, 22, 22, 23, 20, // back ]); - let mut mesh = Mesh::new(PrimitiveTopology::TriangleList, Some(indices)); + let mut mesh = Mesh::new(PrimitiveTopology::TriangleList); mesh.attributes .insert(Cow::Borrowed(Mesh::ATTRIBUTE_POSITION), positions.into()); mesh.attributes .insert(Cow::Borrowed(Mesh::ATTRIBUTE_NORMAL), normals.into()); mesh.attributes .insert(Cow::Borrowed(Mesh::ATTRIBUTE_UV_0), uvs.into()); + mesh.indices = Some(indices); mesh } } @@ -294,7 +300,8 @@ pub mod shape { uvs.push(*uv); } - let mut mesh = Mesh::new(PrimitiveTopology::TriangleList, Some(indices)); + let mut mesh = Mesh::new(PrimitiveTopology::TriangleList); + mesh.indices = Some(indices); mesh.attributes .insert(Cow::Borrowed(Mesh::ATTRIBUTE_POSITION), positions.into()); mesh.attributes @@ -334,7 +341,8 @@ pub mod shape { uvs.push(*uv); } - let mut mesh = Mesh::new(PrimitiveTopology::TriangleList, Some(indices)); + let mut mesh = Mesh::new(PrimitiveTopology::TriangleList); + mesh.indices = Some(indices); mesh.attributes .insert(Cow::Borrowed(Mesh::ATTRIBUTE_POSITION), positions.into()); mesh.attributes @@ -407,7 +415,8 @@ pub mod shape { let indices = Indices::U32(indices); - let mut mesh = Mesh::new(PrimitiveTopology::TriangleList, Some(indices)); + let mut mesh = Mesh::new(PrimitiveTopology::TriangleList); + mesh.indices = Some(indices); mesh.attributes .insert(Cow::Borrowed(Mesh::ATTRIBUTE_POSITION), points.into()); mesh.attributes @@ -448,7 +457,7 @@ pub struct MeshResourceProviderState { pub fn mesh_resource_provider_system( mut state: Local, render_resource_context: Res>, - mut meshes: ResMut>, //TODO julian: make res again? + mut meshes: ResMut>, mesh_events: Res>>, mut query: Query<(&Handle, &mut RenderPipelines)>, ) { @@ -561,11 +570,11 @@ pub fn mesh_resource_provider_system( pub fn attributes_count_vertices(attributes: &VertexAttributesHashMap) -> Option { let mut vertex_count: Option = None; - for attribute in attributes { - let attribute_len = attribute.1.len(); + for (attribute_name, attribute_data) in attributes { + let attribute_len = attribute_data.len(); if let Some(previous_vertex_count) = vertex_count { assert_eq!(previous_vertex_count, attribute_len as u32, - "Attribute {} has a different vertex count ({}) than other attributes ({}) in this mesh.", attribute.0, attribute_len, previous_vertex_count); + "Attribute {} has a different vertex count ({}) than other attributes ({}) in this mesh.", attribute_name, attribute_len, previous_vertex_count); } vertex_count = Some(attribute_len as u32); } @@ -576,9 +585,11 @@ pub fn attributes_to_vertex_buffer_data( vertex_count: u32, ) -> (Vec, VertexBufferDescriptor) { // get existing attribute data as bytes and generate attribute descriptor - let mut attributes_gpu_ready = Vec::<(VertexAttributeDescriptor, Vec)>::default(); + let mut attributes_gpu_ready = Vec::<(VertexAttributeDescriptor, &[u8])>::default(); let mut accumulated_offset = 0; - for attribute_data in attributes.iter() { + let mut attributes_as_vec: Vec<_> = attributes.iter().collect(); + attributes_as_vec.sort_by(|a, b| a.0.cmp(b.0)); + for attribute_data in attributes_as_vec { // TODO: allow for custom converter here let vertex_format = VertexFormat::from(attribute_data.1); attributes_gpu_ready.push(( @@ -589,22 +600,20 @@ pub fn attributes_to_vertex_buffer_data( format: vertex_format, shader_location: 0, }, - attribute_data.1.get_bytes().to_vec(), + attribute_data.1.get_bytes(), )); accumulated_offset += vertex_format.get_size(); } - let mut attributes_interleaved_buffer = Vec::::default(); // bundle into interleaved buffers for vertex_index in 0..vertex_count { let vertex_index = vertex_index as usize; - for attribute in &attributes_gpu_ready { - let bytes = &attribute.1; - let stride = bytes.len() / vertex_count as usize; + for (attribute_descriptor, attributes_bytes) in &attributes_gpu_ready { + let stride = attribute_descriptor.format.get_size() as usize; // insert one element attributes_interleaved_buffer - .extend(&bytes[vertex_index * stride..vertex_index * stride + stride]); + .extend(&attributes_bytes[vertex_index * stride..vertex_index * stride + stride]); } } diff --git a/crates/bevy_render/src/pipeline/pipeline_compiler.rs b/crates/bevy_render/src/pipeline/pipeline_compiler.rs index e1a46351b7599..ab2d4af23fa48 100644 --- a/crates/bevy_render/src/pipeline/pipeline_compiler.rs +++ b/crates/bevy_render/src/pipeline/pipeline_compiler.rs @@ -174,7 +174,7 @@ impl PipelineCompiler { let mut mutated_vertex_buffer_descriptor = pipeline_specialization.mesh_attribute_layout.clone(); - let mut fallback_vertex_buffer_descirptor = VertexBufferDescriptor { + let mut fallback_vertex_buffer_descriptor = VertexBufferDescriptor { name: Cow::Borrowed(VERTEX_FALLBACK_LAYOUT_NAME), stride: VertexFormat::Float4.get_size(), //TODO: use smallest possible format ..Default::default() @@ -193,7 +193,7 @@ impl PipelineCompiler { // copy shader location from reflected layout target_vertex_attribute.shader_location = shader_vertex_attribute.shader_location; } else { - fallback_vertex_buffer_descirptor + fallback_vertex_buffer_descriptor .attributes .push(VertexAttributeDescriptor { name: Default::default(), @@ -206,8 +206,8 @@ impl PipelineCompiler { //TODO: add other buffers (like instancing) here let mut vertex_buffer_descriptors = Vec::::default(); vertex_buffer_descriptors.push(mutated_vertex_buffer_descriptor); - if !fallback_vertex_buffer_descirptor.attributes.is_empty() { - vertex_buffer_descriptors.push(fallback_vertex_buffer_descirptor); + if !fallback_vertex_buffer_descriptor.attributes.is_empty() { + vertex_buffer_descriptors.push(fallback_vertex_buffer_descriptor); } pipeline_layout.vertex_buffer_descriptors = vertex_buffer_descriptors; specialized_descriptor.sample_count = pipeline_specialization.sample_count; diff --git a/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs b/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs index 40c3297319c63..96a136fcb97ca 100644 --- a/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs +++ b/crates/bevy_render/src/pipeline/vertex_buffer_descriptor.rs @@ -27,12 +27,6 @@ impl VertexBufferDescriptor { attributes: vec![attribute.clone()], } } - - // just for tests, since a reflected layout doesn't know about the stride - pub fn test_zero_stride(mut self) -> VertexBufferDescriptor { - self.stride = 0; - self - } } #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)] pub enum InputStepMode { diff --git a/crates/bevy_render/src/shader/shader_reflect.rs b/crates/bevy_render/src/shader/shader_reflect.rs index 416bc01a14312..2a35d0fb21b49 100644 --- a/crates/bevy_render/src/shader/shader_reflect.rs +++ b/crates/bevy_render/src/shader/shader_reflect.rs @@ -300,6 +300,12 @@ mod tests { use super::*; use crate::shader::{Shader, ShaderStage}; + impl VertexBufferDescriptor { + pub fn test_zero_stride(mut self) -> VertexBufferDescriptor { + self.stride = 0; + self + } + } #[test] fn test_reflection() { let vertex_shader = Shader::from_glsl( diff --git a/crates/bevy_sprite/src/render/sprite_sheet.vert b/crates/bevy_sprite/src/render/sprite_sheet.vert index 13bf874ec45f0..2491f9438c8bc 100644 --- a/crates/bevy_sprite/src/render/sprite_sheet.vert +++ b/crates/bevy_sprite/src/render/sprite_sheet.vert @@ -38,7 +38,7 @@ layout(set = 2, binding = 1) uniform TextureAtlasSprite { void main() { Rect sprite_rect = Textures[TextureAtlasSprite_index]; vec2 sprite_dimensions = sprite_rect.end - sprite_rect.begin; - vec3 vertex_Position = vec3(Vertex_Position.xy * sprite_dimensions, 0.0); + vec3 vertex_position = vec3(Vertex_Position.xy * sprite_dimensions, 0.0); vec2 atlas_positions[4] = vec2[]( vec2(sprite_rect.begin.x, sprite_rect.end.y), sprite_rect.begin, From 789de512768182a82e8f517a1fcc1df158923592 Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Fri, 30 Oct 2020 19:22:50 +0100 Subject: [PATCH 26/32] Update sprite_sheet.vert --- crates/bevy_sprite/src/render/sprite_sheet.vert | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_sprite/src/render/sprite_sheet.vert b/crates/bevy_sprite/src/render/sprite_sheet.vert index 2491f9438c8bc..d967ac5411ba3 100644 --- a/crates/bevy_sprite/src/render/sprite_sheet.vert +++ b/crates/bevy_sprite/src/render/sprite_sheet.vert @@ -47,5 +47,5 @@ void main() { ); v_Uv = (atlas_positions[gl_VertexIndex] + vec2(0.01, 0.01)) / AtlasSize; v_Color = TextureAtlasSprite_color; - gl_Position = ViewProj * SpriteTransform * vec4(ceil(vertex_Position), 1.0); + gl_Position = ViewProj * SpriteTransform * vec4(ceil(vertex_position), 1.0); } \ No newline at end of file From f759aa6d9e930b90f897026e5bde065fab2370f1 Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Fri, 30 Oct 2020 19:35:58 +0100 Subject: [PATCH 27/32] Update mesh.rs --- crates/bevy_render/src/mesh/mesh.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/bevy_render/src/mesh/mesh.rs b/crates/bevy_render/src/mesh/mesh.rs index 96560613d4b40..5f143207b264e 100644 --- a/crates/bevy_render/src/mesh/mesh.rs +++ b/crates/bevy_render/src/mesh/mesh.rs @@ -12,7 +12,6 @@ use std::borrow::Cow; use crate::pipeline::{InputStepMode, VertexAttributeDescriptor, VertexBufferDescriptor}; use bevy_utils::HashMap; -use downcast_rs::__alloc::collections::BTreeMap; pub const INDEX_BUFFER_ASSET_INDEX: u64 = 0; pub const VERTEX_ATTRIBUTE_BUFFER_ID: u64 = 10; From b766c9a955ac3e8ff0c5d125f8070d0df22924e4 Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Sat, 31 Oct 2020 02:27:20 +0100 Subject: [PATCH 28/32] fixed a bug related to more attributes defined by mesh than used by shader --- crates/bevy_render/src/mesh/mesh.rs | 6 ++-- .../src/pipeline/pipeline_compiler.rs | 29 ++++++++++++++----- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/crates/bevy_render/src/mesh/mesh.rs b/crates/bevy_render/src/mesh/mesh.rs index 5f143207b264e..6dfbea9bd8d69 100644 --- a/crates/bevy_render/src/mesh/mesh.rs +++ b/crates/bevy_render/src/mesh/mesh.rs @@ -586,9 +586,9 @@ pub fn attributes_to_vertex_buffer_data( // get existing attribute data as bytes and generate attribute descriptor let mut attributes_gpu_ready = Vec::<(VertexAttributeDescriptor, &[u8])>::default(); let mut accumulated_offset = 0; - let mut attributes_as_vec: Vec<_> = attributes.iter().collect(); - attributes_as_vec.sort_by(|a, b| a.0.cmp(b.0)); - for attribute_data in attributes_as_vec { + let mut attributes_sorted: Vec<_> = attributes.iter().collect(); + attributes_sorted.sort_by(|a, b| a.0.cmp(b.0)); + for attribute_data in attributes_sorted { // TODO: allow for custom converter here let vertex_format = VertexFormat::from(attribute_data.1); attributes_gpu_ready.push(( diff --git a/crates/bevy_render/src/pipeline/pipeline_compiler.rs b/crates/bevy_render/src/pipeline/pipeline_compiler.rs index ab2d4af23fa48..a221497c516a4 100644 --- a/crates/bevy_render/src/pipeline/pipeline_compiler.rs +++ b/crates/bevy_render/src/pipeline/pipeline_compiler.rs @@ -1,4 +1,5 @@ use super::{state_descriptors::PrimitiveTopology, IndexFormat, PipelineDescriptor}; +use crate::pipeline::InputStepMode; use crate::{ pipeline::{ VertexAttributeDescriptor, VertexBufferDescriptor, VertexFormat, @@ -171,41 +172,53 @@ impl PipelineCompiler { // create a vertex layout that provides all attributes from either the specialized vertex buffers or a zero buffer let mut pipeline_layout = specialized_descriptor.layout.as_mut().unwrap(); - let mut mutated_vertex_buffer_descriptor = - pipeline_specialization.mesh_attribute_layout.clone(); + // the vertex buffer descriptor of the mesh + let mesh_vertex_buffer_descriptor = pipeline_specialization.mesh_attribute_layout.clone(); + + // the vertex buffer descriptor that will be used for this pipeline + let mut compiled_vertex_buffer_descriptor = VertexBufferDescriptor { + step_mode: InputStepMode::Vertex, + stride: mesh_vertex_buffer_descriptor.stride, + ..Default::default() + }; let mut fallback_vertex_buffer_descriptor = VertexBufferDescriptor { name: Cow::Borrowed(VERTEX_FALLBACK_LAYOUT_NAME), stride: VertexFormat::Float4.get_size(), //TODO: use smallest possible format ..Default::default() }; - for shader_vertex_attribute in &mut pipeline_layout.vertex_buffer_descriptors.iter_mut() { + for shader_vertex_attribute in pipeline_layout.vertex_buffer_descriptors.iter() { let shader_vertex_attribute = shader_vertex_attribute .attributes .get(0) .expect("Reflected layout has no attributes."); - if let Some(target_vertex_attribute) = mutated_vertex_buffer_descriptor + if let Some(target_vertex_attribute) = mesh_vertex_buffer_descriptor .attributes - .iter_mut() + .iter() .find(|x| x.name == shader_vertex_attribute.name) { // copy shader location from reflected layout - target_vertex_attribute.shader_location = shader_vertex_attribute.shader_location; + let mut compiled_vertex_attribute = target_vertex_attribute.clone(); + compiled_vertex_attribute.shader_location = shader_vertex_attribute.shader_location; + compiled_vertex_buffer_descriptor + .attributes + .push(compiled_vertex_attribute); } else { fallback_vertex_buffer_descriptor .attributes .push(VertexAttributeDescriptor { name: Default::default(), offset: 0, - format: shader_vertex_attribute.format, //TODO julian: use smallest possible format to minimalize bandwidth + format: shader_vertex_attribute.format, //TODO: use smallest possible format shader_location: shader_vertex_attribute.shader_location, }); } } + //TODO: add other buffers (like instancing) here let mut vertex_buffer_descriptors = Vec::::default(); - vertex_buffer_descriptors.push(mutated_vertex_buffer_descriptor); + vertex_buffer_descriptors.push(compiled_vertex_buffer_descriptor); if !fallback_vertex_buffer_descriptor.attributes.is_empty() { vertex_buffer_descriptors.push(fallback_vertex_buffer_descriptor); } From 223f5a22dcbd7e260d0a94431e86fc101b5b9292 Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Sat, 31 Oct 2020 02:36:40 +0100 Subject: [PATCH 29/32] format --- crates/bevy_ecs/hecs/src/query.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bevy_ecs/hecs/src/query.rs b/crates/bevy_ecs/hecs/src/query.rs index 5486c1d23d8a2..18c4835a28234 100644 --- a/crates/bevy_ecs/hecs/src/query.rs +++ b/crates/bevy_ecs/hecs/src/query.rs @@ -625,8 +625,8 @@ pub struct QueryIter<'w, Q: Query> { } impl<'w, Q: Query> QueryIter<'w, Q> { - // #[allow(clippy::declare_interior_mutable_const)] // no trait bounds on const fns - // const EMPTY: Q::Fetch = Q::Fetch::DANGLING; + #[allow(clippy::declare_interior_mutable_const)] // no trait bounds on const fns + // const EMPTY: Q::Fetch = Q::Fetch::DANGLING; const EMPTY: ChunkInfo = ChunkInfo { fetch: Q::Fetch::DANGLING, len: 0, From 5a4d6e2378e81b8b817362fb857607b7de48356e Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Sat, 31 Oct 2020 02:37:29 +0100 Subject: [PATCH 30/32] Revert "format" This reverts commit 223f5a22dcbd7e260d0a94431e86fc101b5b9292. --- crates/bevy_ecs/hecs/src/query.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bevy_ecs/hecs/src/query.rs b/crates/bevy_ecs/hecs/src/query.rs index 18c4835a28234..5486c1d23d8a2 100644 --- a/crates/bevy_ecs/hecs/src/query.rs +++ b/crates/bevy_ecs/hecs/src/query.rs @@ -625,8 +625,8 @@ pub struct QueryIter<'w, Q: Query> { } impl<'w, Q: Query> QueryIter<'w, Q> { - #[allow(clippy::declare_interior_mutable_const)] // no trait bounds on const fns - // const EMPTY: Q::Fetch = Q::Fetch::DANGLING; + // #[allow(clippy::declare_interior_mutable_const)] // no trait bounds on const fns + // const EMPTY: Q::Fetch = Q::Fetch::DANGLING; const EMPTY: ChunkInfo = ChunkInfo { fetch: Q::Fetch::DANGLING, len: 0, From 87fde6d6c62f27f0ff67e3238be79716e3b8264a Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Sat, 31 Oct 2020 02:56:26 +0100 Subject: [PATCH 31/32] Update pipeline_compiler.rs --- crates/bevy_render/src/pipeline/pipeline_compiler.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/bevy_render/src/pipeline/pipeline_compiler.rs b/crates/bevy_render/src/pipeline/pipeline_compiler.rs index a221497c516a4..5e51ca77d91bb 100644 --- a/crates/bevy_render/src/pipeline/pipeline_compiler.rs +++ b/crates/bevy_render/src/pipeline/pipeline_compiler.rs @@ -1,8 +1,7 @@ use super::{state_descriptors::PrimitiveTopology, IndexFormat, PipelineDescriptor}; -use crate::pipeline::InputStepMode; use crate::{ pipeline::{ - VertexAttributeDescriptor, VertexBufferDescriptor, VertexFormat, + VertexAttributeDescriptor, InputStepMode, VertexBufferDescriptor, VertexFormat, VERTEX_FALLBACK_LAYOUT_NAME, }, renderer::RenderResourceContext, From e665298493d6ae5c0beba0c446015bedc0ebfa5c Mon Sep 17 00:00:00 2001 From: Julian Heinken Date: Sat, 31 Oct 2020 02:58:15 +0100 Subject: [PATCH 32/32] Update pipeline_compiler.rs --- crates/bevy_render/src/pipeline/pipeline_compiler.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_render/src/pipeline/pipeline_compiler.rs b/crates/bevy_render/src/pipeline/pipeline_compiler.rs index 5e51ca77d91bb..6c1378711ac09 100644 --- a/crates/bevy_render/src/pipeline/pipeline_compiler.rs +++ b/crates/bevy_render/src/pipeline/pipeline_compiler.rs @@ -1,7 +1,7 @@ use super::{state_descriptors::PrimitiveTopology, IndexFormat, PipelineDescriptor}; use crate::{ pipeline::{ - VertexAttributeDescriptor, InputStepMode, VertexBufferDescriptor, VertexFormat, + InputStepMode, VertexAttributeDescriptor, VertexBufferDescriptor, VertexFormat, VERTEX_FALLBACK_LAYOUT_NAME, }, renderer::RenderResourceContext,