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