• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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