diff --git a/src/front/spv/function.rs b/src/front/spv/function.rs index 8bd683a1b6..082c9ff170 100644 --- a/src/front/spv/function.rs +++ b/src/front/spv/function.rs @@ -235,20 +235,47 @@ impl> super::Parser { for &v_id in ep.variable_ids.iter() { let lvar = self.lookup_variable.lookup(v_id)?; if let super::Variable::Output(ref result) = lvar.inner { - members.push(crate::StructMember { - name: None, - ty: result.ty, - binding: result.binding.clone(), - size: None, - align: None, - }); - // populate just the globals first, then do `Load` in a - // separate step, so that we can get a range. - components.push( - function - .expressions - .append(crate::Expression::GlobalVariable(lvar.handle)), - ); + let expr_handle = function + .expressions + .append(crate::Expression::GlobalVariable(lvar.handle)); + match module.types[result.ty].inner { + crate::TypeInner::Struct { + members: ref sub_members, + .. + } => { + for (index, sm) in sub_members.iter().enumerate() { + if sm.binding.is_none() { + // unrecognized binding, skip + continue; + } + members.push(crate::StructMember { + name: sm.name.clone(), + ty: sm.ty, + binding: sm.binding.clone(), + size: None, + align: None, + }); + components.push(function.expressions.append( + crate::Expression::AccessIndex { + base: expr_handle, + index: index as u32, + }, + )); + } + } + _ => { + members.push(crate::StructMember { + name: None, + ty: result.ty, + binding: result.binding.clone(), + size: None, + align: None, + }); + // populate just the globals first, then do `Load` in a + // separate step, so that we can get a range. + components.push(expr_handle); + } + } } } diff --git a/src/front/spv/mod.rs b/src/front/spv/mod.rs index 46e1453ff9..6bcab546a8 100644 --- a/src/front/spv/mod.rs +++ b/src/front/spv/mod.rs @@ -2414,10 +2414,11 @@ impl> Parser { .future_member_decor .remove(&(id, i)) .unwrap_or_default(); + let binding = decor.io_binding().ok(); members.push(crate::StructMember { name: decor.name, ty, - binding: None, + binding, size: None, //TODO align: None, }); @@ -2871,7 +2872,8 @@ impl> Parser { (inner, var) } ExtendedClass::Output => { - let binding = dec.io_binding()?; + // For output interface blocks. this would be a structure. + let binding = dec.io_binding().ok(); let var = crate::GlobalVariable { name: dec.name, class: crate::StorageClass::Private, @@ -2882,7 +2884,7 @@ impl> Parser { }; let inner = Variable::Output(crate::FunctionResult { ty: effective_ty, - binding: Some(binding), + binding, }); (inner, var) } diff --git a/tests/in/quad-vert.spv b/tests/in/quad-vert.spv new file mode 100644 index 0000000000..eaf03d2fbe Binary files /dev/null and b/tests/in/quad-vert.spv differ diff --git a/tests/snapshots.rs b/tests/snapshots.rs index ab51a9bc45..d94f1f0522 100644 --- a/tests/snapshots.rs +++ b/tests/snapshots.rs @@ -283,6 +283,12 @@ fn convert_spv(name: &str, targets: Targets) { .unwrap(); } +#[cfg(feature = "spv-in")] +#[test] +fn convert_spv_quad_vert() { + convert_spv("quad-vert", Targets::empty()); +} + #[cfg(feature = "spv-in")] #[test] fn convert_spv_shadow() {