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 
31 namespace spvtools {
32 namespace val {
33 namespace {
34 
35 using spvtest::ScopedContext;
36 using testing::Combine;
37 using testing::Eq;
38 using testing::HasSubstr;
39 using testing::Values;
40 using 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.
73 using CapTestParameter =
74     std::tuple<std::string, std::pair<std::string, std::vector<std::string>>>;
75 
Capability(const CapTestParameter & p)76 const std::string& Capability(const CapTestParameter& p) {
77   return std::get<0>(p);
78 }
Remainder(const CapTestParameter & p)79 const std::string& Remainder(const CapTestParameter& p) {
80   return std::get<1>(p).first;
81 }
MustSucceed(const CapTestParameter & p)82 const std::vector<std::string>& MustSucceed(const CapTestParameter& p) {
83   return std::get<1>(p).second;
84 }
85 
86 // Creates assembly to test from p.
MakeAssembly(const CapTestParameter & p)87 std::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.
ExpectedResult(const CapTestParameter & p)98 spv_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.
105 using ValidateCapability = spvtest::ValidateBase<CapTestParameter>;
106 
107 // Always assembles using v1.1.
108 using ValidateCapabilityV11 = spvtest::ValidateBase<CapTestParameter>;
109 
110 // Always assembles using Vulkan 1.0.
111 // TODO(dneto): Refactor all these tests to scale better across environments.
112 using ValidateCapabilityVulkan10 = spvtest::ValidateBase<CapTestParameter>;
113 // Always assembles using OpenGL 4.0.
114 using ValidateCapabilityOpenGL40 = spvtest::ValidateBase<CapTestParameter>;
115 // Always assembles using Vulkan 1.1.
116 using ValidateCapabilityVulkan11 = spvtest::ValidateBase<CapTestParameter>;
117 // Always assembles using Vulkan 1.2.
118 using ValidateCapabilityVulkan12 = spvtest::ValidateBase<CapTestParameter>;
119 
TEST_F(ValidateCapability,Default)120 TEST_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
AllCapabilities()136 const 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 
AllSpirV15Capabilities()220 const 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 
AllSpirV10Capabilities()328 const 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 
AllVulkan10Capabilities()390 const 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 
AllVulkan11Capabilities()436 const 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 
AllVulkan12Capabilities()501 const 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 
MatrixDependencies()589 const 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 
ShaderDependencies()631 const 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 
TessellationDependencies()672 const std::vector<std::string>& TessellationDependencies() {
673   static const auto r = new std::vector<std::string>{
674   "Tessellation",
675   "TessellationPointSize"};
676   return *r;
677 }
678 
GeometryDependencies()679 const 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 
GeometryTessellationDependencies()688 const 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.
KernelDependencies()701 const 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 
KernelAndGroupNonUniformDependencies()718 const 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 
AddressesDependencies()743 const std::vector<std::string>& AddressesDependencies() {
744   static const auto r = new std::vector<std::string>{
745   "Addresses",
746   "GenericPointer"};
747   return *r;
748 }
749 
Sampled1DDependencies()750 const std::vector<std::string>& Sampled1DDependencies() {
751   static const auto r = new std::vector<std::string>{
752   "Sampled1D",
753   "Image1D"};
754   return *r;
755 }
756 
SampledRectDependencies()757 const std::vector<std::string>& SampledRectDependencies() {
758   static const auto r = new std::vector<std::string>{
759   "SampledRect",
760   "ImageRect"};
761   return *r;
762 }
763 
SampledBufferDependencies()764 const std::vector<std::string>& SampledBufferDependencies() {
765   static const auto r = new std::vector<std::string>{
766   "SampledBuffer",
767   "ImageBuffer"};
768   return *r;
769 }
770 
771 const char kOpenCLMemoryModel[] = \
772   " OpCapability Kernel"
773   " OpMemoryModel Logical OpenCL ";
774 
775 const char kGLSL450MemoryModel[] = \
776   " OpCapability Shader"
777   " OpMemoryModel Logical GLSL450 ";
778 
779 const 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 
787 const char kVoidFVoid2[] = \
788   " %void_f = OpTypeFunction %voidt"
789   " %func   = OpFunction %voidt None %void_f"
790   " %label  = OpLabel"
791   "           OpReturn"
792   "           OpFunctionEnd ";
793 
794 INSTANTIATE_TEST_SUITE_P(ExecutionModel, ValidateCapability,
795                         Combine(
796                             ValuesIn(AllCapabilities()),
797                             Values(
798 std::make_pair(std::string(kOpenCLMemoryModel) +
799           " OpEntryPoint Vertex %func \"shader\"" +
800           std::string(kVoidFVoid), ShaderDependencies()),
801 std::make_pair(std::string(kOpenCLMemoryModel) +
802           " OpEntryPoint TessellationControl %func \"shader\"" +
803           std::string(kVoidFVoid), TessellationDependencies()),
804 std::make_pair(std::string(kOpenCLMemoryModel) +
805           " OpEntryPoint TessellationEvaluation %func \"shader\"" +
806           std::string(kVoidFVoid), TessellationDependencies()),
807 std::make_pair(std::string(kOpenCLMemoryModel) +
808           " OpEntryPoint Geometry %func \"shader\"" +
809           " OpExecutionMode %func InputPoints" +
810           " OpExecutionMode %func OutputPoints" +
811           std::string(kVoidFVoid), GeometryDependencies()),
812 std::make_pair(std::string(kOpenCLMemoryModel) +
813           " OpEntryPoint Fragment %func \"shader\"" +
814           " OpExecutionMode %func OriginUpperLeft" +
815           std::string(kVoidFVoid), ShaderDependencies()),
816 std::make_pair(std::string(kOpenCLMemoryModel) +
817           " OpEntryPoint GLCompute %func \"shader\"" +
818           std::string(kVoidFVoid), ShaderDependencies()),
819 std::make_pair(std::string(kGLSL450MemoryModel) +
820           " OpEntryPoint Kernel %func \"shader\"" +
821           std::string(kVoidFVoid), KernelDependencies())
822 )));
823 
824 INSTANTIATE_TEST_SUITE_P(AddressingAndMemoryModel, ValidateCapability,
825                         Combine(
826                             ValuesIn(AllCapabilities()),
827                             Values(
828 std::make_pair(" OpCapability Shader"
829           " OpMemoryModel Logical Simple"
830           " OpEntryPoint Vertex %func \"shader\"" +
831           std::string(kVoidFVoid),     AllCapabilities()),
832 std::make_pair(" OpCapability Shader"
833           " OpMemoryModel Logical GLSL450"
834           " OpEntryPoint Vertex %func \"shader\"" +
835           std::string(kVoidFVoid),    AllCapabilities()),
836 std::make_pair(" OpCapability Kernel"
837           " OpMemoryModel Logical OpenCL"
838           " OpEntryPoint Kernel %func \"compute\"" +
839           std::string(kVoidFVoid),     AllCapabilities()),
840 std::make_pair(" OpCapability Shader"
841           " OpMemoryModel Physical32 Simple"
842           " OpEntryPoint Vertex %func \"shader\"" +
843           std::string(kVoidFVoid),  AddressesDependencies()),
844 std::make_pair(" OpCapability Shader"
845           " OpMemoryModel Physical32 GLSL450"
846           " OpEntryPoint Vertex %func \"shader\"" +
847           std::string(kVoidFVoid), AddressesDependencies()),
848 std::make_pair(" OpCapability Kernel"
849           " OpMemoryModel Physical32 OpenCL"
850           " OpEntryPoint Kernel %func \"compute\"" +
851           std::string(kVoidFVoid),  AddressesDependencies()),
852 std::make_pair(" OpCapability Shader"
853           " OpMemoryModel Physical64 Simple"
854           " OpEntryPoint Vertex %func \"shader\"" +
855           std::string(kVoidFVoid),  AddressesDependencies()),
856 std::make_pair(" OpCapability Shader"
857           " OpMemoryModel Physical64 GLSL450"
858           " OpEntryPoint Vertex %func \"shader\"" +
859           std::string(kVoidFVoid), AddressesDependencies()),
860 std::make_pair(" OpCapability Kernel"
861           " OpMemoryModel Physical64 OpenCL"
862           " OpEntryPoint Kernel %func \"compute\"" +
863           std::string(kVoidFVoid),  AddressesDependencies())
864 )));
865 
866 INSTANTIATE_TEST_SUITE_P(ExecutionMode, ValidateCapability,
867                         Combine(
868                             ValuesIn(AllCapabilities()),
869                             Values(
870 std::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()),
876 std::make_pair(std::string(kOpenCLMemoryModel) +
877           "OpEntryPoint TessellationControl %func \"shader\" "
878           "OpExecutionMode %func SpacingEqual" +
879           std::string(kVoidFVoid), TessellationDependencies()),
880 std::make_pair(std::string(kOpenCLMemoryModel) +
881           "OpEntryPoint TessellationControl %func \"shader\" "
882           "OpExecutionMode %func SpacingFractionalEven" +
883           std::string(kVoidFVoid), TessellationDependencies()),
884 std::make_pair(std::string(kOpenCLMemoryModel) +
885           "OpEntryPoint TessellationControl %func \"shader\" "
886           "OpExecutionMode %func SpacingFractionalOdd" +
887           std::string(kVoidFVoid), TessellationDependencies()),
888 std::make_pair(std::string(kOpenCLMemoryModel) +
889           "OpEntryPoint TessellationControl %func \"shader\" "
890           "OpExecutionMode %func VertexOrderCw" +
891           std::string(kVoidFVoid), TessellationDependencies()),
892 std::make_pair(std::string(kOpenCLMemoryModel) +
893           "OpEntryPoint TessellationControl %func \"shader\" "
894           "OpExecutionMode %func VertexOrderCcw" +
895           std::string(kVoidFVoid), TessellationDependencies()),
896 std::make_pair(std::string(kOpenCLMemoryModel) +
897           "OpEntryPoint Fragment %func \"shader\" "
898           "OpExecutionMode %func PixelCenterInteger" +
899           " OpExecutionMode %func OriginUpperLeft" +
900           std::string(kVoidFVoid), ShaderDependencies()),
901 std::make_pair(std::string(kOpenCLMemoryModel) +
902           "OpEntryPoint Fragment %func \"shader\" "
903           "OpExecutionMode %func OriginUpperLeft" +
904           std::string(kVoidFVoid), ShaderDependencies()),
905 std::make_pair(std::string(kOpenCLMemoryModel) +
906           "OpEntryPoint Fragment %func \"shader\" "
907           "OpExecutionMode %func OriginLowerLeft" +
908           std::string(kVoidFVoid), ShaderDependencies()),
909 std::make_pair(std::string(kOpenCLMemoryModel) +
910           "OpEntryPoint Fragment %func \"shader\" "
911           "OpExecutionMode %func EarlyFragmentTests" +
912           " OpExecutionMode %func OriginUpperLeft" +
913           std::string(kVoidFVoid), ShaderDependencies()),
914 std::make_pair(std::string(kOpenCLMemoryModel) +
915           "OpEntryPoint TessellationControl %func \"shader\" "
916           "OpExecutionMode %func PointMode" +
917           std::string(kVoidFVoid), TessellationDependencies()),
918 std::make_pair(std::string(kOpenCLMemoryModel) +
919           "OpEntryPoint Vertex %func \"shader\" "
920           "OpExecutionMode %func Xfb" +
921           std::string(kVoidFVoid), std::vector<std::string>{"TransformFeedback"}),
922 std::make_pair(std::string(kOpenCLMemoryModel) +
923           "OpEntryPoint Fragment %func \"shader\" "
924           "OpExecutionMode %func DepthReplacing" +
925           " OpExecutionMode %func OriginUpperLeft" +
926           std::string(kVoidFVoid), ShaderDependencies()),
927 std::make_pair(std::string(kOpenCLMemoryModel) +
928           "OpEntryPoint Fragment %func \"shader\" "
929           "OpExecutionMode %func DepthGreater" +
930           " OpExecutionMode %func OriginUpperLeft" +
931           std::string(kVoidFVoid), ShaderDependencies()),
932 std::make_pair(std::string(kOpenCLMemoryModel) +
933           "OpEntryPoint Fragment %func \"shader\" "
934           "OpExecutionMode %func DepthLess" +
935           " OpExecutionMode %func OriginUpperLeft" +
936           std::string(kVoidFVoid), ShaderDependencies()),
937 std::make_pair(std::string(kOpenCLMemoryModel) +
938           "OpEntryPoint Fragment %func \"shader\" "
939           "OpExecutionMode %func DepthUnchanged" +
940           " OpExecutionMode %func OriginUpperLeft" +
941           std::string(kVoidFVoid), ShaderDependencies()),
942 std::make_pair(std::string(kOpenCLMemoryModel) +
943           "OpEntryPoint Kernel %func \"shader\" "
944           "OpExecutionMode %func LocalSize 42 42 42" +
945           std::string(kVoidFVoid), AllCapabilities()),
946 std::make_pair(std::string(kGLSL450MemoryModel) +
947           "OpEntryPoint Kernel %func \"shader\" "
948           "OpExecutionMode %func LocalSizeHint 42 42 42" +
949           std::string(kVoidFVoid), KernelDependencies()),
950 std::make_pair(std::string(kOpenCLMemoryModel) +
951           "OpEntryPoint Geometry %func \"shader\" "
952           "OpExecutionMode %func InputPoints" +
953           " OpExecutionMode %func OutputPoints" +
954           std::string(kVoidFVoid), GeometryDependencies()),
955 std::make_pair(std::string(kOpenCLMemoryModel) +
956           "OpEntryPoint Geometry %func \"shader\" "
957           "OpExecutionMode %func InputLines" +
958           " OpExecutionMode %func OutputLineStrip" +
959           std::string(kVoidFVoid), GeometryDependencies()),
960 std::make_pair(std::string(kOpenCLMemoryModel) +
961           "OpEntryPoint Geometry %func \"shader\" "
962           "OpExecutionMode %func InputLinesAdjacency" +
963           " OpExecutionMode %func OutputLineStrip" +
964           std::string(kVoidFVoid), GeometryDependencies()),
965 std::make_pair(std::string(kOpenCLMemoryModel) +
966           "OpEntryPoint Geometry %func \"shader\" "
967           "OpExecutionMode %func Triangles" +
968           " OpExecutionMode %func OutputTriangleStrip" +
969           std::string(kVoidFVoid), GeometryDependencies()),
970 std::make_pair(std::string(kOpenCLMemoryModel) +
971           "OpEntryPoint TessellationControl %func \"shader\" "
972           "OpExecutionMode %func Triangles" +
973           std::string(kVoidFVoid), TessellationDependencies()),
974 std::make_pair(std::string(kOpenCLMemoryModel) +
975           "OpEntryPoint Geometry %func \"shader\" "
976           "OpExecutionMode %func InputTrianglesAdjacency" +
977           " OpExecutionMode %func OutputTriangleStrip" +
978           std::string(kVoidFVoid), GeometryDependencies()),
979 std::make_pair(std::string(kOpenCLMemoryModel) +
980           "OpEntryPoint TessellationControl %func \"shader\" "
981           "OpExecutionMode %func Quads" +
982           std::string(kVoidFVoid), TessellationDependencies()),
983 std::make_pair(std::string(kOpenCLMemoryModel) +
984           "OpEntryPoint TessellationControl %func \"shader\" "
985           "OpExecutionMode %func Isolines" +
986           std::string(kVoidFVoid), TessellationDependencies()),
987 std::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()),
993 std::make_pair(std::string(kOpenCLMemoryModel) +
994           "OpEntryPoint TessellationControl %func \"shader\" "
995           "OpExecutionMode %func OutputVertices 42" +
996           std::string(kVoidFVoid), TessellationDependencies()),
997 std::make_pair(std::string(kOpenCLMemoryModel) +
998           "OpEntryPoint Geometry %func \"shader\" "
999           "OpExecutionMode %func OutputPoints" +
1000           " OpExecutionMode %func InputPoints" +
1001           std::string(kVoidFVoid), GeometryDependencies()),
1002 std::make_pair(std::string(kOpenCLMemoryModel) +
1003           "OpEntryPoint Geometry %func \"shader\" "
1004           "OpExecutionMode %func OutputLineStrip" +
1005           " OpExecutionMode %func InputLines" +
1006           std::string(kVoidFVoid), GeometryDependencies()),
1007 std::make_pair(std::string(kOpenCLMemoryModel) +
1008           "OpEntryPoint Geometry %func \"shader\" "
1009           "OpExecutionMode %func OutputTriangleStrip" +
1010           " OpExecutionMode %func Triangles" +
1011           std::string(kVoidFVoid), GeometryDependencies()),
1012 std::make_pair(std::string(kGLSL450MemoryModel) +
1013           "OpEntryPoint Kernel %func \"shader\" "
1014           "OpExecutionMode %func VecTypeHint 2" +
1015           std::string(kVoidFVoid), KernelDependencies()),
1016 std::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 
1023 INSTANTIATE_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 
1039 INSTANTIATE_TEST_SUITE_P(StorageClass, ValidateCapability,
1040                         Combine(
1041                             ValuesIn(AllCapabilities()),
1042                             Values(
1043 std::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()),
1049 std::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()),
1055 std::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()),
1061 std::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()),
1067 std::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()),
1073 std::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()),
1079 std::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()),
1085 std::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()),
1091 std::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"}),
1097 std::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 
1105 INSTANTIATE_TEST_SUITE_P(Dim, ValidateCapability,
1106                         Combine(
1107                             ValuesIn(AllCapabilities()),
1108                             Values(
1109 std::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()),
1115 std::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()),
1121 std::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()),
1127 std::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()),
1133 std::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()),
1139 std::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()),
1145 std::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
1155 INSTANTIATE_TEST_SUITE_P(SamplerAddressingMode, ValidateCapability,
1156                         Combine(
1157                             ValuesIn(AllCapabilities()),
1158                             Values(
1159 std::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"}),
1165 std::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"}),
1171 std::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"}),
1177 std::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"}),
1183 std::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 
1202 INSTANTIATE_TEST_SUITE_P(Decoration, ValidateCapability,
1203                         Combine(
1204                             ValuesIn(AllCapabilities()),
1205                             Values(
1206 std::make_pair(std::string(kOpenCLMemoryModel) +
1207           "OpEntryPoint Kernel %func \"compute\" \n"
1208           "OpDecorate %intt RelaxedPrecision\n"
1209           "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
1210           ShaderDependencies()),
1211 std::make_pair(std::string(kOpenCLMemoryModel) +
1212           // Block applies to struct type.
1213           "OpEntryPoint Kernel %func \"compute\" \n"
1214           "OpDecorate %block Block\n"
1215           "%intt = OpTypeInt 32 0\n"
1216           "%block = OpTypeStruct %intt\n" + std::string(kVoidFVoid),
1217           ShaderDependencies()),
1218 std::make_pair(std::string(kOpenCLMemoryModel) +
1219           // BufferBlock applies to struct type.
1220           "OpEntryPoint Kernel %func \"compute\" \n"
1221           "OpDecorate %block BufferBlock\n"
1222           "%intt = OpTypeInt 32 0\n"
1223           "%block = OpTypeStruct %intt\n" + std::string(kVoidFVoid),
1224           ShaderDependencies()),
1225 std::make_pair(std::string(kOpenCLMemoryModel) +
1226           "OpEntryPoint Kernel %func \"compute\" \n"
1227           "OpDecorate %intt RowMajor\n"
1228           "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
1229           MatrixDependencies()),
1230 std::make_pair(std::string(kOpenCLMemoryModel) +
1231           "OpEntryPoint Kernel %func \"compute\" \n"
1232           "OpDecorate %intt ColMajor\n"
1233           "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
1234           MatrixDependencies()),
1235 std::make_pair(std::string(kOpenCLMemoryModel) +
1236           "OpEntryPoint Kernel %func \"compute\" \n"
1237           "OpDecorate %intt ArrayStride 1\n"
1238           "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
1239           ShaderDependencies()),
1240 std::make_pair(std::string(kOpenCLMemoryModel) +
1241           "OpEntryPoint Kernel %func \"compute\" \n"
1242           "OpDecorate %intt MatrixStride 1\n"
1243           "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
1244           MatrixDependencies()),
1245 std::make_pair(std::string(kOpenCLMemoryModel) +
1246           "OpEntryPoint Kernel %func \"compute\" \n"
1247           "OpDecorate %intt GLSLShared\n"
1248           "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
1249           ShaderDependencies()),
1250 std::make_pair(std::string(kOpenCLMemoryModel) +
1251           "OpEntryPoint Kernel %func \"compute\" \n"
1252           "OpDecorate %intt GLSLPacked\n"
1253           "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
1254           ShaderDependencies()),
1255 std::make_pair(std::string(kGLSL450MemoryModel) +
1256           "OpEntryPoint Vertex %func \"shader\" \n"
1257           "OpDecorate %intt CPacked\n"
1258           "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
1259           KernelDependencies()),
1260 std::make_pair(std::string(kOpenCLMemoryModel) +
1261           "OpEntryPoint Kernel %func \"compute\" \n"
1262           "OpDecorate %intt NoPerspective\n"
1263           "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
1264           ShaderDependencies()),
1265 std::make_pair(std::string(kOpenCLMemoryModel) +
1266           "OpEntryPoint Kernel %func \"compute\" \n"
1267           "OpDecorate %intt Flat\n"
1268           "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
1269           ShaderDependencies()),
1270 std::make_pair(std::string(kOpenCLMemoryModel) +
1271           "OpEntryPoint Kernel %func \"compute\" \n"
1272           "OpDecorate %intt Patch\n"
1273           "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
1274           TessellationDependencies()),
1275 std::make_pair(std::string(kOpenCLMemoryModel) +
1276           "OpEntryPoint Kernel %func \"compute\" \n"
1277           "OpDecorate %intt Centroid\n"
1278           "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
1279           ShaderDependencies()),
1280 std::make_pair(std::string(kOpenCLMemoryModel) +
1281           "OpEntryPoint Kernel %func \"compute\" \n"
1282           "OpDecorate %intt Sample\n"
1283           "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
1284           std::vector<std::string>{"SampleRateShading"}),
1285 std::make_pair(std::string(kOpenCLMemoryModel) +
1286           "OpEntryPoint Kernel %func \"compute\" \n"
1287           "OpDecorate %intt Invariant\n"
1288           "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
1289           ShaderDependencies()),
1290 std::make_pair(std::string(kOpenCLMemoryModel) +
1291           "OpEntryPoint Kernel %func \"compute\" \n"
1292           "OpDecorate %intt Restrict\n"
1293           "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
1294           AllCapabilities()),
1295 std::make_pair(std::string(kOpenCLMemoryModel) +
1296           "OpEntryPoint Kernel %func \"compute\" \n"
1297           "OpDecorate %intt Aliased\n"
1298           "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
1299           AllCapabilities()),
1300 std::make_pair(std::string(kOpenCLMemoryModel) +
1301           "OpEntryPoint Kernel %func \"compute\" \n"
1302           "OpDecorate %intt Volatile\n"
1303           "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
1304           AllCapabilities()),
1305 std::make_pair(std::string(kGLSL450MemoryModel) +
1306           "OpEntryPoint Vertex %func \"shader\" \n"
1307           "OpDecorate %intt Constant\n"
1308           "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
1309           KernelDependencies()),
1310 std::make_pair(std::string(kOpenCLMemoryModel) +
1311           "OpEntryPoint Kernel %func \"compute\" \n"
1312           "OpDecorate %intt Coherent\n"
1313           "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
1314           AllCapabilities()),
1315 std::make_pair(std::string(kOpenCLMemoryModel) +
1316           // NonWritable must target something valid, such as a storage image.
1317           "OpEntryPoint Kernel %func \"compute\" \n"
1318           "OpDecorate %var NonWritable "
1319           "%float = OpTypeFloat 32 "
1320           "%imstor = OpTypeImage %float 2D 0 0 0 2 Unknown "
1321           "%ptr = OpTypePointer UniformConstant %imstor "
1322           "%var = OpVariable %ptr UniformConstant "
1323           + std::string(kVoidFVoid),
1324           AllCapabilities()),
1325 std::make_pair(std::string(kOpenCLMemoryModel) +
1326           "OpEntryPoint Kernel %func \"compute\" \n"
1327           "OpDecorate %intt NonReadable\n"
1328           "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
1329           AllCapabilities()),
1330 std::make_pair(std::string(kOpenCLMemoryModel) +
1331           // Uniform must target a non-void value.
1332           "OpEntryPoint Kernel %func \"compute\" \n"
1333           "OpDecorate %int0 Uniform\n"
1334           "%intt = OpTypeInt 32 0\n" +
1335           "%int0 = OpConstantNull %intt"
1336           + std::string(kVoidFVoid),
1337           ShaderDependencies()),
1338 std::make_pair(std::string(kGLSL450MemoryModel) +
1339           "OpEntryPoint Vertex %func \"shader\" \n"
1340           "OpDecorate %intt SaturatedConversion\n"
1341           "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
1342           KernelDependencies()),
1343 std::make_pair(std::string(kOpenCLMemoryModel) +
1344           "OpEntryPoint Kernel %func \"compute\" \n"
1345           "OpDecorate %intt Stream 0\n"
1346           "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
1347           std::vector<std::string>{"GeometryStreams"}),
1348 std::make_pair(std::string(kOpenCLMemoryModel) +
1349           "OpEntryPoint Kernel %func \"compute\" \n"
1350           "OpMemberDecorate %struct 0 Location 0\n"
1351           "%intt = OpTypeInt 32 0\n"
1352           "%struct = OpTypeStruct %intt\n" + std::string(kVoidFVoid),
1353           ShaderDependencies()),
1354 std::make_pair(std::string(kOpenCLMemoryModel) +
1355           "OpEntryPoint Kernel %func \"compute\" \n"
1356           "OpDecorate %var Component 0\n"
1357           "%intt = OpTypeInt 32 0\n"
1358           "%ptr = OpTypePointer Input %intt\n"
1359           "%var = OpVariable %ptr Input\n" + std::string(kVoidFVoid),
1360           ShaderDependencies()),
1361 std::make_pair(std::string(kOpenCLMemoryModel) +
1362           "OpEntryPoint Kernel %func \"compute\" \n"
1363           "OpDecorate %intt Index 0\n"
1364           "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
1365           ShaderDependencies()),
1366 std::make_pair(std::string(kOpenCLMemoryModel) +
1367           "OpEntryPoint Kernel %func \"compute\" \n"
1368           "OpDecorate %intt Binding 0\n"
1369           "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
1370           ShaderDependencies()),
1371 std::make_pair(std::string(kOpenCLMemoryModel) +
1372           "OpEntryPoint Kernel %func \"compute\" \n"
1373           "OpDecorate %intt DescriptorSet 0\n"
1374           "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
1375           ShaderDependencies()),
1376 std::make_pair(std::string(kOpenCLMemoryModel) +
1377           "OpEntryPoint Kernel %func \"compute\" \n"
1378           "OpDecorate %intt Offset 0\n"
1379           "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
1380           ShaderDependencies()),
1381 std::make_pair(std::string(kOpenCLMemoryModel) +
1382           "OpEntryPoint Kernel %func \"compute\" \n"
1383           "OpDecorate %intt XfbBuffer 0\n"
1384           "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
1385           std::vector<std::string>{"TransformFeedback"}),
1386 std::make_pair(std::string(kOpenCLMemoryModel) +
1387           "OpEntryPoint Kernel %func \"compute\" \n"
1388           "OpDecorate %intt XfbStride 0\n"
1389           "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
1390           std::vector<std::string>{"TransformFeedback"}),
1391 std::make_pair(std::string(kGLSL450MemoryModel) +
1392           "OpEntryPoint Vertex %func \"shader\" \n"
1393           "OpDecorate %intt FuncParamAttr Zext\n"
1394           "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
1395           KernelDependencies()),
1396 std::make_pair(std::string(kGLSL450MemoryModel) +
1397           "OpEntryPoint Vertex %func \"shader\" \n"
1398           "OpDecorate %intt FPFastMathMode Fast\n"
1399           "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
1400           KernelDependencies()),
1401 std::make_pair(std::string(kOpenCLMemoryModel) +
1402           "OpEntryPoint Kernel %func \"compute\" \n"
1403           "OpDecorate %intt LinkageAttributes \"other\" Import\n"
1404           "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
1405           std::vector<std::string>{"Linkage"}),
1406 std::make_pair(std::string(kOpenCLMemoryModel) +
1407           "OpEntryPoint Kernel %func \"compute\" \n"
1408           "OpDecorate %intt NoContraction\n"
1409           "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
1410           ShaderDependencies()),
1411 std::make_pair(std::string(kOpenCLMemoryModel) +
1412           "OpEntryPoint Kernel %func \"compute\" \n"
1413           "OpDecorate %intt InputAttachmentIndex 0\n"
1414           "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
1415           std::vector<std::string>{"InputAttachment"}),
1416 std::make_pair(std::string(kGLSL450MemoryModel) +
1417           "OpEntryPoint Vertex %func \"shader\" \n"
1418           "OpDecorate %intt Alignment 4\n"
1419           "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
1420           KernelDependencies())
1421 )));
1422 
1423 // clang-format on
1424 INSTANTIATE_TEST_SUITE_P(
1425     DecorationSpecId, ValidateCapability,
1426     Combine(
1427         ValuesIn(AllSpirV10Capabilities()),
1428         Values(std::make_pair(std::string(kOpenCLMemoryModel) +
1429                                   "OpEntryPoint Vertex %func \"shader\" \n" +
1430                                   "OpDecorate %1 SpecId 1\n"
1431                                   "%intt = OpTypeInt 32 0\n"
1432                                   "%1 = OpSpecConstant %intt 0\n" +
1433                                   std::string(kVoidFVoid),
1434                               ShaderDependencies()))));
1435 
1436 INSTANTIATE_TEST_SUITE_P(
1437     DecorationV11, ValidateCapabilityV11,
1438     Combine(ValuesIn(AllCapabilities()),
1439             Values(std::make_pair(std::string(kOpenCLMemoryModel) +
1440                                       "OpEntryPoint Kernel %func \"compute\" \n"
1441                                       "OpDecorate %p MaxByteOffset 0 "
1442                                       "%i32 = OpTypeInt 32 0 "
1443                                       "%pi32 = OpTypePointer Workgroup %i32 "
1444                                       "%p = OpVariable %pi32 Workgroup " +
1445                                       std::string(kVoidFVoid),
1446                                   AddressesDependencies()),
1447                    // Trying to test OpDecorate here, but if this fails due to
1448                    // incorrect OpMemoryModel validation, that must also be
1449                    // fixed.
1450                    std::make_pair(
1451                        std::string("OpMemoryModel Logical OpenCL "
1452                                    "OpEntryPoint Kernel %func \"compute\" \n"
1453                                    "OpDecorate %1 SpecId 1 "
1454                                    "%intt = OpTypeInt 32 0 "
1455                                    "%1 = OpSpecConstant %intt 0") +
1456                            std::string(kVoidFVoid),
1457                        KernelDependencies()),
1458                    std::make_pair(
1459                        std::string("OpMemoryModel Logical Simple "
1460                                    "OpEntryPoint Vertex %func \"shader\" \n"
1461                                    "OpDecorate %1 SpecId 1 "
1462                                    "%intt = OpTypeInt 32 0 "
1463                                    "%1 = OpSpecConstant %intt 0") +
1464                            std::string(kVoidFVoid),
1465                        ShaderDependencies()))));
1466 // clang-format off
1467 
1468 INSTANTIATE_TEST_SUITE_P(BuiltIn, ValidateCapability,
1469                         Combine(
1470                             ValuesIn(AllCapabilities()),
1471                             Values(
1472 std::make_pair(std::string(kOpenCLMemoryModel) +
1473           "OpEntryPoint Kernel %func \"compute\" \n" +
1474           "OpDecorate %int0 BuiltIn Position\n"
1475           "%intt = OpTypeInt 32 0\n"
1476           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1477           ShaderDependencies()),
1478 // Just mentioning PointSize, ClipDistance, or CullDistance as a BuiltIn does
1479 // not trigger the requirement for the associated capability.
1480 // See https://github.com/KhronosGroup/SPIRV-Tools/issues/365
1481 std::make_pair(std::string(kOpenCLMemoryModel) +
1482           "OpEntryPoint Kernel %func \"compute\" \n" +
1483           "OpDecorate %int0 BuiltIn PointSize\n"
1484           "%intt = OpTypeInt 32 0\n"
1485           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1486           AllCapabilities()),
1487 std::make_pair(std::string(kOpenCLMemoryModel) +
1488           "OpEntryPoint Kernel %func \"compute\" \n" +
1489           "OpDecorate %int0 BuiltIn ClipDistance\n"
1490           "%intt = OpTypeInt 32 0\n"
1491           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1492           AllCapabilities()),
1493 std::make_pair(std::string(kOpenCLMemoryModel) +
1494           "OpEntryPoint Kernel %func \"compute\" \n" +
1495           "OpDecorate %int0 BuiltIn CullDistance\n"
1496           "%intt = OpTypeInt 32 0\n"
1497           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1498           AllCapabilities()),
1499 std::make_pair(std::string(kOpenCLMemoryModel) +
1500           "OpEntryPoint Kernel %func \"compute\" \n" +
1501           "OpDecorate %int0 BuiltIn VertexId\n"
1502           "%intt = OpTypeInt 32 0\n"
1503           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1504           ShaderDependencies()),
1505 std::make_pair(std::string(kOpenCLMemoryModel) +
1506           "OpEntryPoint Kernel %func \"compute\" \n" +
1507           "OpDecorate %int0 BuiltIn InstanceId\n"
1508           "%intt = OpTypeInt 32 0\n"
1509           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1510           ShaderDependencies()),
1511 std::make_pair(std::string(kOpenCLMemoryModel) +
1512           "OpEntryPoint Kernel %func \"compute\" \n" +
1513           "OpDecorate %int0 BuiltIn PrimitiveId\n"
1514           "%intt = OpTypeInt 32 0\n"
1515           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1516           GeometryTessellationDependencies()),
1517 std::make_pair(std::string(kOpenCLMemoryModel) +
1518           "OpEntryPoint Kernel %func \"compute\" \n" +
1519           "OpDecorate %int0 BuiltIn InvocationId\n"
1520           "%intt = OpTypeInt 32 0\n"
1521           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1522           GeometryTessellationDependencies()),
1523 std::make_pair(std::string(kOpenCLMemoryModel) +
1524           "OpEntryPoint Kernel %func \"compute\" \n" +
1525           "OpDecorate %int0 BuiltIn Layer\n"
1526           "%intt = OpTypeInt 32 0\n"
1527           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1528           GeometryDependencies()),
1529 std::make_pair(std::string(kOpenCLMemoryModel) +
1530           "OpEntryPoint Kernel %func \"compute\" \n" +
1531           "OpDecorate %int0 BuiltIn ViewportIndex\n"
1532           "%intt = OpTypeInt 32 0\n"
1533           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1534           std::vector<std::string>{"MultiViewport"}),
1535 std::make_pair(std::string(kOpenCLMemoryModel) +
1536           "OpEntryPoint Kernel %func \"compute\" \n" +
1537           "OpDecorate %int0 BuiltIn TessLevelOuter\n"
1538           "%intt = OpTypeInt 32 0\n"
1539           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1540           TessellationDependencies()),
1541 std::make_pair(std::string(kOpenCLMemoryModel) +
1542           "OpEntryPoint Kernel %func \"compute\" \n" +
1543           "OpDecorate %int0 BuiltIn TessLevelInner\n"
1544           "%intt = OpTypeInt 32 0\n"
1545           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1546           TessellationDependencies()),
1547 std::make_pair(std::string(kOpenCLMemoryModel) +
1548           "OpEntryPoint Kernel %func \"compute\" \n" +
1549           "OpDecorate %int0 BuiltIn TessCoord\n"
1550           "%intt = OpTypeInt 32 0\n"
1551           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1552           TessellationDependencies()),
1553 std::make_pair(std::string(kOpenCLMemoryModel) +
1554           "OpEntryPoint Kernel %func \"compute\" \n" +
1555           "OpDecorate %int0 BuiltIn PatchVertices\n"
1556           "%intt = OpTypeInt 32 0\n"
1557           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1558           TessellationDependencies()),
1559 std::make_pair(std::string(kOpenCLMemoryModel) +
1560           "OpEntryPoint Kernel %func \"compute\" \n" +
1561           "OpDecorate %int0 BuiltIn FragCoord\n"
1562           "%intt = OpTypeInt 32 0\n"
1563           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1564           ShaderDependencies()),
1565 std::make_pair(std::string(kOpenCLMemoryModel) +
1566           "OpEntryPoint Kernel %func \"compute\" \n" +
1567           "OpDecorate %int0 BuiltIn PointCoord\n"
1568           "%intt = OpTypeInt 32 0\n"
1569           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1570           ShaderDependencies()),
1571 std::make_pair(std::string(kOpenCLMemoryModel) +
1572           "OpEntryPoint Kernel %func \"compute\" \n" +
1573           "OpDecorate %int0 BuiltIn FrontFacing\n"
1574           "%intt = OpTypeInt 32 0\n"
1575           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1576           ShaderDependencies()),
1577 std::make_pair(std::string(kOpenCLMemoryModel) +
1578           "OpEntryPoint Kernel %func \"compute\" \n" +
1579           "OpDecorate %int0 BuiltIn SampleId\n"
1580           "%intt = OpTypeInt 32 0\n"
1581           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1582           std::vector<std::string>{"SampleRateShading"}),
1583 std::make_pair(std::string(kOpenCLMemoryModel) +
1584           "OpEntryPoint Kernel %func \"compute\" \n" +
1585           "OpDecorate %int0 BuiltIn SamplePosition\n"
1586           "%intt = OpTypeInt 32 0\n"
1587           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1588           std::vector<std::string>{"SampleRateShading"}),
1589 std::make_pair(std::string(kOpenCLMemoryModel) +
1590           "OpEntryPoint Kernel %func \"compute\" \n" +
1591           "OpDecorate %int0 BuiltIn SampleMask\n"
1592           "%intt = OpTypeInt 32 0\n"
1593           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1594           ShaderDependencies()),
1595 std::make_pair(std::string(kOpenCLMemoryModel) +
1596           "OpEntryPoint Kernel %func \"compute\" \n" +
1597           "OpDecorate %int0 BuiltIn FragDepth\n"
1598           "%intt = OpTypeInt 32 0\n"
1599           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1600           ShaderDependencies()),
1601 std::make_pair(std::string(kOpenCLMemoryModel) +
1602           "OpEntryPoint Kernel %func \"compute\" \n" +
1603           "OpDecorate %int0 BuiltIn HelperInvocation\n"
1604           "%intt = OpTypeInt 32 0\n"
1605           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1606           ShaderDependencies()),
1607 std::make_pair(std::string(kOpenCLMemoryModel) +
1608           "OpEntryPoint Kernel %func \"compute\" \n" +
1609           "OpDecorate %int0 BuiltIn VertexIndex\n"
1610           "%intt = OpTypeInt 32 0\n"
1611           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1612           ShaderDependencies()),
1613 std::make_pair(std::string(kOpenCLMemoryModel) +
1614           "OpEntryPoint Kernel %func \"compute\" \n" +
1615           "OpDecorate %int0 BuiltIn InstanceIndex\n"
1616           "%intt = OpTypeInt 32 0\n"
1617           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1618           ShaderDependencies()),
1619 std::make_pair(std::string(kOpenCLMemoryModel) +
1620           "OpEntryPoint Kernel %func \"compute\" \n" +
1621           "OpDecorate %int0 BuiltIn NumWorkgroups\n"
1622           "%intt = OpTypeInt 32 0\n"
1623           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1624           AllCapabilities()),
1625 std::make_pair(std::string(kOpenCLMemoryModel) +
1626           "OpEntryPoint Kernel %func \"compute\" \n" +
1627           "OpDecorate %int0 BuiltIn WorkgroupSize\n"
1628           "%intt = OpTypeInt 32 0\n"
1629           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1630           AllCapabilities()),
1631 std::make_pair(std::string(kOpenCLMemoryModel) +
1632           "OpEntryPoint Kernel %func \"compute\" \n" +
1633           "OpDecorate %int0 BuiltIn WorkgroupId\n"
1634           "%intt = OpTypeInt 32 0\n"
1635           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1636           AllCapabilities()),
1637 std::make_pair(std::string(kOpenCLMemoryModel) +
1638           "OpEntryPoint Kernel %func \"compute\" \n" +
1639           "OpDecorate %int0 BuiltIn LocalInvocationId\n"
1640           "%intt = OpTypeInt 32 0\n"
1641           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1642           AllCapabilities()),
1643 std::make_pair(std::string(kOpenCLMemoryModel) +
1644           "OpEntryPoint Kernel %func \"compute\" \n" +
1645           "OpDecorate %int0 BuiltIn GlobalInvocationId\n"
1646           "%intt = OpTypeInt 32 0\n"
1647           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1648           AllCapabilities()),
1649 std::make_pair(std::string(kOpenCLMemoryModel) +
1650           "OpEntryPoint Kernel %func \"compute\" \n" +
1651           "OpDecorate %int0 BuiltIn LocalInvocationIndex\n"
1652           "%intt = OpTypeInt 32 0\n"
1653           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1654           AllCapabilities()),
1655 std::make_pair(std::string(kGLSL450MemoryModel) +
1656           "OpEntryPoint Vertex %func \"shader\" \n" +
1657           "OpDecorate %int0 BuiltIn WorkDim\n"
1658           "%intt = OpTypeInt 32 0\n"
1659           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1660           KernelDependencies()),
1661 std::make_pair(std::string(kGLSL450MemoryModel) +
1662           "OpEntryPoint Vertex %func \"shader\" \n" +
1663           "OpDecorate %int0 BuiltIn GlobalSize\n"
1664           "%intt = OpTypeInt 32 0\n"
1665           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1666           KernelDependencies()),
1667 std::make_pair(std::string(kGLSL450MemoryModel) +
1668           "OpEntryPoint Vertex %func \"shader\" \n" +
1669           "OpDecorate %int0 BuiltIn EnqueuedWorkgroupSize\n"
1670           "%intt = OpTypeInt 32 0\n"
1671           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1672           KernelDependencies()),
1673 std::make_pair(std::string(kGLSL450MemoryModel) +
1674           "OpEntryPoint Vertex %func \"shader\" \n" +
1675           "OpDecorate %int0 BuiltIn GlobalOffset\n"
1676           "%intt = OpTypeInt 32 0\n"
1677           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1678           KernelDependencies()),
1679 std::make_pair(std::string(kGLSL450MemoryModel) +
1680           "OpEntryPoint Vertex %func \"shader\" \n" +
1681           "OpDecorate %int0 BuiltIn GlobalLinearId\n"
1682           "%intt = OpTypeInt 32 0\n"
1683           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1684           KernelDependencies()),
1685 std::make_pair(std::string(kGLSL450MemoryModel) +
1686           "OpEntryPoint Vertex %func \"shader\" \n" +
1687           "OpDecorate %int0 BuiltIn SubgroupSize\n"
1688           "%intt = OpTypeInt 32 0\n"
1689           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1690           KernelAndGroupNonUniformDependencies()),
1691 std::make_pair(std::string(kGLSL450MemoryModel) +
1692           "OpEntryPoint Vertex %func \"shader\" \n" +
1693           "OpDecorate %int0 BuiltIn SubgroupMaxSize\n"
1694           "%intt = OpTypeInt 32 0\n"
1695           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1696           KernelDependencies()),
1697 std::make_pair(std::string(kGLSL450MemoryModel) +
1698           "OpEntryPoint Vertex %func \"shader\" \n" +
1699           "OpDecorate %int0 BuiltIn NumSubgroups\n"
1700           "%intt = OpTypeInt 32 0\n"
1701           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1702           KernelAndGroupNonUniformDependencies()),
1703 std::make_pair(std::string(kGLSL450MemoryModel) +
1704           "OpEntryPoint Vertex %func \"shader\" \n" +
1705           "OpDecorate %int0 BuiltIn NumEnqueuedSubgroups\n"
1706           "%intt = OpTypeInt 32 0\n"
1707           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1708           KernelDependencies()),
1709 std::make_pair(std::string(kGLSL450MemoryModel) +
1710           "OpEntryPoint Vertex %func \"shader\" \n" +
1711           "OpDecorate %int0 BuiltIn SubgroupId\n"
1712           "%intt = OpTypeInt 32 0\n"
1713           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1714           KernelAndGroupNonUniformDependencies()),
1715 std::make_pair(std::string(kGLSL450MemoryModel) +
1716           "OpEntryPoint Vertex %func \"shader\" \n" +
1717           "OpDecorate %int0 BuiltIn SubgroupLocalInvocationId\n"
1718           "%intt = OpTypeInt 32 0\n"
1719           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1720           KernelAndGroupNonUniformDependencies()),
1721 std::make_pair(std::string(kOpenCLMemoryModel) +
1722           "OpEntryPoint Kernel %func \"compute\" \n" +
1723           "OpDecorate %int0 BuiltIn VertexIndex\n"
1724           "%intt = OpTypeInt 32 0\n"
1725           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1726           ShaderDependencies()),
1727 std::make_pair(std::string(kOpenCLMemoryModel) +
1728           "OpEntryPoint Kernel %func \"compute\" \n" +
1729           "OpDecorate %int0 BuiltIn InstanceIndex\n"
1730           "%intt = OpTypeInt 32 0\n"
1731           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1732           ShaderDependencies())
1733 )));
1734 
1735 // Ensure that mere mention of PointSize, ClipDistance, or CullDistance as
1736 // BuiltIns does not trigger the requirement for the associated
1737 // capability.
1738 // See https://github.com/KhronosGroup/SPIRV-Tools/issues/365
1739 INSTANTIATE_TEST_SUITE_P(BuiltIn, ValidateCapabilityVulkan10,
1740                         Combine(
1741                             // All capabilities to try.
1742                             ValuesIn(AllSpirV10Capabilities()),
1743                             Values(
1744 std::make_pair(std::string(kGLSL450MemoryModel) +
1745           "OpEntryPoint Vertex %func \"shader\" \n"
1746           "OpMemberDecorate %block 0 BuiltIn PointSize\n"
1747           "%f32 = OpTypeFloat 32\n"
1748           "%block = OpTypeStruct %f32\n"
1749           "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
1750           // Capabilities which should succeed.
1751           AllVulkan10Capabilities()),
1752 std::make_pair(std::string(kGLSL450MemoryModel) +
1753           "OpEntryPoint Vertex %func \"shader\" \n"
1754           "OpMemberDecorate %block 0 BuiltIn ClipDistance\n"
1755           "%f32 = OpTypeFloat 32\n"
1756           "%intt = OpTypeInt 32 0\n"
1757           "%intt_4 = OpConstant %intt 4\n"
1758           "%f32arr4 = OpTypeArray %f32 %intt_4\n"
1759           "%block = OpTypeStruct %f32arr4\n" + std::string(kVoidFVoid),
1760           AllVulkan10Capabilities()),
1761 std::make_pair(std::string(kGLSL450MemoryModel) +
1762           "OpEntryPoint Vertex %func \"shader\" \n"
1763           "OpMemberDecorate %block 0 BuiltIn CullDistance\n"
1764           "%f32 = OpTypeFloat 32\n"
1765           "%intt = OpTypeInt 32 0\n"
1766           "%intt_4 = OpConstant %intt 4\n"
1767           "%f32arr4 = OpTypeArray %f32 %intt_4\n"
1768           "%block = OpTypeStruct %f32arr4\n" + std::string(kVoidFVoid),
1769           AllVulkan10Capabilities())
1770 )));
1771 
1772 INSTANTIATE_TEST_SUITE_P(BuiltIn, ValidateCapabilityOpenGL40,
1773                         Combine(
1774                             // OpenGL 4.0 is based on SPIR-V 1.0
1775                             ValuesIn(AllSpirV10Capabilities()),
1776                             Values(
1777 std::make_pair(std::string(kGLSL450MemoryModel) +
1778           "OpEntryPoint Vertex %func \"shader\" \n" +
1779           "OpDecorate %int0 BuiltIn PointSize\n"
1780           "%intt = OpTypeInt 32 0\n"
1781           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1782           AllSpirV10Capabilities()),
1783 std::make_pair(std::string(kGLSL450MemoryModel) +
1784           "OpEntryPoint Vertex %func \"shader\" \n" +
1785           "OpDecorate %int0 BuiltIn ClipDistance\n"
1786           "%intt = OpTypeInt 32 0\n"
1787           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1788           AllSpirV10Capabilities()),
1789 std::make_pair(std::string(kGLSL450MemoryModel) +
1790           "OpEntryPoint Vertex %func \"shader\" \n" +
1791           "OpDecorate %int0 BuiltIn CullDistance\n"
1792           "%intt = OpTypeInt 32 0\n"
1793           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1794           AllSpirV10Capabilities())
1795 )));
1796 
1797 INSTANTIATE_TEST_SUITE_P(Capabilities, ValidateCapabilityVulkan11,
1798                         Combine(
1799                             // All capabilities to try.
1800                             ValuesIn(AllCapabilities()),
1801                             Values(
1802 std::make_pair(std::string(kGLSL450MemoryModel) +
1803           "OpEntryPoint Vertex %func \"shader\" \n" +
1804           "OpDecorate %int0 BuiltIn PointSize\n"
1805           "%intt = OpTypeInt 32 0\n"
1806           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1807           AllVulkan11Capabilities()),
1808 std::make_pair(std::string(kGLSL450MemoryModel) +
1809           "OpEntryPoint Vertex %func \"shader\" \n" +
1810           "OpDecorate %int0 BuiltIn CullDistance\n"
1811           "%intt = OpTypeInt 32 0\n"
1812           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1813           AllVulkan11Capabilities())
1814 )));
1815 
1816 INSTANTIATE_TEST_SUITE_P(Capabilities, ValidateCapabilityVulkan12,
1817                         Combine(
1818                             // All capabilities to try.
1819                             ValuesIn(AllSpirV15Capabilities()),
1820                             Values(
1821 std::make_pair(std::string(kGLSL450MemoryModel) +
1822           "OpEntryPoint Vertex %func \"shader\" \n" +
1823           "OpDecorate %int0 BuiltIn PointSize\n"
1824           "%intt = OpTypeInt 32 0\n"
1825           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1826           AllVulkan12Capabilities()),
1827 std::make_pair(std::string(kGLSL450MemoryModel) +
1828           "OpEntryPoint Vertex %func \"shader\" \n" +
1829           "OpDecorate %int0 BuiltIn CullDistance\n"
1830           "%intt = OpTypeInt 32 0\n"
1831           "%int0 = OpConstant %intt 0\n" + std::string(kVoidFVoid),
1832           AllVulkan12Capabilities())
1833 )));
1834 
1835 // TODO(umar): Selection Control
1836 // TODO(umar): Loop Control
1837 // TODO(umar): Function Control
1838 // TODO(umar): Memory Semantics
1839 // TODO(umar): Memory Access
1840 // TODO(umar): Scope
1841 // TODO(umar): Group Operation
1842 // TODO(umar): Kernel Enqueue Flags
1843 // TODO(umar): Kernel Profiling Flags
1844 
1845 INSTANTIATE_TEST_SUITE_P(MatrixOp, ValidateCapability,
1846                         Combine(
1847                             ValuesIn(AllCapabilities()),
1848                             Values(
1849 std::make_pair(std::string(kOpenCLMemoryModel) +
1850           "OpEntryPoint Kernel %func \"compute\" \n" +
1851           "%f32      = OpTypeFloat 32\n"
1852           "%vec3     = OpTypeVector %f32 3\n"
1853           "%mat33    = OpTypeMatrix %vec3 3\n" + std::string(kVoidFVoid),
1854           MatrixDependencies()))));
1855 // clang-format on
1856 
1857 #if 0
1858 // TODO(atgoo@github.com) The following test is not valid as it generates
1859 // invalid combinations of images, instructions and image operands.
1860 //
1861 // Creates assembly containing an OpImageFetch instruction using operands for
1862 // the image-operands part.  The assembly defines constants %fzero and %izero
1863 // that can be used for operands where IDs are required.  The assembly is valid,
1864 // apart from not declaring any capabilities required by the operands.
1865 string ImageOperandsTemplate(const std::string& operands) {
1866   ostringstream ss;
1867   // clang-format off
1868   ss << R"(
1869 OpCapability Kernel
1870 OpCapability Linkage
1871 OpMemoryModel Logical OpenCL
1872 
1873 %i32 = OpTypeInt 32 0
1874 %f32 = OpTypeFloat 32
1875 %v4i32 = OpTypeVector %i32 4
1876 %timg = OpTypeImage %i32 2D 0 0 0 0 Unknown
1877 %pimg = OpTypePointer UniformConstant %timg
1878 %tfun = OpTypeFunction %i32
1879 
1880 %vimg = OpVariable %pimg UniformConstant
1881 %izero = OpConstant %i32 0
1882 %fzero = OpConstant %f32 0.
1883 
1884 %main = OpFunction %i32 None %tfun
1885 %lbl = OpLabel
1886 %img = OpLoad %timg %vimg
1887 %r1 = OpImageFetch %v4i32 %img %izero )" << operands << R"(
1888 OpReturnValue %izero
1889 OpFunctionEnd
1890 )";
1891   // clang-format on
1892   return ss.str();
1893 }
1894 
1895 INSTANTIATE_TEST_SUITE_P(
1896     TwoImageOperandsMask, ValidateCapability,
1897     Combine(
1898         ValuesIn(AllCapabilities()),
1899         Values(std::make_pair(ImageOperandsTemplate("Bias|Lod %fzero %fzero"),
1900                          ShaderDependencies()),
1901                std::make_pair(ImageOperandsTemplate("Lod|Offset %fzero %izero"),
1902                          std::vector<std::string>{"ImageGatherExtended"}),
1903                std::make_pair(ImageOperandsTemplate("Sample|MinLod %izero %fzero"),
1904                          std::vector<std::string>{"MinLod"}),
1905                std::make_pair(ImageOperandsTemplate("Lod|Sample %fzero %izero"),
1906                          AllCapabilities()))), );
1907 #endif
1908 
1909 // TODO(umar): Instruction capability checks
1910 
spvCoreOperandTableNameLookup(spv_target_env env,const spv_operand_table table,const spv_operand_type_t type,const char * name,const size_t nameLength)1911 spv_result_t spvCoreOperandTableNameLookup(spv_target_env env,
1912                                            const spv_operand_table table,
1913                                            const spv_operand_type_t type,
1914                                            const char* name,
1915                                            const size_t nameLength) {
1916   if (!table) return SPV_ERROR_INVALID_TABLE;
1917   if (!name) return SPV_ERROR_INVALID_POINTER;
1918 
1919   for (uint64_t typeIndex = 0; typeIndex < table->count; ++typeIndex) {
1920     const auto& group = table->types[typeIndex];
1921     if (type != group.type) continue;
1922     for (uint64_t index = 0; index < group.count; ++index) {
1923       const auto& entry = group.entries[index];
1924       // Check for min version only.
1925       if (spvVersionForTargetEnv(env) >= entry.minVersion &&
1926           nameLength == strlen(entry.name) &&
1927           !strncmp(entry.name, name, nameLength)) {
1928         return SPV_SUCCESS;
1929       }
1930     }
1931   }
1932 
1933   return SPV_ERROR_INVALID_LOOKUP;
1934 }
1935 
1936 // True if capability exists in core spec of env.
Exists(const std::string & capability,spv_target_env env)1937 bool Exists(const std::string& capability, spv_target_env env) {
1938   ScopedContext sc(env);
1939   return SPV_SUCCESS ==
1940          spvCoreOperandTableNameLookup(env, sc.context->operand_table,
1941                                        SPV_OPERAND_TYPE_CAPABILITY,
1942                                        capability.c_str(), capability.size());
1943 }
1944 
TEST_P(ValidateCapability,Capability)1945 TEST_P(ValidateCapability, Capability) {
1946   const std::string capability = Capability(GetParam());
1947   spv_target_env env = SPV_ENV_UNIVERSAL_1_0;
1948   if (!capability.empty()) {
1949     if (Exists(capability, SPV_ENV_UNIVERSAL_1_0))
1950       env = SPV_ENV_UNIVERSAL_1_0;
1951     else if (Exists(capability, SPV_ENV_UNIVERSAL_1_1))
1952       env = SPV_ENV_UNIVERSAL_1_1;
1953     else if (Exists(capability, SPV_ENV_UNIVERSAL_1_2))
1954       env = SPV_ENV_UNIVERSAL_1_2;
1955     else
1956       env = SPV_ENV_UNIVERSAL_1_3;
1957   }
1958   const std::string test_code = MakeAssembly(GetParam());
1959   CompileSuccessfully(test_code, env);
1960   ASSERT_EQ(ExpectedResult(GetParam()), ValidateInstructions(env))
1961       << "target env: " << spvTargetEnvDescription(env) << "\ntest code:\n"
1962       << test_code;
1963 }
1964 
TEST_P(ValidateCapabilityV11,Capability)1965 TEST_P(ValidateCapabilityV11, Capability) {
1966   const std::string capability = Capability(GetParam());
1967   if (Exists(capability, SPV_ENV_UNIVERSAL_1_1)) {
1968     const std::string test_code = MakeAssembly(GetParam());
1969     CompileSuccessfully(test_code, SPV_ENV_UNIVERSAL_1_1);
1970     ASSERT_EQ(ExpectedResult(GetParam()),
1971               ValidateInstructions(SPV_ENV_UNIVERSAL_1_1))
1972         << test_code;
1973   }
1974 }
1975 
TEST_P(ValidateCapabilityVulkan10,Capability)1976 TEST_P(ValidateCapabilityVulkan10, Capability) {
1977   const std::string capability = Capability(GetParam());
1978   if (Exists(capability, SPV_ENV_VULKAN_1_0)) {
1979     const std::string test_code = MakeAssembly(GetParam());
1980     CompileSuccessfully(test_code, SPV_ENV_VULKAN_1_0);
1981     ASSERT_EQ(ExpectedResult(GetParam()),
1982               ValidateInstructions(SPV_ENV_VULKAN_1_0))
1983         << test_code;
1984   }
1985 }
1986 
TEST_P(ValidateCapabilityVulkan11,Capability)1987 TEST_P(ValidateCapabilityVulkan11, Capability) {
1988   const std::string capability = Capability(GetParam());
1989   if (Exists(capability, SPV_ENV_VULKAN_1_1)) {
1990     const std::string test_code = MakeAssembly(GetParam());
1991     CompileSuccessfully(test_code, SPV_ENV_VULKAN_1_1);
1992     ASSERT_EQ(ExpectedResult(GetParam()),
1993               ValidateInstructions(SPV_ENV_VULKAN_1_1))
1994         << test_code;
1995   }
1996 }
1997 
TEST_P(ValidateCapabilityVulkan12,Capability)1998 TEST_P(ValidateCapabilityVulkan12, Capability) {
1999   const std::string capability = Capability(GetParam());
2000   if (Exists(capability, SPV_ENV_VULKAN_1_2)) {
2001     const std::string test_code = MakeAssembly(GetParam());
2002     CompileSuccessfully(test_code, SPV_ENV_VULKAN_1_2);
2003     ASSERT_EQ(ExpectedResult(GetParam()),
2004               ValidateInstructions(SPV_ENV_VULKAN_1_2))
2005         << test_code;
2006   }
2007 }
2008 
TEST_P(ValidateCapabilityOpenGL40,Capability)2009 TEST_P(ValidateCapabilityOpenGL40, Capability) {
2010   const std::string capability = Capability(GetParam());
2011   if (Exists(capability, SPV_ENV_OPENGL_4_0)) {
2012     const std::string test_code = MakeAssembly(GetParam());
2013     CompileSuccessfully(test_code, SPV_ENV_OPENGL_4_0);
2014     ASSERT_EQ(ExpectedResult(GetParam()),
2015               ValidateInstructions(SPV_ENV_OPENGL_4_0))
2016         << test_code;
2017   }
2018 }
2019 
TEST_F(ValidateCapability,SemanticsIdIsAnIdNotALiteral)2020 TEST_F(ValidateCapability, SemanticsIdIsAnIdNotALiteral) {
2021   // From https://github.com/KhronosGroup/SPIRV-Tools/issues/248
2022   // The validator was interpreting the memory semantics ID number
2023   // as the value to be checked rather than an ID that references
2024   // another value to be checked.
2025   // In this case a raw ID of 64 was mistaken to mean a literal
2026   // semantic value of UniformMemory, which would require the Shader
2027   // capability.
2028   const char str[] = R"(
2029 OpCapability Kernel
2030 OpCapability Linkage
2031 OpMemoryModel Logical OpenCL
2032 
2033 ;  %i32 has ID 1
2034 %i32    = OpTypeInt 32 0
2035 %tf     = OpTypeFunction %i32
2036 %pi32   = OpTypePointer CrossWorkgroup %i32
2037 %var    = OpVariable %pi32 CrossWorkgroup
2038 %c      = OpConstant %i32 100
2039 %scope  = OpConstant %i32 1 ; Device scope
2040 
2041 ; Fake an instruction with 64 as the result id.
2042 ; !64 = OpConstantNull %i32
2043 !0x3002e !1 !64
2044 
2045 %f = OpFunction %i32 None %tf
2046 %l = OpLabel
2047 %result = OpAtomicIAdd %i32 %var %scope !64 %c
2048 OpReturnValue %result
2049 OpFunctionEnd
2050 )";
2051 
2052   CompileSuccessfully(str);
2053 
2054   // Since we are forcing usage of <id> 64, the "id bound" in the binary header
2055   // must be overwritten so that <id> 64 is considered within bound.
2056   // ID Bound is at index 3 of the binary. Set it to 65.
2057   OverwriteAssembledBinary(3, 65);
2058 
2059   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
2060 }
2061 
TEST_F(ValidateCapability,IntSignednessKernelGood)2062 TEST_F(ValidateCapability, IntSignednessKernelGood) {
2063   const std::string spirv = R"(
2064 OpCapability Kernel
2065 OpCapability Linkage
2066 OpMemoryModel Logical OpenCL
2067 %i32    = OpTypeInt 32 0
2068 )";
2069   CompileSuccessfully(spirv);
2070   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2071 }
2072 
TEST_F(ValidateCapability,IntSignednessKernelBad)2073 TEST_F(ValidateCapability, IntSignednessKernelBad) {
2074   const std::string spirv = R"(
2075 OpCapability Kernel
2076 OpCapability Linkage
2077 OpMemoryModel Logical OpenCL
2078 %i32    = OpTypeInt 32 1
2079 )";
2080   CompileSuccessfully(spirv);
2081   EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions());
2082   EXPECT_THAT(getDiagnosticString(),
2083               HasSubstr("The Signedness in OpTypeInt must always be 0 when "
2084                         "Kernel capability is used."));
2085 }
2086 
TEST_F(ValidateCapability,IntSignednessShaderGood)2087 TEST_F(ValidateCapability, IntSignednessShaderGood) {
2088   const std::string spirv = R"(
2089 OpCapability Shader
2090 OpCapability Linkage
2091 OpMemoryModel Logical GLSL450
2092 %u32    = OpTypeInt 32 0
2093 %i32    = OpTypeInt 32 1
2094 )";
2095   CompileSuccessfully(spirv);
2096   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2097 }
2098 
TEST_F(ValidateCapability,NonVulkan10Capability)2099 TEST_F(ValidateCapability, NonVulkan10Capability) {
2100   const std::string spirv = R"(
2101 OpCapability Shader
2102 OpCapability Linkage
2103 OpMemoryModel Logical GLSL450
2104 %u32    = OpTypeInt 32 0
2105 %i32    = OpTypeInt 32 1
2106 )";
2107   CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
2108   EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
2109             ValidateInstructions(SPV_ENV_VULKAN_1_0));
2110   EXPECT_THAT(getDiagnosticString(),
2111               HasSubstr("Capability Linkage is not allowed by Vulkan 1.0"));
2112 }
2113 
TEST_F(ValidateCapability,Vulkan10EnabledByExtension)2114 TEST_F(ValidateCapability, Vulkan10EnabledByExtension) {
2115   const std::string spirv = R"(
2116 OpCapability Shader
2117 OpCapability DrawParameters
2118 OpExtension "SPV_KHR_shader_draw_parameters"
2119 OpMemoryModel Logical GLSL450
2120 OpEntryPoint Vertex %func "shader"
2121 OpMemberDecorate %block 0 BuiltIn PointSize
2122 %f32 = OpTypeFloat 32
2123 %block = OpTypeStruct %f32
2124 )" + std::string(kVoidFVoid);
2125 
2126   CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
2127   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
2128 }
2129 
TEST_F(ValidateCapability,Vulkan10NotEnabledByExtension)2130 TEST_F(ValidateCapability, Vulkan10NotEnabledByExtension) {
2131   const std::string spirv = R"(
2132 OpCapability Shader
2133 OpCapability DrawParameters
2134 OpMemoryModel Logical GLSL450
2135 OpEntryPoint Vertex %func "shader"
2136 OpDecorate %intt BuiltIn PointSize
2137 %intt = OpTypeInt 32 0
2138 )" + std::string(kVoidFVoid);
2139 
2140   CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
2141   EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
2142             ValidateInstructions(SPV_ENV_VULKAN_1_0));
2143   EXPECT_THAT(
2144       getDiagnosticString(),
2145       HasSubstr("Capability DrawParameters is not allowed by Vulkan 1.0"));
2146 }
2147 
TEST_F(ValidateCapability,NonOpenCL12FullCapability)2148 TEST_F(ValidateCapability, NonOpenCL12FullCapability) {
2149   const std::string spirv = R"(
2150 OpCapability Kernel
2151 OpCapability Addresses
2152 OpCapability Linkage
2153 OpCapability Pipes
2154 OpMemoryModel Physical64 OpenCL
2155 %u32    = OpTypeInt 32 0
2156 )";
2157   CompileSuccessfully(spirv, SPV_ENV_OPENCL_1_2);
2158   EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
2159             ValidateInstructions(SPV_ENV_OPENCL_1_2));
2160   EXPECT_THAT(
2161       getDiagnosticString(),
2162       HasSubstr("Capability Pipes is not allowed by OpenCL 1.2 Full Profile"));
2163 }
2164 
TEST_F(ValidateCapability,OpenCL12FullEnabledByCapability)2165 TEST_F(ValidateCapability, OpenCL12FullEnabledByCapability) {
2166   const std::string spirv = R"(
2167 OpCapability Kernel
2168 OpCapability Addresses
2169 OpCapability Linkage
2170 OpCapability ImageBasic
2171 OpCapability Sampled1D
2172 OpMemoryModel Physical64 OpenCL
2173 %u32    = OpTypeInt 32 0
2174 )" + std::string(kVoidFVoid);
2175 
2176   CompileSuccessfully(spirv, SPV_ENV_OPENCL_1_2);
2177   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_1_2));
2178 }
2179 
TEST_F(ValidateCapability,OpenCL12FullNotEnabledByCapability)2180 TEST_F(ValidateCapability, OpenCL12FullNotEnabledByCapability) {
2181   const std::string spirv = R"(
2182 OpCapability Kernel
2183 OpCapability Addresses
2184 OpCapability Linkage
2185 OpCapability Sampled1D
2186 OpMemoryModel Physical64 OpenCL
2187 %u32    = OpTypeInt 32 0
2188 )" + std::string(kVoidFVoid);
2189 
2190   CompileSuccessfully(spirv, SPV_ENV_OPENCL_1_2);
2191   EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
2192             ValidateInstructions(SPV_ENV_OPENCL_1_2));
2193   EXPECT_THAT(
2194       getDiagnosticString(),
2195       HasSubstr(
2196           "Capability Sampled1D is not allowed by OpenCL 1.2 Full Profile"));
2197 }
2198 
TEST_F(ValidateCapability,NonOpenCL12EmbeddedCapability)2199 TEST_F(ValidateCapability, NonOpenCL12EmbeddedCapability) {
2200   const std::string spirv = R"(
2201 OpCapability Kernel
2202 OpCapability Addresses
2203 OpCapability Linkage
2204 OpCapability Int64
2205 OpMemoryModel Physical64 OpenCL
2206 %u32    = OpTypeInt 32 0
2207 )";
2208   CompileSuccessfully(spirv, SPV_ENV_OPENCL_EMBEDDED_1_2);
2209   EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
2210             ValidateInstructions(SPV_ENV_OPENCL_EMBEDDED_1_2));
2211   EXPECT_THAT(
2212       getDiagnosticString(),
2213       HasSubstr(
2214           "Capability Int64 is not allowed by OpenCL 1.2 Embedded Profile"));
2215 }
2216 
TEST_F(ValidateCapability,OpenCL12EmbeddedEnabledByCapability)2217 TEST_F(ValidateCapability, OpenCL12EmbeddedEnabledByCapability) {
2218   const std::string spirv = R"(
2219 OpCapability Kernel
2220 OpCapability Addresses
2221 OpCapability Linkage
2222 OpCapability ImageBasic
2223 OpCapability Sampled1D
2224 OpMemoryModel Physical64 OpenCL
2225 %u32    = OpTypeInt 32 0
2226 )" + std::string(kVoidFVoid);
2227 
2228   CompileSuccessfully(spirv, SPV_ENV_OPENCL_EMBEDDED_1_2);
2229   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_EMBEDDED_1_2));
2230 }
2231 
TEST_F(ValidateCapability,OpenCL12EmbeddedNotEnabledByCapability)2232 TEST_F(ValidateCapability, OpenCL12EmbeddedNotEnabledByCapability) {
2233   const std::string spirv = R"(
2234 OpCapability Kernel
2235 OpCapability Addresses
2236 OpCapability Linkage
2237 OpCapability Sampled1D
2238 OpMemoryModel Physical64 OpenCL
2239 %u32    = OpTypeInt 32 0
2240 )" + std::string(kVoidFVoid);
2241 
2242   CompileSuccessfully(spirv, SPV_ENV_OPENCL_EMBEDDED_1_2);
2243   EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
2244             ValidateInstructions(SPV_ENV_OPENCL_EMBEDDED_1_2));
2245   EXPECT_THAT(getDiagnosticString(),
2246               HasSubstr("Capability Sampled1D is not allowed by OpenCL 1.2 "
2247                         "Embedded Profile"));
2248 }
2249 
TEST_F(ValidateCapability,OpenCL12EmbeddedNoLongerEnabledByCapability)2250 TEST_F(ValidateCapability, OpenCL12EmbeddedNoLongerEnabledByCapability) {
2251   const std::string spirv = R"(
2252 OpCapability Kernel
2253 OpCapability Addresses
2254 OpCapability Linkage
2255 OpCapability Pipes
2256 OpMemoryModel Physical64 OpenCL
2257 %u32    = OpTypeInt 32 0
2258 )" + std::string(kVoidFVoid);
2259 
2260   CompileSuccessfully(spirv, SPV_ENV_OPENCL_EMBEDDED_1_2);
2261   EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
2262             ValidateInstructions(SPV_ENV_OPENCL_EMBEDDED_1_2));
2263   EXPECT_THAT(getDiagnosticString(),
2264               HasSubstr("Capability Pipes is not allowed by OpenCL 1.2 "
2265                         "Embedded Profile"));
2266 }
2267 
TEST_F(ValidateCapability,OpenCL20FullCapability)2268 TEST_F(ValidateCapability, OpenCL20FullCapability) {
2269   const std::string spirv = R"(
2270 OpCapability Kernel
2271 OpCapability Addresses
2272 OpCapability Linkage
2273 OpCapability Groups
2274 OpCapability Pipes
2275 OpMemoryModel Physical64 OpenCL
2276 %u32    = OpTypeInt 32 0
2277 )";
2278   CompileSuccessfully(spirv, SPV_ENV_OPENCL_2_0);
2279   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_2_0));
2280 }
2281 
TEST_F(ValidateCapability,NonOpenCL20FullCapability)2282 TEST_F(ValidateCapability, NonOpenCL20FullCapability) {
2283   const std::string spirv = R"(
2284 OpCapability Kernel
2285 OpCapability Addresses
2286 OpCapability Linkage
2287 OpCapability Matrix
2288 OpMemoryModel Physical64 OpenCL
2289 %u32    = OpTypeInt 32 0
2290 )";
2291   CompileSuccessfully(spirv, SPV_ENV_OPENCL_2_0);
2292   EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
2293             ValidateInstructions(SPV_ENV_OPENCL_2_0));
2294   EXPECT_THAT(
2295       getDiagnosticString(),
2296       HasSubstr(
2297           "Capability Matrix is not allowed by OpenCL 2.0/2.1 Full Profile"));
2298 }
2299 
TEST_F(ValidateCapability,OpenCL20FullEnabledByCapability)2300 TEST_F(ValidateCapability, OpenCL20FullEnabledByCapability) {
2301   const std::string spirv = R"(
2302 OpCapability Kernel
2303 OpCapability Addresses
2304 OpCapability Linkage
2305 OpCapability ImageBasic
2306 OpCapability Sampled1D
2307 OpMemoryModel Physical64 OpenCL
2308 %u32    = OpTypeInt 32 0
2309 )" + std::string(kVoidFVoid);
2310 
2311   CompileSuccessfully(spirv, SPV_ENV_OPENCL_2_0);
2312   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_2_0));
2313 }
2314 
TEST_F(ValidateCapability,OpenCL20FullNotEnabledByCapability)2315 TEST_F(ValidateCapability, OpenCL20FullNotEnabledByCapability) {
2316   const std::string spirv = R"(
2317 OpCapability Kernel
2318 OpCapability Addresses
2319 OpCapability Linkage
2320 OpCapability Sampled1D
2321 OpMemoryModel Physical64 OpenCL
2322 %u32    = OpTypeInt 32 0
2323 )" + std::string(kVoidFVoid);
2324 
2325   CompileSuccessfully(spirv, SPV_ENV_OPENCL_2_0);
2326   EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
2327             ValidateInstructions(SPV_ENV_OPENCL_2_0));
2328   EXPECT_THAT(getDiagnosticString(),
2329               HasSubstr("Capability Sampled1D is not allowed by OpenCL 2.0/2.1 "
2330                         "Full Profile"));
2331 }
2332 
TEST_F(ValidateCapability,NonOpenCL20EmbeddedCapability)2333 TEST_F(ValidateCapability, NonOpenCL20EmbeddedCapability) {
2334   const std::string spirv = R"(
2335 OpCapability Kernel
2336 OpCapability Addresses
2337 OpCapability Linkage
2338 OpCapability Int64
2339 OpMemoryModel Physical64 OpenCL
2340 %u32    = OpTypeInt 32 0
2341 )";
2342   CompileSuccessfully(spirv, SPV_ENV_OPENCL_EMBEDDED_2_0);
2343   EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
2344             ValidateInstructions(SPV_ENV_OPENCL_EMBEDDED_2_0));
2345   EXPECT_THAT(getDiagnosticString(),
2346               HasSubstr("Capability Int64 is not allowed by OpenCL 2.0/2.1 "
2347                         "Embedded Profile"));
2348 }
2349 
TEST_F(ValidateCapability,OpenCL20EmbeddedEnabledByCapability)2350 TEST_F(ValidateCapability, OpenCL20EmbeddedEnabledByCapability) {
2351   const std::string spirv = R"(
2352 OpCapability Kernel
2353 OpCapability Addresses
2354 OpCapability Linkage
2355 OpCapability ImageBasic
2356 OpCapability Sampled1D
2357 OpMemoryModel Physical64 OpenCL
2358 %u32    = OpTypeInt 32 0
2359 )" + std::string(kVoidFVoid);
2360 
2361   CompileSuccessfully(spirv, SPV_ENV_OPENCL_EMBEDDED_2_0);
2362   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_EMBEDDED_2_0));
2363 }
2364 
TEST_F(ValidateCapability,OpenCL20EmbeddedNotEnabledByCapability)2365 TEST_F(ValidateCapability, OpenCL20EmbeddedNotEnabledByCapability) {
2366   const std::string spirv = R"(
2367 OpCapability Kernel
2368 OpCapability Addresses
2369 OpCapability Linkage
2370 OpCapability Sampled1D
2371 OpMemoryModel Physical64 OpenCL
2372 %u32    = OpTypeInt 32 0
2373 )" + std::string(kVoidFVoid);
2374 
2375   CompileSuccessfully(spirv, SPV_ENV_OPENCL_EMBEDDED_2_0);
2376   EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
2377             ValidateInstructions(SPV_ENV_OPENCL_EMBEDDED_2_0));
2378   EXPECT_THAT(getDiagnosticString(),
2379               HasSubstr("Capability Sampled1D is not allowed by OpenCL 2.0/2.1 "
2380                         "Embedded Profile"));
2381 }
2382 
TEST_F(ValidateCapability,OpenCL22FullCapability)2383 TEST_F(ValidateCapability, OpenCL22FullCapability) {
2384   const std::string spirv = R"(
2385 OpCapability Kernel
2386 OpCapability Addresses
2387 OpCapability Linkage
2388 OpCapability PipeStorage
2389 OpMemoryModel Physical64 OpenCL
2390 %u32    = OpTypeInt 32 0
2391 )";
2392   CompileSuccessfully(spirv, SPV_ENV_OPENCL_2_2);
2393   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_2_2));
2394 }
2395 
TEST_F(ValidateCapability,NonOpenCL22FullCapability)2396 TEST_F(ValidateCapability, NonOpenCL22FullCapability) {
2397   const std::string spirv = R"(
2398 OpCapability Kernel
2399 OpCapability Addresses
2400 OpCapability Linkage
2401 OpCapability Matrix
2402 OpMemoryModel Physical64 OpenCL
2403 %u32    = OpTypeInt 32 0
2404 )";
2405   CompileSuccessfully(spirv, SPV_ENV_OPENCL_2_2);
2406   EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
2407             ValidateInstructions(SPV_ENV_OPENCL_2_2));
2408   EXPECT_THAT(
2409       getDiagnosticString(),
2410       HasSubstr("Capability Matrix is not allowed by OpenCL 2.2 Full Profile"));
2411 }
2412 
TEST_F(ValidateCapability,OpenCL22FullEnabledByCapability)2413 TEST_F(ValidateCapability, OpenCL22FullEnabledByCapability) {
2414   const std::string spirv = R"(
2415 OpCapability Kernel
2416 OpCapability Addresses
2417 OpCapability Linkage
2418 OpCapability ImageBasic
2419 OpCapability Sampled1D
2420 OpMemoryModel Physical64 OpenCL
2421 %u32    = OpTypeInt 32 0
2422 )" + std::string(kVoidFVoid);
2423 
2424   CompileSuccessfully(spirv, SPV_ENV_OPENCL_2_2);
2425   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_2_2));
2426 }
2427 
TEST_F(ValidateCapability,OpenCL22FullNotEnabledByCapability)2428 TEST_F(ValidateCapability, OpenCL22FullNotEnabledByCapability) {
2429   const std::string spirv = R"(
2430 OpCapability Kernel
2431 OpCapability Addresses
2432 OpCapability Linkage
2433 OpCapability Sampled1D
2434 OpMemoryModel Physical64 OpenCL
2435 %u32    = OpTypeInt 32 0
2436 )" + std::string(kVoidFVoid);
2437 
2438   CompileSuccessfully(spirv, SPV_ENV_OPENCL_2_2);
2439   EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
2440             ValidateInstructions(SPV_ENV_OPENCL_2_2));
2441   EXPECT_THAT(
2442       getDiagnosticString(),
2443       HasSubstr(
2444           "Capability Sampled1D is not allowed by OpenCL 2.2 Full Profile"));
2445 }
2446 
TEST_F(ValidateCapability,NonOpenCL22EmbeddedCapability)2447 TEST_F(ValidateCapability, NonOpenCL22EmbeddedCapability) {
2448   const std::string spirv = R"(
2449 OpCapability Kernel
2450 OpCapability Addresses
2451 OpCapability Linkage
2452 OpCapability Int64
2453 OpMemoryModel Physical64 OpenCL
2454 %u32    = OpTypeInt 32 0
2455 )";
2456   CompileSuccessfully(spirv, SPV_ENV_OPENCL_EMBEDDED_2_2);
2457   EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
2458             ValidateInstructions(SPV_ENV_OPENCL_EMBEDDED_2_2));
2459   EXPECT_THAT(
2460       getDiagnosticString(),
2461       HasSubstr(
2462           "Capability Int64 is not allowed by OpenCL 2.2 Embedded Profile"));
2463 }
2464 
TEST_F(ValidateCapability,OpenCL22EmbeddedEnabledByCapability)2465 TEST_F(ValidateCapability, OpenCL22EmbeddedEnabledByCapability) {
2466   const std::string spirv = R"(
2467 OpCapability Kernel
2468 OpCapability Addresses
2469 OpCapability Linkage
2470 OpCapability ImageBasic
2471 OpCapability Sampled1D
2472 OpMemoryModel Physical64 OpenCL
2473 %u32    = OpTypeInt 32 0
2474 )" + std::string(kVoidFVoid);
2475 
2476   CompileSuccessfully(spirv, SPV_ENV_OPENCL_EMBEDDED_2_2);
2477   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_EMBEDDED_2_2));
2478 }
2479 
TEST_F(ValidateCapability,OpenCL22EmbeddedNotEnabledByCapability)2480 TEST_F(ValidateCapability, OpenCL22EmbeddedNotEnabledByCapability) {
2481   const std::string spirv = R"(
2482 OpCapability Kernel
2483 OpCapability Addresses
2484 OpCapability Linkage
2485 OpCapability Sampled1D
2486 OpMemoryModel Physical64 OpenCL
2487 %u32    = OpTypeInt 32 0
2488 )" + std::string(kVoidFVoid);
2489 
2490   CompileSuccessfully(spirv, SPV_ENV_OPENCL_EMBEDDED_2_2);
2491   EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
2492             ValidateInstructions(SPV_ENV_OPENCL_EMBEDDED_2_2));
2493   EXPECT_THAT(getDiagnosticString(),
2494               HasSubstr("Capability Sampled1D is not allowed by OpenCL 2.2 "
2495                         "Embedded Profile"));
2496 }
2497 
2498 // Three tests to check enablement of an enum (a decoration) which is not
2499 // in core, and is directly enabled by a capability, but not directly enabled
2500 // by an extension.  See https://github.com/KhronosGroup/SPIRV-Tools/issues/1596
2501 
TEST_F(ValidateCapability,DecorationFromExtensionMissingEnabledByCapability)2502 TEST_F(ValidateCapability, DecorationFromExtensionMissingEnabledByCapability) {
2503   // Decoration ViewportRelativeNV is enabled by ShaderViewportMaskNV, which in
2504   // turn is enabled by SPV_NV_viewport_array2.
2505   const std::string spirv = R"(
2506 OpCapability Shader
2507 OpMemoryModel Logical Simple
2508 OpDecorate %void ViewportRelativeNV
2509 )" + std::string(kVoidFVoid);
2510 
2511   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_0);
2512   EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
2513             ValidateInstructions(SPV_ENV_UNIVERSAL_1_0));
2514   EXPECT_THAT(getDiagnosticString(),
2515               HasSubstr("Operand 2 of Decorate requires one of these "
2516                         "capabilities: ShaderViewportMaskNV"));
2517 }
2518 
TEST_F(ValidateCapability,CapabilityEnabledByMissingExtension)2519 TEST_F(ValidateCapability, CapabilityEnabledByMissingExtension) {
2520   // Capability ShaderViewportMaskNV is enabled by SPV_NV_viewport_array2.
2521   const std::string spirv = R"(
2522 OpCapability Shader
2523 OpCapability ShaderViewportMaskNV
2524 OpMemoryModel Logical Simple
2525 )" + std::string(kVoidFVoid);
2526 
2527   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_0);
2528   EXPECT_EQ(SPV_ERROR_MISSING_EXTENSION,
2529             ValidateInstructions(SPV_ENV_UNIVERSAL_1_0));
2530   EXPECT_THAT(getDiagnosticString(),
2531               HasSubstr("operand ShaderViewportMaskNV(5255) requires one of "
2532                         "these extensions: SPV_NV_viewport_array2"));
2533 }
2534 
TEST_F(ValidateCapability,DecorationEnabledByCapabilityEnabledByPresentExtension)2535 TEST_F(ValidateCapability,
2536        DecorationEnabledByCapabilityEnabledByPresentExtension) {
2537   // Decoration ViewportRelativeNV is enabled by ShaderViewportMaskNV, which in
2538   // turn is enabled by SPV_NV_viewport_array2.
2539   const std::string spirv = R"(
2540 OpCapability Shader
2541 OpCapability Linkage
2542 OpCapability ShaderViewportMaskNV
2543 OpExtension "SPV_NV_viewport_array2"
2544 OpMemoryModel Logical Simple
2545 OpDecorate %void ViewportRelativeNV
2546 %void = OpTypeVoid
2547 )";
2548 
2549   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_0);
2550   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_0))
2551       << getDiagnosticString();
2552 }
2553 
2554 // Three tests to check enablement of an instruction  which is not in core, and
2555 // is directly enabled by a capability, but not directly enabled by an
2556 // extension. See https://github.com/KhronosGroup/SPIRV-Tools/issues/1624
2557 // Instruction OpSubgroupShuffleINTEL is enabled by SubgroupShuffleINTEL, which
2558 // in turn is enabled by SPV_INTEL_subgroups.
2559 
TEST_F(ValidateCapability,InstructionFromExtensionMissingEnabledByCapability)2560 TEST_F(ValidateCapability, InstructionFromExtensionMissingEnabledByCapability) {
2561   // Decoration ViewportRelativeNV is enabled by ShaderViewportMaskNV, which in
2562   // turn is enabled by SPV_NV_viewport_array2.
2563   const std::string spirv = R"(
2564 OpCapability Kernel
2565 OpCapability Addresses
2566 ; OpCapability SubgroupShuffleINTEL
2567 OpExtension "SPV_INTEL_subgroups"
2568 OpMemoryModel Physical32 OpenCL
2569 OpEntryPoint Kernel %main "main"
2570 %void = OpTypeVoid
2571 %uint = OpTypeInt 32 0
2572 %voidfn = OpTypeFunction %void
2573 %zero = OpConstant %uint 0
2574 %main = OpFunction %void None %voidfn
2575 %entry = OpLabel
2576 %foo = OpSubgroupShuffleINTEL %uint %zero %zero
2577 OpReturn
2578 OpFunctionEnd
2579 )";
2580 
2581   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_0);
2582   EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
2583             ValidateInstructions(SPV_ENV_UNIVERSAL_1_0));
2584   EXPECT_THAT(getDiagnosticString(),
2585               HasSubstr("Opcode SubgroupShuffleINTEL requires one of these "
2586                         "capabilities: SubgroupShuffleINTEL"));
2587 }
2588 
TEST_F(ValidateCapability,InstructionEnablingCapabilityEnabledByMissingExtension)2589 TEST_F(ValidateCapability,
2590        InstructionEnablingCapabilityEnabledByMissingExtension) {
2591   const std::string spirv = R"(
2592 OpCapability Kernel
2593 OpCapability Addresses
2594 OpCapability SubgroupShuffleINTEL
2595 ; OpExtension "SPV_INTEL_subgroups"
2596 OpMemoryModel Physical32 OpenCL
2597 OpEntryPoint Kernel %main "main"
2598 %void = OpTypeVoid
2599 %uint = OpTypeInt 32 0
2600 %voidfn = OpTypeFunction %void
2601 %zero = OpConstant %uint 0
2602 %main = OpFunction %void None %voidfn
2603 %entry = OpLabel
2604 %foo = OpSubgroupShuffleINTEL %uint %zero %zero
2605 OpReturn
2606 OpFunctionEnd
2607 )";
2608 
2609   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_0);
2610   EXPECT_EQ(SPV_ERROR_MISSING_EXTENSION,
2611             ValidateInstructions(SPV_ENV_UNIVERSAL_1_0));
2612   EXPECT_THAT(getDiagnosticString(),
2613               HasSubstr("operand SubgroupShuffleINTEL(5568) requires one of "
2614                         "these extensions: SPV_INTEL_subgroups"));
2615 }
2616 
TEST_F(ValidateCapability,InstructionEnabledByCapabilityEnabledByPresentExtension)2617 TEST_F(ValidateCapability,
2618        InstructionEnabledByCapabilityEnabledByPresentExtension) {
2619   const std::string spirv = R"(
2620 OpCapability Kernel
2621 OpCapability Addresses
2622 OpCapability SubgroupShuffleINTEL
2623 OpExtension "SPV_INTEL_subgroups"
2624 OpMemoryModel Physical32 OpenCL
2625 OpEntryPoint Kernel %main "main"
2626 %void = OpTypeVoid
2627 %uint = OpTypeInt 32 0
2628 %voidfn = OpTypeFunction %void
2629 %zero = OpConstant %uint 0
2630 %main = OpFunction %void None %voidfn
2631 %entry = OpLabel
2632 %foo = OpSubgroupShuffleINTEL %uint %zero %zero
2633 OpReturn
2634 OpFunctionEnd
2635 )";
2636 
2637   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_0);
2638   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_0))
2639       << getDiagnosticString();
2640 }
2641 
TEST_F(ValidateCapability,VulkanMemoryModelWithVulkanKHR)2642 TEST_F(ValidateCapability, VulkanMemoryModelWithVulkanKHR) {
2643   const std::string spirv = R"(
2644 OpCapability Shader
2645 OpCapability VulkanMemoryModelKHR
2646 OpCapability Linkage
2647 OpExtension "SPV_KHR_vulkan_memory_model"
2648 OpMemoryModel Logical VulkanKHR
2649 )";
2650 
2651   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
2652   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3))
2653       << getDiagnosticString();
2654 }
2655 
TEST_F(ValidateCapability,VulkanMemoryModelWithGLSL450)2656 TEST_F(ValidateCapability, VulkanMemoryModelWithGLSL450) {
2657   const std::string spirv = R"(
2658 OpCapability Shader
2659 OpCapability VulkanMemoryModelKHR
2660 OpCapability Linkage
2661 OpExtension "SPV_KHR_vulkan_memory_model"
2662 OpMemoryModel Logical GLSL450
2663 )";
2664 
2665   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
2666   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
2667             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2668   EXPECT_THAT(getDiagnosticString(),
2669               HasSubstr("VulkanMemoryModelKHR capability must only be "
2670                         "specified if the VulkanKHR memory model is used"));
2671 }
2672 
2673 // In the grammar, SubgroupEqMask and SubgroupMaskKHR have different enabling
2674 // lists of extensions.
TEST_F(ValidateCapability,SubgroupEqMaskEnabledByExtension)2675 TEST_F(ValidateCapability, SubgroupEqMaskEnabledByExtension) {
2676   const std::string spirv = R"(
2677 OpCapability Shader
2678 OpCapability SubgroupBallotKHR
2679 OpExtension "SPV_KHR_shader_ballot"
2680 OpMemoryModel Logical Simple
2681 OpEntryPoint GLCompute %main "main"
2682 OpDecorate %var BuiltIn SubgroupEqMask
2683 %void = OpTypeVoid
2684 %uint = OpTypeInt 32 0
2685 %ptr_uint = OpTypePointer Private %uint
2686 %var = OpVariable %ptr_uint Private
2687 %fn = OpTypeFunction %void
2688 %main = OpFunction %void None %fn
2689 %entry = OpLabel
2690 %val = OpLoad %uint %var
2691 OpReturn
2692 OpFunctionEnd
2693 )";
2694 
2695   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_0);
2696   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_0))
2697       << getDiagnosticString();
2698 }
2699 
2700 // Test that extensions incorporated into SPIR-V 1.5 no longer require
2701 // the associated OpExtension instruction.  Test one capability per extension.
2702 
2703 struct CapabilityExtensionVersionCase {
2704   std::string capability;
2705   std::string capability_new_name;
2706   std::string extension;
2707   spv_target_env last_version_requiring_extension;
2708   spv_target_env first_version_in_core;
2709 };
2710 
2711 using ValidateCapabilityExtensionVersionTest =
2712     spvtest::ValidateBase<CapabilityExtensionVersionCase>;
2713 
2714 // Returns a minimal shader module with the given capability instruction.
MinimalShaderModuleWithCapability(std::string cap)2715 std::string MinimalShaderModuleWithCapability(std::string cap) {
2716   std::string mem_model =
2717       (cap.find("VulkanMemory") == 0) ? "VulkanKHR" : "GLSL450";
2718   std::string extra_cap = (cap.find("VulkanMemoryModelDeviceScope") == 0)
2719                               ? "\nOpCapability VulkanMemoryModelKHR\n"
2720                               : "";
2721   return std::string("OpCapability ") + cap + extra_cap + R"(
2722 OpCapability Shader
2723 OpMemoryModel Logical )" + mem_model + R"(
2724 OpEntryPoint Vertex %main "main"
2725 %void = OpTypeVoid
2726 %void_fn = OpTypeFunction %void
2727 %main = OpFunction %void None %void_fn
2728 %entry = OpLabel
2729 OpReturn
2730 OpFunctionEnd
2731 )";
2732 }
2733 
TEST_P(ValidateCapabilityExtensionVersionTest,FailsInOlderSpirvVersion)2734 TEST_P(ValidateCapabilityExtensionVersionTest, FailsInOlderSpirvVersion) {
2735   const auto spirv = MinimalShaderModuleWithCapability(GetParam().capability);
2736   CompileSuccessfully(spirv, GetParam().last_version_requiring_extension);
2737   EXPECT_EQ(SPV_ERROR_MISSING_EXTENSION,
2738             ValidateInstructions(GetParam().last_version_requiring_extension));
2739   EXPECT_THAT(getDiagnosticString(),
2740               HasSubstr(std::string("1st operand of Capability: operand ") +
2741                         GetParam().capability_new_name))
2742       << spirv << "\n";
2743   EXPECT_THAT(getDiagnosticString(),
2744               HasSubstr(std::string("requires one of these extensions: ") +
2745                         GetParam().extension));
2746 }
2747 
TEST_P(ValidateCapabilityExtensionVersionTest,SucceedsInNewerSpirvVersionWithOldName)2748 TEST_P(ValidateCapabilityExtensionVersionTest,
2749        SucceedsInNewerSpirvVersionWithOldName) {
2750   const auto spirv = MinimalShaderModuleWithCapability(GetParam().capability);
2751   CompileSuccessfully(spirv, GetParam().first_version_in_core);
2752   EXPECT_EQ(SPV_SUCCESS,
2753             ValidateInstructions(GetParam().first_version_in_core));
2754   EXPECT_THAT(getDiagnosticString(), Eq("")) << spirv << "\n";
2755 }
2756 
TEST_P(ValidateCapabilityExtensionVersionTest,SucceedsInNewerSpirvVersionWithNewName)2757 TEST_P(ValidateCapabilityExtensionVersionTest,
2758        SucceedsInNewerSpirvVersionWithNewName) {
2759   const auto spirv =
2760       MinimalShaderModuleWithCapability(GetParam().capability_new_name);
2761   CompileSuccessfully(spirv, GetParam().first_version_in_core);
2762   EXPECT_EQ(SPV_SUCCESS,
2763             ValidateInstructions(GetParam().first_version_in_core));
2764   EXPECT_THAT(getDiagnosticString(), Eq("")) << spirv << "\n";
2765 }
2766 
CapVersionCases1_5()2767 std::vector<CapabilityExtensionVersionCase> CapVersionCases1_5() {
2768 #define IN15NOSUFFIX(C, E) \
2769   { C, C, E, SPV_ENV_UNIVERSAL_1_4, SPV_ENV_UNIVERSAL_1_5 }
2770 #define IN15(C, C_WITHOUT_SUFFIX, E) \
2771   { C, C_WITHOUT_SUFFIX, E, SPV_ENV_UNIVERSAL_1_4, SPV_ENV_UNIVERSAL_1_5 }
2772   return std::vector<CapabilityExtensionVersionCase>{
2773       // SPV_KHR_8bit_storage
2774       IN15NOSUFFIX("StorageBuffer8BitAccess", "SPV_KHR_8bit_storage"),
2775       IN15NOSUFFIX("UniformAndStorageBuffer8BitAccess", "SPV_KHR_8bit_storage"),
2776       IN15NOSUFFIX("StoragePushConstant8", "SPV_KHR_8bit_storage"),
2777       // SPV_EXT_descriptor_indexing
2778       IN15("ShaderNonUniformEXT", "ShaderNonUniform",
2779            "SPV_EXT_descriptor_indexing"),
2780       IN15("RuntimeDescriptorArrayEXT", "RuntimeDescriptorArray",
2781            "SPV_EXT_descriptor_indexing"),
2782       IN15("InputAttachmentArrayDynamicIndexingEXT",
2783            "InputAttachmentArrayDynamicIndexing",
2784            "SPV_EXT_descriptor_indexing"),
2785       IN15("UniformTexelBufferArrayDynamicIndexingEXT",
2786            "UniformTexelBufferArrayDynamicIndexing",
2787            "SPV_EXT_descriptor_indexing"),
2788       IN15("StorageTexelBufferArrayDynamicIndexingEXT",
2789            "StorageTexelBufferArrayDynamicIndexing",
2790            "SPV_EXT_descriptor_indexing"),
2791       IN15("UniformBufferArrayNonUniformIndexingEXT",
2792            "UniformBufferArrayNonUniformIndexing",
2793            "SPV_EXT_descriptor_indexing"),
2794       IN15("SampledImageArrayNonUniformIndexingEXT",
2795            "SampledImageArrayNonUniformIndexing",
2796            "SPV_EXT_descriptor_indexing"),
2797       IN15("StorageBufferArrayNonUniformIndexingEXT",
2798            "StorageBufferArrayNonUniformIndexing",
2799            "SPV_EXT_descriptor_indexing"),
2800       IN15("StorageImageArrayNonUniformIndexingEXT",
2801            "StorageImageArrayNonUniformIndexing",
2802            "SPV_EXT_descriptor_indexing"),
2803       IN15("InputAttachmentArrayNonUniformIndexingEXT",
2804            "InputAttachmentArrayNonUniformIndexing",
2805            "SPV_EXT_descriptor_indexing"),
2806       IN15("UniformTexelBufferArrayNonUniformIndexingEXT",
2807            "UniformTexelBufferArrayNonUniformIndexing",
2808            "SPV_EXT_descriptor_indexing"),
2809       IN15("StorageTexelBufferArrayNonUniformIndexingEXT",
2810            "StorageTexelBufferArrayNonUniformIndexing",
2811            "SPV_EXT_descriptor_indexing"),
2812       // SPV_EXT_physical_storage_buffer
2813       IN15("PhysicalStorageBufferAddressesEXT",
2814            "PhysicalStorageBufferAddresses", "SPV_EXT_physical_storage_buffer"),
2815       // SPV_KHR_vulkan_memory_model
2816       IN15("VulkanMemoryModelKHR", "VulkanMemoryModel",
2817            "SPV_KHR_vulkan_memory_model"),
2818       IN15("VulkanMemoryModelDeviceScopeKHR", "VulkanMemoryModelDeviceScope",
2819            "SPV_KHR_vulkan_memory_model"),
2820   };
2821 #undef IN15
2822 }
2823 
2824 INSTANTIATE_TEST_SUITE_P(NewInSpirv1_5, ValidateCapabilityExtensionVersionTest,
2825                          ValuesIn(CapVersionCases1_5()));
2826 
TEST_P(ValidateCapability,CapShaderViewportIndexLayerFailsInOlderSpirvVersion)2827 TEST_P(ValidateCapability,
2828        CapShaderViewportIndexLayerFailsInOlderSpirvVersion) {
2829   const auto spirv =
2830       MinimalShaderModuleWithCapability("ShaderViewportIndexLayerEXT");
2831   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
2832   EXPECT_EQ(SPV_ERROR_MISSING_EXTENSION,
2833             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
2834   EXPECT_THAT(
2835       getDiagnosticString(),
2836       HasSubstr(
2837           "1st operand of Capability: operand ShaderViewportIndexLayerEXT"));
2838   EXPECT_THAT(getDiagnosticString(),
2839               HasSubstr("requires one of these extensions: "
2840                         "SPV_EXT_shader_viewport_index_layer"));
2841 }
2842 
TEST_P(ValidateCapability,CapShaderViewportIndexLayerFailsInNewSpirvVersion)2843 TEST_P(ValidateCapability, CapShaderViewportIndexLayerFailsInNewSpirvVersion) {
2844   const auto spirv =
2845       MinimalShaderModuleWithCapability("ShaderViewportIndexLayerEXT");
2846   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_5);
2847   EXPECT_EQ(SPV_ERROR_MISSING_EXTENSION,
2848             ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
2849   EXPECT_THAT(
2850       getDiagnosticString(),
2851       HasSubstr(
2852           "1st operand of Capability: operand ShaderViewportIndexLayerEXT"));
2853   EXPECT_THAT(getDiagnosticString(),
2854               HasSubstr("requires one of these extensions: "
2855                         "SPV_EXT_shader_viewport_index_layer"));
2856 }
2857 
TEST_F(ValidateCapability,CapShaderViewportIndexSucceedsInNewSpirvVersion)2858 TEST_F(ValidateCapability, CapShaderViewportIndexSucceedsInNewSpirvVersion) {
2859   const auto spirv = MinimalShaderModuleWithCapability("ShaderViewportIndex");
2860   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_5);
2861   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
2862   EXPECT_THAT(getDiagnosticString(), Eq(""));
2863 }
2864 
TEST_F(ValidateCapability,CapShaderLayerSucceedsInNewSpirvVersion)2865 TEST_F(ValidateCapability, CapShaderLayerSucceedsInNewSpirvVersion) {
2866   const auto spirv = MinimalShaderModuleWithCapability("ShaderLayer");
2867   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_5);
2868   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
2869   EXPECT_THAT(getDiagnosticString(), Eq(""));
2870 }
2871 
2872 }  // namespace
2873 }  // namespace val
2874 }  // namespace spvtools
2875