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