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