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