1 // Copyright (c) 2016 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 // Validation tests for Data Rules.
16
17 #include <string>
18 #include <utility>
19
20 #include "gmock/gmock.h"
21 #include "test/unit_spirv.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::MatchesRegex;
30
31 using ValidateData = spvtest::ValidateBase<std::pair<std::string, bool>>;
32
HeaderWith(std::string cap)33 std::string HeaderWith(std::string cap) {
34 return std::string("OpCapability Shader OpCapability Linkage OpCapability ") +
35 cap + " OpMemoryModel Logical GLSL450 ";
36 }
37
38 std::string header = R"(
39 OpCapability Shader
40 OpCapability Linkage
41 OpMemoryModel Logical GLSL450
42 )";
43 std::string header_with_addresses = R"(
44 OpCapability Addresses
45 OpCapability Kernel
46 OpCapability GenericPointer
47 OpCapability Linkage
48 OpMemoryModel Physical32 OpenCL
49 )";
50 std::string header_with_vec16_cap = R"(
51 OpCapability Shader
52 OpCapability Vector16
53 OpCapability Linkage
54 OpMemoryModel Logical GLSL450
55 )";
56 std::string header_with_int8 = R"(
57 OpCapability Shader
58 OpCapability Linkage
59 OpCapability Int8
60 OpMemoryModel Logical GLSL450
61 )";
62 std::string header_with_int16 = R"(
63 OpCapability Shader
64 OpCapability Linkage
65 OpCapability Int16
66 OpMemoryModel Logical GLSL450
67 )";
68 std::string header_with_int64 = R"(
69 OpCapability Shader
70 OpCapability Linkage
71 OpCapability Int64
72 OpMemoryModel Logical GLSL450
73 )";
74 std::string header_with_float16 = R"(
75 OpCapability Shader
76 OpCapability Linkage
77 OpCapability Float16
78 OpMemoryModel Logical GLSL450
79 )";
80 std::string header_with_float16_buffer = R"(
81 OpCapability Shader
82 OpCapability Linkage
83 OpCapability Float16Buffer
84 OpMemoryModel Logical GLSL450
85 )";
86 std::string header_with_float64 = R"(
87 OpCapability Shader
88 OpCapability Linkage
89 OpCapability Float64
90 OpMemoryModel Logical GLSL450
91 )";
92
93 std::string invalid_comp_error = "Illegal number of components";
94 std::string missing_cap_error = "requires the Vector16 capability";
95 std::string missing_int8_cap_error = "requires the Int8 capability";
96 std::string missing_int16_cap_error =
97 "requires the Int16 capability,"
98 " or an extension that explicitly enables 16-bit integers.";
99 std::string missing_int64_cap_error = "requires the Int64 capability";
100 std::string missing_float16_cap_error =
101 "requires the Float16 or Float16Buffer capability,"
102 " or an extension that explicitly enables 16-bit floating point.";
103 std::string missing_float64_cap_error = "requires the Float64 capability";
104 std::string invalid_num_bits_error = "Invalid number of bits";
105
TEST_F(ValidateData,vec0)106 TEST_F(ValidateData, vec0) {
107 std::string str = header + R"(
108 %1 = OpTypeFloat 32
109 %2 = OpTypeVector %1 0
110 )";
111 CompileSuccessfully(str.c_str());
112 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
113 EXPECT_THAT(getDiagnosticString(), HasSubstr(invalid_comp_error));
114 }
115
TEST_F(ValidateData,vec1)116 TEST_F(ValidateData, vec1) {
117 std::string str = header + R"(
118 %1 = OpTypeFloat 32
119 %2 = OpTypeVector %1 1
120 )";
121 CompileSuccessfully(str.c_str());
122 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
123 EXPECT_THAT(getDiagnosticString(), HasSubstr(invalid_comp_error));
124 }
125
TEST_F(ValidateData,vec2)126 TEST_F(ValidateData, vec2) {
127 std::string str = header + R"(
128 %1 = OpTypeFloat 32
129 %2 = OpTypeVector %1 2
130 )";
131 CompileSuccessfully(str.c_str());
132 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
133 }
134
TEST_F(ValidateData,vec3)135 TEST_F(ValidateData, vec3) {
136 std::string str = header + R"(
137 %1 = OpTypeFloat 32
138 %2 = OpTypeVector %1 3
139 )";
140 CompileSuccessfully(str.c_str());
141 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
142 }
143
TEST_F(ValidateData,vec4)144 TEST_F(ValidateData, vec4) {
145 std::string str = header + R"(
146 %1 = OpTypeFloat 32
147 %2 = OpTypeVector %1 4
148 )";
149 CompileSuccessfully(str.c_str());
150 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
151 }
152
TEST_F(ValidateData,vec5)153 TEST_F(ValidateData, vec5) {
154 std::string str = header + R"(
155 %1 = OpTypeFloat 32
156 %2 = OpTypeVector %1 5
157 )";
158 CompileSuccessfully(str.c_str());
159 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
160 EXPECT_THAT(getDiagnosticString(), HasSubstr(invalid_comp_error));
161 }
162
TEST_F(ValidateData,vec8)163 TEST_F(ValidateData, vec8) {
164 std::string str = header + R"(
165 %1 = OpTypeFloat 32
166 %2 = OpTypeVector %1 8
167 )";
168 CompileSuccessfully(str.c_str());
169 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
170 EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_cap_error));
171 }
172
TEST_F(ValidateData,vec8_with_capability)173 TEST_F(ValidateData, vec8_with_capability) {
174 std::string str = header_with_vec16_cap + R"(
175 %1 = OpTypeFloat 32
176 %2 = OpTypeVector %1 8
177 )";
178 CompileSuccessfully(str.c_str());
179 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
180 }
181
TEST_F(ValidateData,vec16)182 TEST_F(ValidateData, vec16) {
183 std::string str = header + R"(
184 %1 = OpTypeFloat 32
185 %2 = OpTypeVector %1 8
186 )";
187 CompileSuccessfully(str.c_str());
188 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
189 EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_cap_error));
190 }
191
TEST_F(ValidateData,vec16_with_capability)192 TEST_F(ValidateData, vec16_with_capability) {
193 std::string str = header_with_vec16_cap + R"(
194 %1 = OpTypeFloat 32
195 %2 = OpTypeVector %1 16
196 )";
197 CompileSuccessfully(str.c_str());
198 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
199 }
200
TEST_F(ValidateData,vec15)201 TEST_F(ValidateData, vec15) {
202 std::string str = header + R"(
203 %1 = OpTypeFloat 32
204 %2 = OpTypeVector %1 15
205 )";
206 CompileSuccessfully(str.c_str());
207 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
208 EXPECT_THAT(getDiagnosticString(), HasSubstr(invalid_comp_error));
209 }
210
TEST_F(ValidateData,int8_good)211 TEST_F(ValidateData, int8_good) {
212 std::string str = header_with_int8 + "%2 = OpTypeInt 8 0";
213 CompileSuccessfully(str.c_str());
214 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
215 }
216
TEST_F(ValidateData,int8_bad)217 TEST_F(ValidateData, int8_bad) {
218 std::string str = header + "%2 = OpTypeInt 8 1";
219 CompileSuccessfully(str.c_str());
220 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
221 EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_int8_cap_error));
222 }
223
TEST_F(ValidateData,int8_with_storage_buffer_8bit_access_good)224 TEST_F(ValidateData, int8_with_storage_buffer_8bit_access_good) {
225 std::string str = HeaderWith(
226 "StorageBuffer8BitAccess "
227 "OpExtension \"SPV_KHR_8bit_storage\"") +
228 " %2 = OpTypeInt 8 0";
229 CompileSuccessfully(str.c_str());
230 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()) << getDiagnosticString();
231 }
232
TEST_F(ValidateData,int8_with_uniform_and_storage_buffer_8bit_access_good)233 TEST_F(ValidateData, int8_with_uniform_and_storage_buffer_8bit_access_good) {
234 std::string str = HeaderWith(
235 "UniformAndStorageBuffer8BitAccess "
236 "OpExtension \"SPV_KHR_8bit_storage\"") +
237 " %2 = OpTypeInt 8 0";
238 CompileSuccessfully(str.c_str());
239 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()) << getDiagnosticString();
240 }
241
TEST_F(ValidateData,int8_with_storage_push_constant_8_good)242 TEST_F(ValidateData, int8_with_storage_push_constant_8_good) {
243 std::string str = HeaderWith(
244 "StoragePushConstant8 "
245 "OpExtension \"SPV_KHR_8bit_storage\"") +
246 " %2 = OpTypeInt 8 0";
247 CompileSuccessfully(str.c_str());
248 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()) << getDiagnosticString();
249 }
250
TEST_F(ValidateData,int16_good)251 TEST_F(ValidateData, int16_good) {
252 std::string str = header_with_int16 + "%2 = OpTypeInt 16 1";
253 CompileSuccessfully(str.c_str());
254 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
255 }
256
TEST_F(ValidateData,storage_uniform_buffer_block_16_good)257 TEST_F(ValidateData, storage_uniform_buffer_block_16_good) {
258 std::string str = HeaderWith(
259 "StorageUniformBufferBlock16 "
260 "OpExtension \"SPV_KHR_16bit_storage\"") +
261 "%2 = OpTypeInt 16 1 %3 = OpTypeFloat 16";
262 CompileSuccessfully(str.c_str());
263 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
264 }
265
TEST_F(ValidateData,storage_uniform_16_good)266 TEST_F(ValidateData, storage_uniform_16_good) {
267 std::string str =
268 HeaderWith("StorageUniform16 OpExtension \"SPV_KHR_16bit_storage\"") +
269 "%2 = OpTypeInt 16 1 %3 = OpTypeFloat 16";
270 CompileSuccessfully(str.c_str());
271 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
272 }
273
TEST_F(ValidateData,storage_push_constant_16_good)274 TEST_F(ValidateData, storage_push_constant_16_good) {
275 std::string str = HeaderWith(
276 "StoragePushConstant16 "
277 "OpExtension \"SPV_KHR_16bit_storage\"") +
278 "%2 = OpTypeInt 16 1 %3 = OpTypeFloat 16";
279 CompileSuccessfully(str.c_str());
280 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
281 }
282
TEST_F(ValidateData,storage_input_output_16_good)283 TEST_F(ValidateData, storage_input_output_16_good) {
284 std::string str = HeaderWith(
285 "StorageInputOutput16 "
286 "OpExtension \"SPV_KHR_16bit_storage\"") +
287 "%2 = OpTypeInt 16 1 %3 = OpTypeFloat 16";
288 CompileSuccessfully(str.c_str());
289 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
290 }
291
TEST_F(ValidateData,amd_gpu_shader_half_float_fetch_16_good)292 TEST_F(ValidateData, amd_gpu_shader_half_float_fetch_16_good) {
293 std::string str = R"(
294 OpCapability Shader
295 OpCapability Linkage
296 OpExtension "SPV_AMD_gpu_shader_half_float_fetch"
297 OpMemoryModel Logical GLSL450
298 %2 = OpTypeFloat 16)";
299 CompileSuccessfully(str.c_str());
300 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
301 }
302
TEST_F(ValidateData,int16_bad)303 TEST_F(ValidateData, int16_bad) {
304 std::string str = header + "%2 = OpTypeInt 16 1";
305 CompileSuccessfully(str.c_str());
306 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
307 EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_int16_cap_error));
308 }
309
TEST_F(ValidateData,int64_good)310 TEST_F(ValidateData, int64_good) {
311 std::string str = header_with_int64 + "%2 = OpTypeInt 64 1";
312 CompileSuccessfully(str.c_str());
313 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
314 }
315
TEST_F(ValidateData,int64_bad)316 TEST_F(ValidateData, int64_bad) {
317 std::string str = header + "%2 = OpTypeInt 64 1";
318 CompileSuccessfully(str.c_str());
319 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
320 EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_int64_cap_error));
321 }
322
323 // Number of bits in an integer may be only one of: {8,16,32,64}
TEST_F(ValidateData,int_invalid_num_bits)324 TEST_F(ValidateData, int_invalid_num_bits) {
325 std::string str = header + "%2 = OpTypeInt 48 1";
326 CompileSuccessfully(str.c_str());
327 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
328 EXPECT_THAT(getDiagnosticString(), HasSubstr(invalid_num_bits_error));
329 }
330
TEST_F(ValidateData,float16_good)331 TEST_F(ValidateData, float16_good) {
332 std::string str = header_with_float16 + "%2 = OpTypeFloat 16";
333 CompileSuccessfully(str.c_str());
334 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
335 }
336
TEST_F(ValidateData,float16_buffer_good)337 TEST_F(ValidateData, float16_buffer_good) {
338 std::string str = header_with_float16_buffer + "%2 = OpTypeFloat 16";
339 CompileSuccessfully(str.c_str());
340 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
341 }
342
TEST_F(ValidateData,float16_bad)343 TEST_F(ValidateData, float16_bad) {
344 std::string str = header + "%2 = OpTypeFloat 16";
345 CompileSuccessfully(str.c_str());
346 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
347 EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_float16_cap_error));
348 }
349
TEST_F(ValidateData,float64_good)350 TEST_F(ValidateData, float64_good) {
351 std::string str = header_with_float64 + "%2 = OpTypeFloat 64";
352 CompileSuccessfully(str.c_str());
353 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
354 }
355
TEST_F(ValidateData,float64_bad)356 TEST_F(ValidateData, float64_bad) {
357 std::string str = header + "%2 = OpTypeFloat 64";
358 CompileSuccessfully(str.c_str());
359 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
360 EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_float64_cap_error));
361 }
362
363 // Number of bits in a float may be only one of: {16,32,64}
TEST_F(ValidateData,float_invalid_num_bits)364 TEST_F(ValidateData, float_invalid_num_bits) {
365 std::string str = header + "%2 = OpTypeFloat 48";
366 CompileSuccessfully(str.c_str());
367 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
368 EXPECT_THAT(getDiagnosticString(), HasSubstr(invalid_num_bits_error));
369 }
370
TEST_F(ValidateData,matrix_data_type_float)371 TEST_F(ValidateData, matrix_data_type_float) {
372 std::string str = header + R"(
373 %f32 = OpTypeFloat 32
374 %vec3 = OpTypeVector %f32 3
375 %mat33 = OpTypeMatrix %vec3 3
376 )";
377 CompileSuccessfully(str.c_str());
378 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
379 }
380
TEST_F(ValidateData,ids_should_be_validated_before_data)381 TEST_F(ValidateData, ids_should_be_validated_before_data) {
382 std::string str = header + R"(
383 %f32 = OpTypeFloat 32
384 %mat33 = OpTypeMatrix %vec3 3
385 )";
386 CompileSuccessfully(str.c_str());
387 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
388 EXPECT_THAT(getDiagnosticString(),
389 HasSubstr("Operand '3[%3]' requires a previous definition"));
390 }
391
TEST_F(ValidateData,matrix_bad_column_type)392 TEST_F(ValidateData, matrix_bad_column_type) {
393 std::string str = header + R"(
394 %f32 = OpTypeFloat 32
395 %mat33 = OpTypeMatrix %f32 3
396 )";
397 CompileSuccessfully(str.c_str());
398 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
399 EXPECT_THAT(getDiagnosticString(),
400 HasSubstr("Columns in a matrix must be of type vector"));
401 }
402
TEST_F(ValidateData,matrix_data_type_int)403 TEST_F(ValidateData, matrix_data_type_int) {
404 std::string str = header + R"(
405 %int32 = OpTypeInt 32 1
406 %vec3 = OpTypeVector %int32 3
407 %mat33 = OpTypeMatrix %vec3 3
408 )";
409 CompileSuccessfully(str.c_str());
410 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
411 EXPECT_THAT(getDiagnosticString(),
412 HasSubstr("can only be parameterized with floating-point types"));
413 }
414
TEST_F(ValidateData,matrix_data_type_bool)415 TEST_F(ValidateData, matrix_data_type_bool) {
416 std::string str = header + R"(
417 %boolt = OpTypeBool
418 %vec3 = OpTypeVector %boolt 3
419 %mat33 = OpTypeMatrix %vec3 3
420 )";
421 CompileSuccessfully(str.c_str());
422 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
423 EXPECT_THAT(getDiagnosticString(),
424 HasSubstr("can only be parameterized with floating-point types"));
425 }
426
TEST_F(ValidateData,matrix_with_0_columns)427 TEST_F(ValidateData, matrix_with_0_columns) {
428 std::string str = header + R"(
429 %f32 = OpTypeFloat 32
430 %vec3 = OpTypeVector %f32 3
431 %mat33 = OpTypeMatrix %vec3 0
432 )";
433 CompileSuccessfully(str.c_str());
434 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
435 EXPECT_THAT(
436 getDiagnosticString(),
437 HasSubstr("can only be parameterized as having only 2, 3, or 4 columns"));
438 }
439
TEST_F(ValidateData,matrix_with_1_column)440 TEST_F(ValidateData, matrix_with_1_column) {
441 std::string str = header + R"(
442 %f32 = OpTypeFloat 32
443 %vec3 = OpTypeVector %f32 3
444 %mat33 = OpTypeMatrix %vec3 1
445 )";
446 CompileSuccessfully(str.c_str());
447 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
448 EXPECT_THAT(
449 getDiagnosticString(),
450 HasSubstr("can only be parameterized as having only 2, 3, or 4 columns"));
451 }
452
TEST_F(ValidateData,matrix_with_2_columns)453 TEST_F(ValidateData, matrix_with_2_columns) {
454 std::string str = header + R"(
455 %f32 = OpTypeFloat 32
456 %vec3 = OpTypeVector %f32 3
457 %mat33 = OpTypeMatrix %vec3 2
458 )";
459 CompileSuccessfully(str.c_str());
460 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
461 }
462
TEST_F(ValidateData,matrix_with_3_columns)463 TEST_F(ValidateData, matrix_with_3_columns) {
464 std::string str = header + R"(
465 %f32 = OpTypeFloat 32
466 %vec3 = OpTypeVector %f32 3
467 %mat33 = OpTypeMatrix %vec3 3
468 )";
469 CompileSuccessfully(str.c_str());
470 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
471 }
472
TEST_F(ValidateData,matrix_with_4_columns)473 TEST_F(ValidateData, matrix_with_4_columns) {
474 std::string str = header + R"(
475 %f32 = OpTypeFloat 32
476 %vec3 = OpTypeVector %f32 3
477 %mat33 = OpTypeMatrix %vec3 4
478 )";
479 CompileSuccessfully(str.c_str());
480 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
481 }
482
TEST_F(ValidateData,matrix_with_5_column)483 TEST_F(ValidateData, matrix_with_5_column) {
484 std::string str = header + R"(
485 %f32 = OpTypeFloat 32
486 %vec3 = OpTypeVector %f32 3
487 %mat33 = OpTypeMatrix %vec3 5
488 )";
489 CompileSuccessfully(str.c_str());
490 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
491 EXPECT_THAT(
492 getDiagnosticString(),
493 HasSubstr("can only be parameterized as having only 2, 3, or 4 columns"));
494 }
495
TEST_F(ValidateData,specialize_int)496 TEST_F(ValidateData, specialize_int) {
497 std::string str = header + R"(
498 %i32 = OpTypeInt 32 1
499 %len = OpSpecConstant %i32 2)";
500 CompileSuccessfully(str.c_str());
501 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
502 }
503
TEST_F(ValidateData,specialize_float)504 TEST_F(ValidateData, specialize_float) {
505 std::string str = header + R"(
506 %f32 = OpTypeFloat 32
507 %len = OpSpecConstant %f32 2)";
508 CompileSuccessfully(str.c_str());
509 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
510 }
511
TEST_F(ValidateData,specialize_boolean)512 TEST_F(ValidateData, specialize_boolean) {
513 std::string str = header + R"(
514 %2 = OpTypeBool
515 %3 = OpSpecConstantTrue %2
516 %4 = OpSpecConstantFalse %2)";
517 CompileSuccessfully(str.c_str());
518 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
519 }
520
TEST_F(ValidateData,specialize_boolean_true_to_int)521 TEST_F(ValidateData, specialize_boolean_true_to_int) {
522 std::string str = header + R"(
523 %2 = OpTypeInt 32 1
524 %3 = OpSpecConstantTrue %2)";
525 CompileSuccessfully(str.c_str());
526 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
527 EXPECT_THAT(getDiagnosticString(),
528 HasSubstr("OpSpecConstantTrue Result Type <id> '1[%int]' is not "
529 "a boolean type"));
530 }
531
TEST_F(ValidateData,specialize_boolean_false_to_int)532 TEST_F(ValidateData, specialize_boolean_false_to_int) {
533 std::string str = header + R"(
534 %2 = OpTypeInt 32 1
535 %4 = OpSpecConstantFalse %2)";
536 CompileSuccessfully(str.c_str());
537 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
538 EXPECT_THAT(getDiagnosticString(),
539 HasSubstr("OpSpecConstantFalse Result Type <id> '1[%int]' is not "
540 "a boolean type"));
541 }
542
TEST_F(ValidateData,missing_forward_pointer_decl)543 TEST_F(ValidateData, missing_forward_pointer_decl) {
544 std::string str = header_with_addresses + R"(
545 %uintt = OpTypeInt 32 0
546 %3 = OpTypeStruct %fwd_ptrt %uintt
547 )";
548 CompileSuccessfully(str.c_str());
549 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
550 EXPECT_THAT(getDiagnosticString(),
551 HasSubstr("Operand '3[%3]' requires a previous definition"));
552 }
553
TEST_F(ValidateData,missing_forward_pointer_decl_self_reference)554 TEST_F(ValidateData, missing_forward_pointer_decl_self_reference) {
555 std::string str = header_with_addresses + R"(
556 %uintt = OpTypeInt 32 0
557 %3 = OpTypeStruct %3 %uintt
558 )";
559 CompileSuccessfully(str.c_str());
560 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
561 EXPECT_THAT(
562 getDiagnosticString(),
563 HasSubstr("Operand '2[%_struct_2]' requires a previous definition"));
564 }
565
TEST_F(ValidateData,forward_pointer_missing_definition)566 TEST_F(ValidateData, forward_pointer_missing_definition) {
567 std::string str = header_with_addresses + R"(
568 OpTypeForwardPointer %_ptr_Generic_struct_A Generic
569 %uintt = OpTypeInt 32 0
570 %struct_B = OpTypeStruct %uintt %_ptr_Generic_struct_A
571 )";
572 CompileSuccessfully(str.c_str());
573 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
574 EXPECT_THAT(getDiagnosticString(),
575 HasSubstr("forward referenced IDs have not been defined"));
576 }
577
TEST_F(ValidateData,forward_ref_bad_type)578 TEST_F(ValidateData, forward_ref_bad_type) {
579 std::string str = header_with_addresses + R"(
580 OpTypeForwardPointer %_ptr_Generic_struct_A Generic
581 %uintt = OpTypeInt 32 0
582 %struct_B = OpTypeStruct %uintt %_ptr_Generic_struct_A
583 %_ptr_Generic_struct_A = OpTypeFloat 32
584 )";
585 CompileSuccessfully(str.c_str());
586 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
587 EXPECT_THAT(getDiagnosticString(),
588 HasSubstr("Pointer type in OpTypeForwardPointer is not a pointer "
589 "type.\n OpTypeForwardPointer %float Generic\n"));
590 }
591
TEST_F(ValidateData,forward_ref_points_to_non_struct)592 TEST_F(ValidateData, forward_ref_points_to_non_struct) {
593 std::string str = header_with_addresses + R"(
594 OpTypeForwardPointer %_ptr_Generic_struct_A Generic
595 %uintt = OpTypeInt 32 0
596 %struct_B = OpTypeStruct %uintt %_ptr_Generic_struct_A
597 %_ptr_Generic_struct_A = OpTypePointer Generic %uintt
598 )";
599 CompileSuccessfully(str.c_str());
600 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
601 EXPECT_THAT(getDiagnosticString(),
602 HasSubstr("Forward pointers must point to a structure"));
603 }
604
TEST_F(ValidateData,struct_forward_pointer_good)605 TEST_F(ValidateData, struct_forward_pointer_good) {
606 std::string str = header_with_addresses + R"(
607 OpTypeForwardPointer %_ptr_Generic_struct_A Generic
608 %uintt = OpTypeInt 32 0
609 %struct_B = OpTypeStruct %uintt %_ptr_Generic_struct_A
610 %struct_C = OpTypeStruct %uintt %struct_B
611 %struct_A = OpTypeStruct %uintt %struct_C
612 %_ptr_Generic_struct_A = OpTypePointer Generic %struct_C
613 )";
614 CompileSuccessfully(str.c_str());
615 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
616 }
617
TEST_F(ValidateData,ext_16bit_storage_caps_allow_free_fp_rounding_mode)618 TEST_F(ValidateData, ext_16bit_storage_caps_allow_free_fp_rounding_mode) {
619 for (const char* cap : {"StorageUniform16", "StorageUniformBufferBlock16"}) {
620 for (const char* mode : {"RTE", "RTZ", "RTP", "RTN"}) {
621 std::string str = std::string(R"(
622 OpCapability Shader
623 OpCapability Linkage
624 OpCapability )") +
625 cap + R"(
626 OpExtension "SPV_KHR_storage_buffer_storage_class"
627 OpExtension "SPV_KHR_variable_pointers"
628 OpExtension "SPV_KHR_16bit_storage"
629 OpMemoryModel Logical GLSL450
630 OpDecorate %_ FPRoundingMode )" + mode + R"(
631 %half = OpTypeFloat 16
632 %float = OpTypeFloat 32
633 %float_1_25 = OpConstant %float 1.25
634 %half_ptr = OpTypePointer StorageBuffer %half
635 %half_ptr_var = OpVariable %half_ptr StorageBuffer
636 %void = OpTypeVoid
637 %func = OpTypeFunction %void
638 %main = OpFunction %void None %func
639 %main_entry = OpLabel
640 %_ = OpFConvert %half %float_1_25
641 OpStore %half_ptr_var %_
642 OpReturn
643 OpFunctionEnd
644 )";
645 CompileSuccessfully(str.c_str());
646 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
647 }
648 }
649 }
650
TEST_F(ValidateData,vulkan_disallow_free_fp_rounding_mode)651 TEST_F(ValidateData, vulkan_disallow_free_fp_rounding_mode) {
652 for (const char* mode : {"RTE", "RTZ"}) {
653 for (const auto env : {SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1}) {
654 std::string str = std::string(R"(
655 OpCapability Shader
656 OpExtension "SPV_KHR_storage_buffer_storage_class"
657 OpExtension "SPV_KHR_variable_pointers"
658 OpMemoryModel Logical GLSL450
659 OpDecorate %_ FPRoundingMode )") +
660 mode + R"(
661 %half = OpTypeFloat 16
662 %float = OpTypeFloat 32
663 %float_1_25 = OpConstant %float 1.25
664 %half_ptr = OpTypePointer StorageBuffer %half
665 %half_ptr_var = OpVariable %half_ptr StorageBuffer
666 %void = OpTypeVoid
667 %func = OpTypeFunction %void
668 %main = OpFunction %void None %func
669 %main_entry = OpLabel
670 %_ = OpFConvert %half %float_1_25
671 OpStore %half_ptr_var %_
672 OpReturn
673 OpFunctionEnd
674 )";
675 CompileSuccessfully(str.c_str());
676 ASSERT_EQ(SPV_ERROR_INVALID_CAPABILITY, ValidateInstructions(env));
677 EXPECT_THAT(
678 getDiagnosticString(),
679 HasSubstr(
680 "Operand 2 of Decorate requires one of these capabilities: "
681 "StorageBuffer16BitAccess UniformAndStorageBuffer16BitAccess "
682 "StoragePushConstant16 StorageInputOutput16"));
683 }
684 }
685 }
686
TEST_F(ValidateData,void_array)687 TEST_F(ValidateData, void_array) {
688 std::string str = header + R"(
689 %void = OpTypeVoid
690 %int = OpTypeInt 32 0
691 %int_5 = OpConstant %int 5
692 %array = OpTypeArray %void %int_5
693 )";
694
695 CompileSuccessfully(str.c_str());
696 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
697 EXPECT_THAT(
698 getDiagnosticString(),
699 HasSubstr("OpTypeArray Element Type <id> '1[%void]' is a void type."));
700 }
701
TEST_F(ValidateData,void_runtime_array)702 TEST_F(ValidateData, void_runtime_array) {
703 std::string str = header + R"(
704 %void = OpTypeVoid
705 %array = OpTypeRuntimeArray %void
706 )";
707
708 CompileSuccessfully(str.c_str());
709 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
710 EXPECT_THAT(
711 getDiagnosticString(),
712 HasSubstr(
713 "OpTypeRuntimeArray Element Type <id> '1[%void]' is a void type."));
714 }
715
TEST_F(ValidateData,vulkan_RTA_array_at_end_of_struct)716 TEST_F(ValidateData, vulkan_RTA_array_at_end_of_struct) {
717 std::string str = R"(
718 OpCapability Shader
719 OpMemoryModel Logical GLSL450
720 OpEntryPoint Fragment %func "func"
721 OpExecutionMode %func OriginUpperLeft
722 OpDecorate %array_t ArrayStride 4
723 OpMemberDecorate %struct_t 0 Offset 0
724 OpMemberDecorate %struct_t 1 Offset 4
725 OpDecorate %struct_t Block
726 %uint_t = OpTypeInt 32 0
727 %array_t = OpTypeRuntimeArray %uint_t
728 %struct_t = OpTypeStruct %uint_t %array_t
729 %struct_ptr = OpTypePointer StorageBuffer %struct_t
730 %2 = OpVariable %struct_ptr StorageBuffer
731 %void = OpTypeVoid
732 %func_t = OpTypeFunction %void
733 %func = OpFunction %void None %func_t
734 %1 = OpLabel
735 OpReturn
736 OpFunctionEnd
737 )";
738
739 CompileSuccessfully(str.c_str(), SPV_ENV_VULKAN_1_1);
740 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
741 }
742
TEST_F(ValidateData,vulkan_RTA_not_at_end_of_struct)743 TEST_F(ValidateData, vulkan_RTA_not_at_end_of_struct) {
744 std::string str = R"(
745 OpCapability Shader
746 OpMemoryModel Logical GLSL450
747 OpEntryPoint Fragment %func "func"
748 OpExecutionMode %func OriginUpperLeft
749 OpDecorate %array_t ArrayStride 4
750 OpMemberDecorate %struct_t 0 Offset 0
751 OpMemberDecorate %struct_t 1 Offset 4
752 OpDecorate %struct_t Block
753 %uint_t = OpTypeInt 32 0
754 %array_t = OpTypeRuntimeArray %uint_t
755 %struct_t = OpTypeStruct %array_t %uint_t
756 %struct_ptr = OpTypePointer StorageBuffer %struct_t
757 %2 = OpVariable %struct_ptr StorageBuffer
758 %void = OpTypeVoid
759 %func_t = OpTypeFunction %void
760 %func = OpFunction %void None %func_t
761 %1 = OpLabel
762 OpReturn
763 OpFunctionEnd
764 )";
765
766 CompileSuccessfully(str.c_str(), SPV_ENV_VULKAN_1_1);
767 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
768 EXPECT_THAT(getDiagnosticString(),
769 AnyVUID("VUID-StandaloneSpirv-OpTypeRuntimeArray-04680"));
770 EXPECT_THAT(getDiagnosticString(),
771 HasSubstr("In Vulkan, OpTypeRuntimeArray must only be used for "
772 "the last member of an OpTypeStruct\n %_struct_3 = "
773 "OpTypeStruct %_runtimearr_uint %uint\n"));
774 }
775
TEST_F(ValidateData,TypeForwardReference)776 TEST_F(ValidateData, TypeForwardReference) {
777 std::string test = R"(
778 OpCapability Shader
779 OpCapability PhysicalStorageBufferAddresses
780 OpCapability Linkage
781 OpMemoryModel Logical GLSL450
782 OpTypeForwardPointer %1 PhysicalStorageBuffer
783 %2 = OpTypeStruct
784 %3 = OpTypeRuntimeArray %1
785 %1 = OpTypePointer PhysicalStorageBuffer %2
786 )";
787
788 CompileSuccessfully(test, SPV_ENV_UNIVERSAL_1_5);
789 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
790 }
791
TEST_F(ValidateData,VulkanTypeForwardStorageClass)792 TEST_F(ValidateData, VulkanTypeForwardStorageClass) {
793 std::string test = R"(
794 OpCapability Shader
795 OpCapability PhysicalStorageBufferAddresses
796 OpMemoryModel Logical GLSL450
797 OpTypeForwardPointer %1 Uniform
798 %2 = OpTypeStruct
799 %3 = OpTypeRuntimeArray %1
800 %1 = OpTypePointer Uniform %2
801 )";
802
803 CompileSuccessfully(test, SPV_ENV_VULKAN_1_2);
804 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
805 EXPECT_THAT(getDiagnosticString(),
806 AnyVUID("VUID-StandaloneSpirv-OpTypeForwardPointer-04711"));
807 EXPECT_THAT(getDiagnosticString(),
808 HasSubstr("In Vulkan, OpTypeForwardPointer must have "
809 "a storage class of PhysicalStorageBuffer."));
810 }
811
TEST_F(ValidateData,TypeForwardReferenceMustBeForwardPointer)812 TEST_F(ValidateData, TypeForwardReferenceMustBeForwardPointer) {
813 std::string test = R"(
814 OpCapability Shader
815 OpCapability PhysicalStorageBufferAddresses
816 OpCapability Linkage
817 OpMemoryModel Logical GLSL450
818 %1 = OpTypeStruct
819 %2 = OpTypeRuntimeArray %3
820 %3 = OpTypePointer PhysicalStorageBuffer %1
821 )";
822
823 CompileSuccessfully(test, SPV_ENV_UNIVERSAL_1_5);
824 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
825 EXPECT_THAT(getDiagnosticString(),
826 HasSubstr("Operand '3[%_ptr_PhysicalStorageBuffer__struct_1]' "
827 "requires a previous definition"));
828 }
829
830 } // namespace
831 } // namespace val
832 } // namespace spvtools
833