mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-25 00:04:15 +00:00
Write structure definitions in the shader analyser
This commit is contained in:
parent
f6bdc2478f
commit
85ded76ead
@ -14,6 +14,7 @@ pub use glsl_to_spirv::ShaderType;
|
||||
|
||||
mod enums;
|
||||
mod parse;
|
||||
mod structs;
|
||||
|
||||
pub fn build_glsl_shaders<'a, I>(shaders: I)
|
||||
where I: IntoIterator<Item = (&'a str, ShaderType)>
|
||||
@ -121,6 +122,9 @@ impl {name} {{
|
||||
}}
|
||||
"#));
|
||||
|
||||
// struct definitions
|
||||
output.push_str(&structs::write_structs(&doc));
|
||||
|
||||
// descriptor sets
|
||||
output.push_str(&write_descriptor_sets(&doc));
|
||||
}
|
||||
@ -501,6 +505,11 @@ fn type_from_id(doc: &parse::Spirv, searched: u32) -> String {
|
||||
let t = type_from_id(doc, component_id);
|
||||
return format!("[{}; {}]", t, count);
|
||||
},
|
||||
&parse::Instruction::TypeMatrix { result_id, column_type_id, column_count } if result_id == searched => {
|
||||
// FIXME: row-major or column-major
|
||||
let t = type_from_id(doc, column_type_id);
|
||||
return format!("[{}; {}]", t, column_count);
|
||||
},
|
||||
&parse::Instruction::TypeImage { result_id, sampled_type_id, ref dim, depth, arrayed, ms, sampled, ref format, ref access } if result_id == searched => {
|
||||
return format!("{}{}Texture{:?}{}{:?}",
|
||||
if ms { "Multisample" } else { "" },
|
||||
|
83
vulkano-shaders/src/structs.rs
Normal file
83
vulkano-shaders/src/structs.rs
Normal file
@ -0,0 +1,83 @@
|
||||
use parse;
|
||||
use enums;
|
||||
|
||||
/// Translates all the structs that are contained in the SPIR-V document as Rust structs.
|
||||
pub fn write_structs(doc: &parse::Spirv) -> String {
|
||||
let mut result = String::new();
|
||||
|
||||
for instruction in &doc.instructions {
|
||||
match *instruction {
|
||||
parse::Instruction::TypeStruct { result_id, ref member_types } => {
|
||||
result.push_str(&write_struct(doc, result_id, member_types));
|
||||
result.push_str("\n");
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
/// Writes a single struct.
|
||||
fn write_struct(doc: &parse::Spirv, struct_id: u32, members: &[u32]) -> String {
|
||||
let name = ::name_from_id(doc, struct_id);
|
||||
|
||||
let mut members_defs = Vec::with_capacity(members.len());
|
||||
|
||||
for (num, &member) in members.iter().enumerate() {
|
||||
let ty = ::type_from_id(doc, member);
|
||||
let member_name = ::member_name_from_id(doc, struct_id, num as u32);
|
||||
|
||||
// Ignore the field if it is built in, which includes `gl_Position` for example.
|
||||
if is_builtin_member(doc, struct_id, num as u32) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let offset = doc.instructions.iter().filter_map(|i| {
|
||||
match *i {
|
||||
parse::Instruction::MemberDecorate { target_id, member,
|
||||
decoration: enums::Decoration::DecorationOffset,
|
||||
ref params } if target_id == struct_id &&
|
||||
member as usize == num =>
|
||||
{
|
||||
return Some(params[0]);
|
||||
},
|
||||
_ => ()
|
||||
};
|
||||
|
||||
None
|
||||
}).next().expect(&format!("Struct member `{}` of `{}` is missing an `Offset` decoration",
|
||||
member_name, name));
|
||||
|
||||
members_defs.push(format!("{name}: {ty} /* {off} */", name = member_name, ty = ty, off = offset));
|
||||
}
|
||||
|
||||
// GLSL doesn't allow empty structures. However it is possible to have structures entirely
|
||||
// made of built-in members, hence this check.
|
||||
if !members_defs.is_empty() {
|
||||
format!("#[repr(C)]\n#[derive(Copy, Clone, Debug, Default)]\n\
|
||||
pub struct {name} {{\n\t{members}\n}}\n",
|
||||
name = name, members = members_defs.join(",\n\t"))
|
||||
} else {
|
||||
String::new()
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if a `BuiltIn` decorator is applied on a struct member.
|
||||
fn is_builtin_member(doc: &parse::Spirv, id: u32, member_id: u32) -> bool {
|
||||
let mut result = String::new();
|
||||
|
||||
for instruction in &doc.instructions {
|
||||
match *instruction {
|
||||
parse::Instruction::MemberDecorate { target_id, member,
|
||||
decoration: enums::Decoration::DecorationBuiltIn,
|
||||
.. } if target_id == id && member == member_id =>
|
||||
{
|
||||
return true;
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
Loading…
Reference in New Issue
Block a user