Fix shader interfaces for tessellation and geometry shaders

This commit is contained in:
Pierre Krieger 2016-06-06 15:08:49 +02:00
parent d06d0e44ce
commit f220519e05
2 changed files with 34 additions and 11 deletions

View File

@ -27,7 +27,17 @@ pub fn write_entry_point(doc: &parse::Spirv, instruction: &parse::Instruction) -
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 interface_structs = write_interface_structs(doc, &capitalized_ep_name, interface,
match *execution {
enums::ExecutionModel::ExecutionModelTessellationControl => true,
enums::ExecutionModel::ExecutionModelTessellationEvaluation => true,
enums::ExecutionModel::ExecutionModelGeometry => true,
_ => false
},
match *execution {
enums::ExecutionModel::ExecutionModelTessellationControl => true,
_ => false,
});
let (ty, f_call) = match *execution {
enums::ExecutionModel::ExecutionModelVertex => {
@ -86,7 +96,8 @@ pub fn write_entry_point(doc: &parse::Spirv, instruction: &parse::Instruction) -
(interface_structs, entry_point)
}
fn write_interface_structs(doc: &parse::Spirv, capitalized_ep_name: &str, interface: &[u32])
fn write_interface_structs(doc: &parse::Spirv, capitalized_ep_name: &str, interface: &[u32],
ignore_first_array_in: bool, ignore_first_array_out: bool)
-> String
{
let mut input_elements = Vec::new();
@ -107,9 +118,9 @@ fn write_interface_structs(doc: &parse::Spirv, capitalized_ep_name: &str, interf
continue;
}
let to_write = match storage_class {
&enums::StorageClass::StorageClassInput => &mut input_elements,
&enums::StorageClass::StorageClassOutput => &mut output_elements,
let (to_write, ignore_first_array) = match storage_class {
&enums::StorageClass::StorageClassInput => (&mut input_elements, ignore_first_array_in),
&enums::StorageClass::StorageClassOutput => (&mut output_elements, ignore_first_array_out),
_ => continue
};
@ -121,7 +132,7 @@ fn write_interface_structs(doc: &parse::Spirv, capitalized_ep_name: &str, interf
None => panic!("Attribute `{}` (id {}) is missing a location", name, result_id)
};
to_write.push((loc, name, format_from_id(doc, result_type_id)));
to_write.push((loc, name, format_from_id(doc, result_type_id, ignore_first_array)));
},
_ => ()
}

View File

@ -189,17 +189,24 @@ impl From<ParseError> for Error {
}
/// Returns the vulkano `Format` and number of occupied locations from an id.
fn format_from_id(doc: &parse::Spirv, searched: u32) -> (String, usize) {
///
/// If `ignore_first_array` is true, the function expects the outermost instruction to be
/// `OpTypeArray`. If it's the case, the OpTypeArray will be ignored. If not, the function will
/// panic.
fn format_from_id(doc: &parse::Spirv, searched: u32, ignore_first_array: bool) -> (String, usize) {
for instruction in doc.instructions.iter() {
match instruction {
&parse::Instruction::TypeInt { result_id, width, signedness } if result_id == searched => {
assert!(!ignore_first_array);
return ("R32Sint".to_owned(), 1);
},
&parse::Instruction::TypeFloat { result_id, width } if result_id == searched => {
assert!(!ignore_first_array);
return ("R32Sfloat".to_owned(), 1);
},
&parse::Instruction::TypeVector { result_id, component_id, count } if result_id == searched => {
let (format, sz) = format_from_id(doc, component_id);
assert!(!ignore_first_array);
let (format, sz) = format_from_id(doc, component_id, false);
assert!(format.starts_with("R32"));
assert_eq!(sz, 1);
let format = if count == 1 {
@ -216,11 +223,16 @@ fn format_from_id(doc: &parse::Spirv, searched: u32) -> (String, usize) {
return (format, sz);
},
&parse::Instruction::TypeMatrix { result_id, column_type_id, column_count } if result_id == searched => {
let (format, sz) = format_from_id(doc, column_type_id);
assert!(!ignore_first_array);
let (format, sz) = format_from_id(doc, column_type_id, false);
return (format, sz * column_count as usize);
},
&parse::Instruction::TypeArray { result_id, type_id, length_id } if result_id == searched => {
let (format, sz) = format_from_id(doc, type_id);
if ignore_first_array {
return format_from_id(doc, type_id, false);
}
let (format, sz) = format_from_id(doc, type_id, false);
let len = doc.instructions.iter().filter_map(|e| {
match e { &parse::Instruction::Constant { result_id, ref data, .. } if result_id == length_id => Some(data.clone()), _ => None }
}).next().expect("failed to find array length");
@ -228,7 +240,7 @@ fn format_from_id(doc: &parse::Spirv, searched: u32) -> (String, usize) {
return (format, sz * len as usize);
},
&parse::Instruction::TypePointer { result_id, type_id, .. } if result_id == searched => {
return format_from_id(doc, type_id);
return format_from_id(doc, type_id, ignore_first_array);
},
_ => ()
}