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