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