validate VertexBufferDescriptors and fill in blanks when possible

This commit is contained in:
Carter Anderson 2020-03-21 21:10:58 -07:00
parent a4eed18800
commit fb496a6172
9 changed files with 103 additions and 29 deletions

View File

@ -9,7 +9,6 @@ Here is the current list of planned features. All items are sorted in approximat
* Textures * Textures
* Physically based rendering * Physically based rendering
* Skeletal animation * Skeletal animation
* Macro to produce vertex buffer attributes (and maybe descriptors) from structs
* Add runtime type safety to uniform bindings (and maybe compile time) * Add runtime type safety to uniform bindings (and maybe compile time)
* Inject layout set/bindings into shader source so they don't need to be defined in-shader. Specify set / binding indices in resource providers? * Inject layout set/bindings into shader source so they don't need to be defined in-shader. Specify set / binding indices in resource providers?
* Pull as much logic as possible from wgpu_renderer into a "render orchestrator" struct/trait * Pull as much logic as possible from wgpu_renderer into a "render orchestrator" struct/trait

View File

@ -334,9 +334,13 @@ pub fn derive_uniforms(input: TokenStream) -> TokenStream {
} }
fn get_vertex_buffer_descriptor() -> Option<&'static bevy::render::pipeline::VertexBufferDescriptor> { fn get_vertex_buffer_descriptor() -> Option<&'static bevy::render::pipeline::VertexBufferDescriptor> {
if #vertex_buffer_descriptor_ident.attributes.len() == 0 {
None
} else {
Some(&#vertex_buffer_descriptor_ident) Some(&#vertex_buffer_descriptor_ident)
} }
} }
}
}) })
} }

View File

