• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 The Tint Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "src/writer/spirv/spv_dump.h"
16 #include "src/writer/spirv/test_helper.h"
17 
18 namespace tint {
19 namespace writer {
20 namespace spirv {
21 namespace {
22 
23 using BuilderTest = TestHelper;
24 
TEST_F(BuilderTest,FunctionVar_NoStorageClass)25 TEST_F(BuilderTest, FunctionVar_NoStorageClass) {
26   auto* v = Var("var", ty.f32(), ast::StorageClass::kFunction);
27   WrapInFunction(v);
28 
29   spirv::Builder& b = Build();
30 
31   b.push_function(Function{});
32   EXPECT_TRUE(b.GenerateFunctionVariable(v)) << b.error();
33   EXPECT_EQ(DumpInstructions(b.debug()), R"(OpName %1 "var"
34 )");
35   EXPECT_EQ(DumpInstructions(b.types()), R"(%3 = OpTypeFloat 32
36 %2 = OpTypePointer Function %3
37 %4 = OpConstantNull %3
38 )");
39 
40   const auto& func = b.functions()[0];
41   EXPECT_EQ(DumpInstructions(func.variables()),
42             R"(%1 = OpVariable %2 Function %4
43 )");
44 }
45 
TEST_F(BuilderTest,FunctionVar_WithConstantConstructor)46 TEST_F(BuilderTest, FunctionVar_WithConstantConstructor) {
47   auto* init = vec3<f32>(1.f, 1.f, 3.f);
48   auto* v = Var("var", ty.vec3<f32>(), ast::StorageClass::kFunction, init);
49   WrapInFunction(v);
50 
51   spirv::Builder& b = Build();
52 
53   b.push_function(Function{});
54   EXPECT_TRUE(b.GenerateFunctionVariable(v)) << b.error();
55   ASSERT_FALSE(b.has_error()) << b.error();
56 
57   EXPECT_EQ(DumpInstructions(b.debug()), R"(OpName %6 "var"
58 )");
59   EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
60 %1 = OpTypeVector %2 3
61 %3 = OpConstant %2 1
62 %4 = OpConstant %2 3
63 %5 = OpConstantComposite %1 %3 %3 %4
64 %7 = OpTypePointer Function %1
65 %8 = OpConstantNull %1
66 )");
67   EXPECT_EQ(DumpInstructions(b.functions()[0].variables()),
68             R"(%6 = OpVariable %7 Function %8
69 )");
70   EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
71             R"(OpStore %6 %5
72 )");
73 }
74 
TEST_F(BuilderTest,FunctionVar_WithNonConstantConstructor)75 TEST_F(BuilderTest, FunctionVar_WithNonConstantConstructor) {
76   auto* init = vec2<f32>(1.f, Add(3.f, 3.f));
77 
78   auto* v = Var("var", ty.vec2<f32>(), ast::StorageClass::kNone, init);
79   WrapInFunction(v);
80 
81   spirv::Builder& b = Build();
82 
83   b.push_function(Function{});
84   EXPECT_TRUE(b.GenerateFunctionVariable(v)) << b.error();
85   ASSERT_FALSE(b.has_error()) << b.error();
86 
87   EXPECT_EQ(DumpInstructions(b.debug()), R"(OpName %7 "var"
88 )");
89   EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
90 %1 = OpTypeVector %2 2
91 %3 = OpConstant %2 1
92 %4 = OpConstant %2 3
93 %8 = OpTypePointer Function %1
94 %9 = OpConstantNull %1
95 )");
96   EXPECT_EQ(DumpInstructions(b.functions()[0].variables()),
97             R"(%7 = OpVariable %8 Function %9
98 )");
99   EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
100             R"(%5 = OpFAdd %2 %4 %4
101 %6 = OpCompositeConstruct %1 %3 %5
102 OpStore %7 %6
103 )");
104 }
105 
TEST_F(BuilderTest,FunctionVar_WithNonConstantConstructorLoadedFromVar)106 TEST_F(BuilderTest, FunctionVar_WithNonConstantConstructorLoadedFromVar) {
107   // var v : f32 = 1.0;
108   // var v2 : f32 = v; // Should generate the load and store automatically.
109 
110   auto* v = Var("v", ty.f32(), ast::StorageClass::kNone, Expr(1.f));
111 
112   auto* v2 = Var("v2", ty.f32(), ast::StorageClass::kNone, Expr("v"));
113   WrapInFunction(v, v2);
114 
115   spirv::Builder& b = Build();
116 
117   b.push_function(Function{});
118   EXPECT_TRUE(b.GenerateFunctionVariable(v)) << b.error();
119   EXPECT_TRUE(b.GenerateFunctionVariable(v2)) << b.error();
120   ASSERT_FALSE(b.has_error()) << b.error();
121 
122   EXPECT_EQ(DumpInstructions(b.debug()), R"(OpName %3 "v"
123 OpName %7 "v2"
124 )");
125   EXPECT_EQ(DumpInstructions(b.types()), R"(%1 = OpTypeFloat 32
126 %2 = OpConstant %1 1
127 %4 = OpTypePointer Function %1
128 %5 = OpConstantNull %1
129 )");
130   EXPECT_EQ(DumpInstructions(b.functions()[0].variables()),
131             R"(%3 = OpVariable %4 Function %5
132 %7 = OpVariable %4 Function %5
133 )");
134   EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
135             R"(OpStore %3 %2
136 %6 = OpLoad %1 %3
137 OpStore %7 %6
138 )");
139 }
140 
TEST_F(BuilderTest,FunctionVar_ConstWithVarInitializer)141 TEST_F(BuilderTest, FunctionVar_ConstWithVarInitializer) {
142   // var v : f32 = 1.0;
143   // let v2 : f32 = v; // Should generate the load
144 
145   auto* v = Var("v", ty.f32(), ast::StorageClass::kNone, Expr(1.f));
146 
147   auto* v2 = Var("v2", ty.f32(), ast::StorageClass::kNone, Expr("v"));
148   WrapInFunction(v, v2);
149 
150   spirv::Builder& b = Build();
151 
152   b.push_function(Function{});
153   EXPECT_TRUE(b.GenerateFunctionVariable(v)) << b.error();
154   EXPECT_TRUE(b.GenerateFunctionVariable(v2)) << b.error();
155   ASSERT_FALSE(b.has_error()) << b.error();
156 
157   EXPECT_EQ(DumpInstructions(b.debug()), R"(OpName %3 "v"
158 OpName %7 "v2"
159 )");
160   EXPECT_EQ(DumpInstructions(b.types()), R"(%1 = OpTypeFloat 32
161 %2 = OpConstant %1 1
162 %4 = OpTypePointer Function %1
163 %5 = OpConstantNull %1
164 )");
165   EXPECT_EQ(DumpInstructions(b.functions()[0].variables()),
166             R"(%3 = OpVariable %4 Function %5
167 %7 = OpVariable %4 Function %5
168 )");
169   EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
170             R"(OpStore %3 %2
171 %6 = OpLoad %1 %3
172 OpStore %7 %6
173 )");
174 }
175 
TEST_F(BuilderTest,FunctionVar_Const)176 TEST_F(BuilderTest, FunctionVar_Const) {
177   auto* init = vec3<f32>(1.f, 1.f, 3.f);
178 
179   auto* v = Const("var", ty.vec3<f32>(), init);
180 
181   WrapInFunction(v);
182 
183   spirv::Builder& b = Build();
184 
185   EXPECT_TRUE(b.GenerateFunctionVariable(v)) << b.error();
186   ASSERT_FALSE(b.has_error()) << b.error();
187 
188   EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
189 %1 = OpTypeVector %2 3
190 %3 = OpConstant %2 1
191 %4 = OpConstant %2 3
192 %5 = OpConstantComposite %1 %3 %3 %4
193 )");
194 }
195 
196 }  // namespace
197 }  // namespace spirv
198 }  // namespace writer
199 }  // namespace tint
200