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