@ -26,8 +26,6 @@ fn main() {
r#" r#"
#version 450 #version 450
layout(location = 0) in vec4 Vertex_Position; layout(location = 0) in vec4 Vertex_Position;
layout(location = 1) in vec4 Vertex_Normal;
layout(location = 2) in vec2 Vertex_Uv;
layout(location = 0) out vec4 v_Position; layout(location = 0) out vec4 v_Position;
layout(set = 0, binding = 0) uniform Camera { layout(set = 0, binding = 0) uniform Camera {
mat4 ViewProj; mat4 ViewProj;

View File

@ -6,6 +6,15 @@ pub trait GetBytes {
fn get_bytes_ref(&self) -> Option<&[u8]>; fn get_bytes_ref(&self) -> Option<&[u8]>;
} }
impl GetBytes for f32 {
fn get_bytes(&self) -> Vec<u8> {
self.as_bytes().to_vec()
}
fn get_bytes_ref(&self) -> Option<&[u8]> {
Some(self.as_bytes())
}
}
impl GetBytes for [f32; 2] { impl GetBytes for [f32; 2] {
fn get_bytes(&self) -> Vec<u8> { fn get_bytes(&self) -> Vec<u8> {
self.as_bytes().to_vec() self.as_bytes().to_vec()

View File

@ -8,6 +8,26 @@ pub struct VertexBufferDescriptor {
pub attributes: Vec<VertexAttributeDescriptor>, pub attributes: Vec<VertexAttributeDescriptor>,
} }
impl VertexBufferDescriptor {
pub fn sync_with_descriptor(&mut self, descriptor: &VertexBufferDescriptor) {
for attribute in self.attributes.iter_mut() {
let descriptor_attribute = descriptor
.attributes
.iter()
.find(|a| a.name == attribute.name)
.unwrap_or_else(|| {
panic!(
"Encountered unsupported Vertex Buffer Attribute: {}",
attribute.name
);
});
attribute.offset = descriptor_attribute.offset;
}
self.stride = descriptor.stride;
}
}
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
pub enum InputStepMode { pub enum InputStepMode {
Vertex = 0, Vertex = 0,

View File

@ -3,8 +3,11 @@ use crate::{
prelude::Renderable, prelude::Renderable,
render::{ render::{
mesh::Mesh, mesh::Mesh,
render_graph::RenderGraph,
render_resource::{AssetBatchers, BufferInfo, BufferUsage, ResourceProvider}, render_resource::{AssetBatchers, BufferInfo, BufferUsage, ResourceProvider},
renderer::Renderer, renderer::Renderer,
shader::AsUniforms,
Vertex,
}, },
}; };
use legion::{filter::*, prelude::*}; use legion::{filter::*, prelude::*};
@ -39,6 +42,16 @@ impl MeshResourceProvider {
} }
impl ResourceProvider for MeshResourceProvider { impl ResourceProvider for MeshResourceProvider {
fn initialize(
&mut self,
_renderer: &mut dyn Renderer,
_world: &mut World,
resources: &Resources,
) {
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
render_graph.set_vertex_buffer_descriptor(Vertex::get_vertex_buffer_descriptor().cloned().unwrap());
}
fn update(&mut self, renderer: &mut dyn Renderer, world: &mut World, resources: &Resources) { fn update(&mut self, renderer: &mut dyn Renderer, world: &mut World, resources: &Resources) {
let mesh_storage = resources.get_mut::<AssetStorage<Mesh>>().unwrap(); let mesh_storage = resources.get_mut::<AssetStorage<Mesh>>().unwrap();
let mut asset_batchers = resources.get_mut::<AssetBatchers>().unwrap(); let mut asset_batchers = resources.get_mut::<AssetBatchers>().unwrap();

View File

@ -1,24 +1,32 @@
use crate as bevy;
use crate::{ use crate::{
ecs, ecs,
prelude::Node, prelude::Node,
render::{ render::{
render_graph::RenderGraph,
render_resource::{ render_resource::{
resource_name, BufferArrayInfo, BufferInfo, BufferUsage, RenderResource, resource_name, BufferArrayInfo, BufferInfo, BufferUsage, RenderResource,
ResourceProvider, ResourceProvider,
}, },
renderer::Renderer, renderer::Renderer,
shader::AsUniforms,
}, },
}; };
use bevy_derive::Uniforms;
use bevy_transform::prelude::Parent; use bevy_transform::prelude::Parent;
use legion::prelude::*; use legion::prelude::*;
use zerocopy::{AsBytes, FromBytes}; use zerocopy::{AsBytes, FromBytes};
#[repr(C)] #[repr(C)]
#[derive(Clone, Copy, Debug, AsBytes, FromBytes)] #[derive(Clone, Copy, Debug, AsBytes, FromBytes, Uniforms)]
pub struct RectData { pub struct Rect {
#[uniform(instance)]
pub position: [f32; 2], pub position: [f32; 2],
#[uniform(instance)]
pub size: [f32; 2], pub size: [f32; 2],
#[uniform(instance)]
pub color: [f32; 4], pub color: [f32; 4],
#[uniform(instance)]
pub z_index: f32, pub z_index: f32,
} }
@ -44,7 +52,7 @@ impl UiResourceProvider {
let mut add_data: Box<dyn FnMut(&World, Entity, ()) -> Option<()>> = let mut add_data: Box<dyn FnMut(&World, Entity, ()) -> Option<()>> =
Box::new(|world, entity, _| { Box::new(|world, entity, _| {
let node = world.get_component::<Node>(entity).unwrap(); let node = world.get_component::<Node>(entity).unwrap();
data.push(RectData { data.push(Rect {
position: node.global_position.into(), position: node.global_position.into(),
size: node.size.into(), size: node.size.into(),
color: node.color.into(), color: node.color.into(),
@ -69,7 +77,7 @@ impl UiResourceProvider {
return; return;
} }
let size = std::mem::size_of::<RectData>() as u64; let size = std::mem::size_of::<Rect>() as u64;
let data_len = data.len() as u64; let data_len = data.len() as u64;
if let Some(old_instance_buffer) = self.instance_buffer { if let Some(old_instance_buffer) = self.instance_buffer {
@ -102,8 +110,10 @@ impl ResourceProvider for UiResourceProvider {
&mut self, &mut self,
_renderer: &mut dyn Renderer, _renderer: &mut dyn Renderer,
_world: &mut World, _world: &mut World,
_resources: &Resources, resources: &Resources,
) { ) {
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
render_graph.set_vertex_buffer_descriptor(Rect::get_vertex_buffer_descriptor().cloned().unwrap());
} }
fn update(&mut self, renderer: &mut dyn Renderer, world: &mut World, _resources: &Resources) { fn update(&mut self, renderer: &mut dyn Renderer, world: &mut World, _resources: &Resources) {

View File

@ -444,7 +444,6 @@ where
if let Some(vertex_buffer_descriptor) = vertex_buffer_descriptor { if let Some(vertex_buffer_descriptor) = vertex_buffer_descriptor {
if let None = render_graph.get_vertex_buffer_descriptor(&vertex_buffer_descriptor.name) if let None = render_graph.get_vertex_buffer_descriptor(&vertex_buffer_descriptor.name)
{ {
println!("{:#?}", vertex_buffer_descriptor);
render_graph.set_vertex_buffer_descriptor(vertex_buffer_descriptor.clone()); render_graph.set_vertex_buffer_descriptor(vertex_buffer_descriptor.clone());
} }
} }
@ -461,13 +460,12 @@ where
world: &mut World, world: &mut World,
resources: &Resources, resources: &Resources,
) { ) {
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
self.initialize_vertex_buffer_descriptor(&mut render_graph);
self.update(renderer, world, resources); self.update(renderer, world, resources);
} }
fn update(&mut self, renderer: &mut dyn Renderer, world: &mut World, resources: &Resources) { fn update(&mut self, renderer: &mut dyn Renderer, world: &mut World, resources: &Resources) {
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
self.initialize_vertex_buffer_descriptor(&mut render_graph);
// TODO: this breaks down in multiple ways: // TODO: this breaks down in multiple ways:
// (SOLVED 1) resource_info will be set after the first run so this won't update. // (SOLVED 1) resource_info will be set after the first run so this won't update.
// (2) if we create new buffers, the old bind groups will be invalid // (2) if we create new buffers, the old bind groups will be invalid

View File

@ -67,10 +67,46 @@ impl WgpuRenderer {
} }
} }
pub fn setup_vertex_buffer_descriptors(
render_graph: &RenderGraph,
vertex_spirv: &Shader,
pipeline_descriptor: &PipelineDescriptor,
) -> Vec<OwnedWgpuVertexBufferDescriptor> {
let mut reflected_vertex_layout = if pipeline_descriptor.reflect_vertex_buffer_descriptors {
Some(vertex_spirv.reflect_layout().unwrap())
} else {
None
};
let vertex_buffer_descriptors = if let Some(ref mut layout) = reflected_vertex_layout {
for vertex_buffer_descriptor in layout.vertex_buffer_descriptors.iter_mut() {
if let Some(graph_descriptor) =
render_graph.get_vertex_buffer_descriptor(&vertex_buffer_descriptor.name)
{
vertex_buffer_descriptor.sync_with_descriptor(graph_descriptor);
} else {
panic!(
"Encountered unsupported Vertex Buffer: {}",
vertex_buffer_descriptor.name
);
}
}
&layout.vertex_buffer_descriptors
} else {
&pipeline_descriptor.vertex_buffer_descriptors
};
vertex_buffer_descriptors
.iter()
.map(|v| v.into())
.collect::<Vec<OwnedWgpuVertexBufferDescriptor>>()
}
pub fn create_render_pipeline( pub fn create_render_pipeline(
wgpu_resources: &mut WgpuResources, wgpu_resources: &mut WgpuResources,
pipeline_descriptor: &mut PipelineDescriptor, pipeline_descriptor: &mut PipelineDescriptor,
device: &wgpu::Device, device: &wgpu::Device,
render_graph: &RenderGraph,
vertex_shader: &Shader, vertex_shader: &Shader,
fragment_shader: Option<&Shader>, fragment_shader: Option<&Shader>,
) -> wgpu::RenderPipeline { ) -> wgpu::RenderPipeline {
@ -166,22 +202,8 @@ impl WgpuRenderer {
bind_group_layouts: bind_group_layouts.as_slice(), bind_group_layouts: bind_group_layouts.as_slice(),
}); });
let reflected_vertex_layout = if pipeline_descriptor.reflect_vertex_buffer_descriptors { let owned_vertex_buffer_descriptors =
Some(vertex_spirv.reflect_layout().unwrap()) Self::setup_vertex_buffer_descriptors(render_graph, &vertex_spirv, pipeline_descriptor);
} else {
None
};
let vertex_buffer_descriptors = if let Some(ref layout) = reflected_vertex_layout {
&layout.vertex_buffer_descriptors
} else {
&pipeline_descriptor.vertex_buffer_descriptors
};
let owned_vertex_buffer_descriptors = vertex_buffer_descriptors
.iter()
.map(|v| v.into())
.collect::<Vec<OwnedWgpuVertexBufferDescriptor>>();
let color_states = pipeline_descriptor let color_states = pipeline_descriptor
.color_states .color_states
@ -462,6 +484,7 @@ impl Renderer for WgpuRenderer {
&mut self.wgpu_resources, &mut self.wgpu_resources,
pipeline_descriptor, pipeline_descriptor,
&self.device, &self.device,
&render_graph,
vertex_shader, vertex_shader,
fragment_shader, fragment_shader,
); );