1 // Copyright (c) 2017 Google Inc.
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 // Tests for unique type declaration rules validator.
16
17 #include <string>
18
19 #include "gmock/gmock.h"
20 #include "test/unit_spirv.h"
21 #include "test/val/val_code_generator.h"
22 #include "test/val/val_fixtures.h"
23
24 namespace spvtools {
25 namespace val {
26 namespace {
27
28 using ::testing::HasSubstr;
29 using ::testing::Not;
30 using ::testing::Values;
31
32 using ValidateConversion = spvtest::ValidateBase<bool>;
33
GenerateShaderCode(const std::string & body,const std::string & capabilities_and_extensions="",const std::string & decorations="",const std::string & types="",const std::string & variables="")34 std::string GenerateShaderCode(
35 const std::string& body,
36 const std::string& capabilities_and_extensions = "",
37 const std::string& decorations = "", const std::string& types = "",
38 const std::string& variables = "") {
39 const std::string capabilities =
40 R"(
41 OpCapability Shader
42 OpCapability Int64
43 OpCapability Float64)";
44
45 const std::string after_extension_before_decorations =
46 R"(
47 OpMemoryModel Logical GLSL450
48 OpEntryPoint Fragment %main "main"
49 OpExecutionMode %main OriginUpperLeft)";
50
51 const std::string after_decorations_before_types =
52 R"(
53 %void = OpTypeVoid
54 %func = OpTypeFunction %void
55 %bool = OpTypeBool
56 %f32 = OpTypeFloat 32
57 %u32 = OpTypeInt 32 0
58 %s32 = OpTypeInt 32 1
59 %f64 = OpTypeFloat 64
60 %u64 = OpTypeInt 64 0
61 %s64 = OpTypeInt 64 1
62 %boolvec2 = OpTypeVector %bool 2
63 %s32vec2 = OpTypeVector %s32 2
64 %u32vec2 = OpTypeVector %u32 2
65 %u64vec2 = OpTypeVector %u64 2
66 %f32vec2 = OpTypeVector %f32 2
67 %f64vec2 = OpTypeVector %f64 2
68 %boolvec3 = OpTypeVector %bool 3
69 %u32vec3 = OpTypeVector %u32 3
70 %u64vec3 = OpTypeVector %u64 3
71 %s32vec3 = OpTypeVector %s32 3
72 %f32vec3 = OpTypeVector %f32 3
73 %f64vec3 = OpTypeVector %f64 3
74 %boolvec4 = OpTypeVector %bool 4
75 %u32vec4 = OpTypeVector %u32 4
76 %u64vec4 = OpTypeVector %u64 4
77 %s32vec4 = OpTypeVector %s32 4
78 %f32vec4 = OpTypeVector %f32 4
79 %f64vec4 = OpTypeVector %f64 4
80
81 %f32_0 = OpConstant %f32 0
82 %f32_1 = OpConstant %f32 1
83 %f32_2 = OpConstant %f32 2
84 %f32_3 = OpConstant %f32 3
85 %f32_4 = OpConstant %f32 4
86
87 %s32_0 = OpConstant %s32 0
88 %s32_1 = OpConstant %s32 1
89 %s32_2 = OpConstant %s32 2
90 %s32_3 = OpConstant %s32 3
91 %s32_4 = OpConstant %s32 4
92 %s32_m1 = OpConstant %s32 -1
93
94 %u32_0 = OpConstant %u32 0
95 %u32_1 = OpConstant %u32 1
96 %u32_2 = OpConstant %u32 2
97 %u32_3 = OpConstant %u32 3
98 %u32_4 = OpConstant %u32 4
99
100 %f64_0 = OpConstant %f64 0
101 %f64_1 = OpConstant %f64 1
102 %f64_2 = OpConstant %f64 2
103 %f64_3 = OpConstant %f64 3
104 %f64_4 = OpConstant %f64 4
105
106 %s64_0 = OpConstant %s64 0
107 %s64_1 = OpConstant %s64 1
108 %s64_2 = OpConstant %s64 2
109 %s64_3 = OpConstant %s64 3
110 %s64_4 = OpConstant %s64 4
111 %s64_m1 = OpConstant %s64 -1
112
113 %u64_0 = OpConstant %u64 0
114 %u64_1 = OpConstant %u64 1
115 %u64_2 = OpConstant %u64 2
116 %u64_3 = OpConstant %u64 3
117 %u64_4 = OpConstant %u64 4
118
119 %u32vec2_01 = OpConstantComposite %u32vec2 %u32_0 %u32_1
120 %u32vec2_12 = OpConstantComposite %u32vec2 %u32_1 %u32_2
121 %u32vec3_012 = OpConstantComposite %u32vec3 %u32_0 %u32_1 %u32_2
122 %u32vec3_123 = OpConstantComposite %u32vec3 %u32_1 %u32_2 %u32_3
123 %u32vec4_0123 = OpConstantComposite %u32vec4 %u32_0 %u32_1 %u32_2 %u32_3
124 %u32vec4_1234 = OpConstantComposite %u32vec4 %u32_1 %u32_2 %u32_3 %u32_4
125
126 %s32vec2_01 = OpConstantComposite %s32vec2 %s32_0 %s32_1
127 %s32vec2_12 = OpConstantComposite %s32vec2 %s32_1 %s32_2
128 %s32vec3_012 = OpConstantComposite %s32vec3 %s32_0 %s32_1 %s32_2
129 %s32vec3_123 = OpConstantComposite %s32vec3 %s32_1 %s32_2 %s32_3
130 %s32vec4_0123 = OpConstantComposite %s32vec4 %s32_0 %s32_1 %s32_2 %s32_3
131 %s32vec4_1234 = OpConstantComposite %s32vec4 %s32_1 %s32_2 %s32_3 %s32_4
132
133 %f32vec2_01 = OpConstantComposite %f32vec2 %f32_0 %f32_1
134 %f32vec2_12 = OpConstantComposite %f32vec2 %f32_1 %f32_2
135 %f32vec3_012 = OpConstantComposite %f32vec3 %f32_0 %f32_1 %f32_2
136 %f32vec3_123 = OpConstantComposite %f32vec3 %f32_1 %f32_2 %f32_3
137 %f32vec4_0123 = OpConstantComposite %f32vec4 %f32_0 %f32_1 %f32_2 %f32_3
138 %f32vec4_1234 = OpConstantComposite %f32vec4 %f32_1 %f32_2 %f32_3 %f32_4
139
140 %f64vec2_01 = OpConstantComposite %f64vec2 %f64_0 %f64_1
141 %f64vec2_12 = OpConstantComposite %f64vec2 %f64_1 %f64_2
142 %f64vec3_012 = OpConstantComposite %f64vec3 %f64_0 %f64_1 %f64_2
143 %f64vec3_123 = OpConstantComposite %f64vec3 %f64_1 %f64_2 %f64_3
144 %f64vec4_0123 = OpConstantComposite %f64vec4 %f64_0 %f64_1 %f64_2 %f64_3
145 %f64vec4_1234 = OpConstantComposite %f64vec4 %f64_1 %f64_2 %f64_3 %f64_4
146
147 %true = OpConstantTrue %bool
148 %false = OpConstantFalse %bool
149
150 %f32ptr_func = OpTypePointer Function %f32)";
151
152 const std::string after_variables_before_body =
153 R"(
154 %main = OpFunction %void None %func
155 %main_entry = OpLabel)";
156
157 const std::string after_body =
158 R"(
159 OpReturn
160 OpFunctionEnd)";
161
162 return capabilities + capabilities_and_extensions +
163 after_extension_before_decorations + decorations +
164 after_decorations_before_types + types + variables +
165 after_variables_before_body + body + after_body;
166 }
167
GenerateKernelCode(const std::string & body,const std::string & capabilities_and_extensions="")168 std::string GenerateKernelCode(
169 const std::string& body,
170 const std::string& capabilities_and_extensions = "") {
171 const std::string capabilities =
172 R"(
173 OpCapability Addresses
174 OpCapability Kernel
175 OpCapability Linkage
176 OpCapability GenericPointer
177 OpCapability Int64
178 OpCapability Float64)";
179
180 const std::string after_extension_before_body =
181 R"(
182 OpMemoryModel Physical32 OpenCL
183 %void = OpTypeVoid
184 %func = OpTypeFunction %void
185 %bool = OpTypeBool
186 %f32 = OpTypeFloat 32
187 %u32 = OpTypeInt 32 0
188 %f64 = OpTypeFloat 64
189 %u64 = OpTypeInt 64 0
190 %boolvec2 = OpTypeVector %bool 2
191 %u32vec2 = OpTypeVector %u32 2
192 %u64vec2 = OpTypeVector %u64 2
193 %f32vec2 = OpTypeVector %f32 2
194 %f64vec2 = OpTypeVector %f64 2
195 %boolvec3 = OpTypeVector %bool 3
196 %u32vec3 = OpTypeVector %u32 3
197 %u64vec3 = OpTypeVector %u64 3
198 %f32vec3 = OpTypeVector %f32 3
199 %f64vec3 = OpTypeVector %f64 3
200 %boolvec4 = OpTypeVector %bool 4
201 %u32vec4 = OpTypeVector %u32 4
202 %u64vec4 = OpTypeVector %u64 4
203 %f32vec4 = OpTypeVector %f32 4
204 %f64vec4 = OpTypeVector %f64 4
205
206 %f32_0 = OpConstant %f32 0
207 %f32_1 = OpConstant %f32 1
208 %f32_2 = OpConstant %f32 2
209 %f32_3 = OpConstant %f32 3
210 %f32_4 = OpConstant %f32 4
211
212 %u32_0 = OpConstant %u32 0
213 %u32_1 = OpConstant %u32 1
214 %u32_2 = OpConstant %u32 2
215 %u32_3 = OpConstant %u32 3
216 %u32_4 = OpConstant %u32 4
217
218 %f64_0 = OpConstant %f64 0
219 %f64_1 = OpConstant %f64 1
220 %f64_2 = OpConstant %f64 2
221 %f64_3 = OpConstant %f64 3
222 %f64_4 = OpConstant %f64 4
223
224 %u64_0 = OpConstant %u64 0
225 %u64_1 = OpConstant %u64 1
226 %u64_2 = OpConstant %u64 2
227 %u64_3 = OpConstant %u64 3
228 %u64_4 = OpConstant %u64 4
229
230 %u32vec2_01 = OpConstantComposite %u32vec2 %u32_0 %u32_1
231 %u32vec2_12 = OpConstantComposite %u32vec2 %u32_1 %u32_2
232 %u32vec3_012 = OpConstantComposite %u32vec3 %u32_0 %u32_1 %u32_2
233 %u32vec3_123 = OpConstantComposite %u32vec3 %u32_1 %u32_2 %u32_3
234 %u32vec4_0123 = OpConstantComposite %u32vec4 %u32_0 %u32_1 %u32_2 %u32_3
235 %u32vec4_1234 = OpConstantComposite %u32vec4 %u32_1 %u32_2 %u32_3 %u32_4
236
237 %f32vec2_01 = OpConstantComposite %f32vec2 %f32_0 %f32_1
238 %f32vec2_12 = OpConstantComposite %f32vec2 %f32_1 %f32_2
239 %f32vec3_012 = OpConstantComposite %f32vec3 %f32_0 %f32_1 %f32_2
240 %f32vec3_123 = OpConstantComposite %f32vec3 %f32_1 %f32_2 %f32_3
241 %f32vec4_0123 = OpConstantComposite %f32vec4 %f32_0 %f32_1 %f32_2 %f32_3
242 %f32vec4_1234 = OpConstantComposite %f32vec4 %f32_1 %f32_2 %f32_3 %f32_4
243
244 %f64vec2_01 = OpConstantComposite %f64vec2 %f64_0 %f64_1
245 %f64vec2_12 = OpConstantComposite %f64vec2 %f64_1 %f64_2
246 %f64vec3_012 = OpConstantComposite %f64vec3 %f64_0 %f64_1 %f64_2
247 %f64vec3_123 = OpConstantComposite %f64vec3 %f64_1 %f64_2 %f64_3
248 %f64vec4_0123 = OpConstantComposite %f64vec4 %f64_0 %f64_1 %f64_2 %f64_3
249 %f64vec4_1234 = OpConstantComposite %f64vec4 %f64_1 %f64_2 %f64_3 %f64_4
250
251 %u64vec2_01 = OpConstantComposite %u64vec2 %u64_0 %u64_1
252
253 %true = OpConstantTrue %bool
254 %false = OpConstantFalse %bool
255
256 %f32ptr_func = OpTypePointer Function %f32
257 %u32ptr_func = OpTypePointer Function %u32
258 %f32ptr_gen = OpTypePointer Generic %f32
259 %f32ptr_inp = OpTypePointer Input %f32
260 %f32ptr_wg = OpTypePointer Workgroup %f32
261 %f32ptr_cwg = OpTypePointer CrossWorkgroup %f32
262
263 %f32inp = OpVariable %f32ptr_inp Input
264
265 %main = OpFunction %void None %func
266 %main_entry = OpLabel)";
267
268 const std::string after_body =
269 R"(
270 OpReturn
271 OpFunctionEnd)";
272
273 return capabilities + capabilities_and_extensions +
274 after_extension_before_body + body + after_body;
275 }
276
TEST_F(ValidateConversion,ConvertFToUSuccess)277 TEST_F(ValidateConversion, ConvertFToUSuccess) {
278 const std::string body = R"(
279 %val1 = OpConvertFToU %u32 %f32_1
280 %val2 = OpConvertFToU %u32 %f64_0
281 %val3 = OpConvertFToU %u32vec2 %f32vec2_01
282 )";
283
284 CompileSuccessfully(GenerateShaderCode(body).c_str());
285 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
286 }
287
TEST_F(ValidateConversion,ConvertFToUWrongResultType)288 TEST_F(ValidateConversion, ConvertFToUWrongResultType) {
289 const std::string body = R"(
290 %val = OpConvertFToU %s32 %f32_1
291 )";
292
293 CompileSuccessfully(GenerateShaderCode(body).c_str());
294 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
295 EXPECT_THAT(getDiagnosticString(),
296 HasSubstr("Expected unsigned int scalar or vector type as Result "
297 "Type: ConvertFToU"));
298 }
299
TEST_F(ValidateConversion,ConvertFToUWrongInputType)300 TEST_F(ValidateConversion, ConvertFToUWrongInputType) {
301 const std::string body = R"(
302 %val = OpConvertFToU %u32 %u32_1
303 )";
304
305 CompileSuccessfully(GenerateShaderCode(body).c_str());
306 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
307 EXPECT_THAT(
308 getDiagnosticString(),
309 HasSubstr("Expected input to be float scalar or vector: ConvertFToU"));
310 }
311
TEST_F(ValidateConversion,ConvertFToUDifferentDimension)312 TEST_F(ValidateConversion, ConvertFToUDifferentDimension) {
313 const std::string body = R"(
314 %val = OpConvertFToU %u32 %f32vec2_01
315 )";
316
317 CompileSuccessfully(GenerateShaderCode(body).c_str());
318 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
319 EXPECT_THAT(getDiagnosticString(),
320 HasSubstr("Expected input to have the same dimension as Result "
321 "Type: ConvertFToU"));
322 }
323
TEST_F(ValidateConversion,ConvertFToSSuccess)324 TEST_F(ValidateConversion, ConvertFToSSuccess) {
325 const std::string body = R"(
326 %val1 = OpConvertFToS %s32 %f32_1
327 %val2 = OpConvertFToS %u32 %f64_0
328 %val3 = OpConvertFToS %s32vec2 %f32vec2_01
329 )";
330
331 CompileSuccessfully(GenerateShaderCode(body).c_str());
332 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
333 }
334
TEST_F(ValidateConversion,ConvertFToSWrongResultType)335 TEST_F(ValidateConversion, ConvertFToSWrongResultType) {
336 const std::string body = R"(
337 %val = OpConvertFToS %bool %f32_1
338 )";
339
340 CompileSuccessfully(GenerateShaderCode(body).c_str());
341 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
342 EXPECT_THAT(
343 getDiagnosticString(),
344 HasSubstr(
345 "Expected int scalar or vector type as Result Type: ConvertFToS"));
346 }
347
TEST_F(ValidateConversion,ConvertFToSWrongInputType)348 TEST_F(ValidateConversion, ConvertFToSWrongInputType) {
349 const std::string body = R"(
350 %val = OpConvertFToS %s32 %u32_1
351 )";
352
353 CompileSuccessfully(GenerateShaderCode(body).c_str());
354 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
355 EXPECT_THAT(
356 getDiagnosticString(),
357 HasSubstr("Expected input to be float scalar or vector: ConvertFToS"));
358 }
359
TEST_F(ValidateConversion,ConvertFToSDifferentDimension)360 TEST_F(ValidateConversion, ConvertFToSDifferentDimension) {
361 const std::string body = R"(
362 %val = OpConvertFToS %u32 %f32vec2_01
363 )";
364
365 CompileSuccessfully(GenerateShaderCode(body).c_str());
366 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
367 EXPECT_THAT(getDiagnosticString(),
368 HasSubstr("Expected input to have the same dimension as Result "
369 "Type: ConvertFToS"));
370 }
371
TEST_F(ValidateConversion,ConvertSToFSuccess)372 TEST_F(ValidateConversion, ConvertSToFSuccess) {
373 const std::string body = R"(
374 %val1 = OpConvertSToF %f32 %u32_1
375 %val2 = OpConvertSToF %f32 %s64_0
376 %val3 = OpConvertSToF %f32vec2 %s32vec2_01
377 )";
378
379 CompileSuccessfully(GenerateShaderCode(body).c_str());
380 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
381 }
382
TEST_F(ValidateConversion,ConvertSToFWrongResultType)383 TEST_F(ValidateConversion, ConvertSToFWrongResultType) {
384 const std::string body = R"(
385 %val = OpConvertSToF %u32 %s32_1
386 )";
387
388 CompileSuccessfully(GenerateShaderCode(body).c_str());
389 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
390 EXPECT_THAT(
391 getDiagnosticString(),
392 HasSubstr(
393 "Expected float scalar or vector type as Result Type: ConvertSToF"));
394 }
395
TEST_F(ValidateConversion,ConvertSToFWrongInputType)396 TEST_F(ValidateConversion, ConvertSToFWrongInputType) {
397 const std::string body = R"(
398 %val = OpConvertSToF %f32 %f32_1
399 )";
400
401 CompileSuccessfully(GenerateShaderCode(body).c_str());
402 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
403 EXPECT_THAT(
404 getDiagnosticString(),
405 HasSubstr("Expected input to be int scalar or vector: ConvertSToF"));
406 }
407
TEST_F(ValidateConversion,ConvertSToFDifferentDimension)408 TEST_F(ValidateConversion, ConvertSToFDifferentDimension) {
409 const std::string body = R"(
410 %val = OpConvertSToF %f32 %u32vec2_01
411 )";
412
413 CompileSuccessfully(GenerateShaderCode(body).c_str());
414 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
415 EXPECT_THAT(getDiagnosticString(),
416 HasSubstr("Expected input to have the same dimension as Result "
417 "Type: ConvertSToF"));
418 }
419
TEST_F(ValidateConversion,UConvertSuccess)420 TEST_F(ValidateConversion, UConvertSuccess) {
421 const std::string body = R"(
422 %val1 = OpUConvert %u32 %u64_1
423 %val2 = OpUConvert %u64 %s32_0
424 %val3 = OpUConvert %u64vec2 %s32vec2_01
425 )";
426
427 CompileSuccessfully(GenerateShaderCode(body).c_str());
428 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
429 }
430
TEST_F(ValidateConversion,UConvertWrongResultType)431 TEST_F(ValidateConversion, UConvertWrongResultType) {
432 const std::string body = R"(
433 %val = OpUConvert %s32 %s32_1
434 )";
435
436 CompileSuccessfully(GenerateShaderCode(body).c_str());
437 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
438 EXPECT_THAT(getDiagnosticString(),
439 HasSubstr("Expected unsigned int scalar or vector type as Result "
440 "Type: UConvert"));
441 }
442
TEST_F(ValidateConversion,UConvertWrongInputType)443 TEST_F(ValidateConversion, UConvertWrongInputType) {
444 const std::string body = R"(
445 %val = OpUConvert %u32 %f32_1
446 )";
447
448 CompileSuccessfully(GenerateShaderCode(body).c_str());
449 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
450 EXPECT_THAT(getDiagnosticString(),
451 HasSubstr("Expected input to be int scalar or vector: UConvert"));
452 }
453
TEST_F(ValidateConversion,UConvertDifferentDimension)454 TEST_F(ValidateConversion, UConvertDifferentDimension) {
455 const std::string body = R"(
456 %val = OpUConvert %u32 %u32vec2_01
457 )";
458
459 CompileSuccessfully(GenerateShaderCode(body).c_str());
460 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
461 EXPECT_THAT(getDiagnosticString(),
462 HasSubstr("Expected input to have the same dimension as Result "
463 "Type: UConvert"));
464 }
465
TEST_F(ValidateConversion,UConvertSameBitWidth)466 TEST_F(ValidateConversion, UConvertSameBitWidth) {
467 const std::string body = R"(
468 %val = OpUConvert %u32 %s32_1
469 )";
470
471 CompileSuccessfully(GenerateShaderCode(body).c_str());
472 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
473 EXPECT_THAT(getDiagnosticString(),
474 HasSubstr("Expected input to have different bit width from "
475 "Result Type: UConvert"));
476 }
477
TEST_F(ValidateConversion,SConvertSuccess)478 TEST_F(ValidateConversion, SConvertSuccess) {
479 const std::string body = R"(
480 %val1 = OpSConvert %s32 %u64_1
481 %val2 = OpSConvert %s64 %s32_0
482 %val3 = OpSConvert %u64vec2 %s32vec2_01
483 )";
484
485 CompileSuccessfully(GenerateShaderCode(body).c_str());
486 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
487 }
488
TEST_F(ValidateConversion,SConvertWrongResultType)489 TEST_F(ValidateConversion, SConvertWrongResultType) {
490 const std::string body = R"(
491 %val = OpSConvert %f32 %s32_1
492 )";
493
494 CompileSuccessfully(GenerateShaderCode(body).c_str());
495 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
496 EXPECT_THAT(
497 getDiagnosticString(),
498 HasSubstr("Expected int scalar or vector type as Result Type: SConvert"));
499 }
500
TEST_F(ValidateConversion,SConvertWrongInputType)501 TEST_F(ValidateConversion, SConvertWrongInputType) {
502 const std::string body = R"(
503 %val = OpSConvert %u32 %f32_1
504 )";
505
506 CompileSuccessfully(GenerateShaderCode(body).c_str());
507 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
508 EXPECT_THAT(getDiagnosticString(),
509 HasSubstr("Expected input to be int scalar or vector: SConvert"));
510 }
511
TEST_F(ValidateConversion,SConvertDifferentDimension)512 TEST_F(ValidateConversion, SConvertDifferentDimension) {
513 const std::string body = R"(
514 %val = OpSConvert %s32 %u32vec2_01
515 )";
516
517 CompileSuccessfully(GenerateShaderCode(body).c_str());
518 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
519 EXPECT_THAT(getDiagnosticString(),
520 HasSubstr("Expected input to have the same dimension as Result "
521 "Type: SConvert"));
522 }
523
TEST_F(ValidateConversion,SConvertSameBitWidth)524 TEST_F(ValidateConversion, SConvertSameBitWidth) {
525 const std::string body = R"(
526 %val = OpSConvert %u32 %s32_1
527 )";
528
529 CompileSuccessfully(GenerateShaderCode(body).c_str());
530 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
531 EXPECT_THAT(getDiagnosticString(),
532 HasSubstr("Expected input to have different bit width from "
533 "Result Type: SConvert"));
534 }
535
TEST_F(ValidateConversion,FConvertSuccess)536 TEST_F(ValidateConversion, FConvertSuccess) {
537 const std::string body = R"(
538 %val1 = OpFConvert %f32 %f64_1
539 %val2 = OpFConvert %f64 %f32_0
540 %val3 = OpFConvert %f64vec2 %f32vec2_01
541 )";
542
543 CompileSuccessfully(GenerateShaderCode(body).c_str());
544 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
545 }
546
TEST_F(ValidateConversion,FConvertWrongResultType)547 TEST_F(ValidateConversion, FConvertWrongResultType) {
548 const std::string body = R"(
549 %val = OpFConvert %u32 %f32_1
550 )";
551
552 CompileSuccessfully(GenerateShaderCode(body).c_str());
553 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
554 EXPECT_THAT(
555 getDiagnosticString(),
556 HasSubstr(
557 "Expected float scalar or vector type as Result Type: FConvert"));
558 }
559
TEST_F(ValidateConversion,FConvertWrongInputType)560 TEST_F(ValidateConversion, FConvertWrongInputType) {
561 const std::string body = R"(
562 %val = OpFConvert %f32 %u64_1
563 )";
564
565 CompileSuccessfully(GenerateShaderCode(body).c_str());
566 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
567 EXPECT_THAT(
568 getDiagnosticString(),
569 HasSubstr("Expected input to be float scalar or vector: FConvert"));
570 }
571
TEST_F(ValidateConversion,FConvertDifferentDimension)572 TEST_F(ValidateConversion, FConvertDifferentDimension) {
573 const std::string body = R"(
574 %val = OpFConvert %f64 %f32vec2_01
575 )";
576
577 CompileSuccessfully(GenerateShaderCode(body).c_str());
578 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
579 EXPECT_THAT(getDiagnosticString(),
580 HasSubstr("Expected input to have the same dimension as Result "
581 "Type: FConvert"));
582 }
583
TEST_F(ValidateConversion,FConvertSameBitWidth)584 TEST_F(ValidateConversion, FConvertSameBitWidth) {
585 const std::string body = R"(
586 %val = OpFConvert %f32 %f32_1
587 )";
588
589 CompileSuccessfully(GenerateShaderCode(body).c_str());
590 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
591 EXPECT_THAT(getDiagnosticString(),
592 HasSubstr("Expected input to have different bit width from "
593 "Result Type: FConvert"));
594 }
595
TEST_F(ValidateConversion,QuantizeToF16Success)596 TEST_F(ValidateConversion, QuantizeToF16Success) {
597 const std::string body = R"(
598 %val1 = OpQuantizeToF16 %f32 %f32_1
599 %val2 = OpQuantizeToF16 %f32 %f32_0
600 %val3 = OpQuantizeToF16 %f32vec2 %f32vec2_01
601 )";
602
603 CompileSuccessfully(GenerateShaderCode(body).c_str());
604 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
605 }
606
TEST_F(ValidateConversion,QuantizeToF16WrongResultType)607 TEST_F(ValidateConversion, QuantizeToF16WrongResultType) {
608 const std::string body = R"(
609 %val = OpQuantizeToF16 %u32 %f32_1
610 )";
611
612 CompileSuccessfully(GenerateShaderCode(body).c_str());
613 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
614 EXPECT_THAT(
615 getDiagnosticString(),
616 HasSubstr("Expected 32-bit float scalar or vector type as Result Type: "
617 "QuantizeToF16"));
618 }
619
TEST_F(ValidateConversion,QuantizeToF16WrongResultTypeBitWidth)620 TEST_F(ValidateConversion, QuantizeToF16WrongResultTypeBitWidth) {
621 const std::string body = R"(
622 %val = OpQuantizeToF16 %u64 %f64_1
623 )";
624
625 CompileSuccessfully(GenerateShaderCode(body).c_str());
626 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
627 EXPECT_THAT(
628 getDiagnosticString(),
629 HasSubstr("Expected 32-bit float scalar or vector type as Result Type: "
630 "QuantizeToF16"));
631 }
632
TEST_F(ValidateConversion,QuantizeToF16WrongInputType)633 TEST_F(ValidateConversion, QuantizeToF16WrongInputType) {
634 const std::string body = R"(
635 %val = OpQuantizeToF16 %f32 %f64_1
636 )";
637
638 CompileSuccessfully(GenerateShaderCode(body).c_str());
639 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
640 EXPECT_THAT(
641 getDiagnosticString(),
642 HasSubstr(
643 "Expected input type to be equal to Result Type: QuantizeToF16"));
644 }
645
TEST_F(ValidateConversion,ConvertPtrToUSuccess)646 TEST_F(ValidateConversion, ConvertPtrToUSuccess) {
647 const std::string body = R"(
648 %ptr = OpVariable %f32ptr_func Function
649 %val1 = OpConvertPtrToU %u32 %ptr
650 %val2 = OpConvertPtrToU %u64 %ptr
651 )";
652
653 CompileSuccessfully(GenerateKernelCode(body).c_str());
654 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
655 }
656
TEST_F(ValidateConversion,ConvertPtrToUWrongResultType)657 TEST_F(ValidateConversion, ConvertPtrToUWrongResultType) {
658 const std::string body = R"(
659 %ptr = OpVariable %f32ptr_func Function
660 %val = OpConvertPtrToU %f32 %ptr
661 )";
662
663 CompileSuccessfully(GenerateKernelCode(body).c_str());
664 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
665 EXPECT_THAT(getDiagnosticString(),
666 HasSubstr("Expected unsigned int scalar type as Result Type: "
667 "ConvertPtrToU"));
668 }
669
TEST_F(ValidateConversion,ConvertPtrToUNotPointer)670 TEST_F(ValidateConversion, ConvertPtrToUNotPointer) {
671 const std::string body = R"(
672 %val = OpConvertPtrToU %u32 %f32_1
673 )";
674
675 CompileSuccessfully(GenerateKernelCode(body).c_str());
676 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
677 EXPECT_THAT(getDiagnosticString(),
678 HasSubstr("Expected input to be a pointer: ConvertPtrToU"));
679 }
680
TEST_F(ValidateConversion,SatConvertSToUSuccess)681 TEST_F(ValidateConversion, SatConvertSToUSuccess) {
682 const std::string body = R"(
683 %val1 = OpSatConvertSToU %u32 %u64_2
684 %val2 = OpSatConvertSToU %u64 %u32_1
685 %val3 = OpSatConvertSToU %u64vec2 %u32vec2_12
686 )";
687
688 CompileSuccessfully(GenerateKernelCode(body).c_str());
689 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
690 }
691
TEST_F(ValidateConversion,SatConvertSToUWrongResultType)692 TEST_F(ValidateConversion, SatConvertSToUWrongResultType) {
693 const std::string body = R"(
694 %val = OpSatConvertSToU %f32 %u32_1
695 )";
696
697 CompileSuccessfully(GenerateKernelCode(body).c_str());
698 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
699 EXPECT_THAT(getDiagnosticString(),
700 HasSubstr("Expected int scalar or vector type as Result Type: "
701 "SatConvertSToU"));
702 }
703
TEST_F(ValidateConversion,SatConvertSToUWrongInputType)704 TEST_F(ValidateConversion, SatConvertSToUWrongInputType) {
705 const std::string body = R"(
706 %val = OpSatConvertSToU %u32 %f32_1
707 )";
708
709 CompileSuccessfully(GenerateKernelCode(body).c_str());
710 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
711 EXPECT_THAT(
712 getDiagnosticString(),
713 HasSubstr("Expected int scalar or vector as input: SatConvertSToU"));
714 }
715
TEST_F(ValidateConversion,SatConvertSToUDifferentDimension)716 TEST_F(ValidateConversion, SatConvertSToUDifferentDimension) {
717 const std::string body = R"(
718 %val = OpSatConvertSToU %u32 %u32vec2_12
719 )";
720
721 CompileSuccessfully(GenerateKernelCode(body).c_str());
722 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
723 EXPECT_THAT(
724 getDiagnosticString(),
725 HasSubstr("Expected input to have the same dimension as Result Type: "
726 "SatConvertSToU"));
727 }
728
TEST_F(ValidateConversion,ConvertUToPtrSuccess)729 TEST_F(ValidateConversion, ConvertUToPtrSuccess) {
730 const std::string body = R"(
731 %val1 = OpConvertUToPtr %f32ptr_func %u32_1
732 %val2 = OpConvertUToPtr %f32ptr_func %u64_1
733 )";
734
735 CompileSuccessfully(GenerateKernelCode(body).c_str());
736 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
737 }
738
TEST_F(ValidateConversion,ConvertUToPtrWrongResultType)739 TEST_F(ValidateConversion, ConvertUToPtrWrongResultType) {
740 const std::string body = R"(
741 %val = OpConvertUToPtr %f32 %u32_1
742 )";
743
744 CompileSuccessfully(GenerateKernelCode(body).c_str());
745 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
746 EXPECT_THAT(getDiagnosticString(),
747 HasSubstr("Expected Result Type to be a pointer: ConvertUToPtr"));
748 }
749
TEST_F(ValidateConversion,ConvertUToPtrNotInt)750 TEST_F(ValidateConversion, ConvertUToPtrNotInt) {
751 const std::string body = R"(
752 %val = OpConvertUToPtr %f32ptr_func %f32_1
753 )";
754
755 CompileSuccessfully(GenerateKernelCode(body).c_str());
756 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
757 EXPECT_THAT(getDiagnosticString(),
758 HasSubstr("Expected int scalar as input: ConvertUToPtr"));
759 }
760
TEST_F(ValidateConversion,ConvertUToPtrNotIntScalar)761 TEST_F(ValidateConversion, ConvertUToPtrNotIntScalar) {
762 const std::string body = R"(
763 %val = OpConvertUToPtr %f32ptr_func %u32vec2_12
764 )";
765
766 CompileSuccessfully(GenerateKernelCode(body).c_str());
767 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
768 EXPECT_THAT(getDiagnosticString(),
769 HasSubstr("Expected int scalar as input: ConvertUToPtr"));
770 }
771
TEST_F(ValidateConversion,PtrCastToGenericSuccess)772 TEST_F(ValidateConversion, PtrCastToGenericSuccess) {
773 const std::string body = R"(
774 %ptr_func = OpVariable %f32ptr_func Function
775 %val = OpPtrCastToGeneric %f32ptr_gen %ptr_func
776 )";
777
778 CompileSuccessfully(GenerateKernelCode(body).c_str());
779 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
780 }
781
TEST_F(ValidateConversion,PtrCastToGenericWrongResultType)782 TEST_F(ValidateConversion, PtrCastToGenericWrongResultType) {
783 const std::string body = R"(
784 %ptr_func = OpVariable %f32ptr_func Function
785 %val = OpPtrCastToGeneric %f32 %ptr_func
786 )";
787
788 CompileSuccessfully(GenerateKernelCode(body).c_str());
789 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
790 EXPECT_THAT(
791 getDiagnosticString(),
792 HasSubstr("Expected Result Type to be a pointer: PtrCastToGeneric"));
793 }
794
TEST_F(ValidateConversion,PtrCastToGenericWrongResultStorageClass)795 TEST_F(ValidateConversion, PtrCastToGenericWrongResultStorageClass) {
796 const std::string body = R"(
797 %ptr_func = OpVariable %f32ptr_func Function
798 %val = OpPtrCastToGeneric %f32ptr_func %ptr_func
799 )";
800
801 CompileSuccessfully(GenerateKernelCode(body).c_str());
802 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
803 EXPECT_THAT(getDiagnosticString(),
804 HasSubstr("Expected Result Type to have storage class Generic: "
805 "PtrCastToGeneric"));
806 }
807
TEST_F(ValidateConversion,PtrCastToGenericWrongInputType)808 TEST_F(ValidateConversion, PtrCastToGenericWrongInputType) {
809 const std::string body = R"(
810 %ptr_func = OpVariable %f32ptr_func Function
811 %val = OpPtrCastToGeneric %f32ptr_gen %f32
812 )";
813
814 CompileSuccessfully(GenerateKernelCode(body).c_str());
815 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
816 EXPECT_THAT(getDiagnosticString(),
817 HasSubstr("Operand '4[%float]' cannot be a "
818 "type"));
819 }
820
TEST_F(ValidateConversion,PtrCastToGenericWrongInputStorageClass)821 TEST_F(ValidateConversion, PtrCastToGenericWrongInputStorageClass) {
822 const std::string body = R"(
823 %val = OpPtrCastToGeneric %f32ptr_gen %f32inp
824 )";
825
826 CompileSuccessfully(GenerateKernelCode(body).c_str());
827 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
828 EXPECT_THAT(getDiagnosticString(),
829 HasSubstr("Expected input to have storage class Workgroup, "
830 "CrossWorkgroup or Function: PtrCastToGeneric"));
831 }
832
TEST_F(ValidateConversion,PtrCastToGenericPointToDifferentType)833 TEST_F(ValidateConversion, PtrCastToGenericPointToDifferentType) {
834 const std::string body = R"(
835 %ptr_func = OpVariable %u32ptr_func Function
836 %val = OpPtrCastToGeneric %f32ptr_gen %ptr_func
837 )";
838
839 CompileSuccessfully(GenerateKernelCode(body).c_str());
840 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
841 EXPECT_THAT(
842 getDiagnosticString(),
843 HasSubstr("Expected input and Result Type to point to the same type: "
844 "PtrCastToGeneric"));
845 }
846
TEST_F(ValidateConversion,GenericCastToPtrSuccess)847 TEST_F(ValidateConversion, GenericCastToPtrSuccess) {
848 const std::string body = R"(
849 %ptr_func = OpVariable %f32ptr_func Function
850 %ptr_gen = OpPtrCastToGeneric %f32ptr_gen %ptr_func
851 %ptr_func2 = OpGenericCastToPtr %f32ptr_func %ptr_gen
852 %ptr_wg = OpGenericCastToPtr %f32ptr_wg %ptr_gen
853 %ptr_cwg = OpGenericCastToPtr %f32ptr_cwg %ptr_gen
854 )";
855
856 CompileSuccessfully(GenerateKernelCode(body).c_str());
857 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
858 }
859
TEST_F(ValidateConversion,GenericCastToPtrWrongResultType)860 TEST_F(ValidateConversion, GenericCastToPtrWrongResultType) {
861 const std::string body = R"(
862 %ptr_func = OpVariable %f32ptr_func Function
863 %ptr_gen = OpPtrCastToGeneric %f32ptr_gen %ptr_func
864 %ptr_func2 = OpGenericCastToPtr %f32 %ptr_gen
865 )";
866
867 CompileSuccessfully(GenerateKernelCode(body).c_str());
868 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
869 EXPECT_THAT(
870 getDiagnosticString(),
871 HasSubstr("Expected Result Type to be a pointer: GenericCastToPtr"));
872 }
873
TEST_F(ValidateConversion,GenericCastToPtrWrongResultStorageClass)874 TEST_F(ValidateConversion, GenericCastToPtrWrongResultStorageClass) {
875 const std::string body = R"(
876 %ptr_func = OpVariable %f32ptr_func Function
877 %ptr_gen = OpPtrCastToGeneric %f32ptr_gen %ptr_func
878 %ptr_func2 = OpGenericCastToPtr %f32ptr_gen %ptr_gen
879 )";
880
881 CompileSuccessfully(GenerateKernelCode(body).c_str());
882 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
883 EXPECT_THAT(getDiagnosticString(),
884 HasSubstr("Expected Result Type to have storage class Workgroup, "
885 "CrossWorkgroup or Function: GenericCastToPtr"));
886 }
887
TEST_F(ValidateConversion,GenericCastToPtrWrongInputType)888 TEST_F(ValidateConversion, GenericCastToPtrWrongInputType) {
889 const std::string body = R"(
890 %ptr_func = OpVariable %f32ptr_func Function
891 %ptr_gen = OpPtrCastToGeneric %f32ptr_gen %ptr_func
892 %ptr_func2 = OpGenericCastToPtr %f32ptr_func %f32_1
893 )";
894
895 CompileSuccessfully(GenerateKernelCode(body).c_str());
896 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
897 EXPECT_THAT(getDiagnosticString(),
898 HasSubstr("Expected input to be a pointer: GenericCastToPtr"));
899 }
900
TEST_F(ValidateConversion,GenericCastToPtrWrongInputStorageClass)901 TEST_F(ValidateConversion, GenericCastToPtrWrongInputStorageClass) {
902 const std::string body = R"(
903 %ptr_func = OpVariable %f32ptr_func Function
904 %ptr_func2 = OpGenericCastToPtr %f32ptr_func %ptr_func
905 )";
906
907 CompileSuccessfully(GenerateKernelCode(body).c_str());
908 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
909 EXPECT_THAT(getDiagnosticString(),
910 HasSubstr("Expected input to have storage class Generic: "
911 "GenericCastToPtr"));
912 }
913
TEST_F(ValidateConversion,GenericCastToPtrPointToDifferentType)914 TEST_F(ValidateConversion, GenericCastToPtrPointToDifferentType) {
915 const std::string body = R"(
916 %ptr_func = OpVariable %f32ptr_func Function
917 %ptr_gen = OpPtrCastToGeneric %f32ptr_gen %ptr_func
918 %ptr_func2 = OpGenericCastToPtr %u32ptr_func %ptr_gen
919 )";
920
921 CompileSuccessfully(GenerateKernelCode(body).c_str());
922 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
923 EXPECT_THAT(
924 getDiagnosticString(),
925 HasSubstr("Expected input and Result Type to point to the same type: "
926 "GenericCastToPtr"));
927 }
928
TEST_F(ValidateConversion,GenericCastToPtrExplicitSuccess)929 TEST_F(ValidateConversion, GenericCastToPtrExplicitSuccess) {
930 const std::string body = R"(
931 %ptr_func = OpVariable %f32ptr_func Function
932 %ptr_gen = OpPtrCastToGeneric %f32ptr_gen %ptr_func
933 %ptr_func2 = OpGenericCastToPtrExplicit %f32ptr_func %ptr_gen Function
934 %ptr_wg = OpGenericCastToPtrExplicit %f32ptr_wg %ptr_gen Workgroup
935 %ptr_cwg = OpGenericCastToPtrExplicit %f32ptr_cwg %ptr_gen CrossWorkgroup
936 )";
937
938 CompileSuccessfully(GenerateKernelCode(body).c_str());
939 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
940 }
941
TEST_F(ValidateConversion,GenericCastToPtrExplicitWrongResultType)942 TEST_F(ValidateConversion, GenericCastToPtrExplicitWrongResultType) {
943 const std::string body = R"(
944 %ptr_func = OpVariable %f32ptr_func Function
945 %ptr_gen = OpPtrCastToGeneric %f32ptr_gen %ptr_func
946 %ptr_func2 = OpGenericCastToPtrExplicit %f32 %ptr_gen Function
947 )";
948
949 CompileSuccessfully(GenerateKernelCode(body).c_str());
950 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
951 EXPECT_THAT(
952 getDiagnosticString(),
953 HasSubstr(
954 "Expected Result Type to be a pointer: GenericCastToPtrExplicit"));
955 }
956
TEST_F(ValidateConversion,GenericCastToPtrExplicitResultStorageClassDiffers)957 TEST_F(ValidateConversion, GenericCastToPtrExplicitResultStorageClassDiffers) {
958 const std::string body = R"(
959 %ptr_func = OpVariable %f32ptr_func Function
960 %ptr_gen = OpPtrCastToGeneric %f32ptr_gen %ptr_func
961 %ptr_func2 = OpGenericCastToPtrExplicit %f32ptr_func %ptr_gen Workgroup
962 )";
963
964 CompileSuccessfully(GenerateKernelCode(body).c_str());
965 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
966 EXPECT_THAT(getDiagnosticString(),
967 HasSubstr("Expected Result Type to be of target storage class: "
968 "GenericCastToPtrExplicit"));
969 }
970
TEST_F(ValidateConversion,GenericCastToPtrExplicitWrongResultStorageClass)971 TEST_F(ValidateConversion, GenericCastToPtrExplicitWrongResultStorageClass) {
972 const std::string body = R"(
973 %ptr_func = OpVariable %f32ptr_func Function
974 %ptr_gen = OpPtrCastToGeneric %f32ptr_gen %ptr_func
975 %ptr_func2 = OpGenericCastToPtrExplicit %f32ptr_gen %ptr_gen Generic
976 )";
977
978 CompileSuccessfully(GenerateKernelCode(body).c_str());
979 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
980 EXPECT_THAT(
981 getDiagnosticString(),
982 HasSubstr("Expected target storage class to be Workgroup, "
983 "CrossWorkgroup or Function: GenericCastToPtrExplicit"));
984 }
985
TEST_F(ValidateConversion,GenericCastToPtrExplicitWrongInputType)986 TEST_F(ValidateConversion, GenericCastToPtrExplicitWrongInputType) {
987 const std::string body = R"(
988 %ptr_func = OpVariable %f32ptr_func Function
989 %ptr_gen = OpPtrCastToGeneric %f32ptr_gen %ptr_func
990 %ptr_func2 = OpGenericCastToPtrExplicit %f32ptr_func %f32_1 Function
991 )";
992
993 CompileSuccessfully(GenerateKernelCode(body).c_str());
994 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
995 EXPECT_THAT(
996 getDiagnosticString(),
997 HasSubstr("Expected input to be a pointer: GenericCastToPtrExplicit"));
998 }
999
TEST_F(ValidateConversion,GenericCastToPtrExplicitWrongInputStorageClass)1000 TEST_F(ValidateConversion, GenericCastToPtrExplicitWrongInputStorageClass) {
1001 const std::string body = R"(
1002 %ptr_func = OpVariable %f32ptr_func Function
1003 %ptr_func2 = OpGenericCastToPtrExplicit %f32ptr_func %ptr_func Function
1004 )";
1005
1006 CompileSuccessfully(GenerateKernelCode(body).c_str());
1007 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1008 EXPECT_THAT(getDiagnosticString(),
1009 HasSubstr("Expected input to have storage class Generic: "
1010 "GenericCastToPtrExplicit"));
1011 }
1012
TEST_F(ValidateConversion,GenericCastToPtrExplicitPointToDifferentType)1013 TEST_F(ValidateConversion, GenericCastToPtrExplicitPointToDifferentType) {
1014 const std::string body = R"(
1015 %ptr_func = OpVariable %f32ptr_func Function
1016 %ptr_gen = OpPtrCastToGeneric %f32ptr_gen %ptr_func
1017 %ptr_func2 = OpGenericCastToPtrExplicit %u32ptr_func %ptr_gen Function
1018 )";
1019
1020 CompileSuccessfully(GenerateKernelCode(body).c_str());
1021 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1022 EXPECT_THAT(
1023 getDiagnosticString(),
1024 HasSubstr("Expected input and Result Type to point to the same type: "
1025 "GenericCastToPtrExplicit"));
1026 }
1027
TEST_F(ValidateConversion,CoopMatConversionSuccess)1028 TEST_F(ValidateConversion, CoopMatConversionSuccess) {
1029 const std::string body =
1030 R"(
1031 OpCapability Shader
1032 OpCapability Float16
1033 OpCapability Int16
1034 OpCapability CooperativeMatrixNV
1035 OpExtension "SPV_NV_cooperative_matrix"
1036 OpMemoryModel Logical GLSL450
1037 OpEntryPoint GLCompute %main "main"
1038 %void = OpTypeVoid
1039 %func = OpTypeFunction %void
1040 %bool = OpTypeBool
1041 %f16 = OpTypeFloat 16
1042 %f32 = OpTypeFloat 32
1043 %u16 = OpTypeInt 16 0
1044 %u32 = OpTypeInt 32 0
1045 %s16 = OpTypeInt 16 1
1046 %s32 = OpTypeInt 32 1
1047
1048 %u32_8 = OpConstant %u32 8
1049 %subgroup = OpConstant %u32 3
1050
1051 %f16mat = OpTypeCooperativeMatrixNV %f16 %subgroup %u32_8 %u32_8
1052 %f32mat = OpTypeCooperativeMatrixNV %f32 %subgroup %u32_8 %u32_8
1053 %u16mat = OpTypeCooperativeMatrixNV %u16 %subgroup %u32_8 %u32_8
1054 %u32mat = OpTypeCooperativeMatrixNV %u32 %subgroup %u32_8 %u32_8
1055 %s16mat = OpTypeCooperativeMatrixNV %s16 %subgroup %u32_8 %u32_8
1056 %s32mat = OpTypeCooperativeMatrixNV %s32 %subgroup %u32_8 %u32_8
1057
1058 %f16_1 = OpConstant %f16 1
1059 %f32_1 = OpConstant %f32 1
1060 %u16_1 = OpConstant %u16 1
1061 %u32_1 = OpConstant %u32 1
1062 %s16_1 = OpConstant %s16 1
1063 %s32_1 = OpConstant %s32 1
1064
1065 %f16mat_1 = OpConstantComposite %f16mat %f16_1
1066 %f32mat_1 = OpConstantComposite %f32mat %f32_1
1067 %u16mat_1 = OpConstantComposite %u16mat %u16_1
1068 %u32mat_1 = OpConstantComposite %u32mat %u32_1
1069 %s16mat_1 = OpConstantComposite %s16mat %s16_1
1070 %s32mat_1 = OpConstantComposite %s32mat %s32_1
1071
1072 %main = OpFunction %void None %func
1073 %main_entry = OpLabel
1074
1075 %val11 = OpConvertFToU %u16mat %f16mat_1
1076 %val12 = OpConvertFToU %u32mat %f16mat_1
1077 %val13 = OpConvertFToS %s16mat %f16mat_1
1078 %val14 = OpConvertFToS %s32mat %f16mat_1
1079 %val15 = OpFConvert %f32mat %f16mat_1
1080
1081 %val21 = OpConvertFToU %u16mat %f32mat_1
1082 %val22 = OpConvertFToU %u32mat %f32mat_1
1083 %val23 = OpConvertFToS %s16mat %f32mat_1
1084 %val24 = OpConvertFToS %s32mat %f32mat_1
1085 %val25 = OpFConvert %f16mat %f32mat_1
1086
1087 %val31 = OpConvertUToF %f16mat %u16mat_1
1088 %val32 = OpConvertUToF %f32mat %u16mat_1
1089 %val33 = OpUConvert %u32mat %u16mat_1
1090 %val34 = OpSConvert %s32mat %u16mat_1
1091
1092 %val41 = OpConvertSToF %f16mat %s16mat_1
1093 %val42 = OpConvertSToF %f32mat %s16mat_1
1094 %val43 = OpUConvert %u32mat %s16mat_1
1095 %val44 = OpSConvert %s32mat %s16mat_1
1096
1097 OpReturn
1098 OpFunctionEnd)";
1099
1100 CompileSuccessfully(body.c_str());
1101 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1102 }
1103
TEST_F(ValidateConversion,CoopMatConversionShapesMismatchFail)1104 TEST_F(ValidateConversion, CoopMatConversionShapesMismatchFail) {
1105 const std::string body =
1106 R"(
1107 OpCapability Shader
1108 OpCapability Float16
1109 OpCapability Int16
1110 OpCapability CooperativeMatrixNV
1111 OpExtension "SPV_NV_cooperative_matrix"
1112 OpMemoryModel Logical GLSL450
1113 OpEntryPoint GLCompute %main "main"
1114 %void = OpTypeVoid
1115 %func = OpTypeFunction %void
1116 %bool = OpTypeBool
1117 %f16 = OpTypeFloat 16
1118 %f32 = OpTypeFloat 32
1119 %u16 = OpTypeInt 16 0
1120 %u32 = OpTypeInt 32 0
1121 %s16 = OpTypeInt 16 1
1122 %s32 = OpTypeInt 32 1
1123
1124 %u32_8 = OpConstant %u32 8
1125 %u32_4 = OpConstant %u32 4
1126 %subgroup = OpConstant %u32 3
1127
1128 %f16mat = OpTypeCooperativeMatrixNV %f16 %subgroup %u32_8 %u32_8
1129 %f32mat = OpTypeCooperativeMatrixNV %f32 %subgroup %u32_4 %u32_4
1130
1131 %f16_1 = OpConstant %f16 1
1132
1133 %f16mat_1 = OpConstantComposite %f16mat %f16_1
1134
1135 %main = OpFunction %void None %func
1136 %main_entry = OpLabel
1137
1138 %val15 = OpFConvert %f32mat %f16mat_1
1139
1140 OpReturn
1141 OpFunctionEnd)";
1142
1143 CompileSuccessfully(body.c_str());
1144 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1145 EXPECT_THAT(
1146 getDiagnosticString(),
1147 HasSubstr(
1148 "Expected rows of Matrix type and Result Type to be identical"));
1149 }
1150
TEST_F(ValidateConversion,CoopMatConversionShapesMismatchPass)1151 TEST_F(ValidateConversion, CoopMatConversionShapesMismatchPass) {
1152 const std::string body =
1153 R"(
1154 OpCapability Shader
1155 OpCapability Float16
1156 OpCapability Int16
1157 OpCapability CooperativeMatrixNV
1158 OpExtension "SPV_NV_cooperative_matrix"
1159 OpMemoryModel Logical GLSL450
1160 OpEntryPoint GLCompute %main "main"
1161 %void = OpTypeVoid
1162 %func = OpTypeFunction %void
1163 %bool = OpTypeBool
1164 %f16 = OpTypeFloat 16
1165 %f32 = OpTypeFloat 32
1166 %u16 = OpTypeInt 16 0
1167 %u32 = OpTypeInt 32 0
1168 %s16 = OpTypeInt 16 1
1169 %s32 = OpTypeInt 32 1
1170
1171 %u32_8 = OpConstant %u32 8
1172 %u32_4 = OpSpecConstant %u32 4
1173 %subgroup = OpConstant %u32 3
1174
1175 %f16mat = OpTypeCooperativeMatrixNV %f16 %subgroup %u32_8 %u32_8
1176 %f32mat = OpTypeCooperativeMatrixNV %f32 %subgroup %u32_4 %u32_4
1177
1178 %f16_1 = OpConstant %f16 1
1179
1180 %f16mat_1 = OpConstantComposite %f16mat %f16_1
1181
1182 %main = OpFunction %void None %func
1183 %main_entry = OpLabel
1184
1185 %val15 = OpFConvert %f32mat %f16mat_1
1186
1187 OpReturn
1188 OpFunctionEnd)";
1189
1190 CompileSuccessfully(body.c_str());
1191 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1192 }
1193
TEST_F(ValidateConversion,BitcastSuccess)1194 TEST_F(ValidateConversion, BitcastSuccess) {
1195 const std::string body = R"(
1196 %ptr = OpVariable %f32ptr_func Function
1197 %val1 = OpBitcast %u32 %ptr
1198 %val2 = OpBitcast %u64 %ptr
1199 %val3 = OpBitcast %f32ptr_func %u32_1
1200 %val4 = OpBitcast %f32ptr_wg %u64_1
1201 %val5 = OpBitcast %f32 %u32_1
1202 %val6 = OpBitcast %f32vec2 %u32vec2_12
1203 %val7 = OpBitcast %f32vec2 %u64_1
1204 %val8 = OpBitcast %f64 %u32vec2_12
1205 %val9 = OpBitcast %f32vec4 %f64vec2_12
1206 )";
1207
1208 CompileSuccessfully(GenerateKernelCode(body).c_str());
1209 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1210 }
1211
TEST_F(ValidateConversion,BitcastSuccessSPV1p5)1212 TEST_F(ValidateConversion, BitcastSuccessSPV1p5) {
1213 const std::string body = R"(
1214 %ptr = OpVariable %f32ptr_func Function
1215 %val1 = OpBitcast %u32 %ptr
1216 %val2 = OpBitcast %u64 %ptr
1217 %val3 = OpBitcast %f32ptr_func %u32_1
1218 %val4 = OpBitcast %f32ptr_wg %u64_1
1219 %val5 = OpBitcast %f32 %u32_1
1220 %val6 = OpBitcast %f32vec2 %u32vec2_12
1221 %val7 = OpBitcast %f32vec2 %u64_1
1222 %val8 = OpBitcast %f64 %u32vec2_12
1223 %val9 = OpBitcast %f32vec4 %f64vec2_12
1224 %val10 = OpBitcast %u32ptr_func %u32vec2_01
1225 %val11 = OpBitcast %u32vec2 %ptr
1226 )";
1227
1228 CompileSuccessfully(GenerateKernelCode(body).c_str(), SPV_ENV_UNIVERSAL_1_5);
1229 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
1230 }
1231
TEST_F(ValidateConversion,BitcastSuccessPhysicalStorageBufferKHR)1232 TEST_F(ValidateConversion, BitcastSuccessPhysicalStorageBufferKHR) {
1233 const std::string body = R"(
1234 %ptr = OpVariable %f32ptr_func Function
1235 %val1 = OpBitcast %u32 %ptr
1236 %val2 = OpBitcast %u64 %ptr
1237 %val3 = OpBitcast %f32ptr_func %u32_1
1238 %val4 = OpBitcast %f32ptr_wg %u64_1
1239 %val5 = OpBitcast %f32 %u32_1
1240 %val6 = OpBitcast %f32vec2 %u32vec2_12
1241 %val7 = OpBitcast %f32vec2 %u64_1
1242 %val8 = OpBitcast %f64 %u32vec2_12
1243 %val9 = OpBitcast %f32vec4 %f64vec2_12
1244 %val10 = OpBitcast %u32ptr_func %u32vec2_01
1245 %val11 = OpBitcast %u32vec2 %ptr
1246 )";
1247
1248 CompileSuccessfully(
1249 GenerateKernelCode(body,
1250 "\nOpExtension \"SPV_KHR_physical_storage_buffer\"")
1251 .c_str());
1252 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1253 }
1254
TEST_F(ValidateConversion,BitcastInputHasNoType)1255 TEST_F(ValidateConversion, BitcastInputHasNoType) {
1256 const std::string body = R"(
1257 %val = OpBitcast %u32 %f32
1258 )";
1259
1260 CompileSuccessfully(GenerateKernelCode(body).c_str());
1261 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1262 EXPECT_THAT(getDiagnosticString(),
1263 HasSubstr("Operand '4[%float]' cannot be a "
1264 "type"));
1265 }
1266
TEST_F(ValidateConversion,BitcastWrongResultType)1267 TEST_F(ValidateConversion, BitcastWrongResultType) {
1268 const std::string body = R"(
1269 %val = OpBitcast %bool %f32_1
1270 )";
1271
1272 CompileSuccessfully(GenerateKernelCode(body).c_str());
1273 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1274 EXPECT_THAT(
1275 getDiagnosticString(),
1276 HasSubstr("Expected Result Type to be a pointer or int or float vector "
1277 "or scalar type: Bitcast"));
1278 }
1279
TEST_F(ValidateConversion,BitcastWrongInputType)1280 TEST_F(ValidateConversion, BitcastWrongInputType) {
1281 const std::string body = R"(
1282 %val = OpBitcast %u32 %true
1283 )";
1284
1285 CompileSuccessfully(GenerateKernelCode(body).c_str());
1286 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1287 EXPECT_THAT(getDiagnosticString(),
1288 HasSubstr("Expected input to be a pointer or int or float vector "
1289 "or scalar: Bitcast"));
1290 }
1291
TEST_F(ValidateConversion,BitcastPtrWrongInputType)1292 TEST_F(ValidateConversion, BitcastPtrWrongInputType) {
1293 const std::string body = R"(
1294 %val = OpBitcast %u32ptr_func %f32_1
1295 )";
1296
1297 CompileSuccessfully(GenerateKernelCode(body).c_str());
1298 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1299 EXPECT_THAT(getDiagnosticString(),
1300 HasSubstr("Expected input to be a pointer or int scalar if "
1301 "Result Type is pointer: Bitcast"));
1302 }
1303
TEST_F(ValidateConversion,BitcastPtrWrongInputTypeSPV1p5)1304 TEST_F(ValidateConversion, BitcastPtrWrongInputTypeSPV1p5) {
1305 const std::string body = R"(
1306 %val = OpBitcast %u32ptr_func %f32_1
1307 )";
1308
1309 CompileSuccessfully(GenerateKernelCode(body).c_str(), SPV_ENV_UNIVERSAL_1_5);
1310 ASSERT_EQ(SPV_ERROR_INVALID_DATA,
1311 ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
1312 EXPECT_THAT(getDiagnosticString(),
1313 HasSubstr("Expected input to be a pointer, int scalar or 32-bit "
1314 "int vector if Result Type is pointer: Bitcast"));
1315 }
1316
TEST_F(ValidateConversion,BitcastPtrWrongInputTypePhysicalStorageBufferKHR)1317 TEST_F(ValidateConversion, BitcastPtrWrongInputTypePhysicalStorageBufferKHR) {
1318 const std::string body = R"(
1319 %val = OpBitcast %u32ptr_func %f32_1
1320 )";
1321
1322 CompileSuccessfully(
1323 GenerateKernelCode(body,
1324 "\nOpExtension \"SPV_KHR_physical_storage_buffer\"")
1325 .c_str());
1326 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1327 EXPECT_THAT(getDiagnosticString(),
1328 HasSubstr("Expected input to be a pointer, int scalar or 32-bit "
1329 "int vector if Result Type is pointer: Bitcast"));
1330 }
1331
TEST_F(ValidateConversion,BitcastPtrWrongInputTypeIntVectorSPV1p5)1332 TEST_F(ValidateConversion, BitcastPtrWrongInputTypeIntVectorSPV1p5) {
1333 const std::string body = R"(
1334 %val = OpBitcast %u32ptr_func %u64vec2_01
1335 )";
1336
1337 CompileSuccessfully(GenerateKernelCode(body).c_str(), SPV_ENV_UNIVERSAL_1_5);
1338 ASSERT_EQ(SPV_ERROR_INVALID_DATA,
1339 ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
1340 EXPECT_THAT(getDiagnosticString(),
1341 HasSubstr("Expected input to be a pointer, int scalar or 32-bit "
1342 "int vector if Result Type is pointer: Bitcast"));
1343 }
1344
TEST_F(ValidateConversion,BitcastPtrWrongInputTypeIntVectorPhysicalStorageBufferKHR)1345 TEST_F(ValidateConversion,
1346 BitcastPtrWrongInputTypeIntVectorPhysicalStorageBufferKHR) {
1347 const std::string body = R"(
1348 %val = OpBitcast %u32ptr_func %u64vec2_01
1349 )";
1350
1351 CompileSuccessfully(
1352 GenerateKernelCode(body,
1353 "\nOpExtension \"SPV_KHR_physical_storage_buffer\"")
1354 .c_str());
1355 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1356 EXPECT_THAT(getDiagnosticString(),
1357 HasSubstr("Expected input to be a pointer, int scalar or 32-bit "
1358 "int vector if Result Type is pointer: Bitcast"));
1359 }
1360
TEST_F(ValidateConversion,BitcastPtrWrongResultType)1361 TEST_F(ValidateConversion, BitcastPtrWrongResultType) {
1362 const std::string body = R"(
1363 %val = OpBitcast %f32 %f32inp
1364 )";
1365
1366 CompileSuccessfully(GenerateKernelCode(body).c_str());
1367 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1368 EXPECT_THAT(getDiagnosticString(),
1369 HasSubstr("Pointer can only be converted to another pointer or "
1370 "int scalar: Bitcast"));
1371 }
1372
TEST_F(ValidateConversion,BitcastPtrWrongResultTypeSPV1p5)1373 TEST_F(ValidateConversion, BitcastPtrWrongResultTypeSPV1p5) {
1374 const std::string body = R"(
1375 %val = OpBitcast %f32 %f32inp
1376 )";
1377
1378 CompileSuccessfully(GenerateKernelCode(body).c_str(), SPV_ENV_UNIVERSAL_1_5);
1379 ASSERT_EQ(SPV_ERROR_INVALID_DATA,
1380 ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
1381 EXPECT_THAT(getDiagnosticString(),
1382 HasSubstr("Pointer can only be converted to another pointer, int "
1383 "scalar or 32-bit int vector: Bitcast"));
1384 }
1385
TEST_F(ValidateConversion,BitcastPtrWrongResultTypePhysicalStorageBufferKHR)1386 TEST_F(ValidateConversion, BitcastPtrWrongResultTypePhysicalStorageBufferKHR) {
1387 const std::string body = R"(
1388 %val = OpBitcast %f32 %f32inp
1389 )";
1390
1391 CompileSuccessfully(
1392 GenerateKernelCode(body,
1393 "\nOpExtension \"SPV_KHR_physical_storage_buffer\"")
1394 .c_str());
1395 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1396 EXPECT_THAT(getDiagnosticString(),
1397 HasSubstr("Pointer can only be converted to another pointer, int "
1398 "scalar or 32-bit int vector: Bitcast"));
1399 }
1400
TEST_F(ValidateConversion,BitcastPtrWrongResultTypeIntVectorSPV1p5)1401 TEST_F(ValidateConversion, BitcastPtrWrongResultTypeIntVectorSPV1p5) {
1402 const std::string body = R"(
1403 %val = OpBitcast %u64vec2 %f32inp
1404 )";
1405
1406 CompileSuccessfully(GenerateKernelCode(body).c_str(), SPV_ENV_UNIVERSAL_1_5);
1407 ASSERT_EQ(SPV_ERROR_INVALID_DATA,
1408 ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
1409 EXPECT_THAT(getDiagnosticString(),
1410 HasSubstr("Pointer can only be converted to another pointer, int "
1411 "scalar or 32-bit int vector: Bitcast"));
1412 }
1413
TEST_F(ValidateConversion,BitcastPtrWrongResultTypeIntVectorPhysicalStorageBufferKHR)1414 TEST_F(ValidateConversion,
1415 BitcastPtrWrongResultTypeIntVectorPhysicalStorageBufferKHR) {
1416 const std::string body = R"(
1417 %val = OpBitcast %u64vec2 %f32inp
1418 )";
1419
1420 CompileSuccessfully(
1421 GenerateKernelCode(body,
1422 "\nOpExtension \"SPV_KHR_physical_storage_buffer\"")
1423 .c_str());
1424 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1425 EXPECT_THAT(getDiagnosticString(),
1426 HasSubstr("Pointer can only be converted to another pointer, int "
1427 "scalar or 32-bit int vector: Bitcast"));
1428 }
1429
TEST_F(ValidateConversion,BitcastDifferentTotalBitWidth)1430 TEST_F(ValidateConversion, BitcastDifferentTotalBitWidth) {
1431 const std::string body = R"(
1432 %val = OpBitcast %f32 %u64_1
1433 )";
1434
1435 CompileSuccessfully(GenerateKernelCode(body).c_str());
1436 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1437 EXPECT_THAT(
1438 getDiagnosticString(),
1439 HasSubstr(
1440 "Expected input to have the same total bit width as Result Type: "
1441 "Bitcast"));
1442 }
1443
TEST_F(ValidateConversion,ConvertUToPtrInputIsAType)1444 TEST_F(ValidateConversion, ConvertUToPtrInputIsAType) {
1445 const std::string spirv = R"(
1446 OpCapability Addresses
1447 OpCapability Shader
1448 OpCapability Linkage
1449 OpMemoryModel Logical GLSL450
1450 %int = OpTypeInt 32 0
1451 %ptr_int = OpTypePointer Function %int
1452 %void = OpTypeVoid
1453 %voidfn = OpTypeFunction %void
1454 %func = OpFunction %void None %voidfn
1455 %entry = OpLabel
1456 %1 = OpConvertUToPtr %ptr_int %int
1457 OpReturn
1458 OpFunctionEnd
1459 )";
1460
1461 CompileSuccessfully(spirv);
1462 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1463 EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand '1[%uint]' cannot be a "
1464 "type"));
1465 }
1466
TEST_F(ValidateConversion,ConvertUToPtrPSBSuccess)1467 TEST_F(ValidateConversion, ConvertUToPtrPSBSuccess) {
1468 const std::string body = R"(
1469 OpCapability PhysicalStorageBufferAddresses
1470 OpCapability Int64
1471 OpCapability Shader
1472 OpExtension "SPV_EXT_physical_storage_buffer"
1473 OpMemoryModel PhysicalStorageBuffer64 GLSL450
1474 OpEntryPoint Fragment %main "main"
1475 OpExecutionMode %main OriginUpperLeft
1476 %uint64 = OpTypeInt 64 0
1477 %u64_1 = OpConstant %uint64 1
1478 %ptr = OpTypePointer PhysicalStorageBuffer %uint64
1479 %void = OpTypeVoid
1480 %voidfn = OpTypeFunction %void
1481 %main = OpFunction %void None %voidfn
1482 %entry = OpLabel
1483 %val1 = OpConvertUToPtr %ptr %u64_1
1484 OpReturn
1485 OpFunctionEnd
1486 )";
1487
1488 CompileSuccessfully(body.c_str());
1489 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1490 }
1491
TEST_F(ValidateConversion,ConvertUToPtrPSBStorageClass)1492 TEST_F(ValidateConversion, ConvertUToPtrPSBStorageClass) {
1493 const std::string body = R"(
1494 OpCapability PhysicalStorageBufferAddresses
1495 OpCapability Int64
1496 OpCapability Shader
1497 OpExtension "SPV_EXT_physical_storage_buffer"
1498 OpMemoryModel PhysicalStorageBuffer64 GLSL450
1499 OpEntryPoint Fragment %main "main"
1500 OpExecutionMode %main OriginUpperLeft
1501 %uint64 = OpTypeInt 64 0
1502 %u64_1 = OpConstant %uint64 1
1503 %ptr = OpTypePointer Function %uint64
1504 %void = OpTypeVoid
1505 %voidfn = OpTypeFunction %void
1506 %main = OpFunction %void None %voidfn
1507 %entry = OpLabel
1508 %val1 = OpConvertUToPtr %ptr %u64_1
1509 %val2 = OpConvertPtrToU %uint64 %val1
1510 OpReturn
1511 OpFunctionEnd
1512 )";
1513
1514 CompileSuccessfully(body.c_str());
1515 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1516 EXPECT_THAT(getDiagnosticString(),
1517 HasSubstr("Pointer storage class must be "
1518 "PhysicalStorageBuffer: ConvertUToPtr"));
1519 }
1520
TEST_F(ValidateConversion,ConvertUToPtrVulkanWrongWidth)1521 TEST_F(ValidateConversion, ConvertUToPtrVulkanWrongWidth) {
1522 const std::string body = R"(
1523 OpCapability PhysicalStorageBufferAddresses
1524 OpCapability Int64
1525 OpCapability Shader
1526 OpExtension "SPV_EXT_physical_storage_buffer"
1527 OpMemoryModel PhysicalStorageBuffer64 GLSL450
1528 OpEntryPoint Fragment %main "main"
1529 OpExecutionMode %main OriginUpperLeft
1530 %uint32 = OpTypeInt 32 0
1531 %uint64 = OpTypeInt 64 0
1532 %u32_1 = OpConstant %uint32 1
1533 %ptr = OpTypePointer PhysicalStorageBuffer %uint64
1534 %void = OpTypeVoid
1535 %voidfn = OpTypeFunction %void
1536 %main = OpFunction %void None %voidfn
1537 %entry = OpLabel
1538 %val1 = OpConvertUToPtr %ptr %u32_1
1539 OpReturn
1540 OpFunctionEnd
1541 )";
1542
1543 CompileSuccessfully(body.c_str());
1544 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1545 EXPECT_THAT(getDiagnosticString(),
1546 AnyVUID("VUID-StandaloneSpirv-PhysicalStorageBuffer64-04710"));
1547 EXPECT_THAT(
1548 getDiagnosticString(),
1549 HasSubstr("PhysicalStorageBuffer64 addressing mode requires the input "
1550 "integer to have a 64-bit width for Vulkan environment."));
1551 }
1552
TEST_F(ValidateConversion,ConvertPtrToUPSBSuccess)1553 TEST_F(ValidateConversion, ConvertPtrToUPSBSuccess) {
1554 const std::string body = R"(
1555 OpCapability PhysicalStorageBufferAddresses
1556 OpCapability Int64
1557 OpCapability Shader
1558 OpExtension "SPV_EXT_physical_storage_buffer"
1559 OpMemoryModel PhysicalStorageBuffer64 GLSL450
1560 OpEntryPoint Fragment %main "main"
1561 OpExecutionMode %main OriginUpperLeft
1562 OpDecorate %val1 RestrictPointer
1563 %uint64 = OpTypeInt 64 0
1564 %u64_1 = OpConstant %uint64 1
1565 %ptr = OpTypePointer PhysicalStorageBuffer %uint64
1566 %pptr_f = OpTypePointer Function %ptr
1567 %void = OpTypeVoid
1568 %voidfn = OpTypeFunction %void
1569 %main = OpFunction %void None %voidfn
1570 %entry = OpLabel
1571 %val1 = OpVariable %pptr_f Function
1572 %val2 = OpLoad %ptr %val1
1573 %val3 = OpConvertPtrToU %uint64 %val2
1574 OpReturn
1575 OpFunctionEnd
1576 )";
1577
1578 CompileSuccessfully(body.c_str());
1579 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1580 }
1581
TEST_F(ValidateConversion,ConvertPtrToUPSBStorageClass)1582 TEST_F(ValidateConversion, ConvertPtrToUPSBStorageClass) {
1583 const std::string body = R"(
1584 OpCapability PhysicalStorageBufferAddresses
1585 OpCapability Int64
1586 OpCapability Shader
1587 OpExtension "SPV_EXT_physical_storage_buffer"
1588 OpMemoryModel PhysicalStorageBuffer64 GLSL450
1589 OpEntryPoint Fragment %main "main"
1590 OpExecutionMode %main OriginUpperLeft
1591 %uint64 = OpTypeInt 64 0
1592 %u64_1 = OpConstant %uint64 1
1593 %ptr = OpTypePointer Function %uint64
1594 %void = OpTypeVoid
1595 %voidfn = OpTypeFunction %void
1596 %main = OpFunction %void None %voidfn
1597 %entry = OpLabel
1598 %val1 = OpVariable %ptr Function
1599 %val2 = OpConvertPtrToU %uint64 %val1
1600 OpReturn
1601 OpFunctionEnd
1602 )";
1603
1604 CompileSuccessfully(body.c_str());
1605 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1606 EXPECT_THAT(getDiagnosticString(),
1607 HasSubstr("Pointer storage class must be "
1608 "PhysicalStorageBuffer: ConvertPtrToU"));
1609 }
1610
TEST_F(ValidateConversion,ConvertPtrToUVulkanWrongWidth)1611 TEST_F(ValidateConversion, ConvertPtrToUVulkanWrongWidth) {
1612 const std::string body = R"(
1613 OpCapability PhysicalStorageBufferAddresses
1614 OpCapability Int64
1615 OpCapability Shader
1616 OpExtension "SPV_EXT_physical_storage_buffer"
1617 OpMemoryModel PhysicalStorageBuffer64 GLSL450
1618 OpEntryPoint Fragment %main "main"
1619 OpExecutionMode %main OriginUpperLeft
1620 OpDecorate %val1 RestrictPointer
1621 %uint32 = OpTypeInt 32 0
1622 %uint64 = OpTypeInt 64 0
1623 %ptr = OpTypePointer PhysicalStorageBuffer %uint64
1624 %pptr_f = OpTypePointer Function %ptr
1625 %void = OpTypeVoid
1626 %voidfn = OpTypeFunction %void
1627 %main = OpFunction %void None %voidfn
1628 %entry = OpLabel
1629 %val1 = OpVariable %pptr_f Function
1630 %val2 = OpLoad %ptr %val1
1631 %val3 = OpConvertPtrToU %uint32 %val2
1632 OpReturn
1633 OpFunctionEnd
1634 )";
1635
1636 CompileSuccessfully(body.c_str());
1637 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1638 EXPECT_THAT(getDiagnosticString(),
1639 AnyVUID("VUID-StandaloneSpirv-PhysicalStorageBuffer64-04710"));
1640 EXPECT_THAT(
1641 getDiagnosticString(),
1642 HasSubstr("PhysicalStorageBuffer64 addressing mode requires the result "
1643 "integer type to have a 64-bit width for Vulkan environment."));
1644 }
1645
TEST_F(ValidateConversion,ConvertUToAccelerationStructureU32Vec2)1646 TEST_F(ValidateConversion, ConvertUToAccelerationStructureU32Vec2) {
1647 const std::string extensions = R"(
1648 OpCapability RayQueryKHR
1649 OpExtension "SPV_KHR_ray_query"
1650 )";
1651 const std::string types = R"(
1652 %u32vec2ptr_func = OpTypePointer Function %u32vec2
1653 %typeAS = OpTypeAccelerationStructureKHR
1654 )";
1655 const std::string body = R"(
1656 %asHandle = OpVariable %u32vec2ptr_func Function
1657 %load = OpLoad %u32vec2 %asHandle
1658 %val = OpConvertUToAccelerationStructureKHR %typeAS %load
1659 )";
1660
1661 CompileSuccessfully(GenerateShaderCode(body, extensions, "", types).c_str());
1662 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1663 }
1664
TEST_F(ValidateConversion,ConvertUToAccelerationStructureSuccessU64)1665 TEST_F(ValidateConversion, ConvertUToAccelerationStructureSuccessU64) {
1666 const std::string extensions = R"(
1667 OpCapability RayQueryKHR
1668 OpExtension "SPV_KHR_ray_query"
1669 )";
1670 const std::string types = R"(
1671 %u64_func = OpTypePointer Function %u64
1672 %typeAS = OpTypeAccelerationStructureKHR
1673 )";
1674 const std::string body = R"(
1675 %asHandle = OpVariable %u64_func Function
1676 %load = OpLoad %u64 %asHandle
1677 %val = OpConvertUToAccelerationStructureKHR %typeAS %load
1678 )";
1679
1680 CompileSuccessfully(GenerateShaderCode(body, extensions, "", types).c_str());
1681 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1682 }
1683
TEST_F(ValidateConversion,ConvertUToAccelerationStructureResult)1684 TEST_F(ValidateConversion, ConvertUToAccelerationStructureResult) {
1685 const std::string extensions = R"(
1686 OpCapability RayQueryKHR
1687 OpExtension "SPV_KHR_ray_query"
1688 )";
1689 const std::string types = R"(
1690 %u32vec2ptr_func = OpTypePointer Function %u32vec2
1691 %typeRQ = OpTypeRayQueryKHR
1692 )";
1693 const std::string body = R"(
1694 %asHandle = OpVariable %u32vec2ptr_func Function
1695 %load = OpLoad %u32vec2 %asHandle
1696 %val = OpConvertUToAccelerationStructureKHR %typeRQ %load
1697 )";
1698
1699 CompileSuccessfully(GenerateShaderCode(body, extensions, "", types).c_str());
1700 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1701 EXPECT_THAT(getDiagnosticString(),
1702 HasSubstr("Expected Result Type to be a Acceleration Structure"));
1703 }
1704
TEST_F(ValidateConversion,ConvertUToAccelerationStructureU32)1705 TEST_F(ValidateConversion, ConvertUToAccelerationStructureU32) {
1706 const std::string extensions = R"(
1707 OpCapability RayQueryKHR
1708 OpExtension "SPV_KHR_ray_query"
1709 )";
1710 const std::string types = R"(
1711 %u32ptr_func = OpTypePointer Function %u32
1712 %typeAS = OpTypeAccelerationStructureKHR
1713 )";
1714 const std::string body = R"(
1715 %asHandle = OpVariable %u32ptr_func Function
1716 %load = OpLoad %u32 %asHandle
1717 %val = OpConvertUToAccelerationStructureKHR %typeAS %load
1718 )";
1719
1720 CompileSuccessfully(GenerateShaderCode(body, extensions, "", types).c_str());
1721 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1722 EXPECT_THAT(getDiagnosticString(),
1723 HasSubstr("Expected 64-bit uint scalar or 2-component 32-bit "
1724 "uint vector as input"));
1725 }
1726
TEST_F(ValidateConversion,ConvertUToAccelerationStructureS64)1727 TEST_F(ValidateConversion, ConvertUToAccelerationStructureS64) {
1728 const std::string extensions = R"(
1729 OpCapability RayQueryKHR
1730 OpExtension "SPV_KHR_ray_query"
1731 )";
1732 const std::string types = R"(
1733 %s64ptr_func = OpTypePointer Function %s64
1734 %typeAS = OpTypeAccelerationStructureKHR
1735 )";
1736 const std::string body = R"(
1737 %asHandle = OpVariable %s64ptr_func Function
1738 %load = OpLoad %s64 %asHandle
1739 %val = OpConvertUToAccelerationStructureKHR %typeAS %load
1740 )";
1741
1742 CompileSuccessfully(GenerateShaderCode(body, extensions, "", types).c_str());
1743 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1744 EXPECT_THAT(getDiagnosticString(),
1745 HasSubstr("Expected 64-bit uint scalar or 2-component 32-bit "
1746 "uint vector as input"));
1747 }
1748
TEST_F(ValidateConversion,ConvertUToAccelerationStructureS32Vec2)1749 TEST_F(ValidateConversion, ConvertUToAccelerationStructureS32Vec2) {
1750 const std::string extensions = R"(
1751 OpCapability RayQueryKHR
1752 OpExtension "SPV_KHR_ray_query"
1753 )";
1754 const std::string types = R"(
1755 %s32vec2ptr_func = OpTypePointer Function %s32vec2
1756 %typeAS = OpTypeAccelerationStructureKHR
1757 )";
1758 const std::string body = R"(
1759 %asHandle = OpVariable %s32vec2ptr_func Function
1760 %load = OpLoad %s32vec2 %asHandle
1761 %val = OpConvertUToAccelerationStructureKHR %typeAS %load
1762 )";
1763
1764 CompileSuccessfully(GenerateShaderCode(body, extensions, "", types).c_str());
1765 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1766 EXPECT_THAT(getDiagnosticString(),
1767 HasSubstr("Expected 64-bit uint scalar or 2-component 32-bit "
1768 "uint vector as input"));
1769 }
1770
1771 using ValidateSmallConversions = spvtest::ValidateBase<std::string>;
1772
GetSmallConversionsCodeGenerator()1773 CodeGenerator GetSmallConversionsCodeGenerator() {
1774 CodeGenerator generator;
1775 generator.capabilities_ = R"(
1776 OpCapability Shader
1777 OpCapability Linkage
1778 OpCapability UniformAndStorageBuffer16BitAccess
1779 OpCapability UniformAndStorageBuffer8BitAccess
1780 )";
1781 generator.extensions_ = R"(
1782 OpExtension "SPV_KHR_16bit_storage"
1783 OpExtension "SPV_KHR_8bit_storage"
1784 )";
1785 generator.memory_model_ = "OpMemoryModel Logical GLSL450\n";
1786 generator.before_types_ = R"(
1787 OpDecorate %char_block Block
1788 OpMemberDecorate %char_block 0 Offset 0
1789 OpDecorate %short_block Block
1790 OpMemberDecorate %short_block 0 Offset 0
1791 OpDecorate %half_block Block
1792 OpMemberDecorate %half_block 0 Offset 0
1793 OpDecorate %int_block Block
1794 OpMemberDecorate %int_block 0 Offset 0
1795 OpDecorate %float_block Block
1796 OpMemberDecorate %float_block 0 Offset 0
1797 )";
1798 generator.types_ = R"(
1799 %void = OpTypeVoid
1800 %int = OpTypeInt 32 0
1801 %int_0 = OpConstant %int 0
1802 %int_1 = OpConstant %int 1
1803 %int2 = OpTypeVector %int 2
1804 %float = OpTypeFloat 32
1805 %float_0 = OpConstant %float 0
1806 %float2 = OpTypeVector %float 2
1807 %char = OpTypeInt 8 0
1808 %char2 = OpTypeVector %char 2
1809 %short = OpTypeInt 16 0
1810 %short2 = OpTypeVector %short 2
1811 %half = OpTypeFloat 16
1812 %half2 = OpTypeVector %half 2
1813 %char_block = OpTypeStruct %char2
1814 %short_block = OpTypeStruct %short2
1815 %half_block = OpTypeStruct %half2
1816 %int_block = OpTypeStruct %int2
1817 %float_block = OpTypeStruct %float2
1818 %ptr_ssbo_char_block = OpTypePointer StorageBuffer %char_block
1819 %ptr_ssbo_char2 = OpTypePointer StorageBuffer %char2
1820 %ptr_ssbo_char = OpTypePointer StorageBuffer %char
1821 %ptr_ssbo_short_block = OpTypePointer StorageBuffer %short_block
1822 %ptr_ssbo_short2 = OpTypePointer StorageBuffer %short2
1823 %ptr_ssbo_short = OpTypePointer StorageBuffer %short
1824 %ptr_ssbo_half_block = OpTypePointer StorageBuffer %half_block
1825 %ptr_ssbo_half2 = OpTypePointer StorageBuffer %half2
1826 %ptr_ssbo_half = OpTypePointer StorageBuffer %half
1827 %ptr_ssbo_int_block = OpTypePointer StorageBuffer %int_block
1828 %ptr_ssbo_int2 = OpTypePointer StorageBuffer %int2
1829 %ptr_ssbo_int = OpTypePointer StorageBuffer %int
1830 %ptr_ssbo_float_block = OpTypePointer StorageBuffer %float_block
1831 %ptr_ssbo_float2 = OpTypePointer StorageBuffer %float2
1832 %ptr_ssbo_float = OpTypePointer StorageBuffer %float
1833 %void_fn = OpTypeFunction %void
1834 %char_var = OpVariable %ptr_ssbo_char_block StorageBuffer
1835 %short_var = OpVariable %ptr_ssbo_short_block StorageBuffer
1836 %half_var = OpVariable %ptr_ssbo_half_block StorageBuffer
1837 %int_var = OpVariable %ptr_ssbo_int_block StorageBuffer
1838 %float_var = OpVariable %ptr_ssbo_float_block StorageBuffer
1839 )";
1840 generator.after_types_ = R"(
1841 %func = OpFunction %void None %void_fn
1842 %entry = OpLabel
1843 %char2_gep = OpAccessChain %ptr_ssbo_char2 %char_var %int_0
1844 %ld_char2 = OpLoad %char2 %char2_gep
1845 %char_gep = OpAccessChain %ptr_ssbo_char %char_var %int_0 %int_0
1846 %ld_char = OpLoad %char %char_gep
1847 %short2_gep = OpAccessChain %ptr_ssbo_short2 %short_var %int_0
1848 %ld_short2 = OpLoad %short2 %short2_gep
1849 %short_gep = OpAccessChain %ptr_ssbo_short %short_var %int_0 %int_0
1850 %ld_short = OpLoad %short %short_gep
1851 %half2_gep = OpAccessChain %ptr_ssbo_half2 %half_var %int_0
1852 %ld_half2 = OpLoad %half2 %half2_gep
1853 %half_gep = OpAccessChain %ptr_ssbo_half %half_var %int_0 %int_0
1854 %ld_half = OpLoad %half %half_gep
1855 %int2_gep = OpAccessChain %ptr_ssbo_int2 %int_var %int_0
1856 %ld_int2 = OpLoad %int2 %int2_gep
1857 %int_gep = OpAccessChain %ptr_ssbo_int %int_var %int_0 %int_0
1858 %ld_int = OpLoad %int %int_gep
1859 %float2_gep = OpAccessChain %ptr_ssbo_float2 %float_var %int_0
1860 %ld_float2 = OpLoad %float2 %float2_gep
1861 %float_gep = OpAccessChain %ptr_ssbo_float %float_var %int_0 %int_0
1862 %ld_float = OpLoad %float %float_gep
1863 )";
1864 generator.add_at_the_end_ = R"(
1865 OpReturn
1866 OpFunctionEnd
1867 )";
1868 return generator;
1869 }
1870
TEST_P(ValidateSmallConversions,Instruction)1871 TEST_P(ValidateSmallConversions, Instruction) {
1872 CodeGenerator generator = GetSmallConversionsCodeGenerator();
1873 generator.after_types_ += GetParam() + "\n";
1874 CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
1875 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1876 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1877 EXPECT_THAT(
1878 getDiagnosticString(),
1879 HasSubstr(
1880 "8- or 16-bit types can only be used with width-only conversions"));
1881 }
1882
1883 INSTANTIATE_TEST_SUITE_P(SmallConversionInstructions, ValidateSmallConversions,
1884 Values("%inst = OpConvertFToU %char %ld_float",
1885 "%inst = OpConvertFToU %char2 %ld_float2",
1886 "%inst = OpConvertFToU %short %ld_float",
1887 "%inst = OpConvertFToU %short2 %ld_float2",
1888 "%inst = OpConvertFToU %int %ld_half",
1889 "%inst = OpConvertFToU %int2 %ld_half2",
1890 "%inst = OpConvertFToS %char %ld_float",
1891 "%inst = OpConvertFToS %char2 %ld_float2",
1892 "%inst = OpConvertFToS %short %ld_float",
1893 "%inst = OpConvertFToS %short2 %ld_float2",
1894 "%inst = OpConvertFToS %int %ld_half",
1895 "%inst = OpConvertFToS %int2 %ld_half2",
1896 "%inst = OpConvertSToF %float %ld_char",
1897 "%inst = OpConvertSToF %float2 %ld_char2",
1898 "%inst = OpConvertSToF %float %ld_short",
1899 "%inst = OpConvertSToF %float2 %ld_short2",
1900 "%inst = OpConvertSToF %half %ld_int",
1901 "%inst = OpConvertSToF %half2 %ld_int2",
1902 "%inst = OpConvertUToF %float %ld_char",
1903 "%inst = OpConvertUToF %float2 %ld_char2",
1904 "%inst = OpConvertUToF %float %ld_short",
1905 "%inst = OpConvertUToF %float2 %ld_short2",
1906 "%inst = OpConvertUToF %half %ld_int",
1907 "%inst = OpConvertUToF %half2 %ld_int2",
1908 "%inst = OpBitcast %half %ld_short",
1909 "%inst = OpBitcast %half2 %ld_short2",
1910 "%inst = OpBitcast %short %ld_half",
1911 "%inst = OpBitcast %short2 %ld_half2"));
1912
1913 } // namespace
1914 } // namespace val
1915 } // namespace spvtools
1916