1// Copyright (c) 2015-2016 The Khronos Group Inc.
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 Logical Layout
16
17#include <sstream>
18#include <string>
19#include <tuple>
20#include <utility>
21#include <vector>
22
23#include "gmock/gmock.h"
24#include "source/assembly_grammar.h"
25#include "source/spirv_target_env.h"
26#include "spirv-tools/libspirv.h"
27#include "test/test_fixture.h"
28#include "test/unit_spirv.h"
29#include "test/val/val_fixtures.h"
30
31namespace spvtools {
32namespace val {
33namespace {
34
35using spvtest::ScopedContext;
36using testing::Combine;
37using testing::Eq;
38using testing::HasSubstr;
39using testing::Values;
40using testing::ValuesIn;
41
42// Parameter for validation test fixtures.  The first std::string is a
43// capability name that will begin the assembly under test, the second the
44// remainder assembly, and the std::vector at the end determines whether the
45// test expects success or failure.  See below for details and convenience
46// methods to access each one.
47//
48// The assembly to test is composed from a variable top line and a fixed
49// remainder.  The top line will be an OpCapability instruction, while the
50// remainder will be some assembly text that succeeds or fails to assemble
51// depending on which capability was chosen.  For instance, the following will
52// succeed:
53//
54// OpCapability Pipes ; implies Kernel
55// OpLifetimeStop %1 0 ; requires Kernel
56//
57// and the following will fail:
58//
59// OpCapability Kernel
60// %1 = OpTypeNamedBarrier ; requires NamedBarrier
61//
62// So how does the test parameter capture which capabilities should cause
63// success and which shouldn't?  The answer is in the last element: it's a
64// std::vector of capabilities that make the remainder assembly succeed.  So if
65// the first-line capability exists in that std::vector, success is expected;
66// otherwise, failure is expected in the tests.
67//
68// We will use testing::Combine() to vary the first line: when we combine
69// AllCapabilities() with a single remainder assembly, we generate enough test
70// cases to try the assembly with every possible capability that could be
71// declared. However, Combine() only produces tuples -- it cannot produce, say,
72// a struct.  Therefore, this type must be a tuple.
73using CapTestParameter =
74    std::tuple<std::string, std::pair<std::string, std::vector<std::string>>>;
75
76const std::string& Capability(const CapTestParameter& p) {
77  return std::get<0>(p);
78}
79const std::string& Remainder(const CapTestParameter& p) {
80  return std::get<1>(p).first;
81}
82const std::vector<std::string>& MustSucceed(const CapTestParameter& p) {
83  return std::get<1>(p).second;
84}
85
86// Creates assembly to test from p.
87std::string MakeAssembly(const CapTestParameter& p) {
88  std::ostringstream ss;
89  const std::string& capability = Capability(p);
90  if (!capability.empty()) {
91    ss << "OpCapability " << capability << "\n";
92  }
93  ss << Remainder(p);
94  return ss.str();
95}
96
97// Expected validation result for p.
98spv_result_t ExpectedResult(const CapTestParameter& p) {
99  const auto& caps = MustSucceed(p);
100  auto found = find(begin(caps), end(caps), Capability(p));
101  return (found == end(caps)) ? SPV_ERROR_INVALID_CAPABILITY : SPV_SUCCESS;
102}
103
104// Assembles using v1.0, unless the parameter's capability requires v1.1.
105using ValidateCapability = spvtest::ValidateBase<CapTestParameter>;
106
107// Always assembles using v1.1.
108using ValidateCapabilityV11 = spvtest::ValidateBase<CapTestParameter>;
109
110// Always assembles using Vulkan 1.0.
111// TODO(dneto): Refactor all these tests to scale better across environments.
112using ValidateCapabilityVulkan10 = spvtest::ValidateBase<CapTestParameter>;
113// Always assembles using OpenGL 4.0.
114using ValidateCapabilityOpenGL40 = spvtest::ValidateBase<CapTestParameter>;
115// Always assembles using Vulkan 1.1.
116using ValidateCapabilityVulkan11 = spvtest::ValidateBase<CapTestParameter>;
117// Always assembles using Vulkan 1.2.
118using ValidateCapabilityVulkan12 = spvtest::ValidateBase<CapTestParameter>;
119
120TEST_F(ValidateCapability, Default) {
121  const char str[] = R"(
122            OpCapability Kernel
123            OpCapability Linkage
124            OpCapability Matrix
125            OpMemoryModel Logical OpenCL
126%f32      = OpTypeFloat 32
127%vec3     = OpTypeVector %f32 3
128%mat33    = OpTypeMatrix %vec3 3
129)";
130
131  CompileSuccessfully(str);
132  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
133}
134
135// clang-format off
136const std::vector<std::string>& AllCapabilities() {
137  static const auto r = new std::vector<std::string>{
138    "",
139    "Matrix",
140    "Shader",
141    "Geometry",
142    "Tessellation",
143    "Addresses",
144    "Linkage",
145    "Kernel",
146    "Vector16",
147    "Float16Buffer",
148    "Float16",
149    "Float64",
150    "Int64",
151    "Int64Atomics",
152    "ImageBasic",
153    "ImageReadWrite",
154    "ImageMipmap",
155    "Pipes",
156    "Groups",
157    "DeviceEnqueue",
158    "LiteralSampler",
159    "AtomicStorage",
160    "Int16",
161    "TessellationPointSize",
162    "GeometryPointSize",
163    "ImageGatherExtended",
164    "StorageImageMultisample",
165    "UniformBufferArrayDynamicIndexing",
166    "SampledImageArrayDynamicIndexing",
167    "StorageBufferArrayDynamicIndexing",
168    "StorageImageArrayDynamicIndexing",
169    "ClipDistance",
170    "CullDistance",
171    "ImageCubeArray",
172    "SampleRateShading",
173    "ImageRect",
174    "SampledRect",
175    "GenericPointer",
176    "Int8",
177    "InputAttachment",
178    "SparseResidency",
179    "MinLod",
180    "Sampled1D",
181    "Image1D",
182    "SampledCubeArray",
183    "SampledBuffer",
184    "ImageBuffer",
185    "ImageMSArray",
186    "StorageImageExtendedFormats",
187    "ImageQuery",
188    "DerivativeControl",
189    "InterpolationFunction",
190    "TransformFeedback",
191    "GeometryStreams",
192    "StorageImageReadWithoutFormat",
193    "StorageImageWriteWithoutFormat",
194    "MultiViewport",
195    "SubgroupDispatch",
196    "NamedBarrier",
197    "PipeStorage",
198    "GroupNonUniform",
199    "GroupNonUniformVote",
200    "GroupNonUniformArithmetic",
201    "GroupNonUniformBallot",
202    "GroupNonUniformShuffle",
203    "GroupNonUniformShuffleRelative",
204    "GroupNonUniformClustered",
205    "GroupNonUniformQuad",
206    "DrawParameters",
207    "StorageBuffer16BitAccess",
208    "StorageUniformBufferBlock16",
209    "UniformAndStorageBuffer16BitAccess",
210    "StorageUniform16",
211    "StoragePushConstant16",
212    "StorageInputOutput16",
213    "DeviceGroup",
214    "MultiView",
215    "VariablePointersStorageBuffer",
216    "VariablePointers"};
217  return *r;
218}
219
220const std::vector<std::string>& AllSpirV15Capabilities() {
221  static const auto r = new std::vector<std::string>{
222    "",
223    "Matrix",
224    "Shader",
225    "Geometry",
226    "Tessellation",
227    "Addresses",
228    "Linkage",
229    "Kernel",
230    "Vector16",
231    "Float16Buffer",
232    "Float16",
233    "Float64",
234    "Int64",
235    "Int64Atomics",
236    "ImageBasic",
237    "ImageReadWrite",
238    "ImageMipmap",
239    "Pipes",
240    "Groups",
241    "DeviceEnqueue",
242    "LiteralSampler",
243    "AtomicStorage",
244    "Int16",
245    "TessellationPointSize",
246    "GeometryPointSize",
247    "ImageGatherExtended",
248    "StorageImageMultisample",
249    "UniformBufferArrayDynamicIndexing",
250    "SampledImageArrayDynamicIndexing",
251    "StorageBufferArrayDynamicIndexing",
252    "StorageImageArrayDynamicIndexing",
253    "ClipDistance",
254    "CullDistance",
255    "ImageCubeArray",
256    "SampleRateShading",
257    "ImageRect",
258    "SampledRect",
259    "GenericPointer",
260    "Int8",
261    "InputAttachment",
262    "SparseResidency",
263    "MinLod",
264    "Sampled1D",
265    "Image1D",
266    "SampledCubeArray",
267    "SampledBuffer",
268    "ImageBuffer",
269    "ImageMSArray",
270    "StorageImageExtendedFormats",
271    "ImageQuery",
272    "DerivativeControl",
273    "InterpolationFunction",
274    "TransformFeedback",
275    "GeometryStreams",
276    "StorageImageReadWithoutFormat",
277    "StorageImageWriteWithoutFormat",
278    "MultiViewport",
279    "SubgroupDispatch",
280    "NamedBarrier",
281    "PipeStorage",
282    "GroupNonUniform",
283    "GroupNonUniformVote",
284    "GroupNonUniformArithmetic",
285    "GroupNonUniformBallot",
286    "GroupNonUniformShuffle",
287    "GroupNonUniformShuffleRelative",
288    "GroupNonUniformClustered",
289    "GroupNonUniformQuad",
290    "DrawParameters",
291    "StorageBuffer16BitAccess",
292    "StorageUniformBufferBlock16",
293    "UniformAndStorageBuffer16BitAccess",
294    "StorageUniform16",
295    "StoragePushConstant16",
296    "StorageInputOutput16",
297    "DeviceGroup",
298    "MultiView",
299    "VariablePointersStorageBuffer",
300    "VariablePointers",
301    "DenormPreserve",
302    "DenormFlushToZero",
303    "SignedZeroInfNanPreserve",
304    "RoundingModeRTE",
305    "RoundingModeRTZ",
306    // Omitted due to extra validation requirements on memory model.
307    //"VulkanMemoryModel",
308    //"VulkanMemoryModelDeviceScope",
309    "StorageBuffer8BitAccess",
310    "UniformAndStorageBuffer8BitAccess",
311    "StoragePushConstant8",
312    "ShaderViewportIndex",
313    "ShaderLayer",
314    "PhysicalStorageBufferAddresses",
315    "RuntimeDescriptorArray",
316    "UniformTexelBufferArrayDynamicIndexing",
317    "StorageTexelBufferArrayDynamicIndexing",
318    "UniformBufferArrayNonUniformIndexing",
319    "SampledImageArrayNonUniformIndexing",
320    "StorageBufferArrayNonUniformIndexing",
321    "StorageImageArrayNonUniformIndexing",
322    "InputAttachmentArrayNonUniformIndexing",
323    "UniformTexelBufferArrayNonUniformIndexing",
324    "StorageTexelBufferArrayNonUniformIndexing"};
325  return *r;
326}
327
328const std::vector<std::string>& AllSpirV10Capabilities() {
329  static const auto r = new std::vector<std::string>{
330    "",
331    "Matrix",
332    "Shader",
333    "Geometry",
334    "Tessellation",
335    "Addresses",
336    "Linkage",
337    "Kernel",
338    "Vector16",
339    "Float16Buffer",
340    "Float16",
341    "Float64",
342    "Int64",
343    "Int64Atomics",
344    "ImageBasic",
345    "ImageReadWrite",
346    "ImageMipmap",
347    "Pipes",
348    "Groups",
349    "DeviceEnqueue",
350    "LiteralSampler",
351    "AtomicStorage",
352    "Int16",
353    "TessellationPointSize",
354    "GeometryPointSize",
355    "ImageGatherExtended",
356    "StorageImageMultisample",
357    "UniformBufferArrayDynamicIndexing",
358    "SampledImageArrayDynamicIndexing",
359    "StorageBufferArrayDynamicIndexing",
360    "StorageImageArrayDynamicIndexing",
361    "ClipDistance",
362    "CullDistance",
363    "ImageCubeArray",
364    "SampleRateShading",
365    "ImageRect",
366    "SampledRect",
367    "GenericPointer",
368    "Int8",
369    "InputAttachment",
370    "SparseResidency",
371    "MinLod",
372    "Sampled1D",
373    "Image1D",
374    "SampledCubeArray",
375    "SampledBuffer",
376    "ImageBuffer",
377    "ImageMSArray",
378    "StorageImageExtendedFormats",
379    "ImageQuery",
380    "DerivativeControl",
381    "InterpolationFunction",
382    "TransformFeedback",
383    "GeometryStreams",
384    "StorageImageReadWithoutFormat",
385    "StorageImageWriteWithoutFormat",
386    "MultiViewport"};
387  return *r;
388}
389
390const std::vector<std::string>& AllVulkan10Capabilities() {
391  static const auto r = new std::vector<std::string>{
392    "",
393    "Matrix",
394    "Shader",
395    "InputAttachment",
396    "Sampled1D",
397    "Image1D",
398    "SampledBuffer",
399    "ImageBuffer",
400    "ImageQuery",
401    "DerivativeControl",
402    "Geometry",
403    "Tessellation",
404    "Float16",
405    "Float64",
406    "Int64",
407    "Int64Atomics",
408    "Int16",
409    "TessellationPointSize",
410    "GeometryPointSize",
411    "ImageGatherExtended",
412    "StorageImageMultisample",
413    "UniformBufferArrayDynamicIndexing",
414    "SampledImageArrayDynamicIndexing",
415    "StorageBufferArrayDynamicIndexing",
416    "StorageImageArrayDynamicIndexing",
417    "ClipDistance",
418    "CullDistance",
419    "ImageCubeArray",
420    "SampleRateShading",
421    "Int8",
422    "SparseResidency",
423    "MinLod",
424    "SampledCubeArray",
425    "ImageMSArray",
426    "StorageImageExtendedFormats",
427    "InterpolationFunction",
428    "StorageImageReadWithoutFormat",
429    "StorageImageWriteWithoutFormat",
430    "MultiViewport",
431    "TransformFeedback",
432    "GeometryStreams"};
433  return *r;
434}
435
436const std::vector<std::string>& AllVulkan11Capabilities() {
437  static const auto r = new std::vector<std::string>{
438    "",
439    "Matrix",
440    "Shader",
441    "InputAttachment",
442    "Sampled1D",
443    "Image1D",
444    "SampledBuffer",
445    "ImageBuffer",
446    "ImageQuery",
447    "DerivativeControl",
448    "Geometry",
449    "Tessellation",
450    "Float16",
451    "Float64",
452    "Int64",
453    "Int64Atomics",
454    "Int16",
455    "TessellationPointSize",
456    "GeometryPointSize",
457    "ImageGatherExtended",
458    "StorageImageMultisample",
459    "UniformBufferArrayDynamicIndexing",
460    "SampledImageArrayDynamicIndexing",
461    "StorageBufferArrayDynamicIndexing",
462    "StorageImageArrayDynamicIndexing",
463    "ClipDistance",
464    "CullDistance",
465    "ImageCubeArray",
466    "SampleRateShading",
467    "Int8",
468    "SparseResidency",
469    "MinLod",
470    "SampledCubeArray",
471    "ImageMSArray",
472    "StorageImageExtendedFormats",
473    "InterpolationFunction",
474    "StorageImageReadWithoutFormat",
475    "StorageImageWriteWithoutFormat",
476    "MultiViewport",
477    "GroupNonUniform",
478    "GroupNonUniformVote",
479    "GroupNonUniformArithmetic",
480    "GroupNonUniformBallot",
481    "GroupNonUniformShuffle",
482    "GroupNonUniformShuffleRelative",
483    "GroupNonUniformClustered",
484    "GroupNonUniformQuad",
485    "DrawParameters",
486    "StorageBuffer16BitAccess",
487    "StorageUniformBufferBlock16",
488    "UniformAndStorageBuffer16BitAccess",
489    "StorageUniform16",
490    "StoragePushConstant16",
491    "StorageInputOutput16",
492    "DeviceGroup",
493    "MultiView",
494    "VariablePointersStorageBuffer",
495    "VariablePointers",
496    "TransformFeedback",
497    "GeometryStreams"};
498  return *r;
499}
500
501const std::vector<std::string>& AllVulkan12Capabilities() {
502  static const auto r = new std::vector<std::string>{
503    "",
504    "Matrix",
505    "Shader",
506    "InputAttachment",
507    "Sampled1D",
508    "Image1D",
509    "SampledBuffer",
510    "ImageBuffer",
511    "ImageQuery",
512    "DerivativeControl",
513    "Geometry",
514    "Tessellation",
515    "Float16",
516    "Float64",
517    "Int64",
518    "Int64Atomics",
519    "Int16",
520    "TessellationPointSize",
521    "GeometryPointSize",
522    "ImageGatherExtended",
523    "StorageImageMultisample",
524    "UniformBufferArrayDynamicIndexing",
525    "SampledImageArrayDynamicIndexing",
526    "StorageBufferArrayDynamicIndexing",
527    "StorageImageArrayDynamicIndexing",
528    "ClipDistance",
529    "CullDistance",
530    "ImageCubeArray",
531    "SampleRateShading",
532    "Int8",
533    "SparseResidency",
534    "MinLod",
535    "SampledCubeArray",
536    "ImageMSArray",
537    "StorageImageExtendedFormats",
538    "InterpolationFunction",
539    "StorageImageReadWithoutFormat",
540    "StorageImageWriteWithoutFormat",
541    "MultiViewport",
542    "GroupNonUniform",
543    "GroupNonUniformVote",
544    "GroupNonUniformArithmetic",
545    "GroupNonUniformBallot",
546    "GroupNonUniformShuffle",
547    "GroupNonUniformShuffleRelative",
548    "GroupNonUniformClustered",
549    "GroupNonUniformQuad",
550    "DrawParameters",
551    "StorageBuffer16BitAccess",
552    "StorageUniformBufferBlock16",
553    "UniformAndStorageBuffer16BitAccess",
554    "StorageUniform16",
555    "StoragePushConstant16",
556    "StorageInputOutput16",
557    "DeviceGroup",
558    "MultiView",
559    "VariablePointersStorageBuffer",
560    "VariablePointers",
561    "TransformFeedback",
562    "GeometryStreams",
563    "DenormPreserve",
564    "DenormFlushToZero",
565    "SignedZeroInfNanPreserve",
566    "RoundingModeRTE",
567    "RoundingModeRTZ",
568    "VulkanMemoryModel",
569    "VulkanMemoryModelDeviceScope",
570    "StorageBuffer8BitAccess",
571    "UniformAndStorageBuffer8BitAccess",
572    "StoragePushConstant8",
573    "ShaderViewportIndex",
574    "ShaderLayer",
575    "PhysicalStorageBufferAddresses",
576    "RuntimeDescriptorArray",
577    "UniformTexelBufferArrayDynamicIndexing",
578    "StorageTexelBufferArrayDynamicIndexing",
579    "UniformBufferArrayNonUniformIndexing",
580    "SampledImageArrayNonUniformIndexing",
581    "StorageBufferArrayNonUniformIndexing",
582    "StorageImageArrayNonUniformIndexing",
583    "InputAttachmentArrayNonUniformIndexing",
584    "UniformTexelBufferArrayNonUniformIndexing",
585    "StorageTexelBufferArrayNonUniformIndexing"};
586  return *r;
587}
588
589const std::vector<std::string>& MatrixDependencies() {
590  static const auto r = new std::vector<std::string>{
591  "Matrix",
592  "Shader",
593  "Geometry",
594  "Tessellation",
595  "AtomicStorage",
596  "TessellationPointSize",
597  "GeometryPointSize",
598  "ImageGatherExtended",
599  "StorageImageMultisample",
600  "UniformBufferArrayDynamicIndexing",
601  "SampledImageArrayDynamicIndexing",
602  "StorageBufferArrayDynamicIndexing",
603  "StorageImageArrayDynamicIndexing",
604  "ClipDistance",
605  "CullDistance",
606  "ImageCubeArray",
607  "SampleRateShading",
608  "ImageRect",
609  "SampledRect",
610  "InputAttachment",
611  "SparseResidency",
612  "MinLod",
613  "SampledCubeArray",
614  "ImageMSArray",
615  "StorageImageExtendedFormats",
616  "ImageQuery",
617  "DerivativeControl",
618  "InterpolationFunction",
619  "TransformFeedback",
620  "GeometryStreams",
621  "StorageImageReadWithoutFormat",
622  "StorageImageWriteWithoutFormat",
623  "MultiViewport",
624  "DrawParameters",
625  "MultiView",
626  "VariablePointersStorageBuffer",
627  "VariablePointers"};
628  return *r;
629}
630
631const std::vector<std::string>& ShaderDependencies() {
632  static const auto r = new std::vector<std::string>{
633  "Shader",
634  "Geometry",
635  "Tessellation",
636  "AtomicStorage",
637  "TessellationPointSize",
638  "GeometryPointSize",
639  "ImageGatherExtended",
640  "StorageImageMultisample",
641  "UniformBufferArrayDynamicIndexing",
642  "SampledImageArrayDynamicIndexing",
643  "StorageBufferArrayDynamicIndexing",
644  "StorageImageArrayDynamicIndexing",
645  "ClipDistance",
646  "CullDistance",
647  "ImageCubeArray",
648  "SampleRateShading",
649  "ImageRect",
650  "SampledRect",
651  "InputAttachment",
652  "SparseResidency",
653  "MinLod",
654  "SampledCubeArray",
655  "ImageMSArray",
656  "StorageImageExtendedFormats",
657  "ImageQuery",
658  "DerivativeControl",
659  "InterpolationFunction",
660  "TransformFeedback",
661  "GeometryStreams",
662  "StorageImageReadWithoutFormat",
663  "StorageImageWriteWithoutFormat",
664  "MultiViewport",
665  "DrawParameters",
666  "MultiView",
667  "VariablePointersStorageBuffer",
668  "VariablePointers"};
669  return *r;
670}
671
672const std::vector<std::string>& TessellationDependencies() {
673  static const auto r = new std::vector<std::string>{
674  "Tessellation",
675  "TessellationPointSize"};
676  return *r;
677}
678
679const std::vector<std::string>& GeometryDependencies() {
680  static const auto r = new std::vector<std::string>{
681  "Geometry",
682  "GeometryPointSize",
683  "GeometryStreams",
684  "MultiViewport"};
685  return *r;
686}
687
688const std::vector<std::string>& GeometryTessellationDependencies() {
689  static const auto r = new std::vector<std::string>{
690  "Tessellation",
691  "TessellationPointSize",
692  "Geometry",
693  "GeometryPointSize",
694  "GeometryStreams",
695  "MultiViewport"};
696  return *r;
697}
698
699// Returns the names of capabilities that directly depend on Kernel,
700// plus itself.
701const std::vector<std::string>& KernelDependencies() {
702  static const auto r = new std::vector<std::string>{
703  "Kernel",
704  "Vector16",
705  "Float16Buffer",
706  "ImageBasic",
707  "ImageReadWrite",
708  "ImageMipmap",
709  "Pipes",
710  "DeviceEnqueue",
711  "LiteralSampler",
712  "SubgroupDispatch",
713  "NamedBarrier",
714  "PipeStorage"};
715  return *r;
716}
717
718const std::vector<std::string>& KernelAndGroupNonUniformDependencies() {
719  static const auto r = new std::vector<std::string>{
720  "Kernel",
721  "Vector16",
722  "Float16Buffer",
723  "ImageBasic",
724  "ImageReadWrite",
725  "ImageMipmap",
726  "Pipes",
727  "DeviceEnqueue",
728  "LiteralSampler",
729  "SubgroupDispatch",
730  "NamedBarrier",
731  "PipeStorage",
732  "GroupNonUniform",
733  "GroupNonUniformVote",
734  "GroupNonUniformArithmetic",
735  "GroupNonUniformBallot",
736  "GroupNonUniformShuffle",
737  "GroupNonUniformShuffleRelative",
738  "GroupNonUniformClustered",
739  "GroupNonUniformQuad"};
740  return *r;
741}
742
743const std::vector<std::string>& AddressesDependencies() {
744  static const auto r = new std::vector<std::string>{
745  "Addresses",
746  "GenericPointer"};
747  return *r;
748}
749
750const std::vector<std::string>& Sampled1DDependencies() {
751  static const auto r = new std::vector<std::string>{
752  "Sampled1D",
753  "Image1D"};
754  return *r;
755}
756
757const std::vector<std::string>& SampledRectDependencies() {
758  static const auto r = new std::vector<std::string>{
759  "SampledRect",
760  "ImageRect"};
761  return *r;
762}
763
764const std::vector<std::string>& SampledBufferDependencies() {
765  static const auto r = new std::vector<std::string>{
766  "SampledBuffer",
767  "ImageBuffer"};
768  return *r;
769}
770
771const char kOpenCLMemoryModel[] = \
772  " OpCapability Kernel"
773  " OpMemoryModel Logical OpenCL ";
774
775const char kGLSL450MemoryModel[] = \
776  " OpCapability Shader"
777  " OpMemoryModel Logical GLSL450 ";
778
779const char kVoidFVoid[] = \
780  " %void   = OpTypeVoid"
781  " %void_f = OpTypeFunction %void"
782  " %func   = OpFunction %void None %void_f"
783  " %label  = OpLabel"
784  "           OpReturn"
785  "           OpFunctionEnd ";
786
787const char kVoidFVoid2[] = \
788  " %void_f = OpTypeFunction %voidt"
789  " %func   = OpFunction %voidt None %void_f"
790  " %label  = OpLabel"
791  "           OpReturn"
792  "           OpFunctionEnd ";
793
794INSTANTIATE_TEST_SUITE_P(ExecutionModel, ValidateCapability,
795                        Combine(
796                            ValuesIn(AllCapabilities()),
797                            Values(
798std::make_pair(std::string(kOpenCLMemoryModel) +
799          " OpEntryPoint Vertex %func \"shader\"" +
800          std::string(kVoidFVoid), ShaderDependencies()),
801std::make_pair(std::string(kOpenCLMemoryModel) +
802          " OpEntryPoint TessellationControl %func \"shader\"" +
803          std::string(kVoidFVoid), TessellationDependencies()),
804std::make_pair(std::string(kOpenCLMemoryModel) +
805          " OpEntryPoint TessellationEvaluation %func \"shader\"" +
806          std::string(kVoidFVoid), TessellationDependencies()),
807std::make_pair(std::string(kOpenCLMemoryModel) +
808          " OpEntryPoint Geometry %func \"shader\"" +
809          " OpExecutionMode %func InputPoints" +
810          " OpExecutionMode %func OutputPoints" +
811          std::string(kVoidFVoid), GeometryDependencies()),
812std::make_pair(std::string(kOpenCLMemoryModel) +
813          " OpEntryPoint Fragment %func \"shader\"" +
814          " OpExecutionMode %func OriginUpperLeft" +
815          std::string(kVoidFVoid), ShaderDependencies()),
816std::make_pair(std::string(kOpenCLMemoryModel) +
817          " OpEntryPoint GLCompute %func \"shader\"" +
818          std::string(kVoidFVoid), ShaderDependencies()),
819std::make_pair(std::string(kGLSL450MemoryModel) +
820          " OpEntryPoint Kernel %func \"shader\"" +
821          std::string(kVoidFVoid), KernelDependencies())
822)));
823
824INSTANTIATE_TEST_SUITE_P(AddressingAndMemoryModel, ValidateCapability,
825                        Combine(
826                            ValuesIn(AllCapabilities()),
827                            Values(
828std::make_pair(" OpCapability Shader"
829          " OpMemoryModel Logical Simple"
830          " OpEntryPoint Vertex %func \"shader\"" +
831          std::string(kVoidFVoid),     AllCapabilities()),
832std::make_pair(" OpCapability Shader"
833          " OpMemoryModel Logical GLSL450"
834          " OpEntryPoint Vertex %func \"shader\"" +
835          std::string(kVoidFVoid),    AllCapabilities()),
836std::make_pair(" OpCapability Kernel"
837          " OpMemoryModel Logical OpenCL"
838          " OpEntryPoint Kernel %func \"compute\"" +
839          std::string(kVoidFVoid),     AllCapabilities()),
840std::make_pair(" OpCapability Shader"
841          " OpMemoryModel Physical32 Simple"
842          " OpEntryPoint Vertex %func \"shader\"" +
843          std::string(kVoidFVoid),  AddressesDependencies()),
844std::make_pair(" OpCapability Shader"
845          " OpMemoryModel Physical32 GLSL450"
846          " OpEntryPoint Vertex %func \"shader\"" +
847          std::string(kVoidFVoid), AddressesDependencies()),
848std::make_pair(" OpCapability Kernel"
849          " OpMemoryModel Physical32 OpenCL"
850          " OpEntryPoint Kernel %func \"compute\"" +
851          std::string(kVoidFVoid),  AddressesDependencies()),
852std::make_pair(" OpCapability Shader"
853          " OpMemoryModel Physical64 Simple"
854          " OpEntryPoint Vertex %func \"shader\"" +
855          std::string(kVoidFVoid),  AddressesDependencies()),
856std::make_pair(" OpCapability Shader"
857          " OpMemoryModel Physical64 GLSL450"
858          " OpEntryPoint Vertex %func \"shader\"" +
859          std::string(kVoidFVoid), AddressesDependencies()),
860std::make_pair(" OpCapability Kernel"
861          " OpMemoryModel Physical64 OpenCL"
862          " OpEntryPoint Kernel %func \"compute\"" +
863          std::string(kVoidFVoid),  AddressesDependencies())
864)));
865
866INSTANTIATE_TEST_SUITE_P(ExecutionMode, ValidateCapability,
867                        Combine(
868                            ValuesIn(AllCapabilities()),
869                            Values(
870std::make_pair(std::string(kOpenCLMemoryModel) +
871          "OpEntryPoint Geometry %func \"shader\" "
872          "OpExecutionMode %func Invocations 42" +
873          " OpExecutionMode %func InputPoints" +
874          " OpExecutionMode %func OutputPoints" +
875          std::string(kVoidFVoid), GeometryDependencies()),
876std::make_pair(std::string(kOpenCLMemoryModel) +
877          "OpEntryPoint TessellationControl %func \"shader\" "
878          "OpExecutionMode %func SpacingEqual" +
879          std::string(kVoidFVoid), TessellationDependencies()),
880std::make_pair(std::string(kOpenCLMemoryModel) +
881          "OpEntryPoint TessellationControl %func \"shader\" "
882          "OpExecutionMode %func SpacingFractionalEven" +
883          std::string(kVoidFVoid), TessellationDependencies()),
884std::make_pair(std::string(kOpenCLMemoryModel) +
885          "OpEntryPoint TessellationControl %func \"shader\" "
886          "OpExecutionMode %func SpacingFractionalOdd" +
887          std::string(kVoidFVoid), TessellationDependencies()),
888std::make_pair(std::string(kOpenCLMemoryModel) +
889          "OpEntryPoint TessellationControl %func \"shader\" "
890          "OpExecutionMode %func VertexOrderCw" +
891          std::string(kVoidFVoid), TessellationDependencies()),
892std::make_pair(std::string(kOpenCLMemoryModel) +
893          "OpEntryPoint TessellationControl %func \"shader\" "
894          "OpExecutionMode %func VertexOrderCcw" +
895          std::string(kVoidFVoid), TessellationDependencies()),
896std::make_pair(std::string(kOpenCLMemoryModel) +
897          "OpEntryPoint Fragment %func \"shader\" "
898          "OpExecutionMode %func PixelCenterInteger" +
899          " OpExecutionMode %func OriginUpperLeft" +
900          std::string(kVoidFVoid), ShaderDependencies()),
901std::make_pair(std::string(kOpenCLMemoryModel) +
902          "OpEntryPoint Fragment %func \"shader\" "
903          "OpExecutionMode %func OriginUpperLeft" +
904          std::string(kVoidFVoid), ShaderDependencies()),
905std::make_pair(std::string(kOpenCLMemoryModel) +
906          "OpEntryPoint Fragment %func \"shader\" "
907          "OpExecutionMode %func OriginLowerLeft" +
908          std::string(kVoidFVoid), ShaderDependencies()),
909std::make_pair(std::string(kOpenCLMemoryModel) +
910          "OpEntryPoint Fragment %func \"shader\" "
911          "OpExecutionMode %func EarlyFragmentTests" +
912          " OpExecutionMode %func OriginUpperLeft" +
913          std::string(kVoidFVoid), ShaderDependencies()),
914std::make_pair(std::string(kOpenCLMemoryModel) +
915          "OpEntryPoint TessellationControl %func \"shader\" "
916          "OpExecutionMode %func PointMode" +
917          std::string(kVoidFVoid), TessellationDependencies()),
918std::make_pair(std::string(kOpenCLMemoryModel) +
919          "OpEntryPoint Vertex %func \"shader\" "
920          "OpExecutionMode %func Xfb" +
921          std::string(kVoidFVoid), std::vector<std::string>{"TransformFeedback"}),
922std::make_pair(std::string(kOpenCLMemoryModel) +
923          "OpEntryPoint Fragment %func \"shader\" "
924          "OpExecutionMode %func DepthReplacing" +
925          " OpExecutionMode %func OriginUpperLeft" +
926          std::string(kVoidFVoid), ShaderDependencies()),
927std::make_pair(std::string(kOpenCLMemoryModel) +
928          "OpEntryPoint Fragment %func \"shader\" "
929          "OpExecutionMode %func DepthGreater" +
930          " OpExecutionMode %func OriginUpperLeft" +
931          std::string(kVoidFVoid), ShaderDependencies()),
932std::make_pair(std::string(kOpenCLMemoryModel) +
933          "OpEntryPoint Fragment %func \"shader\" "
934          "OpExecutionMode %func DepthLess" +
935          " OpExecutionMode %func OriginUpperLeft" +
936          std::string(kVoidFVoid), ShaderDependencies()),
937std::make_pair(std::string(kOpenCLMemoryModel) +
938          "OpEntryPoint Fragment %func \"shader\" "
939          "OpExecutionMode %func DepthUnchanged" +
940          " OpExecutionMode %func OriginUpperLeft" +
941          std::string(kVoidFVoid), ShaderDependencies()),
942std::make_pair(std::string(kOpenCLMemoryModel) +
943          "OpEntryPoint Kernel %func \"shader\" "
944          "OpExecutionMode %func LocalSize 42 42 42" +
945          std::string(kVoidFVoid), AllCapabilities()),
946std::make_pair(std::string(kGLSL450MemoryModel) +
947          "OpEntryPoint Kernel %func \"shader\" "
948          "OpExecutionMode %func LocalSizeHint 42 42 42" +
949          std::string(kVoidFVoid), KernelDependencies()),
950std::make_pair(std::string(kOpenCLMemoryModel) +
951          "OpEntryPoint Geometry %func \"shader\" "
952          "OpExecutionMode %func InputPoints" +
953          " OpExecutionMode %func OutputPoints" +
954          std::string(kVoidFVoid), GeometryDependencies()),
955std::make_pair(std::string(kOpenCLMemoryModel) +
956          "OpEntryPoint Geometry %func \"shader\" "
957          "OpExecutionMode %func InputLines" +
958          " OpExecutionMode %func OutputLineStrip" +
959          std::string(kVoidFVoid), GeometryDependencies()),
960std::make_pair(std::string(kOpenCLMemoryModel) +
961          "OpEntryPoint Geometry %func \"shader\" "
962          "OpExecutionMode %func InputLinesAdjacency" +
963          " OpExecutionMode %func OutputLineStrip" +
964          std::string(kVoidFVoid), GeometryDependencies()),
965std::make_pair(std::string(kOpenCLMemoryModel) +
966          "OpEntryPoint Geometry %func \"shader\" "
967          "OpExecutionMode %func Triangles" +
968          " OpExecutionMode %func OutputTriangleStrip" +
969          std::string(kVoidFVoid), GeometryDependencies()),
970std::make_pair(std::string(kOpenCLMemoryModel) +
971          "OpEntryPoint TessellationControl %func \"shader\" "
972          "OpExecutionMode %func Triangles" +
973          std::string(kVoidFVoid), TessellationDependencies()),
974std::make_pair(std::string(kOpenCLMemoryModel) +
975          "OpEntryPoint Geometry %func \"shader\" "
976          "OpExecutionMode %func InputTrianglesAdjacency" +
977          " OpExecutionMode %func OutputTriangleStrip" +
978          std::string(kVoidFVoid), GeometryDependencies()),
979std::make_pair(std::string(kOpenCLMemoryModel) +
980          "OpEntryPoint TessellationControl %func \"shader\" "
981          "OpExecutionMode %func Quads" +
982          std::string(kVoidFVoid), TessellationDependencies()),
983std::make_pair(std::string(kOpenCLMemoryModel) +
984          "OpEntryPoint TessellationControl %func \"shader\" "
985          "OpExecutionMode %func Isolines" +
986          std::string(kVoidFVoid), TessellationDependencies()),
987std::make_pair(std::string(kOpenCLMemoryModel) +
988          "OpEntryPoint Geometry %func \"shader\" "
989          "OpExecutionMode %func OutputVertices 42" +
990          " OpExecutionMode %func OutputPoints" +
991          " OpExecutionMode %func InputPoints" +
992          std::string(kVoidFVoid), GeometryDependencies()),
993std::make_pair(std::string(kOpenCLMemoryModel) +
994          "OpEntryPoint TessellationControl %func \"shader\" "
995          "OpExecutionMode %func OutputVertices 42" +
996          std::string(kVoidFVoid), TessellationDependencies()),
997std::make_pair(std::string(kOpenCLMemoryModel) +
998          "OpEntryPoint Geometry %func \"shader\" "
999          "OpExecutionMode %func OutputPoints" +
1000          " OpExecutionMode %func InputPoints" +
1001          std::string(kVoidFVoid), GeometryDependencies()),
1002std::make_pair(std::string(kOpenCLMemoryModel) +
1003          "OpEntryPoint Geometry %func \"shader\" "
1004          "OpExecutionMode %func OutputLineStrip" +
1005          " OpExecutionMode %func InputLines" +
1006          std::string(kVoidFVoid), GeometryDependencies()),
1007std::make_pair(std::string(kOpenCLMemoryModel) +
1008          "OpEntryPoint Geometry %func \"shader\" "
1009          "OpExecutionMode %func OutputTriangleStrip" +
1010          " OpExecutionMode %func Triangles" +
1011          std::string(kVoidFVoid), GeometryDependencies()),
1012std::make_pair(std::string(kGLSL450MemoryModel) +
1013          "OpEntryPoint Kernel %func \"shader\" "
1014          "OpExecutionMode %func VecTypeHint 2" +
1015          std::string(kVoidFVoid), KernelDependencies()),
1016std::make_pair(std::string(kGLSL450MemoryModel) +
1017          "OpEntryPoint Kernel %func \"shader\" "
1018          "OpExecutionMode %func ContractionOff" +
1019          std::string(kVoidFVoid), KernelDependencies()))));
1020
1021// clang-format on
1022
1023INSTANTIATE_TEST_SUITE_P(
1024    ExecutionModeV11, ValidateCapabilityV11,
1025    Combine(ValuesIn(AllCapabilities()),
1026            Values(std::make_pair(std::string(kOpenCLMemoryModel) +
1027                                      "OpEntryPoint Kernel %func \"shader\" "
1028                                      "OpExecutionMode %func SubgroupSize 1" +
1029                                      std::string(kVoidFVoid),
1030                                  std::vector<std::string>{"SubgroupDispatch"}),
1031                   std::make_pair(
1032                       std::string(kOpenCLMemoryModel) +
1033                           "OpEntryPoint Kernel %func \"shader\" "
1034                           "OpExecutionMode %func SubgroupsPerWorkgroup 65535" +
1035                           std::string(kVoidFVoid),
1036                       std::vector<std::string>{"SubgroupDispatch"}))));
1037// clang-format off
1038
1039INSTANTIATE_TEST_SUITE_P(StorageClass, ValidateCapability,
1040                        Combine(
1041                            ValuesIn(AllCapabilities()),
1042                            Values(
1043std::make_pair(std::string(kGLSL450MemoryModel) +
1044          " OpEntryPoint Vertex %func \"shader\"" +
1045          " %intt = OpTypeInt 32 0\n"
1046          " %ptrt = OpTypePointer UniformConstant %intt\n"
1047          " %var = OpVariable %ptrt UniformConstant\n" + std::string(kVoidFVoid),
1048          AllCapabilities()),
1049std::make_pair(std::string(kOpenCLMemoryModel) +
1050          " OpEntryPoint Kernel %func \"compute\"" +
1051          " %intt = OpTypeInt 32 0\n"
1052          " %ptrt = OpTypePointer Input %intt"
1053          " %var = OpVariable %ptrt Input\n" + std::string(kVoidFVoid),
1054          AllCapabilities()),
1055std::make_pair(std::string(kOpenCLMemoryModel) +
1056          " OpEntryPoint Vertex %func \"shader\"" +
1057          " %intt = OpTypeInt 32 0\n"
1058          " %ptrt = OpTypePointer Uniform %intt\n"
1059          " %var = OpVariable %ptrt Uniform\n" + std::string(kVoidFVoid),
1060          ShaderDependencies()),
1061std::make_pair(std::string(kOpenCLMemoryModel) +
1062          " OpEntryPoint Vertex %func \"shader\"" +
1063          " %intt = OpTypeInt 32 0\n"
1064          " %ptrt = OpTypePointer Output %intt\n"
1065          " %var = OpVariable %ptrt Output\n" + std::string(kVoidFVoid),
1066          ShaderDependencies()),
1067std::make_pair(std::string(kGLSL450MemoryModel) +
1068          " OpEntryPoint Vertex %func \"shader\"" +
1069          " %intt = OpTypeInt 32 0\n"
1070          " %ptrt = OpTypePointer Workgroup %intt\n"
1071          " %var = OpVariable %ptrt Workgroup\n" + std::string(kVoidFVoid),
1072          AllCapabilities()),
1073std::make_pair(std::string(kGLSL450MemoryModel) +
1074          " OpEntryPoint Vertex %func \"shader\"" +
1075          " %intt = OpTypeInt 32 0\n"
1076          " %ptrt = OpTypePointer CrossWorkgroup %intt\n"
1077          " %var = OpVariable %ptrt CrossWorkgroup\n" + std::string(kVoidFVoid),
1078          AllCapabilities()),
1079std::make_pair(std::string(kOpenCLMemoryModel) +
1080          " OpEntryPoint Kernel %func \"compute\"" +
1081          " %intt = OpTypeInt 32 0\n"
1082          " %ptrt = OpTypePointer Private %intt\n"
1083          " %var = OpVariable %ptrt Private\n" + std::string(kVoidFVoid),
1084          ShaderDependencies()),
1085std::make_pair(std::string(kOpenCLMemoryModel) +
1086          " OpEntryPoint Kernel %func \"compute\"" +
1087          " %intt = OpTypeInt 32 0\n"
1088          " %ptrt = OpTypePointer PushConstant %intt\n"
1089          " %var = OpVariable %ptrt PushConstant\n" + std::string(kVoidFVoid),
1090          ShaderDependencies()),
1091std::make_pair(std::string(kGLSL450MemoryModel) +
1092          " OpEntryPoint Vertex %func \"shader\"" +
1093          " %intt = OpTypeInt 32 0\n"
1094          " %ptrt = OpTypePointer AtomicCounter %intt\n"
1095          " %var = OpVariable %ptrt AtomicCounter\n" + std::string(kVoidFVoid),
1096          std::vector<std::string>{"AtomicStorage"}),
1097std::make_pair(std::string(kGLSL450MemoryModel) +
1098          " OpEntryPoint Vertex %func \"shader\"" +
1099          " %intt = OpTypeInt 32 0\n"
1100          " %ptrt = OpTypePointer Image %intt\n"
1101          " %var = OpVariable %ptrt Image\n" + std::string(kVoidFVoid),
1102          AllCapabilities())
1103)));
1104
1105INSTANTIATE_TEST_SUITE_P(Dim, ValidateCapability,
1106                        Combine(
1107                            ValuesIn(AllCapabilities()),
1108                            Values(
1109std::make_pair(" OpCapability ImageBasic" +
1110          std::string(kOpenCLMemoryModel) +
1111          std::string(" OpEntryPoint Kernel %func \"compute\"") +
1112          " %voidt = OpTypeVoid"
1113          " %imgt = OpTypeImage %voidt 1D 0 0 0 0 Unknown" + std::string(kVoidFVoid2),
1114          Sampled1DDependencies()),
1115std::make_pair(" OpCapability ImageBasic" +
1116          std::string(kOpenCLMemoryModel) +
1117          std::string(" OpEntryPoint Kernel %func \"compute\"") +
1118          " %voidt = OpTypeVoid"
1119          " %imgt = OpTypeImage %voidt 2D 0 0 0 0 Unknown" + std::string(kVoidFVoid2),
1120          AllCapabilities()),
1121std::make_pair(" OpCapability ImageBasic" +
1122          std::string(kOpenCLMemoryModel) +
1123          std::string(" OpEntryPoint Kernel %func \"compute\"") +
1124          " %voidt = OpTypeVoid"
1125          " %imgt = OpTypeImage %voidt 3D 0 0 0 0 Unknown" + std::string(kVoidFVoid2),
1126          AllCapabilities()),
1127std::make_pair(" OpCapability ImageBasic" +
1128          std::string(kOpenCLMemoryModel) +
1129          std::string(" OpEntryPoint Kernel %func \"compute\"") +
1130          " %voidt = OpTypeVoid"
1131          " %imgt = OpTypeImage %voidt Cube 0 0 0 0 Unknown" + std::string(kVoidFVoid2),
1132          ShaderDependencies()),
1133std::make_pair(" OpCapability ImageBasic" +
1134          std::string(kOpenCLMemoryModel) +
1135          std::string(" OpEntryPoint Kernel %func \"compute\"") +
1136          " %voidt = OpTypeVoid"
1137          " %imgt = OpTypeImage %voidt Rect 0 0 0 0 Unknown" + std::string(kVoidFVoid2),
1138          SampledRectDependencies()),
1139std::make_pair(" OpCapability ImageBasic" +
1140          std::string(kOpenCLMemoryModel) +
1141          std::string(" OpEntryPoint Kernel %func \"compute\"") +
1142          " %voidt = OpTypeVoid"
1143          " %imgt = OpTypeImage %voidt Buffer 0 0 0 0 Unknown" + std::string(kVoidFVoid2),
1144          SampledBufferDependencies()),
1145std::make_pair(" OpCapability ImageBasic" +
1146          std::string(kOpenCLMemoryModel) +
1147          std::string(" OpEntryPoint Kernel %func \"compute\"") +
1148          " %voidt = OpTypeVoid"
1149          " %imgt = OpTypeImage %voidt SubpassData 0 0 0 2 Unknown" + std::string(kVoidFVoid2),
1150          std::vector<std::string>{"InputAttachment"})
1151)));
1152
1153// NOTE: All Sampler Address Modes require kernel capabilities but the
1154// OpConstantSampler requires LiteralSampler which depends on Kernel
1155INSTANTIATE_TEST_SUITE_P(SamplerAddressingMode, ValidateCapability,
1156                        Combine(
1157                            ValuesIn(AllCapabilities()),
1158                            Values(
1159std::make_pair(std::string(kGLSL450MemoryModel) +
1160          " OpEntryPoint Vertex %func \"shader\""
1161          " %samplert = OpTypeSampler"
1162          " %sampler = OpConstantSampler %samplert None 1 Nearest" +
1163          std::string(kVoidFVoid),
1164          std::vector<std::string>{"LiteralSampler"}),
1165std::make_pair(std::string(kGLSL450MemoryModel) +
1166          " OpEntryPoint Vertex %func \"shader\""
1167          " %samplert = OpTypeSampler"
1168          " %sampler = OpConstantSampler %samplert ClampToEdge 1 Nearest" +
1169          std::string(kVoidFVoid),
1170          std::vector<std::string>{"LiteralSampler"}),
1171std::make_pair(std::string(kGLSL450MemoryModel) +
1172          " OpEntryPoint Vertex %func \"shader\""
1173          " %samplert = OpTypeSampler"
1174          " %sampler = OpConstantSampler %samplert Clamp 1 Nearest" +
1175          std::string(kVoidFVoid),
1176          std::vector<std::string>{"LiteralSampler"}),
1177std::make_pair(std::string(kGLSL450MemoryModel) +
1178          " OpEntryPoint Vertex %func \"shader\""
1179          " %samplert = OpTypeSampler"
1180          " %sampler = OpConstantSampler %samplert Repeat 1 Nearest" +
1181          std::string(kVoidFVoid),
1182          std::vector<std::string>{"LiteralSampler"}),
1183std::make_pair(std::string(kGLSL450MemoryModel) +
1184          " OpEntryPoint Vertex %func \"shader\""
1185          " %samplert = OpTypeSampler"
1186          " %sampler = OpConstantSampler %samplert RepeatMirrored 1 Nearest" +
1187          std::string(kVoidFVoid),
1188          std::vector<std::string>{"LiteralSampler"})
1189)));
1190
1191// TODO(umar): Sampler Filter Mode
1192// TODO(umar): Image Format
1193// TODO(umar): Image Channel Order
1194// TODO(umar): Image Channel Data Type
1195// TODO(umar): Image Operands
1196// TODO(umar): FP Fast Math Mode
1197// TODO(umar): FP Rounding Mode
1198// TODO(umar): Linkage Type
1199// TODO(umar): Access Qualifier
1200// TODO(umar): Function Parameter Attribute
1201
1202INSTANTIATE_TEST_SUITE_P(Decoration, ValidateCapability,
1203                        Combine(
1204                            ValuesIn(AllCapabilities()),
1205                            Values(
1206std::make_pair(std::string(kOpenCLMemoryModel) +
1207          "OpEntryPoint Kernel %func \"compute\" \n"
1208          "OpDecorate %var RelaxedPrecision\n"
1209          "%intt = OpTypeInt 32 0\n"
1210          "%ptr = OpTypePointer Private %intt\n"
1211          "%var = OpVariable %ptr Private\n" + std::string(kVoidFVoid),
1212          ShaderDependencies()),
1213std::make_pair(std::string(kOpenCLMemoryModel) +
1214          // Block applies to struct type.
1215          "OpEntryPoint Kernel %func \"compute\" \n"
1216          "OpDecorate %block Block\n"
1217          "%intt = OpTypeInt 32 0\n"
1218          "%block = OpTypeStruct %intt\n" + std::string(kVoidFVoid),
1219          ShaderDependencies()),
1220std::make_pair(std::string(kOpenCLMemoryModel) +
1221          // BufferBlock applies to struct type.
1222          "OpEntryPoint Kernel %func \"compute\" \n"
1223          "OpDecorate %block BufferBlock\n"
1224          "%intt = OpTypeInt 32 0\n"
1225          "%block = OpTypeStruct %intt\n" + std::string(kVoidFVoid),
1226          ShaderDependencies()),
1227std::make_pair(std::string(kOpenCLMemoryModel) +
1228          "OpEntryPoint Kernel %func \"compute\" \n"
1229          "OpMemberDecorate %structt 0 RowMajor\n"
1230          "%floatt = OpTypeFloat 32\n"
1231          "%float2 = OpTypeVector %floatt 2\n"
1232          "%mat2x2 = OpTypeMatrix %float2 2\n"
1233          "%structt = OpTypeStruct %mat2x2\n" + std::string(kVoidFVoid),
1234          MatrixDependencies()),
1235std::make_pair(std::string(kOpenCLMemoryModel) +
1236          "OpEntryPoint Kernel %func \"compute\" \n"
1237          "OpMemberDecorate %structt 0 ColMajor\n"
1238          "%floatt = OpTypeFloat 32\n"
1239          "%float2 = OpTypeVector %floatt 2\n"
1240          "%mat2x2 = OpTypeMatrix %float2 2\n"
1241          "%structt = OpTypeStruct %mat2x2\n" + std::string(kVoidFVoid),
1242          MatrixDependencies()),
1243std::make_pair(std::string(kOpenCLMemoryModel) +
1244          "OpEntryPoint Kernel %func \"compute\" \n"
1245          "OpDecorate %array ArrayStride 4\n"
1246          "%intt = OpTypeInt 32 0\n"
1247          "%array = OpTypeRuntimeArray %intt\n" + std::string(kVoidFVoid),
1248          ShaderDependencies()),
1249std::make_pair(std::string(kOpenCLMemoryModel) +
1250          "OpEntryPoint Kernel %func \"compute\" \n"
1251          "OpMemberDecorate %structt 0 MatrixStride 8\n"
1252          "%floatt = OpTypeFloat 32\n"
1253          "%float2 = OpTypeVector %floatt 2\n"
1254          "%mat2x2 = OpTypeMatrix %float2 2\n"
1255          "%structt = OpTypeStruct %mat2x2\n" + std::string(kVoidFVoid),
1256          MatrixDependencies()),
1257std::make_pair(std::string(kOpenCLMemoryModel) +
1258          "OpEntryPoint Kernel %func \"compute\" \n"
1259          "OpDecorate %struct GLSLShared\n"
1260          "%struct = OpTypeStruct\n" + std::string(kVoidFVoid),
1261          ShaderDependencies()),
1262std::make_pair(std::string(kOpenCLMemoryModel) +
1263          "OpEntryPoint Kernel %func \"compute\" \n"
1264          "OpDecorate %struct GLSLPacked\n"
1265          "%struct = OpTypeStruct\n" + std::string(kVoidFVoid),
1266          ShaderDependencies()),
1267std::make_pair(std::string(kGLSL450MemoryModel) +
1268          "OpEntryPoint Vertex %func \"shader\" \n"
1269          "OpDecorate %struct CPacked\n"
1270          "%struct = OpTypeStruct\n" + std::string(kVoidFVoid),
1271          KernelDependencies()),
1272std::make_pair(std::string(kOpenCLMemoryModel) +
1273          "OpEntryPoint Kernel %func \"compute\" \n"
1274          "OpDecorate %var NoPerspective\n"
1275          "%intt = OpTypeInt 32 0\n"
1276          "%ptr = OpTypePointer Input %intt\n"
1277          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1278          ShaderDependencies()),
1279std::make_pair(std::string(kOpenCLMemoryModel) +
1280          "OpEntryPoint Kernel %func \"compute\" \n"
1281          "OpDecorate %var Flat\n"
1282          "%intt = OpTypeInt 32 0\n"
1283          "%ptr = OpTypePointer Input %intt\n"
1284          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1285          ShaderDependencies()),
1286std::make_pair(std::string(kOpenCLMemoryModel) +
1287          "OpEntryPoint Kernel %func \"compute\" \n"
1288          "OpDecorate %var Patch\n"
1289          "%intt = OpTypeInt 32 0\n"
1290          "%ptr = OpTypePointer Input %intt\n"
1291          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1292          TessellationDependencies()),
1293std::make_pair(std::string(kOpenCLMemoryModel) +
1294          "OpEntryPoint Kernel %func \"compute\" \n"
1295          "OpDecorate %var Centroid\n"
1296          "%intt = OpTypeInt 32 0\n"
1297          "%ptr = OpTypePointer Input %intt\n"
1298          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1299          ShaderDependencies()),
1300std::make_pair(std::string(kOpenCLMemoryModel) +
1301          "OpEntryPoint Kernel %func \"compute\" \n"
1302          "OpDecorate %var Sample\n"
1303          "%intt = OpTypeInt 32 0\n"
1304          "%ptr = OpTypePointer Input %intt\n"
1305          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1306          std::vector<std::string>{"SampleRateShading"}),
1307std::make_pair(std::string(kOpenCLMemoryModel) +
1308          "OpEntryPoint Kernel %func \"compute\" \n"
1309          "OpDecorate %var Invariant\n"
1310          "%intt = OpTypeInt 32 0\n"
1311          "%ptr = OpTypePointer Input %intt\n"
1312          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1313          ShaderDependencies()),
1314std::make_pair(std::string(kOpenCLMemoryModel) +
1315          "OpEntryPoint Kernel %func \"compute\" \n"
1316          "OpDecorate %var Restrict\n"
1317          "%intt = OpTypeInt 32 0\n"
1318          "%ptr = OpTypePointer Input %intt\n"
1319          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1320          AllCapabilities()),
1321std::make_pair(std::string(kOpenCLMemoryModel) +
1322          "OpEntryPoint Kernel %func \"compute\" \n"
1323          "OpDecorate %var Aliased\n"
1324          "%intt = OpTypeInt 32 0\n"
1325          "%ptr = OpTypePointer Input %intt\n"
1326          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1327          AllCapabilities()),
1328std::make_pair(std::string(kOpenCLMemoryModel) +
1329          "OpEntryPoint Kernel %func \"compute\" \n"
1330          "OpDecorate %var Volatile\n"
1331          "%intt = OpTypeInt 32 0\n"
1332          "%ptr = OpTypePointer Input %intt\n"
1333          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1334          AllCapabilities()),
1335std::make_pair(std::string(kGLSL450MemoryModel) +
1336          "OpEntryPoint Vertex %func \"shader\" \n"
1337          "OpDecorate %var Constant\n"
1338          "%intt = OpTypeInt 32 0\n"
1339          "%ptr = OpTypePointer Input %intt\n"
1340          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1341          KernelDependencies()),
1342std::make_pair(std::string(kOpenCLMemoryModel) +
1343          "OpEntryPoint Kernel %func \"compute\" \n"
1344          "OpDecorate %var Coherent\n"
1345          "%intt = OpTypeInt 32 0\n"
1346          "%ptr = OpTypePointer Input %intt\n"
1347          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1348          AllCapabilities()),
1349std::make_pair(std::string(kOpenCLMemoryModel) +
1350          // NonWritable must target something valid, such as a storage image.
1351          "OpEntryPoint Kernel %func \"compute\" \n"
1352          "OpDecorate %var NonWritable "
1353          "%float = OpTypeFloat 32 "
1354          "%imstor = OpTypeImage %float 2D 0 0 0 2 Unknown "
1355          "%ptr = OpTypePointer UniformConstant %imstor "
1356          "%var = OpVariable %ptr UniformConstant "
1357          + std::string(kVoidFVoid),
1358          AllCapabilities()),
1359std::make_pair(std::string(kOpenCLMemoryModel) +
1360          "OpEntryPoint Kernel %func \"compute\" \n"
1361          "OpDecorate %var NonReadable "
1362          "%float = OpTypeFloat 32 "
1363          "%imstor = OpTypeImage %float 2D 0 0 0 2 Unknown "
1364          "%ptr = OpTypePointer UniformConstant %imstor "
1365          "%var = OpVariable %ptr UniformConstant "
1366          + std::string(kVoidFVoid),
1367          AllCapabilities()),
1368std::make_pair(std::string(kOpenCLMemoryModel) +
1369          // Uniform must target a non-void value.
1370          "OpEntryPoint Kernel %func \"compute\" \n"
1371          "OpDecorate %int0 Uniform\n"
1372          "%intt = OpTypeInt 32 0\n" +
1373          "%int0 = OpConstantNull %intt"
1374          + std::string(kVoidFVoid),
1375          ShaderDependencies()),
1376std::make_pair(std::string(kGLSL450MemoryModel) +
1377          "OpEntryPoint Vertex %func \"shader\" \n"
1378          "OpDecorate %intt SaturatedConversion\n"
1379          "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
1380          KernelDependencies()),
1381std::make_pair(std::string(kOpenCLMemoryModel) +
1382          "OpEntryPoint Kernel %func \"compute\" \n"
1383          "OpDecorate %var Stream 0\n"
1384          "%intt = OpTypeInt 32 0\n"
1385          "%ptr = OpTypePointer Output %intt\n"
1386          "%var = OpVariable %ptr Output\n" + std::string(kVoidFVoid),
1387          std::vector<std::string>{"GeometryStreams"}),
1388std::make_pair(std::string(kOpenCLMemoryModel) +
1389          "OpEntryPoint Kernel %func \"compute\" \n"
1390          "OpMemberDecorate %struct 0 Location 0\n"
1391          "%intt = OpTypeInt 32 0\n"
1392          "%struct = OpTypeStruct %intt\n" + std::string(kVoidFVoid),
1393          ShaderDependencies()),
1394std::make_pair(std::string(kOpenCLMemoryModel) +
1395          "OpEntryPoint Kernel %func \"compute\" \n"
1396          "OpDecorate %var Component 0\n"
1397          "%intt = OpTypeInt 32 0\n"
1398          "%ptr = OpTypePointer Input %intt\n"
1399          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1400          ShaderDependencies()),
1401std::make_pair(std::string(kOpenCLMemoryModel) +
1402          "OpEntryPoint Kernel %func \"compute\" \n"
1403          "OpDecorate %var Index 0\n"
1404          "%intt = OpTypeInt 32 0\n"
1405          "%ptr = OpTypePointer Input %intt\n"
1406          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1407          ShaderDependencies()),
1408std::make_pair(std::string(kOpenCLMemoryModel) +
1409          "OpEntryPoint Kernel %func \"compute\" \n"
1410          "OpDecorate %var Binding 0\n"
1411          "%intt = OpTypeInt 32 0\n"
1412          "%ptr = OpTypePointer Uniform %intt\n"
1413          "%var = OpVariable %ptr Uniform\n" + std::string(kVoidFVoid),
1414          ShaderDependencies()),
1415std::make_pair(std::string(kOpenCLMemoryModel) +
1416          "OpEntryPoint Kernel %func \"compute\" \n"
1417          "OpDecorate %var DescriptorSet 0\n"
1418          "%intt = OpTypeInt 32 0\n"
1419          "%ptr = OpTypePointer Uniform %intt\n"
1420          "%var = OpVariable %ptr Uniform\n" + std::string(kVoidFVoid),
1421          ShaderDependencies()),
1422std::make_pair(std::string(kOpenCLMemoryModel) +
1423          "OpEntryPoint Kernel %func \"compute\" \n"
1424          "OpMemberDecorate %structt 0 Offset 0\n"
1425          "%intt = OpTypeInt 32 0\n"
1426          "%structt = OpTypeStruct %intt\n" + std::string(kVoidFVoid),
1427          ShaderDependencies()),
1428std::make_pair(std::string(kOpenCLMemoryModel) +
1429          "OpEntryPoint Kernel %func \"compute\" \n"
1430          "OpDecorate %var XfbBuffer 0\n"
1431          "%intt = OpTypeInt 32 0\n"
1432          "%ptr = OpTypePointer Uniform %intt\n"
1433          "%var = OpVariable %ptr Uniform\n" + std::string(kVoidFVoid),
1434          std::vector<std::string>{"TransformFeedback"}),
1435std::make_pair(std::string(kOpenCLMemoryModel) +
1436          "OpEntryPoint Kernel %func \"compute\" \n"
1437          "OpDecorate %var XfbStride 0\n"
1438          "%intt = OpTypeInt 32 0\n"
1439          "%ptr = OpTypePointer Uniform %intt\n"
1440          "%var = OpVariable %ptr Uniform\n" + std::string(kVoidFVoid),
1441          std::vector<std::string>{"TransformFeedback"}),
1442std::make_pair(std::string(kGLSL450MemoryModel) +
1443          "OpEntryPoint Vertex %func \"shader\" \n"
1444          "OpDecorate %intt FuncParamAttr Zext\n"
1445          "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
1446          KernelDependencies()),
1447std::make_pair(std::string(kGLSL450MemoryModel) +
1448          "OpEntryPoint Vertex %func \"shader\" \n"
1449          "OpDecorate %intt FPFastMathMode Fast\n"
1450          "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
1451          KernelDependencies()),
1452std::make_pair(std::string(kOpenCLMemoryModel) +
1453          "OpEntryPoint Kernel %func \"compute\" \n"
1454          "OpDecorate %intt LinkageAttributes \"other\" Import\n"
1455          "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
1456          std::vector<std::string>{"Linkage"}),
1457std::make_pair(std::string(kOpenCLMemoryModel) +
1458          "OpEntryPoint Kernel %func \"compute\" \n"
1459          "OpDecorate %intt NoContraction\n"
1460          "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
1461          ShaderDependencies()),
1462std::make_pair(std::string(kOpenCLMemoryModel) +
1463          "OpEntryPoint Kernel %func \"compute\" \n"
1464          "OpDecorate %var InputAttachmentIndex 0\n"
1465          "%intt = OpTypeInt 32 0\n"
1466          "%ptr = OpTypePointer UniformConstant %intt\n"
1467          "%var = OpVariable %ptr UniformConstant\n" + std::string(kVoidFVoid),
1468          std::vector<std::string>{"InputAttachment"}),
1469std::make_pair(std::string(kGLSL450MemoryModel) +
1470          "OpEntryPoint Vertex %func \"shader\" \n"
1471          "OpDecorate %intt Alignment 4\n"
1472          "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
1473          KernelDependencies())
1474)));
1475
1476// clang-format on
1477INSTANTIATE_TEST_SUITE_P(
1478    DecorationSpecId, ValidateCapability,
1479    Combine(
1480        ValuesIn(AllSpirV10Capabilities()),
1481        Values(std::make_pair(std::string(kOpenCLMemoryModel) +
1482                                  "OpEntryPoint Vertex %func \"shader\" \n" +
1483                                  "OpDecorate %1 SpecId 1\n"
1484                                  "%intt = OpTypeInt 32 0\n"
1485                                  "%1 = OpSpecConstant %intt 0\n" +
1486                                  std::string(kVoidFVoid),
1487                              ShaderDependencies()))));
1488
1489INSTANTIATE_TEST_SUITE_P(
1490    DecorationV11, ValidateCapabilityV11,
1491    Combine(ValuesIn(AllCapabilities()),
1492            Values(std::make_pair(std::string(kOpenCLMemoryModel) +
1493                                      "OpEntryPoint Kernel %func \"compute\" \n"
1494                                      "OpDecorate %p MaxByteOffset 0 "
1495                                      "%i32 = OpTypeInt 32 0 "
1496                                      "%pi32 = OpTypePointer Workgroup %i32 "
1497                                      "%p = OpVariable %pi32 Workgroup " +
1498                                      std::string(kVoidFVoid),
1499                                  AddressesDependencies()),
1500                   // Trying to test OpDecorate here, but if this fails due to
1501                   // incorrect OpMemoryModel validation, that must also be
1502                   // fixed.
1503                   std::make_pair(
1504                       std::string("OpMemoryModel Logical OpenCL "
1505                                   "OpEntryPoint Kernel %func \"compute\" \n"
1506                                   "OpDecorate %1 SpecId 1 "
1507                                   "%intt = OpTypeInt 32 0 "
1508                                   "%1 = OpSpecConstant %intt 0") +
1509                           std::string(kVoidFVoid),
1510                       KernelDependencies()),
1511                   std::make_pair(
1512                       std::string("OpMemoryModel Logical Simple "
1513                                   "OpEntryPoint Vertex %func \"shader\" \n"
1514                                   "OpDecorate %1 SpecId 1 "
1515                                   "%intt = OpTypeInt 32 0 "
1516                                   "%1 = OpSpecConstant %intt 0") +
1517                           std::string(kVoidFVoid),
1518                       ShaderDependencies()))));
1519// clang-format off
1520
1521INSTANTIATE_TEST_SUITE_P(BuiltIn, ValidateCapability,
1522                        Combine(
1523                            ValuesIn(AllCapabilities()),
1524                            Values(
1525std::make_pair(std::string(kOpenCLMemoryModel) +
1526          "OpEntryPoint Kernel %func \"compute\" \n" +
1527          "OpDecorate %var BuiltIn Position\n"
1528          "%intt = OpTypeInt 32 0\n"
1529          "%ptr = OpTypePointer Input %intt\n"
1530          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1531          ShaderDependencies()),
1532// Just mentioning PointSize, ClipDistance, or CullDistance as a BuiltIn does
1533// not trigger the requirement for the associated capability.
1534// See https://github.com/KhronosGroup/SPIRV-Tools/issues/365
1535std::make_pair(std::string(kOpenCLMemoryModel) +
1536          "OpEntryPoint Kernel %func \"compute\" \n" +
1537          "OpDecorate %var BuiltIn PointSize\n"
1538          "%intt = OpTypeInt 32 0\n"
1539          "%ptr = OpTypePointer Input %intt\n"
1540          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1541          AllCapabilities()),
1542std::make_pair(std::string(kOpenCLMemoryModel) +
1543          "OpEntryPoint Kernel %func \"compute\" \n" +
1544          "OpDecorate %var BuiltIn ClipDistance\n"
1545          "%intt = OpTypeInt 32 0\n"
1546          "%ptr = OpTypePointer Input %intt\n"
1547          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1548          AllCapabilities()),
1549std::make_pair(std::string(kOpenCLMemoryModel) +
1550          "OpEntryPoint Kernel %func \"compute\" \n" +
1551          "OpDecorate %var BuiltIn CullDistance\n"
1552          "%intt = OpTypeInt 32 0\n"
1553          "%ptr = OpTypePointer Input %intt\n"
1554          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1555          AllCapabilities()),
1556std::make_pair(std::string(kOpenCLMemoryModel) +
1557          "OpEntryPoint Kernel %func \"compute\" \n" +
1558          "OpDecorate %var BuiltIn VertexId\n"
1559          "%intt = OpTypeInt 32 0\n"
1560          "%ptr = OpTypePointer Input %intt\n"
1561          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1562          ShaderDependencies()),
1563std::make_pair(std::string(kOpenCLMemoryModel) +
1564          "OpEntryPoint Kernel %func \"compute\" \n" +
1565          "OpDecorate %var BuiltIn InstanceId\n"
1566          "%intt = OpTypeInt 32 0\n"
1567          "%ptr = OpTypePointer Input %intt\n"
1568          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1569          ShaderDependencies()),
1570std::make_pair(std::string(kOpenCLMemoryModel) +
1571          "OpEntryPoint Kernel %func \"compute\" \n" +
1572          "OpDecorate %var BuiltIn PrimitiveId\n"
1573          "%intt = OpTypeInt 32 0\n"
1574          "%ptr = OpTypePointer Input %intt\n"
1575          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1576          GeometryTessellationDependencies()),
1577std::make_pair(std::string(kOpenCLMemoryModel) +
1578          "OpEntryPoint Kernel %func \"compute\" \n" +
1579          "OpDecorate %var BuiltIn InvocationId\n"
1580          "%intt = OpTypeInt 32 0\n"
1581          "%ptr = OpTypePointer Input %intt\n"
1582          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1583          GeometryTessellationDependencies()),
1584std::make_pair(std::string(kOpenCLMemoryModel) +
1585          "OpEntryPoint Kernel %func \"compute\" \n" +
1586          "OpDecorate %var BuiltIn Layer\n"
1587          "%intt = OpTypeInt 32 0\n"
1588          "%ptr = OpTypePointer Input %intt\n"
1589          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1590          GeometryDependencies()),
1591std::make_pair(std::string(kOpenCLMemoryModel) +
1592          "OpEntryPoint Kernel %func \"compute\" \n" +
1593          "OpDecorate %var BuiltIn ViewportIndex\n"
1594          "%intt = OpTypeInt 32 0\n"
1595          "%ptr = OpTypePointer Input %intt\n"
1596          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1597          std::vector<std::string>{"MultiViewport"}),
1598std::make_pair(std::string(kOpenCLMemoryModel) +
1599          "OpEntryPoint Kernel %func \"compute\" \n" +
1600          "OpDecorate %var BuiltIn TessLevelOuter\n"
1601          "%intt = OpTypeInt 32 0\n"
1602          "%ptr = OpTypePointer Input %intt\n"
1603          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1604          TessellationDependencies()),
1605std::make_pair(std::string(kOpenCLMemoryModel) +
1606          "OpEntryPoint Kernel %func \"compute\" \n" +
1607          "OpDecorate %var BuiltIn TessLevelInner\n"
1608          "%intt = OpTypeInt 32 0\n"
1609          "%ptr = OpTypePointer Input %intt\n"
1610          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1611          TessellationDependencies()),
1612std::make_pair(std::string(kOpenCLMemoryModel) +
1613          "OpEntryPoint Kernel %func \"compute\" \n" +
1614          "OpDecorate %var BuiltIn TessCoord\n"
1615          "%intt = OpTypeInt 32 0\n"
1616          "%ptr = OpTypePointer Input %intt\n"
1617          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1618          TessellationDependencies()),
1619std::make_pair(std::string(kOpenCLMemoryModel) +
1620          "OpEntryPoint Kernel %func \"compute\" \n" +
1621          "OpDecorate %var BuiltIn PatchVertices\n"
1622          "%intt = OpTypeInt 32 0\n"
1623          "%ptr = OpTypePointer Input %intt\n"
1624          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1625          TessellationDependencies()),
1626std::make_pair(std::string(kOpenCLMemoryModel) +
1627          "OpEntryPoint Kernel %func \"compute\" \n" +
1628          "OpDecorate %var BuiltIn FragCoord\n"
1629          "%intt = OpTypeInt 32 0\n"
1630          "%ptr = OpTypePointer Input %intt\n"
1631          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1632          ShaderDependencies()),
1633std::make_pair(std::string(kOpenCLMemoryModel) +
1634          "OpEntryPoint Kernel %func \"compute\" \n" +
1635          "OpDecorate %var BuiltIn PointCoord\n"
1636          "%intt = OpTypeInt 32 0\n"
1637          "%ptr = OpTypePointer Input %intt\n"
1638          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1639          ShaderDependencies()),
1640std::make_pair(std::string(kOpenCLMemoryModel) +
1641          "OpEntryPoint Kernel %func \"compute\" \n" +
1642          "OpDecorate %var BuiltIn FrontFacing\n"
1643          "%intt = OpTypeInt 32 0\n"
1644          "%ptr = OpTypePointer Input %intt\n"
1645          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1646          ShaderDependencies()),
1647std::make_pair(std::string(kOpenCLMemoryModel) +
1648          "OpEntryPoint Kernel %func \"compute\" \n" +
1649          "OpDecorate %var BuiltIn SampleId\n"
1650          "%intt = OpTypeInt 32 0\n"
1651          "%ptr = OpTypePointer Input %intt\n"
1652          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1653          std::vector<std::string>{"SampleRateShading"}),
1654std::make_pair(std::string(kOpenCLMemoryModel) +
1655          "OpEntryPoint Kernel %func \"compute\" \n" +
1656          "OpDecorate %var BuiltIn SamplePosition\n"
1657          "%intt = OpTypeInt 32 0\n"
1658          "%ptr = OpTypePointer Input %intt\n"
1659          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1660          std::vector<std::string>{"SampleRateShading"}),
1661std::make_pair(std::string(kOpenCLMemoryModel) +
1662          "OpEntryPoint Kernel %func \"compute\" \n" +
1663          "OpDecorate %var BuiltIn SampleMask\n"
1664          "%intt = OpTypeInt 32 0\n"
1665          "%ptr = OpTypePointer Input %intt\n"
1666          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1667          ShaderDependencies()),
1668std::make_pair(std::string(kOpenCLMemoryModel) +
1669          "OpEntryPoint Kernel %func \"compute\" \n" +
1670          "OpDecorate %var BuiltIn FragDepth\n"
1671          "%intt = OpTypeInt 32 0\n"
1672          "%ptr = OpTypePointer Input %intt\n"
1673          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1674          ShaderDependencies()),
1675std::make_pair(std::string(kOpenCLMemoryModel) +
1676          "OpEntryPoint Kernel %func \"compute\" \n" +
1677          "OpDecorate %var BuiltIn HelperInvocation\n"
1678          "%intt = OpTypeInt 32 0\n"
1679          "%ptr = OpTypePointer Input %intt\n"
1680          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1681          ShaderDependencies()),
1682std::make_pair(std::string(kOpenCLMemoryModel) +
1683          "OpEntryPoint Kernel %func \"compute\" \n" +
1684          "OpDecorate %var BuiltIn VertexIndex\n"
1685          "%intt = OpTypeInt 32 0\n"
1686          "%ptr = OpTypePointer Input %intt\n"
1687          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1688          ShaderDependencies()),
1689std::make_pair(std::string(kOpenCLMemoryModel) +
1690          "OpEntryPoint Kernel %func \"compute\" \n" +
1691          "OpDecorate %var BuiltIn InstanceIndex\n"
1692          "%intt = OpTypeInt 32 0\n"
1693          "%ptr = OpTypePointer Input %intt\n"
1694          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1695          ShaderDependencies()),
1696std::make_pair(std::string(kOpenCLMemoryModel) +
1697          "OpEntryPoint Kernel %func \"compute\" \n" +
1698          "OpDecorate %var BuiltIn NumWorkgroups\n"
1699          "%intt = OpTypeInt 32 0\n"
1700          "%ptr = OpTypePointer Input %intt\n"
1701          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1702          AllCapabilities()),
1703std::make_pair(std::string(kOpenCLMemoryModel) +
1704          "OpEntryPoint Kernel %func \"compute\" \n" +
1705          "OpDecorate %var BuiltIn WorkgroupId\n"
1706          "%intt = OpTypeInt 32 0\n"
1707          "%ptr = OpTypePointer Input %intt\n"
1708          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1709          AllCapabilities()),
1710std::make_pair(std::string(kOpenCLMemoryModel) +
1711          "OpEntryPoint Kernel %func \"compute\" \n" +
1712          "OpDecorate %var BuiltIn LocalInvocationId\n"
1713          "%intt = OpTypeInt 32 0\n"
1714          "%ptr = OpTypePointer Input %intt\n"
1715          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1716          AllCapabilities()),
1717std::make_pair(std::string(kOpenCLMemoryModel) +
1718          "OpEntryPoint Kernel %func \"compute\" \n" +
1719          "OpDecorate %var BuiltIn GlobalInvocationId\n"
1720          "%intt = OpTypeInt 32 0\n"
1721          "%ptr = OpTypePointer Input %intt\n"
1722          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1723          AllCapabilities()),
1724std::make_pair(std::string(kOpenCLMemoryModel) +
1725          "OpEntryPoint Kernel %func \"compute\" \n" +
1726          "OpDecorate %var BuiltIn LocalInvocationIndex\n"
1727          "%intt = OpTypeInt 32 0\n"
1728          "%ptr = OpTypePointer Input %intt\n"
1729          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1730          AllCapabilities()),
1731std::make_pair(std::string(kGLSL450MemoryModel) +
1732          "OpEntryPoint Vertex %func \"shader\" \n" +
1733          "OpDecorate %var BuiltIn WorkDim\n"
1734          "%intt = OpTypeInt 32 0\n"
1735          "%ptr = OpTypePointer Input %intt\n"
1736          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1737          KernelDependencies()),
1738std::make_pair(std::string(kGLSL450MemoryModel) +
1739          "OpEntryPoint Vertex %func \"shader\" \n" +
1740          "OpDecorate %var BuiltIn GlobalSize\n"
1741          "%intt = OpTypeInt 32 0\n"
1742          "%ptr = OpTypePointer Input %intt\n"
1743          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1744          KernelDependencies()),
1745std::make_pair(std::string(kGLSL450MemoryModel) +
1746          "OpEntryPoint Vertex %func \"shader\" \n" +
1747          "OpDecorate %var BuiltIn EnqueuedWorkgroupSize\n"
1748          "%intt = OpTypeInt 32 0\n"
1749          "%ptr = OpTypePointer Input %intt\n"
1750          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1751          KernelDependencies()),
1752std::make_pair(std::string(kGLSL450MemoryModel) +
1753          "OpEntryPoint Vertex %func \"shader\" \n" +
1754          "OpDecorate %var BuiltIn GlobalOffset\n"
1755          "%intt = OpTypeInt 32 0\n"
1756          "%ptr = OpTypePointer Input %intt\n"
1757          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1758          KernelDependencies()),
1759std::make_pair(std::string(kGLSL450MemoryModel) +
1760          "OpEntryPoint Vertex %func \"shader\" \n" +
1761          "OpDecorate %var BuiltIn GlobalLinearId\n"
1762          "%intt = OpTypeInt 32 0\n"
1763          "%ptr = OpTypePointer Input %intt\n"
1764          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1765          KernelDependencies()),
1766std::make_pair(std::string(kGLSL450MemoryModel) +
1767          "OpEntryPoint Vertex %func \"shader\" \n" +
1768          "OpDecorate %var BuiltIn SubgroupSize\n"
1769          "%intt = OpTypeInt 32 0\n"
1770          "%ptr = OpTypePointer Input %intt\n"
1771          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1772          KernelAndGroupNonUniformDependencies()),
1773std::make_pair(std::string(kGLSL450MemoryModel) +
1774          "OpEntryPoint Vertex %func \"shader\" \n" +
1775          "OpDecorate %var BuiltIn SubgroupMaxSize\n"
1776          "%intt = OpTypeInt 32 0\n"
1777          "%ptr = OpTypePointer Input %intt\n"
1778          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1779          KernelDependencies()),
1780std::make_pair(std::string(kGLSL450MemoryModel) +
1781          "OpEntryPoint Vertex %func \"shader\" \n" +
1782          "OpDecorate %var BuiltIn NumSubgroups\n"
1783          "%intt = OpTypeInt 32 0\n"
1784          "%ptr = OpTypePointer Input %intt\n"
1785          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1786          KernelAndGroupNonUniformDependencies()),
1787std::make_pair(std::string(kGLSL450MemoryModel) +
1788          "OpEntryPoint Vertex %func \"shader\" \n" +
1789          "OpDecorate %var BuiltIn NumEnqueuedSubgroups\n"
1790          "%intt = OpTypeInt 32 0\n"
1791          "%ptr = OpTypePointer Input %intt\n"
1792          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1793          KernelDependencies()),
1794std::make_pair(std::string(kGLSL450MemoryModel) +
1795          "OpEntryPoint Vertex %func \"shader\" \n" +
1796          "OpDecorate %var BuiltIn SubgroupId\n"
1797          "%intt = OpTypeInt 32 0\n"
1798          "%ptr = OpTypePointer Input %intt\n"
1799          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1800          KernelAndGroupNonUniformDependencies()),
1801std::make_pair(std::string(kGLSL450MemoryModel) +
1802          "OpEntryPoint Vertex %func \"shader\" \n" +
1803          "OpDecorate %var BuiltIn SubgroupLocalInvocationId\n"
1804          "%intt = OpTypeInt 32 0\n"
1805          "%ptr = OpTypePointer Input %intt\n"
1806          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1807          KernelAndGroupNonUniformDependencies()),
1808std::make_pair(std::string(kOpenCLMemoryModel) +
1809          "OpEntryPoint Kernel %func \"compute\" \n" +
1810          "OpDecorate %var BuiltIn VertexIndex\n"
1811          "%intt = OpTypeInt 32 0\n"
1812          "%ptr = OpTypePointer Input %intt\n"
1813          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1814          ShaderDependencies()),
1815std::make_pair(std::string(kOpenCLMemoryModel) +
1816          "OpEntryPoint Kernel %func \"compute\" \n" +
1817          "OpDecorate %var BuiltIn InstanceIndex\n"
1818          "%intt = OpTypeInt 32 0\n"
1819          "%ptr = OpTypePointer Input %intt\n"
1820          "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1821          ShaderDependencies())
1822)));
1823
1824// Ensure that mere mention of PointSize, ClipDistance, or CullDistance as
1825// BuiltIns does not trigger the requirement for the associated
1826// capability.
1827// See https://github.com/KhronosGroup/SPIRV-Tools/issues/365
1828INSTANTIATE_TEST_SUITE_P(BuiltIn, ValidateCapabilityVulkan10,
1829                        Combine(
1830                            // All capabilities to try.
1831                            ValuesIn(AllSpirV10Capabilities()),
1832                            Values(
1833std::make_pair(std::string(kGLSL450MemoryModel) +
1834          "OpEntryPoint Vertex %func \"shader\" %var\n" +
1835          "OpDecorate %var BuiltIn PointSize\n"
1836          "%float = OpTypeFloat 32\n"
1837          "%ptr_output_float = OpTypePointer Output %float\n"
1838          "%var = OpVariable %ptr_output_float Output\n" + std::string(kVoidFVoid),
1839          // Capabilities which should succeed.
1840          AllVulkan10Capabilities()),
1841std::make_pair(std::string(kGLSL450MemoryModel) +
1842          "OpEntryPoint Vertex %func \"shader\" \n"
1843          "OpMemberDecorate %block 0 BuiltIn ClipDistance\n"
1844          "%f32 = OpTypeFloat 32\n"
1845          "%intt = OpTypeInt 32 0\n"
1846          "%intt_4 = OpConstant %intt 4\n"
1847          "%f32arr4 = OpTypeArray %f32 %intt_4\n"
1848          "%block = OpTypeStruct %f32arr4\n" + std::string(kVoidFVoid),
1849          AllVulkan10Capabilities()),
1850std::make_pair(std::string(kGLSL450MemoryModel) +
1851          "OpEntryPoint Vertex %func \"shader\" \n"
1852          "OpMemberDecorate %block 0 BuiltIn CullDistance\n"
1853          "%f32 = OpTypeFloat 32\n"
1854          "%intt = OpTypeInt 32 0\n"
1855          "%intt_4 = OpConstant %intt 4\n"
1856          "%f32arr4 = OpTypeArray %f32 %intt_4\n"
1857          "%block = OpTypeStruct %f32arr4\n" + std::string(kVoidFVoid),
1858          AllVulkan10Capabilities())
1859)));
1860
1861INSTANTIATE_TEST_SUITE_P(BuiltIn, ValidateCapabilityOpenGL40,
1862                        Combine(
1863                            // OpenGL 4.0 is based on SPIR-V 1.0
1864                            ValuesIn(AllSpirV10Capabilities()),
1865                            Values(
1866std::make_pair(std::string(kGLSL450MemoryModel) +
1867          "OpEntryPoint Vertex %func \"shader\" %var\n" +
1868          "OpDecorate %var BuiltIn PointSize\n"
1869          "%float = OpTypeFloat 32\n"
1870          "%ptr_output_float = OpTypePointer Output %float\n"
1871          "%var = OpVariable %ptr_output_float Output\n" + std::string(kVoidFVoid),
1872          AllSpirV10Capabilities()),
1873std::make_pair(std::string(kGLSL450MemoryModel) +
1874          "OpEntryPoint Vertex %func \"shader\" %var\n" +
1875          "OpDecorate %var BuiltIn ClipDistance\n"
1876          "%float = OpTypeFloat 32\n"
1877          "%int = OpTypeInt 32 0\n"
1878          "%int_1 = OpConstant %int 1\n"
1879          "%array = OpTypeArray %float %int_1\n"
1880          "%ptr = OpTypePointer Output %array\n"
1881          "%var = OpVariable %ptr Output\n" + std::string(kVoidFVoid),
1882          AllSpirV10Capabilities()),
1883std::make_pair(std::string(kGLSL450MemoryModel) +
1884          "OpEntryPoint Vertex %func \"shader\" %var\n" +
1885          "OpDecorate %var BuiltIn CullDistance\n"
1886          "%float = OpTypeFloat 32\n"
1887          "%int = OpTypeInt 32 0\n"
1888          "%int_1 = OpConstant %int 1\n"
1889          "%array = OpTypeArray %float %int_1\n"
1890          "%ptr = OpTypePointer Output %array\n"
1891          "%var = OpVariable %ptr Output\n" + std::string(kVoidFVoid),
1892          AllSpirV10Capabilities())
1893)));
1894
1895INSTANTIATE_TEST_SUITE_P(Capabilities, ValidateCapabilityVulkan11,
1896                        Combine(
1897                            // All capabilities to try.
1898                            ValuesIn(AllCapabilities()),
1899                            Values(
1900std::make_pair(std::string(kGLSL450MemoryModel) +
1901          "OpEntryPoint Vertex %func \"shader\" %var\n" +
1902          "OpDecorate %var BuiltIn PointSize\n"
1903          "%float = OpTypeFloat 32\n"
1904          "%ptr_output_float = OpTypePointer Output %float\n"
1905          "%var = OpVariable %ptr_output_float Output\n" + std::string(kVoidFVoid),
1906          AllVulkan11Capabilities()),
1907std::make_pair(std::string(kGLSL450MemoryModel) +
1908          "OpEntryPoint Vertex %func \"shader\" %var\n" +
1909          "OpDecorate %var BuiltIn CullDistance\n"
1910          "%float = OpTypeFloat 32\n"
1911          "%int = OpTypeInt 32 0\n"
1912          "%int_1 = OpConstant %int 1\n"
1913          "%array = OpTypeArray %float %int_1\n"
1914          "%ptr = OpTypePointer Output %array\n"
1915          "%var = OpVariable %ptr Output\n" + std::string(kVoidFVoid),
1916          AllVulkan11Capabilities())
1917)));
1918
1919INSTANTIATE_TEST_SUITE_P(Capabilities, ValidateCapabilityVulkan12,
1920                        Combine(
1921                            // All capabilities to try.
1922                            ValuesIn(AllSpirV15Capabilities()),
1923                            Values(
1924std::make_pair(std::string(kGLSL450MemoryModel) +
1925          "OpEntryPoint Vertex %func \"shader\" %var\n" +
1926          "OpDecorate %var BuiltIn PointSize\n"
1927          "%float = OpTypeFloat 32\n"
1928          "%ptr_output_float = OpTypePointer Output %float\n"
1929          "%var = OpVariable %ptr_output_float Output\n" + std::string(kVoidFVoid),
1930          AllVulkan12Capabilities()),
1931std::make_pair(std::string(kGLSL450MemoryModel) +
1932          "OpEntryPoint Vertex %func \"shader\" %var\n" +
1933          "OpDecorate %var BuiltIn CullDistance\n"
1934          "%float = OpTypeFloat 32\n"
1935          "%int = OpTypeInt 32 0\n"
1936          "%int_1 = OpConstant %int 1\n"
1937          "%array = OpTypeArray %float %int_1\n"
1938          "%ptr = OpTypePointer Output %array\n"
1939          "%var = OpVariable %ptr Output\n" + std::string(kVoidFVoid),
1940          AllVulkan12Capabilities())
1941)));
1942
1943// TODO(umar): Selection Control
1944// TODO(umar): Loop Control
1945// TODO(umar): Function Control
1946// TODO(umar): Memory Semantics
1947// TODO(umar): Memory Access
1948// TODO(umar): Scope
1949// TODO(umar): Group Operation
1950// TODO(umar): Kernel Enqueue Flags
1951// TODO(umar): Kernel Profiling Flags
1952
1953INSTANTIATE_TEST_SUITE_P(MatrixOp, ValidateCapability,
1954                        Combine(
1955                            ValuesIn(AllCapabilities()),
1956                            Values(
1957std::make_pair(std::string(kOpenCLMemoryModel) +
1958          "OpEntryPoint Kernel %func \"compute\" \n" +
1959          "%f32      = OpTypeFloat 32\n"
1960          "%vec3     = OpTypeVector %f32 3\n"
1961          "%mat33    = OpTypeMatrix %vec3 3\n" + std::string(kVoidFVoid),
1962          MatrixDependencies()))));
1963// clang-format on
1964
1965#if 0
1966// TODO(atgoo@github.com) The following test is not valid as it generates
1967// invalid combinations of images, instructions and image operands.
1968//
1969// Creates assembly containing an OpImageFetch instruction using operands for
1970// the image-operands part.  The assembly defines constants %fzero and %izero
1971// that can be used for operands where IDs are required.  The assembly is valid,
1972// apart from not declaring any capabilities required by the operands.
1973string ImageOperandsTemplate(const std::string& operands) {
1974  ostringstream ss;
1975  // clang-format off
1976  ss << R"(
1977OpCapability Kernel
1978OpCapability Linkage
1979OpMemoryModel Logical OpenCL
1980
1981%i32 = OpTypeInt 32 0
1982%f32 = OpTypeFloat 32
1983%v4i32 = OpTypeVector %i32 4
1984%timg = OpTypeImage %i32 2D 0 0 0 0 Unknown
1985%pimg = OpTypePointer UniformConstant %timg
1986%tfun = OpTypeFunction %i32
1987
1988%vimg = OpVariable %pimg UniformConstant
1989%izero = OpConstant %i32 0
1990%fzero = OpConstant %f32 0.
1991
1992%main = OpFunction %i32 None %tfun
1993%lbl = OpLabel
1994%img = OpLoad %timg %vimg
1995%r1 = OpImageFetch %v4i32 %img %izero )" << operands << R"(
1996OpReturnValue %izero
1997OpFunctionEnd
1998)";
1999  // clang-format on
2000  return ss.str();
2001}
2002
2003INSTANTIATE_TEST_SUITE_P(
2004    TwoImageOperandsMask, ValidateCapability,
2005    Combine(
2006        ValuesIn(AllCapabilities()),
2007        Values(std::make_pair(ImageOperandsTemplate("Bias|Lod %fzero %fzero"),
2008                         ShaderDependencies()),
2009               std::make_pair(ImageOperandsTemplate("Lod|Offset %fzero %izero"),
2010                         std::vector<std::string>{"ImageGatherExtended"}),
2011               std::make_pair(ImageOperandsTemplate("Sample|MinLod %izero %fzero"),
2012                         std::vector<std::string>{"MinLod"}),
2013               std::make_pair(ImageOperandsTemplate("Lod|Sample %fzero %izero"),
2014                         AllCapabilities()))), );
2015#endif
2016
2017// TODO(umar): Instruction capability checks
2018
2019spv_result_t spvCoreOperandTableNameLookup(spv_target_env env,
2020                                           const spv_operand_table table,
2021                                           const spv_operand_type_t type,
2022                                           const char* name,
2023                                           const size_t nameLength) {
2024  if (!table) return SPV_ERROR_INVALID_TABLE;
2025  if (!name) return SPV_ERROR_INVALID_POINTER;
2026
2027  for (uint64_t typeIndex = 0; typeIndex < table->count; ++typeIndex) {
2028    const auto& group = table->types[typeIndex];
2029    if (type != group.type) continue;
2030    for (uint64_t index = 0; index < group.count; ++index) {
2031      const auto& entry = group.entries[index];
2032      // Check for min version only.
2033      if (spvVersionForTargetEnv(env) >= entry.minVersion &&
2034          nameLength == strlen(entry.name) &&
2035          !strncmp(entry.name, name, nameLength)) {
2036        return SPV_SUCCESS;
2037      }
2038    }
2039  }
2040
2041  return SPV_ERROR_INVALID_LOOKUP;
2042}
2043
2044// True if capability exists in core spec of env.
2045bool Exists(const std::string& capability, spv_target_env env) {
2046  ScopedContext sc(env);
2047  return SPV_SUCCESS ==
2048         spvCoreOperandTableNameLookup(env, sc.context->operand_table,
2049                                       SPV_OPERAND_TYPE_CAPABILITY,
2050                                       capability.c_str(), capability.size());
2051}
2052
2053TEST_P(ValidateCapability, Capability) {
2054  const std::string capability = Capability(GetParam());
2055  spv_target_env env = SPV_ENV_UNIVERSAL_1_0;
2056  if (!capability.empty()) {
2057    if (Exists(capability, SPV_ENV_UNIVERSAL_1_0))
2058      env = SPV_ENV_UNIVERSAL_1_0;
2059    else if (Exists(capability, SPV_ENV_UNIVERSAL_1_1))
2060      env = SPV_ENV_UNIVERSAL_1_1;
2061    else if (Exists(capability, SPV_ENV_UNIVERSAL_1_2))
2062      env = SPV_ENV_UNIVERSAL_1_2;
2063    else
2064      env = SPV_ENV_UNIVERSAL_1_3;
2065  }
2066  const std::string test_code = MakeAssembly(GetParam());
2067  CompileSuccessfully(test_code, env);
2068  ASSERT_EQ(ExpectedResult(GetParam()), ValidateInstructions(env))
2069      << "target env: " << spvTargetEnvDescription(env) << "\ntest code:\n"
2070      << test_code;
2071}
2072
2073TEST_P(ValidateCapabilityV11, Capability) {
2074  const std::string capability = Capability(GetParam());
2075  if (Exists(capability, SPV_ENV_UNIVERSAL_1_1)) {
2076    const std::string test_code = MakeAssembly(GetParam());
2077    CompileSuccessfully(test_code, SPV_ENV_UNIVERSAL_1_1);
2078    ASSERT_EQ(ExpectedResult(GetParam()),
2079              ValidateInstructions(SPV_ENV_UNIVERSAL_1_1))
2080        << test_code;
2081  }
2082}
2083
2084TEST_P(ValidateCapabilityVulkan10, Capability) {
2085  const std::string capability = Capability(GetParam());
2086  if (Exists(capability, SPV_ENV_VULKAN_1_0)) {
2087    const std::string test_code = MakeAssembly(GetParam());
2088    CompileSuccessfully(test_code, SPV_ENV_VULKAN_1_0);
2089    ASSERT_EQ(ExpectedResult(GetParam()),
2090              ValidateInstructions(SPV_ENV_VULKAN_1_0))
2091        << test_code;
2092  }
2093}
2094
2095TEST_P(ValidateCapabilityVulkan11, Capability) {
2096  const std::string capability = Capability(GetParam());
2097  if (Exists(capability, SPV_ENV_VULKAN_1_1)) {
2098    const std::string test_code = MakeAssembly(GetParam());
2099    CompileSuccessfully(test_code, SPV_ENV_VULKAN_1_1);
2100    ASSERT_EQ(ExpectedResult(GetParam()),
2101              ValidateInstructions(SPV_ENV_VULKAN_1_1))
2102        << test_code;
2103  }
2104}
2105
2106TEST_P(ValidateCapabilityVulkan12, Capability) {
2107  const std::string capability = Capability(GetParam());
2108  if (Exists(capability, SPV_ENV_VULKAN_1_2)) {
2109    const std::string test_code = MakeAssembly(GetParam());
2110    CompileSuccessfully(test_code, SPV_ENV_VULKAN_1_2);
2111    ASSERT_EQ(ExpectedResult(GetParam()),
2112              ValidateInstructions(SPV_ENV_VULKAN_1_2))
2113        << test_code;
2114  }
2115}
2116
2117TEST_P(ValidateCapabilityOpenGL40, Capability) {
2118  const std::string capability = Capability(GetParam());
2119  if (Exists(capability, SPV_ENV_OPENGL_4_0)) {
2120    const std::string test_code = MakeAssembly(GetParam());
2121    CompileSuccessfully(test_code, SPV_ENV_OPENGL_4_0);
2122    ASSERT_EQ(ExpectedResult(GetParam()),
2123              ValidateInstructions(SPV_ENV_OPENGL_4_0))
2124        << test_code;
2125  }
2126}
2127
2128TEST_F(ValidateCapability, SemanticsIdIsAnIdNotALiteral) {
2129  // From https://github.com/KhronosGroup/SPIRV-Tools/issues/248
2130  // The validator was interpreting the memory semantics ID number
2131  // as the value to be checked rather than an ID that references
2132  // another value to be checked.
2133  // In this case a raw ID of 64 was mistaken to mean a literal
2134  // semantic value of UniformMemory, which would require the Shader
2135  // capability.
2136  const char str[] = R"(
2137OpCapability Kernel
2138OpCapability Linkage
2139OpMemoryModel Logical OpenCL
2140
2141;  %i32 has ID 1
2142%i32    = OpTypeInt 32 0
2143%tf     = OpTypeFunction %i32
2144%pi32   = OpTypePointer CrossWorkgroup %i32
2145%var    = OpVariable %pi32 CrossWorkgroup
2146%c      = OpConstant %i32 100
2147%scope  = OpConstant %i32 1 ; Device scope
2148
2149; Fake an instruction with 64 as the result id.
2150; !64 = OpConstantNull %i32
2151!0x3002e !1 !64
2152
2153%f = OpFunction %i32 None %tf
2154%l = OpLabel
2155%result = OpAtomicIAdd %i32 %var %scope !64 %c
2156OpReturnValue %result
2157OpFunctionEnd
2158)";
2159
2160  CompileSuccessfully(str);
2161
2162  // Since we are forcing usage of <id> 64, the "id bound" in the binary header
2163  // must be overwritten so that <id> 64 is considered within bound.
2164  // ID Bound is at index 3 of the binary. Set it to 65.
2165  OverwriteAssembledBinary(3, 65);
2166
2167  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
2168}
2169
2170TEST_F(ValidateCapability, IntSignednessKernelGood) {
2171  const std::string spirv = R"(
2172OpCapability Kernel
2173OpCapability Linkage
2174OpMemoryModel Logical OpenCL
2175%i32    = OpTypeInt 32 0
2176)";
2177  CompileSuccessfully(spirv);
2178  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2179}
2180
2181TEST_F(ValidateCapability, IntSignednessKernelBad) {
2182  const std::string spirv = R"(
2183OpCapability Kernel
2184OpCapability Linkage
2185OpMemoryModel Logical OpenCL
2186%i32    = OpTypeInt 32 1
2187)";
2188  CompileSuccessfully(spirv);
2189  EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions());
2190  EXPECT_THAT(getDiagnosticString(),
2191              HasSubstr("The Signedness in OpTypeInt must always be 0 when "
2192                        "Kernel capability is used."));
2193}
2194
2195TEST_F(ValidateCapability, IntSignednessShaderGood) {
2196  const std::string spirv = R"(
2197OpCapability Shader
2198OpCapability Linkage
2199OpMemoryModel Logical GLSL450
2200%u32    = OpTypeInt 32 0
2201%i32    = OpTypeInt 32 1
2202)";
2203  CompileSuccessfully(spirv);
2204  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2205}
2206
2207TEST_F(ValidateCapability, NonVulkan10Capability) {
2208  const std::string spirv = R"(
2209OpCapability Shader
2210OpCapability Linkage
2211OpMemoryModel Logical GLSL450
2212%u32    = OpTypeInt 32 0
2213%i32    = OpTypeInt 32 1
2214)";
2215  CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
2216  EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
2217            ValidateInstructions(SPV_ENV_VULKAN_1_0));
2218  EXPECT_THAT(getDiagnosticString(),
2219              HasSubstr("Capability Linkage is not allowed by Vulkan 1.0"));
2220}
2221
2222TEST_F(ValidateCapability, Vulkan10EnabledByExtension) {
2223  const std::string spirv = R"(
2224OpCapability Shader
2225OpCapability DrawParameters
2226OpExtension "SPV_KHR_shader_draw_parameters"
2227OpMemoryModel Logical GLSL450
2228OpEntryPoint Vertex %func "shader"
2229OpMemberDecorate %block 0 BuiltIn PointSize
2230%f32 = OpTypeFloat 32
2231%block = OpTypeStruct %f32
2232)" + std::string(kVoidFVoid);
2233
2234  CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
2235  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
2236}
2237
2238TEST_F(ValidateCapability, Vulkan10NotEnabledByExtension) {
2239  const std::string spirv = R"(
2240OpCapability Shader
2241OpCapability DrawParameters
2242OpMemoryModel Logical GLSL450
2243OpEntryPoint Vertex %func "shader"
2244OpDecorate %intt BuiltIn PointSize
2245%intt = OpTypeInt 32 0
2246)" + std::string(kVoidFVoid);
2247
2248  CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
2249  EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
2250            ValidateInstructions(SPV_ENV_VULKAN_1_0));
2251  EXPECT_THAT(
2252      getDiagnosticString(),
2253      HasSubstr("Capability DrawParameters is not allowed by Vulkan 1.0"));
2254}
2255
2256TEST_F(ValidateCapability, NonOpenCL12FullCapability) {
2257  const std::string spirv = R"(
2258OpCapability Kernel
2259OpCapability Addresses
2260OpCapability Linkage
2261OpCapability Pipes
2262OpMemoryModel Physical64 OpenCL
2263%u32    = OpTypeInt 32 0
2264)";
2265  CompileSuccessfully(spirv, SPV_ENV_OPENCL_1_2);
2266  EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
2267            ValidateInstructions(SPV_ENV_OPENCL_1_2));
2268  EXPECT_THAT(
2269      getDiagnosticString(),
2270      HasSubstr("Capability Pipes is not allowed by OpenCL 1.2 Full Profile"));
2271}
2272
2273TEST_F(ValidateCapability, OpenCL12FullEnabledByCapability) {
2274  const std::string spirv = R"(
2275OpCapability Kernel
2276OpCapability Addresses
2277OpCapability Linkage
2278OpCapability ImageBasic
2279OpCapability Sampled1D
2280OpMemoryModel Physical64 OpenCL
2281%u32    = OpTypeInt 32 0
2282)" + std::string(kVoidFVoid);
2283
2284  CompileSuccessfully(spirv, SPV_ENV_OPENCL_1_2);
2285  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_1_2));
2286}
2287
2288TEST_F(ValidateCapability, OpenCL12FullNotEnabledByCapability) {
2289  const std::string spirv = R"(
2290OpCapability Kernel
2291OpCapability Addresses
2292OpCapability Linkage
2293OpCapability Sampled1D
2294OpMemoryModel Physical64 OpenCL
2295%u32    = OpTypeInt 32 0
2296)" + std::string(kVoidFVoid);
2297
2298  CompileSuccessfully(spirv, SPV_ENV_OPENCL_1_2);
2299  EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
2300            ValidateInstructions(SPV_ENV_OPENCL_1_2));
2301  EXPECT_THAT(
2302      getDiagnosticString(),
2303      HasSubstr(
2304          "Capability Sampled1D is not allowed by OpenCL 1.2 Full Profile"));
2305}
2306
2307TEST_F(ValidateCapability, NonOpenCL12EmbeddedCapability) {
2308  const std::string spirv = R"(
2309OpCapability Kernel
2310OpCapability Addresses
2311OpCapability Linkage
2312OpCapability Int64
2313OpMemoryModel Physical64 OpenCL
2314%u32    = OpTypeInt 32 0
2315)";
2316  CompileSuccessfully(spirv, SPV_ENV_OPENCL_EMBEDDED_1_2);
2317  EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
2318            ValidateInstructions(SPV_ENV_OPENCL_EMBEDDED_1_2));
2319  EXPECT_THAT(
2320      getDiagnosticString(),
2321      HasSubstr(
2322          "Capability Int64 is not allowed by OpenCL 1.2 Embedded Profile"));
2323}
2324
2325TEST_F(ValidateCapability, OpenCL12EmbeddedEnabledByCapability) {
2326  const std::string spirv = R"(
2327OpCapability Kernel
2328OpCapability Addresses
2329OpCapability Linkage
2330OpCapability ImageBasic
2331OpCapability Sampled1D
2332OpMemoryModel Physical64 OpenCL
2333%u32    = OpTypeInt 32 0
2334)" + std::string(kVoidFVoid);
2335
2336  CompileSuccessfully(spirv, SPV_ENV_OPENCL_EMBEDDED_1_2);
2337  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_EMBEDDED_1_2));
2338}
2339
2340TEST_F(ValidateCapability, OpenCL12EmbeddedNotEnabledByCapability) {
2341  const std::string spirv = R"(
2342OpCapability Kernel
2343OpCapability Addresses
2344OpCapability Linkage
2345OpCapability Sampled1D
2346OpMemoryModel Physical64 OpenCL
2347%u32    = OpTypeInt 32 0
2348)" + std::string(kVoidFVoid);
2349
2350  CompileSuccessfully(spirv, SPV_ENV_OPENCL_EMBEDDED_1_2);
2351  EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
2352            ValidateInstructions(SPV_ENV_OPENCL_EMBEDDED_1_2));
2353  EXPECT_THAT(getDiagnosticString(),
2354              HasSubstr("Capability Sampled1D is not allowed by OpenCL 1.2 "
2355                        "Embedded Profile"));
2356}
2357
2358TEST_F(ValidateCapability, OpenCL12EmbeddedNoLongerEnabledByCapability) {
2359  const std::string spirv = R"(
2360OpCapability Kernel
2361OpCapability Addresses
2362OpCapability Linkage
2363OpCapability Pipes
2364OpMemoryModel Physical64 OpenCL
2365%u32    = OpTypeInt 32 0
2366)" + std::string(kVoidFVoid);
2367
2368  CompileSuccessfully(spirv, SPV_ENV_OPENCL_EMBEDDED_1_2);
2369  EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
2370            ValidateInstructions(SPV_ENV_OPENCL_EMBEDDED_1_2));
2371  EXPECT_THAT(getDiagnosticString(),
2372              HasSubstr("Capability Pipes is not allowed by OpenCL 1.2 "
2373                        "Embedded Profile"));
2374}
2375
2376TEST_F(ValidateCapability, OpenCL20FullCapability) {
2377  const std::string spirv = R"(
2378OpCapability Kernel
2379OpCapability Addresses
2380OpCapability Linkage
2381OpCapability Groups
2382OpCapability Pipes
2383OpMemoryModel Physical64 OpenCL
2384%u32    = OpTypeInt 32 0
2385)";
2386  CompileSuccessfully(spirv, SPV_ENV_OPENCL_2_0);
2387  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_2_0));
2388}
2389
2390TEST_F(ValidateCapability, NonOpenCL20FullCapability) {
2391  const std::string spirv = R"(
2392OpCapability Kernel
2393OpCapability Addresses
2394OpCapability Linkage
2395OpCapability Matrix
2396OpMemoryModel Physical64 OpenCL
2397%u32    = OpTypeInt 32 0
2398)";
2399  CompileSuccessfully(spirv, SPV_ENV_OPENCL_2_0);
2400  EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
2401            ValidateInstructions(SPV_ENV_OPENCL_2_0));
2402  EXPECT_THAT(
2403      getDiagnosticString(),
2404      HasSubstr(
2405          "Capability Matrix is not allowed by OpenCL 2.0/2.1 Full Profile"));
2406}
2407
2408TEST_F(ValidateCapability, OpenCL20FullEnabledByCapability) {
2409  const std::string spirv = R"(
2410OpCapability Kernel
2411OpCapability Addresses
2412OpCapability Linkage
2413OpCapability ImageBasic
2414OpCapability Sampled1D
2415OpMemoryModel Physical64 OpenCL
2416%u32    = OpTypeInt 32 0
2417)" + std::string(kVoidFVoid);
2418
2419  CompileSuccessfully(spirv, SPV_ENV_OPENCL_2_0);
2420  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_2_0));
2421}
2422
2423TEST_F(ValidateCapability, OpenCL20FullNotEnabledByCapability) {
2424  const std::string spirv = R"(
2425OpCapability Kernel
2426OpCapability Addresses
2427OpCapability Linkage
2428OpCapability Sampled1D
2429OpMemoryModel Physical64 OpenCL
2430%u32    = OpTypeInt 32 0
2431)" + std::string(kVoidFVoid);
2432
2433  CompileSuccessfully(spirv, SPV_ENV_OPENCL_2_0);
2434  EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
2435            ValidateInstructions(SPV_ENV_OPENCL_2_0));
2436  EXPECT_THAT(getDiagnosticString(),
2437              HasSubstr("Capability Sampled1D is not allowed by OpenCL 2.0/2.1 "
2438                        "Full Profile"));
2439}
2440
2441TEST_F(ValidateCapability, NonOpenCL20EmbeddedCapability) {
2442  const std::string spirv = R"(
2443OpCapability Kernel
2444OpCapability Addresses
2445OpCapability Linkage
2446OpCapability Int64
2447OpMemoryModel Physical64 OpenCL
2448%u32    = OpTypeInt 32 0
2449)";
2450  CompileSuccessfully(spirv, SPV_ENV_OPENCL_EMBEDDED_2_0);
2451  EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
2452            ValidateInstructions(SPV_ENV_OPENCL_EMBEDDED_2_0));
2453  EXPECT_THAT(getDiagnosticString(),
2454              HasSubstr("Capability Int64 is not allowed by OpenCL 2.0/2.1 "
2455                        "Embedded Profile"));
2456}
2457
2458TEST_F(ValidateCapability, OpenCL20EmbeddedEnabledByCapability) {
2459  const std::string spirv = R"(
2460OpCapability Kernel
2461OpCapability Addresses
2462OpCapability Linkage
2463OpCapability ImageBasic
2464OpCapability Sampled1D
2465OpMemoryModel Physical64 OpenCL
2466%u32    = OpTypeInt 32 0
2467)" + std::string(kVoidFVoid);
2468
2469  CompileSuccessfully(spirv, SPV_ENV_OPENCL_EMBEDDED_2_0);
2470  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_EMBEDDED_2_0));
2471}
2472
2473TEST_F(ValidateCapability, OpenCL20EmbeddedNotEnabledByCapability) {
2474  const std::string spirv = R"(
2475OpCapability Kernel
2476OpCapability Addresses
2477OpCapability Linkage
2478OpCapability Sampled1D
2479OpMemoryModel Physical64 OpenCL
2480%u32    = OpTypeInt 32 0
2481)" + std::string(kVoidFVoid);
2482
2483  CompileSuccessfully(spirv, SPV_ENV_OPENCL_EMBEDDED_2_0);
2484  EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
2485            ValidateInstructions(SPV_ENV_OPENCL_EMBEDDED_2_0));
2486  EXPECT_THAT(getDiagnosticString(),
2487              HasSubstr("Capability Sampled1D is not allowed by OpenCL 2.0/2.1 "
2488                        "Embedded Profile"));
2489}
2490
2491TEST_F(ValidateCapability, OpenCL22FullCapability) {
2492  const std::string spirv = R"(
2493OpCapability Kernel
2494OpCapability Addresses
2495OpCapability Linkage
2496OpCapability PipeStorage
2497OpMemoryModel Physical64 OpenCL
2498%u32    = OpTypeInt 32 0
2499)";
2500  CompileSuccessfully(spirv, SPV_ENV_OPENCL_2_2);
2501  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_2_2));
2502}
2503
2504TEST_F(ValidateCapability, NonOpenCL22FullCapability) {
2505  const std::string spirv = R"(
2506OpCapability Kernel
2507OpCapability Addresses
2508OpCapability Linkage
2509OpCapability Matrix
2510OpMemoryModel Physical64 OpenCL
2511%u32    = OpTypeInt 32 0
2512)";
2513  CompileSuccessfully(spirv, SPV_ENV_OPENCL_2_2);
2514  EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
2515            ValidateInstructions(SPV_ENV_OPENCL_2_2));
2516  EXPECT_THAT(
2517      getDiagnosticString(),
2518      HasSubstr("Capability Matrix is not allowed by OpenCL 2.2 Full Profile"));
2519}
2520
2521TEST_F(ValidateCapability, OpenCL22FullEnabledByCapability) {
2522  const std::string spirv = R"(
2523OpCapability Kernel
2524OpCapability Addresses
2525OpCapability Linkage
2526OpCapability ImageBasic
2527OpCapability Sampled1D
2528OpMemoryModel Physical64 OpenCL
2529%u32    = OpTypeInt 32 0
2530)" + std::string(kVoidFVoid);
2531
2532  CompileSuccessfully(spirv, SPV_ENV_OPENCL_2_2);
2533  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_2_2));
2534}
2535
2536TEST_F(ValidateCapability, OpenCL22FullNotEnabledByCapability) {
2537  const std::string spirv = R"(
2538OpCapability Kernel
2539OpCapability Addresses
2540OpCapability Linkage
2541OpCapability Sampled1D
2542OpMemoryModel Physical64 OpenCL
2543%u32    = OpTypeInt 32 0
2544)" + std::string(kVoidFVoid);
2545
2546  CompileSuccessfully(spirv, SPV_ENV_OPENCL_2_2);
2547  EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
2548            ValidateInstructions(SPV_ENV_OPENCL_2_2));
2549  EXPECT_THAT(
2550      getDiagnosticString(),
2551      HasSubstr(
2552          "Capability Sampled1D is not allowed by OpenCL 2.2 Full Profile"));
2553}
2554
2555TEST_F(ValidateCapability, NonOpenCL22EmbeddedCapability) {
2556  const std::string spirv = R"(
2557OpCapability Kernel
2558OpCapability Addresses
2559OpCapability Linkage
2560OpCapability Int64
2561OpMemoryModel Physical64 OpenCL
2562%u32    = OpTypeInt 32 0
2563)";
2564  CompileSuccessfully(spirv, SPV_ENV_OPENCL_EMBEDDED_2_2);
2565  EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
2566            ValidateInstructions(SPV_ENV_OPENCL_EMBEDDED_2_2));
2567  EXPECT_THAT(
2568      getDiagnosticString(),
2569      HasSubstr(
2570          "Capability Int64 is not allowed by OpenCL 2.2 Embedded Profile"));
2571}
2572
2573TEST_F(ValidateCapability, OpenCL22EmbeddedEnabledByCapability) {
2574  const std::string spirv = R"(
2575OpCapability Kernel
2576OpCapability Addresses
2577OpCapability Linkage
2578OpCapability ImageBasic
2579OpCapability Sampled1D
2580OpMemoryModel Physical64 OpenCL
2581%u32    = OpTypeInt 32 0
2582)" + std::string(kVoidFVoid);
2583
2584  CompileSuccessfully(spirv, SPV_ENV_OPENCL_EMBEDDED_2_2);
2585  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_EMBEDDED_2_2));
2586}
2587
2588TEST_F(ValidateCapability, OpenCL22EmbeddedNotEnabledByCapability) {
2589  const std::string spirv = R"(
2590OpCapability Kernel
2591OpCapability Addresses
2592OpCapability Linkage
2593OpCapability Sampled1D
2594OpMemoryModel Physical64 OpenCL
2595%u32    = OpTypeInt 32 0
2596)" + std::string(kVoidFVoid);
2597
2598  CompileSuccessfully(spirv, SPV_ENV_OPENCL_EMBEDDED_2_2);
2599  EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
2600            ValidateInstructions(SPV_ENV_OPENCL_EMBEDDED_2_2));
2601  EXPECT_THAT(getDiagnosticString(),
2602              HasSubstr("Capability Sampled1D is not allowed by OpenCL 2.2 "
2603                        "Embedded Profile"));
2604}
2605
2606// Three tests to check enablement of an enum (a decoration) which is not
2607// in core, and is directly enabled by a capability, but not directly enabled
2608// by an extension.  See https://github.com/KhronosGroup/SPIRV-Tools/issues/1596
2609
2610TEST_F(ValidateCapability, DecorationFromExtensionMissingEnabledByCapability) {
2611  // Decoration ViewportRelativeNV is enabled by ShaderViewportMaskNV, which in
2612  // turn is enabled by SPV_NV_viewport_array2.
2613  const std::string spirv = R"(
2614OpCapability Shader
2615OpMemoryModel Logical Simple
2616OpDecorate %void ViewportRelativeNV
2617)" + std::string(kVoidFVoid);
2618
2619  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_0);
2620  EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
2621            ValidateInstructions(SPV_ENV_UNIVERSAL_1_0));
2622  EXPECT_THAT(getDiagnosticString(),
2623              HasSubstr("Operand 2 of Decorate requires one of these "
2624                        "capabilities: ShaderViewportMaskNV"));
2625}
2626
2627TEST_F(ValidateCapability, CapabilityEnabledByMissingExtension) {
2628  // Capability ShaderViewportMaskNV is enabled by SPV_NV_viewport_array2.
2629  const std::string spirv = R"(
2630OpCapability Shader
2631OpCapability ShaderViewportMaskNV
2632OpMemoryModel Logical Simple
2633)" + std::string(kVoidFVoid);
2634
2635  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_0);
2636  EXPECT_EQ(SPV_ERROR_MISSING_EXTENSION,
2637            ValidateInstructions(SPV_ENV_UNIVERSAL_1_0));
2638  EXPECT_THAT(getDiagnosticString(),
2639              HasSubstr("operand ShaderViewportMaskNV(5255) requires one of "
2640                        "these extensions: SPV_NV_viewport_array2"));
2641}
2642
2643TEST_F(ValidateCapability,
2644       DecorationEnabledByCapabilityEnabledByPresentExtension) {
2645  // Decoration ViewportRelativeNV is enabled by ShaderViewportMaskNV, which in
2646  // turn is enabled by SPV_NV_viewport_array2.
2647  const std::string spirv = R"(
2648OpCapability Shader
2649OpCapability Linkage
2650OpCapability ShaderViewportMaskNV
2651OpExtension "SPV_NV_viewport_array2"
2652OpMemoryModel Logical Simple
2653OpDecorate %void ViewportRelativeNV
2654%void = OpTypeVoid
2655)";
2656
2657  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_0);
2658  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_0))
2659      << getDiagnosticString();
2660}
2661
2662// Three tests to check enablement of an instruction  which is not in core, and
2663// is directly enabled by a capability, but not directly enabled by an
2664// extension. See https://github.com/KhronosGroup/SPIRV-Tools/issues/1624
2665// Instruction OpSubgroupShuffleINTEL is enabled by SubgroupShuffleINTEL, which
2666// in turn is enabled by SPV_INTEL_subgroups.
2667
2668TEST_F(ValidateCapability, InstructionFromExtensionMissingEnabledByCapability) {
2669  // Decoration ViewportRelativeNV is enabled by ShaderViewportMaskNV, which in
2670  // turn is enabled by SPV_NV_viewport_array2.
2671  const std::string spirv = R"(
2672OpCapability Kernel
2673OpCapability Addresses
2674; OpCapability SubgroupShuffleINTEL
2675OpExtension "SPV_INTEL_subgroups"
2676OpMemoryModel Physical32 OpenCL
2677OpEntryPoint Kernel %main "main"
2678%void = OpTypeVoid
2679%uint = OpTypeInt 32 0
2680%voidfn = OpTypeFunction %void
2681%zero = OpConstant %uint 0
2682%main = OpFunction %void None %voidfn
2683%entry = OpLabel
2684%foo = OpSubgroupShuffleINTEL %uint %zero %zero
2685OpReturn
2686OpFunctionEnd
2687)";
2688
2689  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_0);
2690  EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
2691            ValidateInstructions(SPV_ENV_UNIVERSAL_1_0));
2692  EXPECT_THAT(getDiagnosticString(),
2693              HasSubstr("Opcode SubgroupShuffleINTEL requires one of these "
2694                        "capabilities: SubgroupShuffleINTEL"));
2695}
2696
2697TEST_F(ValidateCapability,
2698       InstructionEnablingCapabilityEnabledByMissingExtension) {
2699  const std::string spirv = R"(
2700OpCapability Kernel
2701OpCapability Addresses
2702OpCapability SubgroupShuffleINTEL
2703; OpExtension "SPV_INTEL_subgroups"
2704OpMemoryModel Physical32 OpenCL
2705OpEntryPoint Kernel %main "main"
2706%void = OpTypeVoid
2707%uint = OpTypeInt 32 0
2708%voidfn = OpTypeFunction %void
2709%zero = OpConstant %uint 0
2710%main = OpFunction %void None %voidfn
2711%entry = OpLabel
2712%foo = OpSubgroupShuffleINTEL %uint %zero %zero
2713OpReturn
2714OpFunctionEnd
2715)";
2716
2717  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_0);
2718  EXPECT_EQ(SPV_ERROR_MISSING_EXTENSION,
2719            ValidateInstructions(SPV_ENV_UNIVERSAL_1_0));
2720  EXPECT_THAT(getDiagnosticString(),
2721              HasSubstr("operand SubgroupShuffleINTEL(5568) requires one of "
2722                        "these extensions: SPV_INTEL_subgroups"));
2723}
2724
2725TEST_F(ValidateCapability,
2726       InstructionEnabledByCapabilityEnabledByPresentExtension) {
2727  const std::string spirv = R"(
2728OpCapability Kernel
2729OpCapability Addresses
2730OpCapability SubgroupShuffleINTEL
2731OpExtension "SPV_INTEL_subgroups"
2732OpMemoryModel Physical32 OpenCL
2733OpEntryPoint Kernel %main "main"
2734%void = OpTypeVoid
2735%uint = OpTypeInt 32 0
2736%voidfn = OpTypeFunction %void
2737%zero = OpConstant %uint 0
2738%main = OpFunction %void None %voidfn
2739%entry = OpLabel
2740%foo = OpSubgroupShuffleINTEL %uint %zero %zero
2741OpReturn
2742OpFunctionEnd
2743)";
2744
2745  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_0);
2746  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_0))
2747      << getDiagnosticString();
2748}
2749
2750TEST_F(ValidateCapability, VulkanMemoryModelWithVulkanKHR) {
2751  const std::string spirv = R"(
2752OpCapability Shader
2753OpCapability VulkanMemoryModelKHR
2754OpCapability Linkage
2755OpExtension "SPV_KHR_vulkan_memory_model"
2756OpMemoryModel Logical VulkanKHR
2757)";
2758
2759  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
2760  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3))
2761      << getDiagnosticString();
2762}
2763
2764TEST_F(ValidateCapability, VulkanMemoryModelWithGLSL450) {
2765  const std::string spirv = R"(
2766OpCapability Shader
2767OpCapability VulkanMemoryModelKHR
2768OpCapability Linkage
2769OpExtension "SPV_KHR_vulkan_memory_model"
2770OpMemoryModel Logical GLSL450
2771)";
2772
2773  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
2774  EXPECT_EQ(SPV_ERROR_INVALID_DATA,
2775            ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2776  EXPECT_THAT(getDiagnosticString(),
2777              HasSubstr("VulkanMemoryModelKHR capability must only be "
2778                        "specified if the VulkanKHR memory model is used"));
2779}
2780
2781// In the grammar, SubgroupEqMask and SubgroupMaskKHR have different enabling
2782// lists of extensions.
2783TEST_F(ValidateCapability, SubgroupEqMaskEnabledByExtension) {
2784  const std::string spirv = R"(
2785OpCapability Shader
2786OpCapability SubgroupBallotKHR
2787OpExtension "SPV_KHR_shader_ballot"
2788OpMemoryModel Logical Simple
2789OpEntryPoint GLCompute %main "main"
2790OpDecorate %var BuiltIn SubgroupEqMask
2791%void = OpTypeVoid
2792%uint = OpTypeInt 32 0
2793%ptr_uint = OpTypePointer Private %uint
2794%var = OpVariable %ptr_uint Private
2795%fn = OpTypeFunction %void
2796%main = OpFunction %void None %fn
2797%entry = OpLabel
2798%val = OpLoad %uint %var
2799OpReturn
2800OpFunctionEnd
2801)";
2802
2803  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_0);
2804  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_0))
2805      << getDiagnosticString();
2806}
2807
2808// Test that extensions incorporated into SPIR-V 1.5 no longer require
2809// the associated OpExtension instruction.  Test one capability per extension.
2810
2811struct CapabilityExtensionVersionCase {
2812  std::string capability;
2813  std::string capability_new_name;
2814  std::string extension;
2815  spv_target_env last_version_requiring_extension;
2816  spv_target_env first_version_in_core;
2817};
2818
2819using ValidateCapabilityExtensionVersionTest =
2820    spvtest::ValidateBase<CapabilityExtensionVersionCase>;
2821
2822// Returns a minimal shader module with the given capability instruction.
2823std::string MinimalShaderModuleWithCapability(std::string cap) {
2824  std::string mem_model =
2825      (cap.find("VulkanMemory") == 0) ? "VulkanKHR" : "GLSL450";
2826  std::string extra_cap = (cap.find("VulkanMemoryModelDeviceScope") == 0)
2827                              ? "\nOpCapability VulkanMemoryModelKHR\n"
2828                              : "";
2829  return std::string("OpCapability ") + cap + extra_cap + R"(
2830OpCapability Shader
2831OpMemoryModel Logical )" + mem_model + R"(
2832OpEntryPoint Vertex %main "main"
2833%void = OpTypeVoid
2834%void_fn = OpTypeFunction %void
2835%main = OpFunction %void None %void_fn
2836%entry = OpLabel
2837OpReturn
2838OpFunctionEnd
2839)";
2840}
2841
2842TEST_P(ValidateCapabilityExtensionVersionTest, FailsInOlderSpirvVersion) {
2843  const auto spirv = MinimalShaderModuleWithCapability(GetParam().capability);
2844  CompileSuccessfully(spirv, GetParam().last_version_requiring_extension);
2845  EXPECT_EQ(SPV_ERROR_MISSING_EXTENSION,
2846            ValidateInstructions(GetParam().last_version_requiring_extension));
2847  EXPECT_THAT(getDiagnosticString(),
2848              HasSubstr(std::string("1st operand of Capability: operand ") +
2849                        GetParam().capability_new_name))
2850      << spirv << "\n";
2851  EXPECT_THAT(getDiagnosticString(),
2852              HasSubstr(std::string("requires one of these extensions: ") +
2853                        GetParam().extension));
2854}
2855
2856TEST_P(ValidateCapabilityExtensionVersionTest,
2857       SucceedsInNewerSpirvVersionWithOldName) {
2858  const auto spirv = MinimalShaderModuleWithCapability(GetParam().capability);
2859  CompileSuccessfully(spirv, GetParam().first_version_in_core);
2860  EXPECT_EQ(SPV_SUCCESS,
2861            ValidateInstructions(GetParam().first_version_in_core));
2862  EXPECT_THAT(getDiagnosticString(), Eq("")) << spirv << "\n";
2863}
2864
2865TEST_P(ValidateCapabilityExtensionVersionTest,
2866       SucceedsInNewerSpirvVersionWithNewName) {
2867  const auto spirv =
2868      MinimalShaderModuleWithCapability(GetParam().capability_new_name);
2869  CompileSuccessfully(spirv, GetParam().first_version_in_core);
2870  EXPECT_EQ(SPV_SUCCESS,
2871            ValidateInstructions(GetParam().first_version_in_core));
2872  EXPECT_THAT(getDiagnosticString(), Eq("")) << spirv << "\n";
2873}
2874
2875std::vector<CapabilityExtensionVersionCase> CapVersionCases1_5() {
2876#define IN15NOSUFFIX(C, E) \
2877  { C, C, E, SPV_ENV_UNIVERSAL_1_4, SPV_ENV_UNIVERSAL_1_5 }
2878#define IN15(C, C_WITHOUT_SUFFIX, E) \
2879  { C, C_WITHOUT_SUFFIX, E, SPV_ENV_UNIVERSAL_1_4, SPV_ENV_UNIVERSAL_1_5 }
2880  return std::vector<CapabilityExtensionVersionCase>{
2881      // SPV_KHR_8bit_storage
2882      IN15NOSUFFIX("StorageBuffer8BitAccess", "SPV_KHR_8bit_storage"),
2883      IN15NOSUFFIX("UniformAndStorageBuffer8BitAccess", "SPV_KHR_8bit_storage"),
2884      IN15NOSUFFIX("StoragePushConstant8", "SPV_KHR_8bit_storage"),
2885      // SPV_EXT_descriptor_indexing
2886      IN15("ShaderNonUniformEXT", "ShaderNonUniform",
2887           "SPV_EXT_descriptor_indexing"),
2888      IN15("RuntimeDescriptorArrayEXT", "RuntimeDescriptorArray",
2889           "SPV_EXT_descriptor_indexing"),
2890      IN15("InputAttachmentArrayDynamicIndexingEXT",
2891           "InputAttachmentArrayDynamicIndexing",
2892           "SPV_EXT_descriptor_indexing"),
2893      IN15("UniformTexelBufferArrayDynamicIndexingEXT",
2894           "UniformTexelBufferArrayDynamicIndexing",
2895           "SPV_EXT_descriptor_indexing"),
2896      IN15("StorageTexelBufferArrayDynamicIndexingEXT",
2897           "StorageTexelBufferArrayDynamicIndexing",
2898           "SPV_EXT_descriptor_indexing"),
2899      IN15("UniformBufferArrayNonUniformIndexingEXT",
2900           "UniformBufferArrayNonUniformIndexing",
2901           "SPV_EXT_descriptor_indexing"),
2902      IN15("SampledImageArrayNonUniformIndexingEXT",
2903           "SampledImageArrayNonUniformIndexing",
2904           "SPV_EXT_descriptor_indexing"),
2905      IN15("StorageBufferArrayNonUniformIndexingEXT",
2906           "StorageBufferArrayNonUniformIndexing",
2907           "SPV_EXT_descriptor_indexing"),
2908      IN15("StorageImageArrayNonUniformIndexingEXT",
2909           "StorageImageArrayNonUniformIndexing",
2910           "SPV_EXT_descriptor_indexing"),
2911      IN15("InputAttachmentArrayNonUniformIndexingEXT",
2912           "InputAttachmentArrayNonUniformIndexing",
2913           "SPV_EXT_descriptor_indexing"),
2914      IN15("UniformTexelBufferArrayNonUniformIndexingEXT",
2915           "UniformTexelBufferArrayNonUniformIndexing",
2916           "SPV_EXT_descriptor_indexing"),
2917      IN15("StorageTexelBufferArrayNonUniformIndexingEXT",
2918           "StorageTexelBufferArrayNonUniformIndexing",
2919           "SPV_EXT_descriptor_indexing"),
2920      // SPV_EXT_physical_storage_buffer
2921      IN15("PhysicalStorageBufferAddresses", "PhysicalStorageBufferAddresses",
2922           "SPV_EXT_physical_storage_buffer"),
2923      // SPV_KHR_vulkan_memory_model
2924      IN15("VulkanMemoryModelKHR", "VulkanMemoryModel",
2925           "SPV_KHR_vulkan_memory_model"),
2926      IN15("VulkanMemoryModelDeviceScopeKHR", "VulkanMemoryModelDeviceScope",
2927           "SPV_KHR_vulkan_memory_model"),
2928  };
2929#undef IN15
2930}
2931
2932INSTANTIATE_TEST_SUITE_P(NewInSpirv1_5, ValidateCapabilityExtensionVersionTest,
2933                         ValuesIn(CapVersionCases1_5()));
2934
2935TEST_P(ValidateCapability,
2936       CapShaderViewportIndexLayerFailsInOlderSpirvVersion) {
2937  const auto spirv =
2938      MinimalShaderModuleWithCapability("ShaderViewportIndexLayerEXT");
2939  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
2940  EXPECT_EQ(SPV_ERROR_MISSING_EXTENSION,
2941            ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
2942  EXPECT_THAT(
2943      getDiagnosticString(),
2944      HasSubstr(
2945          "1st operand of Capability: operand ShaderViewportIndexLayerEXT"));
2946  EXPECT_THAT(getDiagnosticString(),
2947              HasSubstr("requires one of these extensions: "
2948                        "SPV_EXT_shader_viewport_index_layer"));
2949}
2950
2951TEST_P(ValidateCapability, CapShaderViewportIndexLayerFailsInNewSpirvVersion) {
2952  const auto spirv =
2953      MinimalShaderModuleWithCapability("ShaderViewportIndexLayerEXT");
2954  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_5);
2955  EXPECT_EQ(SPV_ERROR_MISSING_EXTENSION,
2956            ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
2957  EXPECT_THAT(
2958      getDiagnosticString(),
2959      HasSubstr(
2960          "1st operand of Capability: operand ShaderViewportIndexLayerEXT"));
2961  EXPECT_THAT(getDiagnosticString(),
2962              HasSubstr("requires one of these extensions: "
2963                        "SPV_EXT_shader_viewport_index_layer"));
2964}
2965
2966TEST_F(ValidateCapability, CapShaderViewportIndexSucceedsInNewSpirvVersion) {
2967  const auto spirv = MinimalShaderModuleWithCapability("ShaderViewportIndex");
2968  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_5);
2969  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
2970  EXPECT_THAT(getDiagnosticString(), Eq(""));
2971}
2972
2973TEST_F(ValidateCapability, CapShaderLayerSucceedsInNewSpirvVersion) {
2974  const auto spirv = MinimalShaderModuleWithCapability("ShaderLayer");
2975  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_5);
2976  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
2977  EXPECT_THAT(getDiagnosticString(), Eq(""));
2978}
2979
2980}  // namespace
2981}  // namespace val
2982}  // namespace spvtools
2983