From f2155d49d1eb624d7d0ae012b060d42bd59dc593 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Fri, 26 Mar 2021 23:52:55 -0400 Subject: [PATCH] [msl] fix initialization of arrayed members, enable METAL snapshot of quad-vert --- src/back/msl/writer.rs | 63 +++++++++++++++++++++++++++--- tests/out/quad-vert.msl.snap | 75 ++++++++++++++++++++++++++++++++++++ tests/snapshots.rs | 2 +- 3 files changed, 134 insertions(+), 6 deletions(-) create mode 100644 tests/out/quad-vert.msl.snap diff --git a/src/back/msl/writer.rs b/src/back/msl/writer.rs index c73f67c8be..e045c9a240 100644 --- a/src/back/msl/writer.rs +++ b/src/back/msl/writer.rs @@ -205,6 +205,39 @@ impl Writer { Ok(()) } + fn put_initialization_component( + &mut self, + component: Handle, + context: &ExpressionContext, + ) -> Result<(), Error> { + // we can't initialize the array members just like other members, + // we have to unwrap them one level deeper... + let component_res = &context.info[component].ty; + if let crate::TypeInner::Array { + size: crate::ArraySize::Constant(const_handle), + .. + } = *component_res.inner_with(&context.module.types) + { + //HACK: we are forcefully duplicating the expression here, + // it would be nice to find a more C++ idiomatic solution for initializing array members + let size = context.module.constants[const_handle] + .to_array_length() + .unwrap(); + write!(self.out, "{{")?; + for j in 0..size { + if j != 0 { + write!(self.out, ",")?; + } + self.put_expression(component, context, false)?; + write!(self.out, "[{}]", j)?; + } + write!(self.out, "}}")?; + } else { + self.put_expression(component, context, true)?; + } + Ok(()) + } + fn put_expression( &mut self, expr_handle: Handle, @@ -301,7 +334,7 @@ impl Writer { if i != 0 { write!(self.out, ", ")?; } - self.put_expression(component, context, true)?; + self.put_initialization_component(component, context)?; } write!(self.out, "}}")?; } @@ -819,11 +852,31 @@ impl Writer { self.put_expression(expr_handle, &context.expression, true)?; writeln!(self.out, ";")?; write!(self.out, "{}return {} {{", level, struct_name)?; - for index in 0..members.len() as u32 { + for (index, member) in members.iter().enumerate() { let comma = if index == 0 { "" } else { "," }; - let name = - &self.names[&NameKey::StructMember(result_ty, index)]; - write!(self.out, "{} {}.{}", comma, tmp, name)?; + let name = &self.names + [&NameKey::StructMember(result_ty, index as u32)]; + // logic similar to `put_initialization_component` + if let crate::TypeInner::Array { + size: crate::ArraySize::Constant(const_handle), + .. + } = context.expression.module.types[member.ty].inner + { + let size = context.expression.module.constants + [const_handle] + .to_array_length() + .unwrap(); + write!(self.out, "{} {{", comma)?; + for j in 0..size { + if j != 0 { + write!(self.out, ",")?; + } + write!(self.out, "{}.{}[{}]", tmp, name, j)?; + } + write!(self.out, "}}")?; + } else { + write!(self.out, "{} {}.{}", comma, tmp, name)?; + } } } _ => { diff --git a/tests/out/quad-vert.msl.snap b/tests/out/quad-vert.msl.snap new file mode 100644 index 0000000000..80b8111412 --- /dev/null +++ b/tests/out/quad-vert.msl.snap @@ -0,0 +1,75 @@ +--- +source: tests/snapshots.rs +expression: msl +--- +#include +#include + +constexpr constant unsigned const_0u = 0u; +constexpr constant unsigned const_1u = 1u; +constexpr constant unsigned const_2u = 2u; +constexpr constant unsigned const_3u = 3u; +constexpr constant unsigned const_1u1 = 1u; +constexpr constant int const_0i = 0; +constexpr constant float const_0f = 0.0; +constexpr constant float const_1f = 1.0; +typedef float type; +typedef metal::float2 type1; +typedef thread type1 *type2; +typedef thread type1 *type3; +typedef metal::float4 type4; +typedef uint type5; +typedef type type6[const_1u1]; +struct gl_PerVertex { + type4 gl_Position; + type gl_PointSize; + type6 gl_ClipDistance; + type6 gl_CullDistance; +}; +typedef thread gl_PerVertex *type7; +typedef int type8; +typedef thread type4 *type9; +struct type10 { + type1 member; + type4 gl_Position1; + type gl_PointSize1; + type6 gl_ClipDistance1; +}; +void main1( + type1 v_uv, + type1 a_uv, + gl_PerVertex _, + type1 a_pos +) { + v_uv = a_uv; + type1 _expr9 = a_pos; + _.gl_Position = metal::float4(_expr9.x, _expr9.y, const_0f, const_1f); + return; +} + +struct main2Input { + type1 a_uv1 [[attribute(1)]]; + type1 a_pos1 [[attribute(0)]]; +}; +struct main2Output { + type1 member [[user(loc0)]]; + type4 gl_Position1 [[position]]; + type gl_PointSize1 [[point_size]]; + type6 gl_ClipDistance1 [[clip_distance]]; +}; +vertex main2Output main2( + main2Input varyings [[stage_in]] +) { + type1 v_uv = {}; + type1 a_uv = {}; + gl_PerVertex _ = {}; + type1 a_pos = {}; + const auto a_uv1 = varyings.a_uv1; + const auto a_pos1 = varyings.a_pos1; + a_uv = a_uv1; + a_pos = a_pos1; + main1(v_uv, a_uv, _, a_pos); + const auto _tmp = type10 {v_uv, _.gl_Position, _.gl_PointSize, {_.gl_ClipDistance[0]}}; + return main2Output { _tmp.member, _tmp.gl_Position1, _tmp.gl_PointSize1, {_tmp.gl_ClipDistance1[0]} }; +} + diff --git a/tests/snapshots.rs b/tests/snapshots.rs index d94f1f0522..30def8d2ce 100644 --- a/tests/snapshots.rs +++ b/tests/snapshots.rs @@ -286,7 +286,7 @@ fn convert_spv(name: &str, targets: Targets) { #[cfg(feature = "spv-in")] #[test] fn convert_spv_quad_vert() { - convert_spv("quad-vert", Targets::empty()); + convert_spv("quad-vert", Targets::METAL); } #[cfg(feature = "spv-in")]