toggle-able "bevy conventions" in shaders

This commit is contained in:
Carter Anderson 2020-05-07 19:09:25 -07:00
parent 3d65a0d236
commit 5e5df2bb87
4 changed files with 28 additions and 19 deletions

View File

@ -135,6 +135,9 @@ impl PipelineDescriptor {
/// Reflects the pipeline layout from its shaders. /// Reflects the pipeline layout from its shaders.
/// ///
/// If `bevy_conventions` is true, it will be assumed that the shader follows "bevy shader conventions". These allow
/// richer reflection, such as inferred Vertex Buffer names and inferred instancing.
///
/// If `vertex_buffer_descriptors` is set, the pipeline's vertex buffers /// If `vertex_buffer_descriptors` is set, the pipeline's vertex buffers
/// will inherit their layouts from global descriptors, otherwise the layout will be assumed to be complete / local. /// will inherit their layouts from global descriptors, otherwise the layout will be assumed to be complete / local.
/// ///
@ -143,6 +146,7 @@ impl PipelineDescriptor {
pub fn reflect_layout( pub fn reflect_layout(
&mut self, &mut self,
shaders: &AssetStorage<Shader>, shaders: &AssetStorage<Shader>,
bevy_conventions: bool,
vertex_buffer_descriptors: Option<&VertexBufferDescriptors>, vertex_buffer_descriptors: Option<&VertexBufferDescriptors>,
dynamic_uniform_lookup: Option<(&RenderResourceAssignments, &dyn RenderResourceContext)>, dynamic_uniform_lookup: Option<(&RenderResourceAssignments, &dyn RenderResourceContext)>,
) { ) {
@ -153,9 +157,9 @@ impl PipelineDescriptor {
.as_ref() .as_ref()
.map(|handle| shaders.get(&handle).unwrap()); .map(|handle| shaders.get(&handle).unwrap());
let mut layouts = vec![vertex_spirv.reflect_layout().unwrap()]; let mut layouts = vec![vertex_spirv.reflect_layout(bevy_conventions).unwrap()];
if let Some(ref fragment_spirv) = fragment_spirv { if let Some(ref fragment_spirv) = fragment_spirv {
layouts.push(fragment_spirv.reflect_layout().unwrap()); layouts.push(fragment_spirv.reflect_layout(bevy_conventions).unwrap());
} }
let mut layout = PipelineLayout::from_shader_layouts(&mut layouts); let mut layout = PipelineLayout::from_shader_layouts(&mut layouts);

View File

@ -113,6 +113,7 @@ impl PipelineCompiler {
compiled_pipeline_descriptor.reflect_layout( compiled_pipeline_descriptor.reflect_layout(
shaders, shaders,
true,
Some(vertex_buffer_descriptors), Some(vertex_buffer_descriptors),
Some((render_resource_assignments, render_resource_context)), Some((render_resource_assignments, render_resource_context)),
); );

View File

@ -88,9 +88,9 @@ impl Shader {
} }
} }
pub fn reflect_layout(&self) -> Option<ShaderLayout> { pub fn reflect_layout(&self, enforce_bevy_conventions: bool) -> Option<ShaderLayout> {
if let ShaderSource::Spirv(ref spirv) = self.source { if let ShaderSource::Spirv(ref spirv) = self.source {
Some(ShaderLayout::from_spirv(spirv.as_slice())) Some(ShaderLayout::from_spirv(spirv.as_slice(), enforce_bevy_conventions))
} else { } else {
panic!("Cannot reflect layout of non-SpirV shader. Try compiling this shader to SpirV first using self.get_spirv_shader()"); panic!("Cannot reflect layout of non-SpirV shader. Try compiling this shader to SpirV first using self.get_spirv_shader()");
} }

View File

@ -36,7 +36,7 @@ pub struct ShaderLayout {
} }
impl ShaderLayout { impl ShaderLayout {
pub fn from_spirv(spirv_data: &[u32]) -> ShaderLayout { pub fn from_spirv(spirv_data: &[u32], bevy_conventions: bool) -> ShaderLayout {
match ShaderModule::load_u8_data(spirv_data.as_bytes()) { match ShaderModule::load_u8_data(spirv_data.as_bytes()) {
Ok(ref mut module) => { Ok(ref mut module) => {
let entry_point_name = module.get_entry_point_name(); let entry_point_name = module.get_entry_point_name();
@ -62,21 +62,25 @@ impl ShaderLayout {
for vertex_attribute_descriptor in vertex_attribute_descriptors.drain(..) { for vertex_attribute_descriptor in vertex_attribute_descriptors.drain(..) {
let mut instance = false; let mut instance = false;
let current_buffer_name = { let current_buffer_name = {
let parts = vertex_attribute_descriptor if bevy_conventions {
.name let parts = vertex_attribute_descriptor
.splitn(3, "_") .name
.collect::<Vec<&str>>(); .splitn(3, "_")
if parts.len() == 3 { .collect::<Vec<&str>>();
if parts[0] == "I" { if parts.len() == 3 {
instance = true; if parts[0] == "I" {
parts[1].to_string() instance = true;
} else { parts[1].to_string()
} else {
parts[0].to_string()
}
} else if parts.len() == 2 {
parts[0].to_string() parts[0].to_string()
} else {
panic!("Vertex attributes must follow the form BUFFERNAME_PROPERTYNAME. For example: Vertex_Position");
} }
} else if parts.len() == 2 {
parts[0].to_string()
} else { } else {
panic!("Vertex attributes must follow the form BUFFERNAME_PROPERTYNAME. For example: Vertex_Position"); "DefaultVertex".to_string()
} }
}; };
@ -360,7 +364,7 @@ mod tests {
) )
.get_spirv_shader(None); .get_spirv_shader(None);
let layout = vertex_shader.reflect_layout().unwrap(); let layout = vertex_shader.reflect_layout(true).unwrap();
assert_eq!( assert_eq!(
layout, layout,
ShaderLayout { ShaderLayout {
@ -459,6 +463,6 @@ mod tests {
) )
.get_spirv_shader(None); .get_spirv_shader(None);
let _layout = vertex_shader.reflect_layout().unwrap(); let _layout = vertex_shader.reflect_layout(true).unwrap();
} }
} }