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 "gmock/gmock.h"
16 #include "src/reader/spirv/function.h"
17 #include "src/reader/spirv/parser_impl_test_helper.h"
18 #include "src/reader/spirv/spirv_tools_helpers_test.h"
19
20 namespace tint {
21 namespace reader {
22 namespace spirv {
23 namespace {
24
25 using ::testing::HasSubstr;
26
Preamble()27 std::string Preamble() {
28 return R"(
29 OpCapability Shader
30 %glsl = OpExtInstImport "GLSL.std.450"
31 OpMemoryModel Logical GLSL450
32 OpEntryPoint GLCompute %100 "main"
33 OpExecutionMode %100 LocalSize 1 1 1
34
35 OpName %u1 "u1"
36 OpName %u2 "u2"
37 OpName %u3 "u3"
38 OpName %i1 "i1"
39 OpName %i2 "i2"
40 OpName %i3 "i3"
41 OpName %f1 "f1"
42 OpName %f2 "f2"
43 OpName %f3 "f3"
44 OpName %v2u1 "v2u1"
45 OpName %v2u2 "v2u2"
46 OpName %v2u3 "v2u3"
47 OpName %v2i1 "v2i1"
48 OpName %v2i2 "v2i2"
49 OpName %v2i3 "v2i3"
50 OpName %v2f1 "v2f1"
51 OpName %v2f2 "v2f2"
52 OpName %v2f3 "v2f3"
53 OpName %v3f1 "v3f1"
54 OpName %v3f2 "v3f2"
55 OpName %v4f1 "v4f1"
56 OpName %v4f2 "v4f2"
57
58 %void = OpTypeVoid
59 %voidfn = OpTypeFunction %void
60
61 %uint = OpTypeInt 32 0
62 %int = OpTypeInt 32 1
63 %float = OpTypeFloat 32
64
65 %uint_10 = OpConstant %uint 10
66 %uint_15 = OpConstant %uint 15
67 %uint_20 = OpConstant %uint 20
68 %int_30 = OpConstant %int 30
69 %int_35 = OpConstant %int 35
70 %int_40 = OpConstant %int 40
71 %float_50 = OpConstant %float 50
72 %float_60 = OpConstant %float 60
73 %float_70 = OpConstant %float 70
74
75 %v2uint = OpTypeVector %uint 2
76 %v2int = OpTypeVector %int 2
77 %v2float = OpTypeVector %float 2
78 %v3float = OpTypeVector %float 3
79 %v4float = OpTypeVector %float 4
80
81 %v2uint_10_20 = OpConstantComposite %v2uint %uint_10 %uint_20
82 %v2uint_20_10 = OpConstantComposite %v2uint %uint_20 %uint_10
83 %v2uint_15_15 = OpConstantComposite %v2uint %uint_15 %uint_15
84 %v2int_30_40 = OpConstantComposite %v2int %int_30 %int_40
85 %v2int_40_30 = OpConstantComposite %v2int %int_40 %int_30
86 %v2int_35_35 = OpConstantComposite %v2int %int_35 %int_35
87 %v2float_50_60 = OpConstantComposite %v2float %float_50 %float_60
88 %v2float_60_50 = OpConstantComposite %v2float %float_60 %float_50
89 %v2float_70_70 = OpConstantComposite %v2float %float_70 %float_70
90
91 %v3float_50_60_70 = OpConstantComposite %v3float %float_50 %float_60 %float_70
92 %v3float_60_70_50 = OpConstantComposite %v3float %float_60 %float_70 %float_50
93
94 %v4float_50_50_50_50 = OpConstantComposite %v4float %float_50 %float_50 %float_50 %float_50
95
96 %100 = OpFunction %void None %voidfn
97 %entry = OpLabel
98
99 %u1 = OpCopyObject %uint %uint_10
100 %u2 = OpCopyObject %uint %uint_15
101 %u3 = OpCopyObject %uint %uint_20
102
103 %i1 = OpCopyObject %int %int_30
104 %i2 = OpCopyObject %int %int_35
105 %i3 = OpCopyObject %int %int_40
106
107 %f1 = OpCopyObject %float %float_50
108 %f2 = OpCopyObject %float %float_60
109 %f3 = OpCopyObject %float %float_70
110
111 %v2u1 = OpCopyObject %v2uint %v2uint_10_20
112 %v2u2 = OpCopyObject %v2uint %v2uint_20_10
113 %v2u3 = OpCopyObject %v2uint %v2uint_15_15
114
115 %v2i1 = OpCopyObject %v2int %v2int_30_40
116 %v2i2 = OpCopyObject %v2int %v2int_40_30
117 %v2i3 = OpCopyObject %v2int %v2int_35_35
118
119 %v2f1 = OpCopyObject %v2float %v2float_50_60
120 %v2f2 = OpCopyObject %v2float %v2float_60_50
121 %v2f3 = OpCopyObject %v2float %v2float_70_70
122
123 %v3f1 = OpCopyObject %v3float %v3float_50_60_70
124 %v3f2 = OpCopyObject %v3float %v3float_60_70_50
125
126 %v4f1 = OpCopyObject %v4float %v4float_50_50_50_50
127 %v4f2 = OpCopyObject %v4float %v4f1
128 )";
129 }
130
131 struct GlslStd450Case {
132 std::string opcode;
133 std::string wgsl_func;
134 };
operator <<(std::ostream & out,GlslStd450Case c)135 inline std::ostream& operator<<(std::ostream& out, GlslStd450Case c) {
136 out << "GlslStd450Case(" << c.opcode << " " << c.wgsl_func << ")";
137 return out;
138 }
139
140 // Nomenclature:
141 // Float = scalar float
142 // Floating = scalar float or vector-of-float
143 // Float3 = 3-element vector of float
144 // Int = scalar signed int
145 // Inting = scalar int or vector-of-int
146 // Uint = scalar unsigned int
147 // Uinting = scalar unsigned or vector-of-unsigned
148
149 using SpvParserTest_GlslStd450_Float_Floating =
150 SpvParserTestBase<::testing::TestWithParam<GlslStd450Case>>;
151 using SpvParserTest_GlslStd450_Float_FloatingFloating =
152 SpvParserTestBase<::testing::TestWithParam<GlslStd450Case>>;
153 using SpvParserTest_GlslStd450_Floating_Floating =
154 SpvParserTestBase<::testing::TestWithParam<GlslStd450Case>>;
155 using SpvParserTest_GlslStd450_Floating_FloatingFloating =
156 SpvParserTestBase<::testing::TestWithParam<GlslStd450Case>>;
157 using SpvParserTest_GlslStd450_Floating_FloatingFloatingFloating =
158 SpvParserTestBase<::testing::TestWithParam<GlslStd450Case>>;
159 using SpvParserTest_GlslStd450_Floating_FloatingInting =
160 SpvParserTestBase<::testing::TestWithParam<GlslStd450Case>>;
161 using SpvParserTest_GlslStd450_Float3_Float3Float3 =
162 SpvParserTestBase<::testing::TestWithParam<GlslStd450Case>>;
163
164 using SpvParserTest_GlslStd450_Inting_Inting =
165 SpvParserTestBase<::testing::TestWithParam<GlslStd450Case>>;
166 using SpvParserTest_GlslStd450_Inting_IntingInting =
167 SpvParserTestBase<::testing::TestWithParam<GlslStd450Case>>;
168 using SpvParserTest_GlslStd450_Inting_IntingIntingInting =
169 SpvParserTestBase<::testing::TestWithParam<GlslStd450Case>>;
170 using SpvParserTest_GlslStd450_Uinting_UintingUinting =
171 SpvParserTestBase<::testing::TestWithParam<GlslStd450Case>>;
172 using SpvParserTest_GlslStd450_Uinting_UintingUintingUinting =
173 SpvParserTestBase<::testing::TestWithParam<GlslStd450Case>>;
174
TEST_P(SpvParserTest_GlslStd450_Float_Floating,Scalar)175 TEST_P(SpvParserTest_GlslStd450_Float_Floating, Scalar) {
176 const auto assembly = Preamble() + R"(
177 %1 = OpExtInst %float %glsl )" +
178 GetParam().opcode + R"( %f1
179 OpReturn
180 OpFunctionEnd
181 )";
182 auto p = parser(test::Assemble(assembly));
183 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
184 auto fe = p->function_emitter(100);
185 EXPECT_TRUE(fe.EmitBody()) << p->error();
186 auto ast_body = fe.ast_body();
187 const auto body = test::ToString(p->program(), ast_body);
188 EXPECT_THAT(body,
189 HasSubstr("let x_1 : f32 = " + GetParam().wgsl_func + "(f1);"))
190 << body;
191 }
192
TEST_P(SpvParserTest_GlslStd450_Float_Floating,Vector)193 TEST_P(SpvParserTest_GlslStd450_Float_Floating, Vector) {
194 const auto assembly = Preamble() + R"(
195 %1 = OpExtInst %float %glsl )" +
196 GetParam().opcode + R"( %v2f1
197 OpReturn
198 OpFunctionEnd
199 )";
200 auto p = parser(test::Assemble(assembly));
201 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
202 auto fe = p->function_emitter(100);
203 EXPECT_TRUE(fe.EmitBody()) << p->error();
204 auto ast_body = fe.ast_body();
205 const auto body = test::ToString(p->program(), ast_body);
206 EXPECT_THAT(body,
207 HasSubstr("let x_1 : f32 = " + GetParam().wgsl_func + "(v2f1);"))
208 << body;
209 }
210
TEST_P(SpvParserTest_GlslStd450_Float_FloatingFloating,Scalar)211 TEST_P(SpvParserTest_GlslStd450_Float_FloatingFloating, Scalar) {
212 const auto assembly = Preamble() + R"(
213 %1 = OpExtInst %float %glsl )" +
214 GetParam().opcode + R"( %f1 %f2
215 OpReturn
216 OpFunctionEnd
217 )";
218 auto p = parser(test::Assemble(assembly));
219 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
220 auto fe = p->function_emitter(100);
221 EXPECT_TRUE(fe.EmitBody()) << p->error();
222 auto ast_body = fe.ast_body();
223 const auto body = test::ToString(p->program(), ast_body);
224 EXPECT_THAT(
225 body, HasSubstr("let x_1 : f32 = " + GetParam().wgsl_func + "(f1, f2);"))
226 << body;
227 }
228
TEST_P(SpvParserTest_GlslStd450_Float_FloatingFloating,Vector)229 TEST_P(SpvParserTest_GlslStd450_Float_FloatingFloating, Vector) {
230 const auto assembly = Preamble() + R"(
231 %1 = OpExtInst %float %glsl )" +
232 GetParam().opcode + R"( %v2f1 %v2f2
233 OpReturn
234 OpFunctionEnd
235 )";
236 auto p = parser(test::Assemble(assembly));
237 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
238 auto fe = p->function_emitter(100);
239 EXPECT_TRUE(fe.EmitBody()) << p->error();
240 auto ast_body = fe.ast_body();
241 const auto body = test::ToString(p->program(), ast_body);
242 EXPECT_THAT(body, HasSubstr("let x_1 : f32 = " + GetParam().wgsl_func +
243 "(v2f1, v2f2);"))
244 << body;
245 }
246
TEST_P(SpvParserTest_GlslStd450_Floating_Floating,Scalar)247 TEST_P(SpvParserTest_GlslStd450_Floating_Floating, Scalar) {
248 const auto assembly = Preamble() + R"(
249 %1 = OpExtInst %float %glsl )" +
250 GetParam().opcode + R"( %f1
251 OpReturn
252 OpFunctionEnd
253 )";
254 auto p = parser(test::Assemble(assembly));
255 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
256 auto fe = p->function_emitter(100);
257 EXPECT_TRUE(fe.EmitBody()) << p->error();
258 auto ast_body = fe.ast_body();
259 const auto body = test::ToString(p->program(), ast_body);
260 EXPECT_THAT(body,
261 HasSubstr("let x_1 : f32 = " + GetParam().wgsl_func + "(f1);"))
262 << body;
263 }
264
TEST_P(SpvParserTest_GlslStd450_Floating_Floating,Vector)265 TEST_P(SpvParserTest_GlslStd450_Floating_Floating, Vector) {
266 const auto assembly = Preamble() + R"(
267 %1 = OpExtInst %v2float %glsl )" +
268 GetParam().opcode + R"( %v2f1
269 OpReturn
270 OpFunctionEnd
271 )";
272 auto p = parser(test::Assemble(assembly));
273 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
274 auto fe = p->function_emitter(100);
275 EXPECT_TRUE(fe.EmitBody()) << p->error();
276 auto ast_body = fe.ast_body();
277 const auto body = test::ToString(p->program(), ast_body);
278 EXPECT_THAT(body, HasSubstr("let x_1 : vec2<f32> = " + GetParam().wgsl_func +
279 "(v2f1);"))
280 << body;
281 }
282
TEST_P(SpvParserTest_GlslStd450_Floating_FloatingFloating,Scalar)283 TEST_P(SpvParserTest_GlslStd450_Floating_FloatingFloating, Scalar) {
284 const auto assembly = Preamble() + R"(
285 %1 = OpExtInst %float %glsl )" +
286 GetParam().opcode + R"( %f1 %f2
287 OpReturn
288 OpFunctionEnd
289 )";
290 auto p = parser(test::Assemble(assembly));
291 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
292 auto fe = p->function_emitter(100);
293 EXPECT_TRUE(fe.EmitBody()) << p->error();
294 auto ast_body = fe.ast_body();
295 const auto body = test::ToString(p->program(), ast_body);
296 EXPECT_THAT(
297 body, HasSubstr("let x_1 : f32 = " + GetParam().wgsl_func + "(f1, f2);"))
298 << body;
299 }
300
TEST_P(SpvParserTest_GlslStd450_Floating_FloatingFloating,Vector)301 TEST_P(SpvParserTest_GlslStd450_Floating_FloatingFloating, Vector) {
302 const auto assembly = Preamble() + R"(
303 %1 = OpExtInst %v2float %glsl )" +
304 GetParam().opcode + R"( %v2f1 %v2f2
305 OpReturn
306 OpFunctionEnd
307 )";
308 auto p = parser(test::Assemble(assembly));
309 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
310 auto fe = p->function_emitter(100);
311 EXPECT_TRUE(fe.EmitBody()) << p->error();
312 auto ast_body = fe.ast_body();
313 const auto body = test::ToString(p->program(), ast_body);
314 EXPECT_THAT(body, HasSubstr("let x_1 : vec2<f32> = " + GetParam().wgsl_func +
315 "(v2f1, v2f2);"))
316 << body;
317 }
318
TEST_P(SpvParserTest_GlslStd450_Floating_FloatingFloatingFloating,Scalar)319 TEST_P(SpvParserTest_GlslStd450_Floating_FloatingFloatingFloating, Scalar) {
320 const auto assembly = Preamble() + R"(
321 %1 = OpExtInst %float %glsl )" +
322 GetParam().opcode + R"( %f1 %f2 %f3
323 OpReturn
324 OpFunctionEnd
325 )";
326 auto p = parser(test::Assemble(assembly));
327 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
328 auto fe = p->function_emitter(100);
329 EXPECT_TRUE(fe.EmitBody()) << p->error();
330 auto ast_body = fe.ast_body();
331 const auto body = test::ToString(p->program(), ast_body);
332 EXPECT_THAT(body, HasSubstr("let x_1 : f32 = " + GetParam().wgsl_func +
333 "(f1, f2, f3);"))
334 << body;
335 }
336
TEST_P(SpvParserTest_GlslStd450_Floating_FloatingFloatingFloating,Vector)337 TEST_P(SpvParserTest_GlslStd450_Floating_FloatingFloatingFloating, Vector) {
338 const auto assembly = Preamble() + R"(
339 %1 = OpExtInst %v2float %glsl )" +
340 GetParam().opcode +
341 R"( %v2f1 %v2f2 %v2f3
342 OpReturn
343 OpFunctionEnd
344 )";
345 auto p = parser(test::Assemble(assembly));
346 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
347 auto fe = p->function_emitter(100);
348 EXPECT_TRUE(fe.EmitBody()) << p->error();
349 auto ast_body = fe.ast_body();
350 const auto body = test::ToString(p->program(), ast_body);
351 EXPECT_THAT(body, HasSubstr("let x_1 : vec2<f32> = " + GetParam().wgsl_func +
352 "(v2f1, v2f2, v2f3);"))
353 << body;
354 }
355
TEST_P(SpvParserTest_GlslStd450_Floating_FloatingInting,Scalar)356 TEST_P(SpvParserTest_GlslStd450_Floating_FloatingInting, Scalar) {
357 const auto assembly = Preamble() + R"(
358 %1 = OpExtInst %float %glsl )" +
359 GetParam().opcode + R"( %f1 %i1
360 OpReturn
361 OpFunctionEnd
362 )";
363 auto p = parser(test::Assemble(assembly));
364 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
365 auto fe = p->function_emitter(100);
366 EXPECT_TRUE(fe.EmitBody()) << p->error();
367 auto ast_body = fe.ast_body();
368 const auto body = test::ToString(p->program(), ast_body);
369 EXPECT_THAT(
370 body, HasSubstr("let x_1 : f32 = " + GetParam().wgsl_func + "(f1, i1);"))
371 << body;
372 }
373
TEST_P(SpvParserTest_GlslStd450_Floating_FloatingInting,Vector)374 TEST_P(SpvParserTest_GlslStd450_Floating_FloatingInting, Vector) {
375 const auto assembly = Preamble() + R"(
376 %1 = OpExtInst %v2float %glsl )" +
377 GetParam().opcode +
378 R"( %v2f1 %v2i1
379 OpReturn
380 OpFunctionEnd
381 )";
382 auto p = parser(test::Assemble(assembly));
383 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
384 auto fe = p->function_emitter(100);
385 EXPECT_TRUE(fe.EmitBody()) << p->error();
386 auto ast_body = fe.ast_body();
387 const auto body = test::ToString(p->program(), ast_body);
388 EXPECT_THAT(body, HasSubstr("let x_1 : vec2<f32> = " + GetParam().wgsl_func +
389 "(v2f1, v2i1);"))
390 << body;
391 }
392
TEST_P(SpvParserTest_GlslStd450_Float3_Float3Float3,Samples)393 TEST_P(SpvParserTest_GlslStd450_Float3_Float3Float3, Samples) {
394 const auto assembly = Preamble() + R"(
395 %1 = OpExtInst %v3float %glsl )" +
396 GetParam().opcode +
397 R"( %v3f1 %v3f2
398 OpReturn
399 OpFunctionEnd
400 )";
401 auto p = parser(test::Assemble(assembly));
402 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
403 auto fe = p->function_emitter(100);
404 EXPECT_TRUE(fe.EmitBody()) << p->error();
405 auto ast_body = fe.ast_body();
406 const auto body = test::ToString(p->program(), ast_body);
407 EXPECT_THAT(body, HasSubstr("let x_1 : vec3<f32> = " + GetParam().wgsl_func +
408 "(v3f1, v3f2);"))
409 << body;
410 }
411
412 INSTANTIATE_TEST_SUITE_P(Samples,
413 SpvParserTest_GlslStd450_Float_Floating,
414 ::testing::Values(GlslStd450Case{"Length", "length"}));
415
416 INSTANTIATE_TEST_SUITE_P(Samples,
417 SpvParserTest_GlslStd450_Float_FloatingFloating,
418 ::testing::Values(GlslStd450Case{"Distance",
419 "distance"}));
420
421 INSTANTIATE_TEST_SUITE_P(Samples,
422 SpvParserTest_GlslStd450_Floating_Floating,
423 ::testing::ValuesIn(std::vector<GlslStd450Case>{
424 {"Acos", "acos"},
425 {"Asin", "asin"},
426 {"Atan", "atan"},
427 {"Ceil", "ceil"},
428 {"Cos", "cos"},
429 {"Cosh", "cosh"},
430 {"Exp", "exp"},
431 {"Exp2", "exp2"},
432 {"FAbs", "abs"},
433 {"FSign", "sign"},
434 {"Floor", "floor"},
435 {"Fract", "fract"},
436 {"InverseSqrt", "inverseSqrt"},
437 {"Log", "log"},
438 {"Log2", "log2"},
439 {"Round", "round"},
440 {"RoundEven", "round"},
441 {"Sin", "sin"},
442 {"Sinh", "sinh"},
443 {"Sqrt", "sqrt"},
444 {"Tan", "tan"},
445 {"Tanh", "tanh"},
446 {"Trunc", "trunc"},
447 }));
448
449 INSTANTIATE_TEST_SUITE_P(Samples,
450 SpvParserTest_GlslStd450_Floating_FloatingFloating,
451 ::testing::ValuesIn(std::vector<GlslStd450Case>{
452 {"Atan2", "atan2"},
453 {"NMax", "max"},
454 {"NMin", "min"},
455 {"FMax", "max"}, // WGSL max promises more for NaN
456 {"FMin", "min"}, // WGSL min promises more for NaN
457 {"Pow", "pow"},
458 {"Step", "step"},
459 }));
460
461 INSTANTIATE_TEST_SUITE_P(Samples,
462 SpvParserTest_GlslStd450_Floating_FloatingInting,
463 ::testing::Values(GlslStd450Case{"Ldexp", "ldexp"}));
464 // For ldexp with unsigned second argument, see below.
465
466 INSTANTIATE_TEST_SUITE_P(Samples,
467 SpvParserTest_GlslStd450_Float3_Float3Float3,
468 ::testing::Values(GlslStd450Case{"Cross", "cross"}));
469
470 INSTANTIATE_TEST_SUITE_P(
471 Samples,
472 SpvParserTest_GlslStd450_Floating_FloatingFloatingFloating,
473 ::testing::ValuesIn(std::vector<GlslStd450Case>{
474 {"NClamp", "clamp"},
475 {"FClamp", "clamp"}, // WGSL FClamp promises more for NaN
476 {"Fma", "fma"},
477 {"FMix", "mix"},
478 {"SmoothStep", "smoothStep"}}));
479
TEST_P(SpvParserTest_GlslStd450_Inting_Inting,Scalar)480 TEST_P(SpvParserTest_GlslStd450_Inting_Inting, Scalar) {
481 const auto assembly = Preamble() + R"(
482 %1 = OpExtInst %int %glsl )" +
483 GetParam().opcode +
484 R"( %i1
485 OpReturn
486 OpFunctionEnd
487 )";
488 auto p = parser(test::Assemble(assembly));
489 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
490 auto fe = p->function_emitter(100);
491 EXPECT_TRUE(fe.EmitBody()) << p->error();
492 auto ast_body = fe.ast_body();
493 const auto body = test::ToString(p->program(), ast_body);
494 EXPECT_THAT(body,
495 HasSubstr("let x_1 : i32 = " + GetParam().wgsl_func + "(i1);"))
496 << body;
497 }
498
TEST_P(SpvParserTest_GlslStd450_Inting_Inting,Vector)499 TEST_P(SpvParserTest_GlslStd450_Inting_Inting, Vector) {
500 const auto assembly = Preamble() + R"(
501 %1 = OpExtInst %v2int %glsl )" +
502 GetParam().opcode +
503 R"( %v2i1
504 OpReturn
505 OpFunctionEnd
506 )";
507 auto p = parser(test::Assemble(assembly));
508 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
509 auto fe = p->function_emitter(100);
510 EXPECT_TRUE(fe.EmitBody()) << p->error();
511 auto ast_body = fe.ast_body();
512 const auto body = test::ToString(p->program(), ast_body);
513 EXPECT_THAT(body, HasSubstr("let x_1 : vec2<i32> = " + GetParam().wgsl_func +
514 "(v2i1);"))
515 << body;
516 }
517
TEST_P(SpvParserTest_GlslStd450_Inting_IntingInting,Scalar)518 TEST_P(SpvParserTest_GlslStd450_Inting_IntingInting, Scalar) {
519 const auto assembly = Preamble() + R"(
520 %1 = OpExtInst %int %glsl )" +
521 GetParam().opcode +
522 R"( %i1 %i2
523 OpReturn
524 OpFunctionEnd
525 )";
526 auto p = parser(test::Assemble(assembly));
527 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
528 auto fe = p->function_emitter(100);
529 EXPECT_TRUE(fe.EmitBody()) << p->error();
530 auto ast_body = fe.ast_body();
531 const auto body = test::ToString(p->program(), ast_body);
532 EXPECT_THAT(
533 body, HasSubstr("let x_1 : i32 = " + GetParam().wgsl_func + "(i1, i2);"))
534 << body;
535 }
536
TEST_P(SpvParserTest_GlslStd450_Inting_IntingInting,Vector)537 TEST_P(SpvParserTest_GlslStd450_Inting_IntingInting, Vector) {
538 const auto assembly = Preamble() + R"(
539 %1 = OpExtInst %v2int %glsl )" +
540 GetParam().opcode +
541 R"( %v2i1 %v2i2
542 OpReturn
543 OpFunctionEnd
544 )";
545 auto p = parser(test::Assemble(assembly));
546 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
547 auto fe = p->function_emitter(100);
548 EXPECT_TRUE(fe.EmitBody()) << p->error();
549 auto ast_body = fe.ast_body();
550 const auto body = test::ToString(p->program(), ast_body);
551 EXPECT_THAT(body, HasSubstr("let x_1 : vec2<i32> = " + GetParam().wgsl_func +
552 "(v2i1, v2i2);"))
553 << body;
554 }
555
TEST_P(SpvParserTest_GlslStd450_Inting_IntingIntingInting,Scalar)556 TEST_P(SpvParserTest_GlslStd450_Inting_IntingIntingInting, Scalar) {
557 const auto assembly = Preamble() + R"(
558 %1 = OpExtInst %int %glsl )" +
559 GetParam().opcode +
560 R"( %i1 %i2 %i3
561 OpReturn
562 OpFunctionEnd
563 )";
564 auto p = parser(test::Assemble(assembly));
565 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
566 auto fe = p->function_emitter(100);
567 EXPECT_TRUE(fe.EmitBody()) << p->error();
568 auto ast_body = fe.ast_body();
569 const auto body = test::ToString(p->program(), ast_body);
570 EXPECT_THAT(body, HasSubstr("let x_1 : i32 = " + GetParam().wgsl_func +
571 "(i1, i2, i3);"))
572 << body;
573 }
574
TEST_P(SpvParserTest_GlslStd450_Inting_IntingIntingInting,Vector)575 TEST_P(SpvParserTest_GlslStd450_Inting_IntingIntingInting, Vector) {
576 const auto assembly = Preamble() + R"(
577 %1 = OpExtInst %v2int %glsl )" +
578 GetParam().opcode +
579 R"( %v2i1 %v2i2 %v2i3
580 OpReturn
581 OpFunctionEnd
582 )";
583 auto p = parser(test::Assemble(assembly));
584 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
585 auto fe = p->function_emitter(100);
586 EXPECT_TRUE(fe.EmitBody()) << p->error();
587 auto ast_body = fe.ast_body();
588 const auto body = test::ToString(p->program(), ast_body);
589 EXPECT_THAT(body, HasSubstr("let x_1 : vec2<i32> = " + GetParam().wgsl_func +
590 "(v2i1, v2i2, v2i3);"))
591 << body;
592 }
593
594 INSTANTIATE_TEST_SUITE_P(Samples,
595 SpvParserTest_GlslStd450_Inting_Inting,
596 ::testing::Values(GlslStd450Case{"SAbs", "abs"}));
597
598 INSTANTIATE_TEST_SUITE_P(Samples,
599 SpvParserTest_GlslStd450_Inting_IntingInting,
600 ::testing::Values(GlslStd450Case{"SMax", "max"},
601 GlslStd450Case{"SMin", "min"}));
602
603 INSTANTIATE_TEST_SUITE_P(Samples,
604 SpvParserTest_GlslStd450_Inting_IntingIntingInting,
605 ::testing::Values(GlslStd450Case{"SClamp", "clamp"}));
606
TEST_P(SpvParserTest_GlslStd450_Uinting_UintingUinting,Scalar)607 TEST_P(SpvParserTest_GlslStd450_Uinting_UintingUinting, Scalar) {
608 const auto assembly = Preamble() + R"(
609 %1 = OpExtInst %uint %glsl )" +
610 GetParam().opcode + R"( %u1 %u2
611 OpReturn
612 OpFunctionEnd
613 )";
614 auto p = parser(test::Assemble(assembly));
615 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
616 auto fe = p->function_emitter(100);
617 EXPECT_TRUE(fe.EmitBody()) << p->error();
618 auto ast_body = fe.ast_body();
619 const auto body = test::ToString(p->program(), ast_body);
620 EXPECT_THAT(
621 body, HasSubstr("let x_1 : u32 = " + GetParam().wgsl_func + "(u1, u2);"))
622 << body;
623 }
624
TEST_P(SpvParserTest_GlslStd450_Uinting_UintingUinting,Vector)625 TEST_P(SpvParserTest_GlslStd450_Uinting_UintingUinting, Vector) {
626 const auto assembly = Preamble() + R"(
627 %1 = OpExtInst %v2uint %glsl )" +
628 GetParam().opcode +
629 R"( %v2u1 %v2u2
630 OpReturn
631 OpFunctionEnd
632 )";
633 auto p = parser(test::Assemble(assembly));
634 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
635 auto fe = p->function_emitter(100);
636 EXPECT_TRUE(fe.EmitBody()) << p->error();
637 auto ast_body = fe.ast_body();
638 const auto body = test::ToString(p->program(), ast_body);
639 EXPECT_THAT(body, HasSubstr("let x_1 : vec2<u32> = " + GetParam().wgsl_func +
640 "(v2u1, v2u2);"))
641 << body;
642 }
643
TEST_P(SpvParserTest_GlslStd450_Uinting_UintingUintingUinting,Scalar)644 TEST_P(SpvParserTest_GlslStd450_Uinting_UintingUintingUinting, Scalar) {
645 const auto assembly = Preamble() + R"(
646 %1 = OpExtInst %uint %glsl )" +
647 GetParam().opcode + R"( %u1 %u2 %u3
648 OpReturn
649 OpFunctionEnd
650 )";
651 auto p = parser(test::Assemble(assembly));
652 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
653 auto fe = p->function_emitter(100);
654 EXPECT_TRUE(fe.EmitBody()) << p->error();
655 auto ast_body = fe.ast_body();
656 const auto body = test::ToString(p->program(), ast_body);
657 EXPECT_THAT(body, HasSubstr("let x_1 : u32 = " + GetParam().wgsl_func +
658 "(u1, u2, u3);"))
659 << body;
660 }
661
TEST_P(SpvParserTest_GlslStd450_Uinting_UintingUintingUinting,Vector)662 TEST_P(SpvParserTest_GlslStd450_Uinting_UintingUintingUinting, Vector) {
663 const auto assembly = Preamble() + R"(
664 %1 = OpExtInst %v2uint %glsl )" +
665 GetParam().opcode +
666 R"( %v2u1 %v2u2 %v2u3
667 OpReturn
668 OpFunctionEnd
669 )";
670 auto p = parser(test::Assemble(assembly));
671 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
672 auto fe = p->function_emitter(100);
673 EXPECT_TRUE(fe.EmitBody()) << p->error();
674 auto ast_body = fe.ast_body();
675 const auto body = test::ToString(p->program(), ast_body);
676 EXPECT_THAT(body, HasSubstr("let x_1 : vec2<u32> = " + GetParam().wgsl_func +
677 "(v2u1, v2u2, v2u3);"))
678 << body;
679 }
680
681 INSTANTIATE_TEST_SUITE_P(Samples,
682 SpvParserTest_GlslStd450_Uinting_UintingUinting,
683 ::testing::Values(GlslStd450Case{"UMax", "max"},
684 GlslStd450Case{"UMin", "min"}));
685
686 INSTANTIATE_TEST_SUITE_P(Samples,
687 SpvParserTest_GlslStd450_Uinting_UintingUintingUinting,
688 ::testing::Values(GlslStd450Case{"UClamp", "clamp"}));
689
690 // Test Normalize. WGSL does not have a scalar form of the normalize builtin.
691 // So we have to test it separately, as it does not fit the patterns tested
692 // above.
693
TEST_F(SpvParserTest,Normalize_Scalar)694 TEST_F(SpvParserTest, Normalize_Scalar) {
695 // Scalar normalize always results in 1.0
696 const auto assembly = Preamble() + R"(
697 %1 = OpExtInst %float %glsl Normalize %f1
698 OpReturn
699 OpFunctionEnd
700 )";
701 auto p = parser(test::Assemble(assembly));
702 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
703 auto fe = p->function_emitter(100);
704 EXPECT_TRUE(fe.EmitBody()) << p->error();
705 auto ast_body = fe.ast_body();
706 const auto body = test::ToString(p->program(), ast_body);
707 EXPECT_THAT(body, HasSubstr("let x_1 : f32 = 1.0;")) << body;
708 }
709
TEST_F(SpvParserTest,Normalize_Vector2)710 TEST_F(SpvParserTest, Normalize_Vector2) {
711 // Scalar normalize always results in 1.0
712 const auto assembly = Preamble() + R"(
713 %1 = OpExtInst %v2float %glsl Normalize %v2f1
714 OpReturn
715 OpFunctionEnd
716 )";
717 auto p = parser(test::Assemble(assembly));
718 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
719 auto fe = p->function_emitter(100);
720 EXPECT_TRUE(fe.EmitBody()) << p->error();
721 auto ast_body = fe.ast_body();
722 const auto body = test::ToString(p->program(), ast_body);
723 EXPECT_THAT(body, HasSubstr("let x_1 : vec2<f32> = normalize(v2f1);"))
724 << body;
725 }
726
TEST_F(SpvParserTest,Normalize_Vector3)727 TEST_F(SpvParserTest, Normalize_Vector3) {
728 // Scalar normalize always results in 1.0
729 const auto assembly = Preamble() + R"(
730 %1 = OpExtInst %v3float %glsl Normalize %v3f1
731 OpReturn
732 OpFunctionEnd
733 )";
734 auto p = parser(test::Assemble(assembly));
735 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
736 auto fe = p->function_emitter(100);
737 EXPECT_TRUE(fe.EmitBody()) << p->error();
738 auto ast_body = fe.ast_body();
739 const auto body = test::ToString(p->program(), ast_body);
740 EXPECT_THAT(body, HasSubstr("let x_1 : vec3<f32> = normalize(v3f1);"))
741 << body;
742 }
743
TEST_F(SpvParserTest,Normalize_Vector4)744 TEST_F(SpvParserTest, Normalize_Vector4) {
745 // Scalar normalize always results in 1.0
746 const auto assembly = Preamble() + R"(
747 %1 = OpExtInst %v4float %glsl Normalize %v4f1
748 OpReturn
749 OpFunctionEnd
750 )";
751 auto p = parser(test::Assemble(assembly));
752 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
753 auto fe = p->function_emitter(100);
754 EXPECT_TRUE(fe.EmitBody()) << p->error();
755 auto ast_body = fe.ast_body();
756 const auto body = test::ToString(p->program(), ast_body);
757 EXPECT_THAT(body, HasSubstr("let x_1 : vec4<f32> = normalize(v4f1);"))
758 << body;
759 }
760
761 // Check that we convert signedness of operands and result type.
762 // This is needed for each of the integer-based extended instructions.
763
TEST_F(SpvParserTest,RectifyOperandsAndResult_SAbs)764 TEST_F(SpvParserTest, RectifyOperandsAndResult_SAbs) {
765 const auto assembly = Preamble() + R"(
766 %1 = OpExtInst %uint %glsl SAbs %u1
767 %2 = OpExtInst %v2uint %glsl SAbs %v2u1
768 OpReturn
769 OpFunctionEnd
770 )";
771 auto p = parser(test::Assemble(assembly));
772 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
773 auto fe = p->function_emitter(100);
774 EXPECT_TRUE(fe.EmitBody()) << p->error();
775 auto ast_body = fe.ast_body();
776 const auto body = test::ToString(p->program(), ast_body);
777 EXPECT_THAT(
778 body,
779 HasSubstr(R"(let x_1 : u32 = bitcast<u32>(abs(bitcast<i32>(u1)));)"))
780 << body;
781 EXPECT_THAT(
782 body,
783 HasSubstr(
784 R"(let x_2 : vec2<u32> = bitcast<vec2<u32>>(abs(bitcast<vec2<i32>>(v2u1)));)"))
785 << body;
786 }
787
TEST_F(SpvParserTest,RectifyOperandsAndResult_SMax)788 TEST_F(SpvParserTest, RectifyOperandsAndResult_SMax) {
789 const auto assembly = Preamble() + R"(
790 %1 = OpExtInst %uint %glsl SMax %u1 %u2
791 %2 = OpExtInst %v2uint %glsl SMax %v2u1 %v2u2
792 OpReturn
793 OpFunctionEnd
794 )";
795 auto p = parser(test::Assemble(assembly));
796 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
797 auto fe = p->function_emitter(100);
798 EXPECT_TRUE(fe.EmitBody()) << p->error();
799 auto ast_body = fe.ast_body();
800 auto body = test::ToString(p->program(), ast_body);
801 EXPECT_THAT(
802 body,
803 HasSubstr(
804 R"(let x_1 : u32 = bitcast<u32>(max(bitcast<i32>(u1), bitcast<i32>(u2)));)"))
805 << body;
806 EXPECT_THAT(
807 body,
808 HasSubstr(
809 R"(let x_2 : vec2<u32> = bitcast<vec2<u32>>(max(bitcast<vec2<i32>>(v2u1), bitcast<vec2<i32>>(v2u2)));)"))
810 << body;
811 }
812
TEST_F(SpvParserTest,RectifyOperandsAndResult_SMin)813 TEST_F(SpvParserTest, RectifyOperandsAndResult_SMin) {
814 const auto assembly = Preamble() + R"(
815 %1 = OpExtInst %uint %glsl SMin %u1 %u2
816 %2 = OpExtInst %v2uint %glsl SMin %v2u1 %v2u2
817 OpReturn
818 OpFunctionEnd
819 )";
820 auto p = parser(test::Assemble(assembly));
821 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
822 auto fe = p->function_emitter(100);
823 EXPECT_TRUE(fe.EmitBody()) << p->error();
824 auto ast_body = fe.ast_body();
825 auto body = test::ToString(p->program(), ast_body);
826 EXPECT_THAT(
827 body,
828 HasSubstr(
829 R"(let x_1 : u32 = bitcast<u32>(min(bitcast<i32>(u1), bitcast<i32>(u2)));)"))
830 << body;
831 EXPECT_THAT(
832 body,
833 HasSubstr(
834 R"(let x_2 : vec2<u32> = bitcast<vec2<u32>>(min(bitcast<vec2<i32>>(v2u1), bitcast<vec2<i32>>(v2u2)));)"))
835 << body;
836 }
837
TEST_F(SpvParserTest,RectifyOperandsAndResult_SClamp)838 TEST_F(SpvParserTest, RectifyOperandsAndResult_SClamp) {
839 const auto assembly = Preamble() + R"(
840 %1 = OpExtInst %uint %glsl SClamp %u1 %i2 %u3
841 %2 = OpExtInst %v2uint %glsl SClamp %v2u1 %v2i2 %v2u3
842 OpReturn
843 OpFunctionEnd
844 )";
845 auto p = parser(test::Assemble(assembly));
846 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
847 auto fe = p->function_emitter(100);
848 EXPECT_TRUE(fe.EmitBody()) << p->error();
849 auto ast_body = fe.ast_body();
850 auto body = test::ToString(p->program(), ast_body);
851 EXPECT_THAT(
852 body,
853 HasSubstr(
854 R"(let x_1 : u32 = bitcast<u32>(clamp(bitcast<i32>(u1), i2, bitcast<i32>(u3)));)"))
855 << body;
856 EXPECT_THAT(
857 body,
858 HasSubstr(
859 R"(let x_2 : vec2<u32> = bitcast<vec2<u32>>(clamp(bitcast<vec2<i32>>(v2u1), v2i2, bitcast<vec2<i32>>(v2u3)));)"))
860 << body;
861 }
862
TEST_F(SpvParserTest,RectifyOperandsAndResult_UMax)863 TEST_F(SpvParserTest, RectifyOperandsAndResult_UMax) {
864 const auto assembly = Preamble() + R"(
865 %1 = OpExtInst %int %glsl UMax %i1 %i2
866 %2 = OpExtInst %v2int %glsl UMax %v2i1 %v2i2
867 OpReturn
868 OpFunctionEnd
869 )";
870 auto p = parser(test::Assemble(assembly));
871 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
872 auto fe = p->function_emitter(100);
873 EXPECT_TRUE(fe.EmitBody()) << p->error();
874 auto ast_body = fe.ast_body();
875 auto body = test::ToString(p->program(), ast_body);
876 EXPECT_THAT(
877 body,
878 HasSubstr(
879 R"(let x_1 : i32 = bitcast<i32>(max(bitcast<u32>(i1), bitcast<u32>(i2)));)"))
880 << body;
881 EXPECT_THAT(
882 body,
883 HasSubstr(
884 R"(let x_2 : vec2<i32> = bitcast<vec2<i32>>(max(bitcast<vec2<u32>>(v2i1), bitcast<vec2<u32>>(v2i2)));)"))
885 << body;
886 }
887
TEST_F(SpvParserTest,RectifyOperandsAndResult_UMin)888 TEST_F(SpvParserTest, RectifyOperandsAndResult_UMin) {
889 const auto assembly = Preamble() + R"(
890 %1 = OpExtInst %int %glsl UMin %i1 %i2
891 %2 = OpExtInst %v2int %glsl UMin %v2i1 %v2i2
892 OpReturn
893 OpFunctionEnd
894 )";
895 auto p = parser(test::Assemble(assembly));
896 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
897 auto fe = p->function_emitter(100);
898 EXPECT_TRUE(fe.EmitBody()) << p->error();
899 auto ast_body = fe.ast_body();
900 auto body = test::ToString(p->program(), ast_body);
901 EXPECT_THAT(
902 body,
903 HasSubstr(
904 R"(let x_1 : i32 = bitcast<i32>(min(bitcast<u32>(i1), bitcast<u32>(i2)));)"))
905 << body;
906 EXPECT_THAT(
907 body,
908 HasSubstr(
909 R"(let x_2 : vec2<i32> = bitcast<vec2<i32>>(min(bitcast<vec2<u32>>(v2i1), bitcast<vec2<u32>>(v2i2)));)"))
910 << body;
911 }
912
TEST_F(SpvParserTest,RectifyOperandsAndResult_UClamp)913 TEST_F(SpvParserTest, RectifyOperandsAndResult_UClamp) {
914 const auto assembly = Preamble() + R"(
915 %1 = OpExtInst %int %glsl UClamp %i1 %u2 %i3
916 %2 = OpExtInst %v2int %glsl UClamp %v2i1 %v2u2 %v2i3
917 OpReturn
918 OpFunctionEnd
919 )";
920 auto p = parser(test::Assemble(assembly));
921 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
922 auto fe = p->function_emitter(100);
923 EXPECT_TRUE(fe.EmitBody()) << p->error();
924 auto ast_body = fe.ast_body();
925 auto body = test::ToString(p->program(), ast_body);
926 EXPECT_THAT(
927 body,
928 HasSubstr(
929 R"(let x_1 : i32 = bitcast<i32>(clamp(bitcast<u32>(i1), u2, bitcast<u32>(i3)));)"))
930 << body;
931 EXPECT_THAT(
932 body,
933 HasSubstr(
934 R"(let x_2 : vec2<i32> = bitcast<vec2<i32>>(clamp(bitcast<vec2<u32>>(v2i1), v2u2, bitcast<vec2<u32>>(v2i3)));)"))
935 << body;
936 }
937
938 struct DataPackingCase {
939 std::string opcode;
940 std::string wgsl_func;
941 uint32_t vec_size;
942 };
943
operator <<(std::ostream & out,DataPackingCase c)944 inline std::ostream& operator<<(std::ostream& out, DataPackingCase c) {
945 out << "DataPacking(" << c.opcode << ")";
946 return out;
947 }
948
949 using SpvParserTest_GlslStd450_DataPacking =
950 SpvParserTestBase<::testing::TestWithParam<DataPackingCase>>;
951
TEST_P(SpvParserTest_GlslStd450_DataPacking,Valid)952 TEST_P(SpvParserTest_GlslStd450_DataPacking, Valid) {
953 auto param = GetParam();
954 const auto assembly = Preamble() + R"(
955 %1 = OpExtInst %uint %glsl )" +
956 param.opcode +
957 (param.vec_size == 2 ? " %v2f1" : " %v4f1") + R"(
958 OpReturn
959 OpFunctionEnd
960 )";
961 auto p = parser(test::Assemble(assembly));
962 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
963 auto fe = p->function_emitter(100);
964 EXPECT_TRUE(fe.EmitBody()) << p->error();
965 auto ast_body = fe.ast_body();
966 const auto body = test::ToString(p->program(), ast_body);
967 EXPECT_THAT(body, HasSubstr("let x_1 : u32 = " + param.wgsl_func + "(v" +
968 std::to_string(param.vec_size) + "f1);"))
969 << body;
970 }
971
972 INSTANTIATE_TEST_SUITE_P(Samples,
973 SpvParserTest_GlslStd450_DataPacking,
974 ::testing::ValuesIn(std::vector<DataPackingCase>{
975 {"PackSnorm4x8", "pack4x8snorm", 4},
976 {"PackUnorm4x8", "pack4x8unorm", 4},
977 {"PackSnorm2x16", "pack2x16snorm", 2},
978 {"PackUnorm2x16", "pack2x16unorm", 2},
979 {"PackHalf2x16", "pack2x16float", 2}}));
980
981 using SpvParserTest_GlslStd450_DataUnpacking =
982 SpvParserTestBase<::testing::TestWithParam<DataPackingCase>>;
983
TEST_P(SpvParserTest_GlslStd450_DataUnpacking,Valid)984 TEST_P(SpvParserTest_GlslStd450_DataUnpacking, Valid) {
985 auto param = GetParam();
986 const auto assembly = Preamble() + R"(
987 %1 = OpExtInst )" + (param.vec_size == 2 ? "%v2float" : "%v4float") +
988 std::string(" %glsl ") + param.opcode + R"( %u1
989 OpReturn
990 OpFunctionEnd
991 )";
992 auto p = parser(test::Assemble(assembly));
993 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
994 auto fe = p->function_emitter(100);
995 EXPECT_TRUE(fe.EmitBody()) << p->error();
996 auto ast_body = fe.ast_body();
997 const auto body = test::ToString(p->program(), ast_body);
998 EXPECT_THAT(body, HasSubstr("let x_1 : " +
999 std::string(param.vec_size == 2 ? "vec2<f32>"
1000 : "vec4<f32>") +
1001
1002 +" = " + param.wgsl_func + "(u1);"))
1003 << body;
1004 }
1005
1006 INSTANTIATE_TEST_SUITE_P(Samples,
1007 SpvParserTest_GlslStd450_DataUnpacking,
1008 ::testing::ValuesIn(std::vector<DataPackingCase>{
1009 {"UnpackSnorm4x8", "unpack4x8snorm", 4},
1010 {"UnpackUnorm4x8", "unpack4x8unorm", 4},
1011 {"UnpackSnorm2x16", "unpack2x16snorm", 2},
1012 {"UnpackUnorm2x16", "unpack2x16unorm", 2},
1013 {"UnpackHalf2x16", "unpack2x16float", 2}}));
1014
TEST_F(SpvParserTest,GlslStd450_Refract_Scalar)1015 TEST_F(SpvParserTest, GlslStd450_Refract_Scalar) {
1016 const auto assembly = Preamble() + R"(
1017 %1 = OpExtInst %float %glsl Refract %f1 %f2 %f3
1018 OpReturn
1019 OpFunctionEnd
1020 )";
1021 auto p = parser(test::Assemble(assembly));
1022 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
1023 auto fe = p->function_emitter(100);
1024 EXPECT_TRUE(fe.EmitBody()) << p->error();
1025 auto ast_body = fe.ast_body();
1026 const auto body = test::ToString(p->program(), ast_body);
1027 const auto* expected =
1028 R"(let x_1 : f32 = refract(vec2<f32>(f1, 0.0), vec2<f32>(f2, 0.0), f3).x;)";
1029
1030 EXPECT_THAT(body, HasSubstr(expected)) << body;
1031 }
1032
TEST_F(SpvParserTest,GlslStd450_Refract_Vector)1033 TEST_F(SpvParserTest, GlslStd450_Refract_Vector) {
1034 const auto assembly = Preamble() + R"(
1035 %1 = OpExtInst %v2float %glsl Refract %v2f1 %v2f2 %f3
1036 OpReturn
1037 OpFunctionEnd
1038 )";
1039 auto p = parser(test::Assemble(assembly));
1040 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
1041 auto fe = p->function_emitter(100);
1042 EXPECT_TRUE(fe.EmitBody()) << p->error();
1043 auto ast_body = fe.ast_body();
1044 const auto body = test::ToString(p->program(), ast_body);
1045 const auto* expected = R"(let x_1 : vec2<f32> = refract(v2f1, v2f2, f3);)";
1046
1047 EXPECT_THAT(body, HasSubstr(expected)) << body;
1048 }
1049
TEST_F(SpvParserTest,GlslStd450_FaceForward_Scalar)1050 TEST_F(SpvParserTest, GlslStd450_FaceForward_Scalar) {
1051 const auto assembly = Preamble() + R"(
1052 %99 = OpFAdd %float %f1 %f1 ; normal operand has only one use
1053 %1 = OpExtInst %float %glsl FaceForward %99 %f2 %f3
1054 OpReturn
1055 OpFunctionEnd
1056 )";
1057 auto p = parser(test::Assemble(assembly));
1058 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
1059 auto fe = p->function_emitter(100);
1060 EXPECT_TRUE(fe.EmitBody()) << p->error();
1061 auto ast_body = fe.ast_body();
1062 const auto body = test::ToString(p->program(), ast_body);
1063 // The %99 sum only has one use. Ensure it is evaluated only once by
1064 // making a let-declaration for it, since it is the normal operand to
1065 // the builtin function, and code generation uses it twice.
1066 const auto* expected =
1067 R"(let x_1 : f32 = select(-(x_99), x_99, ((f2 * f3) < 0.0));)";
1068
1069 EXPECT_THAT(body, HasSubstr(expected)) << body;
1070 }
1071
TEST_F(SpvParserTest,GlslStd450_FaceForward_Vector)1072 TEST_F(SpvParserTest, GlslStd450_FaceForward_Vector) {
1073 const auto assembly = Preamble() + R"(
1074 %99 = OpFAdd %v2float %v2f1 %v2f1
1075 %1 = OpExtInst %v2float %glsl FaceForward %v2f1 %v2f2 %v2f3
1076 OpReturn
1077 OpFunctionEnd
1078 )";
1079 auto p = parser(test::Assemble(assembly));
1080 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
1081 auto fe = p->function_emitter(100);
1082 EXPECT_TRUE(fe.EmitBody()) << p->error();
1083 auto ast_body = fe.ast_body();
1084 const auto body = test::ToString(p->program(), ast_body);
1085 const auto* expected =
1086 R"(let x_1 : vec2<f32> = faceForward(v2f1, v2f2, v2f3);)";
1087
1088 EXPECT_THAT(body, HasSubstr(expected)) << body;
1089 }
1090
TEST_F(SpvParserTest,GlslStd450_Reflect_Scalar)1091 TEST_F(SpvParserTest, GlslStd450_Reflect_Scalar) {
1092 const auto assembly = Preamble() + R"(
1093 %98 = OpFAdd %float %f1 %f1 ; has only one use
1094 %99 = OpFAdd %float %f2 %f2 ; has only one use
1095 %1 = OpExtInst %float %glsl Reflect %98 %99
1096 OpReturn
1097 OpFunctionEnd
1098 )";
1099 auto p = parser(test::Assemble(assembly));
1100 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
1101 auto fe = p->function_emitter(100);
1102 EXPECT_TRUE(fe.EmitBody()) << p->error();
1103 auto ast_body = fe.ast_body();
1104 const auto body = test::ToString(p->program(), ast_body);
1105 // The %99 sum only has one use. Ensure it is evaluated only once by
1106 // making a let-declaration for it, since it is the normal operand to
1107 // the builtin function, and code generation uses it twice.
1108 const auto* expected =
1109 R"(let x_1 : f32 = (x_98 - (2.0 * (x_99 * (x_99 * x_98))));)";
1110
1111 EXPECT_THAT(body, HasSubstr(expected)) << body;
1112 }
1113
TEST_F(SpvParserTest,GlslStd450_Reflect_Vector)1114 TEST_F(SpvParserTest, GlslStd450_Reflect_Vector) {
1115 const auto assembly = Preamble() + R"(
1116 %98 = OpFAdd %v2float %v2f1 %v2f1
1117 %99 = OpFAdd %v2float %v2f2 %v2f2
1118 %1 = OpExtInst %v2float %glsl Reflect %98 %99
1119 OpReturn
1120 OpFunctionEnd
1121 )";
1122 auto p = parser(test::Assemble(assembly));
1123 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
1124 auto fe = p->function_emitter(100);
1125 EXPECT_TRUE(fe.EmitBody()) << p->error();
1126 auto ast_body = fe.ast_body();
1127 const auto body = test::ToString(p->program(), ast_body);
1128 const auto* expected = R"(
1129 let x_98 : vec2<f32> = (v2f1 + v2f1);
1130 let x_99 : vec2<f32> = (v2f2 + v2f2);
1131 let x_1 : vec2<f32> = reflect(x_98, x_99);
1132 )";
1133
1134 EXPECT_THAT(body, HasSubstr(expected)) << body;
1135 }
1136
TEST_F(SpvParserTest,GlslStd450_Degrees_Scalar)1137 TEST_F(SpvParserTest, GlslStd450_Degrees_Scalar) {
1138 const auto assembly = Preamble() + R"(
1139 %1 = OpExtInst %float %glsl Degrees %float_50
1140 OpReturn
1141 OpFunctionEnd
1142 )";
1143 auto p = parser(test::Assemble(assembly));
1144 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
1145 auto fe = p->function_emitter(100);
1146 EXPECT_TRUE(fe.EmitBody()) << p->error();
1147 auto ast_body = fe.ast_body();
1148 const auto body = test::ToString(p->program(), ast_body);
1149 const auto* expected = "let x_1 : f32 = (50.0 * 57.295780182);";
1150
1151 EXPECT_THAT(body, HasSubstr(expected)) << body;
1152 }
1153
TEST_F(SpvParserTest,GlslStd450_Degrees_Vector)1154 TEST_F(SpvParserTest, GlslStd450_Degrees_Vector) {
1155 const auto assembly = Preamble() + R"(
1156 %1 = OpExtInst %v3float %glsl Degrees %v3float_60_70_50
1157 OpReturn
1158 OpFunctionEnd
1159 )";
1160 auto p = parser(test::Assemble(assembly));
1161 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
1162 auto fe = p->function_emitter(100);
1163 EXPECT_TRUE(fe.EmitBody()) << p->error();
1164 auto ast_body = fe.ast_body();
1165 const auto body = test::ToString(p->program(), ast_body);
1166 const auto* expected =
1167 R"(let x_1 : vec3<f32> = (vec3<f32>(60.0, 70.0, 50.0) * vec3<f32>(57.295780182));)";
1168
1169 EXPECT_THAT(body, HasSubstr(expected)) << body;
1170 }
1171
TEST_F(SpvParserTest,GlslStd450_Radians_Scalar)1172 TEST_F(SpvParserTest, GlslStd450_Radians_Scalar) {
1173 const auto assembly = Preamble() + R"(
1174 %1 = OpExtInst %float %glsl Radians %float_50
1175 OpReturn
1176 OpFunctionEnd
1177 )";
1178 auto p = parser(test::Assemble(assembly));
1179 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
1180 auto fe = p->function_emitter(100);
1181 EXPECT_TRUE(fe.EmitBody()) << p->error();
1182 auto ast_body = fe.ast_body();
1183 const auto body = test::ToString(p->program(), ast_body);
1184 const auto* expected = "let x_1 : f32 = (50.0 * 0.017453292);";
1185
1186 EXPECT_THAT(body, HasSubstr(expected)) << body;
1187 }
1188
TEST_F(SpvParserTest,GlslStd450_Radians_Vector)1189 TEST_F(SpvParserTest, GlslStd450_Radians_Vector) {
1190 const auto assembly = Preamble() + R"(
1191 %1 = OpExtInst %v3float %glsl Radians %v3float_60_70_50
1192 OpReturn
1193 OpFunctionEnd
1194 )";
1195 auto p = parser(test::Assemble(assembly));
1196 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
1197 auto fe = p->function_emitter(100);
1198 EXPECT_TRUE(fe.EmitBody()) << p->error();
1199 auto ast_body = fe.ast_body();
1200 const auto body = test::ToString(p->program(), ast_body);
1201 const auto* expected =
1202 R"(let x_1 : vec3<f32> = (vec3<f32>(60.0, 70.0, 50.0) * vec3<f32>(0.017453292));)";
1203
1204 EXPECT_THAT(body, HasSubstr(expected)) << body;
1205 }
1206
1207 // For ldexp with signed second argument, see above.
TEST_F(SpvParserTest,GlslStd450_Ldexp_Scalar_Float_Uint)1208 TEST_F(SpvParserTest, GlslStd450_Ldexp_Scalar_Float_Uint) {
1209 const auto assembly = Preamble() + R"(
1210 %1 = OpExtInst %float %glsl Ldexp %f1 %u1
1211 OpReturn
1212 OpFunctionEnd
1213 )";
1214 auto p = parser(test::Assemble(assembly));
1215 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
1216 auto fe = p->function_emitter(100);
1217 EXPECT_TRUE(fe.EmitBody()) << p->error();
1218 auto ast_body = fe.ast_body();
1219 const auto body = test::ToString(p->program(), ast_body);
1220 const auto* expected = "let x_1 : f32 = ldexp(f1, i32(u1));";
1221
1222 EXPECT_THAT(body, HasSubstr(expected)) << body;
1223 }
1224
TEST_F(SpvParserTest,GlslStd450_Ldexp_Vector_Floatvec_Uintvec)1225 TEST_F(SpvParserTest, GlslStd450_Ldexp_Vector_Floatvec_Uintvec) {
1226 const auto assembly = Preamble() + R"(
1227 %1 = OpExtInst %v2float %glsl Ldexp %v2f1 %v2u1
1228 OpReturn
1229 OpFunctionEnd
1230 )";
1231 auto p = parser(test::Assemble(assembly));
1232 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
1233 auto fe = p->function_emitter(100);
1234 EXPECT_TRUE(fe.EmitBody()) << p->error();
1235 auto ast_body = fe.ast_body();
1236 const auto body = test::ToString(p->program(), ast_body);
1237 const auto* expected = "let x_1 : vec2<f32> = ldexp(v2f1, vec2<i32>(v2u1));";
1238
1239 EXPECT_THAT(body, HasSubstr(expected)) << body;
1240 }
1241
1242 } // namespace
1243 } // namespace spirv
1244 } // namespace reader
1245 } // namespace tint
1246