reader/spirv: Partially handle MatrixStride on matrix arrays
SPIR-V spec states:
> Each structure-type member that is a matrix or array-of-matrices must have be decorated with a MatrixStride Decoration
As already pointed out in https://dawn-review.googlesource.com/c/tint/+/59840, we were not handling arrays-of-matrices.
To do this correctly, we need the ast::StrideDecoration to be placed on the Matrix type, which is a much bigger change to support.
For now, chase the type, and error if we have a custom MatrixStride on an array of matrices, otherwise drop the decoration.
Bug: tint:1049
Fixed: tint:1088
Change-Id: Idcb75b3df88040836a03a14e0ca402ebee7be9a7
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/60923
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: David Neto <dneto@google.com>
Commit-Queue: David Neto <dneto@google.com>
Auto-Submit: Ben Clayton <bclayton@google.com>
diff --git a/src/reader/spirv/parser_impl.cc b/src/reader/spirv/parser_impl.cc
index de9fe80..43886bd 100644
--- a/src/reader/spirv/parser_impl.cc
+++ b/src/reader/spirv/parser_impl.cc
@@ -487,11 +487,22 @@
return {};
}
uint32_t stride = decoration[1];
- uint32_t natural_stride = 0;
- if (auto* mat = member_ty->As<Matrix>()) {
- natural_stride = (mat->rows == 2) ? 8 : 16;
+ auto* ty = member_ty->UnwrapAlias();
+ while (auto* arr = ty->As<Array>()) {
+ ty = arr->type->UnwrapAlias();
}
+ auto* mat = ty->As<Matrix>();
+ if (!mat) {
+ Fail() << "MatrixStride cannot be applied to type " << ty->String();
+ return {};
+ }
+ uint32_t natural_stride = (mat->rows == 2) ? 8 : 16;
if (stride == natural_stride) {
+ return {}; // Decoration matches the natural stride for the matrix
+ }
+ if (!member_ty->Is<Matrix>()) {
+ Fail() << "custom matrix strides not currently supported on array of "
+ "matrices";
return {};
}
return {
diff --git a/src/reader/spirv/parser_type.h b/src/reader/spirv/parser_type.h
index 0db8aee..e82a0df 100644
--- a/src/reader/spirv/parser_type.h
+++ b/src/reader/spirv/parser_type.h
@@ -80,7 +80,10 @@
/// @returns true if this type is an unsigned scalar or vector
bool IsUnsignedScalarOrVector() const;
-#ifndef NDEBUG
+#ifdef NDEBUG
+ /// @returns "<no-type-info>", for debug purposes only
+ std::string String() const { return "<no-type-info>"; }
+#else
/// @returns a string representation of the type, for debug purposes only
virtual std::string String() const = 0;
#endif // NDEBUG
diff --git a/test/bug/tint/1088.spvasm b/test/bug/tint/1088.spvasm
new file mode 100644
index 0000000..d68575c
--- /dev/null
+++ b/test/bug/tint/1088.spvasm
@@ -0,0 +1,149 @@
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 8
+; Bound: 91
+; Schema: 0
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Vertex %main "main" %position %__0 %vUV %uv %normal
+ OpSource GLSL 450
+ OpName %main "main"
+ OpName %q "q"
+ OpName %position "position"
+ OpName %p "p"
+ OpName %LeftOver "LeftOver"
+ OpMemberName %LeftOver 0 "worldViewProjection"
+ OpMemberName %LeftOver 1 "time"
+ OpMemberName %LeftOver 2 "test2"
+ OpMemberName %LeftOver 3 "test"
+ OpName %_ ""
+ OpName %gl_PerVertex "gl_PerVertex"
+ OpMemberName %gl_PerVertex 0 "gl_Position"
+ OpMemberName %gl_PerVertex 1 "gl_PointSize"
+ OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
+ OpMemberName %gl_PerVertex 3 "gl_CullDistance"
+ OpName %__0 ""
+ OpName %vUV "vUV"
+ OpName %uv "uv"
+ OpName %normal "normal"
+ OpDecorate %position Location 0
+ OpDecorate %_arr_mat4v4float_uint_2 ArrayStride 64
+ OpDecorate %_arr_float_uint_4 ArrayStride 16
+ OpMemberDecorate %LeftOver 0 ColMajor
+ OpMemberDecorate %LeftOver 0 Offset 0
+ OpMemberDecorate %LeftOver 0 MatrixStride 16
+ OpMemberDecorate %LeftOver 1 Offset 64
+ OpMemberDecorate %LeftOver 2 ColMajor
+ OpMemberDecorate %LeftOver 2 Offset 80
+ OpMemberDecorate %LeftOver 2 MatrixStride 16
+ OpMemberDecorate %LeftOver 3 Offset 208
+ OpDecorate %LeftOver Block
+ OpDecorate %_ DescriptorSet 2
+ OpDecorate %_ Binding 2
+ OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
+ OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
+ OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
+ OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
+ OpDecorate %gl_PerVertex Block
+ OpDecorate %vUV Location 0
+ OpDecorate %uv Location 2
+ OpDecorate %normal Location 1
+ %void = OpTypeVoid
+ %3 = OpTypeFunction %void
+ %float = OpTypeFloat 32
+ %v4float = OpTypeVector %float 4
+ %_ptr_Function_v4float = OpTypePointer Function %v4float
+ %v3float = OpTypeVector %float 3
+ %_ptr_Input_v3float = OpTypePointer Input %v3float
+ %position = OpVariable %_ptr_Input_v3float Input
+ %float_1 = OpConstant %float 1
+ %_ptr_Function_v3float = OpTypePointer Function %v3float
+ %uint = OpTypeInt 32 0
+ %uint_0 = OpConstant %uint 0
+ %_ptr_Function_float = OpTypePointer Function %float
+ %mat4v4float = OpTypeMatrix %v4float 4
+ %uint_2 = OpConstant %uint 2
+ %_arr_mat4v4float_uint_2 = OpTypeArray %mat4v4float %uint_2
+ %uint_4 = OpConstant %uint 4
+ %_arr_float_uint_4 = OpTypeArray %float %uint_4
+ %LeftOver = OpTypeStruct %mat4v4float %float %_arr_mat4v4float_uint_2 %_arr_float_uint_4
+ %_ptr_Uniform_LeftOver = OpTypePointer Uniform %LeftOver
+ %_ = OpVariable %_ptr_Uniform_LeftOver Uniform
+ %int = OpTypeInt 32 1
+ %int_3 = OpConstant %int 3
+ %int_0 = OpConstant %int 0
+ %_ptr_Uniform_float = OpTypePointer Uniform %float
+ %uint_1 = OpConstant %uint 1
+ %_ptr_Input_float = OpTypePointer Input %float
+ %int_1 = OpConstant %int 1
+ %float_4 = OpConstant %float 4
+ %_arr_float_uint_1 = OpTypeArray %float %uint_1
+ %gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
+%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
+ %__0 = OpVariable %_ptr_Output_gl_PerVertex Output
+%_ptr_Uniform_mat4v4float = OpTypePointer Uniform %mat4v4float
+ %_ptr_Output_v4float = OpTypePointer Output %v4float
+ %v2float = OpTypeVector %float 2
+ %_ptr_Output_v2float = OpTypePointer Output %v2float
+ %vUV = OpVariable %_ptr_Output_v2float Output
+ %_ptr_Input_v2float = OpTypePointer Input %v2float
+ %uv = OpVariable %_ptr_Input_v2float Input
+ %float_n1 = OpConstant %float -1
+ %_ptr_Output_float = OpTypePointer Output %float
+ %normal = OpVariable %_ptr_Input_v3float Input
+ %main = OpFunction %void None %3
+ %5 = OpLabel
+ %q = OpVariable %_ptr_Function_v4float Function
+ %p = OpVariable %_ptr_Function_v3float Function
+ %13 = OpLoad %v3float %position
+ %15 = OpCompositeExtract %float %13 0
+ %16 = OpCompositeExtract %float %13 1
+ %17 = OpCompositeExtract %float %13 2
+ %18 = OpCompositeConstruct %v4float %15 %16 %17 %float_1
+ OpStore %q %18
+ %21 = OpLoad %v4float %q
+ %22 = OpVectorShuffle %v3float %21 %21 0 1 2
+ OpStore %p %22
+ %26 = OpAccessChain %_ptr_Function_float %p %uint_0
+ %27 = OpLoad %float %26
+ %40 = OpAccessChain %_ptr_Uniform_float %_ %int_3 %int_0
+ %41 = OpLoad %float %40
+ %44 = OpAccessChain %_ptr_Input_float %position %uint_1
+ %45 = OpLoad %float %44
+ %46 = OpFMul %float %41 %45
+ %48 = OpAccessChain %_ptr_Uniform_float %_ %int_1
+ %49 = OpLoad %float %48
+ %50 = OpFAdd %float %46 %49
+ %51 = OpExtInst %float %1 Sin %50
+ %52 = OpFAdd %float %27 %51
+ %53 = OpAccessChain %_ptr_Function_float %p %uint_0
+ OpStore %53 %52
+ %54 = OpAccessChain %_ptr_Function_float %p %uint_1
+ %55 = OpLoad %float %54
+ %56 = OpAccessChain %_ptr_Uniform_float %_ %int_1
+ %57 = OpLoad %float %56
+ %59 = OpFAdd %float %57 %float_4
+ %60 = OpExtInst %float %1 Sin %59
+ %61 = OpFAdd %float %55 %60
+ %62 = OpAccessChain %_ptr_Function_float %p %uint_1
+ OpStore %62 %61
+ %68 = OpAccessChain %_ptr_Uniform_mat4v4float %_ %int_0
+ %69 = OpLoad %mat4v4float %68
+ %70 = OpLoad %v3float %p
+ %71 = OpCompositeExtract %float %70 0
+ %72 = OpCompositeExtract %float %70 1
+ %73 = OpCompositeExtract %float %70 2
+ %74 = OpCompositeConstruct %v4float %71 %72 %73 %float_1
+ %75 = OpMatrixTimesVector %v4float %69 %74
+ %77 = OpAccessChain %_ptr_Output_v4float %__0 %int_0
+ OpStore %77 %75
+ %83 = OpLoad %v2float %uv
+ OpStore %vUV %83
+ %86 = OpAccessChain %_ptr_Output_float %__0 %int_0 %uint_1
+ %87 = OpLoad %float %86
+ %88 = OpFMul %float %87 %float_n1
+ %89 = OpAccessChain %_ptr_Output_float %__0 %int_0 %uint_1
+ OpStore %89 %88
+ OpReturn
+ OpFunctionEnd
diff --git a/test/bug/tint/1088.spvasm.expected.hlsl b/test/bug/tint/1088.spvasm.expected.hlsl
new file mode 100644
index 0000000..a77d6dc
--- /dev/null
+++ b/test/bug/tint/1088.spvasm.expected.hlsl
@@ -0,0 +1,68 @@
+static float3 position = float3(0.0f, 0.0f, 0.0f);
+cbuffer cbuffer_x_14 : register(b2, space2) {
+ uint4 x_14[17];
+};
+static float2 vUV = float2(0.0f, 0.0f);
+static float2 uv = float2(0.0f, 0.0f);
+static float3 normal = float3(0.0f, 0.0f, 0.0f);
+static float4 gl_Position = float4(0.0f, 0.0f, 0.0f, 0.0f);
+
+float4x4 tint_symbol_5(uint4 buffer[17], uint offset) {
+ const uint scalar_offset = ((offset + 0u)) / 4;
+ const uint scalar_offset_1 = ((offset + 16u)) / 4;
+ const uint scalar_offset_2 = ((offset + 32u)) / 4;
+ const uint scalar_offset_3 = ((offset + 48u)) / 4;
+ return float4x4(asfloat(buffer[scalar_offset / 4]), asfloat(buffer[scalar_offset_1 / 4]), asfloat(buffer[scalar_offset_2 / 4]), asfloat(buffer[scalar_offset_3 / 4]));
+}
+
+void main_1() {
+ float4 q = float4(0.0f, 0.0f, 0.0f, 0.0f);
+ float3 p = float3(0.0f, 0.0f, 0.0f);
+ const float3 x_13 = position;
+ q = float4(x_13.x, x_13.y, x_13.z, 1.0f);
+ const float4 x_21 = q;
+ p = float3(x_21.x, x_21.y, x_21.z);
+ const float x_27 = p.x;
+ const uint scalar_offset_4 = ((208u + (16u * uint(0)))) / 4;
+ const float x_41 = asfloat(x_14[scalar_offset_4 / 4][scalar_offset_4 % 4]);
+ const float x_45 = position.y;
+ const float x_49 = asfloat(x_14[4].x);
+ p.x = (x_27 + sin(((x_41 * x_45) + x_49)));
+ const float x_55 = p.y;
+ const float x_57 = asfloat(x_14[4].x);
+ p.y = (x_55 + sin((x_57 + 4.0f)));
+ const float4x4 x_69 = tint_symbol_5(x_14, 0u);
+ const float3 x_70 = p;
+ gl_Position = mul(float4(x_70.x, x_70.y, x_70.z, 1.0f), x_69);
+ vUV = uv;
+ const float x_87 = gl_Position.y;
+ gl_Position.y = (x_87 * -1.0f);
+ return;
+}
+
+struct main_out {
+ float4 gl_Position;
+ float2 vUV_1;
+};
+struct tint_symbol_1 {
+ float3 position_param : TEXCOORD0;
+ float3 normal_param : TEXCOORD1;
+ float2 uv_param : TEXCOORD2;
+};
+struct tint_symbol_2 {
+ float2 vUV_1 : TEXCOORD0;
+ float4 gl_Position : SV_Position;
+};
+
+tint_symbol_2 main(tint_symbol_1 tint_symbol) {
+ const float3 position_param = tint_symbol.position_param;
+ const float2 uv_param = tint_symbol.uv_param;
+ const float3 normal_param = tint_symbol.normal_param;
+ position = position_param;
+ uv = uv_param;
+ normal = normal_param;
+ main_1();
+ const main_out tint_symbol_3 = {gl_Position, vUV};
+ const tint_symbol_2 tint_symbol_7 = {tint_symbol_3.vUV_1, tint_symbol_3.gl_Position};
+ return tint_symbol_7;
+}
diff --git a/test/bug/tint/1088.spvasm.expected.msl b/test/bug/tint/1088.spvasm.expected.msl
new file mode 100644
index 0000000..2e9e3da
--- /dev/null
+++ b/test/bug/tint/1088.spvasm.expected.msl
@@ -0,0 +1,77 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct tint_array_wrapper {
+ /* 0x0000 */ float4x4 arr[2];
+};
+struct tint_padded_array_element {
+ /* 0x0000 */ float el;
+ /* 0x0004 */ int8_t tint_pad[12];
+};
+struct tint_array_wrapper_1 {
+ /* 0x0000 */ tint_padded_array_element arr[4];
+};
+struct LeftOver {
+ /* 0x0000 */ float4x4 worldViewProjection;
+ /* 0x0040 */ float time;
+ /* 0x0044 */ int8_t tint_pad_1[12];
+ /* 0x0050 */ tint_array_wrapper test2;
+ /* 0x00d0 */ tint_array_wrapper_1 test;
+};
+struct main_out {
+ float4 gl_Position;
+ float2 vUV_1;
+};
+struct tint_symbol_2 {
+ float3 position_param [[attribute(0)]];
+ float3 normal_param [[attribute(1)]];
+ float2 uv_param [[attribute(2)]];
+};
+struct tint_symbol_3 {
+ float2 vUV_1 [[user(locn0)]];
+ float4 gl_Position [[position]];
+};
+
+void main_1(constant LeftOver& x_14, thread float3* const tint_symbol_6, thread float4* const tint_symbol_7, thread float2* const tint_symbol_8, thread float2* const tint_symbol_9) {
+ float4 q = 0.0f;
+ float3 p = 0.0f;
+ float3 const x_13 = *(tint_symbol_6);
+ q = float4(x_13.x, x_13.y, x_13.z, 1.0f);
+ float4 const x_21 = q;
+ p = float3(x_21.x, x_21.y, x_21.z);
+ float const x_27 = p.x;
+ float const x_41 = x_14.test.arr[0].el;
+ float const x_45 = (*(tint_symbol_6)).y;
+ float const x_49 = x_14.time;
+ p.x = (x_27 + sin(((x_41 * x_45) + x_49)));
+ float const x_55 = p.y;
+ float const x_57 = x_14.time;
+ p.y = (x_55 + sin((x_57 + 4.0f)));
+ float4x4 const x_69 = x_14.worldViewProjection;
+ float3 const x_70 = p;
+ *(tint_symbol_7) = (x_69 * float4(x_70.x, x_70.y, x_70.z, 1.0f));
+ float2 const x_83 = *(tint_symbol_8);
+ *(tint_symbol_9) = x_83;
+ float const x_87 = (*(tint_symbol_7)).y;
+ (*(tint_symbol_7)).y = (x_87 * -1.0f);
+ return;
+}
+
+vertex tint_symbol_3 tint_symbol(tint_symbol_2 tint_symbol_1 [[stage_in]], constant LeftOver& x_14 [[buffer(2)]]) {
+ thread float3 tint_symbol_10 = 0.0f;
+ thread float2 tint_symbol_11 = 0.0f;
+ thread float3 tint_symbol_12 = 0.0f;
+ thread float4 tint_symbol_13 = 0.0f;
+ thread float2 tint_symbol_14 = 0.0f;
+ float3 const position_param = tint_symbol_1.position_param;
+ float2 const uv_param = tint_symbol_1.uv_param;
+ float3 const normal_param = tint_symbol_1.normal_param;
+ tint_symbol_10 = position_param;
+ tint_symbol_11 = uv_param;
+ tint_symbol_12 = normal_param;
+ main_1(x_14, &(tint_symbol_10), &(tint_symbol_13), &(tint_symbol_11), &(tint_symbol_14));
+ main_out const tint_symbol_4 = {.gl_Position=tint_symbol_13, .vUV_1=tint_symbol_14};
+ tint_symbol_3 const tint_symbol_5 = {.vUV_1=tint_symbol_4.vUV_1, .gl_Position=tint_symbol_4.gl_Position};
+ return tint_symbol_5;
+}
+
diff --git a/test/bug/tint/1088.spvasm.expected.spvasm b/test/bug/tint/1088.spvasm.expected.spvasm
new file mode 100644
index 0000000..aef2a82
--- /dev/null
+++ b/test/bug/tint/1088.spvasm.expected.spvasm
@@ -0,0 +1,193 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 119
+; Schema: 0
+ OpCapability Shader
+ %74 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Vertex %main "main" %tint_pointsize %tint_symbol %tint_symbol_1 %tint_symbol_2 %tint_symbol_4 %tint_symbol_5
+ OpName %tint_pointsize "tint_pointsize"
+ OpName %position "position"
+ OpName %LeftOver "LeftOver"
+ OpMemberName %LeftOver 0 "worldViewProjection"
+ OpMemberName %LeftOver 1 "time"
+ OpMemberName %LeftOver 2 "test2"
+ OpMemberName %LeftOver 3 "test"
+ OpName %x_14 "x_14"
+ OpName %vUV "vUV"
+ OpName %uv "uv"
+ OpName %normal "normal"
+ OpName %gl_Position "gl_Position"
+ OpName %tint_symbol "tint_symbol"
+ OpName %tint_symbol_1 "tint_symbol_1"
+ OpName %tint_symbol_2 "tint_symbol_2"
+ OpName %tint_symbol_4 "tint_symbol_4"
+ OpName %tint_symbol_5 "tint_symbol_5"
+ OpName %main_1 "main_1"
+ OpName %q "q"
+ OpName %p "p"
+ OpName %main_out "main_out"
+ OpMemberName %main_out 0 "gl_Position"
+ OpMemberName %main_out 1 "vUV_1"
+ OpName %tint_symbol_6 "tint_symbol_6"
+ OpName %tint_symbol_3 "tint_symbol_3"
+ OpName %main "main"
+ OpDecorate %tint_pointsize BuiltIn PointSize
+ OpDecorate %LeftOver Block
+ OpMemberDecorate %LeftOver 0 Offset 0
+ OpMemberDecorate %LeftOver 0 ColMajor
+ OpMemberDecorate %LeftOver 0 MatrixStride 16
+ OpMemberDecorate %LeftOver 1 Offset 64
+ OpMemberDecorate %LeftOver 2 Offset 80
+ OpMemberDecorate %LeftOver 2 ColMajor
+ OpMemberDecorate %LeftOver 2 MatrixStride 16
+ OpDecorate %_arr_mat4v4float_uint_2 ArrayStride 64
+ OpMemberDecorate %LeftOver 3 Offset 208
+ OpDecorate %_arr_float_uint_4 ArrayStride 16
+ OpDecorate %x_14 NonWritable
+ OpDecorate %x_14 DescriptorSet 2
+ OpDecorate %x_14 Binding 2
+ OpDecorate %tint_symbol Location 0
+ OpDecorate %tint_symbol_1 Location 2
+ OpDecorate %tint_symbol_2 Location 1
+ OpDecorate %tint_symbol_4 BuiltIn Position
+ OpDecorate %tint_symbol_5 Location 0
+ OpMemberDecorate %main_out 0 Offset 0
+ OpMemberDecorate %main_out 1 Offset 16
+ %float = OpTypeFloat 32
+%_ptr_Output_float = OpTypePointer Output %float
+ %4 = OpConstantNull %float
+%tint_pointsize = OpVariable %_ptr_Output_float Output %4
+ %v3float = OpTypeVector %float 3
+%_ptr_Private_v3float = OpTypePointer Private %v3float
+ %8 = OpConstantNull %v3float
+ %position = OpVariable %_ptr_Private_v3float Private %8
+ %v4float = OpTypeVector %float 4
+%mat4v4float = OpTypeMatrix %v4float 4
+ %uint = OpTypeInt 32 0
+ %uint_2 = OpConstant %uint 2
+%_arr_mat4v4float_uint_2 = OpTypeArray %mat4v4float %uint_2
+ %uint_4 = OpConstant %uint 4
+%_arr_float_uint_4 = OpTypeArray %float %uint_4
+ %LeftOver = OpTypeStruct %mat4v4float %float %_arr_mat4v4float_uint_2 %_arr_float_uint_4
+%_ptr_Uniform_LeftOver = OpTypePointer Uniform %LeftOver
+ %x_14 = OpVariable %_ptr_Uniform_LeftOver Uniform
+ %v2float = OpTypeVector %float 2
+%_ptr_Private_v2float = OpTypePointer Private %v2float
+ %22 = OpConstantNull %v2float
+ %vUV = OpVariable %_ptr_Private_v2float Private %22
+ %uv = OpVariable %_ptr_Private_v2float Private %22
+ %normal = OpVariable %_ptr_Private_v3float Private %8
+%_ptr_Private_v4float = OpTypePointer Private %v4float
+ %27 = OpConstantNull %v4float
+%gl_Position = OpVariable %_ptr_Private_v4float Private %27
+%_ptr_Input_v3float = OpTypePointer Input %v3float
+%tint_symbol = OpVariable %_ptr_Input_v3float Input
+%_ptr_Input_v2float = OpTypePointer Input %v2float
+%tint_symbol_1 = OpVariable %_ptr_Input_v2float Input
+%tint_symbol_2 = OpVariable %_ptr_Input_v3float Input
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%tint_symbol_4 = OpVariable %_ptr_Output_v4float Output %27
+%_ptr_Output_v2float = OpTypePointer Output %v2float
+%tint_symbol_5 = OpVariable %_ptr_Output_v2float Output %22
+ %void = OpTypeVoid
+ %37 = OpTypeFunction %void
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+%_ptr_Function_v3float = OpTypePointer Function %v3float
+ %float_1 = OpConstant %float 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_Function_float = OpTypePointer Function %float
+ %uint_3 = OpConstant %uint 3
+ %int = OpTypeInt 32 1
+ %int_0 = OpConstant %int 0
+%_ptr_Uniform_float = OpTypePointer Uniform %float
+ %uint_1 = OpConstant %uint 1
+%_ptr_Private_float = OpTypePointer Private %float
+ %float_4 = OpConstant %float 4
+%_ptr_Uniform_mat4v4float = OpTypePointer Uniform %mat4v4float
+ %float_n1 = OpConstant %float -1
+ %main_out = OpTypeStruct %v4float %v2float
+ %102 = OpTypeFunction %void %main_out
+ %main_1 = OpFunction %void None %37
+ %40 = OpLabel
+ %q = OpVariable %_ptr_Function_v4float Function %27
+ %p = OpVariable %_ptr_Function_v3float Function %8
+ %45 = OpLoad %v3float %position
+ %46 = OpCompositeExtract %float %45 0
+ %47 = OpCompositeExtract %float %45 1
+ %48 = OpCompositeExtract %float %45 2
+ %50 = OpCompositeConstruct %v4float %46 %47 %48 %float_1
+ OpStore %q %50
+ %51 = OpLoad %v4float %q
+ %52 = OpCompositeExtract %float %51 0
+ %53 = OpCompositeExtract %float %51 1
+ %54 = OpCompositeExtract %float %51 2
+ %55 = OpCompositeConstruct %v3float %52 %53 %54
+ OpStore %p %55
+ %58 = OpAccessChain %_ptr_Function_float %p %uint_0
+ %59 = OpLoad %float %58
+ %64 = OpAccessChain %_ptr_Uniform_float %x_14 %uint_3 %int_0
+ %65 = OpLoad %float %64
+ %68 = OpAccessChain %_ptr_Private_float %position %uint_1
+ %69 = OpLoad %float %68
+ %70 = OpAccessChain %_ptr_Uniform_float %x_14 %uint_1
+ %71 = OpLoad %float %70
+ %72 = OpAccessChain %_ptr_Function_float %p %uint_0
+ %75 = OpFMul %float %65 %69
+ %76 = OpFAdd %float %75 %71
+ %73 = OpExtInst %float %74 Sin %76
+ %77 = OpFAdd %float %59 %73
+ OpStore %72 %77
+ %78 = OpAccessChain %_ptr_Function_float %p %uint_1
+ %79 = OpLoad %float %78
+ %80 = OpAccessChain %_ptr_Uniform_float %x_14 %uint_1
+ %81 = OpLoad %float %80
+ %82 = OpAccessChain %_ptr_Function_float %p %uint_1
+ %85 = OpFAdd %float %81 %float_4
+ %83 = OpExtInst %float %74 Sin %85
+ %86 = OpFAdd %float %79 %83
+ OpStore %82 %86
+ %88 = OpAccessChain %_ptr_Uniform_mat4v4float %x_14 %uint_0
+ %89 = OpLoad %mat4v4float %88
+ %90 = OpLoad %v3float %p
+ %91 = OpCompositeExtract %float %90 0
+ %92 = OpCompositeExtract %float %90 1
+ %93 = OpCompositeExtract %float %90 2
+ %94 = OpCompositeConstruct %v4float %91 %92 %93 %float_1
+ %95 = OpMatrixTimesVector %v4float %89 %94
+ OpStore %gl_Position %95
+ %96 = OpLoad %v2float %uv
+ OpStore %vUV %96
+ %97 = OpAccessChain %_ptr_Private_float %gl_Position %uint_1
+ %98 = OpLoad %float %97
+ %99 = OpAccessChain %_ptr_Private_float %gl_Position %uint_1
+ %101 = OpFMul %float %98 %float_n1
+ OpStore %99 %101
+ OpReturn
+ OpFunctionEnd
+%tint_symbol_6 = OpFunction %void None %102
+%tint_symbol_3 = OpFunctionParameter %main_out
+ %106 = OpLabel
+ %107 = OpCompositeExtract %v4float %tint_symbol_3 0
+ OpStore %tint_symbol_4 %107
+ %108 = OpCompositeExtract %v2float %tint_symbol_3 1
+ OpStore %tint_symbol_5 %108
+ OpReturn
+ OpFunctionEnd
+ %main = OpFunction %void None %37
+ %110 = OpLabel
+ OpStore %tint_pointsize %float_1
+ %111 = OpLoad %v3float %tint_symbol
+ OpStore %position %111
+ %112 = OpLoad %v2float %tint_symbol_1
+ OpStore %uv %112
+ %113 = OpLoad %v3float %tint_symbol_2
+ OpStore %normal %113
+ %114 = OpFunctionCall %void %main_1
+ %116 = OpLoad %v4float %gl_Position
+ %117 = OpLoad %v2float %vUV
+ %118 = OpCompositeConstruct %main_out %116 %117
+ %115 = OpFunctionCall %void %tint_symbol_6 %118
+ OpReturn
+ OpFunctionEnd
diff --git a/test/bug/tint/1088.spvasm.expected.wgsl b/test/bug/tint/1088.spvasm.expected.wgsl
new file mode 100644
index 0000000..347b3c6
--- /dev/null
+++ b/test/bug/tint/1088.spvasm.expected.wgsl
@@ -0,0 +1,66 @@
+type Arr = [[stride(64)]] array<mat4x4<f32>, 2>;
+
+type Arr_1 = [[stride(16)]] array<f32, 4>;
+
+[[block]]
+struct LeftOver {
+ worldViewProjection : mat4x4<f32>;
+ time : f32;
+ [[size(12)]]
+ padding : u32;
+ test2 : Arr;
+ test : Arr_1;
+};
+
+var<private> position : vec3<f32>;
+
+[[group(2), binding(2)]] var<uniform> x_14 : LeftOver;
+
+var<private> vUV : vec2<f32>;
+
+var<private> uv : vec2<f32>;
+
+var<private> normal : vec3<f32>;
+
+var<private> gl_Position : vec4<f32>;
+
+fn main_1() {
+ var q : vec4<f32>;
+ var p : vec3<f32>;
+ let x_13 : vec3<f32> = position;
+ q = vec4<f32>(x_13.x, x_13.y, x_13.z, 1.0);
+ let x_21 : vec4<f32> = q;
+ p = vec3<f32>(x_21.x, x_21.y, x_21.z);
+ let x_27 : f32 = p.x;
+ let x_41 : f32 = x_14.test[0];
+ let x_45 : f32 = position.y;
+ let x_49 : f32 = x_14.time;
+ p.x = (x_27 + sin(((x_41 * x_45) + x_49)));
+ let x_55 : f32 = p.y;
+ let x_57 : f32 = x_14.time;
+ p.y = (x_55 + sin((x_57 + 4.0)));
+ let x_69 : mat4x4<f32> = x_14.worldViewProjection;
+ let x_70 : vec3<f32> = p;
+ gl_Position = (x_69 * vec4<f32>(x_70.x, x_70.y, x_70.z, 1.0));
+ let x_83 : vec2<f32> = uv;
+ vUV = x_83;
+ let x_87 : f32 = gl_Position.y;
+ gl_Position.y = (x_87 * -1.0);
+ return;
+}
+
+struct main_out {
+ [[builtin(position)]]
+ gl_Position : vec4<f32>;
+ [[location(0)]]
+ vUV_1 : vec2<f32>;
+};
+
+[[stage(vertex)]]
+fn main([[location(0)]] position_param : vec3<f32>, [[location(2)]] uv_param : vec2<f32>, [[location(1)]] normal_param : vec3<f32>) -> main_out {
+ position = position_param;
+ uv = uv_param;
+ normal = normal_param;
+ main_1();
+ return main_out(gl_Position, vUV);
+}