mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2025-02-16 09:02:25 +00:00
Generate attributes description struct for all shader stages
This commit is contained in:
parent
ad27205f7b
commit
e2fc113711
@ -12,7 +12,7 @@
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
#extension GL_ARB_shading_language_420pack : enable
|
||||
|
||||
in vec2 tex_coords;
|
||||
layout(location = 0) in vec2 tex_coords;
|
||||
layout(location = 0) out vec4 f_color;
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D tex;
|
||||
|
@ -13,7 +13,7 @@
|
||||
#extension GL_ARB_shading_language_420pack : enable
|
||||
|
||||
layout(location = 0) in vec2 position;
|
||||
out vec2 tex_coords;
|
||||
layout(location = 0) out vec2 tex_coords;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(position, 0.0, 1.0);
|
||||
|
@ -12,7 +12,7 @@
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
#extension GL_ARB_shading_language_420pack : enable
|
||||
|
||||
in vec3 v_normal;
|
||||
layout(location = 0) in vec3 v_normal;
|
||||
layout(location = 0) out vec4 f_color;
|
||||
|
||||
const vec3 LIGHT = vec3(0.0, 0.0, 1.0);
|
||||
|
@ -15,7 +15,7 @@
|
||||
layout(location = 0) in vec3 position;
|
||||
layout(location = 1) in vec3 normal;
|
||||
|
||||
out vec3 v_normal;
|
||||
layout(location = 0) out vec3 v_normal;
|
||||
|
||||
layout(set = 0, binding = 0) uniform Data {
|
||||
mat4 worldview;
|
||||
|
@ -16,7 +16,7 @@ use location_decoration;
|
||||
use type_from_id;
|
||||
use format_from_id;
|
||||
|
||||
pub fn write_entry_point(doc: &parse::Spirv, instruction: &parse::Instruction) -> String {
|
||||
pub fn write_entry_point(doc: &parse::Spirv, instruction: &parse::Instruction) -> (String, String) {
|
||||
let (execution, ep_name, interface) = match instruction {
|
||||
&parse::Instruction::EntryPoint { ref execution, id, ref name, ref interface } => {
|
||||
(execution, name, interface)
|
||||
@ -24,57 +24,15 @@ pub fn write_entry_point(doc: &parse::Spirv, instruction: &parse::Instruction) -
|
||||
_ => unreachable!()
|
||||
};
|
||||
|
||||
let capitalized_ep_name: String = ep_name.chars().take(1).flat_map(|c| c.to_uppercase())
|
||||
.chain(ep_name.chars().skip(1)).collect();
|
||||
|
||||
let interface_structs = write_interface_structs(doc, &capitalized_ep_name, interface);
|
||||
|
||||
let (ty, f_call) = match *execution {
|
||||
enums::ExecutionModel::ExecutionModelVertex => {
|
||||
let mut attributes = Vec::new();
|
||||
|
||||
for interface in interface.iter() {
|
||||
for i in doc.instructions.iter() {
|
||||
match i {
|
||||
&parse::Instruction::Variable { result_type_id, result_id,
|
||||
storage_class: enums::StorageClass::StorageClassInput, .. }
|
||||
if &result_id == interface =>
|
||||
{
|
||||
if is_builtin(doc, result_id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let name = name_from_id(doc, result_id);
|
||||
let loc = match location_decoration(doc, result_id) {
|
||||
Some(l) => l,
|
||||
None => panic!("vertex attribute `{}` is missing a location", name)
|
||||
};
|
||||
attributes.push((loc, name, format_from_id(doc, result_type_id)));
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Checking for overlapping attributes.
|
||||
for (offset, &(loc, ref name, (_, loc_len))) in attributes.iter().enumerate() {
|
||||
for &(loc2, ref name2, (_, loc_len2)) in attributes.iter().skip(offset + 1) {
|
||||
if loc == loc2 || (loc < loc2 && loc + loc_len as u32 > loc2) ||
|
||||
(loc2 < loc && loc2 + loc_len2 as u32 > loc)
|
||||
{
|
||||
panic!("The locations of vertex attributes `{}` and `{}` overlap",
|
||||
name, name2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let attributes = attributes.iter().map(|&(loc, ref name, (ref ty, num_locs))| {
|
||||
assert!(num_locs >= 1);
|
||||
|
||||
format!("::vulkano::pipeline::shader::ShaderInterfaceDefEntry {{
|
||||
location: {} .. {},
|
||||
format: ::vulkano::format::Format::{},
|
||||
name: Some(::std::borrow::Cow::Borrowed(\"{}\"))
|
||||
}}", loc, loc as usize + num_locs, ty, name)
|
||||
}).collect::<Vec<_>>().join(", ");
|
||||
|
||||
let t = "::vulkano::pipeline::shader::VertexShaderEntryPoint<(), Vec<::vulkano::pipeline::shader::ShaderInterfaceDefEntry>, Layout>".to_owned();
|
||||
let f = format!("vertex_shader_entry_point(::std::ffi::CStr::from_ptr(NAME.as_ptr() as *const _), Layout, vec![{}])", attributes);
|
||||
let t = format!("::vulkano::pipeline::shader::VertexShaderEntryPoint<(), {}Input, Layout>", capitalized_ep_name);
|
||||
let f = format!("vertex_shader_entry_point(::std::ffi::CStr::from_ptr(NAME.as_ptr() as *const _), Layout, {}Input)", capitalized_ep_name);
|
||||
(t, f)
|
||||
},
|
||||
|
||||
@ -96,9 +54,8 @@ pub fn write_entry_point(doc: &parse::Spirv, instruction: &parse::Instruction) -
|
||||
for interface in interface.iter() {
|
||||
for i in doc.instructions.iter() {
|
||||
match i {
|
||||
&parse::Instruction::Variable { result_type_id, result_id,
|
||||
storage_class: enums::StorageClass::StorageClassOutput, .. }
|
||||
if &result_id == interface =>
|
||||
&parse::Instruction::Variable { result_type_id, result_id, ref storage_class,
|
||||
.. } if &result_id == interface =>
|
||||
{
|
||||
output_types.push(type_from_id(doc, result_type_id));
|
||||
},
|
||||
@ -125,7 +82,7 @@ pub fn write_entry_point(doc: &parse::Spirv, instruction: &parse::Instruction) -
|
||||
enums::ExecutionModel::ExecutionModelKernel => panic!("Kernels are not supported"),
|
||||
};
|
||||
|
||||
format!(r#"
|
||||
let entry_point = format!(r#"
|
||||
/// Returns a logical struct describing the entry point named `{ep_name}`.
|
||||
#[inline]
|
||||
pub fn {ep_name}_entry_point(&self) -> {ty} {{
|
||||
@ -138,5 +95,113 @@ pub fn write_entry_point(doc: &parse::Spirv, instruction: &parse::Instruction) -
|
||||
"#, ep_name = ep_name, ep_name_lenp1 = ep_name.chars().count() + 1, ty = ty,
|
||||
encoded_ep_name = ep_name.chars().map(|c| (c as u32).to_string())
|
||||
.collect::<Vec<String>>().join(", "),
|
||||
f_call = f_call)
|
||||
f_call = f_call);
|
||||
|
||||
(interface_structs, entry_point)
|
||||
}
|
||||
|
||||
fn write_interface_structs(doc: &parse::Spirv, capitalized_ep_name: &str, interface: &[u32])
|
||||
-> String
|
||||
{
|
||||
let mut input_elements = Vec::new();
|
||||
let mut output_elements = Vec::new();
|
||||
|
||||
// Filling `input_elements` and `output_elements`.
|
||||
for interface in interface.iter() {
|
||||
for i in doc.instructions.iter() {
|
||||
match i {
|
||||
&parse::Instruction::Variable { result_type_id, result_id, ref storage_class, .. }
|
||||
if &result_id == interface =>
|
||||
{
|
||||
if is_builtin(doc, result_id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if is_builtin(doc, result_type_id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let to_write = match storage_class {
|
||||
&enums::StorageClass::StorageClassInput => &mut input_elements,
|
||||
&enums::StorageClass::StorageClassOutput => &mut output_elements,
|
||||
_ => continue
|
||||
};
|
||||
|
||||
let name = name_from_id(doc, result_id);
|
||||
if name == "__unnamed" { continue; } // FIXME: hack
|
||||
|
||||
let loc = match location_decoration(doc, result_id) {
|
||||
Some(l) => l,
|
||||
None => panic!("Attribute `{}` (id {}) is missing a location", name, result_id)
|
||||
};
|
||||
|
||||
to_write.push((loc, name, format_from_id(doc, result_type_id)));
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
write_interface_struct(&format!("{}Input", capitalized_ep_name), &input_elements) +
|
||||
&write_interface_struct(&format!("{}Output", capitalized_ep_name), &output_elements)
|
||||
}
|
||||
|
||||
fn write_interface_struct(struct_name: &str, attributes: &[(u32, String, (String, usize))]) -> String {
|
||||
// Checking for overlapping elements.
|
||||
for (offset, &(loc, ref name, (_, loc_len))) in attributes.iter().enumerate() {
|
||||
for &(loc2, ref name2, (_, loc_len2)) in attributes.iter().skip(offset + 1) {
|
||||
if loc == loc2 || (loc < loc2 && loc + loc_len as u32 > loc2) ||
|
||||
(loc2 < loc && loc2 + loc_len2 as u32 > loc)
|
||||
{
|
||||
panic!("The locations of attributes `{}` and `{}` overlap",
|
||||
name, name2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let body = attributes.iter().enumerate().map(|(num, &(loc, ref name, (ref ty, num_locs)))| {
|
||||
assert!(num_locs >= 1);
|
||||
|
||||
format!("if self.num == {} {{
|
||||
self.num += 1;
|
||||
|
||||
return Some(::vulkano::pipeline::shader::ShaderInterfaceDefEntry {{
|
||||
location: {} .. {},
|
||||
format: ::vulkano::format::Format::{},
|
||||
name: Some(::std::borrow::Cow::Borrowed(\"{}\"))
|
||||
}});
|
||||
}}", num, loc, loc as usize + num_locs, ty, name)
|
||||
}).collect::<Vec<_>>().join("");
|
||||
|
||||
format!("
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct {name};
|
||||
|
||||
unsafe impl ::vulkano::pipeline::shader::ShaderInterfaceDef for {name} {{
|
||||
type Iter = {name}Iter;
|
||||
fn elements(&self) -> {name}Iter {{
|
||||
{name}Iter {{ num: 0 }}
|
||||
}}
|
||||
}}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct {name}Iter {{ num: u16 }}
|
||||
impl Iterator for {name}Iter {{
|
||||
type Item = ::vulkano::pipeline::shader::ShaderInterfaceDefEntry;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Self::Item> {{
|
||||
{body}
|
||||
None
|
||||
}}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {{
|
||||
let len = ({len} - self.num) as usize;
|
||||
(len, Some(len))
|
||||
}}
|
||||
}}
|
||||
|
||||
impl ExactSizeIterator for {name}Iter {{}}
|
||||
", name = struct_name, body = body, len = attributes.len())
|
||||
}
|
||||
|
@ -136,9 +136,12 @@ impl {name} {{
|
||||
"#, name = name, spirv_data = spirv_data));
|
||||
|
||||
// writing one method for each entry point of this module
|
||||
let mut outside_impl = String::new();
|
||||
for instruction in doc.instructions.iter() {
|
||||
if let &parse::Instruction::EntryPoint { .. } = instruction {
|
||||
output.push_str(&entry_point::write_entry_point(&doc, instruction));
|
||||
let (outside, entry_point) = entry_point::write_entry_point(&doc, instruction);
|
||||
output.push_str(&entry_point);
|
||||
outside_impl.push_str(&outside);
|
||||
}
|
||||
}
|
||||
|
||||
@ -147,6 +150,8 @@ impl {name} {{
|
||||
}}
|
||||
"#));
|
||||
|
||||
output.push_str(&outside_impl);
|
||||
|
||||
// struct definitions
|
||||
output.push_str("pub mod ty {");
|
||||
output.push_str(&structs::write_structs(&doc));
|
||||
|
Loading…
Reference in New Issue
Block a user