test: Add E2E test coverage for shader IO
This provides much more complete coverage than what we have in the
unit tests. We now test:
- All builtins, for all stages, both struct and non-struct
- Multiple location attributes for vertex and fragment stages, both
struct and non-struct
- Mixing builtins and location attributes, whilst mixing struct and
non-struct
- A few "interesting" cases of IO structs being shared between
different functions, stages, and with an SSBO variable
There are 7 skipped tests for MSL due to two different MSL bugs which
will be fixed in upcoming patches.
Change-Id: I8b802591762c8ff018e01bf37838551e353162b1
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/53120
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Auto-Submit: James Price <jrprice@google.com>
diff --git a/test/shader_io/compute_input_builtins.wgsl b/test/shader_io/compute_input_builtins.wgsl
new file mode 100644
index 0000000..b3d6672
--- /dev/null
+++ b/test/shader_io/compute_input_builtins.wgsl
@@ -0,0 +1,14 @@
+[[stage(compute)]]
+fn main(
+ [[builtin(local_invocation_id)]] local_invocation_id : vec3<u32>,
+ [[builtin(local_invocation_index)]] local_invocation_index : u32,
+ [[builtin(global_invocation_id)]] global_invocation_id : vec3<u32>,
+ [[builtin(workgroup_id)]] workgroup_id : vec3<u32>,
+ // TODO(crbug.com/tint/752): [[builtin(num_workgroups)]] num_workgroups : vec3<u32>;
+) {
+ let foo : u32 =
+ local_invocation_id.x +
+ local_invocation_index +
+ global_invocation_id.x +
+ workgroup_id.x;
+}
diff --git a/test/shader_io/compute_input_builtins.wgsl.expected.hlsl b/test/shader_io/compute_input_builtins.wgsl.expected.hlsl
new file mode 100644
index 0000000..476144a
--- /dev/null
+++ b/test/shader_io/compute_input_builtins.wgsl.expected.hlsl
@@ -0,0 +1,17 @@
+struct tint_symbol_1 {
+ uint3 local_invocation_id : SV_GroupThreadID;
+ uint local_invocation_index : SV_GroupIndex;
+ uint3 global_invocation_id : SV_DispatchThreadID;
+ uint3 workgroup_id : SV_GroupID;
+};
+
+[numthreads(1, 1, 1)]
+void main(tint_symbol_1 tint_symbol) {
+ const uint3 local_invocation_id = tint_symbol.local_invocation_id;
+ const uint local_invocation_index = tint_symbol.local_invocation_index;
+ const uint3 global_invocation_id = tint_symbol.global_invocation_id;
+ const uint3 workgroup_id = tint_symbol.workgroup_id;
+ const uint foo = (((local_invocation_id.x + local_invocation_index) + global_invocation_id.x) + workgroup_id.x);
+ return;
+}
+
diff --git a/test/shader_io/compute_input_builtins.wgsl.expected.msl b/test/shader_io/compute_input_builtins.wgsl.expected.msl
new file mode 100644
index 0000000..71d62fb
--- /dev/null
+++ b/test/shader_io/compute_input_builtins.wgsl.expected.msl
@@ -0,0 +1 @@
+SKIP: crbug.com/tint/817 attribute only applies to parameters
diff --git a/test/shader_io/compute_input_builtins.wgsl.expected.spvasm b/test/shader_io/compute_input_builtins.wgsl.expected.spvasm
new file mode 100644
index 0000000..b47c180
--- /dev/null
+++ b/test/shader_io/compute_input_builtins.wgsl.expected.spvasm
@@ -0,0 +1,43 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 24
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main" %tint_symbol %tint_symbol_1 %tint_symbol_2 %tint_symbol_3
+ OpExecutionMode %main LocalSize 1 1 1
+ OpName %tint_symbol "tint_symbol"
+ OpName %tint_symbol_1 "tint_symbol_1"
+ OpName %tint_symbol_2 "tint_symbol_2"
+ OpName %tint_symbol_3 "tint_symbol_3"
+ OpName %main "main"
+ OpDecorate %tint_symbol BuiltIn LocalInvocationId
+ OpDecorate %tint_symbol_1 BuiltIn LocalInvocationIndex
+ OpDecorate %tint_symbol_2 BuiltIn GlobalInvocationId
+ OpDecorate %tint_symbol_3 BuiltIn WorkgroupId
+ %uint = OpTypeInt 32 0
+ %v3uint = OpTypeVector %uint 3
+%_ptr_Input_v3uint = OpTypePointer Input %v3uint
+%tint_symbol = OpVariable %_ptr_Input_v3uint Input
+%_ptr_Input_uint = OpTypePointer Input %uint
+%tint_symbol_1 = OpVariable %_ptr_Input_uint Input
+%tint_symbol_2 = OpVariable %_ptr_Input_v3uint Input
+%tint_symbol_3 = OpVariable %_ptr_Input_v3uint Input
+ %void = OpTypeVoid
+ %9 = OpTypeFunction %void
+ %uint_0 = OpConstant %uint 0
+ %main = OpFunction %void None %9
+ %12 = OpLabel
+ %14 = OpAccessChain %_ptr_Input_uint %tint_symbol %uint_0
+ %15 = OpLoad %uint %14
+ %16 = OpLoad %uint %tint_symbol_1
+ %17 = OpIAdd %uint %15 %16
+ %18 = OpAccessChain %_ptr_Input_uint %tint_symbol_2 %uint_0
+ %19 = OpLoad %uint %18
+ %20 = OpIAdd %uint %17 %19
+ %21 = OpAccessChain %_ptr_Input_uint %tint_symbol_3 %uint_0
+ %22 = OpLoad %uint %21
+ %23 = OpIAdd %uint %20 %22
+ OpReturn
+ OpFunctionEnd
diff --git a/test/shader_io/compute_input_builtins.wgsl.expected.wgsl b/test/shader_io/compute_input_builtins.wgsl.expected.wgsl
new file mode 100644
index 0000000..95ee85f
--- /dev/null
+++ b/test/shader_io/compute_input_builtins.wgsl.expected.wgsl
@@ -0,0 +1,4 @@
+[[stage(compute)]]
+fn main([[builtin(local_invocation_id)]] local_invocation_id : vec3<u32>, [[builtin(local_invocation_index)]] local_invocation_index : u32, [[builtin(global_invocation_id)]] global_invocation_id : vec3<u32>, [[builtin(workgroup_id)]] workgroup_id : vec3<u32>) {
+ let foo : u32 = (((local_invocation_id.x + local_invocation_index) + global_invocation_id.x) + workgroup_id.x);
+}
diff --git a/test/shader_io/compute_input_builtins_struct.wgsl b/test/shader_io/compute_input_builtins_struct.wgsl
new file mode 100644
index 0000000..17f15b2
--- /dev/null
+++ b/test/shader_io/compute_input_builtins_struct.wgsl
@@ -0,0 +1,16 @@
+struct ComputeInputs {
+ [[builtin(local_invocation_id)]] local_invocation_id : vec3<u32>;
+ [[builtin(local_invocation_index)]] local_invocation_index : u32;
+ [[builtin(global_invocation_id)]] global_invocation_id : vec3<u32>;
+ [[builtin(workgroup_id)]] workgroup_id : vec3<u32>;
+ // TODO(crbug.com/tint/752): [[builtin(num_workgroups)]] num_workgroups : vec3<u32>;
+};
+
+[[stage(compute)]]
+fn main(inputs : ComputeInputs) {
+ let foo : u32 =
+ inputs.local_invocation_id.x +
+ inputs.local_invocation_index +
+ inputs.global_invocation_id.x +
+ inputs.workgroup_id.x;
+}
diff --git a/test/shader_io/compute_input_builtins_struct.wgsl.expected.hlsl b/test/shader_io/compute_input_builtins_struct.wgsl.expected.hlsl
new file mode 100644
index 0000000..a33806b
--- /dev/null
+++ b/test/shader_io/compute_input_builtins_struct.wgsl.expected.hlsl
@@ -0,0 +1,20 @@
+struct ComputeInputs {
+ uint3 local_invocation_id;
+ uint local_invocation_index;
+ uint3 global_invocation_id;
+ uint3 workgroup_id;
+};
+struct tint_symbol_1 {
+ uint3 local_invocation_id : SV_GroupThreadID;
+ uint local_invocation_index : SV_GroupIndex;
+ uint3 global_invocation_id : SV_DispatchThreadID;
+ uint3 workgroup_id : SV_GroupID;
+};
+
+[numthreads(1, 1, 1)]
+void main(tint_symbol_1 tint_symbol) {
+ const ComputeInputs inputs = {tint_symbol.local_invocation_id, tint_symbol.local_invocation_index, tint_symbol.global_invocation_id, tint_symbol.workgroup_id};
+ const uint foo = (((inputs.local_invocation_id.x + inputs.local_invocation_index) + inputs.global_invocation_id.x) + inputs.workgroup_id.x);
+ return;
+}
+
diff --git a/test/shader_io/compute_input_builtins_struct.wgsl.expected.msl b/test/shader_io/compute_input_builtins_struct.wgsl.expected.msl
new file mode 100644
index 0000000..71d62fb
--- /dev/null
+++ b/test/shader_io/compute_input_builtins_struct.wgsl.expected.msl
@@ -0,0 +1 @@
+SKIP: crbug.com/tint/817 attribute only applies to parameters
diff --git a/test/shader_io/compute_input_builtins_struct.wgsl.expected.spvasm b/test/shader_io/compute_input_builtins_struct.wgsl.expected.spvasm
new file mode 100644
index 0000000..f54703d
--- /dev/null
+++ b/test/shader_io/compute_input_builtins_struct.wgsl.expected.spvasm
@@ -0,0 +1,57 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 29
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main" %tint_symbol %tint_symbol_1 %tint_symbol_2 %tint_symbol_3
+ OpExecutionMode %main LocalSize 1 1 1
+ OpName %tint_symbol "tint_symbol"
+ OpName %tint_symbol_1 "tint_symbol_1"
+ OpName %tint_symbol_2 "tint_symbol_2"
+ OpName %tint_symbol_3 "tint_symbol_3"
+ OpName %main "main"
+ OpName %ComputeInputs "ComputeInputs"
+ OpMemberName %ComputeInputs 0 "local_invocation_id"
+ OpMemberName %ComputeInputs 1 "local_invocation_index"
+ OpMemberName %ComputeInputs 2 "global_invocation_id"
+ OpMemberName %ComputeInputs 3 "workgroup_id"
+ OpDecorate %tint_symbol BuiltIn LocalInvocationId
+ OpDecorate %tint_symbol_1 BuiltIn LocalInvocationIndex
+ OpDecorate %tint_symbol_2 BuiltIn GlobalInvocationId
+ OpDecorate %tint_symbol_3 BuiltIn WorkgroupId
+ OpMemberDecorate %ComputeInputs 0 Offset 0
+ OpMemberDecorate %ComputeInputs 1 Offset 12
+ OpMemberDecorate %ComputeInputs 2 Offset 16
+ OpMemberDecorate %ComputeInputs 3 Offset 32
+ %uint = OpTypeInt 32 0
+ %v3uint = OpTypeVector %uint 3
+%_ptr_Input_v3uint = OpTypePointer Input %v3uint
+%tint_symbol = OpVariable %_ptr_Input_v3uint Input
+%_ptr_Input_uint = OpTypePointer Input %uint
+%tint_symbol_1 = OpVariable %_ptr_Input_uint Input
+%tint_symbol_2 = OpVariable %_ptr_Input_v3uint Input
+%tint_symbol_3 = OpVariable %_ptr_Input_v3uint Input
+ %void = OpTypeVoid
+ %9 = OpTypeFunction %void
+%ComputeInputs = OpTypeStruct %v3uint %uint %v3uint %v3uint
+ %main = OpFunction %void None %9
+ %12 = OpLabel
+ %14 = OpLoad %v3uint %tint_symbol
+ %15 = OpLoad %uint %tint_symbol_1
+ %16 = OpLoad %v3uint %tint_symbol_2
+ %17 = OpLoad %v3uint %tint_symbol_3
+ %18 = OpCompositeConstruct %ComputeInputs %14 %15 %16 %17
+ %19 = OpCompositeExtract %v3uint %18 0
+ %20 = OpCompositeExtract %uint %19 0
+ %21 = OpCompositeExtract %uint %18 1
+ %22 = OpIAdd %uint %20 %21
+ %23 = OpCompositeExtract %v3uint %18 2
+ %24 = OpCompositeExtract %uint %23 0
+ %25 = OpIAdd %uint %22 %24
+ %26 = OpCompositeExtract %v3uint %18 3
+ %27 = OpCompositeExtract %uint %26 0
+ %28 = OpIAdd %uint %25 %27
+ OpReturn
+ OpFunctionEnd
diff --git a/test/shader_io/compute_input_builtins_struct.wgsl.expected.wgsl b/test/shader_io/compute_input_builtins_struct.wgsl.expected.wgsl
new file mode 100644
index 0000000..c7f51b9
--- /dev/null
+++ b/test/shader_io/compute_input_builtins_struct.wgsl.expected.wgsl
@@ -0,0 +1,15 @@
+struct ComputeInputs {
+ [[builtin(local_invocation_id)]]
+ local_invocation_id : vec3<u32>;
+ [[builtin(local_invocation_index)]]
+ local_invocation_index : u32;
+ [[builtin(global_invocation_id)]]
+ global_invocation_id : vec3<u32>;
+ [[builtin(workgroup_id)]]
+ workgroup_id : vec3<u32>;
+};
+
+[[stage(compute)]]
+fn main(inputs : ComputeInputs) {
+ let foo : u32 = (((inputs.local_invocation_id.x + inputs.local_invocation_index) + inputs.global_invocation_id.x) + inputs.workgroup_id.x);
+}
diff --git a/test/shader_io/compute_input_mixed.wgsl b/test/shader_io/compute_input_mixed.wgsl
new file mode 100644
index 0000000..e9ccaaa
--- /dev/null
+++ b/test/shader_io/compute_input_mixed.wgsl
@@ -0,0 +1,20 @@
+struct ComputeInputs0 {
+ [[builtin(local_invocation_id)]] local_invocation_id : vec3<u32>;
+};
+struct ComputeInputs1 {
+ [[builtin(workgroup_id)]] workgroup_id : vec3<u32>;
+};
+
+[[stage(compute)]]
+fn main(
+ inputs0 : ComputeInputs0,
+ [[builtin(local_invocation_index)]] local_invocation_index : u32,
+ [[builtin(global_invocation_id)]] global_invocation_id : vec3<u32>,
+ inputs1 : ComputeInputs1,
+) {
+ let foo : u32 =
+ inputs0.local_invocation_id.x +
+ local_invocation_index +
+ global_invocation_id.x +
+ inputs1.workgroup_id.x;
+}
diff --git a/test/shader_io/compute_input_mixed.wgsl.expected.hlsl b/test/shader_io/compute_input_mixed.wgsl.expected.hlsl
new file mode 100644
index 0000000..f9a8369
--- /dev/null
+++ b/test/shader_io/compute_input_mixed.wgsl.expected.hlsl
@@ -0,0 +1,23 @@
+struct ComputeInputs0 {
+ uint3 local_invocation_id;
+};
+struct ComputeInputs1 {
+ uint3 workgroup_id;
+};
+struct tint_symbol_1 {
+ uint3 local_invocation_id : SV_GroupThreadID;
+ uint local_invocation_index : SV_GroupIndex;
+ uint3 global_invocation_id : SV_DispatchThreadID;
+ uint3 workgroup_id : SV_GroupID;
+};
+
+[numthreads(1, 1, 1)]
+void main(tint_symbol_1 tint_symbol) {
+ const ComputeInputs0 inputs0 = {tint_symbol.local_invocation_id};
+ const uint local_invocation_index = tint_symbol.local_invocation_index;
+ const uint3 global_invocation_id = tint_symbol.global_invocation_id;
+ const ComputeInputs1 inputs1 = {tint_symbol.workgroup_id};
+ const uint foo = (((inputs0.local_invocation_id.x + local_invocation_index) + global_invocation_id.x) + inputs1.workgroup_id.x);
+ return;
+}
+
diff --git a/test/shader_io/compute_input_mixed.wgsl.expected.msl b/test/shader_io/compute_input_mixed.wgsl.expected.msl
new file mode 100644
index 0000000..71d62fb
--- /dev/null
+++ b/test/shader_io/compute_input_mixed.wgsl.expected.msl
@@ -0,0 +1 @@
+SKIP: crbug.com/tint/817 attribute only applies to parameters
diff --git a/test/shader_io/compute_input_mixed.wgsl.expected.spvasm b/test/shader_io/compute_input_mixed.wgsl.expected.spvasm
new file mode 100644
index 0000000..145635e
--- /dev/null
+++ b/test/shader_io/compute_input_mixed.wgsl.expected.spvasm
@@ -0,0 +1,55 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 30
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main" %tint_symbol %tint_symbol_4 %tint_symbol_2 %tint_symbol_3
+ OpExecutionMode %main LocalSize 1 1 1
+ OpName %tint_symbol "tint_symbol"
+ OpName %tint_symbol_2 "tint_symbol_2"
+ OpName %tint_symbol_3 "tint_symbol_3"
+ OpName %tint_symbol_4 "tint_symbol_4"
+ OpName %main "main"
+ OpName %ComputeInputs0 "ComputeInputs0"
+ OpMemberName %ComputeInputs0 0 "local_invocation_id"
+ OpName %ComputeInputs1 "ComputeInputs1"
+ OpMemberName %ComputeInputs1 0 "workgroup_id"
+ OpDecorate %tint_symbol BuiltIn LocalInvocationId
+ OpDecorate %tint_symbol_2 BuiltIn LocalInvocationIndex
+ OpDecorate %tint_symbol_3 BuiltIn GlobalInvocationId
+ OpDecorate %tint_symbol_4 BuiltIn WorkgroupId
+ OpMemberDecorate %ComputeInputs0 0 Offset 0
+ OpMemberDecorate %ComputeInputs1 0 Offset 0
+ %uint = OpTypeInt 32 0
+ %v3uint = OpTypeVector %uint 3
+%_ptr_Input_v3uint = OpTypePointer Input %v3uint
+%tint_symbol = OpVariable %_ptr_Input_v3uint Input
+%_ptr_Input_uint = OpTypePointer Input %uint
+%tint_symbol_2 = OpVariable %_ptr_Input_uint Input
+%tint_symbol_3 = OpVariable %_ptr_Input_v3uint Input
+%tint_symbol_4 = OpVariable %_ptr_Input_v3uint Input
+ %void = OpTypeVoid
+ %9 = OpTypeFunction %void
+%ComputeInputs0 = OpTypeStruct %v3uint
+%ComputeInputs1 = OpTypeStruct %v3uint
+ %uint_0 = OpConstant %uint 0
+ %main = OpFunction %void None %9
+ %12 = OpLabel
+ %14 = OpLoad %v3uint %tint_symbol
+ %15 = OpCompositeConstruct %ComputeInputs0 %14
+ %17 = OpLoad %v3uint %tint_symbol_4
+ %18 = OpCompositeConstruct %ComputeInputs1 %17
+ %19 = OpCompositeExtract %v3uint %15 0
+ %20 = OpCompositeExtract %uint %19 0
+ %21 = OpLoad %uint %tint_symbol_2
+ %22 = OpIAdd %uint %20 %21
+ %24 = OpAccessChain %_ptr_Input_uint %tint_symbol_3 %uint_0
+ %25 = OpLoad %uint %24
+ %26 = OpIAdd %uint %22 %25
+ %27 = OpCompositeExtract %v3uint %18 0
+ %28 = OpCompositeExtract %uint %27 0
+ %29 = OpIAdd %uint %26 %28
+ OpReturn
+ OpFunctionEnd
diff --git a/test/shader_io/compute_input_mixed.wgsl.expected.wgsl b/test/shader_io/compute_input_mixed.wgsl.expected.wgsl
new file mode 100644
index 0000000..2233b53
--- /dev/null
+++ b/test/shader_io/compute_input_mixed.wgsl.expected.wgsl
@@ -0,0 +1,14 @@
+struct ComputeInputs0 {
+ [[builtin(local_invocation_id)]]
+ local_invocation_id : vec3<u32>;
+};
+
+struct ComputeInputs1 {
+ [[builtin(workgroup_id)]]
+ workgroup_id : vec3<u32>;
+};
+
+[[stage(compute)]]
+fn main(inputs0 : ComputeInputs0, [[builtin(local_invocation_index)]] local_invocation_index : u32, [[builtin(global_invocation_id)]] global_invocation_id : vec3<u32>, inputs1 : ComputeInputs1) {
+ let foo : u32 = (((inputs0.local_invocation_id.x + local_invocation_index) + global_invocation_id.x) + inputs1.workgroup_id.x);
+}
diff --git a/test/shader_io/fragment_input_builtins.wgsl b/test/shader_io/fragment_input_builtins.wgsl
new file mode 100644
index 0000000..0395bfd
--- /dev/null
+++ b/test/shader_io/fragment_input_builtins.wgsl
@@ -0,0 +1,12 @@
+[[stage(fragment)]]
+fn main(
+ [[builtin(position)]] position : vec4<f32>,
+ [[builtin(front_facing)]] front_facing : bool,
+ [[builtin(sample_index)]] sample_index : u32,
+ [[builtin(sample_mask)]] sample_mask : u32,
+) {
+ if (front_facing) {
+ let foo : vec4<f32> = position;
+ let bar : u32 = sample_index + sample_mask;
+ }
+}
diff --git a/test/shader_io/fragment_input_builtins.wgsl.expected.hlsl b/test/shader_io/fragment_input_builtins.wgsl.expected.hlsl
new file mode 100644
index 0000000..461ac3f
--- /dev/null
+++ b/test/shader_io/fragment_input_builtins.wgsl.expected.hlsl
@@ -0,0 +1,19 @@
+struct tint_symbol_1 {
+ float4 position : SV_Position;
+ bool front_facing : SV_IsFrontFace;
+ uint sample_index : SV_SampleIndex;
+ uint sample_mask : SV_Coverage;
+};
+
+void main(tint_symbol_1 tint_symbol) {
+ const float4 position = tint_symbol.position;
+ const bool front_facing = tint_symbol.front_facing;
+ const uint sample_index = tint_symbol.sample_index;
+ const uint sample_mask = tint_symbol.sample_mask;
+ if (front_facing) {
+ const float4 foo = position;
+ const uint bar = (sample_index + sample_mask);
+ }
+ return;
+}
+
diff --git a/test/shader_io/fragment_input_builtins.wgsl.expected.msl b/test/shader_io/fragment_input_builtins.wgsl.expected.msl
new file mode 100644
index 0000000..3e46c6f
--- /dev/null
+++ b/test/shader_io/fragment_input_builtins.wgsl.expected.msl
@@ -0,0 +1,22 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct tint_symbol_2 {
+ float4 position [[position]];
+ bool front_facing [[front_facing]];
+ uint sample_index [[sample_id]];
+ uint sample_mask [[sample_mask]];
+};
+
+fragment void tint_symbol(tint_symbol_2 tint_symbol_1 [[stage_in]]) {
+ float4 const position = tint_symbol_1.position;
+ bool const front_facing = tint_symbol_1.front_facing;
+ uint const sample_index = tint_symbol_1.sample_index;
+ uint const sample_mask = tint_symbol_1.sample_mask;
+ if (front_facing) {
+ float4 const foo = position;
+ uint const bar = (sample_index + sample_mask);
+ }
+ return;
+}
+
diff --git a/test/shader_io/fragment_input_builtins.wgsl.expected.spvasm b/test/shader_io/fragment_input_builtins.wgsl.expected.spvasm
new file mode 100644
index 0000000..b6e26bd
--- /dev/null
+++ b/test/shader_io/fragment_input_builtins.wgsl.expected.spvasm
@@ -0,0 +1,53 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 29
+; Schema: 0
+ OpCapability Shader
+ OpCapability SampleRateShading
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %main "main" %tint_symbol_1 %tint_symbol %tint_symbol_2 %tint_symbol_3
+ OpExecutionMode %main OriginUpperLeft
+ OpName %tint_symbol "tint_symbol"
+ OpName %tint_symbol_1 "tint_symbol_1"
+ OpName %tint_symbol_2 "tint_symbol_2"
+ OpName %tint_symbol_3 "tint_symbol_3"
+ OpName %main "main"
+ OpDecorate %tint_symbol BuiltIn FragCoord
+ OpDecorate %tint_symbol_1 BuiltIn FrontFacing
+ OpDecorate %tint_symbol_2 BuiltIn SampleId
+ OpDecorate %_arr_uint_uint_1 ArrayStride 4
+ OpDecorate %tint_symbol_3 BuiltIn SampleMask
+ %float = OpTypeFloat 32
+ %v4float = OpTypeVector %float 4
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%tint_symbol = OpVariable %_ptr_Input_v4float Input
+ %bool = OpTypeBool
+%_ptr_Input_bool = OpTypePointer Input %bool
+%tint_symbol_1 = OpVariable %_ptr_Input_bool Input
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%tint_symbol_2 = OpVariable %_ptr_Input_uint Input
+ %uint_1 = OpConstant %uint 1
+%_arr_uint_uint_1 = OpTypeArray %uint %uint_1
+%_ptr_Input__arr_uint_uint_1 = OpTypePointer Input %_arr_uint_uint_1
+%tint_symbol_3 = OpVariable %_ptr_Input__arr_uint_uint_1 Input
+ %void = OpTypeVoid
+ %15 = OpTypeFunction %void
+ %int = OpTypeInt 32 1
+ %int_0 = OpConstant %int 0
+ %main = OpFunction %void None %15
+ %18 = OpLabel
+ %19 = OpLoad %bool %tint_symbol_1
+ OpSelectionMerge %20 None
+ OpBranchConditional %19 %21 %20
+ %21 = OpLabel
+ %22 = OpLoad %v4float %tint_symbol
+ %23 = OpLoad %uint %tint_symbol_2
+ %26 = OpAccessChain %_ptr_Input_uint %tint_symbol_3 %int_0
+ %27 = OpLoad %uint %26
+ %28 = OpIAdd %uint %23 %27
+ OpBranch %20
+ %20 = OpLabel
+ OpReturn
+ OpFunctionEnd
diff --git a/test/shader_io/fragment_input_builtins.wgsl.expected.wgsl b/test/shader_io/fragment_input_builtins.wgsl.expected.wgsl
new file mode 100644
index 0000000..cfad6db
--- /dev/null
+++ b/test/shader_io/fragment_input_builtins.wgsl.expected.wgsl
@@ -0,0 +1,7 @@
+[[stage(fragment)]]
+fn main([[builtin(position)]] position : vec4<f32>, [[builtin(front_facing)]] front_facing : bool, [[builtin(sample_index)]] sample_index : u32, [[builtin(sample_mask)]] sample_mask : u32) {
+ if (front_facing) {
+ let foo : vec4<f32> = position;
+ let bar : u32 = (sample_index + sample_mask);
+ }
+}
diff --git a/test/shader_io/fragment_input_builtins_struct.wgsl b/test/shader_io/fragment_input_builtins_struct.wgsl
new file mode 100644
index 0000000..af9e0d3
--- /dev/null
+++ b/test/shader_io/fragment_input_builtins_struct.wgsl
@@ -0,0 +1,14 @@
+struct FragmentInputs {
+ [[builtin(position)]] position : vec4<f32>;
+ [[builtin(front_facing)]] front_facing : bool;
+ [[builtin(sample_index)]] sample_index : u32;
+ [[builtin(sample_mask)]] sample_mask : u32;
+};
+
+[[stage(fragment)]]
+fn main(inputs : FragmentInputs) {
+ if (inputs.front_facing) {
+ let foo : vec4<f32> = inputs.position;
+ let bar : u32 = inputs.sample_index + inputs.sample_mask;
+ }
+}
diff --git a/test/shader_io/fragment_input_builtins_struct.wgsl.expected.hlsl b/test/shader_io/fragment_input_builtins_struct.wgsl.expected.hlsl
new file mode 100644
index 0000000..21e09a5
--- /dev/null
+++ b/test/shader_io/fragment_input_builtins_struct.wgsl.expected.hlsl
@@ -0,0 +1,22 @@
+struct FragmentInputs {
+ float4 position;
+ bool front_facing;
+ uint sample_index;
+ uint sample_mask;
+};
+struct tint_symbol_1 {
+ float4 position : SV_Position;
+ bool front_facing : SV_IsFrontFace;
+ uint sample_index : SV_SampleIndex;
+ uint sample_mask : SV_Coverage;
+};
+
+void main(tint_symbol_1 tint_symbol) {
+ const FragmentInputs inputs = {tint_symbol.position, tint_symbol.front_facing, tint_symbol.sample_index, tint_symbol.sample_mask};
+ if (inputs.front_facing) {
+ const float4 foo = inputs.position;
+ const uint bar = (inputs.sample_index + inputs.sample_mask);
+ }
+ return;
+}
+
diff --git a/test/shader_io/fragment_input_builtins_struct.wgsl.expected.msl b/test/shader_io/fragment_input_builtins_struct.wgsl.expected.msl
new file mode 100644
index 0000000..5b5ed67
--- /dev/null
+++ b/test/shader_io/fragment_input_builtins_struct.wgsl.expected.msl
@@ -0,0 +1,25 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct FragmentInputs {
+ float4 position;
+ bool front_facing;
+ uint sample_index;
+ uint sample_mask;
+};
+struct tint_symbol_2 {
+ float4 position [[position]];
+ bool front_facing [[front_facing]];
+ uint sample_index [[sample_id]];
+ uint sample_mask [[sample_mask]];
+};
+
+fragment void tint_symbol(tint_symbol_2 tint_symbol_1 [[stage_in]]) {
+ FragmentInputs const inputs = {tint_symbol_1.position, tint_symbol_1.front_facing, tint_symbol_1.sample_index, tint_symbol_1.sample_mask};
+ if (inputs.front_facing) {
+ float4 const foo = inputs.position;
+ uint const bar = (inputs.sample_index + inputs.sample_mask);
+ }
+ return;
+}
+
diff --git a/test/shader_io/fragment_input_builtins_struct.wgsl.expected.spvasm b/test/shader_io/fragment_input_builtins_struct.wgsl.expected.spvasm
new file mode 100644
index 0000000..16ace31
--- /dev/null
+++ b/test/shader_io/fragment_input_builtins_struct.wgsl.expected.spvasm
@@ -0,0 +1,68 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 35
+; Schema: 0
+ OpCapability Shader
+ OpCapability SampleRateShading
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %main "main" %tint_symbol %tint_symbol_1 %tint_symbol_2 %tint_symbol_3
+ OpExecutionMode %main OriginUpperLeft
+ OpName %tint_symbol "tint_symbol"
+ OpName %tint_symbol_1 "tint_symbol_1"
+ OpName %tint_symbol_2 "tint_symbol_2"
+ OpName %tint_symbol_3 "tint_symbol_3"
+ OpName %main "main"
+ OpName %FragmentInputs "FragmentInputs"
+ OpMemberName %FragmentInputs 0 "position"
+ OpMemberName %FragmentInputs 1 "front_facing"
+ OpMemberName %FragmentInputs 2 "sample_index"
+ OpMemberName %FragmentInputs 3 "sample_mask"
+ OpDecorate %tint_symbol BuiltIn FragCoord
+ OpDecorate %tint_symbol_1 BuiltIn FrontFacing
+ OpDecorate %tint_symbol_2 BuiltIn SampleId
+ OpDecorate %_arr_uint_uint_1 ArrayStride 4
+ OpDecorate %tint_symbol_3 BuiltIn SampleMask
+ OpMemberDecorate %FragmentInputs 0 Offset 0
+ OpMemberDecorate %FragmentInputs 1 Offset 16
+ OpMemberDecorate %FragmentInputs 2 Offset 20
+ OpMemberDecorate %FragmentInputs 3 Offset 24
+ %float = OpTypeFloat 32
+ %v4float = OpTypeVector %float 4
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%tint_symbol = OpVariable %_ptr_Input_v4float Input
+ %bool = OpTypeBool
+%_ptr_Input_bool = OpTypePointer Input %bool
+%tint_symbol_1 = OpVariable %_ptr_Input_bool Input
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%tint_symbol_2 = OpVariable %_ptr_Input_uint Input
+ %uint_1 = OpConstant %uint 1
+%_arr_uint_uint_1 = OpTypeArray %uint %uint_1
+%_ptr_Input__arr_uint_uint_1 = OpTypePointer Input %_arr_uint_uint_1
+%tint_symbol_3 = OpVariable %_ptr_Input__arr_uint_uint_1 Input
+ %void = OpTypeVoid
+ %15 = OpTypeFunction %void
+%FragmentInputs = OpTypeStruct %v4float %bool %uint %uint
+ %int = OpTypeInt 32 1
+ %int_0 = OpConstant %int 0
+ %main = OpFunction %void None %15
+ %18 = OpLabel
+ %20 = OpLoad %v4float %tint_symbol
+ %21 = OpLoad %bool %tint_symbol_1
+ %22 = OpLoad %uint %tint_symbol_2
+ %25 = OpAccessChain %_ptr_Input_uint %tint_symbol_3 %int_0
+ %26 = OpLoad %uint %25
+ %27 = OpCompositeConstruct %FragmentInputs %20 %21 %22 %26
+ %28 = OpCompositeExtract %bool %27 1
+ OpSelectionMerge %29 None
+ OpBranchConditional %28 %30 %29
+ %30 = OpLabel
+ %31 = OpCompositeExtract %v4float %27 0
+ %32 = OpCompositeExtract %uint %27 2
+ %33 = OpCompositeExtract %uint %27 3
+ %34 = OpIAdd %uint %32 %33
+ OpBranch %29
+ %29 = OpLabel
+ OpReturn
+ OpFunctionEnd
diff --git a/test/shader_io/fragment_input_builtins_struct.wgsl.expected.wgsl b/test/shader_io/fragment_input_builtins_struct.wgsl.expected.wgsl
new file mode 100644
index 0000000..0cf1aeb
--- /dev/null
+++ b/test/shader_io/fragment_input_builtins_struct.wgsl.expected.wgsl
@@ -0,0 +1,18 @@
+struct FragmentInputs {
+ [[builtin(position)]]
+ position : vec4<f32>;
+ [[builtin(front_facing)]]
+ front_facing : bool;
+ [[builtin(sample_index)]]
+ sample_index : u32;
+ [[builtin(sample_mask)]]
+ sample_mask : u32;
+};
+
+[[stage(fragment)]]
+fn main(inputs : FragmentInputs) {
+ if (inputs.front_facing) {
+ let foo : vec4<f32> = inputs.position;
+ let bar : u32 = (inputs.sample_index + inputs.sample_mask);
+ }
+}
diff --git a/test/shader_io/fragment_input_locations.wgsl b/test/shader_io/fragment_input_locations.wgsl
new file mode 100644
index 0000000..09aa769
--- /dev/null
+++ b/test/shader_io/fragment_input_locations.wgsl
@@ -0,0 +1,12 @@
+[[stage(fragment)]]
+fn main(
+ [[location(0)]] loc0 : i32,
+ [[location(1)]] loc1 : u32,
+ [[location(2)]] loc2 : f32,
+ [[location(3)]] loc3 : vec4<f32>,
+) {
+ let i : i32 = loc0;
+ let u : u32 = loc1;
+ let f : f32 = loc2;
+ let v : vec4<f32> = loc3;
+}
diff --git a/test/shader_io/fragment_input_locations.wgsl.expected.hlsl b/test/shader_io/fragment_input_locations.wgsl.expected.hlsl
new file mode 100644
index 0000000..6f08c68
--- /dev/null
+++ b/test/shader_io/fragment_input_locations.wgsl.expected.hlsl
@@ -0,0 +1,19 @@
+struct tint_symbol_1 {
+ int loc0 : TEXCOORD0;
+ uint loc1 : TEXCOORD1;
+ float loc2 : TEXCOORD2;
+ float4 loc3 : TEXCOORD3;
+};
+
+void main(tint_symbol_1 tint_symbol) {
+ const int loc0 = tint_symbol.loc0;
+ const uint loc1 = tint_symbol.loc1;
+ const float loc2 = tint_symbol.loc2;
+ const float4 loc3 = tint_symbol.loc3;
+ const int i = loc0;
+ const uint u = loc1;
+ const float f = loc2;
+ const float4 v = loc3;
+ return;
+}
+
diff --git a/test/shader_io/fragment_input_locations.wgsl.expected.msl b/test/shader_io/fragment_input_locations.wgsl.expected.msl
new file mode 100644
index 0000000..c8014ad
--- /dev/null
+++ b/test/shader_io/fragment_input_locations.wgsl.expected.msl
@@ -0,0 +1,22 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct tint_symbol_2 {
+ int loc0 [[user(locn0)]];
+ uint loc1 [[user(locn1)]];
+ float loc2 [[user(locn2)]];
+ float4 loc3 [[user(locn3)]];
+};
+
+fragment void tint_symbol(tint_symbol_2 tint_symbol_1 [[stage_in]]) {
+ int const loc0 = tint_symbol_1.loc0;
+ uint const loc1 = tint_symbol_1.loc1;
+ float const loc2 = tint_symbol_1.loc2;
+ float4 const loc3 = tint_symbol_1.loc3;
+ int const i = loc0;
+ uint const u = loc1;
+ float const f = loc2;
+ float4 const v = loc3;
+ return;
+}
+
diff --git a/test/shader_io/fragment_input_locations.wgsl.expected.spvasm b/test/shader_io/fragment_input_locations.wgsl.expected.spvasm
new file mode 100644
index 0000000..98e3d29
--- /dev/null
+++ b/test/shader_io/fragment_input_locations.wgsl.expected.spvasm
@@ -0,0 +1,40 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 21
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %main "main" %tint_symbol %tint_symbol_1 %tint_symbol_2 %tint_symbol_3
+ OpExecutionMode %main OriginUpperLeft
+ OpName %tint_symbol "tint_symbol"
+ OpName %tint_symbol_1 "tint_symbol_1"
+ OpName %tint_symbol_2 "tint_symbol_2"
+ OpName %tint_symbol_3 "tint_symbol_3"
+ OpName %main "main"
+ OpDecorate %tint_symbol Location 0
+ OpDecorate %tint_symbol_1 Location 1
+ OpDecorate %tint_symbol_2 Location 2
+ OpDecorate %tint_symbol_3 Location 3
+ %int = OpTypeInt 32 1
+%_ptr_Input_int = OpTypePointer Input %int
+%tint_symbol = OpVariable %_ptr_Input_int Input
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%tint_symbol_1 = OpVariable %_ptr_Input_uint Input
+ %float = OpTypeFloat 32
+%_ptr_Input_float = OpTypePointer Input %float
+%tint_symbol_2 = OpVariable %_ptr_Input_float Input
+ %v4float = OpTypeVector %float 4
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%tint_symbol_3 = OpVariable %_ptr_Input_v4float Input
+ %void = OpTypeVoid
+ %13 = OpTypeFunction %void
+ %main = OpFunction %void None %13
+ %16 = OpLabel
+ %17 = OpLoad %int %tint_symbol
+ %18 = OpLoad %uint %tint_symbol_1
+ %19 = OpLoad %float %tint_symbol_2
+ %20 = OpLoad %v4float %tint_symbol_3
+ OpReturn
+ OpFunctionEnd
diff --git a/test/shader_io/fragment_input_locations.wgsl.expected.wgsl b/test/shader_io/fragment_input_locations.wgsl.expected.wgsl
new file mode 100644
index 0000000..2ab1394
--- /dev/null
+++ b/test/shader_io/fragment_input_locations.wgsl.expected.wgsl
@@ -0,0 +1,7 @@
+[[stage(fragment)]]
+fn main([[location(0)]] loc0 : i32, [[location(1)]] loc1 : u32, [[location(2)]] loc2 : f32, [[location(3)]] loc3 : vec4<f32>) {
+ let i : i32 = loc0;
+ let u : u32 = loc1;
+ let f : f32 = loc2;
+ let v : vec4<f32> = loc3;
+}
diff --git a/test/shader_io/fragment_input_locations_struct.wgsl b/test/shader_io/fragment_input_locations_struct.wgsl
new file mode 100644
index 0000000..710ded1
--- /dev/null
+++ b/test/shader_io/fragment_input_locations_struct.wgsl
@@ -0,0 +1,14 @@
+struct FragmentInputs {
+ [[location(0)]] loc0 : i32;
+ [[location(1)]] loc1 : u32;
+ [[location(2)]] loc2 : f32;
+ [[location(3)]] loc3 : vec4<f32>;
+};
+
+[[stage(fragment)]]
+fn main(inputs : FragmentInputs) {
+ let i : i32 = inputs.loc0;
+ let u : u32 = inputs.loc1;
+ let f : f32 = inputs.loc2;
+ let v : vec4<f32> = inputs.loc3;
+}
diff --git a/test/shader_io/fragment_input_locations_struct.wgsl.expected.hlsl b/test/shader_io/fragment_input_locations_struct.wgsl.expected.hlsl
new file mode 100644
index 0000000..8174496
--- /dev/null
+++ b/test/shader_io/fragment_input_locations_struct.wgsl.expected.hlsl
@@ -0,0 +1,22 @@
+struct FragmentInputs {
+ int loc0;
+ uint loc1;
+ float loc2;
+ float4 loc3;
+};
+struct tint_symbol_1 {
+ int loc0 : TEXCOORD0;
+ uint loc1 : TEXCOORD1;
+ float loc2 : TEXCOORD2;
+ float4 loc3 : TEXCOORD3;
+};
+
+void main(tint_symbol_1 tint_symbol) {
+ const FragmentInputs inputs = {tint_symbol.loc0, tint_symbol.loc1, tint_symbol.loc2, tint_symbol.loc3};
+ const int i = inputs.loc0;
+ const uint u = inputs.loc1;
+ const float f = inputs.loc2;
+ const float4 v = inputs.loc3;
+ return;
+}
+
diff --git a/test/shader_io/fragment_input_locations_struct.wgsl.expected.msl b/test/shader_io/fragment_input_locations_struct.wgsl.expected.msl
new file mode 100644
index 0000000..3250f3e
--- /dev/null
+++ b/test/shader_io/fragment_input_locations_struct.wgsl.expected.msl
@@ -0,0 +1,25 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct FragmentInputs {
+ int loc0;
+ uint loc1;
+ float loc2;
+ float4 loc3;
+};
+struct tint_symbol_2 {
+ int loc0 [[user(locn0)]];
+ uint loc1 [[user(locn1)]];
+ float loc2 [[user(locn2)]];
+ float4 loc3 [[user(locn3)]];
+};
+
+fragment void tint_symbol(tint_symbol_2 tint_symbol_1 [[stage_in]]) {
+ FragmentInputs const inputs = {tint_symbol_1.loc0, tint_symbol_1.loc1, tint_symbol_1.loc2, tint_symbol_1.loc3};
+ int const i = inputs.loc0;
+ uint const u = inputs.loc1;
+ float const f = inputs.loc2;
+ float4 const v = inputs.loc3;
+ return;
+}
+
diff --git a/test/shader_io/fragment_input_locations_struct.wgsl.expected.spvasm b/test/shader_io/fragment_input_locations_struct.wgsl.expected.spvasm
new file mode 100644
index 0000000..8088af5
--- /dev/null
+++ b/test/shader_io/fragment_input_locations_struct.wgsl.expected.spvasm
@@ -0,0 +1,55 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 27
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %main "main" %tint_symbol %tint_symbol_1 %tint_symbol_2 %tint_symbol_3
+ OpExecutionMode %main OriginUpperLeft
+ OpName %tint_symbol "tint_symbol"
+ OpName %tint_symbol_1 "tint_symbol_1"
+ OpName %tint_symbol_2 "tint_symbol_2"
+ OpName %tint_symbol_3 "tint_symbol_3"
+ OpName %main "main"
+ OpName %FragmentInputs "FragmentInputs"
+ OpMemberName %FragmentInputs 0 "loc0"
+ OpMemberName %FragmentInputs 1 "loc1"
+ OpMemberName %FragmentInputs 2 "loc2"
+ OpMemberName %FragmentInputs 3 "loc3"
+ OpDecorate %tint_symbol Location 0
+ OpDecorate %tint_symbol_1 Location 1
+ OpDecorate %tint_symbol_2 Location 2
+ OpDecorate %tint_symbol_3 Location 3
+ OpMemberDecorate %FragmentInputs 0 Offset 0
+ OpMemberDecorate %FragmentInputs 1 Offset 4
+ OpMemberDecorate %FragmentInputs 2 Offset 8
+ OpMemberDecorate %FragmentInputs 3 Offset 16
+ %int = OpTypeInt 32 1
+%_ptr_Input_int = OpTypePointer Input %int
+%tint_symbol = OpVariable %_ptr_Input_int Input
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%tint_symbol_1 = OpVariable %_ptr_Input_uint Input
+ %float = OpTypeFloat 32
+%_ptr_Input_float = OpTypePointer Input %float
+%tint_symbol_2 = OpVariable %_ptr_Input_float Input
+ %v4float = OpTypeVector %float 4
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%tint_symbol_3 = OpVariable %_ptr_Input_v4float Input
+ %void = OpTypeVoid
+ %13 = OpTypeFunction %void
+%FragmentInputs = OpTypeStruct %int %uint %float %v4float
+ %main = OpFunction %void None %13
+ %16 = OpLabel
+ %18 = OpLoad %int %tint_symbol
+ %19 = OpLoad %uint %tint_symbol_1
+ %20 = OpLoad %float %tint_symbol_2
+ %21 = OpLoad %v4float %tint_symbol_3
+ %22 = OpCompositeConstruct %FragmentInputs %18 %19 %20 %21
+ %23 = OpCompositeExtract %int %22 0
+ %24 = OpCompositeExtract %uint %22 1
+ %25 = OpCompositeExtract %float %22 2
+ %26 = OpCompositeExtract %v4float %22 3
+ OpReturn
+ OpFunctionEnd
diff --git a/test/shader_io/fragment_input_locations_struct.wgsl.expected.wgsl b/test/shader_io/fragment_input_locations_struct.wgsl.expected.wgsl
new file mode 100644
index 0000000..f5f3a8b
--- /dev/null
+++ b/test/shader_io/fragment_input_locations_struct.wgsl.expected.wgsl
@@ -0,0 +1,18 @@
+struct FragmentInputs {
+ [[location(0)]]
+ loc0 : i32;
+ [[location(1)]]
+ loc1 : u32;
+ [[location(2)]]
+ loc2 : f32;
+ [[location(3)]]
+ loc3 : vec4<f32>;
+};
+
+[[stage(fragment)]]
+fn main(inputs : FragmentInputs) {
+ let i : i32 = inputs.loc0;
+ let u : u32 = inputs.loc1;
+ let f : f32 = inputs.loc2;
+ let v : vec4<f32> = inputs.loc3;
+}
diff --git a/test/shader_io/fragment_input_mixed.wgsl b/test/shader_io/fragment_input_mixed.wgsl
new file mode 100644
index 0000000..d6864ee
--- /dev/null
+++ b/test/shader_io/fragment_input_mixed.wgsl
@@ -0,0 +1,27 @@
+struct FragmentInputs0 {
+ [[builtin(position)]] position : vec4<f32>;
+ [[location(0)]] loc0 : i32;
+};
+struct FragmentInputs1 {
+ [[location(3)]] loc3 : vec4<f32>;
+ [[builtin(sample_mask)]] sample_mask : u32;
+};
+
+[[stage(fragment)]]
+fn main(
+ inputs0 : FragmentInputs0,
+ [[builtin(front_facing)]] front_facing : bool,
+ [[location(1)]] loc1 : u32,
+ [[builtin(sample_index)]] sample_index : u32,
+ inputs1 : FragmentInputs1,
+ [[location(2)]] loc2 : f32,
+) {
+ if (front_facing) {
+ let foo : vec4<f32> = inputs0.position;
+ let bar : u32 = sample_index + inputs1.sample_mask;
+ let i : i32 = inputs0.loc0;
+ let u : u32 = loc1;
+ let f : f32 = loc2;
+ let v : vec4<f32> = inputs1.loc3;
+ }
+}
diff --git a/test/shader_io/fragment_input_mixed.wgsl.expected.hlsl b/test/shader_io/fragment_input_mixed.wgsl.expected.hlsl
new file mode 100644
index 0000000..d83e6cc
--- /dev/null
+++ b/test/shader_io/fragment_input_mixed.wgsl.expected.hlsl
@@ -0,0 +1,37 @@
+struct FragmentInputs0 {
+ float4 position;
+ int loc0;
+};
+struct FragmentInputs1 {
+ float4 loc3;
+ uint sample_mask;
+};
+struct tint_symbol_1 {
+ int loc0 : TEXCOORD0;
+ uint loc1 : TEXCOORD1;
+ float loc2 : TEXCOORD2;
+ float4 loc3 : TEXCOORD3;
+ float4 position : SV_Position;
+ bool front_facing : SV_IsFrontFace;
+ uint sample_index : SV_SampleIndex;
+ uint sample_mask : SV_Coverage;
+};
+
+void main(tint_symbol_1 tint_symbol) {
+ const FragmentInputs0 inputs0 = {tint_symbol.position, tint_symbol.loc0};
+ const bool front_facing = tint_symbol.front_facing;
+ const uint loc1 = tint_symbol.loc1;
+ const uint sample_index = tint_symbol.sample_index;
+ const FragmentInputs1 inputs1 = {tint_symbol.loc3, tint_symbol.sample_mask};
+ const float loc2 = tint_symbol.loc2;
+ if (front_facing) {
+ const float4 foo = inputs0.position;
+ const uint bar = (sample_index + inputs1.sample_mask);
+ const int i = inputs0.loc0;
+ const uint u = loc1;
+ const float f = loc2;
+ const float4 v = inputs1.loc3;
+ }
+ return;
+}
+
diff --git a/test/shader_io/fragment_input_mixed.wgsl.expected.msl b/test/shader_io/fragment_input_mixed.wgsl.expected.msl
new file mode 100644
index 0000000..a115991
--- /dev/null
+++ b/test/shader_io/fragment_input_mixed.wgsl.expected.msl
@@ -0,0 +1,40 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct FragmentInputs0 {
+ float4 position;
+ int loc0;
+};
+struct FragmentInputs1 {
+ float4 loc3;
+ uint sample_mask;
+};
+struct tint_symbol_2 {
+ int loc0 [[user(locn0)]];
+ uint loc1 [[user(locn1)]];
+ float loc2 [[user(locn2)]];
+ float4 loc3 [[user(locn3)]];
+ float4 position [[position]];
+ bool front_facing [[front_facing]];
+ uint sample_index [[sample_id]];
+ uint sample_mask [[sample_mask]];
+};
+
+fragment void tint_symbol(tint_symbol_2 tint_symbol_1 [[stage_in]]) {
+ FragmentInputs0 const inputs0 = {tint_symbol_1.position, tint_symbol_1.loc0};
+ bool const front_facing = tint_symbol_1.front_facing;
+ uint const loc1 = tint_symbol_1.loc1;
+ uint const sample_index = tint_symbol_1.sample_index;
+ FragmentInputs1 const inputs1 = {tint_symbol_1.loc3, tint_symbol_1.sample_mask};
+ float const loc2 = tint_symbol_1.loc2;
+ if (front_facing) {
+ float4 const foo = inputs0.position;
+ uint const bar = (sample_index + inputs1.sample_mask);
+ int const i = inputs0.loc0;
+ uint const u = loc1;
+ float const f = loc2;
+ float4 const v = inputs1.loc3;
+ }
+ return;
+}
+
diff --git a/test/shader_io/fragment_input_mixed.wgsl.expected.spvasm b/test/shader_io/fragment_input_mixed.wgsl.expected.spvasm
new file mode 100644
index 0000000..df5c0a7
--- /dev/null
+++ b/test/shader_io/fragment_input_mixed.wgsl.expected.spvasm
@@ -0,0 +1,89 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 47
+; Schema: 0
+ OpCapability Shader
+ OpCapability SampleRateShading
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %main "main" %tint_symbol %tint_symbol_1 %tint_symbol_6 %tint_symbol_7 %tint_symbol_3 %tint_symbol_5 %tint_symbol_4 %tint_symbol_9
+ OpExecutionMode %main OriginUpperLeft
+ OpName %tint_symbol "tint_symbol"
+ OpName %tint_symbol_1 "tint_symbol_1"
+ OpName %tint_symbol_3 "tint_symbol_3"
+ OpName %tint_symbol_4 "tint_symbol_4"
+ OpName %tint_symbol_5 "tint_symbol_5"
+ OpName %tint_symbol_6 "tint_symbol_6"
+ OpName %tint_symbol_7 "tint_symbol_7"
+ OpName %tint_symbol_9 "tint_symbol_9"
+ OpName %main "main"
+ OpName %FragmentInputs0 "FragmentInputs0"
+ OpMemberName %FragmentInputs0 0 "position"
+ OpMemberName %FragmentInputs0 1 "loc0"
+ OpName %FragmentInputs1 "FragmentInputs1"
+ OpMemberName %FragmentInputs1 0 "loc3"
+ OpMemberName %FragmentInputs1 1 "sample_mask"
+ OpDecorate %tint_symbol BuiltIn FragCoord
+ OpDecorate %tint_symbol_1 Location 0
+ OpDecorate %tint_symbol_3 BuiltIn FrontFacing
+ OpDecorate %tint_symbol_4 Location 1
+ OpDecorate %tint_symbol_5 BuiltIn SampleId
+ OpDecorate %tint_symbol_6 Location 3
+ OpDecorate %_arr_uint_uint_1 ArrayStride 4
+ OpDecorate %tint_symbol_7 BuiltIn SampleMask
+ OpDecorate %tint_symbol_9 Location 2
+ OpMemberDecorate %FragmentInputs0 0 Offset 0
+ OpMemberDecorate %FragmentInputs0 1 Offset 16
+ OpMemberDecorate %FragmentInputs1 0 Offset 0
+ OpMemberDecorate %FragmentInputs1 1 Offset 16
+ %float = OpTypeFloat 32
+ %v4float = OpTypeVector %float 4
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%tint_symbol = OpVariable %_ptr_Input_v4float Input
+ %int = OpTypeInt 32 1
+%_ptr_Input_int = OpTypePointer Input %int
+%tint_symbol_1 = OpVariable %_ptr_Input_int Input
+ %bool = OpTypeBool
+%_ptr_Input_bool = OpTypePointer Input %bool
+%tint_symbol_3 = OpVariable %_ptr_Input_bool Input
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%tint_symbol_4 = OpVariable %_ptr_Input_uint Input
+%tint_symbol_5 = OpVariable %_ptr_Input_uint Input
+%tint_symbol_6 = OpVariable %_ptr_Input_v4float Input
+ %uint_1 = OpConstant %uint 1
+%_arr_uint_uint_1 = OpTypeArray %uint %uint_1
+%_ptr_Input__arr_uint_uint_1 = OpTypePointer Input %_arr_uint_uint_1
+%tint_symbol_7 = OpVariable %_ptr_Input__arr_uint_uint_1 Input
+%_ptr_Input_float = OpTypePointer Input %float
+%tint_symbol_9 = OpVariable %_ptr_Input_float Input
+ %void = OpTypeVoid
+ %22 = OpTypeFunction %void
+%FragmentInputs0 = OpTypeStruct %v4float %int
+%FragmentInputs1 = OpTypeStruct %v4float %uint
+ %int_0 = OpConstant %int 0
+ %main = OpFunction %void None %22
+ %25 = OpLabel
+ %27 = OpLoad %v4float %tint_symbol
+ %28 = OpLoad %int %tint_symbol_1
+ %29 = OpCompositeConstruct %FragmentInputs0 %27 %28
+ %31 = OpLoad %v4float %tint_symbol_6
+ %33 = OpAccessChain %_ptr_Input_uint %tint_symbol_7 %int_0
+ %34 = OpLoad %uint %33
+ %35 = OpCompositeConstruct %FragmentInputs1 %31 %34
+ %36 = OpLoad %bool %tint_symbol_3
+ OpSelectionMerge %37 None
+ OpBranchConditional %36 %38 %37
+ %38 = OpLabel
+ %39 = OpCompositeExtract %v4float %29 0
+ %40 = OpLoad %uint %tint_symbol_5
+ %41 = OpCompositeExtract %uint %35 1
+ %42 = OpIAdd %uint %40 %41
+ %43 = OpCompositeExtract %int %29 1
+ %44 = OpLoad %uint %tint_symbol_4
+ %45 = OpLoad %float %tint_symbol_9
+ %46 = OpCompositeExtract %v4float %35 0
+ OpBranch %37
+ %37 = OpLabel
+ OpReturn
+ OpFunctionEnd
diff --git a/test/shader_io/fragment_input_mixed.wgsl.expected.wgsl b/test/shader_io/fragment_input_mixed.wgsl.expected.wgsl
new file mode 100644
index 0000000..afc2348
--- /dev/null
+++ b/test/shader_io/fragment_input_mixed.wgsl.expected.wgsl
@@ -0,0 +1,25 @@
+struct FragmentInputs0 {
+ [[builtin(position)]]
+ position : vec4<f32>;
+ [[location(0)]]
+ loc0 : i32;
+};
+
+struct FragmentInputs1 {
+ [[location(3)]]
+ loc3 : vec4<f32>;
+ [[builtin(sample_mask)]]
+ sample_mask : u32;
+};
+
+[[stage(fragment)]]
+fn main(inputs0 : FragmentInputs0, [[builtin(front_facing)]] front_facing : bool, [[location(1)]] loc1 : u32, [[builtin(sample_index)]] sample_index : u32, inputs1 : FragmentInputs1, [[location(2)]] loc2 : f32) {
+ if (front_facing) {
+ let foo : vec4<f32> = inputs0.position;
+ let bar : u32 = (sample_index + inputs1.sample_mask);
+ let i : i32 = inputs0.loc0;
+ let u : u32 = loc1;
+ let f : f32 = loc2;
+ let v : vec4<f32> = inputs1.loc3;
+ }
+}
diff --git a/test/shader_io/fragment_output_builtins.wgsl b/test/shader_io/fragment_output_builtins.wgsl
new file mode 100644
index 0000000..462cb77
--- /dev/null
+++ b/test/shader_io/fragment_output_builtins.wgsl
@@ -0,0 +1,9 @@
+[[stage(fragment)]]
+fn main1() -> [[builtin(frag_depth)]] f32 {
+ return 1.0;
+}
+
+[[stage(fragment)]]
+fn main2() -> [[builtin(sample_mask)]] u32 {
+ return 1u;
+}
diff --git a/test/shader_io/fragment_output_builtins.wgsl.expected.hlsl b/test/shader_io/fragment_output_builtins.wgsl.expected.hlsl
new file mode 100644
index 0000000..30309e5
--- /dev/null
+++ b/test/shader_io/fragment_output_builtins.wgsl.expected.hlsl
@@ -0,0 +1,17 @@
+struct tint_symbol {
+ float value : SV_Depth;
+};
+struct tint_symbol_1 {
+ uint value : SV_Coverage;
+};
+
+tint_symbol main1() {
+ const tint_symbol tint_symbol_2 = {1.0f};
+ return tint_symbol_2;
+}
+
+tint_symbol_1 main2() {
+ const tint_symbol_1 tint_symbol_3 = {1u};
+ return tint_symbol_3;
+}
+
diff --git a/test/shader_io/fragment_output_builtins.wgsl.expected.msl b/test/shader_io/fragment_output_builtins.wgsl.expected.msl
new file mode 100644
index 0000000..d56fd42
--- /dev/null
+++ b/test/shader_io/fragment_output_builtins.wgsl.expected.msl
@@ -0,0 +1,20 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct tint_symbol {
+ float value [[depth(any)]];
+};
+struct tint_symbol_1 {
+ uint value [[sample_mask]];
+};
+
+fragment tint_symbol main1() {
+ tint_symbol const tint_symbol_2 = {1.0f};
+ return tint_symbol_2;
+}
+
+fragment tint_symbol_1 main2() {
+ tint_symbol_1 const tint_symbol_3 = {1u};
+ return tint_symbol_3;
+}
+
diff --git a/test/shader_io/fragment_output_builtins.wgsl.expected.spvasm b/test/shader_io/fragment_output_builtins.wgsl.expected.spvasm
new file mode 100644
index 0000000..cf60151
--- /dev/null
+++ b/test/shader_io/fragment_output_builtins.wgsl.expected.spvasm
@@ -0,0 +1,64 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 32
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %main1 "main1" %tint_symbol_1
+ OpEntryPoint Fragment %main2 "main2" %tint_symbol_4
+ OpExecutionMode %main1 OriginUpperLeft
+ OpExecutionMode %main1 DepthReplacing
+ OpExecutionMode %main2 OriginUpperLeft
+ OpName %tint_symbol_1 "tint_symbol_1"
+ OpName %tint_symbol_4 "tint_symbol_4"
+ OpName %tint_symbol_2 "tint_symbol_2"
+ OpName %tint_symbol "tint_symbol"
+ OpName %main1 "main1"
+ OpName %tint_symbol_5 "tint_symbol_5"
+ OpName %tint_symbol_3 "tint_symbol_3"
+ OpName %main2 "main2"
+ OpDecorate %tint_symbol_1 BuiltIn FragDepth
+ OpDecorate %_arr_uint_uint_1 ArrayStride 4
+ OpDecorate %tint_symbol_4 BuiltIn SampleMask
+ %float = OpTypeFloat 32
+%_ptr_Output_float = OpTypePointer Output %float
+ %4 = OpConstantNull %float
+%tint_symbol_1 = OpVariable %_ptr_Output_float Output %4
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+%_arr_uint_uint_1 = OpTypeArray %uint %uint_1
+%_ptr_Output__arr_uint_uint_1 = OpTypePointer Output %_arr_uint_uint_1
+ %10 = OpConstantNull %_arr_uint_uint_1
+%tint_symbol_4 = OpVariable %_ptr_Output__arr_uint_uint_1 Output %10
+ %void = OpTypeVoid
+ %11 = OpTypeFunction %void %float
+ %16 = OpTypeFunction %void
+ %float_1 = OpConstant %float 1
+ %21 = OpTypeFunction %void %uint
+ %int = OpTypeInt 32 1
+ %int_0 = OpConstant %int 0
+%_ptr_Output_uint = OpTypePointer Output %uint
+%tint_symbol_2 = OpFunction %void None %11
+%tint_symbol = OpFunctionParameter %float
+ %15 = OpLabel
+ OpStore %tint_symbol_1 %tint_symbol
+ OpReturn
+ OpFunctionEnd
+ %main1 = OpFunction %void None %16
+ %18 = OpLabel
+ %19 = OpFunctionCall %void %tint_symbol_2 %float_1
+ OpReturn
+ OpFunctionEnd
+%tint_symbol_5 = OpFunction %void None %21
+%tint_symbol_3 = OpFunctionParameter %uint
+ %24 = OpLabel
+ %28 = OpAccessChain %_ptr_Output_uint %tint_symbol_4 %int_0
+ OpStore %28 %tint_symbol_3
+ OpReturn
+ OpFunctionEnd
+ %main2 = OpFunction %void None %16
+ %30 = OpLabel
+ %31 = OpFunctionCall %void %tint_symbol_5 %uint_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/shader_io/fragment_output_builtins.wgsl.expected.wgsl b/test/shader_io/fragment_output_builtins.wgsl.expected.wgsl
new file mode 100644
index 0000000..462cb77
--- /dev/null
+++ b/test/shader_io/fragment_output_builtins.wgsl.expected.wgsl
@@ -0,0 +1,9 @@
+[[stage(fragment)]]
+fn main1() -> [[builtin(frag_depth)]] f32 {
+ return 1.0;
+}
+
+[[stage(fragment)]]
+fn main2() -> [[builtin(sample_mask)]] u32 {
+ return 1u;
+}
diff --git a/test/shader_io/fragment_output_builtins_struct.wgsl b/test/shader_io/fragment_output_builtins_struct.wgsl
new file mode 100644
index 0000000..d7b37f8
--- /dev/null
+++ b/test/shader_io/fragment_output_builtins_struct.wgsl
@@ -0,0 +1,9 @@
+struct FragmentOutputs {
+ [[builtin(frag_depth)]] frag_depth : f32;
+ [[builtin(sample_mask)]] sample_mask : u32;
+};
+
+[[stage(fragment)]]
+fn main() -> FragmentOutputs {
+ return FragmentOutputs(1.0, 1u);
+}
diff --git a/test/shader_io/fragment_output_builtins_struct.wgsl.expected.hlsl b/test/shader_io/fragment_output_builtins_struct.wgsl.expected.hlsl
new file mode 100644
index 0000000..d266413
--- /dev/null
+++ b/test/shader_io/fragment_output_builtins_struct.wgsl.expected.hlsl
@@ -0,0 +1,15 @@
+struct FragmentOutputs {
+ float frag_depth;
+ uint sample_mask;
+};
+struct tint_symbol {
+ float frag_depth : SV_Depth;
+ uint sample_mask : SV_Coverage;
+};
+
+tint_symbol main() {
+ const FragmentOutputs tint_symbol_1 = {1.0f, 1u};
+ const tint_symbol tint_symbol_2 = {tint_symbol_1.frag_depth, tint_symbol_1.sample_mask};
+ return tint_symbol_2;
+}
+
diff --git a/test/shader_io/fragment_output_builtins_struct.wgsl.expected.msl b/test/shader_io/fragment_output_builtins_struct.wgsl.expected.msl
new file mode 100644
index 0000000..343945f
--- /dev/null
+++ b/test/shader_io/fragment_output_builtins_struct.wgsl.expected.msl
@@ -0,0 +1,18 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct FragmentOutputs {
+ float frag_depth;
+ uint sample_mask;
+};
+struct tint_symbol_1 {
+ float frag_depth [[depth(any)]];
+ uint sample_mask [[sample_mask]];
+};
+
+fragment tint_symbol_1 tint_symbol() {
+ FragmentOutputs const tint_symbol_2 = {1.0f, 1u};
+ tint_symbol_1 const tint_symbol_3 = {tint_symbol_2.frag_depth, tint_symbol_2.sample_mask};
+ return tint_symbol_3;
+}
+
diff --git a/test/shader_io/fragment_output_builtins_struct.wgsl.expected.spvasm b/test/shader_io/fragment_output_builtins_struct.wgsl.expected.spvasm
new file mode 100644
index 0000000..45f416d
--- /dev/null
+++ b/test/shader_io/fragment_output_builtins_struct.wgsl.expected.spvasm
@@ -0,0 +1,57 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 29
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %main "main" %tint_symbol_1 %tint_symbol_2
+ OpExecutionMode %main OriginUpperLeft
+ OpExecutionMode %main DepthReplacing
+ OpName %tint_symbol_1 "tint_symbol_1"
+ OpName %tint_symbol_2 "tint_symbol_2"
+ OpName %FragmentOutputs "FragmentOutputs"
+ OpMemberName %FragmentOutputs 0 "frag_depth"
+ OpMemberName %FragmentOutputs 1 "sample_mask"
+ OpName %tint_symbol_3 "tint_symbol_3"
+ OpName %tint_symbol "tint_symbol"
+ OpName %main "main"
+ OpDecorate %tint_symbol_1 BuiltIn FragDepth
+ OpDecorate %_arr_uint_uint_1 ArrayStride 4
+ OpDecorate %tint_symbol_2 BuiltIn SampleMask
+ OpMemberDecorate %FragmentOutputs 0 Offset 0
+ OpMemberDecorate %FragmentOutputs 1 Offset 4
+ %float = OpTypeFloat 32
+%_ptr_Output_float = OpTypePointer Output %float
+ %4 = OpConstantNull %float
+%tint_symbol_1 = OpVariable %_ptr_Output_float Output %4
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+%_arr_uint_uint_1 = OpTypeArray %uint %uint_1
+%_ptr_Output__arr_uint_uint_1 = OpTypePointer Output %_arr_uint_uint_1
+ %10 = OpConstantNull %_arr_uint_uint_1
+%tint_symbol_2 = OpVariable %_ptr_Output__arr_uint_uint_1 Output %10
+ %void = OpTypeVoid
+%FragmentOutputs = OpTypeStruct %float %uint
+ %11 = OpTypeFunction %void %FragmentOutputs
+ %int = OpTypeInt 32 1
+ %int_0 = OpConstant %int 0
+%_ptr_Output_uint = OpTypePointer Output %uint
+ %23 = OpTypeFunction %void
+ %float_1 = OpConstant %float 1
+ %28 = OpConstantComposite %FragmentOutputs %float_1 %uint_1
+%tint_symbol_3 = OpFunction %void None %11
+%tint_symbol = OpFunctionParameter %FragmentOutputs
+ %16 = OpLabel
+ %17 = OpCompositeExtract %float %tint_symbol 0
+ OpStore %tint_symbol_1 %17
+ %21 = OpAccessChain %_ptr_Output_uint %tint_symbol_2 %int_0
+ %22 = OpCompositeExtract %uint %tint_symbol 1
+ OpStore %21 %22
+ OpReturn
+ OpFunctionEnd
+ %main = OpFunction %void None %23
+ %25 = OpLabel
+ %26 = OpFunctionCall %void %tint_symbol_3 %28
+ OpReturn
+ OpFunctionEnd
diff --git a/test/shader_io/fragment_output_builtins_struct.wgsl.expected.wgsl b/test/shader_io/fragment_output_builtins_struct.wgsl.expected.wgsl
new file mode 100644
index 0000000..6617a26
--- /dev/null
+++ b/test/shader_io/fragment_output_builtins_struct.wgsl.expected.wgsl
@@ -0,0 +1,11 @@
+struct FragmentOutputs {
+ [[builtin(frag_depth)]]
+ frag_depth : f32;
+ [[builtin(sample_mask)]]
+ sample_mask : u32;
+};
+
+[[stage(fragment)]]
+fn main() -> FragmentOutputs {
+ return FragmentOutputs(1.0, 1u);
+}
diff --git a/test/shader_io/fragment_output_locations.wgsl b/test/shader_io/fragment_output_locations.wgsl
new file mode 100644
index 0000000..b5858e8
--- /dev/null
+++ b/test/shader_io/fragment_output_locations.wgsl
@@ -0,0 +1,19 @@
+[[stage(fragment)]]
+fn main0() -> [[location(0)]] i32 {
+ return 1;
+}
+
+[[stage(fragment)]]
+fn main1() -> [[location(1)]] u32 {
+ return 1u;
+}
+
+[[stage(fragment)]]
+fn main2() -> [[location(2)]] f32 {
+ return 1.0;
+}
+
+[[stage(fragment)]]
+fn main3() -> [[location(3)]] vec4<f32> {
+ return vec4<f32>(1.0, 2.0, 3.0, 4.0);
+}
diff --git a/test/shader_io/fragment_output_locations.wgsl.expected.hlsl b/test/shader_io/fragment_output_locations.wgsl.expected.hlsl
new file mode 100644
index 0000000..69f77e0
--- /dev/null
+++ b/test/shader_io/fragment_output_locations.wgsl.expected.hlsl
@@ -0,0 +1,33 @@
+struct tint_symbol {
+ int value : SV_Target0;
+};
+struct tint_symbol_1 {
+ uint value : SV_Target1;
+};
+struct tint_symbol_2 {
+ float value : SV_Target2;
+};
+struct tint_symbol_3 {
+ float4 value : SV_Target3;
+};
+
+tint_symbol main0() {
+ const tint_symbol tint_symbol_4 = {1};
+ return tint_symbol_4;
+}
+
+tint_symbol_1 main1() {
+ const tint_symbol_1 tint_symbol_5 = {1u};
+ return tint_symbol_5;
+}
+
+tint_symbol_2 main2() {
+ const tint_symbol_2 tint_symbol_6 = {1.0f};
+ return tint_symbol_6;
+}
+
+tint_symbol_3 main3() {
+ const tint_symbol_3 tint_symbol_7 = {float4(1.0f, 2.0f, 3.0f, 4.0f)};
+ return tint_symbol_7;
+}
+
diff --git a/test/shader_io/fragment_output_locations.wgsl.expected.msl b/test/shader_io/fragment_output_locations.wgsl.expected.msl
new file mode 100644
index 0000000..58191b0
--- /dev/null
+++ b/test/shader_io/fragment_output_locations.wgsl.expected.msl
@@ -0,0 +1,36 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct tint_symbol {
+ int value [[color(0)]];
+};
+struct tint_symbol_1 {
+ uint value [[color(1)]];
+};
+struct tint_symbol_2 {
+ float value [[color(2)]];
+};
+struct tint_symbol_3 {
+ float4 value [[color(3)]];
+};
+
+fragment tint_symbol main0() {
+ tint_symbol const tint_symbol_4 = {1};
+ return tint_symbol_4;
+}
+
+fragment tint_symbol_1 main1() {
+ tint_symbol_1 const tint_symbol_5 = {1u};
+ return tint_symbol_5;
+}
+
+fragment tint_symbol_2 main2() {
+ tint_symbol_2 const tint_symbol_6 = {1.0f};
+ return tint_symbol_6;
+}
+
+fragment tint_symbol_3 main3() {
+ tint_symbol_3 const tint_symbol_7 = {float4(1.0f, 2.0f, 3.0f, 4.0f)};
+ return tint_symbol_7;
+}
+
diff --git a/test/shader_io/fragment_output_locations.wgsl.expected.spvasm b/test/shader_io/fragment_output_locations.wgsl.expected.spvasm
new file mode 100644
index 0000000..ef873b5
--- /dev/null
+++ b/test/shader_io/fragment_output_locations.wgsl.expected.spvasm
@@ -0,0 +1,108 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 54
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %main0 "main0" %tint_symbol_1
+ OpEntryPoint Fragment %main1 "main1" %tint_symbol_4
+ OpEntryPoint Fragment %main2 "main2" %tint_symbol_7
+ OpEntryPoint Fragment %main3 "main3" %tint_symbol_10
+ OpExecutionMode %main0 OriginUpperLeft
+ OpExecutionMode %main1 OriginUpperLeft
+ OpExecutionMode %main2 OriginUpperLeft
+ OpExecutionMode %main3 OriginUpperLeft
+ OpName %tint_symbol_1 "tint_symbol_1"
+ OpName %tint_symbol_4 "tint_symbol_4"
+ OpName %tint_symbol_7 "tint_symbol_7"
+ OpName %tint_symbol_10 "tint_symbol_10"
+ OpName %tint_symbol_2 "tint_symbol_2"
+ OpName %tint_symbol "tint_symbol"
+ OpName %main0 "main0"
+ OpName %tint_symbol_5 "tint_symbol_5"
+ OpName %tint_symbol_3 "tint_symbol_3"
+ OpName %main1 "main1"
+ OpName %tint_symbol_8 "tint_symbol_8"
+ OpName %tint_symbol_6 "tint_symbol_6"
+ OpName %main2 "main2"
+ OpName %tint_symbol_11 "tint_symbol_11"
+ OpName %tint_symbol_9 "tint_symbol_9"
+ OpName %main3 "main3"
+ OpDecorate %tint_symbol_1 Location 0
+ OpDecorate %tint_symbol_4 Location 1
+ OpDecorate %tint_symbol_7 Location 2
+ OpDecorate %tint_symbol_10 Location 3
+ %int = OpTypeInt 32 1
+%_ptr_Output_int = OpTypePointer Output %int
+ %4 = OpConstantNull %int
+%tint_symbol_1 = OpVariable %_ptr_Output_int Output %4
+ %uint = OpTypeInt 32 0
+%_ptr_Output_uint = OpTypePointer Output %uint
+ %8 = OpConstantNull %uint
+%tint_symbol_4 = OpVariable %_ptr_Output_uint Output %8
+ %float = OpTypeFloat 32
+%_ptr_Output_float = OpTypePointer Output %float
+ %12 = OpConstantNull %float
+%tint_symbol_7 = OpVariable %_ptr_Output_float Output %12
+ %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+ %16 = OpConstantNull %v4float
+%tint_symbol_10 = OpVariable %_ptr_Output_v4float Output %16
+ %void = OpTypeVoid
+ %17 = OpTypeFunction %void %int
+ %22 = OpTypeFunction %void
+ %int_1 = OpConstant %int 1
+ %27 = OpTypeFunction %void %uint
+ %uint_1 = OpConstant %uint 1
+ %35 = OpTypeFunction %void %float
+ %float_1 = OpConstant %float 1
+ %43 = OpTypeFunction %void %v4float
+ %float_2 = OpConstant %float 2
+ %float_3 = OpConstant %float 3
+ %float_4 = OpConstant %float 4
+ %53 = OpConstantComposite %v4float %float_1 %float_2 %float_3 %float_4
+%tint_symbol_2 = OpFunction %void None %17
+%tint_symbol = OpFunctionParameter %int
+ %21 = OpLabel
+ OpStore %tint_symbol_1 %tint_symbol
+ OpReturn
+ OpFunctionEnd
+ %main0 = OpFunction %void None %22
+ %24 = OpLabel
+ %25 = OpFunctionCall %void %tint_symbol_2 %int_1
+ OpReturn
+ OpFunctionEnd
+%tint_symbol_5 = OpFunction %void None %27
+%tint_symbol_3 = OpFunctionParameter %uint
+ %30 = OpLabel
+ OpStore %tint_symbol_4 %tint_symbol_3
+ OpReturn
+ OpFunctionEnd
+ %main1 = OpFunction %void None %22
+ %32 = OpLabel
+ %33 = OpFunctionCall %void %tint_symbol_5 %uint_1
+ OpReturn
+ OpFunctionEnd
+%tint_symbol_8 = OpFunction %void None %35
+%tint_symbol_6 = OpFunctionParameter %float
+ %38 = OpLabel
+ OpStore %tint_symbol_7 %tint_symbol_6
+ OpReturn
+ OpFunctionEnd
+ %main2 = OpFunction %void None %22
+ %40 = OpLabel
+ %41 = OpFunctionCall %void %tint_symbol_8 %float_1
+ OpReturn
+ OpFunctionEnd
+%tint_symbol_11 = OpFunction %void None %43
+%tint_symbol_9 = OpFunctionParameter %v4float
+ %46 = OpLabel
+ OpStore %tint_symbol_10 %tint_symbol_9
+ OpReturn
+ OpFunctionEnd
+ %main3 = OpFunction %void None %22
+ %48 = OpLabel
+ %49 = OpFunctionCall %void %tint_symbol_11 %53
+ OpReturn
+ OpFunctionEnd
diff --git a/test/shader_io/fragment_output_locations.wgsl.expected.wgsl b/test/shader_io/fragment_output_locations.wgsl.expected.wgsl
new file mode 100644
index 0000000..b5858e8
--- /dev/null
+++ b/test/shader_io/fragment_output_locations.wgsl.expected.wgsl
@@ -0,0 +1,19 @@
+[[stage(fragment)]]
+fn main0() -> [[location(0)]] i32 {
+ return 1;
+}
+
+[[stage(fragment)]]
+fn main1() -> [[location(1)]] u32 {
+ return 1u;
+}
+
+[[stage(fragment)]]
+fn main2() -> [[location(2)]] f32 {
+ return 1.0;
+}
+
+[[stage(fragment)]]
+fn main3() -> [[location(3)]] vec4<f32> {
+ return vec4<f32>(1.0, 2.0, 3.0, 4.0);
+}
diff --git a/test/shader_io/fragment_output_locations_struct.wgsl b/test/shader_io/fragment_output_locations_struct.wgsl
new file mode 100644
index 0000000..c196843
--- /dev/null
+++ b/test/shader_io/fragment_output_locations_struct.wgsl
@@ -0,0 +1,11 @@
+struct FragmentOutputs {
+ [[location(0)]] loc0 : i32;
+ [[location(1)]] loc1 : u32;
+ [[location(2)]] loc2 : f32;
+ [[location(3)]] loc3 : vec4<f32>;
+};
+
+[[stage(fragment)]]
+fn main() -> FragmentOutputs {
+ return FragmentOutputs(1, 1u, 1.0, vec4<f32>(1.0, 2.0, 3.0, 4.0));
+}
diff --git a/test/shader_io/fragment_output_locations_struct.wgsl.expected.hlsl b/test/shader_io/fragment_output_locations_struct.wgsl.expected.hlsl
new file mode 100644
index 0000000..b399bc2
--- /dev/null
+++ b/test/shader_io/fragment_output_locations_struct.wgsl.expected.hlsl
@@ -0,0 +1,19 @@
+struct FragmentOutputs {
+ int loc0;
+ uint loc1;
+ float loc2;
+ float4 loc3;
+};
+struct tint_symbol {
+ int loc0 : SV_Target0;
+ uint loc1 : SV_Target1;
+ float loc2 : SV_Target2;
+ float4 loc3 : SV_Target3;
+};
+
+tint_symbol main() {
+ const FragmentOutputs tint_symbol_1 = {1, 1u, 1.0f, float4(1.0f, 2.0f, 3.0f, 4.0f)};
+ const tint_symbol tint_symbol_2 = {tint_symbol_1.loc0, tint_symbol_1.loc1, tint_symbol_1.loc2, tint_symbol_1.loc3};
+ return tint_symbol_2;
+}
+
diff --git a/test/shader_io/fragment_output_locations_struct.wgsl.expected.msl b/test/shader_io/fragment_output_locations_struct.wgsl.expected.msl
new file mode 100644
index 0000000..4e1b359
--- /dev/null
+++ b/test/shader_io/fragment_output_locations_struct.wgsl.expected.msl
@@ -0,0 +1,22 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct FragmentOutputs {
+ int loc0;
+ uint loc1;
+ float loc2;
+ float4 loc3;
+};
+struct tint_symbol_1 {
+ int loc0 [[color(0)]];
+ uint loc1 [[color(1)]];
+ float loc2 [[color(2)]];
+ float4 loc3 [[color(3)]];
+};
+
+fragment tint_symbol_1 tint_symbol() {
+ FragmentOutputs const tint_symbol_2 = {1, 1u, 1.0f, float4(1.0f, 2.0f, 3.0f, 4.0f)};
+ tint_symbol_1 const tint_symbol_3 = {tint_symbol_2.loc0, tint_symbol_2.loc1, tint_symbol_2.loc2, tint_symbol_2.loc3};
+ return tint_symbol_3;
+}
+
diff --git a/test/shader_io/fragment_output_locations_struct.wgsl.expected.spvasm b/test/shader_io/fragment_output_locations_struct.wgsl.expected.spvasm
new file mode 100644
index 0000000..9ad60b7
--- /dev/null
+++ b/test/shader_io/fragment_output_locations_struct.wgsl.expected.spvasm
@@ -0,0 +1,75 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 39
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %main "main" %tint_symbol_1 %tint_symbol_2 %tint_symbol_3 %tint_symbol_4
+ OpExecutionMode %main OriginUpperLeft
+ OpName %tint_symbol_1 "tint_symbol_1"
+ OpName %tint_symbol_2 "tint_symbol_2"
+ OpName %tint_symbol_3 "tint_symbol_3"
+ OpName %tint_symbol_4 "tint_symbol_4"
+ OpName %FragmentOutputs "FragmentOutputs"
+ OpMemberName %FragmentOutputs 0 "loc0"
+ OpMemberName %FragmentOutputs 1 "loc1"
+ OpMemberName %FragmentOutputs 2 "loc2"
+ OpMemberName %FragmentOutputs 3 "loc3"
+ OpName %tint_symbol_5 "tint_symbol_5"
+ OpName %tint_symbol "tint_symbol"
+ OpName %main "main"
+ OpDecorate %tint_symbol_1 Location 0
+ OpDecorate %tint_symbol_2 Location 1
+ OpDecorate %tint_symbol_3 Location 2
+ OpDecorate %tint_symbol_4 Location 3
+ OpMemberDecorate %FragmentOutputs 0 Offset 0
+ OpMemberDecorate %FragmentOutputs 1 Offset 4
+ OpMemberDecorate %FragmentOutputs 2 Offset 8
+ OpMemberDecorate %FragmentOutputs 3 Offset 16
+ %int = OpTypeInt 32 1
+%_ptr_Output_int = OpTypePointer Output %int
+ %4 = OpConstantNull %int
+%tint_symbol_1 = OpVariable %_ptr_Output_int Output %4
+ %uint = OpTypeInt 32 0
+%_ptr_Output_uint = OpTypePointer Output %uint
+ %8 = OpConstantNull %uint
+%tint_symbol_2 = OpVariable %_ptr_Output_uint Output %8
+ %float = OpTypeFloat 32
+%_ptr_Output_float = OpTypePointer Output %float
+ %12 = OpConstantNull %float
+%tint_symbol_3 = OpVariable %_ptr_Output_float Output %12
+ %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+ %16 = OpConstantNull %v4float
+%tint_symbol_4 = OpVariable %_ptr_Output_v4float Output %16
+ %void = OpTypeVoid
+%FragmentOutputs = OpTypeStruct %int %uint %float %v4float
+ %17 = OpTypeFunction %void %FragmentOutputs
+ %27 = OpTypeFunction %void
+ %int_1 = OpConstant %int 1
+ %uint_1 = OpConstant %uint 1
+ %float_1 = OpConstant %float 1
+ %float_2 = OpConstant %float 2
+ %float_3 = OpConstant %float 3
+ %float_4 = OpConstant %float 4
+ %37 = OpConstantComposite %v4float %float_1 %float_2 %float_3 %float_4
+ %38 = OpConstantComposite %FragmentOutputs %int_1 %uint_1 %float_1 %37
+%tint_symbol_5 = OpFunction %void None %17
+%tint_symbol = OpFunctionParameter %FragmentOutputs
+ %22 = OpLabel
+ %23 = OpCompositeExtract %int %tint_symbol 0
+ OpStore %tint_symbol_1 %23
+ %24 = OpCompositeExtract %uint %tint_symbol 1
+ OpStore %tint_symbol_2 %24
+ %25 = OpCompositeExtract %float %tint_symbol 2
+ OpStore %tint_symbol_3 %25
+ %26 = OpCompositeExtract %v4float %tint_symbol 3
+ OpStore %tint_symbol_4 %26
+ OpReturn
+ OpFunctionEnd
+ %main = OpFunction %void None %27
+ %29 = OpLabel
+ %30 = OpFunctionCall %void %tint_symbol_5 %38
+ OpReturn
+ OpFunctionEnd
diff --git a/test/shader_io/fragment_output_locations_struct.wgsl.expected.wgsl b/test/shader_io/fragment_output_locations_struct.wgsl.expected.wgsl
new file mode 100644
index 0000000..879805c
--- /dev/null
+++ b/test/shader_io/fragment_output_locations_struct.wgsl.expected.wgsl
@@ -0,0 +1,15 @@
+struct FragmentOutputs {
+ [[location(0)]]
+ loc0 : i32;
+ [[location(1)]]
+ loc1 : u32;
+ [[location(2)]]
+ loc2 : f32;
+ [[location(3)]]
+ loc3 : vec4<f32>;
+};
+
+[[stage(fragment)]]
+fn main() -> FragmentOutputs {
+ return FragmentOutputs(1, 1u, 1.0, vec4<f32>(1.0, 2.0, 3.0, 4.0));
+}
diff --git a/test/shader_io/fragment_output_mixed.wgsl b/test/shader_io/fragment_output_mixed.wgsl
new file mode 100644
index 0000000..29e5108
--- /dev/null
+++ b/test/shader_io/fragment_output_mixed.wgsl
@@ -0,0 +1,13 @@
+struct FragmentOutputs {
+ [[location(0)]] loc0 : i32;
+ [[builtin(frag_depth)]] frag_depth : f32;
+ [[location(1)]] loc1 : u32;
+ [[location(2)]] loc2 : f32;
+ [[builtin(sample_mask)]] sample_mask : u32;
+ [[location(3)]] loc3 : vec4<f32>;
+};
+
+[[stage(fragment)]]
+fn main() -> FragmentOutputs {
+ return FragmentOutputs(1, 2.0, 1u, 1.0, 2u, vec4<f32>(1.0, 2.0, 3.0, 4.0));
+}
diff --git a/test/shader_io/fragment_output_mixed.wgsl.expected.hlsl b/test/shader_io/fragment_output_mixed.wgsl.expected.hlsl
new file mode 100644
index 0000000..73f00c5
--- /dev/null
+++ b/test/shader_io/fragment_output_mixed.wgsl.expected.hlsl
@@ -0,0 +1,23 @@
+struct FragmentOutputs {
+ int loc0;
+ float frag_depth;
+ uint loc1;
+ float loc2;
+ uint sample_mask;
+ float4 loc3;
+};
+struct tint_symbol {
+ int loc0 : SV_Target0;
+ uint loc1 : SV_Target1;
+ float loc2 : SV_Target2;
+ float4 loc3 : SV_Target3;
+ float frag_depth : SV_Depth;
+ uint sample_mask : SV_Coverage;
+};
+
+tint_symbol main() {
+ const FragmentOutputs tint_symbol_1 = {1, 2.0f, 1u, 1.0f, 2u, float4(1.0f, 2.0f, 3.0f, 4.0f)};
+ const tint_symbol tint_symbol_2 = {tint_symbol_1.loc0, tint_symbol_1.loc1, tint_symbol_1.loc2, tint_symbol_1.loc3, tint_symbol_1.frag_depth, tint_symbol_1.sample_mask};
+ return tint_symbol_2;
+}
+
diff --git a/test/shader_io/fragment_output_mixed.wgsl.expected.msl b/test/shader_io/fragment_output_mixed.wgsl.expected.msl
new file mode 100644
index 0000000..a6e3359
--- /dev/null
+++ b/test/shader_io/fragment_output_mixed.wgsl.expected.msl
@@ -0,0 +1,26 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct FragmentOutputs {
+ int loc0;
+ float frag_depth;
+ uint loc1;
+ float loc2;
+ uint sample_mask;
+ float4 loc3;
+};
+struct tint_symbol_1 {
+ int loc0 [[color(0)]];
+ uint loc1 [[color(1)]];
+ float loc2 [[color(2)]];
+ float4 loc3 [[color(3)]];
+ float frag_depth [[depth(any)]];
+ uint sample_mask [[sample_mask]];
+};
+
+fragment tint_symbol_1 tint_symbol() {
+ FragmentOutputs const tint_symbol_2 = {1, 2.0f, 1u, 1.0f, 2u, float4(1.0f, 2.0f, 3.0f, 4.0f)};
+ tint_symbol_1 const tint_symbol_3 = {tint_symbol_2.loc0, tint_symbol_2.loc1, tint_symbol_2.loc2, tint_symbol_2.loc3, tint_symbol_2.frag_depth, tint_symbol_2.sample_mask};
+ return tint_symbol_3;
+}
+
diff --git a/test/shader_io/fragment_output_mixed.wgsl.expected.spvasm b/test/shader_io/fragment_output_mixed.wgsl.expected.spvasm
new file mode 100644
index 0000000..164fdf0
--- /dev/null
+++ b/test/shader_io/fragment_output_mixed.wgsl.expected.spvasm
@@ -0,0 +1,97 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 49
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %main "main" %tint_symbol_1 %tint_symbol_2 %tint_symbol_3 %tint_symbol_4 %tint_symbol_5 %tint_symbol_6
+ OpExecutionMode %main OriginUpperLeft
+ OpExecutionMode %main DepthReplacing
+ OpName %tint_symbol_1 "tint_symbol_1"
+ OpName %tint_symbol_2 "tint_symbol_2"
+ OpName %tint_symbol_3 "tint_symbol_3"
+ OpName %tint_symbol_4 "tint_symbol_4"
+ OpName %tint_symbol_5 "tint_symbol_5"
+ OpName %tint_symbol_6 "tint_symbol_6"
+ OpName %FragmentOutputs "FragmentOutputs"
+ OpMemberName %FragmentOutputs 0 "loc0"
+ OpMemberName %FragmentOutputs 1 "frag_depth"
+ OpMemberName %FragmentOutputs 2 "loc1"
+ OpMemberName %FragmentOutputs 3 "loc2"
+ OpMemberName %FragmentOutputs 4 "sample_mask"
+ OpMemberName %FragmentOutputs 5 "loc3"
+ OpName %tint_symbol_7 "tint_symbol_7"
+ OpName %tint_symbol "tint_symbol"
+ OpName %main "main"
+ OpDecorate %tint_symbol_1 Location 0
+ OpDecorate %tint_symbol_2 BuiltIn FragDepth
+ OpDecorate %tint_symbol_3 Location 1
+ OpDecorate %tint_symbol_4 Location 2
+ OpDecorate %_arr_uint_uint_1 ArrayStride 4
+ OpDecorate %tint_symbol_5 BuiltIn SampleMask
+ OpDecorate %tint_symbol_6 Location 3
+ OpMemberDecorate %FragmentOutputs 0 Offset 0
+ OpMemberDecorate %FragmentOutputs 1 Offset 4
+ OpMemberDecorate %FragmentOutputs 2 Offset 8
+ OpMemberDecorate %FragmentOutputs 3 Offset 12
+ OpMemberDecorate %FragmentOutputs 4 Offset 16
+ OpMemberDecorate %FragmentOutputs 5 Offset 32
+ %int = OpTypeInt 32 1
+%_ptr_Output_int = OpTypePointer Output %int
+ %4 = OpConstantNull %int
+%tint_symbol_1 = OpVariable %_ptr_Output_int Output %4
+ %float = OpTypeFloat 32
+%_ptr_Output_float = OpTypePointer Output %float
+ %8 = OpConstantNull %float
+%tint_symbol_2 = OpVariable %_ptr_Output_float Output %8
+ %uint = OpTypeInt 32 0
+%_ptr_Output_uint = OpTypePointer Output %uint
+ %12 = OpConstantNull %uint
+%tint_symbol_3 = OpVariable %_ptr_Output_uint Output %12
+%tint_symbol_4 = OpVariable %_ptr_Output_float Output %8
+ %uint_1 = OpConstant %uint 1
+%_arr_uint_uint_1 = OpTypeArray %uint %uint_1
+%_ptr_Output__arr_uint_uint_1 = OpTypePointer Output %_arr_uint_uint_1
+ %18 = OpConstantNull %_arr_uint_uint_1
+%tint_symbol_5 = OpVariable %_ptr_Output__arr_uint_uint_1 Output %18
+ %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+ %22 = OpConstantNull %v4float
+%tint_symbol_6 = OpVariable %_ptr_Output_v4float Output %22
+ %void = OpTypeVoid
+%FragmentOutputs = OpTypeStruct %int %float %uint %float %uint %v4float
+ %23 = OpTypeFunction %void %FragmentOutputs
+ %int_0 = OpConstant %int 0
+ %37 = OpTypeFunction %void
+ %int_1 = OpConstant %int 1
+ %float_2 = OpConstant %float 2
+ %float_1 = OpConstant %float 1
+ %uint_2 = OpConstant %uint 2
+ %float_3 = OpConstant %float 3
+ %float_4 = OpConstant %float 4
+ %47 = OpConstantComposite %v4float %float_1 %float_2 %float_3 %float_4
+ %48 = OpConstantComposite %FragmentOutputs %int_1 %float_2 %uint_1 %float_1 %uint_2 %47
+%tint_symbol_7 = OpFunction %void None %23
+%tint_symbol = OpFunctionParameter %FragmentOutputs
+ %28 = OpLabel
+ %29 = OpCompositeExtract %int %tint_symbol 0
+ OpStore %tint_symbol_1 %29
+ %30 = OpCompositeExtract %float %tint_symbol 1
+ OpStore %tint_symbol_2 %30
+ %31 = OpCompositeExtract %uint %tint_symbol 2
+ OpStore %tint_symbol_3 %31
+ %32 = OpCompositeExtract %float %tint_symbol 3
+ OpStore %tint_symbol_4 %32
+ %34 = OpAccessChain %_ptr_Output_uint %tint_symbol_5 %int_0
+ %35 = OpCompositeExtract %uint %tint_symbol 4
+ OpStore %34 %35
+ %36 = OpCompositeExtract %v4float %tint_symbol 5
+ OpStore %tint_symbol_6 %36
+ OpReturn
+ OpFunctionEnd
+ %main = OpFunction %void None %37
+ %39 = OpLabel
+ %40 = OpFunctionCall %void %tint_symbol_7 %48
+ OpReturn
+ OpFunctionEnd
diff --git a/test/shader_io/fragment_output_mixed.wgsl.expected.wgsl b/test/shader_io/fragment_output_mixed.wgsl.expected.wgsl
new file mode 100644
index 0000000..3fb401c
--- /dev/null
+++ b/test/shader_io/fragment_output_mixed.wgsl.expected.wgsl
@@ -0,0 +1,19 @@
+struct FragmentOutputs {
+ [[location(0)]]
+ loc0 : i32;
+ [[builtin(frag_depth)]]
+ frag_depth : f32;
+ [[location(1)]]
+ loc1 : u32;
+ [[location(2)]]
+ loc2 : f32;
+ [[builtin(sample_mask)]]
+ sample_mask : u32;
+ [[location(3)]]
+ loc3 : vec4<f32>;
+};
+
+[[stage(fragment)]]
+fn main() -> FragmentOutputs {
+ return FragmentOutputs(1, 2.0, 1u, 1.0, 2u, vec4<f32>(1.0, 2.0, 3.0, 4.0));
+}
diff --git a/test/shader_io/shared_struct_different_stages.wgsl b/test/shader_io/shared_struct_different_stages.wgsl
new file mode 100644
index 0000000..802ce43
--- /dev/null
+++ b/test/shader_io/shared_struct_different_stages.wgsl
@@ -0,0 +1,16 @@
+struct Interface {
+ [[location(1)]] col1 : f32;
+ [[location(2)]] col2 : f32;
+ [[builtin(position)]] pos : vec4<f32>;
+};
+
+[[stage(vertex)]]
+fn vert_main() -> Interface {
+ return Interface(0.4, 0.6, vec4<f32>());
+}
+
+[[stage(fragment)]]
+fn frag_main(colors : Interface) {
+ let r : f32 = colors.col1;
+ let g : f32 = colors.col2;
+}
diff --git a/test/shader_io/shared_struct_different_stages.wgsl.expected.hlsl b/test/shader_io/shared_struct_different_stages.wgsl.expected.hlsl
new file mode 100644
index 0000000..f15cb86
--- /dev/null
+++ b/test/shader_io/shared_struct_different_stages.wgsl.expected.hlsl
@@ -0,0 +1,29 @@
+struct Interface {
+ float col1;
+ float col2;
+ float4 pos;
+};
+struct tint_symbol {
+ float col1 : TEXCOORD1;
+ float col2 : TEXCOORD2;
+ float4 pos : SV_Position;
+};
+struct tint_symbol_3 {
+ float col1 : TEXCOORD1;
+ float col2 : TEXCOORD2;
+ float4 pos : SV_Position;
+};
+
+tint_symbol vert_main() {
+ const Interface tint_symbol_1 = {0.400000006f, 0.600000024f, float4(0.0f, 0.0f, 0.0f, 0.0f)};
+ const tint_symbol tint_symbol_4 = {tint_symbol_1.col1, tint_symbol_1.col2, tint_symbol_1.pos};
+ return tint_symbol_4;
+}
+
+void frag_main(tint_symbol_3 tint_symbol_2) {
+ const Interface colors = {tint_symbol_2.col1, tint_symbol_2.col2, tint_symbol_2.pos};
+ const float r = colors.col1;
+ const float g = colors.col2;
+ return;
+}
+
diff --git a/test/shader_io/shared_struct_different_stages.wgsl.expected.msl b/test/shader_io/shared_struct_different_stages.wgsl.expected.msl
new file mode 100644
index 0000000..f303dc0
--- /dev/null
+++ b/test/shader_io/shared_struct_different_stages.wgsl.expected.msl
@@ -0,0 +1,32 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct Interface {
+ float col1;
+ float col2;
+ float4 pos;
+};
+struct tint_symbol {
+ float col1 [[user(locn1)]];
+ float col2 [[user(locn2)]];
+ float4 pos [[position]];
+};
+struct tint_symbol_3 {
+ float col1 [[user(locn1)]];
+ float col2 [[user(locn2)]];
+ float4 pos [[position]];
+};
+
+vertex tint_symbol vert_main() {
+ Interface const tint_symbol_1 = {0.400000006f, 0.600000024f, float4()};
+ tint_symbol const tint_symbol_4 = {tint_symbol_1.col1, tint_symbol_1.col2, tint_symbol_1.pos};
+ return tint_symbol_4;
+}
+
+fragment void frag_main(tint_symbol_3 tint_symbol_2 [[stage_in]]) {
+ Interface const colors = {tint_symbol_2.col1, tint_symbol_2.col2, tint_symbol_2.pos};
+ float const r = colors.col1;
+ float const g = colors.col2;
+ return;
+}
+
diff --git a/test/shader_io/shared_struct_different_stages.wgsl.expected.spvasm b/test/shader_io/shared_struct_different_stages.wgsl.expected.spvasm
new file mode 100644
index 0000000..9c505c1
--- /dev/null
+++ b/test/shader_io/shared_struct_different_stages.wgsl.expected.spvasm
@@ -0,0 +1,85 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 41
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Vertex %vert_main "vert_main" %tint_pointsize %tint_symbol_1 %tint_symbol_2 %tint_symbol_3
+ OpEntryPoint Fragment %frag_main "frag_main" %tint_symbol_5 %tint_symbol_6 %tint_symbol_7
+ OpExecutionMode %frag_main OriginUpperLeft
+ OpName %tint_pointsize "tint_pointsize"
+ OpName %tint_symbol_1 "tint_symbol_1"
+ OpName %tint_symbol_2 "tint_symbol_2"
+ OpName %tint_symbol_3 "tint_symbol_3"
+ OpName %tint_symbol_5 "tint_symbol_5"
+ OpName %tint_symbol_6 "tint_symbol_6"
+ OpName %tint_symbol_7 "tint_symbol_7"
+ OpName %Interface "Interface"
+ OpMemberName %Interface 0 "col1"
+ OpMemberName %Interface 1 "col2"
+ OpMemberName %Interface 2 "pos"
+ OpName %tint_symbol_4 "tint_symbol_4"
+ OpName %tint_symbol "tint_symbol"
+ OpName %vert_main "vert_main"
+ OpName %frag_main "frag_main"
+ OpDecorate %tint_pointsize BuiltIn PointSize
+ OpDecorate %tint_symbol_1 Location 1
+ OpDecorate %tint_symbol_2 Location 2
+ OpDecorate %tint_symbol_3 BuiltIn Position
+ OpDecorate %tint_symbol_5 Location 1
+ OpDecorate %tint_symbol_6 Location 2
+ OpDecorate %tint_symbol_7 BuiltIn FragCoord
+ OpMemberDecorate %Interface 0 Offset 0
+ OpMemberDecorate %Interface 1 Offset 4
+ OpMemberDecorate %Interface 2 Offset 16
+ %float = OpTypeFloat 32
+%_ptr_Output_float = OpTypePointer Output %float
+ %4 = OpConstantNull %float
+%tint_pointsize = OpVariable %_ptr_Output_float Output %4
+%tint_symbol_1 = OpVariable %_ptr_Output_float Output %4
+%tint_symbol_2 = OpVariable %_ptr_Output_float Output %4
+ %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+ %10 = OpConstantNull %v4float
+%tint_symbol_3 = OpVariable %_ptr_Output_v4float Output %10
+%_ptr_Input_float = OpTypePointer Input %float
+%tint_symbol_5 = OpVariable %_ptr_Input_float Input
+%tint_symbol_6 = OpVariable %_ptr_Input_float Input
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%tint_symbol_7 = OpVariable %_ptr_Input_v4float Input
+ %void = OpTypeVoid
+ %Interface = OpTypeStruct %float %float %v4float
+ %16 = OpTypeFunction %void %Interface
+ %25 = OpTypeFunction %void
+ %float_1 = OpConstant %float 1
+%float_0_400000006 = OpConstant %float 0.400000006
+%float_0_600000024 = OpConstant %float 0.600000024
+ %32 = OpConstantComposite %Interface %float_0_400000006 %float_0_600000024 %10
+%tint_symbol_4 = OpFunction %void None %16
+%tint_symbol = OpFunctionParameter %Interface
+ %21 = OpLabel
+ %22 = OpCompositeExtract %float %tint_symbol 0
+ OpStore %tint_symbol_1 %22
+ %23 = OpCompositeExtract %float %tint_symbol 1
+ OpStore %tint_symbol_2 %23
+ %24 = OpCompositeExtract %v4float %tint_symbol 2
+ OpStore %tint_symbol_3 %24
+ OpReturn
+ OpFunctionEnd
+ %vert_main = OpFunction %void None %25
+ %27 = OpLabel
+ OpStore %tint_pointsize %float_1
+ %29 = OpFunctionCall %void %tint_symbol_4 %32
+ OpReturn
+ OpFunctionEnd
+ %frag_main = OpFunction %void None %25
+ %34 = OpLabel
+ %35 = OpLoad %float %tint_symbol_5
+ %36 = OpLoad %float %tint_symbol_6
+ %37 = OpLoad %v4float %tint_symbol_7
+ %38 = OpCompositeConstruct %Interface %35 %36 %37
+ %39 = OpCompositeExtract %float %38 0
+ %40 = OpCompositeExtract %float %38 1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/shader_io/shared_struct_different_stages.wgsl.expected.wgsl b/test/shader_io/shared_struct_different_stages.wgsl.expected.wgsl
new file mode 100644
index 0000000..67a91d6
--- /dev/null
+++ b/test/shader_io/shared_struct_different_stages.wgsl.expected.wgsl
@@ -0,0 +1,19 @@
+struct Interface {
+ [[location(1)]]
+ col1 : f32;
+ [[location(2)]]
+ col2 : f32;
+ [[builtin(position)]]
+ pos : vec4<f32>;
+};
+
+[[stage(vertex)]]
+fn vert_main() -> Interface {
+ return Interface(0.400000006, 0.600000024, vec4<f32>());
+}
+
+[[stage(fragment)]]
+fn frag_main(colors : Interface) {
+ let r : f32 = colors.col1;
+ let g : f32 = colors.col2;
+}
diff --git a/test/shader_io/shared_struct_helper_function.wgsl b/test/shader_io/shared_struct_helper_function.wgsl
new file mode 100644
index 0000000..6527653
--- /dev/null
+++ b/test/shader_io/shared_struct_helper_function.wgsl
@@ -0,0 +1,16 @@
+struct VertexOutput {
+ [[builtin(position)]] pos : vec4<f32>;
+ [[location(0)]] loc0 : i32;
+};
+
+fn foo(x : f32) -> VertexOutput {
+ return VertexOutput(vec4<f32>(x, x, x, 1.0), 42);
+}
+
+fn vert_main1() -> VertexOutput {
+ return foo(0.5);
+}
+
+fn vert_main2() -> VertexOutput {
+ return foo(0.25);
+}
diff --git a/test/shader_io/shared_struct_helper_function.wgsl.expected.hlsl b/test/shader_io/shared_struct_helper_function.wgsl.expected.hlsl
new file mode 100644
index 0000000..46dca7e
--- /dev/null
+++ b/test/shader_io/shared_struct_helper_function.wgsl.expected.hlsl
@@ -0,0 +1,23 @@
+struct VertexOutput {
+ float4 pos;
+ int loc0;
+};
+
+VertexOutput foo(float x) {
+ const VertexOutput tint_symbol = {float4(x, x, x, 1.0f), 42};
+ return tint_symbol;
+}
+
+VertexOutput vert_main1() {
+ return foo(0.5f);
+}
+
+VertexOutput vert_main2() {
+ return foo(0.25f);
+}
+
+[numthreads(1, 1, 1)]
+void unused_entry_point() {
+ return;
+}
+
diff --git a/test/shader_io/shared_struct_helper_function.wgsl.expected.msl b/test/shader_io/shared_struct_helper_function.wgsl.expected.msl
new file mode 100644
index 0000000..f6c8f25
--- /dev/null
+++ b/test/shader_io/shared_struct_helper_function.wgsl.expected.msl
@@ -0,0 +1,21 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct VertexOutput {
+ float4 pos;
+ int loc0;
+};
+
+VertexOutput foo(float x) {
+ VertexOutput const tint_symbol = {float4(x, x, x, 1.0f), 42};
+ return tint_symbol;
+}
+
+VertexOutput vert_main1() {
+ return foo(0.5f);
+}
+
+VertexOutput vert_main2() {
+ return foo(0.25f);
+}
+
diff --git a/test/shader_io/shared_struct_helper_function.wgsl.expected.spvasm b/test/shader_io/shared_struct_helper_function.wgsl.expected.spvasm
new file mode 100644
index 0000000..ee3e97b
--- /dev/null
+++ b/test/shader_io/shared_struct_helper_function.wgsl.expected.spvasm
@@ -0,0 +1,52 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 26
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %unused_entry_point "unused_entry_point"
+ OpExecutionMode %unused_entry_point LocalSize 1 1 1
+ OpName %unused_entry_point "unused_entry_point"
+ OpName %VertexOutput "VertexOutput"
+ OpMemberName %VertexOutput 0 "pos"
+ OpMemberName %VertexOutput 1 "loc0"
+ OpName %foo "foo"
+ OpName %x "x"
+ OpName %vert_main1 "vert_main1"
+ OpName %vert_main2 "vert_main2"
+ OpMemberDecorate %VertexOutput 0 Offset 0
+ OpMemberDecorate %VertexOutput 1 Offset 16
+ %void = OpTypeVoid
+ %1 = OpTypeFunction %void
+ %float = OpTypeFloat 32
+ %v4float = OpTypeVector %float 4
+ %int = OpTypeInt 32 1
+%VertexOutput = OpTypeStruct %v4float %int
+ %5 = OpTypeFunction %VertexOutput %float
+ %float_1 = OpConstant %float 1
+ %int_42 = OpConstant %int 42
+ %17 = OpTypeFunction %VertexOutput
+ %float_0_5 = OpConstant %float 0.5
+ %float_0_25 = OpConstant %float 0.25
+%unused_entry_point = OpFunction %void None %1
+ %4 = OpLabel
+ OpReturn
+ OpFunctionEnd
+ %foo = OpFunction %VertexOutput None %5
+ %x = OpFunctionParameter %float
+ %12 = OpLabel
+ %14 = OpCompositeConstruct %v4float %x %x %x %float_1
+ %16 = OpCompositeConstruct %VertexOutput %14 %int_42
+ OpReturnValue %16
+ OpFunctionEnd
+ %vert_main1 = OpFunction %VertexOutput None %17
+ %19 = OpLabel
+ %20 = OpFunctionCall %VertexOutput %foo %float_0_5
+ OpReturnValue %20
+ OpFunctionEnd
+ %vert_main2 = OpFunction %VertexOutput None %17
+ %23 = OpLabel
+ %24 = OpFunctionCall %VertexOutput %foo %float_0_25
+ OpReturnValue %24
+ OpFunctionEnd
diff --git a/test/shader_io/shared_struct_helper_function.wgsl.expected.wgsl b/test/shader_io/shared_struct_helper_function.wgsl.expected.wgsl
new file mode 100644
index 0000000..e7a0978
--- /dev/null
+++ b/test/shader_io/shared_struct_helper_function.wgsl.expected.wgsl
@@ -0,0 +1,18 @@
+struct VertexOutput {
+ [[builtin(position)]]
+ pos : vec4<f32>;
+ [[location(0)]]
+ loc0 : i32;
+};
+
+fn foo(x : f32) -> VertexOutput {
+ return VertexOutput(vec4<f32>(x, x, x, 1.0), 42);
+}
+
+fn vert_main1() -> VertexOutput {
+ return foo(0.5);
+}
+
+fn vert_main2() -> VertexOutput {
+ return foo(0.25);
+}
diff --git a/test/shader_io/shared_struct_storage_buffer.wgsl b/test/shader_io/shared_struct_storage_buffer.wgsl
new file mode 100644
index 0000000..56f983c
--- /dev/null
+++ b/test/shader_io/shared_struct_storage_buffer.wgsl
@@ -0,0 +1,17 @@
+[[block]]
+struct S {
+ [[align(64)]] [[location(0)]] f : f32;
+ [[size(32)]] [[location(1)]] u : u32;
+ [[align(128)]] [[builtin(position)]] v : vec4<f32>;
+};
+
+[[group(0), binding(0)]]
+var<storage> output : [[access(write)]] S;
+
+[[stage(fragment)]]
+fn frag_main(input : S) {
+ let f : f32 = input.f;
+ let u : u32 = input.u;
+ let v : vec4<f32> = input.v;
+ output = input;
+}
diff --git a/test/shader_io/shared_struct_storage_buffer.wgsl.expected.hlsl b/test/shader_io/shared_struct_storage_buffer.wgsl.expected.hlsl
new file mode 100644
index 0000000..69591b8
--- /dev/null
+++ b/test/shader_io/shared_struct_storage_buffer.wgsl.expected.hlsl
@@ -0,0 +1,28 @@
+struct S {
+ float f;
+ uint u;
+ float4 v;
+};
+struct tint_symbol_1 {
+ float f : TEXCOORD0;
+ uint u : TEXCOORD1;
+ float4 v : SV_Position;
+};
+
+RWByteAddressBuffer output : register(u0, space0);
+
+void tint_symbol_5(RWByteAddressBuffer buffer, uint offset, S value) {
+ buffer.Store((offset + 0u), asuint(value.f));
+ buffer.Store((offset + 4u), asuint(value.u));
+ buffer.Store4((offset + 128u), asuint(value.v));
+}
+
+void frag_main(tint_symbol_1 tint_symbol) {
+ const S input = {tint_symbol.f, tint_symbol.u, tint_symbol.v};
+ const float f = input.f;
+ const uint u = input.u;
+ const float4 v = input.v;
+ tint_symbol_5(output, 0u, input);
+ return;
+}
+
diff --git a/test/shader_io/shared_struct_storage_buffer.wgsl.expected.msl b/test/shader_io/shared_struct_storage_buffer.wgsl.expected.msl
new file mode 100644
index 0000000..8831e0a
--- /dev/null
+++ b/test/shader_io/shared_struct_storage_buffer.wgsl.expected.msl
@@ -0,0 +1 @@
+SKIP: crbug.com/tint/853 type constructors broken with explicit layout structs
diff --git a/test/shader_io/shared_struct_storage_buffer.wgsl.expected.spvasm b/test/shader_io/shared_struct_storage_buffer.wgsl.expected.spvasm
new file mode 100644
index 0000000..527ffad
--- /dev/null
+++ b/test/shader_io/shared_struct_storage_buffer.wgsl.expected.spvasm
@@ -0,0 +1,54 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 24
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %frag_main "frag_main" %tint_symbol %tint_symbol_1 %tint_symbol_2
+ OpExecutionMode %frag_main OriginUpperLeft
+ OpName %S "S"
+ OpMemberName %S 0 "f"
+ OpMemberName %S 1 "u"
+ OpMemberName %S 2 "v"
+ OpName %output "output"
+ OpName %tint_symbol "tint_symbol"
+ OpName %tint_symbol_1 "tint_symbol_1"
+ OpName %tint_symbol_2 "tint_symbol_2"
+ OpName %frag_main "frag_main"
+ OpDecorate %S Block
+ OpMemberDecorate %S 0 Offset 0
+ OpMemberDecorate %S 1 Offset 4
+ OpMemberDecorate %S 2 Offset 128
+ OpDecorate %output NonReadable
+ OpDecorate %output DescriptorSet 0
+ OpDecorate %output Binding 0
+ OpDecorate %tint_symbol Location 0
+ OpDecorate %tint_symbol_1 Location 1
+ OpDecorate %tint_symbol_2 BuiltIn FragCoord
+ %float = OpTypeFloat 32
+ %uint = OpTypeInt 32 0
+ %v4float = OpTypeVector %float 4
+ %S = OpTypeStruct %float %uint %v4float
+%_ptr_StorageBuffer_S = OpTypePointer StorageBuffer %S
+ %output = OpVariable %_ptr_StorageBuffer_S StorageBuffer
+%_ptr_Input_float = OpTypePointer Input %float
+%tint_symbol = OpVariable %_ptr_Input_float Input
+%_ptr_Input_uint = OpTypePointer Input %uint
+%tint_symbol_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%tint_symbol_2 = OpVariable %_ptr_Input_v4float Input
+ %void = OpTypeVoid
+ %13 = OpTypeFunction %void
+ %frag_main = OpFunction %void None %13
+ %16 = OpLabel
+ %17 = OpLoad %float %tint_symbol
+ %18 = OpLoad %uint %tint_symbol_1
+ %19 = OpLoad %v4float %tint_symbol_2
+ %20 = OpCompositeConstruct %S %17 %18 %19
+ %21 = OpCompositeExtract %float %20 0
+ %22 = OpCompositeExtract %uint %20 1
+ %23 = OpCompositeExtract %v4float %20 2
+ OpStore %output %20
+ OpReturn
+ OpFunctionEnd
diff --git a/test/shader_io/shared_struct_storage_buffer.wgsl.expected.wgsl b/test/shader_io/shared_struct_storage_buffer.wgsl.expected.wgsl
new file mode 100644
index 0000000..db8682f
--- /dev/null
+++ b/test/shader_io/shared_struct_storage_buffer.wgsl.expected.wgsl
@@ -0,0 +1,19 @@
+[[block]]
+struct S {
+ [[align(64), location(0)]]
+ f : f32;
+ [[size(32), location(1)]]
+ u : u32;
+ [[align(128), builtin(position)]]
+ v : vec4<f32>;
+};
+
+[[group(0), binding(0)]] var<storage> output : [[access(write)]] S;
+
+[[stage(fragment)]]
+fn frag_main(input : S) {
+ let f : f32 = input.f;
+ let u : u32 = input.u;
+ let v : vec4<f32> = input.v;
+ output = input;
+}
diff --git a/test/shader_io/vertex_input_builtins.wgsl b/test/shader_io/vertex_input_builtins.wgsl
new file mode 100644
index 0000000..6d207b5
--- /dev/null
+++ b/test/shader_io/vertex_input_builtins.wgsl
@@ -0,0 +1,8 @@
+[[stage(vertex)]]
+fn main(
+ [[builtin(vertex_index)]] vertex_index : u32,
+ [[builtin(instance_index)]] instance_index : u32,
+) -> [[builtin(position)]] vec4<f32> {
+ let foo : u32 = vertex_index + instance_index;
+ return vec4<f32>();
+}
diff --git a/test/shader_io/vertex_input_builtins.wgsl.expected.hlsl b/test/shader_io/vertex_input_builtins.wgsl.expected.hlsl
new file mode 100644
index 0000000..5a0e122
--- /dev/null
+++ b/test/shader_io/vertex_input_builtins.wgsl.expected.hlsl
@@ -0,0 +1,16 @@
+struct tint_symbol_1 {
+ uint vertex_index : SV_VertexID;
+ uint instance_index : SV_InstanceID;
+};
+struct tint_symbol_2 {
+ float4 value : SV_Position;
+};
+
+tint_symbol_2 main(tint_symbol_1 tint_symbol) {
+ const uint vertex_index = tint_symbol.vertex_index;
+ const uint instance_index = tint_symbol.instance_index;
+ const uint foo = (vertex_index + instance_index);
+ const tint_symbol_2 tint_symbol_3 = {float4(0.0f, 0.0f, 0.0f, 0.0f)};
+ return tint_symbol_3;
+}
+
diff --git a/test/shader_io/vertex_input_builtins.wgsl.expected.msl b/test/shader_io/vertex_input_builtins.wgsl.expected.msl
new file mode 100644
index 0000000..71d62fb
--- /dev/null
+++ b/test/shader_io/vertex_input_builtins.wgsl.expected.msl
@@ -0,0 +1 @@
+SKIP: crbug.com/tint/817 attribute only applies to parameters
diff --git a/test/shader_io/vertex_input_builtins.wgsl.expected.spvasm b/test/shader_io/vertex_input_builtins.wgsl.expected.spvasm
new file mode 100644
index 0000000..198293c
--- /dev/null
+++ b/test/shader_io/vertex_input_builtins.wgsl.expected.spvasm
@@ -0,0 +1,50 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 26
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Vertex %main "main" %tint_pointsize %tint_symbol %tint_symbol_1 %tint_symbol_3
+ OpName %tint_pointsize "tint_pointsize"
+ OpName %tint_symbol "tint_symbol"
+ OpName %tint_symbol_1 "tint_symbol_1"
+ OpName %tint_symbol_3 "tint_symbol_3"
+ OpName %tint_symbol_4 "tint_symbol_4"
+ OpName %tint_symbol_2 "tint_symbol_2"
+ OpName %main "main"
+ OpDecorate %tint_pointsize BuiltIn PointSize
+ OpDecorate %tint_symbol BuiltIn VertexIndex
+ OpDecorate %tint_symbol_1 BuiltIn InstanceIndex
+ OpDecorate %tint_symbol_3 BuiltIn Position
+ %float = OpTypeFloat 32
+%_ptr_Output_float = OpTypePointer Output %float
+ %4 = OpConstantNull %float
+%tint_pointsize = OpVariable %_ptr_Output_float Output %4
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%tint_symbol = OpVariable %_ptr_Input_uint Input
+%tint_symbol_1 = OpVariable %_ptr_Input_uint Input
+ %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+ %12 = OpConstantNull %v4float
+%tint_symbol_3 = OpVariable %_ptr_Output_v4float Output %12
+ %void = OpTypeVoid
+ %13 = OpTypeFunction %void %v4float
+ %18 = OpTypeFunction %void
+ %float_1 = OpConstant %float 1
+%tint_symbol_4 = OpFunction %void None %13
+%tint_symbol_2 = OpFunctionParameter %v4float
+ %17 = OpLabel
+ OpStore %tint_symbol_3 %tint_symbol_2
+ OpReturn
+ OpFunctionEnd
+ %main = OpFunction %void None %18
+ %20 = OpLabel
+ OpStore %tint_pointsize %float_1
+ %22 = OpLoad %uint %tint_symbol
+ %23 = OpLoad %uint %tint_symbol_1
+ %24 = OpIAdd %uint %22 %23
+ %25 = OpFunctionCall %void %tint_symbol_4 %12
+ OpReturn
+ OpFunctionEnd
diff --git a/test/shader_io/vertex_input_builtins.wgsl.expected.wgsl b/test/shader_io/vertex_input_builtins.wgsl.expected.wgsl
new file mode 100644
index 0000000..ef2f3ac
--- /dev/null
+++ b/test/shader_io/vertex_input_builtins.wgsl.expected.wgsl
@@ -0,0 +1,5 @@
+[[stage(vertex)]]
+fn main([[builtin(vertex_index)]] vertex_index : u32, [[builtin(instance_index)]] instance_index : u32) -> [[builtin(position)]] vec4<f32> {
+ let foo : u32 = (vertex_index + instance_index);
+ return vec4<f32>();
+}
diff --git a/test/shader_io/vertex_input_builtins_struct.wgsl b/test/shader_io/vertex_input_builtins_struct.wgsl
new file mode 100644
index 0000000..d81bcdc
--- /dev/null
+++ b/test/shader_io/vertex_input_builtins_struct.wgsl
@@ -0,0 +1,10 @@
+struct VertexInputs {
+ [[builtin(vertex_index)]] vertex_index : u32;
+ [[builtin(instance_index)]] instance_index : u32;
+};
+
+[[stage(vertex)]]
+fn main(inputs : VertexInputs) -> [[builtin(position)]] vec4<f32> {
+ let foo : u32 = inputs.vertex_index + inputs.instance_index;
+ return vec4<f32>();
+}
diff --git a/test/shader_io/vertex_input_builtins_struct.wgsl.expected.hlsl b/test/shader_io/vertex_input_builtins_struct.wgsl.expected.hlsl
new file mode 100644
index 0000000..632e212
--- /dev/null
+++ b/test/shader_io/vertex_input_builtins_struct.wgsl.expected.hlsl
@@ -0,0 +1,19 @@
+struct VertexInputs {
+ uint vertex_index;
+ uint instance_index;
+};
+struct tint_symbol_1 {
+ uint vertex_index : SV_VertexID;
+ uint instance_index : SV_InstanceID;
+};
+struct tint_symbol_2 {
+ float4 value : SV_Position;
+};
+
+tint_symbol_2 main(tint_symbol_1 tint_symbol) {
+ const VertexInputs inputs = {tint_symbol.vertex_index, tint_symbol.instance_index};
+ const uint foo = (inputs.vertex_index + inputs.instance_index);
+ const tint_symbol_2 tint_symbol_3 = {float4(0.0f, 0.0f, 0.0f, 0.0f)};
+ return tint_symbol_3;
+}
+
diff --git a/test/shader_io/vertex_input_builtins_struct.wgsl.expected.msl b/test/shader_io/vertex_input_builtins_struct.wgsl.expected.msl
new file mode 100644
index 0000000..71d62fb
--- /dev/null
+++ b/test/shader_io/vertex_input_builtins_struct.wgsl.expected.msl
@@ -0,0 +1 @@
+SKIP: crbug.com/tint/817 attribute only applies to parameters
diff --git a/test/shader_io/vertex_input_builtins_struct.wgsl.expected.spvasm b/test/shader_io/vertex_input_builtins_struct.wgsl.expected.spvasm
new file mode 100644
index 0000000..b2af529
--- /dev/null
+++ b/test/shader_io/vertex_input_builtins_struct.wgsl.expected.spvasm
@@ -0,0 +1,59 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 30
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Vertex %main "main" %tint_pointsize %tint_symbol %tint_symbol_1 %tint_symbol_4
+ OpName %tint_pointsize "tint_pointsize"
+ OpName %tint_symbol "tint_symbol"
+ OpName %tint_symbol_1 "tint_symbol_1"
+ OpName %tint_symbol_4 "tint_symbol_4"
+ OpName %tint_symbol_5 "tint_symbol_5"
+ OpName %tint_symbol_3 "tint_symbol_3"
+ OpName %main "main"
+ OpName %VertexInputs "VertexInputs"
+ OpMemberName %VertexInputs 0 "vertex_index"
+ OpMemberName %VertexInputs 1 "instance_index"
+ OpDecorate %tint_pointsize BuiltIn PointSize
+ OpDecorate %tint_symbol BuiltIn VertexIndex
+ OpDecorate %tint_symbol_1 BuiltIn InstanceIndex
+ OpDecorate %tint_symbol_4 BuiltIn Position
+ OpMemberDecorate %VertexInputs 0 Offset 0
+ OpMemberDecorate %VertexInputs 1 Offset 4
+ %float = OpTypeFloat 32
+%_ptr_Output_float = OpTypePointer Output %float
+ %4 = OpConstantNull %float
+%tint_pointsize = OpVariable %_ptr_Output_float Output %4
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%tint_symbol = OpVariable %_ptr_Input_uint Input
+%tint_symbol_1 = OpVariable %_ptr_Input_uint Input
+ %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+ %12 = OpConstantNull %v4float
+%tint_symbol_4 = OpVariable %_ptr_Output_v4float Output %12
+ %void = OpTypeVoid
+ %13 = OpTypeFunction %void %v4float
+ %18 = OpTypeFunction %void
+ %float_1 = OpConstant %float 1
+%VertexInputs = OpTypeStruct %uint %uint
+%tint_symbol_5 = OpFunction %void None %13
+%tint_symbol_3 = OpFunctionParameter %v4float
+ %17 = OpLabel
+ OpStore %tint_symbol_4 %tint_symbol_3
+ OpReturn
+ OpFunctionEnd
+ %main = OpFunction %void None %18
+ %20 = OpLabel
+ OpStore %tint_pointsize %float_1
+ %23 = OpLoad %uint %tint_symbol
+ %24 = OpLoad %uint %tint_symbol_1
+ %25 = OpCompositeConstruct %VertexInputs %23 %24
+ %26 = OpCompositeExtract %uint %25 0
+ %27 = OpCompositeExtract %uint %25 1
+ %28 = OpIAdd %uint %26 %27
+ %29 = OpFunctionCall %void %tint_symbol_5 %12
+ OpReturn
+ OpFunctionEnd
diff --git a/test/shader_io/vertex_input_builtins_struct.wgsl.expected.wgsl b/test/shader_io/vertex_input_builtins_struct.wgsl.expected.wgsl
new file mode 100644
index 0000000..f63100d
--- /dev/null
+++ b/test/shader_io/vertex_input_builtins_struct.wgsl.expected.wgsl
@@ -0,0 +1,12 @@
+struct VertexInputs {
+ [[builtin(vertex_index)]]
+ vertex_index : u32;
+ [[builtin(instance_index)]]
+ instance_index : u32;
+};
+
+[[stage(vertex)]]
+fn main(inputs : VertexInputs) -> [[builtin(position)]] vec4<f32> {
+ let foo : u32 = (inputs.vertex_index + inputs.instance_index);
+ return vec4<f32>();
+}
diff --git a/test/shader_io/vertex_input_locations.wgsl b/test/shader_io/vertex_input_locations.wgsl
new file mode 100644
index 0000000..13fad04
--- /dev/null
+++ b/test/shader_io/vertex_input_locations.wgsl
@@ -0,0 +1,13 @@
+[[stage(vertex)]]
+fn main(
+ [[location(0)]] loc0 : i32,
+ [[location(1)]] loc1 : u32,
+ [[location(2)]] loc2 : f32,
+ [[location(3)]] loc3 : vec4<f32>,
+) -> [[builtin(position)]] vec4<f32> {
+ let i : i32 = loc0;
+ let u : u32 = loc1;
+ let f : f32 = loc2;
+ let v : vec4<f32> = loc3;
+ return vec4<f32>();
+}
diff --git a/test/shader_io/vertex_input_locations.wgsl.expected.hlsl b/test/shader_io/vertex_input_locations.wgsl.expected.hlsl
new file mode 100644
index 0000000..3bb4613
--- /dev/null
+++ b/test/shader_io/vertex_input_locations.wgsl.expected.hlsl
@@ -0,0 +1,23 @@
+struct tint_symbol_1 {
+ int loc0 : TEXCOORD0;
+ uint loc1 : TEXCOORD1;
+ float loc2 : TEXCOORD2;
+ float4 loc3 : TEXCOORD3;
+};
+struct tint_symbol_2 {
+ float4 value : SV_Position;
+};
+
+tint_symbol_2 main(tint_symbol_1 tint_symbol) {
+ const int loc0 = tint_symbol.loc0;
+ const uint loc1 = tint_symbol.loc1;
+ const float loc2 = tint_symbol.loc2;
+ const float4 loc3 = tint_symbol.loc3;
+ const int i = loc0;
+ const uint u = loc1;
+ const float f = loc2;
+ const float4 v = loc3;
+ const tint_symbol_2 tint_symbol_3 = {float4(0.0f, 0.0f, 0.0f, 0.0f)};
+ return tint_symbol_3;
+}
+
diff --git a/test/shader_io/vertex_input_locations.wgsl.expected.msl b/test/shader_io/vertex_input_locations.wgsl.expected.msl
new file mode 100644
index 0000000..a4c8606
--- /dev/null
+++ b/test/shader_io/vertex_input_locations.wgsl.expected.msl
@@ -0,0 +1,26 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct tint_symbol_2 {
+ int loc0 [[attribute(0)]];
+ uint loc1 [[attribute(1)]];
+ float loc2 [[attribute(2)]];
+ float4 loc3 [[attribute(3)]];
+};
+struct tint_symbol_3 {
+ float4 value [[position]];
+};
+
+vertex tint_symbol_3 tint_symbol(tint_symbol_2 tint_symbol_1 [[stage_in]]) {
+ int const loc0 = tint_symbol_1.loc0;
+ uint const loc1 = tint_symbol_1.loc1;
+ float const loc2 = tint_symbol_1.loc2;
+ float4 const loc3 = tint_symbol_1.loc3;
+ int const i = loc0;
+ uint const u = loc1;
+ float const f = loc2;
+ float4 const v = loc3;
+ tint_symbol_3 const tint_symbol_4 = {float4()};
+ return tint_symbol_4;
+}
+
diff --git a/test/shader_io/vertex_input_locations.wgsl.expected.spvasm b/test/shader_io/vertex_input_locations.wgsl.expected.spvasm
new file mode 100644
index 0000000..9a0c93b
--- /dev/null
+++ b/test/shader_io/vertex_input_locations.wgsl.expected.spvasm
@@ -0,0 +1,61 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 33
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Vertex %main "main" %tint_pointsize %tint_symbol %tint_symbol_1 %tint_symbol_2 %tint_symbol_3 %tint_symbol_5
+ OpName %tint_pointsize "tint_pointsize"
+ OpName %tint_symbol "tint_symbol"
+ OpName %tint_symbol_1 "tint_symbol_1"
+ OpName %tint_symbol_2 "tint_symbol_2"
+ OpName %tint_symbol_3 "tint_symbol_3"
+ OpName %tint_symbol_5 "tint_symbol_5"
+ OpName %tint_symbol_6 "tint_symbol_6"
+ OpName %tint_symbol_4 "tint_symbol_4"
+ OpName %main "main"
+ OpDecorate %tint_pointsize BuiltIn PointSize
+ OpDecorate %tint_symbol Location 0
+ OpDecorate %tint_symbol_1 Location 1
+ OpDecorate %tint_symbol_2 Location 2
+ OpDecorate %tint_symbol_3 Location 3
+ OpDecorate %tint_symbol_5 BuiltIn Position
+ %float = OpTypeFloat 32
+%_ptr_Output_float = OpTypePointer Output %float
+ %4 = OpConstantNull %float
+%tint_pointsize = OpVariable %_ptr_Output_float Output %4
+ %int = OpTypeInt 32 1
+%_ptr_Input_int = OpTypePointer Input %int
+%tint_symbol = OpVariable %_ptr_Input_int Input
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%tint_symbol_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Input_float = OpTypePointer Input %float
+%tint_symbol_2 = OpVariable %_ptr_Input_float Input
+ %v4float = OpTypeVector %float 4
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%tint_symbol_3 = OpVariable %_ptr_Input_v4float Input
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+ %18 = OpConstantNull %v4float
+%tint_symbol_5 = OpVariable %_ptr_Output_v4float Output %18
+ %void = OpTypeVoid
+ %19 = OpTypeFunction %void %v4float
+ %24 = OpTypeFunction %void
+ %float_1 = OpConstant %float 1
+%tint_symbol_6 = OpFunction %void None %19
+%tint_symbol_4 = OpFunctionParameter %v4float
+ %23 = OpLabel
+ OpStore %tint_symbol_5 %tint_symbol_4
+ OpReturn
+ OpFunctionEnd
+ %main = OpFunction %void None %24
+ %26 = OpLabel
+ OpStore %tint_pointsize %float_1
+ %28 = OpLoad %int %tint_symbol
+ %29 = OpLoad %uint %tint_symbol_1
+ %30 = OpLoad %float %tint_symbol_2
+ %31 = OpLoad %v4float %tint_symbol_3
+ %32 = OpFunctionCall %void %tint_symbol_6 %18
+ OpReturn
+ OpFunctionEnd
diff --git a/test/shader_io/vertex_input_locations.wgsl.expected.wgsl b/test/shader_io/vertex_input_locations.wgsl.expected.wgsl
new file mode 100644
index 0000000..3730fec
--- /dev/null
+++ b/test/shader_io/vertex_input_locations.wgsl.expected.wgsl
@@ -0,0 +1,8 @@
+[[stage(vertex)]]
+fn main([[location(0)]] loc0 : i32, [[location(1)]] loc1 : u32, [[location(2)]] loc2 : f32, [[location(3)]] loc3 : vec4<f32>) -> [[builtin(position)]] vec4<f32> {
+ let i : i32 = loc0;
+ let u : u32 = loc1;
+ let f : f32 = loc2;
+ let v : vec4<f32> = loc3;
+ return vec4<f32>();
+}
diff --git a/test/shader_io/vertex_input_locations_struct.wgsl b/test/shader_io/vertex_input_locations_struct.wgsl
new file mode 100644
index 0000000..441ffdc
--- /dev/null
+++ b/test/shader_io/vertex_input_locations_struct.wgsl
@@ -0,0 +1,15 @@
+struct VertexInputs {
+ [[location(0)]] loc0 : i32;
+ [[location(1)]] loc1 : u32;
+ [[location(2)]] loc2 : f32;
+ [[location(3)]] loc3 : vec4<f32>;
+};
+
+[[stage(vertex)]]
+fn main(inputs : VertexInputs) -> [[builtin(position)]] vec4<f32> {
+ let i : i32 = inputs.loc0;
+ let u : u32 = inputs.loc1;
+ let f : f32 = inputs.loc2;
+ let v : vec4<f32> = inputs.loc3;
+ return vec4<f32>();
+}
diff --git a/test/shader_io/vertex_input_locations_struct.wgsl.expected.hlsl b/test/shader_io/vertex_input_locations_struct.wgsl.expected.hlsl
new file mode 100644
index 0000000..f93f2fe
--- /dev/null
+++ b/test/shader_io/vertex_input_locations_struct.wgsl.expected.hlsl
@@ -0,0 +1,26 @@
+struct VertexInputs {
+ int loc0;
+ uint loc1;
+ float loc2;
+ float4 loc3;
+};
+struct tint_symbol_1 {
+ int loc0 : TEXCOORD0;
+ uint loc1 : TEXCOORD1;
+ float loc2 : TEXCOORD2;
+ float4 loc3 : TEXCOORD3;
+};
+struct tint_symbol_2 {
+ float4 value : SV_Position;
+};
+
+tint_symbol_2 main(tint_symbol_1 tint_symbol) {
+ const VertexInputs inputs = {tint_symbol.loc0, tint_symbol.loc1, tint_symbol.loc2, tint_symbol.loc3};
+ const int i = inputs.loc0;
+ const uint u = inputs.loc1;
+ const float f = inputs.loc2;
+ const float4 v = inputs.loc3;
+ const tint_symbol_2 tint_symbol_3 = {float4(0.0f, 0.0f, 0.0f, 0.0f)};
+ return tint_symbol_3;
+}
+
diff --git a/test/shader_io/vertex_input_locations_struct.wgsl.expected.msl b/test/shader_io/vertex_input_locations_struct.wgsl.expected.msl
new file mode 100644
index 0000000..6cce9d7
--- /dev/null
+++ b/test/shader_io/vertex_input_locations_struct.wgsl.expected.msl
@@ -0,0 +1,29 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct VertexInputs {
+ int loc0;
+ uint loc1;
+ float loc2;
+ float4 loc3;
+};
+struct tint_symbol_2 {
+ int loc0 [[attribute(0)]];
+ uint loc1 [[attribute(1)]];
+ float loc2 [[attribute(2)]];
+ float4 loc3 [[attribute(3)]];
+};
+struct tint_symbol_3 {
+ float4 value [[position]];
+};
+
+vertex tint_symbol_3 tint_symbol(tint_symbol_2 tint_symbol_1 [[stage_in]]) {
+ VertexInputs const inputs = {tint_symbol_1.loc0, tint_symbol_1.loc1, tint_symbol_1.loc2, tint_symbol_1.loc3};
+ int const i = inputs.loc0;
+ uint const u = inputs.loc1;
+ float const f = inputs.loc2;
+ float4 const v = inputs.loc3;
+ tint_symbol_3 const tint_symbol_4 = {float4()};
+ return tint_symbol_4;
+}
+
diff --git a/test/shader_io/vertex_input_locations_struct.wgsl.expected.spvasm b/test/shader_io/vertex_input_locations_struct.wgsl.expected.spvasm
new file mode 100644
index 0000000..3766af8
--- /dev/null
+++ b/test/shader_io/vertex_input_locations_struct.wgsl.expected.spvasm
@@ -0,0 +1,76 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 39
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Vertex %main "main" %tint_pointsize %tint_symbol %tint_symbol_1 %tint_symbol_2 %tint_symbol_3 %tint_symbol_6
+ OpName %tint_pointsize "tint_pointsize"
+ OpName %tint_symbol "tint_symbol"
+ OpName %tint_symbol_1 "tint_symbol_1"
+ OpName %tint_symbol_2 "tint_symbol_2"
+ OpName %tint_symbol_3 "tint_symbol_3"
+ OpName %tint_symbol_6 "tint_symbol_6"
+ OpName %tint_symbol_7 "tint_symbol_7"
+ OpName %tint_symbol_5 "tint_symbol_5"
+ OpName %main "main"
+ OpName %VertexInputs "VertexInputs"
+ OpMemberName %VertexInputs 0 "loc0"
+ OpMemberName %VertexInputs 1 "loc1"
+ OpMemberName %VertexInputs 2 "loc2"
+ OpMemberName %VertexInputs 3 "loc3"
+ OpDecorate %tint_pointsize BuiltIn PointSize
+ OpDecorate %tint_symbol Location 0
+ OpDecorate %tint_symbol_1 Location 1
+ OpDecorate %tint_symbol_2 Location 2
+ OpDecorate %tint_symbol_3 Location 3
+ OpDecorate %tint_symbol_6 BuiltIn Position
+ OpMemberDecorate %VertexInputs 0 Offset 0
+ OpMemberDecorate %VertexInputs 1 Offset 4
+ OpMemberDecorate %VertexInputs 2 Offset 8
+ OpMemberDecorate %VertexInputs 3 Offset 16
+ %float = OpTypeFloat 32
+%_ptr_Output_float = OpTypePointer Output %float
+ %4 = OpConstantNull %float
+%tint_pointsize = OpVariable %_ptr_Output_float Output %4
+ %int = OpTypeInt 32 1
+%_ptr_Input_int = OpTypePointer Input %int
+%tint_symbol = OpVariable %_ptr_Input_int Input
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%tint_symbol_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Input_float = OpTypePointer Input %float
+%tint_symbol_2 = OpVariable %_ptr_Input_float Input
+ %v4float = OpTypeVector %float 4
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%tint_symbol_3 = OpVariable %_ptr_Input_v4float Input
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+ %18 = OpConstantNull %v4float
+%tint_symbol_6 = OpVariable %_ptr_Output_v4float Output %18
+ %void = OpTypeVoid
+ %19 = OpTypeFunction %void %v4float
+ %24 = OpTypeFunction %void
+ %float_1 = OpConstant %float 1
+%VertexInputs = OpTypeStruct %int %uint %float %v4float
+%tint_symbol_7 = OpFunction %void None %19
+%tint_symbol_5 = OpFunctionParameter %v4float
+ %23 = OpLabel
+ OpStore %tint_symbol_6 %tint_symbol_5
+ OpReturn
+ OpFunctionEnd
+ %main = OpFunction %void None %24
+ %26 = OpLabel
+ OpStore %tint_pointsize %float_1
+ %29 = OpLoad %int %tint_symbol
+ %30 = OpLoad %uint %tint_symbol_1
+ %31 = OpLoad %float %tint_symbol_2
+ %32 = OpLoad %v4float %tint_symbol_3
+ %33 = OpCompositeConstruct %VertexInputs %29 %30 %31 %32
+ %34 = OpCompositeExtract %int %33 0
+ %35 = OpCompositeExtract %uint %33 1
+ %36 = OpCompositeExtract %float %33 2
+ %37 = OpCompositeExtract %v4float %33 3
+ %38 = OpFunctionCall %void %tint_symbol_7 %18
+ OpReturn
+ OpFunctionEnd
diff --git a/test/shader_io/vertex_input_locations_struct.wgsl.expected.wgsl b/test/shader_io/vertex_input_locations_struct.wgsl.expected.wgsl
new file mode 100644
index 0000000..28d40aa
--- /dev/null
+++ b/test/shader_io/vertex_input_locations_struct.wgsl.expected.wgsl
@@ -0,0 +1,19 @@
+struct VertexInputs {
+ [[location(0)]]
+ loc0 : i32;
+ [[location(1)]]
+ loc1 : u32;
+ [[location(2)]]
+ loc2 : f32;
+ [[location(3)]]
+ loc3 : vec4<f32>;
+};
+
+[[stage(vertex)]]
+fn main(inputs : VertexInputs) -> [[builtin(position)]] vec4<f32> {
+ let i : i32 = inputs.loc0;
+ let u : u32 = inputs.loc1;
+ let f : f32 = inputs.loc2;
+ let v : vec4<f32> = inputs.loc3;
+ return vec4<f32>();
+}
diff --git a/test/shader_io/vertex_input_mixed.wgsl b/test/shader_io/vertex_input_mixed.wgsl
new file mode 100644
index 0000000..7c5eafe
--- /dev/null
+++ b/test/shader_io/vertex_input_mixed.wgsl
@@ -0,0 +1,23 @@
+struct VertexInputs0 {
+ [[builtin(vertex_index)]] vertex_index : u32;
+ [[location(0)]] loc0 : i32;
+};
+struct VertexInputs1 {
+ [[location(2)]] loc2 : f32;
+ [[location(3)]] loc3 : vec4<f32>;
+};
+
+[[stage(vertex)]]
+fn main(
+ inputs0 : VertexInputs0,
+ [[location(1)]] loc1 : u32,
+ [[builtin(instance_index)]] instance_index : u32,
+ inputs1 : VertexInputs1,
+) -> [[builtin(position)]] vec4<f32> {
+ let foo : u32 = inputs0.vertex_index + instance_index;
+ let i : i32 = inputs0.loc0;
+ let u : u32 = loc1;
+ let f : f32 = inputs1.loc2;
+ let v : vec4<f32> = inputs1.loc3;
+ return vec4<f32>();
+}
diff --git a/test/shader_io/vertex_input_mixed.wgsl.expected.hlsl b/test/shader_io/vertex_input_mixed.wgsl.expected.hlsl
new file mode 100644
index 0000000..aa630cf
--- /dev/null
+++ b/test/shader_io/vertex_input_mixed.wgsl.expected.hlsl
@@ -0,0 +1,34 @@
+struct VertexInputs0 {
+ uint vertex_index;
+ int loc0;
+};
+struct VertexInputs1 {
+ float loc2;
+ float4 loc3;
+};
+struct tint_symbol_1 {
+ int loc0 : TEXCOORD0;
+ uint loc1 : TEXCOORD1;
+ float loc2 : TEXCOORD2;
+ float4 loc3 : TEXCOORD3;
+ uint vertex_index : SV_VertexID;
+ uint instance_index : SV_InstanceID;
+};
+struct tint_symbol_2 {
+ float4 value : SV_Position;
+};
+
+tint_symbol_2 main(tint_symbol_1 tint_symbol) {
+ const VertexInputs0 inputs0 = {tint_symbol.vertex_index, tint_symbol.loc0};
+ const uint loc1 = tint_symbol.loc1;
+ const uint instance_index = tint_symbol.instance_index;
+ const VertexInputs1 inputs1 = {tint_symbol.loc2, tint_symbol.loc3};
+ const uint foo = (inputs0.vertex_index + instance_index);
+ const int i = inputs0.loc0;
+ const uint u = loc1;
+ const float f = inputs1.loc2;
+ const float4 v = inputs1.loc3;
+ const tint_symbol_2 tint_symbol_3 = {float4(0.0f, 0.0f, 0.0f, 0.0f)};
+ return tint_symbol_3;
+}
+
diff --git a/test/shader_io/vertex_input_mixed.wgsl.expected.msl b/test/shader_io/vertex_input_mixed.wgsl.expected.msl
new file mode 100644
index 0000000..71d62fb
--- /dev/null
+++ b/test/shader_io/vertex_input_mixed.wgsl.expected.msl
@@ -0,0 +1 @@
+SKIP: crbug.com/tint/817 attribute only applies to parameters
diff --git a/test/shader_io/vertex_input_mixed.wgsl.expected.spvasm b/test/shader_io/vertex_input_mixed.wgsl.expected.spvasm
new file mode 100644
index 0000000..f930879
--- /dev/null
+++ b/test/shader_io/vertex_input_mixed.wgsl.expected.spvasm
@@ -0,0 +1,88 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 46
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Vertex %main "main" %tint_pointsize %tint_symbol %tint_symbol_1 %tint_symbol_5 %tint_symbol_6 %tint_symbol_4 %tint_symbol_3 %tint_symbol_9
+ OpName %tint_pointsize "tint_pointsize"
+ OpName %tint_symbol "tint_symbol"
+ OpName %tint_symbol_1 "tint_symbol_1"
+ OpName %tint_symbol_3 "tint_symbol_3"
+ OpName %tint_symbol_4 "tint_symbol_4"
+ OpName %tint_symbol_5 "tint_symbol_5"
+ OpName %tint_symbol_6 "tint_symbol_6"
+ OpName %tint_symbol_9 "tint_symbol_9"
+ OpName %tint_symbol_10 "tint_symbol_10"
+ OpName %tint_symbol_8 "tint_symbol_8"
+ OpName %main "main"
+ OpName %VertexInputs0 "VertexInputs0"
+ OpMemberName %VertexInputs0 0 "vertex_index"
+ OpMemberName %VertexInputs0 1 "loc0"
+ OpName %VertexInputs1 "VertexInputs1"
+ OpMemberName %VertexInputs1 0 "loc2"
+ OpMemberName %VertexInputs1 1 "loc3"
+ OpDecorate %tint_pointsize BuiltIn PointSize
+ OpDecorate %tint_symbol BuiltIn VertexIndex
+ OpDecorate %tint_symbol_1 Location 0
+ OpDecorate %tint_symbol_3 Location 1
+ OpDecorate %tint_symbol_4 BuiltIn InstanceIndex
+ OpDecorate %tint_symbol_5 Location 2
+ OpDecorate %tint_symbol_6 Location 3
+ OpDecorate %tint_symbol_9 BuiltIn Position
+ OpMemberDecorate %VertexInputs0 0 Offset 0
+ OpMemberDecorate %VertexInputs0 1 Offset 4
+ OpMemberDecorate %VertexInputs1 0 Offset 0
+ OpMemberDecorate %VertexInputs1 1 Offset 16
+ %float = OpTypeFloat 32
+%_ptr_Output_float = OpTypePointer Output %float
+ %4 = OpConstantNull %float
+%tint_pointsize = OpVariable %_ptr_Output_float Output %4
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%tint_symbol = OpVariable %_ptr_Input_uint Input
+ %int = OpTypeInt 32 1
+%_ptr_Input_int = OpTypePointer Input %int
+%tint_symbol_1 = OpVariable %_ptr_Input_int Input
+%tint_symbol_3 = OpVariable %_ptr_Input_uint Input
+%tint_symbol_4 = OpVariable %_ptr_Input_uint Input
+%_ptr_Input_float = OpTypePointer Input %float
+%tint_symbol_5 = OpVariable %_ptr_Input_float Input
+ %v4float = OpTypeVector %float 4
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%tint_symbol_6 = OpVariable %_ptr_Input_v4float Input
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+ %20 = OpConstantNull %v4float
+%tint_symbol_9 = OpVariable %_ptr_Output_v4float Output %20
+ %void = OpTypeVoid
+ %21 = OpTypeFunction %void %v4float
+ %26 = OpTypeFunction %void
+ %float_1 = OpConstant %float 1
+%VertexInputs0 = OpTypeStruct %uint %int
+%VertexInputs1 = OpTypeStruct %float %v4float
+%tint_symbol_10 = OpFunction %void None %21
+%tint_symbol_8 = OpFunctionParameter %v4float
+ %25 = OpLabel
+ OpStore %tint_symbol_9 %tint_symbol_8
+ OpReturn
+ OpFunctionEnd
+ %main = OpFunction %void None %26
+ %28 = OpLabel
+ OpStore %tint_pointsize %float_1
+ %31 = OpLoad %uint %tint_symbol
+ %32 = OpLoad %int %tint_symbol_1
+ %33 = OpCompositeConstruct %VertexInputs0 %31 %32
+ %35 = OpLoad %float %tint_symbol_5
+ %36 = OpLoad %v4float %tint_symbol_6
+ %37 = OpCompositeConstruct %VertexInputs1 %35 %36
+ %38 = OpCompositeExtract %uint %33 0
+ %39 = OpLoad %uint %tint_symbol_4
+ %40 = OpIAdd %uint %38 %39
+ %41 = OpCompositeExtract %int %33 1
+ %42 = OpLoad %uint %tint_symbol_3
+ %43 = OpCompositeExtract %float %37 0
+ %44 = OpCompositeExtract %v4float %37 1
+ %45 = OpFunctionCall %void %tint_symbol_10 %20
+ OpReturn
+ OpFunctionEnd
diff --git a/test/shader_io/vertex_input_mixed.wgsl.expected.wgsl b/test/shader_io/vertex_input_mixed.wgsl.expected.wgsl
new file mode 100644
index 0000000..0cd61f6
--- /dev/null
+++ b/test/shader_io/vertex_input_mixed.wgsl.expected.wgsl
@@ -0,0 +1,23 @@
+struct VertexInputs0 {
+ [[builtin(vertex_index)]]
+ vertex_index : u32;
+ [[location(0)]]
+ loc0 : i32;
+};
+
+struct VertexInputs1 {
+ [[location(2)]]
+ loc2 : f32;
+ [[location(3)]]
+ loc3 : vec4<f32>;
+};
+
+[[stage(vertex)]]
+fn main(inputs0 : VertexInputs0, [[location(1)]] loc1 : u32, [[builtin(instance_index)]] instance_index : u32, inputs1 : VertexInputs1) -> [[builtin(position)]] vec4<f32> {
+ let foo : u32 = (inputs0.vertex_index + instance_index);
+ let i : i32 = inputs0.loc0;
+ let u : u32 = loc1;
+ let f : f32 = inputs1.loc2;
+ let v : vec4<f32> = inputs1.loc3;
+ return vec4<f32>();
+}
diff --git a/test/shader_io/vertex_output_builtins.wgsl b/test/shader_io/vertex_output_builtins.wgsl
new file mode 100644
index 0000000..46776de
--- /dev/null
+++ b/test/shader_io/vertex_output_builtins.wgsl
@@ -0,0 +1,4 @@
+[[stage(vertex)]]
+fn main() -> [[builtin(position)]] vec4<f32> {
+ return vec4<f32>(1.0, 2.0, 3.0, 4.0);
+}
diff --git a/test/shader_io/vertex_output_builtins.wgsl.expected.hlsl b/test/shader_io/vertex_output_builtins.wgsl.expected.hlsl
new file mode 100644
index 0000000..1c95996
--- /dev/null
+++ b/test/shader_io/vertex_output_builtins.wgsl.expected.hlsl
@@ -0,0 +1,9 @@
+struct tint_symbol {
+ float4 value : SV_Position;
+};
+
+tint_symbol main() {
+ const tint_symbol tint_symbol_1 = {float4(1.0f, 2.0f, 3.0f, 4.0f)};
+ return tint_symbol_1;
+}
+
diff --git a/test/shader_io/vertex_output_builtins.wgsl.expected.msl b/test/shader_io/vertex_output_builtins.wgsl.expected.msl
new file mode 100644
index 0000000..6cb014c
--- /dev/null
+++ b/test/shader_io/vertex_output_builtins.wgsl.expected.msl
@@ -0,0 +1,12 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct tint_symbol_1 {
+ float4 value [[position]];
+};
+
+vertex tint_symbol_1 tint_symbol() {
+ tint_symbol_1 const tint_symbol_2 = {float4(1.0f, 2.0f, 3.0f, 4.0f)};
+ return tint_symbol_2;
+}
+
diff --git a/test/shader_io/vertex_output_builtins.wgsl.expected.spvasm b/test/shader_io/vertex_output_builtins.wgsl.expected.spvasm
new file mode 100644
index 0000000..c92e684
--- /dev/null
+++ b/test/shader_io/vertex_output_builtins.wgsl.expected.spvasm
@@ -0,0 +1,43 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 23
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Vertex %main "main" %tint_pointsize %tint_symbol_1
+ OpName %tint_pointsize "tint_pointsize"
+ OpName %tint_symbol_1 "tint_symbol_1"
+ OpName %tint_symbol_2 "tint_symbol_2"
+ OpName %tint_symbol "tint_symbol"
+ OpName %main "main"
+ OpDecorate %tint_pointsize BuiltIn PointSize
+ OpDecorate %tint_symbol_1 BuiltIn Position
+ %float = OpTypeFloat 32
+%_ptr_Output_float = OpTypePointer Output %float
+ %4 = OpConstantNull %float
+%tint_pointsize = OpVariable %_ptr_Output_float Output %4
+ %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+ %8 = OpConstantNull %v4float
+%tint_symbol_1 = OpVariable %_ptr_Output_v4float Output %8
+ %void = OpTypeVoid
+ %9 = OpTypeFunction %void %v4float
+ %14 = OpTypeFunction %void
+ %float_1 = OpConstant %float 1
+ %float_2 = OpConstant %float 2
+ %float_3 = OpConstant %float 3
+ %float_4 = OpConstant %float 4
+ %22 = OpConstantComposite %v4float %float_1 %float_2 %float_3 %float_4
+%tint_symbol_2 = OpFunction %void None %9
+%tint_symbol = OpFunctionParameter %v4float
+ %13 = OpLabel
+ OpStore %tint_symbol_1 %tint_symbol
+ OpReturn
+ OpFunctionEnd
+ %main = OpFunction %void None %14
+ %16 = OpLabel
+ OpStore %tint_pointsize %float_1
+ %18 = OpFunctionCall %void %tint_symbol_2 %22
+ OpReturn
+ OpFunctionEnd
diff --git a/test/shader_io/vertex_output_builtins.wgsl.expected.wgsl b/test/shader_io/vertex_output_builtins.wgsl.expected.wgsl
new file mode 100644
index 0000000..46776de
--- /dev/null
+++ b/test/shader_io/vertex_output_builtins.wgsl.expected.wgsl
@@ -0,0 +1,4 @@
+[[stage(vertex)]]
+fn main() -> [[builtin(position)]] vec4<f32> {
+ return vec4<f32>(1.0, 2.0, 3.0, 4.0);
+}
diff --git a/test/shader_io/vertex_output_builtins_struct.wgsl b/test/shader_io/vertex_output_builtins_struct.wgsl
new file mode 100644
index 0000000..9e09d38
--- /dev/null
+++ b/test/shader_io/vertex_output_builtins_struct.wgsl
@@ -0,0 +1,8 @@
+struct VertexOutputs {
+ [[builtin(position)]] position : vec4<f32>;
+};
+
+[[stage(vertex)]]
+fn main() -> VertexOutputs {
+ return VertexOutputs(vec4<f32>(1.0, 2.0, 3.0, 4.0));
+}
diff --git a/test/shader_io/vertex_output_builtins_struct.wgsl.expected.hlsl b/test/shader_io/vertex_output_builtins_struct.wgsl.expected.hlsl
new file mode 100644
index 0000000..8cb1a5f
--- /dev/null
+++ b/test/shader_io/vertex_output_builtins_struct.wgsl.expected.hlsl
@@ -0,0 +1,13 @@
+struct VertexOutputs {
+ float4 position;
+};
+struct tint_symbol {
+ float4 position : SV_Position;
+};
+
+tint_symbol main() {
+ const VertexOutputs tint_symbol_1 = {float4(1.0f, 2.0f, 3.0f, 4.0f)};
+ const tint_symbol tint_symbol_2 = {tint_symbol_1.position};
+ return tint_symbol_2;
+}
+
diff --git a/test/shader_io/vertex_output_builtins_struct.wgsl.expected.msl b/test/shader_io/vertex_output_builtins_struct.wgsl.expected.msl
new file mode 100644
index 0000000..86fbbe5
--- /dev/null
+++ b/test/shader_io/vertex_output_builtins_struct.wgsl.expected.msl
@@ -0,0 +1,16 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct VertexOutputs {
+ float4 position;
+};
+struct tint_symbol_1 {
+ float4 position [[position]];
+};
+
+vertex tint_symbol_1 tint_symbol() {
+ VertexOutputs const tint_symbol_2 = {float4(1.0f, 2.0f, 3.0f, 4.0f)};
+ tint_symbol_1 const tint_symbol_3 = {tint_symbol_2.position};
+ return tint_symbol_3;
+}
+
diff --git a/test/shader_io/vertex_output_builtins_struct.wgsl.expected.spvasm b/test/shader_io/vertex_output_builtins_struct.wgsl.expected.spvasm
new file mode 100644
index 0000000..ae99bdc
--- /dev/null
+++ b/test/shader_io/vertex_output_builtins_struct.wgsl.expected.spvasm
@@ -0,0 +1,49 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 26
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Vertex %main "main" %tint_pointsize %tint_symbol_1
+ OpName %tint_pointsize "tint_pointsize"
+ OpName %tint_symbol_1 "tint_symbol_1"
+ OpName %VertexOutputs "VertexOutputs"
+ OpMemberName %VertexOutputs 0 "position"
+ OpName %tint_symbol_2 "tint_symbol_2"
+ OpName %tint_symbol "tint_symbol"
+ OpName %main "main"
+ OpDecorate %tint_pointsize BuiltIn PointSize
+ OpDecorate %tint_symbol_1 BuiltIn Position
+ OpMemberDecorate %VertexOutputs 0 Offset 0
+ %float = OpTypeFloat 32
+%_ptr_Output_float = OpTypePointer Output %float
+ %4 = OpConstantNull %float
+%tint_pointsize = OpVariable %_ptr_Output_float Output %4
+ %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+ %8 = OpConstantNull %v4float
+%tint_symbol_1 = OpVariable %_ptr_Output_v4float Output %8
+ %void = OpTypeVoid
+%VertexOutputs = OpTypeStruct %v4float
+ %9 = OpTypeFunction %void %VertexOutputs
+ %16 = OpTypeFunction %void
+ %float_1 = OpConstant %float 1
+ %float_2 = OpConstant %float 2
+ %float_3 = OpConstant %float 3
+ %float_4 = OpConstant %float 4
+ %24 = OpConstantComposite %v4float %float_1 %float_2 %float_3 %float_4
+ %25 = OpConstantComposite %VertexOutputs %24
+%tint_symbol_2 = OpFunction %void None %9
+%tint_symbol = OpFunctionParameter %VertexOutputs
+ %14 = OpLabel
+ %15 = OpCompositeExtract %v4float %tint_symbol 0
+ OpStore %tint_symbol_1 %15
+ OpReturn
+ OpFunctionEnd
+ %main = OpFunction %void None %16
+ %18 = OpLabel
+ OpStore %tint_pointsize %float_1
+ %20 = OpFunctionCall %void %tint_symbol_2 %25
+ OpReturn
+ OpFunctionEnd
diff --git a/test/shader_io/vertex_output_builtins_struct.wgsl.expected.wgsl b/test/shader_io/vertex_output_builtins_struct.wgsl.expected.wgsl
new file mode 100644
index 0000000..77d3b51
--- /dev/null
+++ b/test/shader_io/vertex_output_builtins_struct.wgsl.expected.wgsl
@@ -0,0 +1,9 @@
+struct VertexOutputs {
+ [[builtin(position)]]
+ position : vec4<f32>;
+};
+
+[[stage(vertex)]]
+fn main() -> VertexOutputs {
+ return VertexOutputs(vec4<f32>(1.0, 2.0, 3.0, 4.0));
+}
diff --git a/test/shader_io/vertex_output_locations_struct.wgsl b/test/shader_io/vertex_output_locations_struct.wgsl
new file mode 100644
index 0000000..a2303ed
--- /dev/null
+++ b/test/shader_io/vertex_output_locations_struct.wgsl
@@ -0,0 +1,12 @@
+struct VertexOutputs {
+ [[location(0)]] loc0 : i32;
+ [[location(1)]] loc1 : u32;
+ [[location(2)]] loc2 : f32;
+ [[location(3)]] loc3 : vec4<f32>;
+ [[builtin(position)]] position : vec4<f32>;
+};
+
+[[stage(vertex)]]
+fn main() -> VertexOutputs {
+ return VertexOutputs(1, 1u, 1.0, vec4<f32>(1.0, 2.0, 3.0, 4.0), vec4<f32>());
+}
diff --git a/test/shader_io/vertex_output_locations_struct.wgsl.expected.hlsl b/test/shader_io/vertex_output_locations_struct.wgsl.expected.hlsl
new file mode 100644
index 0000000..32ba657
--- /dev/null
+++ b/test/shader_io/vertex_output_locations_struct.wgsl.expected.hlsl
@@ -0,0 +1,21 @@
+struct VertexOutputs {
+ int loc0;
+ uint loc1;
+ float loc2;
+ float4 loc3;
+ float4 position;
+};
+struct tint_symbol {
+ int loc0 : TEXCOORD0;
+ uint loc1 : TEXCOORD1;
+ float loc2 : TEXCOORD2;
+ float4 loc3 : TEXCOORD3;
+ float4 position : SV_Position;
+};
+
+tint_symbol main() {
+ const VertexOutputs tint_symbol_1 = {1, 1u, 1.0f, float4(1.0f, 2.0f, 3.0f, 4.0f), float4(0.0f, 0.0f, 0.0f, 0.0f)};
+ const tint_symbol tint_symbol_2 = {tint_symbol_1.loc0, tint_symbol_1.loc1, tint_symbol_1.loc2, tint_symbol_1.loc3, tint_symbol_1.position};
+ return tint_symbol_2;
+}
+
diff --git a/test/shader_io/vertex_output_locations_struct.wgsl.expected.msl b/test/shader_io/vertex_output_locations_struct.wgsl.expected.msl
new file mode 100644
index 0000000..3bd0de3
--- /dev/null
+++ b/test/shader_io/vertex_output_locations_struct.wgsl.expected.msl
@@ -0,0 +1,24 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct VertexOutputs {
+ int loc0;
+ uint loc1;
+ float loc2;
+ float4 loc3;
+ float4 position;
+};
+struct tint_symbol_1 {
+ int loc0 [[user(locn0)]];
+ uint loc1 [[user(locn1)]];
+ float loc2 [[user(locn2)]];
+ float4 loc3 [[user(locn3)]];
+ float4 position [[position]];
+};
+
+vertex tint_symbol_1 tint_symbol() {
+ VertexOutputs const tint_symbol_2 = {1, 1u, 1.0f, float4(1.0f, 2.0f, 3.0f, 4.0f), float4()};
+ tint_symbol_1 const tint_symbol_3 = {tint_symbol_2.loc0, tint_symbol_2.loc1, tint_symbol_2.loc2, tint_symbol_2.loc3, tint_symbol_2.position};
+ return tint_symbol_3;
+}
+
diff --git a/test/shader_io/vertex_output_locations_struct.wgsl.expected.spvasm b/test/shader_io/vertex_output_locations_struct.wgsl.expected.spvasm
new file mode 100644
index 0000000..dffd402
--- /dev/null
+++ b/test/shader_io/vertex_output_locations_struct.wgsl.expected.spvasm
@@ -0,0 +1,85 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 42
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Vertex %main "main" %tint_pointsize %tint_symbol_1 %tint_symbol_2 %tint_symbol_3 %tint_symbol_4 %tint_symbol_5
+ OpName %tint_pointsize "tint_pointsize"
+ OpName %tint_symbol_1 "tint_symbol_1"
+ OpName %tint_symbol_2 "tint_symbol_2"
+ OpName %tint_symbol_3 "tint_symbol_3"
+ OpName %tint_symbol_4 "tint_symbol_4"
+ OpName %tint_symbol_5 "tint_symbol_5"
+ OpName %VertexOutputs "VertexOutputs"
+ OpMemberName %VertexOutputs 0 "loc0"
+ OpMemberName %VertexOutputs 1 "loc1"
+ OpMemberName %VertexOutputs 2 "loc2"
+ OpMemberName %VertexOutputs 3 "loc3"
+ OpMemberName %VertexOutputs 4 "position"
+ OpName %tint_symbol_6 "tint_symbol_6"
+ OpName %tint_symbol "tint_symbol"
+ OpName %main "main"
+ OpDecorate %tint_pointsize BuiltIn PointSize
+ OpDecorate %tint_symbol_1 Location 0
+ OpDecorate %tint_symbol_2 Location 1
+ OpDecorate %tint_symbol_3 Location 2
+ OpDecorate %tint_symbol_4 Location 3
+ OpDecorate %tint_symbol_5 BuiltIn Position
+ OpMemberDecorate %VertexOutputs 0 Offset 0
+ OpMemberDecorate %VertexOutputs 1 Offset 4
+ OpMemberDecorate %VertexOutputs 2 Offset 8
+ OpMemberDecorate %VertexOutputs 3 Offset 16
+ OpMemberDecorate %VertexOutputs 4 Offset 32
+ %float = OpTypeFloat 32
+%_ptr_Output_float = OpTypePointer Output %float
+ %4 = OpConstantNull %float
+%tint_pointsize = OpVariable %_ptr_Output_float Output %4
+ %int = OpTypeInt 32 1
+%_ptr_Output_int = OpTypePointer Output %int
+ %8 = OpConstantNull %int
+%tint_symbol_1 = OpVariable %_ptr_Output_int Output %8
+ %uint = OpTypeInt 32 0
+%_ptr_Output_uint = OpTypePointer Output %uint
+ %12 = OpConstantNull %uint
+%tint_symbol_2 = OpVariable %_ptr_Output_uint Output %12
+%tint_symbol_3 = OpVariable %_ptr_Output_float Output %4
+ %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+ %17 = OpConstantNull %v4float
+%tint_symbol_4 = OpVariable %_ptr_Output_v4float Output %17
+%tint_symbol_5 = OpVariable %_ptr_Output_v4float Output %17
+ %void = OpTypeVoid
+%VertexOutputs = OpTypeStruct %int %uint %float %v4float %v4float
+ %19 = OpTypeFunction %void %VertexOutputs
+ %30 = OpTypeFunction %void
+ %float_1 = OpConstant %float 1
+ %int_1 = OpConstant %int 1
+ %uint_1 = OpConstant %uint 1
+ %float_2 = OpConstant %float 2
+ %float_3 = OpConstant %float 3
+ %float_4 = OpConstant %float 4
+ %40 = OpConstantComposite %v4float %float_1 %float_2 %float_3 %float_4
+ %41 = OpConstantComposite %VertexOutputs %int_1 %uint_1 %float_1 %40 %17
+%tint_symbol_6 = OpFunction %void None %19
+%tint_symbol = OpFunctionParameter %VertexOutputs
+ %24 = OpLabel
+ %25 = OpCompositeExtract %int %tint_symbol 0
+ OpStore %tint_symbol_1 %25
+ %26 = OpCompositeExtract %uint %tint_symbol 1
+ OpStore %tint_symbol_2 %26
+ %27 = OpCompositeExtract %float %tint_symbol 2
+ OpStore %tint_symbol_3 %27
+ %28 = OpCompositeExtract %v4float %tint_symbol 3
+ OpStore %tint_symbol_4 %28
+ %29 = OpCompositeExtract %v4float %tint_symbol 4
+ OpStore %tint_symbol_5 %29
+ OpReturn
+ OpFunctionEnd
+ %main = OpFunction %void None %30
+ %32 = OpLabel
+ OpStore %tint_pointsize %float_1
+ %34 = OpFunctionCall %void %tint_symbol_6 %41
+ OpReturn
+ OpFunctionEnd
diff --git a/test/shader_io/vertex_output_locations_struct.wgsl.expected.wgsl b/test/shader_io/vertex_output_locations_struct.wgsl.expected.wgsl
new file mode 100644
index 0000000..8716f56
--- /dev/null
+++ b/test/shader_io/vertex_output_locations_struct.wgsl.expected.wgsl
@@ -0,0 +1,17 @@
+struct VertexOutputs {
+ [[location(0)]]
+ loc0 : i32;
+ [[location(1)]]
+ loc1 : u32;
+ [[location(2)]]
+ loc2 : f32;
+ [[location(3)]]
+ loc3 : vec4<f32>;
+ [[builtin(position)]]
+ position : vec4<f32>;
+};
+
+[[stage(vertex)]]
+fn main() -> VertexOutputs {
+ return VertexOutputs(1, 1u, 1.0, vec4<f32>(1.0, 2.0, 3.0, 4.0), vec4<f32>());
+}