1 // Copyright (c) 2021 Google LLC
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 decorations
16
17 #include <string>
18 #include <vector>
19
20 #include "gmock/gmock.h"
21 #include "test/unit_spirv.h"
22 #include "test/val/val_code_generator.h"
23 #include "test/val/val_fixtures.h"
24
25 namespace spvtools {
26 namespace val {
27 namespace {
28
29 using ::testing::Combine;
30 using ::testing::Eq;
31 using ::testing::HasSubstr;
32 using ::testing::Values;
33
34 using DecorationTest = spvtest::ValidateBase<bool>;
35
TEST_F(DecorationTest,WorkgroupSizeShader)36 TEST_F(DecorationTest, WorkgroupSizeShader) {
37 const std::string text = R"(
38 OpCapability Shader
39 OpCapability Linkage
40 OpMemoryModel Logical GLSL450
41 OpDecorate %ones BuiltIn WorkgroupSize
42 %int = OpTypeInt 32 0
43 %int3 = OpTypeVector %int 3
44 %int_1 = OpConstant %int 1
45 %ones = OpConstantComposite %int3 %int_1 %int_1 %int_1
46 )";
47
48 CompileSuccessfully(text);
49 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
50 }
51
TEST_F(DecorationTest,WorkgroupSizeKernel)52 TEST_F(DecorationTest, WorkgroupSizeKernel) {
53 const std::string text = R"(
54 OpCapability Kernel
55 OpCapability Linkage
56 OpMemoryModel Logical OpenCL
57 OpDecorate %var BuiltIn WorkgroupSize
58 %int = OpTypeInt 32 0
59 %int3 = OpTypeVector %int 3
60 %ptr = OpTypePointer Input %int3
61 %var = OpVariable %ptr Input
62 )";
63
64 CompileSuccessfully(text);
65 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
66 }
67
TEST_F(DecorationTest,FPFastMathModeInvalidMask)68 TEST_F(DecorationTest, FPFastMathModeInvalidMask) {
69 const std::string text = R"(
70 OpCapability Shader
71 OpCapability FloatControls2
72 OpExtension "SPV_KHR_float_controls2"
73 OpMemoryModel Logical GLSL450
74 OpEntryPoint GLCompute %main "main"
75 OpExecutionMode %main LocalSize 1 1 1
76 OpDecorate %add FPFastMathMode !524288
77 %void = OpTypeVoid
78 %float = OpTypeFloat 32
79 %undef = OpUndef %float
80 %void_fn = OpTypeFunction %void
81 %main = OpFunction %void None %void_fn
82 %entry = OpLabel
83 %add = OpFAdd %float %undef %undef
84 OpReturn
85 OpFunctionEnd
86 )";
87
88 CompileSuccessfully(text);
89 EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions());
90 EXPECT_THAT(getDiagnosticString(),
91 HasSubstr("Invalid floating-point fast math mode operand"));
92 }
93
TEST_F(DecorationTest,FPFastMathModeAllowTransformMissingAllowContract)94 TEST_F(DecorationTest, FPFastMathModeAllowTransformMissingAllowContract) {
95 const std::string text = R"(
96 OpCapability Shader
97 OpCapability FloatControls2
98 OpExtension "SPV_KHR_float_controls2"
99 OpMemoryModel Logical GLSL450
100 OpEntryPoint GLCompute %main "main"
101 OpExecutionMode %main LocalSize 1 1 1
102 OpDecorate %add FPFastMathMode AllowTransform|AllowReassoc
103 %void = OpTypeVoid
104 %float = OpTypeFloat 32
105 %undef = OpUndef %float
106 %void_fn = OpTypeFunction %void
107 %main = OpFunction %void None %void_fn
108 %entry = OpLabel
109 %add = OpFAdd %float %undef %undef
110 OpReturn
111 OpFunctionEnd
112 )";
113
114 CompileSuccessfully(text);
115 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
116 EXPECT_THAT(getDiagnosticString(),
117 HasSubstr("AllowReassoc and AllowContract must be specified when "
118 "AllowTransform is specified"));
119 }
120
TEST_F(DecorationTest,FPFastMathModeAllowTransformMissingAllowReassoc)121 TEST_F(DecorationTest, FPFastMathModeAllowTransformMissingAllowReassoc) {
122 const std::string text = R"(
123 OpCapability Shader
124 OpCapability FloatControls2
125 OpExtension "SPV_KHR_float_controls2"
126 OpMemoryModel Logical GLSL450
127 OpEntryPoint GLCompute %main "main"
128 OpExecutionMode %main LocalSize 1 1 1
129 OpDecorate %add FPFastMathMode AllowTransform|AllowContract
130 %void = OpTypeVoid
131 %float = OpTypeFloat 32
132 %undef = OpUndef %float
133 %void_fn = OpTypeFunction %void
134 %main = OpFunction %void None %void_fn
135 %entry = OpLabel
136 %add = OpFAdd %float %undef %undef
137 OpReturn
138 OpFunctionEnd
139 )";
140
141 CompileSuccessfully(text);
142 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
143 EXPECT_THAT(getDiagnosticString(),
144 HasSubstr("AllowReassoc and AllowContract must be specified when "
145 "AllowTransform is specified"));
146 }
147
TEST_F(DecorationTest,FPFastMathModeAllowTransformMissingContractAndReassoc)148 TEST_F(DecorationTest, FPFastMathModeAllowTransformMissingContractAndReassoc) {
149 const std::string text = R"(
150 OpCapability Shader
151 OpCapability FloatControls2
152 OpExtension "SPV_KHR_float_controls2"
153 OpMemoryModel Logical GLSL450
154 OpEntryPoint GLCompute %main "main"
155 OpExecutionMode %main LocalSize 1 1 1
156 OpDecorate %add FPFastMathMode AllowTransform
157 %void = OpTypeVoid
158 %float = OpTypeFloat 32
159 %undef = OpUndef %float
160 %void_fn = OpTypeFunction %void
161 %main = OpFunction %void None %void_fn
162 %entry = OpLabel
163 %add = OpFAdd %float %undef %undef
164 OpReturn
165 OpFunctionEnd
166 )";
167
168 CompileSuccessfully(text);
169 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
170 EXPECT_THAT(getDiagnosticString(),
171 HasSubstr("AllowReassoc and AllowContract must be specified when "
172 "AllowTransform is specified"));
173 }
174
TEST_F(DecorationTest,FPFastMathModeAndNoContraction)175 TEST_F(DecorationTest, FPFastMathModeAndNoContraction) {
176 const std::string text = R"(
177 OpCapability Shader
178 OpCapability FloatControls2
179 OpExtension "SPV_KHR_float_controls2"
180 OpMemoryModel Logical GLSL450
181 OpEntryPoint GLCompute %main "main"
182 OpExecutionMode %main LocalSize 1 1 1
183 OpDecorate %add FPFastMathMode None
184 OpDecorate %add NoContraction
185 %void = OpTypeVoid
186 %float = OpTypeFloat 32
187 %undef = OpUndef %float
188 %void_fn = OpTypeFunction %void
189 %main = OpFunction %void None %void_fn
190 %entry = OpLabel
191 %add = OpFAdd %float %undef %undef
192 OpReturn
193 OpFunctionEnd
194 )";
195
196 CompileSuccessfully(text);
197 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
198 EXPECT_THAT(
199 getDiagnosticString(),
200 HasSubstr(
201 "FPFastMathMode and NoContraction cannot decorate the same target"));
202 }
203
TEST_F(DecorationTest,FPFastMathModeAndNoContraction2)204 TEST_F(DecorationTest, FPFastMathModeAndNoContraction2) {
205 const std::string text = R"(
206 OpCapability Shader
207 OpCapability FloatControls2
208 OpExtension "SPV_KHR_float_controls2"
209 OpMemoryModel Logical GLSL450
210 OpEntryPoint GLCompute %main "main"
211 OpExecutionMode %main LocalSize 1 1 1
212 OpDecorate %add NoContraction
213 OpDecorate %add FPFastMathMode None
214 %void = OpTypeVoid
215 %float = OpTypeFloat 32
216 %undef = OpUndef %float
217 %void_fn = OpTypeFunction %void
218 %main = OpFunction %void None %void_fn
219 %entry = OpLabel
220 %add = OpFAdd %float %undef %undef
221 OpReturn
222 OpFunctionEnd
223 )";
224
225 CompileSuccessfully(text);
226 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
227 EXPECT_THAT(
228 getDiagnosticString(),
229 HasSubstr(
230 "FPFastMathMode and NoContraction cannot decorate the same target"));
231 }
232
233 using MemberOnlyDecorations = spvtest::ValidateBase<std::string>;
234
TEST_P(MemberOnlyDecorations,MemberDecoration)235 TEST_P(MemberOnlyDecorations, MemberDecoration) {
236 const auto deco = GetParam();
237 const std::string text = R"(
238 OpCapability Shader
239 OpCapability Linkage
240 OpMemoryModel Logical GLSL450
241 OpMemberDecorate %struct 0 )" +
242 deco + R"(
243 %float = OpTypeFloat 32
244 %float2 = OpTypeVector %float 2
245 %float2x2 = OpTypeMatrix %float2 2
246 %struct = OpTypeStruct %float2x2
247 )";
248
249 CompileSuccessfully(text);
250 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
251 }
252
TEST_P(MemberOnlyDecorations,Decoration)253 TEST_P(MemberOnlyDecorations, Decoration) {
254 const auto deco = GetParam();
255 const std::string text = R"(
256 OpCapability Shader
257 OpCapability Linkage
258 OpMemoryModel Logical GLSL450
259 OpDecorate %struct )" + deco +
260 R"(
261 %float = OpTypeFloat 32
262 %float2 = OpTypeVector %float 2
263 %float2x2 = OpTypeMatrix %float2 2
264 %struct = OpTypeStruct %float2x2
265 )";
266
267 CompileSuccessfully(text);
268 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
269 EXPECT_THAT(getDiagnosticString(),
270 HasSubstr("can only be applied to structure members"));
271 }
272
273 INSTANTIATE_TEST_SUITE_P(ValidateMemberOnlyDecorations, MemberOnlyDecorations,
274 Values("RowMajor", "ColMajor", "MatrixStride 16"
275 // SPIR-V spec bug?
276 /*,"Offset 0"*/));
277
278 using NonMemberOnlyDecorations = spvtest::ValidateBase<std::string>;
279
TEST_P(NonMemberOnlyDecorations,MemberDecoration)280 TEST_P(NonMemberOnlyDecorations, MemberDecoration) {
281 const auto deco = GetParam();
282 const auto text = R"(
283 OpCapability Shader
284 OpCapability Kernel
285 OpCapability Linkage
286 OpCapability InputAttachment
287 OpCapability Addresses
288 OpCapability PhysicalStorageBufferAddresses
289 OpCapability ShaderNonUniform
290 OpExtension "SPV_KHR_no_integer_wrap_decoration"
291 OpExtension "SPV_KHR_physical_storage_buffer"
292 OpExtension "SPV_GOOGLE_hlsl_functionality1"
293 OpExtension "SPV_EXT_descriptor_indexing"
294 OpMemoryModel Logical GLSL450
295 OpMemberDecorate %struct 0 )" +
296 deco + R"(
297 %float = OpTypeFloat 32
298 %float2 = OpTypeVector %float 2
299 %float2x2 = OpTypeMatrix %float2 2
300 %struct = OpTypeStruct %float2x2
301 )";
302
303 CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
304 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
305 EXPECT_THAT(getDiagnosticString(),
306 HasSubstr("cannot be applied to structure members"));
307 }
308
309 INSTANTIATE_TEST_SUITE_P(
310 ValidateNonMemberOnlyDecorations, NonMemberOnlyDecorations,
311 Values("SpecId 1", "Block", "BufferBlock", "ArrayStride 4", "GLSLShared",
312 "GLSLPacked", "CPacked",
313 // TODO: https://github.com/KhronosGroup/glslang/issues/703:
314 // glslang applies Restrict to structure members.
315 //"Restrict",
316 "Aliased", "Constant", "Uniform", "SaturatedConversion", "Index 0",
317 "Binding 0", "DescriptorSet 0", "FuncParamAttr Zext",
318 "FPRoundingMode RTE", "FPFastMathMode None",
319 "LinkageAttributes \"ext\" Import", "NoContraction",
320 "InputAttachmentIndex 0", "Alignment 4", "MaxByteOffset 4",
321 "AlignmentId %float", "MaxByteOffsetId %float", "NoSignedWrap",
322 "NoUnsignedWrap", "NonUniform", "RestrictPointer", "AliasedPointer",
323 "CounterBuffer %float"));
324
325 using StructDecorations = spvtest::ValidateBase<std::string>;
326
TEST_P(StructDecorations,Struct)327 TEST_P(StructDecorations, Struct) {
328 const std::string deco = GetParam();
329 const std::string text = R"(
330 OpCapability Shader
331 OpCapability Kernel
332 OpCapability Linkage
333 OpMemoryModel Logical GLSL450
334 OpDecorate %struct )" + deco +
335 R"(
336 %struct = OpTypeStruct
337 )";
338
339 CompileSuccessfully(text);
340 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
341 }
342
TEST_P(StructDecorations,OtherType)343 TEST_P(StructDecorations, OtherType) {
344 const std::string deco = GetParam();
345 const std::string text = R"(
346 OpCapability Shader
347 OpCapability Kernel
348 OpCapability Linkage
349 OpMemoryModel Logical GLSL450
350 OpDecorate %int )" + deco + R"(
351 %int = OpTypeInt 32 0
352 )";
353
354 CompileSuccessfully(text);
355 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
356 EXPECT_THAT(getDiagnosticString(), HasSubstr("must be a structure type"));
357 }
358
TEST_P(StructDecorations,Variable)359 TEST_P(StructDecorations, Variable) {
360 const std::string deco = GetParam();
361 const std::string text = R"(
362 OpCapability Shader
363 OpCapability Kernel
364 OpCapability Linkage
365 OpMemoryModel Logical GLSL450
366 OpDecorate %var )" + deco + R"(
367 %int = OpTypeInt 32 0
368 %ptr = OpTypePointer Private %int
369 %var = OpVariable %ptr Private
370 )";
371
372 CompileSuccessfully(text);
373 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
374 EXPECT_THAT(getDiagnosticString(), HasSubstr("must be a structure type"));
375 }
376
TEST_P(StructDecorations,FunctionParameter)377 TEST_P(StructDecorations, FunctionParameter) {
378 const auto deco = GetParam();
379 const std::string text = R"(
380 OpCapability Shader
381 OpCapability Kernel
382 OpCapability Linkage
383 OpMemoryModel Logical GLSL450
384 OpDecorate %func LinkageAttributes "import" Import
385 OpDecorate %param )" + deco +
386 R"(
387 %int = OpTypeInt 32 0
388 %void = OpTypeVoid
389 %fn = OpTypeFunction %void %int
390 %func = OpFunction %void None %fn
391 %param = OpFunctionParameter %int
392 OpFunctionEnd
393 )";
394
395 CompileSuccessfully(text);
396 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
397 EXPECT_THAT(getDiagnosticString(), HasSubstr("must be a structure type"));
398 }
399
TEST_P(StructDecorations,Constant)400 TEST_P(StructDecorations, Constant) {
401 const std::string deco = GetParam();
402 const std::string text = R"(
403 OpCapability Shader
404 OpCapability Kernel
405 OpCapability Linkage
406 OpMemoryModel Logical GLSL450
407 OpDecorate %int_0 )" + deco +
408 R"(
409 %int = OpTypeInt 32 0
410 %int_0 = OpConstant %int 0
411 )";
412
413 CompileSuccessfully(text);
414 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
415 EXPECT_THAT(getDiagnosticString(), HasSubstr("must be a structure type"));
416 }
417
418 INSTANTIATE_TEST_SUITE_P(ValidateStructDecorations, StructDecorations,
419 Values("Block", "BufferBlock", "GLSLShared",
420 "GLSLPacked", "CPacked"));
421
422 using ArrayDecorations = spvtest::ValidateBase<std::string>;
423
TEST_P(ArrayDecorations,Array)424 TEST_P(ArrayDecorations, Array) {
425 const auto deco = GetParam();
426 const std::string text = R"(
427 OpCapability Shader
428 OpCapability Linkage
429 OpMemoryModel Logical GLSL450
430 OpDecorate %array )" + deco +
431 R"(
432 %int = OpTypeInt 32 0
433 %int_4 = OpConstant %int 4
434 %array = OpTypeArray %int %int_4
435 )";
436
437 CompileSuccessfully(text);
438 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
439 }
440
TEST_P(ArrayDecorations,RuntimeArray)441 TEST_P(ArrayDecorations, RuntimeArray) {
442 const auto deco = GetParam();
443 const std::string text = R"(
444 OpCapability Shader
445 OpCapability Linkage
446 OpMemoryModel Logical GLSL450
447 OpDecorate %array )" + deco +
448 R"(
449 %int = OpTypeInt 32 0
450 %array = OpTypeRuntimeArray %int
451 )";
452
453 CompileSuccessfully(text);
454 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
455 }
456
TEST_P(ArrayDecorations,Pointer)457 TEST_P(ArrayDecorations, Pointer) {
458 const auto deco = GetParam();
459 const std::string text = R"(
460 OpCapability Shader
461 OpCapability Linkage
462 OpMemoryModel Logical GLSL450
463 OpDecorate %ptr )" + deco + R"(
464 %int = OpTypeInt 32 0
465 %ptr = OpTypePointer Workgroup %int
466 )";
467
468 CompileSuccessfully(text);
469 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
470 }
471
TEST_P(ArrayDecorations,Struct)472 TEST_P(ArrayDecorations, Struct) {
473 const auto deco = GetParam();
474 const std::string text = R"(
475 OpCapability Shader
476 OpCapability Linkage
477 OpMemoryModel Logical GLSL450
478 OpDecorate %struct )" + deco +
479 R"(
480 %int = OpTypeInt 32 0
481 %struct = OpTypeStruct %int
482 )";
483
484 CompileSuccessfully(text);
485 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
486 EXPECT_THAT(getDiagnosticString(),
487 HasSubstr("must be an array or pointer type"));
488 }
489
TEST_P(ArrayDecorations,Variable)490 TEST_P(ArrayDecorations, Variable) {
491 const auto deco = GetParam();
492 const std::string text = R"(
493 OpCapability Shader
494 OpCapability Linkage
495 OpMemoryModel Logical GLSL450
496 OpDecorate %var )" + deco + R"(
497 %int = OpTypeInt 32 0
498 %ptr = OpTypePointer Private %int
499 %var = OpVariable %ptr Private
500 )";
501
502 CompileSuccessfully(text);
503 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
504 EXPECT_THAT(getDiagnosticString(),
505 HasSubstr("must be an array or pointer type"));
506 }
507
TEST_P(ArrayDecorations,FunctionParameter)508 TEST_P(ArrayDecorations, FunctionParameter) {
509 const auto deco = GetParam();
510 const std::string text = R"(
511 OpCapability Shader
512 OpCapability Linkage
513 OpMemoryModel Logical GLSL450
514 OpDecorate %func LinkageAttributes "import" Import
515 OpDecorate %param )" + deco +
516 R"(
517 %int = OpTypeInt 32 0
518 %void = OpTypeVoid
519 %fn = OpTypeFunction %void %int
520 %func = OpFunction %void None %fn
521 %param = OpFunctionParameter %int
522 OpFunctionEnd
523 )";
524
525 CompileSuccessfully(text);
526 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
527 EXPECT_THAT(getDiagnosticString(),
528 HasSubstr("must be an array or pointer type"));
529 }
530
TEST_P(ArrayDecorations,Constant)531 TEST_P(ArrayDecorations, Constant) {
532 const auto deco = GetParam();
533 const std::string text = R"(
534 OpCapability Shader
535 OpCapability Linkage
536 OpMemoryModel Logical GLSL450
537 OpDecorate %null )" + deco +
538 R"(
539 %int = OpTypeInt 32 0
540 %int_4 = OpConstant %int 4
541 %array = OpTypeArray %int %int_4
542 %null = OpConstantNull %array
543 )";
544
545 CompileSuccessfully(text);
546 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
547 EXPECT_THAT(getDiagnosticString(),
548 HasSubstr("must be an array or pointer type"));
549 }
550
551 INSTANTIATE_TEST_SUITE_P(ValidateArrayDecorations, ArrayDecorations,
552 Values("ArrayStride 4"));
553
554 using BuiltInDecorations = spvtest::ValidateBase<std::string>;
555
TEST_P(BuiltInDecorations,Variable)556 TEST_P(BuiltInDecorations, Variable) {
557 const auto deco = GetParam();
558 const std::string text = R"(
559 OpCapability Shader
560 OpCapability Linkage
561 OpMemoryModel Logical GLSL450
562 OpDecorate %var BuiltIn )" +
563 deco + R"(
564 %int = OpTypeInt 32 0
565 %ptr = OpTypePointer Input %int
566 %var = OpVariable %ptr Input
567 )";
568
569 CompileSuccessfully(text);
570 if (deco != "WorkgroupSize") {
571 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
572 } else {
573 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
574 EXPECT_THAT(getDiagnosticString(),
575 HasSubstr("must be a constant for WorkgroupSize"));
576 }
577 }
578
TEST_P(BuiltInDecorations,IntegerType)579 TEST_P(BuiltInDecorations, IntegerType) {
580 const auto deco = GetParam();
581 const std::string text = R"(
582 OpCapability Shader
583 OpCapability Linkage
584 OpMemoryModel Logical GLSL450
585 OpDecorate %int BuiltIn )" +
586 deco + R"(
587 %int = OpTypeInt 32 0
588 )";
589
590 CompileSuccessfully(text);
591 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
592 EXPECT_THAT(getDiagnosticString(),
593 HasSubstr("BuiltIns can only target variables, structure members "
594 "or constants"));
595 }
596
TEST_P(BuiltInDecorations,FunctionParameter)597 TEST_P(BuiltInDecorations, FunctionParameter) {
598 const auto deco = GetParam();
599 const std::string text = R"(
600 OpCapability Shader
601 OpCapability Linkage
602 OpMemoryModel Logical GLSL450
603 OpDecorate %func LinkageAttributes "import" Import
604 OpDecorate %param BuiltIn )" +
605 deco + R"(
606 %int = OpTypeInt 32 0
607 %void = OpTypeVoid
608 %fn = OpTypeFunction %void %int
609 %func = OpFunction %void None %fn
610 %param = OpFunctionParameter %int
611 OpFunctionEnd
612 )";
613
614 CompileSuccessfully(text);
615 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
616 EXPECT_THAT(getDiagnosticString(),
617 HasSubstr("BuiltIns can only target variables, structure members "
618 "or constants"));
619 }
620
TEST_P(BuiltInDecorations,Constant)621 TEST_P(BuiltInDecorations, Constant) {
622 const auto deco = GetParam();
623 const std::string text = R"(
624 OpCapability Shader
625 OpCapability Linkage
626 OpMemoryModel Logical GLSL450
627 OpDecorate %const BuiltIn )" +
628 deco + R"(
629 %int = OpTypeInt 32 0
630 %int3 = OpTypeVector %int 3
631 %int_1 = OpConstant %int 1
632 %const = OpConstantComposite %int3 %int_1 %int_1 %int_1
633 )";
634
635 CompileSuccessfully(text);
636 if (deco == "WorkgroupSize") {
637 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
638 } else {
639 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
640 EXPECT_THAT(getDiagnosticString(), HasSubstr("must be a variable"));
641 }
642 }
643
TEST_P(BuiltInDecorations,SpecConstant)644 TEST_P(BuiltInDecorations, SpecConstant) {
645 const auto deco = GetParam();
646 const std::string text = R"(
647 OpCapability Shader
648 OpCapability Linkage
649 OpMemoryModel Logical GLSL450
650 OpDecorate %const BuiltIn )" +
651 deco + R"(
652 %int = OpTypeInt 32 0
653 %int3 = OpTypeVector %int 3
654 %int_1 = OpConstant %int 1
655 %const = OpSpecConstantComposite %int3 %int_1 %int_1 %int_1
656 )";
657
658 CompileSuccessfully(text);
659 if (deco == "WorkgroupSize") {
660 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
661 } else {
662 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
663 EXPECT_THAT(getDiagnosticString(), HasSubstr("must be a variable"));
664 }
665 }
666
667 INSTANTIATE_TEST_SUITE_P(ValidateBuiltInDecorations, BuiltInDecorations,
668 Values("Position", "PointSize", "VertexId",
669 "InstanceId", "FragCoord", "FrontFacing",
670 "NumWorkgroups", "WorkgroupSize",
671 "LocalInvocationId", "GlobalInvocationId"));
672
673 using MemoryObjectDecorations = spvtest::ValidateBase<std::string>;
674
TEST_P(MemoryObjectDecorations,Variable)675 TEST_P(MemoryObjectDecorations, Variable) {
676 const auto deco = GetParam();
677 const std::string text = R"(
678 OpCapability Shader
679 OpCapability Linkage
680 OpCapability SampleRateShading
681 OpCapability TransformFeedback
682 OpCapability GeometryStreams
683 OpCapability Tessellation
684 OpCapability PhysicalStorageBufferAddresses
685 OpExtension "SPV_KHR_physical_storage_buffer"
686 OpMemoryModel Logical GLSL450
687 OpDecorate %var )" + deco + R"(
688 %float = OpTypeFloat 32
689 %ptr = OpTypePointer Input %float
690 %var = OpVariable %ptr Input
691 )";
692
693 CompileSuccessfully(text);
694 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
695 }
696
TEST_P(MemoryObjectDecorations,FunctionParameterGood)697 TEST_P(MemoryObjectDecorations, FunctionParameterGood) {
698 const auto deco = GetParam();
699 const std::string text = R"(
700 OpCapability Shader
701 OpCapability Linkage
702 OpCapability SampleRateShading
703 OpCapability TransformFeedback
704 OpCapability GeometryStreams
705 OpCapability Tessellation
706 OpCapability PhysicalStorageBufferAddresses
707 OpExtension "SPV_KHR_physical_storage_buffer"
708 OpMemoryModel Logical GLSL450
709 OpDecorate %func LinkageAttributes "import" Import
710 OpDecorate %param )" + deco +
711 R"(
712 %float = OpTypeFloat 32
713 %ptr = OpTypePointer Input %float
714 %void = OpTypeVoid
715 %fn = OpTypeFunction %void %ptr
716 %func = OpFunction %void None %fn
717 %param = OpFunctionParameter %ptr
718 OpFunctionEnd
719 )";
720
721 CompileSuccessfully(text);
722 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
723 }
724
TEST_P(MemoryObjectDecorations,FunctionParameterNotAPointer)725 TEST_P(MemoryObjectDecorations, FunctionParameterNotAPointer) {
726 const auto deco = GetParam();
727 const std::string text = R"(
728 OpCapability Shader
729 OpCapability Linkage
730 OpCapability SampleRateShading
731 OpCapability TransformFeedback
732 OpCapability GeometryStreams
733 OpCapability Tessellation
734 OpCapability PhysicalStorageBufferAddresses
735 OpExtension "SPV_KHR_physical_storage_buffer"
736 OpMemoryModel Logical GLSL450
737 OpDecorate %func LinkageAttributes "import" Import
738 OpDecorate %param )" + deco +
739 R"(
740 %float = OpTypeFloat 32
741 %void = OpTypeVoid
742 %fn = OpTypeFunction %void %float
743 %func = OpFunction %void None %fn
744 %param = OpFunctionParameter %float
745 OpFunctionEnd
746 )";
747
748 CompileSuccessfully(text);
749 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
750 EXPECT_THAT(getDiagnosticString(), HasSubstr("must be a pointer type"));
751 }
752
TEST_P(MemoryObjectDecorations,FloatType)753 TEST_P(MemoryObjectDecorations, FloatType) {
754 const auto deco = GetParam();
755 const std::string text = R"(
756 OpCapability Shader
757 OpCapability Linkage
758 OpCapability SampleRateShading
759 OpCapability TransformFeedback
760 OpCapability GeometryStreams
761 OpCapability Tessellation
762 OpCapability PhysicalStorageBufferAddresses
763 OpExtension "SPV_KHR_physical_storage_buffer"
764 OpMemoryModel Logical GLSL450
765 OpDecorate %float )" + deco +
766 R"(
767 %float = OpTypeFloat 32
768 )";
769
770 CompileSuccessfully(text);
771 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
772 EXPECT_THAT(getDiagnosticString(),
773 HasSubstr("must be a memory object declaration"));
774 }
775
TEST_P(MemoryObjectDecorations,Constant)776 TEST_P(MemoryObjectDecorations, Constant) {
777 const auto deco = GetParam();
778 const std::string text = R"(
779 OpCapability Shader
780 OpCapability Linkage
781 OpCapability SampleRateShading
782 OpCapability TransformFeedback
783 OpCapability GeometryStreams
784 OpCapability Tessellation
785 OpCapability PhysicalStorageBufferAddresses
786 OpExtension "SPV_KHR_physical_storage_buffer"
787 OpMemoryModel Logical GLSL450
788 OpDecorate %const )" + deco +
789 R"(
790 %float = OpTypeFloat 32
791 %const = OpConstant %float 0
792 )";
793
794 CompileSuccessfully(text);
795 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
796 EXPECT_THAT(getDiagnosticString(),
797 HasSubstr("must be a memory object declaration"));
798 }
799
800 // NonWritable and NonReadable are covered by other tests.
801 INSTANTIATE_TEST_SUITE_P(
802 ValidateMemoryObjectDecorations, MemoryObjectDecorations,
803 Values("NoPerspective", "Flat", "Patch", "Centroid", "Component 0",
804 "Sample", "Restrict", "Aliased", "Volatile", "Coherent", "Stream 0",
805 "XfbBuffer 1", "XfbStride 1", "AliasedPointer", "RestrictPointer"));
806
807 using VariableDecorations = spvtest::ValidateBase<std::string>;
808
TEST_P(VariableDecorations,Variable)809 TEST_P(VariableDecorations, Variable) {
810 const auto deco = GetParam();
811 const std::string text = R"(
812 OpCapability Shader
813 OpCapability Kernel
814 OpCapability Linkage
815 OpCapability InputAttachment
816 OpMemoryModel Logical GLSL450
817 OpDecorate %var )" + deco + R"(
818 %float = OpTypeFloat 32
819 %ptr = OpTypePointer Input %float
820 %var = OpVariable %ptr Input
821 )";
822
823 CompileSuccessfully(text);
824 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
825 }
826
TEST_P(VariableDecorations,FunctionParameter)827 TEST_P(VariableDecorations, FunctionParameter) {
828 const auto deco = GetParam();
829 const std::string text = R"(
830 OpCapability Shader
831 OpCapability Kernel
832 OpCapability Linkage
833 OpCapability InputAttachment
834 OpMemoryModel Logical GLSL450
835 OpDecorate %func LinkageAttributes "import" Import
836 OpDecorate %param )" + deco +
837 R"(
838 %float = OpTypeFloat 32
839 %void = OpTypeVoid
840 %fn = OpTypeFunction %void %float
841 %func = OpFunction %void None %fn
842 %param = OpFunctionParameter %float
843 OpFunctionEnd
844 )";
845
846 CompileSuccessfully(text);
847 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
848 EXPECT_THAT(getDiagnosticString(), HasSubstr("must be a variable"));
849 }
850
TEST_P(VariableDecorations,FloatType)851 TEST_P(VariableDecorations, FloatType) {
852 const auto deco = GetParam();
853 const std::string text = R"(
854 OpCapability Shader
855 OpCapability Kernel
856 OpCapability Linkage
857 OpCapability InputAttachment
858 OpMemoryModel Logical GLSL450
859 OpDecorate %float )" + deco +
860 R"(
861 %float = OpTypeFloat 32
862 )";
863
864 CompileSuccessfully(text);
865 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
866 EXPECT_THAT(getDiagnosticString(), HasSubstr("must be a variable"));
867 }
868
TEST_P(VariableDecorations,Constant)869 TEST_P(VariableDecorations, Constant) {
870 const auto deco = GetParam();
871 const std::string text = R"(
872 OpCapability Shader
873 OpCapability Kernel
874 OpCapability Linkage
875 OpCapability InputAttachment
876 OpMemoryModel Logical GLSL450
877 OpDecorate %const )" + deco +
878 R"(
879 %float = OpTypeFloat 32
880 %const = OpConstant %float 0
881 )";
882
883 CompileSuccessfully(text);
884 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
885 EXPECT_THAT(getDiagnosticString(), HasSubstr("must be a variable"));
886 }
887
888 INSTANTIATE_TEST_SUITE_P(ValidateVariableDecorations, VariableDecorations,
889 Values("Invariant", "Constant", "Location 0",
890 "Index 0", "Binding 0", "DescriptorSet 0"));
891
892 using VulkanIOStorageClass =
893 spvtest::ValidateBase<std::tuple<std::string, std::string>>;
894
TEST_P(VulkanIOStorageClass,Invalid)895 TEST_P(VulkanIOStorageClass, Invalid) {
896 const auto deco = std::get<0>(GetParam());
897 const auto sc = std::get<1>(GetParam());
898 const std::string text = R"(
899 OpCapability Shader
900 OpExtension "SPV_KHR_storage_buffer_storage_class"
901 OpMemoryModel Logical GLSL450
902 OpEntryPoint Fragment %main "main"
903 OpExecutionMode %main OriginUpperLeft
904 OpDecorate %var )" + deco + R"( 0
905 %void = OpTypeVoid
906 %float = OpTypeFloat 32
907 %ptr = OpTypePointer )" +
908 sc +
909 R"( %float
910 %var = OpVariable %ptr )" + sc +
911 R"(
912 %void_fn = OpTypeFunction %void
913 %main = OpFunction %void None %void_fn
914 %entry = OpLabel
915 OpReturn
916 OpFunctionEnd
917 )";
918
919 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
920 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
921 EXPECT_THAT(getDiagnosticString(),
922 AnyVUID("VUID-StandaloneSpirv-Location-06672"));
923 EXPECT_THAT(
924 getDiagnosticString(),
925 HasSubstr("decoration must not be applied to this storage class"));
926 }
927
928 INSTANTIATE_TEST_SUITE_P(ValidateVulkanIOStorageClass, VulkanIOStorageClass,
929 Combine(Values("Location", "Component"),
930 Values("StorageBuffer", "Uniform",
931 "UniformConstant", "Workgroup",
932 "Private")));
933
934 using VulkanResourceStorageClass =
935 spvtest::ValidateBase<std::tuple<std::string, std::string>>;
936
TEST_P(VulkanResourceStorageClass,Invalid)937 TEST_P(VulkanResourceStorageClass, Invalid) {
938 const auto deco = std::get<0>(GetParam());
939 const auto sc = std::get<1>(GetParam());
940 const std::string text = R"(
941 OpCapability Shader
942 OpMemoryModel Logical GLSL450
943 OpEntryPoint Fragment %main "main"
944 OpExecutionMode %main OriginUpperLeft
945 OpDecorate %var )" + deco + R"( 0
946 %void = OpTypeVoid
947 %float = OpTypeFloat 32
948 %ptr = OpTypePointer )" +
949 sc +
950 R"( %float
951 %var = OpVariable %ptr )" + sc +
952 R"(
953 %void_fn = OpTypeFunction %void
954 %main = OpFunction %void None %void_fn
955 %entry = OpLabel
956 OpReturn
957 OpFunctionEnd
958 )";
959
960 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
961 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
962 EXPECT_THAT(getDiagnosticString(),
963 HasSubstr("VUID-StandaloneSpirv-DescriptorSet-06491"));
964 EXPECT_THAT(getDiagnosticString(),
965 HasSubstr("must be in the StorageBuffer, Uniform, or "
966 "UniformConstant storage class"));
967 }
968
969 INSTANTIATE_TEST_SUITE_P(ValidateVulkanResourceStorageClass,
970 VulkanResourceStorageClass,
971 Combine(Values("DescriptorSet", "Binding"),
972 Values("Private", "Input", "Output",
973 "Workgroup")));
974
975 using VulkanInterpolationStorageClass = spvtest::ValidateBase<std::string>;
976
TEST_P(VulkanInterpolationStorageClass,Input)977 TEST_P(VulkanInterpolationStorageClass, Input) {
978 const auto deco = GetParam();
979 const std::string text = R"(
980 OpCapability Shader
981 OpCapability SampleRateShading
982 OpMemoryModel Logical GLSL450
983 OpEntryPoint Fragment %main "main"
984 OpExecutionMode %main OriginUpperLeft
985 OpDecorate %var )" + deco + R"(
986 %void = OpTypeVoid
987 %float = OpTypeFloat 32
988 %void_fn = OpTypeFunction %void
989 %ptr = OpTypePointer Input %float
990 %var = OpVariable %ptr Input
991 %main = OpFunction %void None %void_fn
992 %entry = OpLabel
993 OpReturn
994 OpFunctionEnd
995 )";
996
997 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
998 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
999 }
1000
TEST_P(VulkanInterpolationStorageClass,Output)1001 TEST_P(VulkanInterpolationStorageClass, Output) {
1002 const auto deco = GetParam();
1003 const std::string text = R"(
1004 OpCapability Shader
1005 OpCapability SampleRateShading
1006 OpMemoryModel Logical GLSL450
1007 OpEntryPoint Vertex %main "main"
1008 OpDecorate %var )" + deco + R"(
1009 %void = OpTypeVoid
1010 %float = OpTypeFloat 32
1011 %void_fn = OpTypeFunction %void
1012 %ptr = OpTypePointer Output %float
1013 %var = OpVariable %ptr Output
1014 %main = OpFunction %void None %void_fn
1015 %entry = OpLabel
1016 OpReturn
1017 OpFunctionEnd
1018 )";
1019
1020 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1021 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1022 }
1023
TEST_P(VulkanInterpolationStorageClass,Private)1024 TEST_P(VulkanInterpolationStorageClass, Private) {
1025 const auto deco = GetParam();
1026 const std::string text = R"(
1027 OpCapability Shader
1028 OpCapability SampleRateShading
1029 OpMemoryModel Logical GLSL450
1030 OpEntryPoint Fragment %main "main"
1031 OpExecutionMode %main OriginUpperLeft
1032 OpDecorate %var )" + deco + R"(
1033 %void = OpTypeVoid
1034 %float = OpTypeFloat 32
1035 %void_fn = OpTypeFunction %void
1036 %ptr = OpTypePointer Private %float
1037 %var = OpVariable %ptr Private
1038 %main = OpFunction %void None %void_fn
1039 %entry = OpLabel
1040 OpReturn
1041 OpFunctionEnd
1042 )";
1043
1044 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1045 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1046 EXPECT_THAT(getDiagnosticString(),
1047 HasSubstr("storage class must be Input or Output"));
1048 EXPECT_THAT(getDiagnosticString(),
1049 HasSubstr("[VUID-StandaloneSpirv-Flat-04670"));
1050 }
1051
TEST_P(VulkanInterpolationStorageClass,Uniform)1052 TEST_P(VulkanInterpolationStorageClass, Uniform) {
1053 const auto deco = GetParam();
1054 const std::string text = R"(
1055 OpCapability Shader
1056 OpCapability SampleRateShading
1057 OpMemoryModel Logical GLSL450
1058 OpEntryPoint Fragment %main "main"
1059 OpExecutionMode %main OriginUpperLeft
1060 OpDecorate %var )" + deco + R"(
1061 OpDecorate %var Binding 0
1062 OpDecorate %var DescriptorSet 0
1063 %void = OpTypeVoid
1064 %float = OpTypeFloat 32
1065 %void_fn = OpTypeFunction %void
1066 %ptr = OpTypePointer Uniform %float
1067 %var = OpVariable %ptr Uniform
1068 %main = OpFunction %void None %void_fn
1069 %entry = OpLabel
1070 OpReturn
1071 OpFunctionEnd
1072 )";
1073
1074 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1075 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1076 EXPECT_THAT(getDiagnosticString(),
1077 HasSubstr("storage class must be Input or Output"));
1078 EXPECT_THAT(getDiagnosticString(),
1079 HasSubstr("[VUID-StandaloneSpirv-Flat-04670"));
1080 }
1081
TEST_P(VulkanInterpolationStorageClass,StorageBuffer)1082 TEST_P(VulkanInterpolationStorageClass, StorageBuffer) {
1083 const auto deco = GetParam();
1084 const std::string text = R"(
1085 OpCapability Shader
1086 OpCapability SampleRateShading
1087 OpExtension "SPV_KHR_storage_buffer_storage_class"
1088 OpMemoryModel Logical GLSL450
1089 OpEntryPoint Fragment %main "main"
1090 OpExecutionMode %main OriginUpperLeft
1091 OpDecorate %var )" + deco + R"(
1092 OpDecorate %var Binding 0
1093 OpDecorate %var DescriptorSet 0
1094 %void = OpTypeVoid
1095 %float = OpTypeFloat 32
1096 %void_fn = OpTypeFunction %void
1097 %ptr = OpTypePointer StorageBuffer %float
1098 %var = OpVariable %ptr StorageBuffer
1099 %main = OpFunction %void None %void_fn
1100 %entry = OpLabel
1101 OpReturn
1102 OpFunctionEnd
1103 )";
1104
1105 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1106 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1107 EXPECT_THAT(getDiagnosticString(),
1108 HasSubstr("storage class must be Input or Output"));
1109 EXPECT_THAT(getDiagnosticString(),
1110 HasSubstr("[VUID-StandaloneSpirv-Flat-04670"));
1111 }
1112
1113 INSTANTIATE_TEST_SUITE_P(ValidateVulkanInterpolationStorageClass,
1114 VulkanInterpolationStorageClass,
1115 Values("Flat", "NoPerspective", "Centroid", "Sample"));
1116
1117 } // namespace
1118 } // namespace val
1119 } // namespace spvtools
1120