tint/writer/spirv: Clean up accessor tests
Remove duplicate tests.
Use a common pattern of sanitizing, building and dumping the whole
module instead of calling individual methods. There's too much internal
state being tracked in the tests for my liking.
Split most tests into three:
* Const_* tests will check the emission of creation-time-constant
expressions.
* Runtime_* tests will check the emission of runtime expressions, where
indexing operates with a constant index.
* Dynamic_* tests will check the emission of runtime expressions, where
indexing operates with a runtime index.
Bug: tint:1580
Change-Id: I0f92aaaa570cbd917d2b6937c6396605c6b542c9
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/94333
Reviewed-by: David Neto <dneto@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
diff --git a/src/tint/writer/spirv/builder_accessor_expression_test.cc b/src/tint/writer/spirv/builder_accessor_expression_test.cc
index c04ef6e..7ebed63 100644
--- a/src/tint/writer/spirv/builder_accessor_expression_test.cc
+++ b/src/tint/writer/spirv/builder_accessor_expression_test.cc
@@ -22,193 +22,742 @@
using BuilderTest = TestHelper;
-TEST_F(BuilderTest, IndexAccessor_VectorRef_Literal) {
- // var ary : vec3<f32>;
- // ary[1] -> ref<f32>
+TEST_F(BuilderTest, Const_IndexAccessor_Vector) {
+ // let ary = vec3<i32>(1, 2, 3);
+ // var x = ary[1i];
- auto* var = Var("ary", ty.vec3<f32>());
+ auto* ary = Let("ary", nullptr, vec3<i32>(1_i, 2_i, 3_i));
+ auto* x = Var("x", nullptr, IndexAccessor(ary, 1_i));
+ WrapInFunction(ary, x);
- auto* ary = Expr("ary");
- auto* idx_expr = Expr(1_i);
+ spirv::Builder& b = SanitizeAndBuild();
- auto* expr = IndexAccessor(ary, idx_expr);
- WrapInFunction(var, expr);
+ ASSERT_TRUE(b.Build()) << b.error();
- spirv::Builder& b = Build();
-
- b.push_function(Function{});
- ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.error();
-
- EXPECT_EQ(b.GenerateAccessorExpression(expr), 9u);
-
- EXPECT_EQ(DumpInstructions(b.types()), R"(%4 = OpTypeFloat 32
-%3 = OpTypeVector %4 3
-%2 = OpTypePointer Function %3
-%5 = OpConstantNull %3
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeVoid
+%1 = OpTypeFunction %2
%6 = OpTypeInt 32 1
-%7 = OpConstant %6 1
-%8 = OpTypePointer Function %4
-)");
- EXPECT_EQ(DumpInstructions(b.functions()[0].variables()),
- R"(%1 = OpVariable %2 Function %5
-)");
- EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
- R"(%9 = OpAccessChain %8 %1 %7
-)");
-}
-
-TEST_F(BuilderTest, IndexAccessor_VectorRef_Dynamic) {
- // var ary : vec3<f32>;
- // var idx : i32;
- // ary[idx] -> ref<f32>
-
- auto* var = Var("ary", ty.vec3<f32>());
- auto* idx = Var("idx", ty.i32());
-
- auto* ary = Expr("ary");
- auto* idx_expr = Expr("idx");
-
- auto* expr = IndexAccessor(ary, idx_expr);
- WrapInFunction(var, idx, expr);
-
- spirv::Builder& b = Build();
-
- b.push_function(Function{});
- ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.error();
- ASSERT_TRUE(b.GenerateFunctionVariable(idx)) << b.error();
-
- EXPECT_EQ(b.GenerateAccessorExpression(expr), 12u);
-
- EXPECT_EQ(DumpInstructions(b.types()), R"(%4 = OpTypeFloat 32
-%3 = OpTypeVector %4 3
-%2 = OpTypePointer Function %3
-%5 = OpConstantNull %3
-%8 = OpTypeInt 32 1
-%7 = OpTypePointer Function %8
-%9 = OpConstantNull %8
-%11 = OpTypePointer Function %4
-)");
- EXPECT_EQ(DumpInstructions(b.functions()[0].variables()),
- R"(%1 = OpVariable %2 Function %5
-%6 = OpVariable %7 Function %9
-)");
- EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
- R"(%10 = OpLoad %8 %6
-%12 = OpAccessChain %11 %1 %10
-)");
-}
-
-TEST_F(BuilderTest, IndexAccessor_VectorRef_Dynamic2) {
- // var ary : vec3<f32>;
- // ary[1 + 2] -> ref<f32>
-
- auto* var = Var("ary", ty.vec3<f32>());
-
- auto* ary = Expr("ary");
-
- auto* expr = IndexAccessor(ary, Add(1_i, 2_i));
- WrapInFunction(var, expr);
-
- spirv::Builder& b = Build();
-
- b.push_function(Function{});
- ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.error();
-
- EXPECT_EQ(b.GenerateAccessorExpression(expr), 11u);
-
- EXPECT_EQ(DumpInstructions(b.types()), R"(%4 = OpTypeFloat 32
-%3 = OpTypeVector %4 3
-%2 = OpTypePointer Function %3
-%5 = OpConstantNull %3
-%6 = OpTypeInt 32 1
+%5 = OpTypeVector %6 3
%7 = OpConstant %6 1
%8 = OpConstant %6 2
-%10 = OpTypePointer Function %4
+%9 = OpConstant %6 3
+%10 = OpConstantComposite %5 %7 %8 %9
+%12 = OpTypePointer Function %6
+%13 = OpConstantNull %6
)");
- EXPECT_EQ(DumpInstructions(b.functions()[0].variables()),
- R"(%1 = OpVariable %2 Function %5
+ EXPECT_EQ(DumpInstructions(b.functions()[0].variables()), R"(%11 = OpVariable %12 Function %13
)");
- EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
- R"(%9 = OpIAdd %6 %7 %8
-%11 = OpAccessChain %10 %1 %9
+ EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"(OpStore %11 %8
+OpReturn
)");
+
+ Validate(b);
}
-TEST_F(BuilderTest, IndexAccessor_ArrayRef_MultiLevel) {
- auto* ary4 = ty.array(ty.vec3<f32>(), 4_u);
+TEST_F(BuilderTest, Runtime_IndexAccessor_Vector) {
+ // var ary : vec3<u32>;
+ // var x = ary[1i];
- // var ary : array<vec3<f32>, 4u>
- // ary[3i][2i];
+ auto* ary = Var("ary", ty.vec3<u32>());
+ auto* x = Var("x", nullptr, IndexAccessor(ary, 1_i));
+ WrapInFunction(ary, x);
- auto* var = Var("ary", ary4);
+ spirv::Builder& b = SanitizeAndBuild();
- auto* expr = IndexAccessor(IndexAccessor("ary", 3_i), 2_i);
- WrapInFunction(var, expr);
+ ASSERT_TRUE(b.Build()) << b.error();
- spirv::Builder& b = Build();
-
- b.push_function(Function{});
- ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.error();
-
- EXPECT_EQ(b.GenerateAccessorExpression(expr), 13u);
-
- EXPECT_EQ(DumpInstructions(b.types()), R"(%5 = OpTypeFloat 32
-%4 = OpTypeVector %5 3
-%6 = OpTypeInt 32 0
-%7 = OpConstant %6 4
-%3 = OpTypeArray %4 %7
-%2 = OpTypePointer Function %3
-%8 = OpConstantNull %3
-%9 = OpTypeInt 32 1
-%10 = OpConstant %9 3
-%11 = OpConstant %9 2
-%12 = OpTypePointer Function %5
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeVoid
+%1 = OpTypeFunction %2
+%8 = OpTypeInt 32 0
+%7 = OpTypeVector %8 3
+%6 = OpTypePointer Function %7
+%9 = OpConstantNull %7
+%10 = OpTypeInt 32 1
+%11 = OpConstant %10 1
+%12 = OpTypePointer Function %8
+%16 = OpConstantNull %8
)");
- EXPECT_EQ(DumpInstructions(b.functions()[0].variables()),
- R"(%1 = OpVariable %2 Function %8
+ EXPECT_EQ(DumpInstructions(b.functions()[0].variables()), R"(%5 = OpVariable %6 Function %9
+%15 = OpVariable %12 Function %16
)");
- EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
- R"(%13 = OpAccessChain %12 %1 %10 %11
+ EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"(%13 = OpAccessChain %12 %5 %11
+%14 = OpLoad %8 %13
+OpStore %15 %14
+OpReturn
)");
+
+ Validate(b);
}
-TEST_F(BuilderTest, IndexAccessor_ArrayRef_ArrayWithSwizzle) {
- auto* ary4 = ty.array(ty.vec3<f32>(), 4_u);
+TEST_F(BuilderTest, Dynamic_IndexAccessor_Vector) {
+ // var ary : vec3<f32>;
+ // var idx : i32;
+ // var x = ary[idx];
- // var a : array<vec3<f32>, 4u>;
- // a[2i].xy;
+ auto* ary = Var("ary", ty.vec3<f32>());
+ auto* idx = Var("idx", ty.i32());
+ auto* x = Var("x", nullptr, IndexAccessor(ary, idx));
+ WrapInFunction(ary, idx, x);
- auto* var = Var("ary", ary4);
+ spirv::Builder& b = SanitizeAndBuild();
- auto* expr = MemberAccessor(IndexAccessor("ary", 2_i), "xy");
- WrapInFunction(var, expr);
+ ASSERT_TRUE(b.Build()) << b.error();
- spirv::Builder& b = Build();
-
- b.push_function(Function{});
- ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.error();
- EXPECT_EQ(b.GenerateAccessorExpression(expr), 15u);
-
- EXPECT_EQ(DumpInstructions(b.types()), R"(%5 = OpTypeFloat 32
-%4 = OpTypeVector %5 3
-%6 = OpTypeInt 32 0
-%7 = OpConstant %6 4
-%3 = OpTypeArray %4 %7
-%2 = OpTypePointer Function %3
-%8 = OpConstantNull %3
-%9 = OpTypeInt 32 1
-%10 = OpConstant %9 2
-%11 = OpTypePointer Function %4
-%13 = OpTypeVector %5 2
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeVoid
+%1 = OpTypeFunction %2
+%8 = OpTypeFloat 32
+%7 = OpTypeVector %8 3
+%6 = OpTypePointer Function %7
+%9 = OpConstantNull %7
+%12 = OpTypeInt 32 1
+%11 = OpTypePointer Function %12
+%13 = OpConstantNull %12
+%15 = OpTypePointer Function %8
+%19 = OpConstantNull %8
)");
- EXPECT_EQ(DumpInstructions(b.functions()[0].variables()),
- R"(%1 = OpVariable %2 Function %8
+ EXPECT_EQ(DumpInstructions(b.functions()[0].variables()), R"(%5 = OpVariable %6 Function %9
+%10 = OpVariable %11 Function %13
+%18 = OpVariable %15 Function %19
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"(%14 = OpLoad %12 %10
+%16 = OpAccessChain %15 %5 %14
+%17 = OpLoad %8 %16
+OpStore %18 %17
+OpReturn
+)");
+
+ Validate(b);
+}
+
+TEST_F(BuilderTest, Const_IndexAccessor_Vector2) {
+ // let ary : vec3<i32>(1, 2, 3);
+ // var x = ary[1i + 2i];
+
+ auto* ary = Let("ary", nullptr, vec3<i32>(1_i, 2_i, 3_i));
+ auto* x = Var("x", nullptr, IndexAccessor(ary, Add(1_i, 2_i)));
+ WrapInFunction(ary, x);
+
+ spirv::Builder& b = SanitizeAndBuild();
+
+ ASSERT_TRUE(b.Build()) << b.error();
+
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeVoid
+%1 = OpTypeFunction %2
+%6 = OpTypeInt 32 1
+%5 = OpTypeVector %6 3
+%7 = OpConstant %6 1
+%8 = OpConstant %6 2
+%9 = OpConstant %6 3
+%10 = OpConstantComposite %5 %7 %8 %9
+%14 = OpTypePointer Function %6
+%15 = OpConstantNull %6
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].variables()), R"(%13 = OpVariable %14 Function %15
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"(%11 = OpIAdd %6 %7 %8
+%12 = OpVectorExtractDynamic %6 %10 %11
+OpStore %13 %12
+OpReturn
+)");
+
+ Validate(b);
+}
+
+TEST_F(BuilderTest, Runtime_IndexAccessor_Vector2) {
+ // var ary : vec3<f32>;
+ // var x = ary[1i + 2i];
+
+ auto* ary = Var("ary", ty.vec3<f32>());
+ auto* x = Var("x", nullptr, IndexAccessor(ary, Add(1_i, 2_i)));
+ WrapInFunction(ary, x);
+
+ spirv::Builder& b = SanitizeAndBuild();
+
+ ASSERT_TRUE(b.Build()) << b.error();
+
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeVoid
+%1 = OpTypeFunction %2
+%8 = OpTypeFloat 32
+%7 = OpTypeVector %8 3
+%6 = OpTypePointer Function %7
+%9 = OpConstantNull %7
+%10 = OpTypeInt 32 1
+%11 = OpConstant %10 1
+%12 = OpConstant %10 2
+%14 = OpTypePointer Function %8
+%18 = OpConstantNull %8
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].variables()), R"(%5 = OpVariable %6 Function %9
+%17 = OpVariable %14 Function %18
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"(%13 = OpIAdd %10 %11 %12
+%15 = OpAccessChain %14 %5 %13
+%16 = OpLoad %8 %15
+OpStore %17 %16
+OpReturn
+)");
+
+ Validate(b);
+}
+
+TEST_F(BuilderTest, Dynamic_IndexAccessor_Vector2) {
+ // var ary : vec3<f32>;
+ // var one = 1i;
+ // var x = ary[one + 2i];
+
+ auto* ary = Var("ary", ty.vec3<f32>());
+ auto* one = Var("one", nullptr, Expr(1_i));
+ auto* x = Var("x", nullptr, IndexAccessor(ary, Add(one, 2_i)));
+ WrapInFunction(ary, one, x);
+
+ spirv::Builder& b = SanitizeAndBuild();
+
+ ASSERT_TRUE(b.Build()) << b.error();
+
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeVoid
+%1 = OpTypeFunction %2
+%8 = OpTypeFloat 32
+%7 = OpTypeVector %8 3
+%6 = OpTypePointer Function %7
+%9 = OpConstantNull %7
+%10 = OpTypeInt 32 1
+%11 = OpConstant %10 1
+%13 = OpTypePointer Function %10
+%14 = OpConstantNull %10
+%16 = OpConstant %10 2
+%18 = OpTypePointer Function %8
+%22 = OpConstantNull %8
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].variables()), R"(%5 = OpVariable %6 Function %9
+%12 = OpVariable %13 Function %14
+%21 = OpVariable %18 Function %22
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"(OpStore %12 %11
+%15 = OpLoad %10 %12
+%17 = OpIAdd %10 %15 %16
+%19 = OpAccessChain %18 %5 %17
+%20 = OpLoad %8 %19
+OpStore %21 %20
+OpReturn
+)");
+
+ Validate(b);
+}
+
+TEST_F(BuilderTest, Const_IndexAccessor_Array_MultiLevel) {
+ // let ary = array<vec3<f32>, 2u>(vec3<f32>(1.0f, 2.0f, 3.0f), vec3<f32>(4.0f, 5.0f, 6.0f));
+ // var x = ary[1i][2i];
+
+ auto* ary =
+ Let("ary", nullptr,
+ array(ty.vec3<f32>(), 2_u, vec3<f32>(1._f, 2._f, 3._f), vec3<f32>(4._f, 5._f, 6._f)));
+ auto* x = Var("x", nullptr, IndexAccessor(IndexAccessor(ary, 1_i), 2_i));
+ WrapInFunction(ary, x);
+
+ spirv::Builder& b = SanitizeAndBuild();
+
+ ASSERT_TRUE(b.Build()) << b.error();
+
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeVoid
+%1 = OpTypeFunction %2
+%7 = OpTypeFloat 32
+%6 = OpTypeVector %7 3
+%8 = OpTypeInt 32 0
+%9 = OpConstant %8 2
+%5 = OpTypeArray %6 %9
+%10 = OpConstant %7 1
+%11 = OpConstant %7 2
+%12 = OpConstant %7 3
+%13 = OpConstantComposite %6 %10 %11 %12
+%14 = OpConstant %7 4
+%15 = OpConstant %7 5
+%16 = OpConstant %7 6
+%17 = OpConstantComposite %6 %14 %15 %16
+%18 = OpConstantComposite %5 %13 %17
+%19 = OpTypeInt 32 1
+%20 = OpConstant %19 1
+%22 = OpConstant %19 2
+%25 = OpTypePointer Function %7
+%26 = OpConstantNull %7
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].variables()), R"(%24 = OpVariable %25 Function %26
)");
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
- R"(%12 = OpAccessChain %11 %1 %10
-%14 = OpLoad %4 %12
-%15 = OpVectorShuffle %13 %14 %14 0 1
+ R"(%21 = OpCompositeExtract %6 %18 1
+%23 = OpCompositeExtract %7 %21 2
+OpStore %24 %23
+OpReturn
)");
+
+ Validate(b);
+}
+
+TEST_F(BuilderTest, Runtime_IndexAccessor_Array_MultiLevel) {
+ // var ary : array<vec3<f32>, 4u>;
+ // var x = ary[1i][2i];
+
+ auto* ary = Var("ary", ty.array(ty.vec3<f32>(), 4_u));
+ auto* x = Var("x", nullptr, IndexAccessor(IndexAccessor(ary, 1_i), 2_i));
+ WrapInFunction(ary, x);
+
+ spirv::Builder& b = SanitizeAndBuild();
+
+ ASSERT_TRUE(b.Build()) << b.error();
+
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeVoid
+%1 = OpTypeFunction %2
+%9 = OpTypeFloat 32
+%8 = OpTypeVector %9 3
+%10 = OpTypeInt 32 0
+%11 = OpConstant %10 4
+%7 = OpTypeArray %8 %11
+%6 = OpTypePointer Function %7
+%12 = OpConstantNull %7
+%13 = OpTypeInt 32 1
+%14 = OpConstant %13 1
+%15 = OpConstant %13 2
+%16 = OpTypePointer Function %9
+%20 = OpConstantNull %9
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].variables()), R"(%5 = OpVariable %6 Function %12
+%19 = OpVariable %16 Function %20
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
+ R"(%17 = OpAccessChain %16 %5 %14 %15
+%18 = OpLoad %9 %17
+OpStore %19 %18
+OpReturn
+)");
+
+ Validate(b);
+}
+
+TEST_F(BuilderTest, Dynamic_IndexAccessor_Array_MultiLevel) {
+ // var ary : array<vec3<f32>, 4u>;
+ // var one = 1i;
+ // var x = ary[one][2i];
+
+ auto* ary = Var("ary", ty.array(ty.vec3<f32>(), 4_u));
+ auto* one = Var("one", nullptr, Expr(3_i));
+ auto* x = Var("x", nullptr, IndexAccessor(IndexAccessor(ary, one), 2_i));
+ WrapInFunction(ary, one, x);
+
+ spirv::Builder& b = SanitizeAndBuild();
+
+ ASSERT_TRUE(b.Build()) << b.error();
+
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeVoid
+%1 = OpTypeFunction %2
+%9 = OpTypeFloat 32
+%8 = OpTypeVector %9 3
+%10 = OpTypeInt 32 0
+%11 = OpConstant %10 4
+%7 = OpTypeArray %8 %11
+%6 = OpTypePointer Function %7
+%12 = OpConstantNull %7
+%13 = OpTypeInt 32 1
+%14 = OpConstant %13 3
+%16 = OpTypePointer Function %13
+%17 = OpConstantNull %13
+%19 = OpConstant %13 2
+%20 = OpTypePointer Function %9
+%24 = OpConstantNull %9
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].variables()), R"(%5 = OpVariable %6 Function %12
+%15 = OpVariable %16 Function %17
+%23 = OpVariable %20 Function %24
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"(OpStore %15 %14
+%18 = OpLoad %13 %15
+%21 = OpAccessChain %20 %5 %18 %19
+%22 = OpLoad %9 %21
+OpStore %23 %22
+OpReturn
+)");
+
+ Validate(b);
+}
+
+TEST_F(BuilderTest, Const_IndexAccessor_Array_ArrayWithSwizzle) {
+ // let ary = array<vec3<f32>, 2u>(vec3<f32>(1.0f, 2.0f, 3.0f), vec3<f32>(4.0f, 5.0f, 6.0f));
+ // var x = a[1i].xy;
+
+ auto* ary =
+ Let("ary", nullptr,
+ array(ty.vec3<f32>(), 2_u, vec3<f32>(1._f, 2._f, 3._f), vec3<f32>(4._f, 5._f, 6._f)));
+ auto* x = Var("x", nullptr, MemberAccessor(IndexAccessor("ary", 1_i), "xy"));
+ WrapInFunction(ary, x);
+
+ spirv::Builder& b = SanitizeAndBuild();
+
+ ASSERT_TRUE(b.Build()) << b.error();
+
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeVoid
+%1 = OpTypeFunction %2
+%7 = OpTypeFloat 32
+%6 = OpTypeVector %7 3
+%8 = OpTypeInt 32 0
+%9 = OpConstant %8 2
+%5 = OpTypeArray %6 %9
+%10 = OpConstant %7 1
+%11 = OpConstant %7 2
+%12 = OpConstant %7 3
+%13 = OpConstantComposite %6 %10 %11 %12
+%14 = OpConstant %7 4
+%15 = OpConstant %7 5
+%16 = OpConstant %7 6
+%17 = OpConstantComposite %6 %14 %15 %16
+%18 = OpConstantComposite %5 %13 %17
+%19 = OpTypeInt 32 1
+%20 = OpConstant %19 1
+%22 = OpTypeVector %7 2
+%25 = OpTypePointer Function %22
+%26 = OpConstantNull %22
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].variables()), R"(%24 = OpVariable %25 Function %26
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
+ R"(%21 = OpCompositeExtract %6 %18 1
+%23 = OpVectorShuffle %22 %21 %21 0 1
+OpStore %24 %23
+OpReturn
+)");
+
+ Validate(b);
+}
+
+TEST_F(BuilderTest, Runtime_IndexAccessor_Array_ArrayWithSwizzle) {
+ // var ary : array<vec3<f32>, 4u>;
+ // var x = ary[1i].xy;
+
+ auto* ary = Var("ary", ty.array(ty.vec3<f32>(), 4_u));
+ auto* x = Var("x", nullptr, MemberAccessor(IndexAccessor("ary", 1_i), "xy"));
+ WrapInFunction(ary, x);
+
+ spirv::Builder& b = SanitizeAndBuild();
+
+ ASSERT_TRUE(b.Build()) << b.error();
+
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeVoid
+%1 = OpTypeFunction %2
+%9 = OpTypeFloat 32
+%8 = OpTypeVector %9 3
+%10 = OpTypeInt 32 0
+%11 = OpConstant %10 4
+%7 = OpTypeArray %8 %11
+%6 = OpTypePointer Function %7
+%12 = OpConstantNull %7
+%13 = OpTypeInt 32 1
+%14 = OpConstant %13 1
+%15 = OpTypePointer Function %8
+%17 = OpTypeVector %9 2
+%21 = OpTypePointer Function %17
+%22 = OpConstantNull %17
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].variables()), R"(%5 = OpVariable %6 Function %12
+%20 = OpVariable %21 Function %22
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"(%16 = OpAccessChain %15 %5 %14
+%18 = OpLoad %8 %16
+%19 = OpVectorShuffle %17 %18 %18 0 1
+OpStore %20 %19
+OpReturn
+)");
+
+ Validate(b);
+}
+
+TEST_F(BuilderTest, Dynamic_IndexAccessor_Array_ArrayWithSwizzle) {
+ // var ary : array<vec3<f32>, 4u>;
+ // var one = 1i;
+ // var x = ary[one].xy;
+
+ auto* ary = Var("ary", ty.array(ty.vec3<f32>(), 4_u));
+ auto* one = Var("one", nullptr, Expr(1_i));
+ auto* x = Var("x", nullptr, MemberAccessor(IndexAccessor("ary", one), "xy"));
+ WrapInFunction(ary, one, x);
+
+ spirv::Builder& b = SanitizeAndBuild();
+
+ ASSERT_TRUE(b.Build()) << b.error();
+
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeVoid
+%1 = OpTypeFunction %2
+%9 = OpTypeFloat 32
+%8 = OpTypeVector %9 3
+%10 = OpTypeInt 32 0
+%11 = OpConstant %10 4
+%7 = OpTypeArray %8 %11
+%6 = OpTypePointer Function %7
+%12 = OpConstantNull %7
+%13 = OpTypeInt 32 1
+%14 = OpConstant %13 1
+%16 = OpTypePointer Function %13
+%17 = OpConstantNull %13
+%19 = OpTypePointer Function %8
+%21 = OpTypeVector %9 2
+%25 = OpTypePointer Function %21
+%26 = OpConstantNull %21
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].variables()), R"(%5 = OpVariable %6 Function %12
+%15 = OpVariable %16 Function %17
+%24 = OpVariable %25 Function %26
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"(OpStore %15 %14
+%18 = OpLoad %13 %15
+%20 = OpAccessChain %19 %5 %18
+%22 = OpLoad %8 %20
+%23 = OpVectorShuffle %21 %22 %22 0 1
+OpStore %24 %23
+OpReturn
+)");
+
+ Validate(b);
+}
+
+TEST_F(BuilderTest, Const_IndexAccessor_Nested_Array_f32) {
+ // let pos : array<array<f32, 2>, 3u> = array<vec2<f32, 2>, 3u>(
+ // array<f32, 2>(0.0, 0.5),
+ // array<f32, 2>(-0.5, -0.5),
+ // array<f32, 2>(0.5, -0.5));
+ // var x = pos[1u][0u];
+
+ auto* pos = Let("pos", ty.array(ty.vec2<f32>(), 3_u),
+ Construct(ty.array(ty.vec2<f32>(), 3_u), vec2<f32>(0_f, 0.5_f),
+ vec2<f32>(-0.5_f, -0.5_f), vec2<f32>(0.5_f, -0.5_f)));
+ auto* x = Var("x", nullptr, IndexAccessor(IndexAccessor(pos, 1_u), 0_u));
+ WrapInFunction(pos, x);
+
+ spirv::Builder& b = SanitizeAndBuild();
+
+ ASSERT_TRUE(b.Build()) << b.error();
+
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeVoid
+%1 = OpTypeFunction %2
+%7 = OpTypeFloat 32
+%6 = OpTypeVector %7 2
+%8 = OpTypeInt 32 0
+%9 = OpConstant %8 3
+%5 = OpTypeArray %6 %9
+%10 = OpConstantNull %7
+%11 = OpConstant %7 0.5
+%12 = OpConstantComposite %6 %10 %11
+%13 = OpConstant %7 -0.5
+%14 = OpConstantComposite %6 %13 %13
+%15 = OpConstantComposite %6 %11 %13
+%16 = OpConstantComposite %5 %12 %14 %15
+%17 = OpConstant %8 1
+%19 = OpConstantNull %8
+%22 = OpTypePointer Function %7
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].variables()), R"(%21 = OpVariable %22 Function %10
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
+ R"(%18 = OpCompositeExtract %6 %16 1
+%20 = OpCompositeExtract %7 %18 0
+OpStore %21 %20
+OpReturn
+)");
+
+ Validate(b);
+}
+
+TEST_F(BuilderTest, Runtime_IndexAccessor_Nested_Array_f32) {
+ // var pos : array<array<f32, 2>, 3u>;
+ // var x = pos[1u][2u];
+
+ auto* pos = Var("pos", ty.array(ty.vec2<f32>(), 3_u));
+ auto* x = Var("x", nullptr, IndexAccessor(IndexAccessor(pos, 1_u), 2_u));
+ WrapInFunction(pos, x);
+
+ spirv::Builder& b = SanitizeAndBuild();
+
+ ASSERT_TRUE(b.Build()) << b.error();
+
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeVoid
+%1 = OpTypeFunction %2
+%9 = OpTypeFloat 32
+%8 = OpTypeVector %9 2
+%10 = OpTypeInt 32 0
+%11 = OpConstant %10 3
+%7 = OpTypeArray %8 %11
+%6 = OpTypePointer Function %7
+%12 = OpConstantNull %7
+%13 = OpConstant %10 1
+%14 = OpConstant %10 2
+%15 = OpTypePointer Function %9
+%19 = OpConstantNull %9
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].variables()), R"(%5 = OpVariable %6 Function %12
+%18 = OpVariable %15 Function %19
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
+ R"(%16 = OpAccessChain %15 %5 %13 %14
+%17 = OpLoad %9 %16
+OpStore %18 %17
+OpReturn
+)");
+
+ Validate(b);
+}
+
+TEST_F(BuilderTest, Dynamic_IndexAccessor_Nested_Array_f32) {
+ // var pos : array<array<f32, 2>, 3u>;
+ // var one = 1u;
+ // var x = pos[one][2u];
+
+ auto* pos = Var("pos", ty.array(ty.vec2<f32>(), 3_u));
+ auto* one = Var("one", nullptr, Expr(2_u));
+ auto* x = Var("x", nullptr, IndexAccessor(IndexAccessor(pos, "one"), 2_u));
+ WrapInFunction(pos, one, x);
+
+ spirv::Builder& b = SanitizeAndBuild();
+
+ ASSERT_TRUE(b.Build()) << b.error();
+
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeVoid
+%1 = OpTypeFunction %2
+%9 = OpTypeFloat 32
+%8 = OpTypeVector %9 2
+%10 = OpTypeInt 32 0
+%11 = OpConstant %10 3
+%7 = OpTypeArray %8 %11
+%6 = OpTypePointer Function %7
+%12 = OpConstantNull %7
+%13 = OpConstant %10 2
+%15 = OpTypePointer Function %10
+%16 = OpConstantNull %10
+%18 = OpTypePointer Function %9
+%22 = OpConstantNull %9
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].variables()), R"(%5 = OpVariable %6 Function %12
+%14 = OpVariable %15 Function %16
+%21 = OpVariable %18 Function %22
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"(OpStore %14 %13
+%17 = OpLoad %10 %14
+%19 = OpAccessChain %18 %5 %17 %13
+%20 = OpLoad %9 %19
+OpStore %21 %20
+OpReturn
+)");
+
+ Validate(b);
+}
+
+TEST_F(BuilderTest, Const_IndexAccessor_Matrix) {
+ // let a : mat2x2<f32>(vec2<f32>(1., 2.), vec2<f32>(3., 4.));
+ // var x = a[1i]
+
+ auto* a = Let("a", ty.mat2x2<f32>(),
+ Construct(ty.mat2x2<f32>(), Construct(ty.vec2<f32>(), 1_f, 2_f),
+ Construct(ty.vec2<f32>(), 3_f, 4_f)));
+ auto* x = Var("x", nullptr, IndexAccessor("a", 1_i));
+ WrapInFunction(a, x);
+
+ spirv::Builder& b = SanitizeAndBuild();
+
+ ASSERT_TRUE(b.Build()) << b.error();
+
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeVoid
+%1 = OpTypeFunction %2
+%7 = OpTypeFloat 32
+%6 = OpTypeVector %7 2
+%5 = OpTypeMatrix %6 2
+%8 = OpConstant %7 1
+%9 = OpConstant %7 2
+%10 = OpConstantComposite %6 %8 %9
+%11 = OpConstant %7 3
+%12 = OpConstant %7 4
+%13 = OpConstantComposite %6 %11 %12
+%14 = OpConstantComposite %5 %10 %13
+%16 = OpTypePointer Function %6
+%17 = OpConstantNull %6
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].variables()), R"(%15 = OpVariable %16 Function %17
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"(OpStore %15 %13
+OpReturn
+)");
+
+ Validate(b);
+}
+
+TEST_F(BuilderTest, Runtime_IndexAccessor_Matrix) {
+ // var a : mat2x2<f32>;
+ // var x = a[1i]
+
+ auto* a = Var("a", ty.mat2x2<f32>());
+ auto* x = Var("x", nullptr, IndexAccessor("a", 1_i));
+ WrapInFunction(a, x);
+
+ spirv::Builder& b = SanitizeAndBuild();
+
+ ASSERT_TRUE(b.Build()) << b.error();
+
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeVoid
+%1 = OpTypeFunction %2
+%9 = OpTypeFloat 32
+%8 = OpTypeVector %9 2
+%7 = OpTypeMatrix %8 2
+%6 = OpTypePointer Function %7
+%10 = OpConstantNull %7
+%11 = OpTypeInt 32 1
+%12 = OpConstant %11 1
+%13 = OpTypePointer Function %8
+%17 = OpConstantNull %8
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].variables()), R"(%5 = OpVariable %6 Function %10
+%16 = OpVariable %13 Function %17
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"(%14 = OpAccessChain %13 %5 %12
+%15 = OpLoad %8 %14
+OpStore %16 %15
+OpReturn
+)");
+
+ Validate(b);
+}
+
+TEST_F(BuilderTest, Dynamic_IndexAccessor_Matrix) {
+ // var a : mat2x2<f32>;
+ // var idx : i32
+ // var x = a[idx]
+
+ auto* a = Var("a", ty.mat2x2<f32>());
+ auto* idx = Var("idx", ty.i32());
+ auto* x = Var("x", nullptr, IndexAccessor("a", idx));
+ WrapInFunction(a, idx, x);
+
+ spirv::Builder& b = SanitizeAndBuild();
+
+ ASSERT_TRUE(b.Build()) << b.error();
+
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeVoid
+%1 = OpTypeFunction %2
+%9 = OpTypeFloat 32
+%8 = OpTypeVector %9 2
+%7 = OpTypeMatrix %8 2
+%6 = OpTypePointer Function %7
+%10 = OpConstantNull %7
+%13 = OpTypeInt 32 1
+%12 = OpTypePointer Function %13
+%14 = OpConstantNull %13
+%16 = OpTypePointer Function %8
+%20 = OpConstantNull %8
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].variables()), R"(%5 = OpVariable %6 Function %10
+%11 = OpVariable %12 Function %14
+%19 = OpVariable %16 Function %20
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"(%15 = OpLoad %13 %11
+%17 = OpAccessChain %16 %5 %15
+%18 = OpLoad %8 %17
+OpStore %19 %18
+OpReturn
+)");
+
+ Validate(b);
}
TEST_F(BuilderTest, MemberAccessor) {
@@ -229,27 +778,28 @@
auto* expr = MemberAccessor("ident", "b");
WrapInFunction(var, expr);
- spirv::Builder& b = Build();
+ spirv::Builder& b = SanitizeAndBuild();
- b.push_function(Function{});
- ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.error();
+ ASSERT_TRUE(b.Build()) << b.error();
- EXPECT_EQ(b.GenerateAccessorExpression(expr), 9u);
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeVoid
+%1 = OpTypeFunction %2
+%8 = OpTypeFloat 32
+%7 = OpTypeStruct %8 %8
+%6 = OpTypePointer Function %7
+%9 = OpConstantNull %7
+%10 = OpTypeInt 32 0
+%11 = OpConstant %10 1
+%12 = OpTypePointer Function %8
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].variables()), R"(%5 = OpVariable %6 Function %9
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"(%13 = OpAccessChain %12 %5 %11
+%14 = OpLoad %8 %13
+OpReturn
+)");
- EXPECT_EQ(DumpInstructions(b.types()), R"(%4 = OpTypeFloat 32
-%3 = OpTypeStruct %4 %4
-%2 = OpTypePointer Function %3
-%5 = OpConstantNull %3
-%6 = OpTypeInt 32 0
-%7 = OpConstant %6 1
-%8 = OpTypePointer Function %4
-)");
- EXPECT_EQ(DumpInstructions(b.functions()[0].variables()),
- R"(%1 = OpVariable %2 Function %5
-)");
- EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
- R"(%9 = OpAccessChain %8 %1 %7
-)");
+ Validate(b);
}
TEST_F(BuilderTest, MemberAccessor_Nested) {
@@ -274,29 +824,31 @@
auto* expr = MemberAccessor(MemberAccessor("ident", "inner"), "b");
WrapInFunction(var, expr);
- spirv::Builder& b = Build();
+ spirv::Builder& b = SanitizeAndBuild();
- b.push_function(Function{});
- ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.error();
+ ASSERT_TRUE(b.Build()) << b.error();
- EXPECT_EQ(b.GenerateAccessorExpression(expr), 11u);
-
- EXPECT_EQ(DumpInstructions(b.types()), R"(%5 = OpTypeFloat 32
-%4 = OpTypeStruct %5 %5
-%3 = OpTypeStruct %4
-%2 = OpTypePointer Function %3
-%6 = OpConstantNull %3
-%7 = OpTypeInt 32 0
-%8 = OpConstant %7 0
-%9 = OpConstant %7 1
-%10 = OpTypePointer Function %5
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeVoid
+%1 = OpTypeFunction %2
+%9 = OpTypeFloat 32
+%8 = OpTypeStruct %9 %9
+%7 = OpTypeStruct %8
+%6 = OpTypePointer Function %7
+%10 = OpConstantNull %7
+%11 = OpTypeInt 32 0
+%12 = OpConstant %11 0
+%13 = OpConstant %11 1
+%14 = OpTypePointer Function %9
)");
- EXPECT_EQ(DumpInstructions(b.functions()[0].variables()),
- R"(%1 = OpVariable %2 Function %6
+ EXPECT_EQ(DumpInstructions(b.functions()[0].variables()), R"(%5 = OpVariable %6 Function %10
)");
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
- R"(%11 = OpAccessChain %10 %1 %8 %9
+ R"(%15 = OpAccessChain %14 %5 %12 %13
+%16 = OpLoad %9 %15
+OpReturn
)");
+
+ Validate(b);
}
TEST_F(BuilderTest, MemberAccessor_NonPointer) {
@@ -317,21 +869,23 @@
auto* expr = MemberAccessor("ident", "b");
WrapInFunction(var, expr);
- spirv::Builder& b = Build();
+ spirv::Builder& b = SanitizeAndBuild();
- b.push_function(Function{});
- ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.error();
+ ASSERT_TRUE(b.Build()) << b.error();
- EXPECT_EQ(b.GenerateAccessorExpression(expr), 5u);
-
- EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
-%1 = OpTypeStruct %2 %2
-%3 = OpConstantNull %2
-%4 = OpConstantComposite %1 %3 %3
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeVoid
+%1 = OpTypeFunction %2
+%6 = OpTypeFloat 32
+%5 = OpTypeStruct %6 %6
+%7 = OpConstantNull %6
+%8 = OpConstantComposite %5 %7 %7
)");
- EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
- R"(%5 = OpCompositeExtract %2 %4 1
+ EXPECT_EQ(DumpInstructions(b.functions()[0].variables()), R"()");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"(%9 = OpCompositeExtract %6 %8 1
+OpReturn
)");
+
+ Validate(b);
}
TEST_F(BuilderTest, MemberAccessor_Nested_NonPointer) {
@@ -357,24 +911,27 @@
auto* expr = MemberAccessor(MemberAccessor("ident", "inner"), "b");
WrapInFunction(var, expr);
- spirv::Builder& b = Build();
+ spirv::Builder& b = SanitizeAndBuild();
- b.push_function(Function{});
- ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.error();
+ ASSERT_TRUE(b.Build()) << b.error();
- EXPECT_EQ(b.GenerateAccessorExpression(expr), 8u);
-
- EXPECT_EQ(DumpInstructions(b.types()), R"(%3 = OpTypeFloat 32
-%2 = OpTypeStruct %3 %3
-%1 = OpTypeStruct %2
-%4 = OpConstantNull %3
-%5 = OpConstantComposite %2 %4 %4
-%6 = OpConstantComposite %1 %5
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeVoid
+%1 = OpTypeFunction %2
+%7 = OpTypeFloat 32
+%6 = OpTypeStruct %7 %7
+%5 = OpTypeStruct %6
+%8 = OpConstantNull %7
+%9 = OpConstantComposite %6 %8 %8
+%10 = OpConstantComposite %5 %9
)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].variables()), R"()");
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
- R"(%7 = OpCompositeExtract %2 %6 0
-%8 = OpCompositeExtract %3 %7 1
+ R"(%11 = OpCompositeExtract %6 %10 0
+%12 = OpCompositeExtract %7 %11 1
+OpReturn
)");
+
+ Validate(b);
}
TEST_F(BuilderTest, MemberAccessor_Nested_WithAlias) {
@@ -401,28 +958,30 @@
auto* expr = MemberAccessor(MemberAccessor("ident", "inner"), "a");
WrapInFunction(var, expr);
- spirv::Builder& b = Build();
+ spirv::Builder& b = SanitizeAndBuild();
- b.push_function(Function{});
- ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.error();
+ ASSERT_TRUE(b.Build()) << b.error();
- EXPECT_EQ(b.GenerateAccessorExpression(expr), 10u);
-
- EXPECT_EQ(DumpInstructions(b.types()), R"(%5 = OpTypeFloat 32
-%4 = OpTypeStruct %5 %5
-%3 = OpTypeStruct %4
-%2 = OpTypePointer Function %3
-%6 = OpConstantNull %3
-%7 = OpTypeInt 32 0
-%8 = OpConstant %7 0
-%9 = OpTypePointer Function %5
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeVoid
+%1 = OpTypeFunction %2
+%9 = OpTypeFloat 32
+%8 = OpTypeStruct %9 %9
+%7 = OpTypeStruct %8
+%6 = OpTypePointer Function %7
+%10 = OpConstantNull %7
+%11 = OpTypeInt 32 0
+%12 = OpConstant %11 0
+%13 = OpTypePointer Function %9
)");
- EXPECT_EQ(DumpInstructions(b.functions()[0].variables()),
- R"(%1 = OpVariable %2 Function %6
+ EXPECT_EQ(DumpInstructions(b.functions()[0].variables()), R"(%5 = OpVariable %6 Function %10
)");
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
- R"(%10 = OpAccessChain %9 %1 %8 %8
+ R"(%14 = OpAccessChain %13 %5 %12 %12
+%15 = OpLoad %9 %14
+OpReturn
)");
+
+ Validate(b);
}
TEST_F(BuilderTest, MemberAccessor_Nested_Assignment_LHS) {
@@ -446,30 +1005,31 @@
auto* expr = Assign(MemberAccessor(MemberAccessor("ident", "inner"), "a"), Expr(2_f));
WrapInFunction(var, expr);
- spirv::Builder& b = Build();
+ spirv::Builder& b = SanitizeAndBuild();
- b.push_function(Function{});
- ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.error();
+ ASSERT_TRUE(b.Build()) << b.error();
- EXPECT_TRUE(b.GenerateAssignStatement(expr)) << b.error();
-
- EXPECT_EQ(DumpInstructions(b.types()), R"(%5 = OpTypeFloat 32
-%4 = OpTypeStruct %5 %5
-%3 = OpTypeStruct %4
-%2 = OpTypePointer Function %3
-%6 = OpConstantNull %3
-%7 = OpTypeInt 32 0
-%8 = OpConstant %7 0
-%9 = OpTypePointer Function %5
-%11 = OpConstant %5 2
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeVoid
+%1 = OpTypeFunction %2
+%9 = OpTypeFloat 32
+%8 = OpTypeStruct %9 %9
+%7 = OpTypeStruct %8
+%6 = OpTypePointer Function %7
+%10 = OpConstantNull %7
+%11 = OpTypeInt 32 0
+%12 = OpConstant %11 0
+%13 = OpTypePointer Function %9
+%15 = OpConstant %9 2
)");
- EXPECT_EQ(DumpInstructions(b.functions()[0].variables()),
- R"(%1 = OpVariable %2 Function %6
+ EXPECT_EQ(DumpInstructions(b.functions()[0].variables()), R"(%5 = OpVariable %6 Function %10
)");
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
- R"(%10 = OpAccessChain %9 %1 %8 %8
-OpStore %10 %11
+ R"(%14 = OpAccessChain %13 %5 %12 %12
+OpStore %14 %15
+OpReturn
)");
+
+ Validate(b);
}
TEST_F(BuilderTest, MemberAccessor_Nested_Assignment_RHS) {
@@ -497,33 +1057,33 @@
auto* expr = Assign("store", rhs);
WrapInFunction(var, store, expr);
- spirv::Builder& b = Build();
+ spirv::Builder& b = SanitizeAndBuild();
- b.push_function(Function{});
- ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.error();
- ASSERT_TRUE(b.GenerateFunctionVariable(store)) << b.error();
+ ASSERT_TRUE(b.Build()) << b.error();
- EXPECT_TRUE(b.GenerateAssignStatement(expr)) << b.error();
-
- EXPECT_EQ(DumpInstructions(b.types()), R"(%5 = OpTypeFloat 32
-%4 = OpTypeStruct %5 %5
-%3 = OpTypeStruct %4
-%2 = OpTypePointer Function %3
-%6 = OpConstantNull %3
-%8 = OpTypePointer Function %5
-%9 = OpConstantNull %5
-%10 = OpTypeInt 32 0
-%11 = OpConstant %10 0
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeVoid
+%1 = OpTypeFunction %2
+%9 = OpTypeFloat 32
+%8 = OpTypeStruct %9 %9
+%7 = OpTypeStruct %8
+%6 = OpTypePointer Function %7
+%10 = OpConstantNull %7
+%12 = OpTypePointer Function %9
+%13 = OpConstantNull %9
+%14 = OpTypeInt 32 0
+%15 = OpConstant %14 0
)");
- EXPECT_EQ(DumpInstructions(b.functions()[0].variables()),
- R"(%1 = OpVariable %2 Function %6
-%7 = OpVariable %8 Function %9
+ EXPECT_EQ(DumpInstructions(b.functions()[0].variables()), R"(%5 = OpVariable %6 Function %10
+%11 = OpVariable %12 Function %13
)");
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
- R"(%12 = OpAccessChain %8 %1 %11 %11
-%13 = OpLoad %5 %12
-OpStore %7 %13
+ R"(%16 = OpAccessChain %12 %5 %15 %15
+%17 = OpLoad %9 %16
+OpStore %11 %17
+OpReturn
)");
+
+ Validate(b);
}
TEST_F(BuilderTest, MemberAccessor_Swizzle_Single) {
@@ -534,27 +1094,28 @@
auto* expr = MemberAccessor("ident", "y");
WrapInFunction(var, expr);
- spirv::Builder& b = Build();
+ spirv::Builder& b = SanitizeAndBuild();
- b.push_function(Function{});
- ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.error();
+ ASSERT_TRUE(b.Build()) << b.error();
- EXPECT_EQ(b.GenerateAccessorExpression(expr), 9u);
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeVoid
+%1 = OpTypeFunction %2
+%8 = OpTypeFloat 32
+%7 = OpTypeVector %8 3
+%6 = OpTypePointer Function %7
+%9 = OpConstantNull %7
+%10 = OpTypeInt 32 0
+%11 = OpConstant %10 1
+%12 = OpTypePointer Function %8
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].variables()), R"(%5 = OpVariable %6 Function %9
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"(%13 = OpAccessChain %12 %5 %11
+%14 = OpLoad %8 %13
+OpReturn
+)");
- EXPECT_EQ(DumpInstructions(b.types()), R"(%4 = OpTypeFloat 32
-%3 = OpTypeVector %4 3
-%2 = OpTypePointer Function %3
-%5 = OpConstantNull %3
-%6 = OpTypeInt 32 0
-%7 = OpConstant %6 1
-%8 = OpTypePointer Function %4
-)");
- EXPECT_EQ(DumpInstructions(b.functions()[0].variables()),
- R"(%1 = OpVariable %2 Function %5
-)");
- EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
- R"(%9 = OpAccessChain %8 %1 %7
-)");
+ Validate(b);
}
TEST_F(BuilderTest, MemberAccessor_Swizzle_MultipleNames) {
@@ -565,26 +1126,26 @@
auto* expr = MemberAccessor("ident", "yx");
WrapInFunction(var, expr);
- spirv::Builder& b = Build();
+ spirv::Builder& b = SanitizeAndBuild();
- b.push_function(Function{});
- ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.error();
+ ASSERT_TRUE(b.Build()) << b.error();
- EXPECT_EQ(b.GenerateAccessorExpression(expr), 8u);
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeVoid
+%1 = OpTypeFunction %2
+%8 = OpTypeFloat 32
+%7 = OpTypeVector %8 3
+%6 = OpTypePointer Function %7
+%9 = OpConstantNull %7
+%10 = OpTypeVector %8 2
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].variables()), R"(%5 = OpVariable %6 Function %9
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"(%11 = OpLoad %7 %5
+%12 = OpVectorShuffle %10 %11 %11 1 0
+OpReturn
+)");
- EXPECT_EQ(DumpInstructions(b.types()), R"(%4 = OpTypeFloat 32
-%3 = OpTypeVector %4 3
-%2 = OpTypePointer Function %3
-%5 = OpConstantNull %3
-%6 = OpTypeVector %4 2
-)");
- EXPECT_EQ(DumpInstructions(b.functions()[0].variables()),
- R"(%1 = OpVariable %2 Function %5
-)");
- EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
- R"(%7 = OpLoad %3 %1
-%8 = OpVectorShuffle %6 %7 %7 1 0
-)");
+ Validate(b);
}
TEST_F(BuilderTest, MemberAccessor_Swizzle_of_Swizzle) {
@@ -595,27 +1156,27 @@
auto* expr = MemberAccessor(MemberAccessor("ident", "yxz"), "xz");
WrapInFunction(var, expr);
- spirv::Builder& b = Build();
+ spirv::Builder& b = SanitizeAndBuild();
- b.push_function(Function{});
- ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.error();
+ ASSERT_TRUE(b.Build()) << b.error();
- EXPECT_EQ(b.GenerateAccessorExpression(expr), 9u);
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeVoid
+%1 = OpTypeFunction %2
+%8 = OpTypeFloat 32
+%7 = OpTypeVector %8 3
+%6 = OpTypePointer Function %7
+%9 = OpConstantNull %7
+%12 = OpTypeVector %8 2
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].variables()), R"(%5 = OpVariable %6 Function %9
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"(%10 = OpLoad %7 %5
+%11 = OpVectorShuffle %7 %10 %10 1 0 2
+%13 = OpVectorShuffle %12 %11 %11 0 2
+OpReturn
+)");
- EXPECT_EQ(DumpInstructions(b.types()), R"(%4 = OpTypeFloat 32
-%3 = OpTypeVector %4 3
-%2 = OpTypePointer Function %3
-%5 = OpConstantNull %3
-%8 = OpTypeVector %4 2
-)");
- EXPECT_EQ(DumpInstructions(b.functions()[0].variables()),
- R"(%1 = OpVariable %2 Function %5
-)");
- EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
- R"(%6 = OpLoad %3 %1
-%7 = OpVectorShuffle %3 %6 %6 1 0 2
-%9 = OpVectorShuffle %8 %7 %7 0 2
-)");
+ Validate(b);
}
TEST_F(BuilderTest, MemberAccessor_Member_of_Swizzle) {
@@ -626,26 +1187,26 @@
auto* expr = MemberAccessor(MemberAccessor("ident", "yxz"), "x");
WrapInFunction(var, expr);
- spirv::Builder& b = Build();
+ spirv::Builder& b = SanitizeAndBuild();
- b.push_function(Function{});
- ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.error();
+ ASSERT_TRUE(b.Build()) << b.error();
- EXPECT_EQ(b.GenerateAccessorExpression(expr), 8u);
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeVoid
+%1 = OpTypeFunction %2
+%8 = OpTypeFloat 32
+%7 = OpTypeVector %8 3
+%6 = OpTypePointer Function %7
+%9 = OpConstantNull %7
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].variables()), R"(%5 = OpVariable %6 Function %9
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"(%10 = OpLoad %7 %5
+%11 = OpVectorShuffle %7 %10 %10 1 0 2
+%12 = OpCompositeExtract %8 %11 0
+OpReturn
+)");
- EXPECT_EQ(DumpInstructions(b.types()), R"(%4 = OpTypeFloat 32
-%3 = OpTypeVector %4 3
-%2 = OpTypePointer Function %3
-%5 = OpConstantNull %3
-)");
- EXPECT_EQ(DumpInstructions(b.functions()[0].variables()),
- R"(%1 = OpVariable %2 Function %5
-)");
- EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
- R"(%6 = OpLoad %3 %1
-%7 = OpVectorShuffle %3 %6 %6 1 0 2
-%8 = OpCompositeExtract %4 %7 0
-)");
+ Validate(b);
}
TEST_F(BuilderTest, MemberAccessor_Array_of_Swizzle) {
@@ -656,28 +1217,28 @@
auto* expr = IndexAccessor(MemberAccessor("ident", "yxz"), 1_i);
WrapInFunction(var, expr);
- spirv::Builder& b = Build();
+ spirv::Builder& b = SanitizeAndBuild();
- b.push_function(Function{});
- ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.error();
+ ASSERT_TRUE(b.Build()) << b.error();
- EXPECT_EQ(b.GenerateAccessorExpression(expr), 10u);
+ EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeVoid
+%1 = OpTypeFunction %2
+%8 = OpTypeFloat 32
+%7 = OpTypeVector %8 3
+%6 = OpTypePointer Function %7
+%9 = OpConstantNull %7
+%12 = OpTypeInt 32 1
+%13 = OpConstant %12 1
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].variables()), R"(%5 = OpVariable %6 Function %9
+)");
+ EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"(%10 = OpLoad %7 %5
+%11 = OpVectorShuffle %7 %10 %10 1 0 2
+%14 = OpCompositeExtract %8 %11 1
+OpReturn
+)");
- EXPECT_EQ(DumpInstructions(b.types()), R"(%4 = OpTypeFloat 32
-%3 = OpTypeVector %4 3
-%2 = OpTypePointer Function %3
-%5 = OpConstantNull %3
-%8 = OpTypeInt 32 1
-%9 = OpConstant %8 1
-)");
- EXPECT_EQ(DumpInstructions(b.functions()[0].variables()),
- R"(%1 = OpVariable %2 Function %5
-)");
- EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
- R"(%6 = OpLoad %3 %1
-%7 = OpVectorShuffle %3 %6 %6 1 0 2
-%10 = OpCompositeExtract %4 %7 1
-)");
+ Validate(b);
}
TEST_F(BuilderTest, IndexAccessor_Mixed_ArrayAndMember) {
@@ -709,323 +1270,37 @@
"yx");
WrapInFunction(var, expr);
- spirv::Builder& b = Build();
-
- b.push_function(Function{});
- ASSERT_TRUE(b.GenerateFunctionVariable(var)) << b.error();
-
- EXPECT_EQ(b.GenerateAccessorExpression(expr), 22u);
-
- EXPECT_EQ(DumpInstructions(b.types()), R"(%9 = OpTypeFloat 32
-%8 = OpTypeVector %9 3
-%7 = OpTypeStruct %8
-%6 = OpTypeStruct %7
-%10 = OpTypeInt 32 0
-%11 = OpConstant %10 3
-%5 = OpTypeArray %6 %11
-%4 = OpTypeStruct %5
-%12 = OpConstant %10 2
-%3 = OpTypeArray %4 %12
-%2 = OpTypePointer Function %3
-%13 = OpConstantNull %3
-%14 = OpTypeInt 32 1
-%15 = OpConstantNull %14
-%16 = OpConstant %10 0
-%17 = OpConstant %14 2
-%18 = OpTypePointer Function %8
-%20 = OpTypeVector %9 2
-)");
- EXPECT_EQ(DumpInstructions(b.functions()[0].variables()),
- R"(%1 = OpVariable %2 Function %13
-)");
- EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
- R"(%19 = OpAccessChain %18 %1 %15 %16 %17 %16 %16
-%21 = OpLoad %8 %19
-%22 = OpVectorShuffle %20 %21 %21 1 0
-)");
-}
-
-TEST_F(BuilderTest, IndexAccessor_Of_Vec) {
- // let pos : array<vec2<f32>, 3u> = array<vec2<f32>, 3u>(
- // vec2<f32>(0.0, 0.5),
- // vec2<f32>(-0.5, -0.5),
- // vec2<f32>(0.5, -0.5));
- // pos[1u]
-
- auto* var = Let("pos", ty.array(ty.vec2<f32>(), 3_u),
- Construct(ty.array(ty.vec2<f32>(), 3_u), vec2<f32>(0_f, 0.5_f),
- vec2<f32>(-0.5_f, -0.5_f), vec2<f32>(0.5_f, -0.5_f)));
-
- auto* expr = IndexAccessor("pos", 1_u);
- WrapInFunction(var, expr);
-
spirv::Builder& b = SanitizeAndBuild();
- ASSERT_TRUE(b.Build());
+ ASSERT_TRUE(b.Build()) << b.error();
EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeVoid
%1 = OpTypeFunction %2
-%7 = OpTypeFloat 32
-%6 = OpTypeVector %7 2
-%8 = OpTypeInt 32 0
-%9 = OpConstant %8 3
-%5 = OpTypeArray %6 %9
-%10 = OpConstantNull %7
-%11 = OpConstant %7 0.5
-%12 = OpConstantComposite %6 %10 %11
-%13 = OpConstant %7 -0.5
-%14 = OpConstantComposite %6 %13 %13
-%15 = OpConstantComposite %6 %11 %13
-%16 = OpConstantComposite %5 %12 %14 %15
-%17 = OpConstant %8 1
+%13 = OpTypeFloat 32
+%12 = OpTypeVector %13 3
+%11 = OpTypeStruct %12
+%10 = OpTypeStruct %11
+%14 = OpTypeInt 32 0
+%15 = OpConstant %14 3
+%9 = OpTypeArray %10 %15
+%8 = OpTypeStruct %9
+%16 = OpConstant %14 2
+%7 = OpTypeArray %8 %16
+%6 = OpTypePointer Function %7
+%17 = OpConstantNull %7
+%18 = OpTypeInt 32 1
+%19 = OpConstantNull %18
+%20 = OpConstant %14 0
+%21 = OpConstant %18 2
+%22 = OpTypePointer Function %12
+%24 = OpTypeVector %13 2
)");
- EXPECT_EQ(DumpInstructions(b.functions()[0].variables()), R"()");
- EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
- R"(%18 = OpCompositeExtract %6 %16 1
-OpReturn
-)");
-
- Validate(b);
-}
-
-TEST_F(BuilderTest, IndexAccessor_Of_Array_Of_f32) {
- // let pos : array<array<f32, 2>, 3u> = array<vec2<f32, 2>, 3u>(
- // array<f32, 2>(0.0, 0.5),
- // array<f32, 2>(-0.5, -0.5),
- // array<f32, 2>(0.5, -0.5));
- // pos[2u][1u]
-
- auto* var = Let("pos", ty.array(ty.vec2<f32>(), 3_u),
- Construct(ty.array(ty.vec2<f32>(), 3_u), vec2<f32>(0_f, 0.5_f),
- vec2<f32>(-0.5_f, -0.5_f), vec2<f32>(0.5_f, -0.5_f)));
-
- auto* expr = IndexAccessor(IndexAccessor("pos", 2_u), 1_u);
- WrapInFunction(var, expr);
-
- spirv::Builder& b = SanitizeAndBuild();
-
- ASSERT_TRUE(b.Build());
-
- EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeVoid
-%1 = OpTypeFunction %2
-%7 = OpTypeFloat 32
-%6 = OpTypeVector %7 2
-%8 = OpTypeInt 32 0
-%9 = OpConstant %8 3
-%5 = OpTypeArray %6 %9
-%10 = OpConstantNull %7
-%11 = OpConstant %7 0.5
-%12 = OpConstantComposite %6 %10 %11
-%13 = OpConstant %7 -0.5
-%14 = OpConstantComposite %6 %13 %13
-%15 = OpConstantComposite %6 %11 %13
-%16 = OpConstantComposite %5 %12 %14 %15
-%17 = OpConstant %8 2
-%19 = OpConstant %8 1
-)");
- EXPECT_EQ(DumpInstructions(b.functions()[0].variables()), R"()");
- EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
- R"(%18 = OpCompositeExtract %6 %16 2
-%20 = OpCompositeExtract %7 %18 1
-OpReturn
-)");
-
- Validate(b);
-}
-
-TEST_F(BuilderTest, IndexAccessor_Vec_Literal) {
- // let pos : vec2<f32> = vec2<f32>(0.0, 0.5);
- // pos[1]
-
- auto* var = Let("pos", ty.vec2<f32>(), vec2<f32>(0_f, 0.5_f));
-
- auto* expr = IndexAccessor("pos", 1_u);
- WrapInFunction(var, expr);
-
- spirv::Builder& b = Build();
-
- b.push_function(Function{});
- ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
- EXPECT_EQ(b.GenerateAccessorExpression(expr), 8u) << b.error();
-
- EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
-%1 = OpTypeVector %2 2
-%3 = OpConstantNull %2
-%4 = OpConstant %2 0.5
-%5 = OpConstantComposite %1 %3 %4
-%6 = OpTypeInt 32 0
-%7 = OpConstant %6 1
-)");
- EXPECT_EQ(DumpInstructions(b.functions()[0].variables()), "");
- EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
- R"(%8 = OpCompositeExtract %2 %5 1
-)");
-}
-
-TEST_F(BuilderTest, IndexAccessor_Vec_Dynamic) {
- // let pos : vec2<f32> = vec2<f32>(0.0, 0.5);
- // idx : i32
- // pos[idx]
-
- auto* var = Let("pos", ty.vec2<f32>(), vec2<f32>(0_f, 0.5_f));
- auto* idx = Var("idx", ty.i32());
- auto* expr = IndexAccessor("pos", idx);
-
- WrapInFunction(var, idx, expr);
-
- spirv::Builder& b = Build();
-
- b.push_function(Function{});
- ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
- ASSERT_TRUE(b.GenerateFunctionVariable(idx)) << b.error();
- EXPECT_EQ(b.GenerateAccessorExpression(expr), 11u) << b.error();
-
- EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
-%1 = OpTypeVector %2 2
-%3 = OpConstantNull %2
-%4 = OpConstant %2 0.5
-%5 = OpConstantComposite %1 %3 %4
-%8 = OpTypeInt 32 1
-%7 = OpTypePointer Function %8
-%9 = OpConstantNull %8
-)");
- EXPECT_EQ(DumpInstructions(b.functions()[0].variables()),
- R"(%6 = OpVariable %7 Function %9
+ EXPECT_EQ(DumpInstructions(b.functions()[0].variables()), R"(%5 = OpVariable %6 Function %17
)");
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
- R"(%10 = OpLoad %8 %6
-%11 = OpVectorExtractDynamic %2 %5 %10
-)");
-}
-
-TEST_F(BuilderTest, IndexAccessor_Array_Literal) {
- // let a : array<f32, 3u>;
- // a[2i]
-
- auto* var = Let("a", ty.array<f32, 3>(), Construct(ty.array<f32, 3>(), 0_f, 0.5_f, 1_f));
- auto* expr = IndexAccessor("a", 2_i);
- WrapInFunction(var, expr);
-
- spirv::Builder& b = SanitizeAndBuild();
-
- ASSERT_TRUE(b.Build());
-
- EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeVoid
-%1 = OpTypeFunction %2
-%6 = OpTypeFloat 32
-%7 = OpTypeInt 32 0
-%8 = OpConstant %7 3
-%5 = OpTypeArray %6 %8
-%9 = OpConstantNull %6
-%10 = OpConstant %6 0.5
-%11 = OpConstant %6 1
-%12 = OpConstantComposite %5 %9 %10 %11
-%13 = OpTypeInt 32 1
-%14 = OpConstant %13 2
-)");
- EXPECT_EQ(DumpInstructions(b.functions()[0].variables()), "");
- EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
- R"(%15 = OpCompositeExtract %6 %12 2
-OpReturn
-)");
-
- Validate(b);
-}
-
-TEST_F(BuilderTest, IndexAccessor_Array_Dynamic) {
- // let a : array<f32, 3>;
- // idx : i32
- // a[idx]
-
- auto* var = Let("a", ty.array<f32, 3>(), Construct(ty.array<f32, 3>(), 0_f, 0.5_f, 1_f));
-
- auto* idx = Var("idx", ty.i32());
- auto* expr = IndexAccessor("a", idx);
-
- WrapInFunction(var, idx, expr);
-
- spirv::Builder& b = SanitizeAndBuild();
-
- ASSERT_TRUE(b.Build());
-
- EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeVoid
-%1 = OpTypeFunction %2
-%6 = OpTypeFloat 32
-%7 = OpTypeInt 32 0
-%8 = OpConstant %7 3
-%5 = OpTypeArray %6 %8
-%9 = OpConstantNull %6
-%10 = OpConstant %6 0.5
-%11 = OpConstant %6 1
-%12 = OpConstantComposite %5 %9 %10 %11
-%15 = OpTypeInt 32 1
-%14 = OpTypePointer Function %15
-%16 = OpConstantNull %15
-%18 = OpTypePointer Function %5
-%19 = OpConstantNull %5
-%21 = OpTypePointer Function %6
-)");
- EXPECT_EQ(DumpInstructions(b.functions()[0].variables()),
- R"(%13 = OpVariable %14 Function %16
-%17 = OpVariable %18 Function %19
-)");
- EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
- R"(OpStore %17 %12
-%20 = OpLoad %15 %13
-%22 = OpAccessChain %21 %17 %20
-%23 = OpLoad %6 %22
-OpReturn
-)");
-
- Validate(b);
-}
-
-TEST_F(BuilderTest, IndexAccessor_Matrix_Dynamic) {
- // let a : mat2x2<f32>(vec2<f32>(1., 2.), vec2<f32>(3., 4.));
- // idx : i32
- // a[idx]
-
- auto* var = Let("a", ty.mat2x2<f32>(),
- Construct(ty.mat2x2<f32>(), Construct(ty.vec2<f32>(), 1_f, 2_f),
- Construct(ty.vec2<f32>(), 3_f, 4_f)));
-
- auto* idx = Var("idx", ty.i32());
- auto* expr = IndexAccessor("a", idx);
-
- WrapInFunction(var, idx, expr);
-
- spirv::Builder& b = SanitizeAndBuild();
-
- ASSERT_TRUE(b.Build());
-
- EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeVoid
-%1 = OpTypeFunction %2
-%7 = OpTypeFloat 32
-%6 = OpTypeVector %7 2
-%5 = OpTypeMatrix %6 2
-%8 = OpConstant %7 1
-%9 = OpConstant %7 2
-%10 = OpConstantComposite %6 %8 %9
-%11 = OpConstant %7 3
-%12 = OpConstant %7 4
-%13 = OpConstantComposite %6 %11 %12
-%14 = OpConstantComposite %5 %10 %13
-%17 = OpTypeInt 32 1
-%16 = OpTypePointer Function %17
-%18 = OpConstantNull %17
-%20 = OpTypePointer Function %5
-%21 = OpConstantNull %5
-%23 = OpTypePointer Function %6
-)");
- EXPECT_EQ(DumpInstructions(b.functions()[0].variables()),
- R"(%15 = OpVariable %16 Function %18
-%19 = OpVariable %20 Function %21
-)");
- EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
- R"(OpStore %19 %14
-%22 = OpLoad %17 %15
-%24 = OpAccessChain %23 %19 %22
-%25 = OpLoad %6 %24
+ R"(%23 = OpAccessChain %22 %5 %19 %20 %21 %20 %20
+%25 = OpLoad %12 %23
+%26 = OpVectorShuffle %24 %25 %25 1 0
OpReturn
)");