Setup dependent external sources
[platform/upstream/VK-GL-CTS.git] / external / glslang / src / SPIRV / GlslangToSpv.cpp
1 //
2 // Copyright (C) 2014-2016 LunarG, Inc.
3 // Copyright (C) 2015-2016 Google, Inc.
4 //
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
9 // are met:
10 //
11 //    Redistributions of source code must retain the above copyright
12 //    notice, this list of conditions and the following disclaimer.
13 //
14 //    Redistributions in binary form must reproduce the above
15 //    copyright notice, this list of conditions and the following
16 //    disclaimer in the documentation and/or other materials provided
17 //    with the distribution.
18 //
19 //    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
20 //    contributors may be used to endorse or promote products derived
21 //    from this software without specific prior written permission.
22 //
23 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27 // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 // POSSIBILITY OF SUCH DAMAGE.
35
36 //
37 // Visit the nodes in the glslang intermediate tree representation to
38 // translate them to SPIR-V.
39 //
40
41 #include "spirv.hpp"
42 #include "GlslangToSpv.h"
43 #include "SpvBuilder.h"
44 namespace spv {
45     #include "GLSL.std.450.h"
46     #include "GLSL.ext.KHR.h"
47 #ifdef AMD_EXTENSIONS
48     #include "GLSL.ext.AMD.h"
49 #endif
50 #ifdef NV_EXTENSIONS
51     #include "GLSL.ext.NV.h"
52 #endif
53 }
54
55 // Glslang includes
56 #include "../glslang/MachineIndependent/localintermediate.h"
57 #include "../glslang/MachineIndependent/SymbolTable.h"
58 #include "../glslang/Include/Common.h"
59 #include "../glslang/Include/revision.h"
60
61 #include <fstream>
62 #include <iomanip>
63 #include <list>
64 #include <map>
65 #include <stack>
66 #include <string>
67 #include <vector>
68
69 namespace {
70
71 // For low-order part of the generator's magic number. Bump up
72 // when there is a change in the style (e.g., if SSA form changes,
73 // or a different instruction sequence to do something gets used).
74 const int GeneratorVersion = 1;
75
76 namespace {
77 class SpecConstantOpModeGuard {
78 public:
79     SpecConstantOpModeGuard(spv::Builder* builder)
80         : builder_(builder) {
81         previous_flag_ = builder->isInSpecConstCodeGenMode();
82     }
83     ~SpecConstantOpModeGuard() {
84         previous_flag_ ? builder_->setToSpecConstCodeGenMode()
85                        : builder_->setToNormalCodeGenMode();
86     }
87     void turnOnSpecConstantOpMode() {
88         builder_->setToSpecConstCodeGenMode();
89     }
90
91 private:
92     spv::Builder* builder_;
93     bool previous_flag_;
94 };
95 }
96
97 //
98 // The main holder of information for translating glslang to SPIR-V.
99 //
100 // Derives from the AST walking base class.
101 //
102 class TGlslangToSpvTraverser : public glslang::TIntermTraverser {
103 public:
104     TGlslangToSpvTraverser(const glslang::TIntermediate*, spv::SpvBuildLogger* logger);
105     virtual ~TGlslangToSpvTraverser() { }
106
107     bool visitAggregate(glslang::TVisit, glslang::TIntermAggregate*);
108     bool visitBinary(glslang::TVisit, glslang::TIntermBinary*);
109     void visitConstantUnion(glslang::TIntermConstantUnion*);
110     bool visitSelection(glslang::TVisit, glslang::TIntermSelection*);
111     bool visitSwitch(glslang::TVisit, glslang::TIntermSwitch*);
112     void visitSymbol(glslang::TIntermSymbol* symbol);
113     bool visitUnary(glslang::TVisit, glslang::TIntermUnary*);
114     bool visitLoop(glslang::TVisit, glslang::TIntermLoop*);
115     bool visitBranch(glslang::TVisit visit, glslang::TIntermBranch*);
116
117     void finishSpv();
118     void dumpSpv(std::vector<unsigned int>& out);
119
120 protected:
121     spv::Decoration TranslateInterpolationDecoration(const glslang::TQualifier& qualifier);
122     spv::Decoration TranslateAuxiliaryStorageDecoration(const glslang::TQualifier& qualifier);
123     spv::BuiltIn TranslateBuiltInDecoration(glslang::TBuiltInVariable, bool memberDeclaration);
124     spv::ImageFormat TranslateImageFormat(const glslang::TType& type);
125     spv::LoopControlMask TranslateLoopControl(glslang::TLoopControl) const;
126     spv::StorageClass TranslateStorageClass(const glslang::TType&);
127     spv::Id createSpvVariable(const glslang::TIntermSymbol*);
128     spv::Id getSampledType(const glslang::TSampler&);
129     spv::Id getInvertedSwizzleType(const glslang::TIntermTyped&);
130     spv::Id createInvertedSwizzle(spv::Decoration precision, const glslang::TIntermTyped&, spv::Id parentResult);
131     void convertSwizzle(const glslang::TIntermAggregate&, std::vector<unsigned>& swizzle);
132     spv::Id convertGlslangToSpvType(const glslang::TType& type);
133     spv::Id convertGlslangToSpvType(const glslang::TType& type, glslang::TLayoutPacking, const glslang::TQualifier&);
134     bool filterMember(const glslang::TType& member);
135     spv::Id convertGlslangStructToSpvType(const glslang::TType&, const glslang::TTypeList* glslangStruct,
136                                           glslang::TLayoutPacking, const glslang::TQualifier&);
137     void decorateStructType(const glslang::TType&, const glslang::TTypeList* glslangStruct, glslang::TLayoutPacking,
138                             const glslang::TQualifier&, spv::Id);
139     spv::Id makeArraySizeId(const glslang::TArraySizes&, int dim);
140     spv::Id accessChainLoad(const glslang::TType& type);
141     void    accessChainStore(const glslang::TType& type, spv::Id rvalue);
142     void multiTypeStore(const glslang::TType&, spv::Id rValue);
143     glslang::TLayoutPacking getExplicitLayout(const glslang::TType& type) const;
144     int getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking, glslang::TLayoutMatrix);
145     int getMatrixStride(const glslang::TType& matrixType, glslang::TLayoutPacking, glslang::TLayoutMatrix);
146     void updateMemberOffset(const glslang::TType& structType, const glslang::TType& memberType, int& currentOffset, int& nextOffset, glslang::TLayoutPacking, glslang::TLayoutMatrix);
147     void declareUseOfStructMember(const glslang::TTypeList& members, int glslangMember);
148
149     bool isShaderEntryPoint(const glslang::TIntermAggregate* node);
150     void makeFunctions(const glslang::TIntermSequence&);
151     void makeGlobalInitializers(const glslang::TIntermSequence&);
152     void visitFunctions(const glslang::TIntermSequence&);
153     void handleFunctionEntry(const glslang::TIntermAggregate* node);
154     void translateArguments(const glslang::TIntermAggregate& node, std::vector<spv::Id>& arguments);
155     void translateArguments(glslang::TIntermUnary& node, std::vector<spv::Id>& arguments);
156     spv::Id createImageTextureFunctionCall(glslang::TIntermOperator* node);
157     spv::Id handleUserFunctionCall(const glslang::TIntermAggregate*);
158
159     spv::Id createBinaryOperation(glslang::TOperator op, spv::Decoration precision, spv::Decoration noContraction, spv::Id typeId, spv::Id left, spv::Id right, glslang::TBasicType typeProxy, bool reduceComparison = true);
160     spv::Id createBinaryMatrixOperation(spv::Op, spv::Decoration precision, spv::Decoration noContraction, spv::Id typeId, spv::Id left, spv::Id right);
161     spv::Id createUnaryOperation(glslang::TOperator op, spv::Decoration precision, spv::Decoration noContraction, spv::Id typeId, spv::Id operand,glslang::TBasicType typeProxy);
162     spv::Id createUnaryMatrixOperation(spv::Op op, spv::Decoration precision, spv::Decoration noContraction, spv::Id typeId, spv::Id operand,glslang::TBasicType typeProxy);
163     spv::Id createConversion(glslang::TOperator op, spv::Decoration precision, spv::Decoration noContraction, spv::Id destTypeId, spv::Id operand, glslang::TBasicType typeProxy);
164     spv::Id makeSmearedConstant(spv::Id constant, int vectorSize);
165     spv::Id createAtomicOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy);
166     spv::Id createInvocationsOperation(glslang::TOperator op, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy);
167     spv::Id CreateInvocationsVectorOperation(spv::Op op, spv::GroupOperation groupOperation, spv::Id typeId, std::vector<spv::Id>& operands);
168     spv::Id createMiscOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy);
169     spv::Id createNoArgOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId);
170     spv::Id getSymbolId(const glslang::TIntermSymbol* node);
171     void addDecoration(spv::Id id, spv::Decoration dec);
172     void addDecoration(spv::Id id, spv::Decoration dec, unsigned value);
173     void addMemberDecoration(spv::Id id, int member, spv::Decoration dec);
174     void addMemberDecoration(spv::Id id, int member, spv::Decoration dec, unsigned value);
175     spv::Id createSpvConstant(const glslang::TIntermTyped&);
176     spv::Id createSpvConstantFromConstUnionArray(const glslang::TType& type, const glslang::TConstUnionArray&, int& nextConst, bool specConstant);
177     bool isTrivialLeaf(const glslang::TIntermTyped* node);
178     bool isTrivial(const glslang::TIntermTyped* node);
179     spv::Id createShortCircuit(glslang::TOperator, glslang::TIntermTyped& left, glslang::TIntermTyped& right);
180     spv::Id getExtBuiltins(const char* name);
181
182     spv::Function* shaderEntry;
183     spv::Function* currentFunction;
184     spv::Instruction* entryPoint;
185     int sequenceDepth;
186
187     spv::SpvBuildLogger* logger;
188
189     // There is a 1:1 mapping between a spv builder and a module; this is thread safe
190     spv::Builder builder;
191     bool inEntryPoint;
192     bool entryPointTerminated;
193     bool linkageOnly;                  // true when visiting the set of objects in the AST present only for establishing interface, whether or not they were statically used
194     std::set<spv::Id> iOSet;           // all input/output variables from either static use or declaration of interface
195     const glslang::TIntermediate* glslangIntermediate;
196     spv::Id stdBuiltins;
197     std::unordered_map<const char*, spv::Id> extBuiltinMap;
198
199     std::unordered_map<int, spv::Id> symbolValues;
200     std::unordered_set<int> rValueParameters;  // set of formal function parameters passed as rValues, rather than a pointer
201     std::unordered_map<std::string, spv::Function*> functionMap;
202     std::unordered_map<const glslang::TTypeList*, spv::Id> structMap[glslang::ElpCount][glslang::ElmCount];
203     std::unordered_map<const glslang::TTypeList*, std::vector<int> > memberRemapper;  // for mapping glslang block indices to spv indices (e.g., due to hidden members)
204     std::stack<bool> breakForLoop;  // false means break for switch
205 };
206
207 //
208 // Helper functions for translating glslang representations to SPIR-V enumerants.
209 //
210
211 // Translate glslang profile to SPIR-V source language.
212 spv::SourceLanguage TranslateSourceLanguage(glslang::EShSource source, EProfile profile)
213 {
214     switch (source) {
215     case glslang::EShSourceGlsl:
216         switch (profile) {
217         case ENoProfile:
218         case ECoreProfile:
219         case ECompatibilityProfile:
220             return spv::SourceLanguageGLSL;
221         case EEsProfile:
222             return spv::SourceLanguageESSL;
223         default:
224             return spv::SourceLanguageUnknown;
225         }
226     case glslang::EShSourceHlsl:
227         return spv::SourceLanguageHLSL;
228     default:
229         return spv::SourceLanguageUnknown;
230     }
231 }
232
233 // Translate glslang language (stage) to SPIR-V execution model.
234 spv::ExecutionModel TranslateExecutionModel(EShLanguage stage)
235 {
236     switch (stage) {
237     case EShLangVertex:           return spv::ExecutionModelVertex;
238     case EShLangTessControl:      return spv::ExecutionModelTessellationControl;
239     case EShLangTessEvaluation:   return spv::ExecutionModelTessellationEvaluation;
240     case EShLangGeometry:         return spv::ExecutionModelGeometry;
241     case EShLangFragment:         return spv::ExecutionModelFragment;
242     case EShLangCompute:          return spv::ExecutionModelGLCompute;
243     default:
244         assert(0);
245         return spv::ExecutionModelFragment;
246     }
247 }
248
249 // Translate glslang sampler type to SPIR-V dimensionality.
250 spv::Dim TranslateDimensionality(const glslang::TSampler& sampler)
251 {
252     switch (sampler.dim) {
253     case glslang::Esd1D:      return spv::Dim1D;
254     case glslang::Esd2D:      return spv::Dim2D;
255     case glslang::Esd3D:      return spv::Dim3D;
256     case glslang::EsdCube:    return spv::DimCube;
257     case glslang::EsdRect:    return spv::DimRect;
258     case glslang::EsdBuffer:  return spv::DimBuffer;
259     case glslang::EsdSubpass: return spv::DimSubpassData;
260     default:
261         assert(0);
262         return spv::Dim2D;
263     }
264 }
265
266 // Translate glslang precision to SPIR-V precision decorations.
267 spv::Decoration TranslatePrecisionDecoration(glslang::TPrecisionQualifier glslangPrecision)
268 {
269     switch (glslangPrecision) {
270     case glslang::EpqLow:    return spv::DecorationRelaxedPrecision;
271     case glslang::EpqMedium: return spv::DecorationRelaxedPrecision;
272     default:
273         return spv::NoPrecision;
274     }
275 }
276
277 // Translate glslang type to SPIR-V precision decorations.
278 spv::Decoration TranslatePrecisionDecoration(const glslang::TType& type)
279 {
280     return TranslatePrecisionDecoration(type.getQualifier().precision);
281 }
282
283 // Translate glslang type to SPIR-V block decorations.
284 spv::Decoration TranslateBlockDecoration(const glslang::TType& type, bool useStorageBuffer)
285 {
286     if (type.getBasicType() == glslang::EbtBlock) {
287         switch (type.getQualifier().storage) {
288         case glslang::EvqUniform:      return spv::DecorationBlock;
289         case glslang::EvqBuffer:       return useStorageBuffer ? spv::DecorationBlock : spv::DecorationBufferBlock;
290         case glslang::EvqVaryingIn:    return spv::DecorationBlock;
291         case glslang::EvqVaryingOut:   return spv::DecorationBlock;
292         default:
293             assert(0);
294             break;
295         }
296     }
297
298     return spv::DecorationMax;
299 }
300
301 // Translate glslang type to SPIR-V memory decorations.
302 void TranslateMemoryDecoration(const glslang::TQualifier& qualifier, std::vector<spv::Decoration>& memory)
303 {
304     if (qualifier.coherent)
305         memory.push_back(spv::DecorationCoherent);
306     if (qualifier.volatil)
307         memory.push_back(spv::DecorationVolatile);
308     if (qualifier.restrict)
309         memory.push_back(spv::DecorationRestrict);
310     if (qualifier.readonly)
311         memory.push_back(spv::DecorationNonWritable);
312     if (qualifier.writeonly)
313        memory.push_back(spv::DecorationNonReadable);
314 }
315
316 // Translate glslang type to SPIR-V layout decorations.
317 spv::Decoration TranslateLayoutDecoration(const glslang::TType& type, glslang::TLayoutMatrix matrixLayout)
318 {
319     if (type.isMatrix()) {
320         switch (matrixLayout) {
321         case glslang::ElmRowMajor:
322             return spv::DecorationRowMajor;
323         case glslang::ElmColumnMajor:
324             return spv::DecorationColMajor;
325         default:
326             // opaque layouts don't need a majorness
327             return spv::DecorationMax;
328         }
329     } else {
330         switch (type.getBasicType()) {
331         default:
332             return spv::DecorationMax;
333             break;
334         case glslang::EbtBlock:
335             switch (type.getQualifier().storage) {
336             case glslang::EvqUniform:
337             case glslang::EvqBuffer:
338                 switch (type.getQualifier().layoutPacking) {
339                 case glslang::ElpShared:  return spv::DecorationGLSLShared;
340                 case glslang::ElpPacked:  return spv::DecorationGLSLPacked;
341                 default:
342                     return spv::DecorationMax;
343                 }
344             case glslang::EvqVaryingIn:
345             case glslang::EvqVaryingOut:
346                 assert(type.getQualifier().layoutPacking == glslang::ElpNone);
347                 return spv::DecorationMax;
348             default:
349                 assert(0);
350                 return spv::DecorationMax;
351             }
352         }
353     }
354 }
355
356 // Translate glslang type to SPIR-V interpolation decorations.
357 // Returns spv::DecorationMax when no decoration
358 // should be applied.
359 spv::Decoration TGlslangToSpvTraverser::TranslateInterpolationDecoration(const glslang::TQualifier& qualifier)
360 {
361     if (qualifier.smooth)
362         // Smooth decoration doesn't exist in SPIR-V 1.0
363         return spv::DecorationMax;
364     else if (qualifier.nopersp)
365         return spv::DecorationNoPerspective;
366     else if (qualifier.flat)
367         return spv::DecorationFlat;
368 #ifdef AMD_EXTENSIONS
369     else if (qualifier.explicitInterp) {
370         builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter);
371         return spv::DecorationExplicitInterpAMD;
372     }
373 #endif
374     else
375         return spv::DecorationMax;
376 }
377
378 // Translate glslang type to SPIR-V auxiliary storage decorations.
379 // Returns spv::DecorationMax when no decoration
380 // should be applied.
381 spv::Decoration TGlslangToSpvTraverser::TranslateAuxiliaryStorageDecoration(const glslang::TQualifier& qualifier)
382 {
383     if (qualifier.patch)
384         return spv::DecorationPatch;
385     else if (qualifier.centroid)
386         return spv::DecorationCentroid;
387     else if (qualifier.sample) {
388         builder.addCapability(spv::CapabilitySampleRateShading);
389         return spv::DecorationSample;
390     } else
391         return spv::DecorationMax;
392 }
393
394 // If glslang type is invariant, return SPIR-V invariant decoration.
395 spv::Decoration TranslateInvariantDecoration(const glslang::TQualifier& qualifier)
396 {
397     if (qualifier.invariant)
398         return spv::DecorationInvariant;
399     else
400         return spv::DecorationMax;
401 }
402
403 // If glslang type is noContraction, return SPIR-V NoContraction decoration.
404 spv::Decoration TranslateNoContractionDecoration(const glslang::TQualifier& qualifier)
405 {
406     if (qualifier.noContraction)
407         return spv::DecorationNoContraction;
408     else
409         return spv::DecorationMax;
410 }
411
412 // Translate a glslang built-in variable to a SPIR-V built in decoration.  Also generate
413 // associated capabilities when required.  For some built-in variables, a capability
414 // is generated only when using the variable in an executable instruction, but not when
415 // just declaring a struct member variable with it.  This is true for PointSize,
416 // ClipDistance, and CullDistance.
417 spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltInVariable builtIn, bool memberDeclaration)
418 {
419     switch (builtIn) {
420     case glslang::EbvPointSize:
421         // Defer adding the capability until the built-in is actually used.
422         if (! memberDeclaration) {
423             switch (glslangIntermediate->getStage()) {
424             case EShLangGeometry:
425                 builder.addCapability(spv::CapabilityGeometryPointSize);
426                 break;
427             case EShLangTessControl:
428             case EShLangTessEvaluation:
429                 builder.addCapability(spv::CapabilityTessellationPointSize);
430                 break;
431             default:
432                 break;
433             }
434         }
435         return spv::BuiltInPointSize;
436
437     // These *Distance capabilities logically belong here, but if the member is declared and
438     // then never used, consumers of SPIR-V prefer the capability not be declared.
439     // They are now generated when used, rather than here when declared.
440     // Potentially, the specification should be more clear what the minimum
441     // use needed is to trigger the capability.
442     //
443     case glslang::EbvClipDistance:
444         if (!memberDeclaration)
445             builder.addCapability(spv::CapabilityClipDistance);
446         return spv::BuiltInClipDistance;
447
448     case glslang::EbvCullDistance:
449         if (!memberDeclaration)
450             builder.addCapability(spv::CapabilityCullDistance);
451         return spv::BuiltInCullDistance;
452
453     case glslang::EbvViewportIndex:
454         if (!memberDeclaration) {
455             builder.addCapability(spv::CapabilityMultiViewport);
456 #ifdef NV_EXTENSIONS
457             if (glslangIntermediate->getStage() == EShLangVertex ||
458                 glslangIntermediate->getStage() == EShLangTessControl ||
459                 glslangIntermediate->getStage() == EShLangTessEvaluation) {
460
461                 builder.addExtension(spv::E_SPV_NV_viewport_array2);
462                 builder.addCapability(spv::CapabilityShaderViewportIndexLayerNV);
463             }
464 #endif
465         }
466         return spv::BuiltInViewportIndex;
467
468     case glslang::EbvSampleId:
469         builder.addCapability(spv::CapabilitySampleRateShading);
470         return spv::BuiltInSampleId;
471
472     case glslang::EbvSamplePosition:
473         builder.addCapability(spv::CapabilitySampleRateShading);
474         return spv::BuiltInSamplePosition;
475
476     case glslang::EbvSampleMask:
477         builder.addCapability(spv::CapabilitySampleRateShading);
478         return spv::BuiltInSampleMask;
479
480     case glslang::EbvLayer:
481         if (!memberDeclaration) {
482             builder.addCapability(spv::CapabilityGeometry);
483 #ifdef NV_EXTENSIONS
484             if (glslangIntermediate->getStage() == EShLangVertex ||
485                 glslangIntermediate->getStage() == EShLangTessControl ||
486                 glslangIntermediate->getStage() == EShLangTessEvaluation) {
487
488                 builder.addExtension(spv::E_SPV_NV_viewport_array2);
489                 builder.addCapability(spv::CapabilityShaderViewportIndexLayerNV);
490             }
491 #endif
492         }
493
494         return spv::BuiltInLayer;
495
496     case glslang::EbvPosition:             return spv::BuiltInPosition;
497     case glslang::EbvVertexId:             return spv::BuiltInVertexId;
498     case glslang::EbvInstanceId:           return spv::BuiltInInstanceId;
499     case glslang::EbvVertexIndex:          return spv::BuiltInVertexIndex;
500     case glslang::EbvInstanceIndex:        return spv::BuiltInInstanceIndex;
501
502     case glslang::EbvBaseVertex:
503         builder.addExtension(spv::E_SPV_KHR_shader_draw_parameters);
504         builder.addCapability(spv::CapabilityDrawParameters);
505         return spv::BuiltInBaseVertex;
506
507     case glslang::EbvBaseInstance:
508         builder.addExtension(spv::E_SPV_KHR_shader_draw_parameters);
509         builder.addCapability(spv::CapabilityDrawParameters);
510         return spv::BuiltInBaseInstance;
511
512     case glslang::EbvDrawId:
513         builder.addExtension(spv::E_SPV_KHR_shader_draw_parameters);
514         builder.addCapability(spv::CapabilityDrawParameters);
515         return spv::BuiltInDrawIndex;
516
517     case glslang::EbvPrimitiveId:
518         if (glslangIntermediate->getStage() == EShLangFragment)
519             builder.addCapability(spv::CapabilityGeometry);
520         return spv::BuiltInPrimitiveId;
521
522     case glslang::EbvInvocationId:         return spv::BuiltInInvocationId;
523     case glslang::EbvTessLevelInner:       return spv::BuiltInTessLevelInner;
524     case glslang::EbvTessLevelOuter:       return spv::BuiltInTessLevelOuter;
525     case glslang::EbvTessCoord:            return spv::BuiltInTessCoord;
526     case glslang::EbvPatchVertices:        return spv::BuiltInPatchVertices;
527     case glslang::EbvFragCoord:            return spv::BuiltInFragCoord;
528     case glslang::EbvPointCoord:           return spv::BuiltInPointCoord;
529     case glslang::EbvFace:                 return spv::BuiltInFrontFacing;
530     case glslang::EbvFragDepth:            return spv::BuiltInFragDepth;
531     case glslang::EbvHelperInvocation:     return spv::BuiltInHelperInvocation;
532     case glslang::EbvNumWorkGroups:        return spv::BuiltInNumWorkgroups;
533     case glslang::EbvWorkGroupSize:        return spv::BuiltInWorkgroupSize;
534     case glslang::EbvWorkGroupId:          return spv::BuiltInWorkgroupId;
535     case glslang::EbvLocalInvocationId:    return spv::BuiltInLocalInvocationId;
536     case glslang::EbvLocalInvocationIndex: return spv::BuiltInLocalInvocationIndex;
537     case glslang::EbvGlobalInvocationId:   return spv::BuiltInGlobalInvocationId;
538
539     case glslang::EbvSubGroupSize:
540         builder.addExtension(spv::E_SPV_KHR_shader_ballot);
541         builder.addCapability(spv::CapabilitySubgroupBallotKHR);
542         return spv::BuiltInSubgroupSize;
543
544     case glslang::EbvSubGroupInvocation:
545         builder.addExtension(spv::E_SPV_KHR_shader_ballot);
546         builder.addCapability(spv::CapabilitySubgroupBallotKHR);
547         return spv::BuiltInSubgroupLocalInvocationId;
548
549     case glslang::EbvSubGroupEqMask:
550         builder.addExtension(spv::E_SPV_KHR_shader_ballot);
551         builder.addCapability(spv::CapabilitySubgroupBallotKHR);
552         return spv::BuiltInSubgroupEqMaskKHR;
553
554     case glslang::EbvSubGroupGeMask:
555         builder.addExtension(spv::E_SPV_KHR_shader_ballot);
556         builder.addCapability(spv::CapabilitySubgroupBallotKHR);
557         return spv::BuiltInSubgroupGeMaskKHR;
558
559     case glslang::EbvSubGroupGtMask:
560         builder.addExtension(spv::E_SPV_KHR_shader_ballot);
561         builder.addCapability(spv::CapabilitySubgroupBallotKHR);
562         return spv::BuiltInSubgroupGtMaskKHR;
563
564     case glslang::EbvSubGroupLeMask:
565         builder.addExtension(spv::E_SPV_KHR_shader_ballot);
566         builder.addCapability(spv::CapabilitySubgroupBallotKHR);
567         return spv::BuiltInSubgroupLeMaskKHR;
568
569     case glslang::EbvSubGroupLtMask:
570         builder.addExtension(spv::E_SPV_KHR_shader_ballot);
571         builder.addCapability(spv::CapabilitySubgroupBallotKHR);
572         return spv::BuiltInSubgroupLtMaskKHR;
573
574 #ifdef AMD_EXTENSIONS
575     case glslang::EbvBaryCoordNoPersp:
576         builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter);
577         return spv::BuiltInBaryCoordNoPerspAMD;
578
579     case glslang::EbvBaryCoordNoPerspCentroid:
580         builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter);
581         return spv::BuiltInBaryCoordNoPerspCentroidAMD;
582
583     case glslang::EbvBaryCoordNoPerspSample:
584         builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter);
585         return spv::BuiltInBaryCoordNoPerspSampleAMD;
586
587     case glslang::EbvBaryCoordSmooth:
588         builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter);
589         return spv::BuiltInBaryCoordSmoothAMD;
590
591     case glslang::EbvBaryCoordSmoothCentroid:
592         builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter);
593         return spv::BuiltInBaryCoordSmoothCentroidAMD;
594
595     case glslang::EbvBaryCoordSmoothSample:
596         builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter);
597         return spv::BuiltInBaryCoordSmoothSampleAMD;
598
599     case glslang::EbvBaryCoordPullModel:
600         builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter);
601         return spv::BuiltInBaryCoordPullModelAMD;
602 #endif
603
604     case glslang::EbvDeviceIndex:
605         builder.addExtension(spv::E_SPV_KHR_device_group);
606         builder.addCapability(spv::CapabilityDeviceGroup);
607         return spv::BuiltInDeviceIndex;
608
609     case glslang::EbvViewIndex:
610         builder.addExtension(spv::E_SPV_KHR_multiview);
611         builder.addCapability(spv::CapabilityMultiView);
612         return spv::BuiltInViewIndex;
613
614 #ifdef NV_EXTENSIONS
615     case glslang::EbvViewportMaskNV:
616         if (!memberDeclaration) {
617             builder.addExtension(spv::E_SPV_NV_viewport_array2);
618             builder.addCapability(spv::CapabilityShaderViewportMaskNV);
619         }
620         return spv::BuiltInViewportMaskNV;
621     case glslang::EbvSecondaryPositionNV:
622         if (!memberDeclaration) {
623             builder.addExtension(spv::E_SPV_NV_stereo_view_rendering);
624             builder.addCapability(spv::CapabilityShaderStereoViewNV);
625         }
626         return spv::BuiltInSecondaryPositionNV;
627     case glslang::EbvSecondaryViewportMaskNV:
628         if (!memberDeclaration) {
629             builder.addExtension(spv::E_SPV_NV_stereo_view_rendering);
630             builder.addCapability(spv::CapabilityShaderStereoViewNV);
631         }
632         return spv::BuiltInSecondaryViewportMaskNV;
633     case glslang::EbvPositionPerViewNV:
634         if (!memberDeclaration) {
635             builder.addExtension(spv::E_SPV_NVX_multiview_per_view_attributes);
636             builder.addCapability(spv::CapabilityPerViewAttributesNV);
637         }
638         return spv::BuiltInPositionPerViewNV;
639     case glslang::EbvViewportMaskPerViewNV:
640         if (!memberDeclaration) {
641             builder.addExtension(spv::E_SPV_NVX_multiview_per_view_attributes);
642             builder.addCapability(spv::CapabilityPerViewAttributesNV);
643         }
644         return spv::BuiltInViewportMaskPerViewNV;
645 #endif 
646     default:
647         return spv::BuiltInMax;
648     }
649 }
650
651 // Translate glslang image layout format to SPIR-V image format.
652 spv::ImageFormat TGlslangToSpvTraverser::TranslateImageFormat(const glslang::TType& type)
653 {
654     assert(type.getBasicType() == glslang::EbtSampler);
655
656     // Check for capabilities
657     switch (type.getQualifier().layoutFormat) {
658     case glslang::ElfRg32f:
659     case glslang::ElfRg16f:
660     case glslang::ElfR11fG11fB10f:
661     case glslang::ElfR16f:
662     case glslang::ElfRgba16:
663     case glslang::ElfRgb10A2:
664     case glslang::ElfRg16:
665     case glslang::ElfRg8:
666     case glslang::ElfR16:
667     case glslang::ElfR8:
668     case glslang::ElfRgba16Snorm:
669     case glslang::ElfRg16Snorm:
670     case glslang::ElfRg8Snorm:
671     case glslang::ElfR16Snorm:
672     case glslang::ElfR8Snorm:
673
674     case glslang::ElfRg32i:
675     case glslang::ElfRg16i:
676     case glslang::ElfRg8i:
677     case glslang::ElfR16i:
678     case glslang::ElfR8i:
679
680     case glslang::ElfRgb10a2ui:
681     case glslang::ElfRg32ui:
682     case glslang::ElfRg16ui:
683     case glslang::ElfRg8ui:
684     case glslang::ElfR16ui:
685     case glslang::ElfR8ui:
686         builder.addCapability(spv::CapabilityStorageImageExtendedFormats);
687         break;
688
689     default:
690         break;
691     }
692
693     // do the translation
694     switch (type.getQualifier().layoutFormat) {
695     case glslang::ElfNone:          return spv::ImageFormatUnknown;
696     case glslang::ElfRgba32f:       return spv::ImageFormatRgba32f;
697     case glslang::ElfRgba16f:       return spv::ImageFormatRgba16f;
698     case glslang::ElfR32f:          return spv::ImageFormatR32f;
699     case glslang::ElfRgba8:         return spv::ImageFormatRgba8;
700     case glslang::ElfRgba8Snorm:    return spv::ImageFormatRgba8Snorm;
701     case glslang::ElfRg32f:         return spv::ImageFormatRg32f;
702     case glslang::ElfRg16f:         return spv::ImageFormatRg16f;
703     case glslang::ElfR11fG11fB10f:  return spv::ImageFormatR11fG11fB10f;
704     case glslang::ElfR16f:          return spv::ImageFormatR16f;
705     case glslang::ElfRgba16:        return spv::ImageFormatRgba16;
706     case glslang::ElfRgb10A2:       return spv::ImageFormatRgb10A2;
707     case glslang::ElfRg16:          return spv::ImageFormatRg16;
708     case glslang::ElfRg8:           return spv::ImageFormatRg8;
709     case glslang::ElfR16:           return spv::ImageFormatR16;
710     case glslang::ElfR8:            return spv::ImageFormatR8;
711     case glslang::ElfRgba16Snorm:   return spv::ImageFormatRgba16Snorm;
712     case glslang::ElfRg16Snorm:     return spv::ImageFormatRg16Snorm;
713     case glslang::ElfRg8Snorm:      return spv::ImageFormatRg8Snorm;
714     case glslang::ElfR16Snorm:      return spv::ImageFormatR16Snorm;
715     case glslang::ElfR8Snorm:       return spv::ImageFormatR8Snorm;
716     case glslang::ElfRgba32i:       return spv::ImageFormatRgba32i;
717     case glslang::ElfRgba16i:       return spv::ImageFormatRgba16i;
718     case glslang::ElfRgba8i:        return spv::ImageFormatRgba8i;
719     case glslang::ElfR32i:          return spv::ImageFormatR32i;
720     case glslang::ElfRg32i:         return spv::ImageFormatRg32i;
721     case glslang::ElfRg16i:         return spv::ImageFormatRg16i;
722     case glslang::ElfRg8i:          return spv::ImageFormatRg8i;
723     case glslang::ElfR16i:          return spv::ImageFormatR16i;
724     case glslang::ElfR8i:           return spv::ImageFormatR8i;
725     case glslang::ElfRgba32ui:      return spv::ImageFormatRgba32ui;
726     case glslang::ElfRgba16ui:      return spv::ImageFormatRgba16ui;
727     case glslang::ElfRgba8ui:       return spv::ImageFormatRgba8ui;
728     case glslang::ElfR32ui:         return spv::ImageFormatR32ui;
729     case glslang::ElfRg32ui:        return spv::ImageFormatRg32ui;
730     case glslang::ElfRg16ui:        return spv::ImageFormatRg16ui;
731     case glslang::ElfRgb10a2ui:     return spv::ImageFormatRgb10a2ui;
732     case glslang::ElfRg8ui:         return spv::ImageFormatRg8ui;
733     case glslang::ElfR16ui:         return spv::ImageFormatR16ui;
734     case glslang::ElfR8ui:          return spv::ImageFormatR8ui;
735     default:                        return spv::ImageFormatMax;
736     }
737 }
738
739 spv::LoopControlMask TGlslangToSpvTraverser::TranslateLoopControl(glslang::TLoopControl loopControl) const
740 {
741     switch (loopControl) {
742     case glslang::ELoopControlNone:       return spv::LoopControlMaskNone;
743     case glslang::ELoopControlUnroll:     return spv::LoopControlUnrollMask;
744     case glslang::ELoopControlDontUnroll: return spv::LoopControlDontUnrollMask;
745     // TODO: DependencyInfinite
746     // TODO: DependencyLength
747     default:                              return spv::LoopControlMaskNone;
748     }
749 }
750
751 // Translate glslang type to SPIR-V storage class.
752 spv::StorageClass TGlslangToSpvTraverser::TranslateStorageClass(const glslang::TType& type)
753 {
754     if (type.getQualifier().isPipeInput())
755         return spv::StorageClassInput;
756     else if (type.getQualifier().isPipeOutput())
757         return spv::StorageClassOutput;
758     else if (type.getBasicType() == glslang::EbtAtomicUint)
759         return spv::StorageClassAtomicCounter;
760     else if (type.containsOpaque())
761         return spv::StorageClassUniformConstant;
762     else if (glslangIntermediate->usingStorageBuffer() && type.getQualifier().storage == glslang::EvqBuffer) {
763         builder.addExtension(spv::E_SPV_KHR_storage_buffer_storage_class);
764         return spv::StorageClassStorageBuffer;
765     } else if (type.getQualifier().isUniformOrBuffer()) {
766         if (type.getQualifier().layoutPushConstant)
767             return spv::StorageClassPushConstant;
768         if (type.getBasicType() == glslang::EbtBlock)
769             return spv::StorageClassUniform;
770         else
771             return spv::StorageClassUniformConstant;
772     } else {
773         switch (type.getQualifier().storage) {
774         case glslang::EvqShared:        return spv::StorageClassWorkgroup;  break;
775         case glslang::EvqGlobal:        return spv::StorageClassPrivate;
776         case glslang::EvqConstReadOnly: return spv::StorageClassFunction;
777         case glslang::EvqTemporary:     return spv::StorageClassFunction;
778         default:
779             assert(0);
780             return spv::StorageClassFunction;
781         }
782     }
783 }
784
785 // Return whether or not the given type is something that should be tied to a
786 // descriptor set.
787 bool IsDescriptorResource(const glslang::TType& type)
788 {
789     // uniform and buffer blocks are included, unless it is a push_constant
790     if (type.getBasicType() == glslang::EbtBlock)
791         return type.getQualifier().isUniformOrBuffer() && ! type.getQualifier().layoutPushConstant;
792
793     // non block...
794     // basically samplerXXX/subpass/sampler/texture are all included
795     // if they are the global-scope-class, not the function parameter
796     // (or local, if they ever exist) class.
797     if (type.getBasicType() == glslang::EbtSampler)
798         return type.getQualifier().isUniformOrBuffer();
799
800     // None of the above.
801     return false;
802 }
803
804 void InheritQualifiers(glslang::TQualifier& child, const glslang::TQualifier& parent)
805 {
806     if (child.layoutMatrix == glslang::ElmNone)
807         child.layoutMatrix = parent.layoutMatrix;
808
809     if (parent.invariant)
810         child.invariant = true;
811     if (parent.nopersp)
812         child.nopersp = true;
813 #ifdef AMD_EXTENSIONS
814     if (parent.explicitInterp)
815         child.explicitInterp = true;
816 #endif
817     if (parent.flat)
818         child.flat = true;
819     if (parent.centroid)
820         child.centroid = true;
821     if (parent.patch)
822         child.patch = true;
823     if (parent.sample)
824         child.sample = true;
825     if (parent.coherent)
826         child.coherent = true;
827     if (parent.volatil)
828         child.volatil = true;
829     if (parent.restrict)
830         child.restrict = true;
831     if (parent.readonly)
832         child.readonly = true;
833     if (parent.writeonly)
834         child.writeonly = true;
835 }
836
837 bool HasNonLayoutQualifiers(const glslang::TType& type, const glslang::TQualifier& qualifier)
838 {
839     // This should list qualifiers that simultaneous satisfy:
840     // - struct members might inherit from a struct declaration
841     //     (note that non-block structs don't explicitly inherit,
842     //      only implicitly, meaning no decoration involved)
843     // - affect decorations on the struct members
844     //     (note smooth does not, and expecting something like volatile
845     //      to effect the whole object)
846     // - are not part of the offset/st430/etc or row/column-major layout
847     return qualifier.invariant || (qualifier.hasLocation() && type.getBasicType() == glslang::EbtBlock);
848 }
849
850 //
851 // Implement the TGlslangToSpvTraverser class.
852 //
853
854 TGlslangToSpvTraverser::TGlslangToSpvTraverser(const glslang::TIntermediate* glslangIntermediate, spv::SpvBuildLogger* buildLogger)
855     : TIntermTraverser(true, false, true), shaderEntry(nullptr), currentFunction(nullptr),
856       sequenceDepth(0), logger(buildLogger),
857       builder((glslang::GetKhronosToolId() << 16) | GeneratorVersion, logger),
858       inEntryPoint(false), entryPointTerminated(false), linkageOnly(false),
859       glslangIntermediate(glslangIntermediate)
860 {
861     spv::ExecutionModel executionModel = TranslateExecutionModel(glslangIntermediate->getStage());
862
863     builder.clearAccessChain();
864     builder.setSource(TranslateSourceLanguage(glslangIntermediate->getSource(), glslangIntermediate->getProfile()), glslangIntermediate->getVersion());
865     stdBuiltins = builder.import("GLSL.std.450");
866     builder.setMemoryModel(spv::AddressingModelLogical, spv::MemoryModelGLSL450);
867     shaderEntry = builder.makeEntryPoint(glslangIntermediate->getEntryPointName().c_str());
868     entryPoint = builder.addEntryPoint(executionModel, shaderEntry, glslangIntermediate->getEntryPointName().c_str());
869
870     // Add the source extensions
871     const auto& sourceExtensions = glslangIntermediate->getRequestedExtensions();
872     for (auto it = sourceExtensions.begin(); it != sourceExtensions.end(); ++it)
873         builder.addSourceExtension(it->c_str());
874
875     // Add the top-level modes for this shader.
876
877     if (glslangIntermediate->getXfbMode()) {
878         builder.addCapability(spv::CapabilityTransformFeedback);
879         builder.addExecutionMode(shaderEntry, spv::ExecutionModeXfb);
880     }
881
882     unsigned int mode;
883     switch (glslangIntermediate->getStage()) {
884     case EShLangVertex:
885         builder.addCapability(spv::CapabilityShader);
886         break;
887
888     case EShLangTessEvaluation:
889     case EShLangTessControl:
890         builder.addCapability(spv::CapabilityTessellation);
891
892         glslang::TLayoutGeometry primitive;
893
894         if (glslangIntermediate->getStage() == EShLangTessControl) {
895             builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, glslangIntermediate->getVertices());
896             primitive = glslangIntermediate->getOutputPrimitive();
897         } else {
898             primitive = glslangIntermediate->getInputPrimitive();
899         }
900
901         switch (primitive) {
902         case glslang::ElgTriangles:           mode = spv::ExecutionModeTriangles;     break;
903         case glslang::ElgQuads:               mode = spv::ExecutionModeQuads;         break;
904         case glslang::ElgIsolines:            mode = spv::ExecutionModeIsolines;      break;
905         default:                              mode = spv::ExecutionModeMax;           break;
906         }
907         if (mode != spv::ExecutionModeMax)
908             builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode);
909
910         switch (glslangIntermediate->getVertexSpacing()) {
911         case glslang::EvsEqual:            mode = spv::ExecutionModeSpacingEqual;          break;
912         case glslang::EvsFractionalEven:   mode = spv::ExecutionModeSpacingFractionalEven; break;
913         case glslang::EvsFractionalOdd:    mode = spv::ExecutionModeSpacingFractionalOdd;  break;
914         default:                           mode = spv::ExecutionModeMax;                   break;
915         }
916         if (mode != spv::ExecutionModeMax)
917             builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode);
918
919         switch (glslangIntermediate->getVertexOrder()) {
920         case glslang::EvoCw:     mode = spv::ExecutionModeVertexOrderCw;  break;
921         case glslang::EvoCcw:    mode = spv::ExecutionModeVertexOrderCcw; break;
922         default:                 mode = spv::ExecutionModeMax;            break;
923         }
924         if (mode != spv::ExecutionModeMax)
925             builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode);
926
927         if (glslangIntermediate->getPointMode())
928             builder.addExecutionMode(shaderEntry, spv::ExecutionModePointMode);
929         break;
930
931     case EShLangGeometry:
932         builder.addCapability(spv::CapabilityGeometry);
933         switch (glslangIntermediate->getInputPrimitive()) {
934         case glslang::ElgPoints:             mode = spv::ExecutionModeInputPoints;             break;
935         case glslang::ElgLines:              mode = spv::ExecutionModeInputLines;              break;
936         case glslang::ElgLinesAdjacency:     mode = spv::ExecutionModeInputLinesAdjacency;     break;
937         case glslang::ElgTriangles:          mode = spv::ExecutionModeTriangles;               break;
938         case glslang::ElgTrianglesAdjacency: mode = spv::ExecutionModeInputTrianglesAdjacency; break;
939         default:                             mode = spv::ExecutionModeMax;                     break;
940         }
941         if (mode != spv::ExecutionModeMax)
942             builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode);
943
944         builder.addExecutionMode(shaderEntry, spv::ExecutionModeInvocations, glslangIntermediate->getInvocations());
945
946         switch (glslangIntermediate->getOutputPrimitive()) {
947         case glslang::ElgPoints:        mode = spv::ExecutionModeOutputPoints;                 break;
948         case glslang::ElgLineStrip:     mode = spv::ExecutionModeOutputLineStrip;              break;
949         case glslang::ElgTriangleStrip: mode = spv::ExecutionModeOutputTriangleStrip;          break;
950         default:                        mode = spv::ExecutionModeMax;                          break;
951         }
952         if (mode != spv::ExecutionModeMax)
953             builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode);
954         builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, glslangIntermediate->getVertices());
955         break;
956
957     case EShLangFragment:
958         builder.addCapability(spv::CapabilityShader);
959         if (glslangIntermediate->getPixelCenterInteger())
960             builder.addExecutionMode(shaderEntry, spv::ExecutionModePixelCenterInteger);
961
962         if (glslangIntermediate->getOriginUpperLeft())
963             builder.addExecutionMode(shaderEntry, spv::ExecutionModeOriginUpperLeft);
964         else
965             builder.addExecutionMode(shaderEntry, spv::ExecutionModeOriginLowerLeft);
966
967         if (glslangIntermediate->getEarlyFragmentTests())
968             builder.addExecutionMode(shaderEntry, spv::ExecutionModeEarlyFragmentTests);
969
970         switch(glslangIntermediate->getDepth()) {
971         case glslang::EldGreater:  mode = spv::ExecutionModeDepthGreater; break;
972         case glslang::EldLess:     mode = spv::ExecutionModeDepthLess;    break;
973         default:                   mode = spv::ExecutionModeMax;          break;
974         }
975         if (mode != spv::ExecutionModeMax)
976             builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode);
977
978         if (glslangIntermediate->getDepth() != glslang::EldUnchanged && glslangIntermediate->isDepthReplacing())
979             builder.addExecutionMode(shaderEntry, spv::ExecutionModeDepthReplacing);
980         break;
981
982     case EShLangCompute:
983         builder.addCapability(spv::CapabilityShader);
984         builder.addExecutionMode(shaderEntry, spv::ExecutionModeLocalSize, glslangIntermediate->getLocalSize(0),
985                                                                            glslangIntermediate->getLocalSize(1),
986                                                                            glslangIntermediate->getLocalSize(2));
987         break;
988
989     default:
990         break;
991     }
992 }
993
994 // Finish creating SPV, after the traversal is complete.
995 void TGlslangToSpvTraverser::finishSpv()
996 {
997     if (! entryPointTerminated) {
998         builder.setBuildPoint(shaderEntry->getLastBlock());
999         builder.leaveFunction();
1000     }
1001
1002     // finish off the entry-point SPV instruction by adding the Input/Output <id>
1003     for (auto it = iOSet.cbegin(); it != iOSet.cend(); ++it)
1004         entryPoint->addIdOperand(*it);
1005
1006     builder.eliminateDeadDecorations();
1007 }
1008
1009 // Write the SPV into 'out'.
1010 void TGlslangToSpvTraverser::dumpSpv(std::vector<unsigned int>& out)
1011 {
1012     builder.dump(out);
1013 }
1014
1015 //
1016 // Implement the traversal functions.
1017 //
1018 // Return true from interior nodes to have the external traversal
1019 // continue on to children.  Return false if children were
1020 // already processed.
1021 //
1022
1023 //
1024 // Symbols can turn into
1025 //  - uniform/input reads
1026 //  - output writes
1027 //  - complex lvalue base setups:  foo.bar[3]....  , where we see foo and start up an access chain
1028 //  - something simple that degenerates into the last bullet
1029 //
1030 void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol)
1031 {
1032     SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder);
1033     if (symbol->getType().getQualifier().isSpecConstant())
1034         spec_constant_op_mode_setter.turnOnSpecConstantOpMode();
1035
1036     // getSymbolId() will set up all the IO decorations on the first call.
1037     // Formal function parameters were mapped during makeFunctions().
1038     spv::Id id = getSymbolId(symbol);
1039
1040     // Include all "static use" and "linkage only" interface variables on the OpEntryPoint instruction
1041     if (builder.isPointer(id)) {
1042         spv::StorageClass sc = builder.getStorageClass(id);
1043         if (sc == spv::StorageClassInput || sc == spv::StorageClassOutput)
1044             iOSet.insert(id);
1045     }
1046
1047     // Only process non-linkage-only nodes for generating actual static uses
1048     if (! linkageOnly || symbol->getQualifier().isSpecConstant()) {
1049         // Prepare to generate code for the access
1050
1051         // L-value chains will be computed left to right.  We're on the symbol now,
1052         // which is the left-most part of the access chain, so now is "clear" time,
1053         // followed by setting the base.
1054         builder.clearAccessChain();
1055
1056         // For now, we consider all user variables as being in memory, so they are pointers,
1057         // except for
1058         // A) R-Value arguments to a function, which are an intermediate object.
1059         //    See comments in handleUserFunctionCall().
1060         // B) Specialization constants (normal constants don't even come in as a variable),
1061         //    These are also pure R-values.
1062         glslang::TQualifier qualifier = symbol->getQualifier();
1063         if (qualifier.isSpecConstant() || rValueParameters.find(symbol->getId()) != rValueParameters.end())
1064             builder.setAccessChainRValue(id);
1065         else
1066             builder.setAccessChainLValue(id);
1067     }
1068 }
1069
1070 bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::TIntermBinary* node)
1071 {
1072     SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder);
1073     if (node->getType().getQualifier().isSpecConstant())
1074         spec_constant_op_mode_setter.turnOnSpecConstantOpMode();
1075
1076     // First, handle special cases
1077     switch (node->getOp()) {
1078     case glslang::EOpAssign:
1079     case glslang::EOpAddAssign:
1080     case glslang::EOpSubAssign:
1081     case glslang::EOpMulAssign:
1082     case glslang::EOpVectorTimesMatrixAssign:
1083     case glslang::EOpVectorTimesScalarAssign:
1084     case glslang::EOpMatrixTimesScalarAssign:
1085     case glslang::EOpMatrixTimesMatrixAssign:
1086     case glslang::EOpDivAssign:
1087     case glslang::EOpModAssign:
1088     case glslang::EOpAndAssign:
1089     case glslang::EOpInclusiveOrAssign:
1090     case glslang::EOpExclusiveOrAssign:
1091     case glslang::EOpLeftShiftAssign:
1092     case glslang::EOpRightShiftAssign:
1093         // A bin-op assign "a += b" means the same thing as "a = a + b"
1094         // where a is evaluated before b. For a simple assignment, GLSL
1095         // says to evaluate the left before the right.  So, always, left
1096         // node then right node.
1097         {
1098             // get the left l-value, save it away
1099             builder.clearAccessChain();
1100             node->getLeft()->traverse(this);
1101             spv::Builder::AccessChain lValue = builder.getAccessChain();
1102
1103             // evaluate the right
1104             builder.clearAccessChain();
1105             node->getRight()->traverse(this);
1106             spv::Id rValue = accessChainLoad(node->getRight()->getType());
1107
1108             if (node->getOp() != glslang::EOpAssign) {
1109                 // the left is also an r-value
1110                 builder.setAccessChain(lValue);
1111                 spv::Id leftRValue = accessChainLoad(node->getLeft()->getType());
1112
1113                 // do the operation
1114                 rValue = createBinaryOperation(node->getOp(), TranslatePrecisionDecoration(node->getOperationPrecision()),
1115                                                TranslateNoContractionDecoration(node->getType().getQualifier()),
1116                                                convertGlslangToSpvType(node->getType()), leftRValue, rValue,
1117                                                node->getType().getBasicType());
1118
1119                 // these all need their counterparts in createBinaryOperation()
1120                 assert(rValue != spv::NoResult);
1121             }
1122
1123             // store the result
1124             builder.setAccessChain(lValue);
1125             multiTypeStore(node->getType(), rValue);
1126
1127             // assignments are expressions having an rValue after they are evaluated...
1128             builder.clearAccessChain();
1129             builder.setAccessChainRValue(rValue);
1130         }
1131         return false;
1132     case glslang::EOpIndexDirect:
1133     case glslang::EOpIndexDirectStruct:
1134         {
1135             // Get the left part of the access chain.
1136             node->getLeft()->traverse(this);
1137
1138             // Add the next element in the chain
1139
1140             const int glslangIndex = node->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst();
1141             if (! node->getLeft()->getType().isArray() &&
1142                 node->getLeft()->getType().isVector() &&
1143                 node->getOp() == glslang::EOpIndexDirect) {
1144                 // This is essentially a hard-coded vector swizzle of size 1,
1145                 // so short circuit the access-chain stuff with a swizzle.
1146                 std::vector<unsigned> swizzle;
1147                 swizzle.push_back(glslangIndex);
1148                 builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType()));
1149             } else {
1150                 int spvIndex = glslangIndex;
1151                 if (node->getLeft()->getBasicType() == glslang::EbtBlock &&
1152                     node->getOp() == glslang::EOpIndexDirectStruct)
1153                 {
1154                     // This may be, e.g., an anonymous block-member selection, which generally need
1155                     // index remapping due to hidden members in anonymous blocks.
1156                     std::vector<int>& remapper = memberRemapper[node->getLeft()->getType().getStruct()];
1157                     assert(remapper.size() > 0);
1158                     spvIndex = remapper[glslangIndex];
1159                 }
1160
1161                 // normal case for indexing array or structure or block
1162                 builder.accessChainPush(builder.makeIntConstant(spvIndex));
1163
1164                 // Add capabilities here for accessing PointSize and clip/cull distance.
1165                 // We have deferred generation of associated capabilities until now.
1166                 if (node->getLeft()->getType().isStruct() && ! node->getLeft()->getType().isArray())
1167                     declareUseOfStructMember(*(node->getLeft()->getType().getStruct()), glslangIndex);
1168             }
1169         }
1170         return false;
1171     case glslang::EOpIndexIndirect:
1172         {
1173             // Structure or array or vector indirection.
1174             // Will use native SPIR-V access-chain for struct and array indirection;
1175             // matrices are arrays of vectors, so will also work for a matrix.
1176             // Will use the access chain's 'component' for variable index into a vector.
1177
1178             // This adapter is building access chains left to right.
1179             // Set up the access chain to the left.
1180             node->getLeft()->traverse(this);
1181
1182             // save it so that computing the right side doesn't trash it
1183             spv::Builder::AccessChain partial = builder.getAccessChain();
1184
1185             // compute the next index in the chain
1186             builder.clearAccessChain();
1187             node->getRight()->traverse(this);
1188             spv::Id index = accessChainLoad(node->getRight()->getType());
1189
1190             // restore the saved access chain
1191             builder.setAccessChain(partial);
1192
1193             if (! node->getLeft()->getType().isArray() && node->getLeft()->getType().isVector())
1194                 builder.accessChainPushComponent(index, convertGlslangToSpvType(node->getLeft()->getType()));
1195             else
1196                 builder.accessChainPush(index);
1197         }
1198         return false;
1199     case glslang::EOpVectorSwizzle:
1200         {
1201             node->getLeft()->traverse(this);
1202             std::vector<unsigned> swizzle;
1203             convertSwizzle(*node->getRight()->getAsAggregate(), swizzle);
1204             builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType()));
1205         }
1206         return false;
1207     case glslang::EOpMatrixSwizzle:
1208         logger->missingFunctionality("matrix swizzle");
1209         return true;
1210     case glslang::EOpLogicalOr:
1211     case glslang::EOpLogicalAnd:
1212         {
1213
1214             // These may require short circuiting, but can sometimes be done as straight
1215             // binary operations.  The right operand must be short circuited if it has
1216             // side effects, and should probably be if it is complex.
1217             if (isTrivial(node->getRight()->getAsTyped()))
1218                 break; // handle below as a normal binary operation
1219             // otherwise, we need to do dynamic short circuiting on the right operand
1220             spv::Id result = createShortCircuit(node->getOp(), *node->getLeft()->getAsTyped(), *node->getRight()->getAsTyped());
1221             builder.clearAccessChain();
1222             builder.setAccessChainRValue(result);
1223         }
1224         return false;
1225     default:
1226         break;
1227     }
1228
1229     // Assume generic binary op...
1230
1231     // get right operand
1232     builder.clearAccessChain();
1233     node->getLeft()->traverse(this);
1234     spv::Id left = accessChainLoad(node->getLeft()->getType());
1235
1236     // get left operand
1237     builder.clearAccessChain();
1238     node->getRight()->traverse(this);
1239     spv::Id right = accessChainLoad(node->getRight()->getType());
1240
1241     // get result
1242     spv::Id result = createBinaryOperation(node->getOp(), TranslatePrecisionDecoration(node->getOperationPrecision()),
1243                                            TranslateNoContractionDecoration(node->getType().getQualifier()),
1244                                            convertGlslangToSpvType(node->getType()), left, right,
1245                                            node->getLeft()->getType().getBasicType());
1246
1247     builder.clearAccessChain();
1248     if (! result) {
1249         logger->missingFunctionality("unknown glslang binary operation");
1250         return true;  // pick up a child as the place-holder result
1251     } else {
1252         builder.setAccessChainRValue(result);
1253         return false;
1254     }
1255 }
1256
1257 bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TIntermUnary* node)
1258 {
1259     SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder);
1260     if (node->getType().getQualifier().isSpecConstant())
1261         spec_constant_op_mode_setter.turnOnSpecConstantOpMode();
1262
1263     spv::Id result = spv::NoResult;
1264
1265     // try texturing first
1266     result = createImageTextureFunctionCall(node);
1267     if (result != spv::NoResult) {
1268         builder.clearAccessChain();
1269         builder.setAccessChainRValue(result);
1270
1271         return false; // done with this node
1272     }
1273
1274     // Non-texturing.
1275
1276     if (node->getOp() == glslang::EOpArrayLength) {
1277         // Quite special; won't want to evaluate the operand.
1278
1279         // Normal .length() would have been constant folded by the front-end.
1280         // So, this has to be block.lastMember.length().
1281         // SPV wants "block" and member number as the operands, go get them.
1282         assert(node->getOperand()->getType().isRuntimeSizedArray());
1283         glslang::TIntermTyped* block = node->getOperand()->getAsBinaryNode()->getLeft();
1284         block->traverse(this);
1285         unsigned int member = node->getOperand()->getAsBinaryNode()->getRight()->getAsConstantUnion()->getConstArray()[0].getUConst();
1286         spv::Id length = builder.createArrayLength(builder.accessChainGetLValue(), member);
1287
1288         builder.clearAccessChain();
1289         builder.setAccessChainRValue(length);
1290
1291         return false;
1292     }
1293
1294     // Start by evaluating the operand
1295
1296     // Does it need a swizzle inversion?  If so, evaluation is inverted;
1297     // operate first on the swizzle base, then apply the swizzle.
1298     spv::Id invertedType = spv::NoType;
1299     auto resultType = [&invertedType, &node, this](){ return invertedType != spv::NoType ? invertedType : convertGlslangToSpvType(node->getType()); };
1300     if (node->getOp() == glslang::EOpInterpolateAtCentroid)
1301         invertedType = getInvertedSwizzleType(*node->getOperand());
1302
1303     builder.clearAccessChain();
1304     if (invertedType != spv::NoType)
1305         node->getOperand()->getAsBinaryNode()->getLeft()->traverse(this);
1306     else
1307         node->getOperand()->traverse(this);
1308
1309     spv::Id operand = spv::NoResult;
1310
1311     if (node->getOp() == glslang::EOpAtomicCounterIncrement ||
1312         node->getOp() == glslang::EOpAtomicCounterDecrement ||
1313         node->getOp() == glslang::EOpAtomicCounter          ||
1314         node->getOp() == glslang::EOpInterpolateAtCentroid)
1315         operand = builder.accessChainGetLValue(); // Special case l-value operands
1316     else
1317         operand = accessChainLoad(node->getOperand()->getType());
1318
1319     spv::Decoration precision = TranslatePrecisionDecoration(node->getOperationPrecision());
1320     spv::Decoration noContraction = TranslateNoContractionDecoration(node->getType().getQualifier());
1321
1322     // it could be a conversion
1323     if (! result)
1324         result = createConversion(node->getOp(), precision, noContraction, resultType(), operand, node->getOperand()->getBasicType());
1325
1326     // if not, then possibly an operation
1327     if (! result)
1328         result = createUnaryOperation(node->getOp(), precision, noContraction, resultType(), operand, node->getOperand()->getBasicType());
1329
1330     if (result) {
1331         if (invertedType)
1332             result = createInvertedSwizzle(precision, *node->getOperand(), result);
1333
1334         builder.clearAccessChain();
1335         builder.setAccessChainRValue(result);
1336
1337         return false; // done with this node
1338     }
1339
1340     // it must be a special case, check...
1341     switch (node->getOp()) {
1342     case glslang::EOpPostIncrement:
1343     case glslang::EOpPostDecrement:
1344     case glslang::EOpPreIncrement:
1345     case glslang::EOpPreDecrement:
1346         {
1347             // we need the integer value "1" or the floating point "1.0" to add/subtract
1348             spv::Id one = 0;
1349             if (node->getBasicType() == glslang::EbtFloat)
1350                 one = builder.makeFloatConstant(1.0F);
1351             else if (node->getBasicType() == glslang::EbtDouble)
1352                 one = builder.makeDoubleConstant(1.0);
1353 #ifdef AMD_EXTENSIONS
1354             else if (node->getBasicType() == glslang::EbtFloat16)
1355                 one = builder.makeFloat16Constant(1.0F);
1356 #endif
1357             else if (node->getBasicType() == glslang::EbtInt64 || node->getBasicType() == glslang::EbtUint64)
1358                 one = builder.makeInt64Constant(1);
1359             else
1360                 one = builder.makeIntConstant(1);
1361             glslang::TOperator op;
1362             if (node->getOp() == glslang::EOpPreIncrement ||
1363                 node->getOp() == glslang::EOpPostIncrement)
1364                 op = glslang::EOpAdd;
1365             else
1366                 op = glslang::EOpSub;
1367
1368             spv::Id result = createBinaryOperation(op, precision,
1369                                                    TranslateNoContractionDecoration(node->getType().getQualifier()),
1370                                                    convertGlslangToSpvType(node->getType()), operand, one,
1371                                                    node->getType().getBasicType());
1372             assert(result != spv::NoResult);
1373
1374             // The result of operation is always stored, but conditionally the
1375             // consumed result.  The consumed result is always an r-value.
1376             builder.accessChainStore(result);
1377             builder.clearAccessChain();
1378             if (node->getOp() == glslang::EOpPreIncrement ||
1379                 node->getOp() == glslang::EOpPreDecrement)
1380                 builder.setAccessChainRValue(result);
1381             else
1382                 builder.setAccessChainRValue(operand);
1383         }
1384
1385         return false;
1386
1387     case glslang::EOpEmitStreamVertex:
1388         builder.createNoResultOp(spv::OpEmitStreamVertex, operand);
1389         return false;
1390     case glslang::EOpEndStreamPrimitive:
1391         builder.createNoResultOp(spv::OpEndStreamPrimitive, operand);
1392         return false;
1393
1394     default:
1395         logger->missingFunctionality("unknown glslang unary");
1396         return true;  // pick up operand as placeholder result
1397     }
1398 }
1399
1400 bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TIntermAggregate* node)
1401 {
1402     SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder);
1403     if (node->getType().getQualifier().isSpecConstant())
1404         spec_constant_op_mode_setter.turnOnSpecConstantOpMode();
1405
1406     spv::Id result = spv::NoResult;
1407     spv::Id invertedType = spv::NoType;  // to use to override the natural type of the node
1408     auto resultType = [&invertedType, &node, this](){ return invertedType != spv::NoType ? invertedType : convertGlslangToSpvType(node->getType()); };
1409
1410     // try texturing
1411     result = createImageTextureFunctionCall(node);
1412     if (result != spv::NoResult) {
1413         builder.clearAccessChain();
1414         builder.setAccessChainRValue(result);
1415
1416         return false;
1417     } else if (node->getOp() == glslang::EOpImageStore) {
1418         // "imageStore" is a special case, which has no result
1419         return false;
1420     }
1421
1422     glslang::TOperator binOp = glslang::EOpNull;
1423     bool reduceComparison = true;
1424     bool isMatrix = false;
1425     bool noReturnValue = false;
1426     bool atomic = false;
1427
1428     assert(node->getOp());
1429
1430     spv::Decoration precision = TranslatePrecisionDecoration(node->getOperationPrecision());
1431
1432     switch (node->getOp()) {
1433     case glslang::EOpSequence:
1434     {
1435         if (preVisit)
1436             ++sequenceDepth;
1437         else
1438             --sequenceDepth;
1439
1440         if (sequenceDepth == 1) {
1441             // If this is the parent node of all the functions, we want to see them
1442             // early, so all call points have actual SPIR-V functions to reference.
1443             // In all cases, still let the traverser visit the children for us.
1444             makeFunctions(node->getAsAggregate()->getSequence());
1445
1446             // Also, we want all globals initializers to go into the beginning of the entry point, before
1447             // anything else gets there, so visit out of order, doing them all now.
1448             makeGlobalInitializers(node->getAsAggregate()->getSequence());
1449
1450             // Initializers are done, don't want to visit again, but functions and link objects need to be processed,
1451             // so do them manually.
1452             visitFunctions(node->getAsAggregate()->getSequence());
1453
1454             return false;
1455         }
1456
1457         return true;
1458     }
1459     case glslang::EOpLinkerObjects:
1460     {
1461         if (visit == glslang::EvPreVisit)
1462             linkageOnly = true;
1463         else
1464             linkageOnly = false;
1465
1466         return true;
1467     }
1468     case glslang::EOpComma:
1469     {
1470         // processing from left to right naturally leaves the right-most
1471         // lying around in the access chain
1472         glslang::TIntermSequence& glslangOperands = node->getSequence();
1473         for (int i = 0; i < (int)glslangOperands.size(); ++i)
1474             glslangOperands[i]->traverse(this);
1475
1476         return false;
1477     }
1478     case glslang::EOpFunction:
1479         if (visit == glslang::EvPreVisit) {
1480             if (isShaderEntryPoint(node)) {
1481                 inEntryPoint = true;
1482                 builder.setBuildPoint(shaderEntry->getLastBlock());
1483                 currentFunction = shaderEntry;
1484             } else {
1485                 handleFunctionEntry(node);
1486             }
1487         } else {
1488             if (inEntryPoint)
1489                 entryPointTerminated = true;
1490             builder.leaveFunction();
1491             inEntryPoint = false;
1492         }
1493
1494         return true;
1495     case glslang::EOpParameters:
1496         // Parameters will have been consumed by EOpFunction processing, but not
1497         // the body, so we still visited the function node's children, making this
1498         // child redundant.
1499         return false;
1500     case glslang::EOpFunctionCall:
1501     {
1502         if (node->isUserDefined())
1503             result = handleUserFunctionCall(node);
1504         // assert(result);  // this can happen for bad shaders because the call graph completeness checking is not yet done
1505         if (result) {
1506             builder.clearAccessChain();
1507             builder.setAccessChainRValue(result);
1508         } else
1509             logger->missingFunctionality("missing user function; linker needs to catch that");
1510
1511         return false;
1512     }
1513     case glslang::EOpConstructMat2x2:
1514     case glslang::EOpConstructMat2x3:
1515     case glslang::EOpConstructMat2x4:
1516     case glslang::EOpConstructMat3x2:
1517     case glslang::EOpConstructMat3x3:
1518     case glslang::EOpConstructMat3x4:
1519     case glslang::EOpConstructMat4x2:
1520     case glslang::EOpConstructMat4x3:
1521     case glslang::EOpConstructMat4x4:
1522     case glslang::EOpConstructDMat2x2:
1523     case glslang::EOpConstructDMat2x3:
1524     case glslang::EOpConstructDMat2x4:
1525     case glslang::EOpConstructDMat3x2:
1526     case glslang::EOpConstructDMat3x3:
1527     case glslang::EOpConstructDMat3x4:
1528     case glslang::EOpConstructDMat4x2:
1529     case glslang::EOpConstructDMat4x3:
1530     case glslang::EOpConstructDMat4x4:
1531 #ifdef AMD_EXTENSIONS
1532     case glslang::EOpConstructF16Mat2x2:
1533     case glslang::EOpConstructF16Mat2x3:
1534     case glslang::EOpConstructF16Mat2x4:
1535     case glslang::EOpConstructF16Mat3x2:
1536     case glslang::EOpConstructF16Mat3x3:
1537     case glslang::EOpConstructF16Mat3x4:
1538     case glslang::EOpConstructF16Mat4x2:
1539     case glslang::EOpConstructF16Mat4x3:
1540     case glslang::EOpConstructF16Mat4x4:
1541 #endif
1542         isMatrix = true;
1543         // fall through
1544     case glslang::EOpConstructFloat:
1545     case glslang::EOpConstructVec2:
1546     case glslang::EOpConstructVec3:
1547     case glslang::EOpConstructVec4:
1548     case glslang::EOpConstructDouble:
1549     case glslang::EOpConstructDVec2:
1550     case glslang::EOpConstructDVec3:
1551     case glslang::EOpConstructDVec4:
1552 #ifdef AMD_EXTENSIONS
1553     case glslang::EOpConstructFloat16:
1554     case glslang::EOpConstructF16Vec2:
1555     case glslang::EOpConstructF16Vec3:
1556     case glslang::EOpConstructF16Vec4:
1557 #endif
1558     case glslang::EOpConstructBool:
1559     case glslang::EOpConstructBVec2:
1560     case glslang::EOpConstructBVec3:
1561     case glslang::EOpConstructBVec4:
1562     case glslang::EOpConstructInt:
1563     case glslang::EOpConstructIVec2:
1564     case glslang::EOpConstructIVec3:
1565     case glslang::EOpConstructIVec4:
1566     case glslang::EOpConstructUint:
1567     case glslang::EOpConstructUVec2:
1568     case glslang::EOpConstructUVec3:
1569     case glslang::EOpConstructUVec4:
1570     case glslang::EOpConstructInt64:
1571     case glslang::EOpConstructI64Vec2:
1572     case glslang::EOpConstructI64Vec3:
1573     case glslang::EOpConstructI64Vec4:
1574     case glslang::EOpConstructUint64:
1575     case glslang::EOpConstructU64Vec2:
1576     case glslang::EOpConstructU64Vec3:
1577     case glslang::EOpConstructU64Vec4:
1578     case glslang::EOpConstructStruct:
1579     case glslang::EOpConstructTextureSampler:
1580     {
1581         std::vector<spv::Id> arguments;
1582         translateArguments(*node, arguments);
1583         spv::Id constructed;
1584         if (node->getOp() == glslang::EOpConstructTextureSampler)
1585             constructed = builder.createOp(spv::OpSampledImage, resultType(), arguments);
1586         else if (node->getOp() == glslang::EOpConstructStruct || node->getType().isArray()) {
1587             std::vector<spv::Id> constituents;
1588             for (int c = 0; c < (int)arguments.size(); ++c)
1589                 constituents.push_back(arguments[c]);
1590             constructed = builder.createCompositeConstruct(resultType(), constituents);
1591         } else if (isMatrix)
1592             constructed = builder.createMatrixConstructor(precision, arguments, resultType());
1593         else
1594             constructed = builder.createConstructor(precision, arguments, resultType());
1595
1596         builder.clearAccessChain();
1597         builder.setAccessChainRValue(constructed);
1598
1599         return false;
1600     }
1601
1602     // These six are component-wise compares with component-wise results.
1603     // Forward on to createBinaryOperation(), requesting a vector result.
1604     case glslang::EOpLessThan:
1605     case glslang::EOpGreaterThan:
1606     case glslang::EOpLessThanEqual:
1607     case glslang::EOpGreaterThanEqual:
1608     case glslang::EOpVectorEqual:
1609     case glslang::EOpVectorNotEqual:
1610     {
1611         // Map the operation to a binary
1612         binOp = node->getOp();
1613         reduceComparison = false;
1614         switch (node->getOp()) {
1615         case glslang::EOpVectorEqual:     binOp = glslang::EOpVectorEqual;      break;
1616         case glslang::EOpVectorNotEqual:  binOp = glslang::EOpVectorNotEqual;   break;
1617         default:                          binOp = node->getOp();                break;
1618         }
1619
1620         break;
1621     }
1622     case glslang::EOpMul:
1623         // component-wise matrix multiply
1624         binOp = glslang::EOpMul;
1625         break;
1626     case glslang::EOpOuterProduct:
1627         // two vectors multiplied to make a matrix
1628         binOp = glslang::EOpOuterProduct;
1629         break;
1630     case glslang::EOpDot:
1631     {
1632         // for scalar dot product, use multiply
1633         glslang::TIntermSequence& glslangOperands = node->getSequence();
1634         if (glslangOperands[0]->getAsTyped()->getVectorSize() == 1)
1635             binOp = glslang::EOpMul;
1636         break;
1637     }
1638     case glslang::EOpMod:
1639         // when an aggregate, this is the floating-point mod built-in function,
1640         // which can be emitted by the one in createBinaryOperation()
1641         binOp = glslang::EOpMod;
1642         break;
1643     case glslang::EOpEmitVertex:
1644     case glslang::EOpEndPrimitive:
1645     case glslang::EOpBarrier:
1646     case glslang::EOpMemoryBarrier:
1647     case glslang::EOpMemoryBarrierAtomicCounter:
1648     case glslang::EOpMemoryBarrierBuffer:
1649     case glslang::EOpMemoryBarrierImage:
1650     case glslang::EOpMemoryBarrierShared:
1651     case glslang::EOpGroupMemoryBarrier:
1652     case glslang::EOpAllMemoryBarrierWithGroupSync:
1653     case glslang::EOpGroupMemoryBarrierWithGroupSync:
1654     case glslang::EOpWorkgroupMemoryBarrier:
1655     case glslang::EOpWorkgroupMemoryBarrierWithGroupSync:
1656         noReturnValue = true;
1657         // These all have 0 operands and will naturally finish up in the code below for 0 operands
1658         break;
1659
1660     case glslang::EOpAtomicAdd:
1661     case glslang::EOpAtomicMin:
1662     case glslang::EOpAtomicMax:
1663     case glslang::EOpAtomicAnd:
1664     case glslang::EOpAtomicOr:
1665     case glslang::EOpAtomicXor:
1666     case glslang::EOpAtomicExchange:
1667     case glslang::EOpAtomicCompSwap:
1668         atomic = true;
1669         break;
1670
1671     default:
1672         break;
1673     }
1674
1675     //
1676     // See if it maps to a regular operation.
1677     //
1678     if (binOp != glslang::EOpNull) {
1679         glslang::TIntermTyped* left = node->getSequence()[0]->getAsTyped();
1680         glslang::TIntermTyped* right = node->getSequence()[1]->getAsTyped();
1681         assert(left && right);
1682
1683         builder.clearAccessChain();
1684         left->traverse(this);
1685         spv::Id leftId = accessChainLoad(left->getType());
1686
1687         builder.clearAccessChain();
1688         right->traverse(this);
1689         spv::Id rightId = accessChainLoad(right->getType());
1690
1691         result = createBinaryOperation(binOp, precision, TranslateNoContractionDecoration(node->getType().getQualifier()),
1692                                        resultType(), leftId, rightId,
1693                                        left->getType().getBasicType(), reduceComparison);
1694
1695         // code above should only make binOp that exists in createBinaryOperation
1696         assert(result != spv::NoResult);
1697         builder.clearAccessChain();
1698         builder.setAccessChainRValue(result);
1699
1700         return false;
1701     }
1702
1703     //
1704     // Create the list of operands.
1705     //
1706     glslang::TIntermSequence& glslangOperands = node->getSequence();
1707     std::vector<spv::Id> operands;
1708     for (int arg = 0; arg < (int)glslangOperands.size(); ++arg) {
1709         // special case l-value operands; there are just a few
1710         bool lvalue = false;
1711         switch (node->getOp()) {
1712         case glslang::EOpFrexp:
1713         case glslang::EOpModf:
1714             if (arg == 1)
1715                 lvalue = true;
1716             break;
1717         case glslang::EOpInterpolateAtSample:
1718         case glslang::EOpInterpolateAtOffset:
1719 #ifdef AMD_EXTENSIONS
1720         case glslang::EOpInterpolateAtVertex:
1721 #endif
1722             if (arg == 0) {
1723                 lvalue = true;
1724
1725                 // Does it need a swizzle inversion?  If so, evaluation is inverted;
1726                 // operate first on the swizzle base, then apply the swizzle.
1727                 if (glslangOperands[0]->getAsOperator() &&
1728                     glslangOperands[0]->getAsOperator()->getOp() == glslang::EOpVectorSwizzle)
1729                     invertedType = convertGlslangToSpvType(glslangOperands[0]->getAsBinaryNode()->getLeft()->getType());
1730             }
1731             break;
1732         case glslang::EOpAtomicAdd:
1733         case glslang::EOpAtomicMin:
1734         case glslang::EOpAtomicMax:
1735         case glslang::EOpAtomicAnd:
1736         case glslang::EOpAtomicOr:
1737         case glslang::EOpAtomicXor:
1738         case glslang::EOpAtomicExchange:
1739         case glslang::EOpAtomicCompSwap:
1740             if (arg == 0)
1741                 lvalue = true;
1742             break;
1743         case glslang::EOpAddCarry:
1744         case glslang::EOpSubBorrow:
1745             if (arg == 2)
1746                 lvalue = true;
1747             break;
1748         case glslang::EOpUMulExtended:
1749         case glslang::EOpIMulExtended:
1750             if (arg >= 2)
1751                 lvalue = true;
1752             break;
1753         default:
1754             break;
1755         }
1756         builder.clearAccessChain();
1757         if (invertedType != spv::NoType && arg == 0)
1758             glslangOperands[0]->getAsBinaryNode()->getLeft()->traverse(this);
1759         else
1760             glslangOperands[arg]->traverse(this);
1761         if (lvalue)
1762             operands.push_back(builder.accessChainGetLValue());
1763         else
1764             operands.push_back(accessChainLoad(glslangOperands[arg]->getAsTyped()->getType()));
1765     }
1766
1767     if (atomic) {
1768         // Handle all atomics
1769         result = createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType());
1770     } else {
1771         // Pass through to generic operations.
1772         switch (glslangOperands.size()) {
1773         case 0:
1774             result = createNoArgOperation(node->getOp(), precision, resultType());
1775             break;
1776         case 1:
1777             result = createUnaryOperation(
1778                 node->getOp(), precision,
1779                 TranslateNoContractionDecoration(node->getType().getQualifier()),
1780                 resultType(), operands.front(),
1781                 glslangOperands[0]->getAsTyped()->getBasicType());
1782             break;
1783         default:
1784             result = createMiscOperation(node->getOp(), precision, resultType(), operands, node->getBasicType());
1785             break;
1786         }
1787         if (invertedType)
1788             result = createInvertedSwizzle(precision, *glslangOperands[0]->getAsBinaryNode(), result);
1789     }
1790
1791     if (noReturnValue)
1792         return false;
1793
1794     if (! result) {
1795         logger->missingFunctionality("unknown glslang aggregate");
1796         return true;  // pick up a child as a placeholder operand
1797     } else {
1798         builder.clearAccessChain();
1799         builder.setAccessChainRValue(result);
1800         return false;
1801     }
1802 }
1803
1804 // This path handles both if-then-else and ?:
1805 // The if-then-else has a node type of void, while
1806 // ?: has either a void or a non-void node type
1807 //
1808 // Leaving the result, when not void:
1809 // GLSL only has r-values as the result of a :?, but
1810 // if we have an l-value, that can be more efficient if it will
1811 // become the base of a complex r-value expression, because the
1812 // next layer copies r-values into memory to use the access-chain mechanism
1813 bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang::TIntermSelection* node)
1814 {
1815     // See if it simple and safe to generate OpSelect instead of using control flow.
1816     // Crucially, side effects must be avoided, and there are performance trade-offs.
1817     // Return true if good idea (and safe) for OpSelect, false otherwise.
1818     const auto selectPolicy = [&]() -> bool {
1819         if ((!node->getType().isScalar() && !node->getType().isVector()) ||
1820             node->getBasicType() == glslang::EbtVoid)
1821             return false;
1822
1823         if (node->getTrueBlock()  == nullptr ||
1824             node->getFalseBlock() == nullptr)
1825             return false;
1826
1827         assert(node->getType() == node->getTrueBlock() ->getAsTyped()->getType() &&
1828                node->getType() == node->getFalseBlock()->getAsTyped()->getType());
1829
1830         // return true if a single operand to ? : is okay for OpSelect
1831         const auto operandOkay = [](glslang::TIntermTyped* node) {
1832             return node->getAsSymbolNode() || node->getType().getQualifier().isConstant();
1833         };
1834
1835         return operandOkay(node->getTrueBlock() ->getAsTyped()) &&
1836                operandOkay(node->getFalseBlock()->getAsTyped());
1837     };
1838
1839     // Emit OpSelect for this selection.
1840     const auto handleAsOpSelect = [&]() {
1841         node->getCondition()->traverse(this);
1842         spv::Id condition = accessChainLoad(node->getCondition()->getType());
1843         node->getTrueBlock()->traverse(this);
1844         spv::Id trueValue = accessChainLoad(node->getTrueBlock()->getAsTyped()->getType());
1845         node->getFalseBlock()->traverse(this);
1846         spv::Id falseValue = accessChainLoad(node->getTrueBlock()->getAsTyped()->getType());
1847
1848         // smear condition to vector, if necessary (AST is always scalar)
1849         if (builder.isVector(trueValue))
1850             condition = builder.smearScalar(spv::NoPrecision, condition, 
1851                                             builder.makeVectorType(builder.makeBoolType(),
1852                                                                    builder.getNumComponents(trueValue)));
1853
1854         spv::Id select = builder.createTriOp(spv::OpSelect,
1855                                              convertGlslangToSpvType(node->getType()), condition,
1856                                                                      trueValue, falseValue);
1857         builder.clearAccessChain();
1858         builder.setAccessChainRValue(select);
1859     };
1860
1861     // Try for OpSelect
1862
1863     if (selectPolicy()) {
1864         SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder);
1865         if (node->getType().getQualifier().isSpecConstant())
1866             spec_constant_op_mode_setter.turnOnSpecConstantOpMode();
1867
1868         handleAsOpSelect();
1869         return false;
1870     }
1871
1872     // Instead, emit control flow...
1873
1874     // Don't handle results as temporaries, because there will be two names
1875     // and better to leave SSA to later passes.
1876     spv::Id result = (node->getBasicType() == glslang::EbtVoid)
1877                         ? spv::NoResult
1878                         : builder.createVariable(spv::StorageClassFunction, convertGlslangToSpvType(node->getType()));
1879
1880     // emit the condition before doing anything with selection
1881     node->getCondition()->traverse(this);
1882
1883     // make an "if" based on the value created by the condition
1884     spv::Builder::If ifBuilder(accessChainLoad(node->getCondition()->getType()), builder);
1885
1886     // emit the "then" statement
1887     if (node->getTrueBlock() != nullptr) {
1888         node->getTrueBlock()->traverse(this);
1889         if (result != spv::NoResult)
1890              builder.createStore(accessChainLoad(node->getTrueBlock()->getAsTyped()->getType()), result);
1891     }
1892
1893     if (node->getFalseBlock() != nullptr) {
1894         ifBuilder.makeBeginElse();
1895         // emit the "else" statement
1896         node->getFalseBlock()->traverse(this);
1897         if (result != spv::NoResult)
1898             builder.createStore(accessChainLoad(node->getFalseBlock()->getAsTyped()->getType()), result);
1899     }
1900
1901     // finish off the control flow
1902     ifBuilder.makeEndIf();
1903
1904     if (result != spv::NoResult) {
1905         // GLSL only has r-values as the result of a :?, but
1906         // if we have an l-value, that can be more efficient if it will
1907         // become the base of a complex r-value expression, because the
1908         // next layer copies r-values into memory to use the access-chain mechanism
1909         builder.clearAccessChain();
1910         builder.setAccessChainLValue(result);
1911     }
1912
1913     return false;
1914 }
1915
1916 bool TGlslangToSpvTraverser::visitSwitch(glslang::TVisit /* visit */, glslang::TIntermSwitch* node)
1917 {
1918     // emit and get the condition before doing anything with switch
1919     node->getCondition()->traverse(this);
1920     spv::Id selector = accessChainLoad(node->getCondition()->getAsTyped()->getType());
1921
1922     // browse the children to sort out code segments
1923     int defaultSegment = -1;
1924     std::vector<TIntermNode*> codeSegments;
1925     glslang::TIntermSequence& sequence = node->getBody()->getSequence();
1926     std::vector<int> caseValues;
1927     std::vector<int> valueIndexToSegment(sequence.size());  // note: probably not all are used, it is an overestimate
1928     for (glslang::TIntermSequence::iterator c = sequence.begin(); c != sequence.end(); ++c) {
1929         TIntermNode* child = *c;
1930         if (child->getAsBranchNode() && child->getAsBranchNode()->getFlowOp() == glslang::EOpDefault)
1931             defaultSegment = (int)codeSegments.size();
1932         else if (child->getAsBranchNode() && child->getAsBranchNode()->getFlowOp() == glslang::EOpCase) {
1933             valueIndexToSegment[caseValues.size()] = (int)codeSegments.size();
1934             caseValues.push_back(child->getAsBranchNode()->getExpression()->getAsConstantUnion()->getConstArray()[0].getIConst());
1935         } else
1936             codeSegments.push_back(child);
1937     }
1938
1939     // handle the case where the last code segment is missing, due to no code
1940     // statements between the last case and the end of the switch statement
1941     if ((caseValues.size() && (int)codeSegments.size() == valueIndexToSegment[caseValues.size() - 1]) ||
1942         (int)codeSegments.size() == defaultSegment)
1943         codeSegments.push_back(nullptr);
1944
1945     // make the switch statement
1946     std::vector<spv::Block*> segmentBlocks; // returned, as the blocks allocated in the call
1947     builder.makeSwitch(selector, (int)codeSegments.size(), caseValues, valueIndexToSegment, defaultSegment, segmentBlocks);
1948
1949     // emit all the code in the segments
1950     breakForLoop.push(false);
1951     for (unsigned int s = 0; s < codeSegments.size(); ++s) {
1952         builder.nextSwitchSegment(segmentBlocks, s);
1953         if (codeSegments[s])
1954             codeSegments[s]->traverse(this);
1955         else
1956             builder.addSwitchBreak();
1957     }
1958     breakForLoop.pop();
1959
1960     builder.endSwitch(segmentBlocks);
1961
1962     return false;
1963 }
1964
1965 void TGlslangToSpvTraverser::visitConstantUnion(glslang::TIntermConstantUnion* node)
1966 {
1967     int nextConst = 0;
1968     spv::Id constant = createSpvConstantFromConstUnionArray(node->getType(), node->getConstArray(), nextConst, false);
1969
1970     builder.clearAccessChain();
1971     builder.setAccessChainRValue(constant);
1972 }
1973
1974 bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIntermLoop* node)
1975 {
1976     auto blocks = builder.makeNewLoop();
1977     builder.createBranch(&blocks.head);
1978
1979     // Loop control:
1980     const spv::LoopControlMask control = TranslateLoopControl(node->getLoopControl());
1981
1982     // TODO: dependency length
1983
1984     // Spec requires back edges to target header blocks, and every header block
1985     // must dominate its merge block.  Make a header block first to ensure these
1986     // conditions are met.  By definition, it will contain OpLoopMerge, followed
1987     // by a block-ending branch.  But we don't want to put any other body/test
1988     // instructions in it, since the body/test may have arbitrary instructions,
1989     // including merges of its own.
1990     builder.setBuildPoint(&blocks.head);
1991     builder.createLoopMerge(&blocks.merge, &blocks.continue_target, control);
1992     if (node->testFirst() && node->getTest()) {
1993         spv::Block& test = builder.makeNewBlock();
1994         builder.createBranch(&test);
1995
1996         builder.setBuildPoint(&test);
1997         node->getTest()->traverse(this);
1998         spv::Id condition =
1999             accessChainLoad(node->getTest()->getType());
2000         builder.createConditionalBranch(condition, &blocks.body, &blocks.merge);
2001
2002         builder.setBuildPoint(&blocks.body);
2003         breakForLoop.push(true);
2004         if (node->getBody())
2005             node->getBody()->traverse(this);
2006         builder.createBranch(&blocks.continue_target);
2007         breakForLoop.pop();
2008
2009         builder.setBuildPoint(&blocks.continue_target);
2010         if (node->getTerminal())
2011             node->getTerminal()->traverse(this);
2012         builder.createBranch(&blocks.head);
2013     } else {
2014         builder.createBranch(&blocks.body);
2015
2016         breakForLoop.push(true);
2017         builder.setBuildPoint(&blocks.body);
2018         if (node->getBody())
2019             node->getBody()->traverse(this);
2020         builder.createBranch(&blocks.continue_target);
2021         breakForLoop.pop();
2022
2023         builder.setBuildPoint(&blocks.continue_target);
2024         if (node->getTerminal())
2025             node->getTerminal()->traverse(this);
2026         if (node->getTest()) {
2027             node->getTest()->traverse(this);
2028             spv::Id condition =
2029                 accessChainLoad(node->getTest()->getType());
2030             builder.createConditionalBranch(condition, &blocks.head, &blocks.merge);
2031         } else {
2032             // TODO: unless there was a break/return/discard instruction
2033             // somewhere in the body, this is an infinite loop, so we should
2034             // issue a warning.
2035             builder.createBranch(&blocks.head);
2036         }
2037     }
2038     builder.setBuildPoint(&blocks.merge);
2039     builder.closeLoop();
2040     return false;
2041 }
2042
2043 bool TGlslangToSpvTraverser::visitBranch(glslang::TVisit /* visit */, glslang::TIntermBranch* node)
2044 {
2045     if (node->getExpression())
2046         node->getExpression()->traverse(this);
2047
2048     switch (node->getFlowOp()) {
2049     case glslang::EOpKill:
2050         builder.makeDiscard();
2051         break;
2052     case glslang::EOpBreak:
2053         if (breakForLoop.top())
2054             builder.createLoopExit();
2055         else
2056             builder.addSwitchBreak();
2057         break;
2058     case glslang::EOpContinue:
2059         builder.createLoopContinue();
2060         break;
2061     case glslang::EOpReturn:
2062         if (node->getExpression()) {
2063             const glslang::TType& glslangReturnType = node->getExpression()->getType();
2064             spv::Id returnId = accessChainLoad(glslangReturnType);
2065             if (builder.getTypeId(returnId) != currentFunction->getReturnType()) {
2066                 builder.clearAccessChain();
2067                 spv::Id copyId = builder.createVariable(spv::StorageClassFunction, currentFunction->getReturnType());
2068                 builder.setAccessChainLValue(copyId);
2069                 multiTypeStore(glslangReturnType, returnId);
2070                 returnId = builder.createLoad(copyId);
2071             }
2072             builder.makeReturn(false, returnId);
2073         } else
2074             builder.makeReturn(false);
2075
2076         builder.clearAccessChain();
2077         break;
2078
2079     default:
2080         assert(0);
2081         break;
2082     }
2083
2084     return false;
2085 }
2086
2087 spv::Id TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol* node)
2088 {
2089     // First, steer off constants, which are not SPIR-V variables, but
2090     // can still have a mapping to a SPIR-V Id.
2091     // This includes specialization constants.
2092     if (node->getQualifier().isConstant()) {
2093         return createSpvConstant(*node);
2094     }
2095
2096     // Now, handle actual variables
2097     spv::StorageClass storageClass = TranslateStorageClass(node->getType());
2098     spv::Id spvType = convertGlslangToSpvType(node->getType());
2099
2100 #ifdef AMD_EXTENSIONS
2101     const bool contains16BitType = node->getType().containsBasicType(glslang::EbtFloat16);
2102     if (contains16BitType) {
2103         if (storageClass == spv::StorageClassInput || storageClass == spv::StorageClassOutput) {
2104             builder.addExtension(spv::E_SPV_KHR_16bit_storage);
2105             builder.addCapability(spv::CapabilityStorageInputOutput16);
2106         } else if (storageClass == spv::StorageClassPushConstant) {
2107             builder.addExtension(spv::E_SPV_KHR_16bit_storage);
2108             builder.addCapability(spv::CapabilityStoragePushConstant16);
2109         } else if (storageClass == spv::StorageClassUniform) {
2110             builder.addExtension(spv::E_SPV_KHR_16bit_storage);
2111             builder.addCapability(spv::CapabilityStorageUniform16);
2112             if (node->getType().getQualifier().storage == glslang::EvqBuffer)
2113                 builder.addCapability(spv::CapabilityStorageUniformBufferBlock16);
2114         }
2115     }
2116 #endif
2117
2118     const char* name = node->getName().c_str();
2119     if (glslang::IsAnonymous(name))
2120         name = "";
2121
2122     return builder.createVariable(storageClass, spvType, name);
2123 }
2124
2125 // Return type Id of the sampled type.
2126 spv::Id TGlslangToSpvTraverser::getSampledType(const glslang::TSampler& sampler)
2127 {
2128     switch (sampler.type) {
2129         case glslang::EbtFloat:    return builder.makeFloatType(32);
2130         case glslang::EbtInt:      return builder.makeIntType(32);
2131         case glslang::EbtUint:     return builder.makeUintType(32);
2132         default:
2133             assert(0);
2134             return builder.makeFloatType(32);
2135     }
2136 }
2137
2138 // If node is a swizzle operation, return the type that should be used if
2139 // the swizzle base is first consumed by another operation, before the swizzle
2140 // is applied.
2141 spv::Id TGlslangToSpvTraverser::getInvertedSwizzleType(const glslang::TIntermTyped& node)
2142 {
2143     if (node.getAsOperator() &&
2144         node.getAsOperator()->getOp() == glslang::EOpVectorSwizzle)
2145         return convertGlslangToSpvType(node.getAsBinaryNode()->getLeft()->getType());
2146     else
2147         return spv::NoType;
2148 }
2149
2150 // When inverting a swizzle with a parent op, this function
2151 // will apply the swizzle operation to a completed parent operation.
2152 spv::Id TGlslangToSpvTraverser::createInvertedSwizzle(spv::Decoration precision, const glslang::TIntermTyped& node, spv::Id parentResult)
2153 {
2154     std::vector<unsigned> swizzle;
2155     convertSwizzle(*node.getAsBinaryNode()->getRight()->getAsAggregate(), swizzle);
2156     return builder.createRvalueSwizzle(precision, convertGlslangToSpvType(node.getType()), parentResult, swizzle);
2157 }
2158
2159 // Convert a glslang AST swizzle node to a swizzle vector for building SPIR-V.
2160 void TGlslangToSpvTraverser::convertSwizzle(const glslang::TIntermAggregate& node, std::vector<unsigned>& swizzle)
2161 {
2162     const glslang::TIntermSequence& swizzleSequence = node.getSequence();
2163     for (int i = 0; i < (int)swizzleSequence.size(); ++i)
2164         swizzle.push_back(swizzleSequence[i]->getAsConstantUnion()->getConstArray()[0].getIConst());
2165 }
2166
2167 // Convert from a glslang type to an SPV type, by calling into a
2168 // recursive version of this function. This establishes the inherited
2169 // layout state rooted from the top-level type.
2170 spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& type)
2171 {
2172     return convertGlslangToSpvType(type, getExplicitLayout(type), type.getQualifier());
2173 }
2174
2175 // Do full recursive conversion of an arbitrary glslang type to a SPIR-V Id.
2176 // explicitLayout can be kept the same throughout the hierarchical recursive walk.
2177 // Mutually recursive with convertGlslangStructToSpvType().
2178 spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& type, glslang::TLayoutPacking explicitLayout, const glslang::TQualifier& qualifier)
2179 {
2180     spv::Id spvType = spv::NoResult;
2181
2182     switch (type.getBasicType()) {
2183     case glslang::EbtVoid:
2184         spvType = builder.makeVoidType();
2185         assert (! type.isArray());
2186         break;
2187     case glslang::EbtFloat:
2188         spvType = builder.makeFloatType(32);
2189         break;
2190     case glslang::EbtDouble:
2191         spvType = builder.makeFloatType(64);
2192         break;
2193 #ifdef AMD_EXTENSIONS
2194     case glslang::EbtFloat16:
2195         builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float);
2196         spvType = builder.makeFloatType(16);
2197         break;
2198 #endif
2199     case glslang::EbtBool:
2200         // "transparent" bool doesn't exist in SPIR-V.  The GLSL convention is
2201         // a 32-bit int where non-0 means true.
2202         if (explicitLayout != glslang::ElpNone)
2203             spvType = builder.makeUintType(32);
2204         else
2205             spvType = builder.makeBoolType();
2206         break;
2207     case glslang::EbtInt:
2208         spvType = builder.makeIntType(32);
2209         break;
2210     case glslang::EbtUint:
2211         spvType = builder.makeUintType(32);
2212         break;
2213     case glslang::EbtInt64:
2214         builder.addCapability(spv::CapabilityInt64);
2215         spvType = builder.makeIntType(64);
2216         break;
2217     case glslang::EbtUint64:
2218         builder.addCapability(spv::CapabilityInt64);
2219         spvType = builder.makeUintType(64);
2220         break;
2221     case glslang::EbtAtomicUint:
2222         builder.addCapability(spv::CapabilityAtomicStorage);
2223         spvType = builder.makeUintType(32);
2224         break;
2225     case glslang::EbtSampler:
2226         {
2227             const glslang::TSampler& sampler = type.getSampler();
2228             if (sampler.sampler) {
2229                 // pure sampler
2230                 spvType = builder.makeSamplerType();
2231             } else {
2232                 // an image is present, make its type
2233                 spvType = builder.makeImageType(getSampledType(sampler), TranslateDimensionality(sampler), sampler.shadow, sampler.arrayed, sampler.ms,
2234                                                 sampler.image ? 2 : 1, TranslateImageFormat(type));
2235                 if (sampler.combined) {
2236                     // already has both image and sampler, make the combined type
2237                     spvType = builder.makeSampledImageType(spvType);
2238                 }
2239             }
2240         }
2241         break;
2242     case glslang::EbtStruct:
2243     case glslang::EbtBlock:
2244         {
2245             // If we've seen this struct type, return it
2246             const glslang::TTypeList* glslangMembers = type.getStruct();
2247
2248             // Try to share structs for different layouts, but not yet for other
2249             // kinds of qualification (primarily not yet including interpolant qualification).
2250             if (! HasNonLayoutQualifiers(type, qualifier))
2251                 spvType = structMap[explicitLayout][qualifier.layoutMatrix][glslangMembers];
2252             if (spvType != spv::NoResult)
2253                 break;
2254
2255             // else, we haven't seen it...
2256             if (type.getBasicType() == glslang::EbtBlock)
2257                 memberRemapper[glslangMembers].resize(glslangMembers->size());
2258             spvType = convertGlslangStructToSpvType(type, glslangMembers, explicitLayout, qualifier);
2259         }
2260         break;
2261     default:
2262         assert(0);
2263         break;
2264     }
2265
2266     if (type.isMatrix())
2267         spvType = builder.makeMatrixType(spvType, type.getMatrixCols(), type.getMatrixRows());
2268     else {
2269         // If this variable has a vector element count greater than 1, create a SPIR-V vector
2270         if (type.getVectorSize() > 1)
2271             spvType = builder.makeVectorType(spvType, type.getVectorSize());
2272     }
2273
2274     if (type.isArray()) {
2275         int stride = 0;  // keep this 0 unless doing an explicit layout; 0 will mean no decoration, no stride
2276
2277         // Do all but the outer dimension
2278         if (type.getArraySizes()->getNumDims() > 1) {
2279             // We need to decorate array strides for types needing explicit layout, except blocks.
2280             if (explicitLayout != glslang::ElpNone && type.getBasicType() != glslang::EbtBlock) {
2281                 // Use a dummy glslang type for querying internal strides of
2282                 // arrays of arrays, but using just a one-dimensional array.
2283                 glslang::TType simpleArrayType(type, 0); // deference type of the array
2284                 while (simpleArrayType.getArraySizes().getNumDims() > 1)
2285                     simpleArrayType.getArraySizes().dereference();
2286
2287                 // Will compute the higher-order strides here, rather than making a whole
2288                 // pile of types and doing repetitive recursion on their contents.
2289                 stride = getArrayStride(simpleArrayType, explicitLayout, qualifier.layoutMatrix);
2290             }
2291
2292             // make the arrays
2293             for (int dim = type.getArraySizes()->getNumDims() - 1; dim > 0; --dim) {
2294                 spvType = builder.makeArrayType(spvType, makeArraySizeId(*type.getArraySizes(), dim), stride);
2295                 if (stride > 0)
2296                     builder.addDecoration(spvType, spv::DecorationArrayStride, stride);
2297                 stride *= type.getArraySizes()->getDimSize(dim);
2298             }
2299         } else {
2300             // single-dimensional array, and don't yet have stride
2301
2302             // We need to decorate array strides for types needing explicit layout, except blocks.
2303             if (explicitLayout != glslang::ElpNone && type.getBasicType() != glslang::EbtBlock)
2304                 stride = getArrayStride(type, explicitLayout, qualifier.layoutMatrix);
2305         }
2306
2307         // Do the outer dimension, which might not be known for a runtime-sized array
2308         if (type.isRuntimeSizedArray()) {
2309             spvType = builder.makeRuntimeArray(spvType);
2310         } else {
2311             assert(type.getOuterArraySize() > 0);
2312             spvType = builder.makeArrayType(spvType, makeArraySizeId(*type.getArraySizes(), 0), stride);
2313         }
2314         if (stride > 0)
2315             builder.addDecoration(spvType, spv::DecorationArrayStride, stride);
2316     }
2317
2318     return spvType;
2319 }
2320
2321 // TODO: this functionality should exist at a higher level, in creating the AST
2322 //
2323 // Identify interface members that don't have their required extension turned on.
2324 //
2325 bool TGlslangToSpvTraverser::filterMember(const glslang::TType& member)
2326 {
2327     auto& extensions = glslangIntermediate->getRequestedExtensions();
2328
2329     if (member.getFieldName() == "gl_ViewportMask" &&
2330         extensions.find("GL_NV_viewport_array2") == extensions.end())
2331         return true;
2332     if (member.getFieldName() == "gl_SecondaryViewportMaskNV" &&
2333         extensions.find("GL_NV_stereo_view_rendering") == extensions.end())
2334         return true;
2335     if (member.getFieldName() == "gl_SecondaryPositionNV" &&
2336         extensions.find("GL_NV_stereo_view_rendering") == extensions.end())
2337         return true;
2338     if (member.getFieldName() == "gl_PositionPerViewNV" &&
2339         extensions.find("GL_NVX_multiview_per_view_attributes") == extensions.end())
2340         return true;
2341     if (member.getFieldName() == "gl_ViewportMaskPerViewNV" &&
2342         extensions.find("GL_NVX_multiview_per_view_attributes") == extensions.end())
2343         return true;
2344
2345     return false;
2346 };
2347
2348 // Do full recursive conversion of a glslang structure (or block) type to a SPIR-V Id.
2349 // explicitLayout can be kept the same throughout the hierarchical recursive walk.
2350 // Mutually recursive with convertGlslangToSpvType().
2351 spv::Id TGlslangToSpvTraverser::convertGlslangStructToSpvType(const glslang::TType& type,
2352                                                               const glslang::TTypeList* glslangMembers,
2353                                                               glslang::TLayoutPacking explicitLayout,
2354                                                               const glslang::TQualifier& qualifier)
2355 {
2356     // Create a vector of struct types for SPIR-V to consume
2357     std::vector<spv::Id> spvMembers;
2358     int memberDelta = 0;  // how much the member's index changes from glslang to SPIR-V, normally 0, except sometimes for blocks
2359     int locationOffset = 0;  // for use across struct members, when they are called recursively
2360     for (int i = 0; i < (int)glslangMembers->size(); i++) {
2361         glslang::TType& glslangMember = *(*glslangMembers)[i].type;
2362         if (glslangMember.hiddenMember()) {
2363             ++memberDelta;
2364             if (type.getBasicType() == glslang::EbtBlock)
2365                 memberRemapper[glslangMembers][i] = -1;
2366         } else {
2367             if (type.getBasicType() == glslang::EbtBlock) {
2368                 memberRemapper[glslangMembers][i] = i - memberDelta;
2369                 if (filterMember(glslangMember))
2370                     continue;
2371             }
2372             // modify just this child's view of the qualifier
2373             glslang::TQualifier memberQualifier = glslangMember.getQualifier();
2374             InheritQualifiers(memberQualifier, qualifier);
2375
2376             // manually inherit location; it's more complex
2377             if (! memberQualifier.hasLocation() && qualifier.hasLocation())
2378                 memberQualifier.layoutLocation = qualifier.layoutLocation + locationOffset;
2379             if (qualifier.hasLocation())
2380                 locationOffset += glslangIntermediate->computeTypeLocationSize(glslangMember);
2381
2382             // recurse
2383             spvMembers.push_back(convertGlslangToSpvType(glslangMember, explicitLayout, memberQualifier));
2384         }
2385     }
2386
2387     // Make the SPIR-V type
2388     spv::Id spvType = builder.makeStructType(spvMembers, type.getTypeName().c_str());
2389     if (! HasNonLayoutQualifiers(type, qualifier))
2390         structMap[explicitLayout][qualifier.layoutMatrix][glslangMembers] = spvType;
2391
2392     // Decorate it
2393     decorateStructType(type, glslangMembers, explicitLayout, qualifier, spvType);
2394
2395     return spvType;
2396 }
2397
2398 void TGlslangToSpvTraverser::decorateStructType(const glslang::TType& type,
2399                                                 const glslang::TTypeList* glslangMembers,
2400                                                 glslang::TLayoutPacking explicitLayout,
2401                                                 const glslang::TQualifier& qualifier,
2402                                                 spv::Id spvType)
2403 {
2404     // Name and decorate the non-hidden members
2405     int offset = -1;
2406     int locationOffset = 0;  // for use within the members of this struct
2407     for (int i = 0; i < (int)glslangMembers->size(); i++) {
2408         glslang::TType& glslangMember = *(*glslangMembers)[i].type;
2409         int member = i;
2410         if (type.getBasicType() == glslang::EbtBlock) {
2411             member = memberRemapper[glslangMembers][i];
2412             if (filterMember(glslangMember))
2413                 continue;
2414         }
2415
2416         // modify just this child's view of the qualifier
2417         glslang::TQualifier memberQualifier = glslangMember.getQualifier();
2418         InheritQualifiers(memberQualifier, qualifier);
2419
2420         // using -1 above to indicate a hidden member
2421         if (member >= 0) {
2422             builder.addMemberName(spvType, member, glslangMember.getFieldName().c_str());
2423             addMemberDecoration(spvType, member, TranslateLayoutDecoration(glslangMember, memberQualifier.layoutMatrix));
2424             addMemberDecoration(spvType, member, TranslatePrecisionDecoration(glslangMember));
2425             // Add interpolation and auxiliary storage decorations only to top-level members of Input and Output storage classes
2426             if (type.getQualifier().storage == glslang::EvqVaryingIn ||
2427                 type.getQualifier().storage == glslang::EvqVaryingOut) {
2428                 if (type.getBasicType() == glslang::EbtBlock ||
2429                     glslangIntermediate->getSource() == glslang::EShSourceHlsl) {
2430                     addMemberDecoration(spvType, member, TranslateInterpolationDecoration(memberQualifier));
2431                     addMemberDecoration(spvType, member, TranslateAuxiliaryStorageDecoration(memberQualifier));
2432                 }
2433             }
2434             addMemberDecoration(spvType, member, TranslateInvariantDecoration(memberQualifier));
2435
2436             if (qualifier.storage == glslang::EvqBuffer) {
2437                 std::vector<spv::Decoration> memory;
2438                 TranslateMemoryDecoration(memberQualifier, memory);
2439                 for (unsigned int i = 0; i < memory.size(); ++i)
2440                     addMemberDecoration(spvType, member, memory[i]);
2441             }
2442
2443             // Compute location decoration; tricky based on whether inheritance is at play and
2444             // what kind of container we have, etc.
2445             // TODO: This algorithm (and it's cousin above doing almost the same thing) should
2446             //       probably move to the linker stage of the front end proper, and just have the
2447             //       answer sitting already distributed throughout the individual member locations.
2448             int location = -1;                // will only decorate if present or inherited
2449             // Ignore member locations if the container is an array, as that's
2450             // ill-specified and decisions have been made to not allow this anyway.
2451             // The object itself must have a location, and that comes out from decorating the object,
2452             // not the type (this code decorates types).
2453             if (! type.isArray()) {
2454                 if (memberQualifier.hasLocation()) { // no inheritance, or override of inheritance
2455                     // struct members should not have explicit locations
2456                     assert(type.getBasicType() != glslang::EbtStruct);
2457                     location = memberQualifier.layoutLocation;
2458                 } else if (type.getBasicType() != glslang::EbtBlock) {
2459                     // If it is a not a Block, (...) Its members are assigned consecutive locations (...)
2460                     // The members, and their nested types, must not themselves have Location decorations.
2461                 } else if (qualifier.hasLocation()) // inheritance
2462                     location = qualifier.layoutLocation + locationOffset;
2463             }
2464             if (location >= 0)
2465                 builder.addMemberDecoration(spvType, member, spv::DecorationLocation, location);
2466
2467             if (qualifier.hasLocation())      // track for upcoming inheritance
2468                 locationOffset += glslangIntermediate->computeTypeLocationSize(glslangMember);
2469
2470             // component, XFB, others
2471             if (glslangMember.getQualifier().hasComponent())
2472                 builder.addMemberDecoration(spvType, member, spv::DecorationComponent, glslangMember.getQualifier().layoutComponent);
2473             if (glslangMember.getQualifier().hasXfbOffset())
2474                 builder.addMemberDecoration(spvType, member, spv::DecorationOffset, glslangMember.getQualifier().layoutXfbOffset);
2475             else if (explicitLayout != glslang::ElpNone) {
2476                 // figure out what to do with offset, which is accumulating
2477                 int nextOffset;
2478                 updateMemberOffset(type, glslangMember, offset, nextOffset, explicitLayout, memberQualifier.layoutMatrix);
2479                 if (offset >= 0)
2480                     builder.addMemberDecoration(spvType, member, spv::DecorationOffset, offset);
2481                 offset = nextOffset;
2482             }
2483
2484             if (glslangMember.isMatrix() && explicitLayout != glslang::ElpNone)
2485                 builder.addMemberDecoration(spvType, member, spv::DecorationMatrixStride, getMatrixStride(glslangMember, explicitLayout, memberQualifier.layoutMatrix));
2486
2487             // built-in variable decorations
2488             spv::BuiltIn builtIn = TranslateBuiltInDecoration(glslangMember.getQualifier().builtIn, true);
2489             if (builtIn != spv::BuiltInMax)
2490                 addMemberDecoration(spvType, member, spv::DecorationBuiltIn, (int)builtIn);
2491
2492 #ifdef NV_EXTENSIONS
2493             if (builtIn == spv::BuiltInLayer) {
2494                 // SPV_NV_viewport_array2 extension
2495                 if (glslangMember.getQualifier().layoutViewportRelative){
2496                     addMemberDecoration(spvType, member, (spv::Decoration)spv::DecorationViewportRelativeNV);
2497                     builder.addCapability(spv::CapabilityShaderViewportMaskNV);
2498                     builder.addExtension(spv::E_SPV_NV_viewport_array2);
2499                 }
2500                 if (glslangMember.getQualifier().layoutSecondaryViewportRelativeOffset != -2048){
2501                     addMemberDecoration(spvType, member, (spv::Decoration)spv::DecorationSecondaryViewportRelativeNV, glslangMember.getQualifier().layoutSecondaryViewportRelativeOffset);
2502                     builder.addCapability(spv::CapabilityShaderStereoViewNV);
2503                     builder.addExtension(spv::E_SPV_NV_stereo_view_rendering);
2504                 }
2505             }
2506             if (glslangMember.getQualifier().layoutPassthrough) {
2507                 addMemberDecoration(spvType, member, (spv::Decoration)spv::DecorationPassthroughNV);
2508                 builder.addCapability(spv::CapabilityGeometryShaderPassthroughNV);
2509                 builder.addExtension(spv::E_SPV_NV_geometry_shader_passthrough);
2510             }
2511 #endif
2512         }
2513     }
2514
2515     // Decorate the structure
2516     addDecoration(spvType, TranslateLayoutDecoration(type, qualifier.layoutMatrix));
2517     addDecoration(spvType, TranslateBlockDecoration(type, glslangIntermediate->usingStorageBuffer()));
2518     if (type.getQualifier().hasStream() && glslangIntermediate->isMultiStream()) {
2519         builder.addCapability(spv::CapabilityGeometryStreams);
2520         builder.addDecoration(spvType, spv::DecorationStream, type.getQualifier().layoutStream);
2521     }
2522     if (glslangIntermediate->getXfbMode()) {
2523         builder.addCapability(spv::CapabilityTransformFeedback);
2524         if (type.getQualifier().hasXfbStride())
2525             builder.addDecoration(spvType, spv::DecorationXfbStride, type.getQualifier().layoutXfbStride);
2526         if (type.getQualifier().hasXfbBuffer())
2527             builder.addDecoration(spvType, spv::DecorationXfbBuffer, type.getQualifier().layoutXfbBuffer);
2528     }
2529 }
2530
2531 // Turn the expression forming the array size into an id.
2532 // This is not quite trivial, because of specialization constants.
2533 // Sometimes, a raw constant is turned into an Id, and sometimes
2534 // a specialization constant expression is.
2535 spv::Id TGlslangToSpvTraverser::makeArraySizeId(const glslang::TArraySizes& arraySizes, int dim)
2536 {
2537     // First, see if this is sized with a node, meaning a specialization constant:
2538     glslang::TIntermTyped* specNode = arraySizes.getDimNode(dim);
2539     if (specNode != nullptr) {
2540         builder.clearAccessChain();
2541         specNode->traverse(this);
2542         return accessChainLoad(specNode->getAsTyped()->getType());
2543     }
2544
2545     // Otherwise, need a compile-time (front end) size, get it:
2546     int size = arraySizes.getDimSize(dim);
2547     assert(size > 0);
2548     return builder.makeUintConstant(size);
2549 }
2550
2551 // Wrap the builder's accessChainLoad to:
2552 //  - localize handling of RelaxedPrecision
2553 //  - use the SPIR-V inferred type instead of another conversion of the glslang type
2554 //    (avoids unnecessary work and possible type punning for structures)
2555 //  - do conversion of concrete to abstract type
2556 spv::Id TGlslangToSpvTraverser::accessChainLoad(const glslang::TType& type)
2557 {
2558     spv::Id nominalTypeId = builder.accessChainGetInferredType();
2559     spv::Id loadedId = builder.accessChainLoad(TranslatePrecisionDecoration(type), nominalTypeId);
2560
2561     // Need to convert to abstract types when necessary
2562     if (type.getBasicType() == glslang::EbtBool) {
2563         if (builder.isScalarType(nominalTypeId)) {
2564             // Conversion for bool
2565             spv::Id boolType = builder.makeBoolType();
2566             if (nominalTypeId != boolType)
2567                 loadedId = builder.createBinOp(spv::OpINotEqual, boolType, loadedId, builder.makeUintConstant(0));
2568         } else if (builder.isVectorType(nominalTypeId)) {
2569             // Conversion for bvec
2570             int vecSize = builder.getNumTypeComponents(nominalTypeId);
2571             spv::Id bvecType = builder.makeVectorType(builder.makeBoolType(), vecSize);
2572             if (nominalTypeId != bvecType)
2573                 loadedId = builder.createBinOp(spv::OpINotEqual, bvecType, loadedId, makeSmearedConstant(builder.makeUintConstant(0), vecSize));
2574         }
2575     }
2576
2577     return loadedId;
2578 }
2579
2580 // Wrap the builder's accessChainStore to:
2581 //  - do conversion of concrete to abstract type
2582 //
2583 // Implicitly uses the existing builder.accessChain as the storage target.
2584 void TGlslangToSpvTraverser::accessChainStore(const glslang::TType& type, spv::Id rvalue)
2585 {
2586     // Need to convert to abstract types when necessary
2587     if (type.getBasicType() == glslang::EbtBool) {
2588         spv::Id nominalTypeId = builder.accessChainGetInferredType();
2589
2590         if (builder.isScalarType(nominalTypeId)) {
2591             // Conversion for bool
2592             spv::Id boolType = builder.makeBoolType();
2593             if (nominalTypeId != boolType) {
2594                 spv::Id zero = builder.makeUintConstant(0);
2595                 spv::Id one  = builder.makeUintConstant(1);
2596                 rvalue = builder.createTriOp(spv::OpSelect, nominalTypeId, rvalue, one, zero);
2597             }
2598         } else if (builder.isVectorType(nominalTypeId)) {
2599             // Conversion for bvec
2600             int vecSize = builder.getNumTypeComponents(nominalTypeId);
2601             spv::Id bvecType = builder.makeVectorType(builder.makeBoolType(), vecSize);
2602             if (nominalTypeId != bvecType) {
2603                 spv::Id zero = makeSmearedConstant(builder.makeUintConstant(0), vecSize);
2604                 spv::Id one  = makeSmearedConstant(builder.makeUintConstant(1), vecSize);
2605                 rvalue = builder.createTriOp(spv::OpSelect, nominalTypeId, rvalue, one, zero);
2606             }
2607         }
2608     }
2609
2610     builder.accessChainStore(rvalue);
2611 }
2612
2613 // For storing when types match at the glslang level, but not might match at the
2614 // SPIR-V level.
2615 //
2616 // This especially happens when a single glslang type expands to multiple
2617 // SPIR-V types, like a struct that is used in a member-undecorated way as well
2618 // as in a member-decorated way.
2619 //
2620 // NOTE: This function can handle any store request; if it's not special it
2621 // simplifies to a simple OpStore.
2622 //
2623 // Implicitly uses the existing builder.accessChain as the storage target.
2624 void TGlslangToSpvTraverser::multiTypeStore(const glslang::TType& type, spv::Id rValue)
2625 {
2626     // we only do the complex path here if it's an aggregate
2627     if (! type.isStruct() && ! type.isArray()) {
2628         accessChainStore(type, rValue);
2629         return;
2630     }
2631
2632     // and, it has to be a case of type aliasing
2633     spv::Id rType = builder.getTypeId(rValue);
2634     spv::Id lValue = builder.accessChainGetLValue();
2635     spv::Id lType = builder.getContainedTypeId(builder.getTypeId(lValue));
2636     if (lType == rType) {
2637         accessChainStore(type, rValue);
2638         return;
2639     }
2640
2641     // Recursively (as needed) copy an aggregate type to a different aggregate type,
2642     // where the two types were the same type in GLSL. This requires member
2643     // by member copy, recursively.
2644
2645     // If an array, copy element by element.
2646     if (type.isArray()) {
2647         glslang::TType glslangElementType(type, 0);
2648         spv::Id elementRType = builder.getContainedTypeId(rType);
2649         for (int index = 0; index < type.getOuterArraySize(); ++index) {
2650             // get the source member
2651             spv::Id elementRValue = builder.createCompositeExtract(rValue, elementRType, index);
2652
2653             // set up the target storage
2654             builder.clearAccessChain();
2655             builder.setAccessChainLValue(lValue);
2656             builder.accessChainPush(builder.makeIntConstant(index));
2657
2658             // store the member
2659             multiTypeStore(glslangElementType, elementRValue);
2660         }
2661     } else {
2662         assert(type.isStruct());
2663
2664         // loop over structure members
2665         const glslang::TTypeList& members = *type.getStruct();
2666         for (int m = 0; m < (int)members.size(); ++m) {
2667             const glslang::TType& glslangMemberType = *members[m].type;
2668
2669             // get the source member
2670             spv::Id memberRType = builder.getContainedTypeId(rType, m);
2671             spv::Id memberRValue = builder.createCompositeExtract(rValue, memberRType, m);
2672
2673             // set up the target storage
2674             builder.clearAccessChain();
2675             builder.setAccessChainLValue(lValue);
2676             builder.accessChainPush(builder.makeIntConstant(m));
2677
2678             // store the member
2679             multiTypeStore(glslangMemberType, memberRValue);
2680         }
2681     }
2682 }
2683
2684 // Decide whether or not this type should be
2685 // decorated with offsets and strides, and if so
2686 // whether std140 or std430 rules should be applied.
2687 glslang::TLayoutPacking TGlslangToSpvTraverser::getExplicitLayout(const glslang::TType& type) const
2688 {
2689     // has to be a block
2690     if (type.getBasicType() != glslang::EbtBlock)
2691         return glslang::ElpNone;
2692
2693     // has to be a uniform or buffer block
2694     if (type.getQualifier().storage != glslang::EvqUniform &&
2695         type.getQualifier().storage != glslang::EvqBuffer)
2696         return glslang::ElpNone;
2697
2698     // return the layout to use
2699     switch (type.getQualifier().layoutPacking) {
2700     case glslang::ElpStd140:
2701     case glslang::ElpStd430:
2702         return type.getQualifier().layoutPacking;
2703     default:
2704         return glslang::ElpNone;
2705     }
2706 }
2707
2708 // Given an array type, returns the integer stride required for that array
2709 int TGlslangToSpvTraverser::getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout)
2710 {
2711     int size;
2712     int stride;
2713     glslangIntermediate->getBaseAlignment(arrayType, size, stride, explicitLayout == glslang::ElpStd140, matrixLayout == glslang::ElmRowMajor);
2714
2715     return stride;
2716 }
2717
2718 // Given a matrix type, or array (of array) of matrixes type, returns the integer stride required for that matrix
2719 // when used as a member of an interface block
2720 int TGlslangToSpvTraverser::getMatrixStride(const glslang::TType& matrixType, glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout)
2721 {
2722     glslang::TType elementType;
2723     elementType.shallowCopy(matrixType);
2724     elementType.clearArraySizes();
2725
2726     int size;
2727     int stride;
2728     glslangIntermediate->getBaseAlignment(elementType, size, stride, explicitLayout == glslang::ElpStd140, matrixLayout == glslang::ElmRowMajor);
2729
2730     return stride;
2731 }
2732
2733 // Given a member type of a struct, realign the current offset for it, and compute
2734 // the next (not yet aligned) offset for the next member, which will get aligned
2735 // on the next call.
2736 // 'currentOffset' should be passed in already initialized, ready to modify, and reflecting
2737 // the migration of data from nextOffset -> currentOffset.  It should be -1 on the first call.
2738 // -1 means a non-forced member offset (no decoration needed).
2739 void TGlslangToSpvTraverser::updateMemberOffset(const glslang::TType& /*structType*/, const glslang::TType& memberType, int& currentOffset, int& nextOffset,
2740                                                 glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout)
2741 {
2742     // this will get a positive value when deemed necessary
2743     nextOffset = -1;
2744
2745     // override anything in currentOffset with user-set offset
2746     if (memberType.getQualifier().hasOffset())
2747         currentOffset = memberType.getQualifier().layoutOffset;
2748
2749     // It could be that current linker usage in glslang updated all the layoutOffset,
2750     // in which case the following code does not matter.  But, that's not quite right
2751     // once cross-compilation unit GLSL validation is done, as the original user
2752     // settings are needed in layoutOffset, and then the following will come into play.
2753
2754     if (explicitLayout == glslang::ElpNone) {
2755         if (! memberType.getQualifier().hasOffset())
2756             currentOffset = -1;
2757
2758         return;
2759     }
2760
2761     // Getting this far means we need explicit offsets
2762     if (currentOffset < 0)
2763         currentOffset = 0;
2764
2765     // Now, currentOffset is valid (either 0, or from a previous nextOffset),
2766     // but possibly not yet correctly aligned.
2767
2768     int memberSize;
2769     int dummyStride;
2770     int memberAlignment = glslangIntermediate->getBaseAlignment(memberType, memberSize, dummyStride, explicitLayout == glslang::ElpStd140, matrixLayout == glslang::ElmRowMajor);
2771
2772     // Adjust alignment for HLSL rules
2773     if (glslangIntermediate->usingHlslOFfsets() &&
2774         ! memberType.isArray() && memberType.isVector()) {
2775         int dummySize;
2776         int componentAlignment = glslangIntermediate->getBaseAlignmentScalar(memberType, dummySize);
2777         if (componentAlignment <= 4)
2778             memberAlignment = componentAlignment;
2779     }
2780
2781     // Bump up to member alignment
2782     glslang::RoundToPow2(currentOffset, memberAlignment);
2783
2784     // Bump up to vec4 if there is a bad straddle
2785     if (glslangIntermediate->improperStraddle(memberType, memberSize, currentOffset))
2786         glslang::RoundToPow2(currentOffset, 16);
2787
2788     nextOffset = currentOffset + memberSize;
2789 }
2790
2791 void TGlslangToSpvTraverser::declareUseOfStructMember(const glslang::TTypeList& members, int glslangMember)
2792 {
2793     const glslang::TBuiltInVariable glslangBuiltIn = members[glslangMember].type->getQualifier().builtIn;
2794     switch (glslangBuiltIn)
2795     {
2796     case glslang::EbvClipDistance:
2797     case glslang::EbvCullDistance:
2798     case glslang::EbvPointSize:
2799 #ifdef NV_EXTENSIONS
2800     case glslang::EbvLayer:
2801     case glslang::EbvViewportIndex:
2802     case glslang::EbvViewportMaskNV:
2803     case glslang::EbvSecondaryPositionNV:
2804     case glslang::EbvSecondaryViewportMaskNV:
2805     case glslang::EbvPositionPerViewNV:
2806     case glslang::EbvViewportMaskPerViewNV:
2807 #endif
2808         // Generate the associated capability.  Delegate to TranslateBuiltInDecoration.
2809         // Alternately, we could just call this for any glslang built-in, since the
2810         // capability already guards against duplicates.
2811         TranslateBuiltInDecoration(glslangBuiltIn, false);
2812         break;
2813     default:
2814         // Capabilities were already generated when the struct was declared.
2815         break;
2816     }
2817 }
2818
2819 bool TGlslangToSpvTraverser::isShaderEntryPoint(const glslang::TIntermAggregate* node)
2820 {
2821     return node->getName().compare(glslangIntermediate->getEntryPointMangledName().c_str()) == 0;
2822 }
2823
2824 // Make all the functions, skeletally, without actually visiting their bodies.
2825 void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslFunctions)
2826 {
2827     for (int f = 0; f < (int)glslFunctions.size(); ++f) {
2828         glslang::TIntermAggregate* glslFunction = glslFunctions[f]->getAsAggregate();
2829         if (! glslFunction || glslFunction->getOp() != glslang::EOpFunction || isShaderEntryPoint(glslFunction))
2830             continue;
2831
2832         // We're on a user function.  Set up the basic interface for the function now,
2833         // so that it's available to call.  Translating the body will happen later.
2834         //
2835         // Typically (except for a "const in" parameter), an address will be passed to the
2836         // function.  What it is an address of varies:
2837         //
2838         // - "in" parameters not marked as "const" can be written to without modifying the calling
2839         //   argument so that write needs to be to a copy, hence the address of a copy works.
2840         //
2841         // - "const in" parameters can just be the r-value, as no writes need occur.
2842         //
2843         // - "out" and "inout" arguments can't be done as pointers to the calling argument, because
2844         //   GLSL has copy-in/copy-out semantics.  They can be handled though with a pointer to a copy.
2845
2846         std::vector<spv::Id> paramTypes;
2847         std::vector<spv::Decoration> paramPrecisions;
2848         glslang::TIntermSequence& parameters = glslFunction->getSequence()[0]->getAsAggregate()->getSequence();
2849
2850         bool implicitThis = (int)parameters.size() > 0 && parameters[0]->getAsSymbolNode()->getName() == glslangIntermediate->implicitThisName;
2851
2852         for (int p = 0; p < (int)parameters.size(); ++p) {
2853             const glslang::TType& paramType = parameters[p]->getAsTyped()->getType();
2854             spv::Id typeId = convertGlslangToSpvType(paramType);
2855             // can we pass by reference?
2856             if (paramType.containsOpaque() ||                                // sampler, etc.
2857                 (paramType.getBasicType() == glslang::EbtBlock &&
2858                  paramType.getQualifier().storage == glslang::EvqBuffer) ||  // SSBO
2859                 (p == 0 && implicitThis))                                    // implicit 'this'
2860                 typeId = builder.makePointer(TranslateStorageClass(paramType), typeId);
2861             else if (paramType.getQualifier().storage != glslang::EvqConstReadOnly)
2862                 typeId = builder.makePointer(spv::StorageClassFunction, typeId);
2863             else
2864                 rValueParameters.insert(parameters[p]->getAsSymbolNode()->getId());
2865             paramPrecisions.push_back(TranslatePrecisionDecoration(paramType));
2866             paramTypes.push_back(typeId);
2867         }
2868
2869         spv::Block* functionBlock;
2870         spv::Function *function = builder.makeFunctionEntry(TranslatePrecisionDecoration(glslFunction->getType()),
2871                                                             convertGlslangToSpvType(glslFunction->getType()),
2872                                                             glslFunction->getName().c_str(), paramTypes, paramPrecisions, &functionBlock);
2873         if (implicitThis)
2874             function->setImplicitThis();
2875
2876         // Track function to emit/call later
2877         functionMap[glslFunction->getName().c_str()] = function;
2878
2879         // Set the parameter id's
2880         for (int p = 0; p < (int)parameters.size(); ++p) {
2881             symbolValues[parameters[p]->getAsSymbolNode()->getId()] = function->getParamId(p);
2882             // give a name too
2883             builder.addName(function->getParamId(p), parameters[p]->getAsSymbolNode()->getName().c_str());
2884         }
2885     }
2886 }
2887
2888 // Process all the initializers, while skipping the functions and link objects
2889 void TGlslangToSpvTraverser::makeGlobalInitializers(const glslang::TIntermSequence& initializers)
2890 {
2891     builder.setBuildPoint(shaderEntry->getLastBlock());
2892     for (int i = 0; i < (int)initializers.size(); ++i) {
2893         glslang::TIntermAggregate* initializer = initializers[i]->getAsAggregate();
2894         if (initializer && initializer->getOp() != glslang::EOpFunction && initializer->getOp() != glslang::EOpLinkerObjects) {
2895
2896             // We're on a top-level node that's not a function.  Treat as an initializer, whose
2897             // code goes into the beginning of the entry point.
2898             initializer->traverse(this);
2899         }
2900     }
2901 }
2902
2903 // Process all the functions, while skipping initializers.
2904 void TGlslangToSpvTraverser::visitFunctions(const glslang::TIntermSequence& glslFunctions)
2905 {
2906     for (int f = 0; f < (int)glslFunctions.size(); ++f) {
2907         glslang::TIntermAggregate* node = glslFunctions[f]->getAsAggregate();
2908         if (node && (node->getOp() == glslang::EOpFunction || node->getOp() == glslang::EOpLinkerObjects))
2909             node->traverse(this);
2910     }
2911 }
2912
2913 void TGlslangToSpvTraverser::handleFunctionEntry(const glslang::TIntermAggregate* node)
2914 {
2915     // SPIR-V functions should already be in the functionMap from the prepass
2916     // that called makeFunctions().
2917     currentFunction = functionMap[node->getName().c_str()];
2918     spv::Block* functionBlock = currentFunction->getEntryBlock();
2919     builder.setBuildPoint(functionBlock);
2920 }
2921
2922 void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate& node, std::vector<spv::Id>& arguments)
2923 {
2924     const glslang::TIntermSequence& glslangArguments = node.getSequence();
2925
2926     glslang::TSampler sampler = {};
2927     bool cubeCompare = false;
2928     if (node.isTexture() || node.isImage()) {
2929         sampler = glslangArguments[0]->getAsTyped()->getType().getSampler();
2930         cubeCompare = sampler.dim == glslang::EsdCube && sampler.arrayed && sampler.shadow;
2931     }
2932
2933     for (int i = 0; i < (int)glslangArguments.size(); ++i) {
2934         builder.clearAccessChain();
2935         glslangArguments[i]->traverse(this);
2936
2937         // Special case l-value operands
2938         bool lvalue = false;
2939         switch (node.getOp()) {
2940         case glslang::EOpImageAtomicAdd:
2941         case glslang::EOpImageAtomicMin:
2942         case glslang::EOpImageAtomicMax:
2943         case glslang::EOpImageAtomicAnd:
2944         case glslang::EOpImageAtomicOr:
2945         case glslang::EOpImageAtomicXor:
2946         case glslang::EOpImageAtomicExchange:
2947         case glslang::EOpImageAtomicCompSwap:
2948             if (i == 0)
2949                 lvalue = true;
2950             break;
2951         case glslang::EOpSparseImageLoad:
2952             if ((sampler.ms && i == 3) || (! sampler.ms && i == 2))
2953                 lvalue = true;
2954             break;
2955         case glslang::EOpSparseTexture:
2956             if ((cubeCompare && i == 3) || (! cubeCompare && i == 2))
2957                 lvalue = true;
2958             break;
2959         case glslang::EOpSparseTextureClamp:
2960             if ((cubeCompare && i == 4) || (! cubeCompare && i == 3))
2961                 lvalue = true;
2962             break;
2963         case glslang::EOpSparseTextureLod:
2964         case glslang::EOpSparseTextureOffset:
2965             if (i == 3)
2966                 lvalue = true;
2967             break;
2968         case glslang::EOpSparseTextureFetch:
2969             if ((sampler.dim != glslang::EsdRect && i == 3) || (sampler.dim == glslang::EsdRect && i == 2))
2970                 lvalue = true;
2971             break;
2972         case glslang::EOpSparseTextureFetchOffset:
2973             if ((sampler.dim != glslang::EsdRect && i == 4) || (sampler.dim == glslang::EsdRect && i == 3))
2974                 lvalue = true;
2975             break;
2976         case glslang::EOpSparseTextureLodOffset:
2977         case glslang::EOpSparseTextureGrad:
2978         case glslang::EOpSparseTextureOffsetClamp:
2979             if (i == 4)
2980                 lvalue = true;
2981             break;
2982         case glslang::EOpSparseTextureGradOffset:
2983         case glslang::EOpSparseTextureGradClamp:
2984             if (i == 5)
2985                 lvalue = true;
2986             break;
2987         case glslang::EOpSparseTextureGradOffsetClamp:
2988             if (i == 6)
2989                 lvalue = true;
2990             break;
2991          case glslang::EOpSparseTextureGather:
2992             if ((sampler.shadow && i == 3) || (! sampler.shadow && i == 2))
2993                 lvalue = true;
2994             break;
2995         case glslang::EOpSparseTextureGatherOffset:
2996         case glslang::EOpSparseTextureGatherOffsets:
2997             if ((sampler.shadow && i == 4) || (! sampler.shadow && i == 3))
2998                 lvalue = true;
2999             break;
3000         default:
3001             break;
3002         }
3003
3004         if (lvalue)
3005             arguments.push_back(builder.accessChainGetLValue());
3006         else
3007             arguments.push_back(accessChainLoad(glslangArguments[i]->getAsTyped()->getType()));
3008     }
3009 }
3010
3011 void TGlslangToSpvTraverser::translateArguments(glslang::TIntermUnary& node, std::vector<spv::Id>& arguments)
3012 {
3013     builder.clearAccessChain();
3014     node.getOperand()->traverse(this);
3015     arguments.push_back(accessChainLoad(node.getOperand()->getType()));
3016 }
3017
3018 spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermOperator* node)
3019 {
3020     if (! node->isImage() && ! node->isTexture()) {
3021         return spv::NoResult;
3022     }
3023     auto resultType = [&node,this]{ return convertGlslangToSpvType(node->getType()); };
3024
3025     // Process a GLSL texturing op (will be SPV image)
3026     const glslang::TSampler sampler = node->getAsAggregate() ? node->getAsAggregate()->getSequence()[0]->getAsTyped()->getType().getSampler()
3027                                                              : node->getAsUnaryNode()->getOperand()->getAsTyped()->getType().getSampler();
3028     std::vector<spv::Id> arguments;
3029     if (node->getAsAggregate())
3030         translateArguments(*node->getAsAggregate(), arguments);
3031     else
3032         translateArguments(*node->getAsUnaryNode(), arguments);
3033     spv::Decoration precision = TranslatePrecisionDecoration(node->getOperationPrecision());
3034
3035     spv::Builder::TextureParameters params = { };
3036     params.sampler = arguments[0];
3037
3038     glslang::TCrackedTextureOp cracked;
3039     node->crackTexture(sampler, cracked);
3040
3041     const bool isUnsignedResult =
3042         node->getType().getBasicType() == glslang::EbtUint64 ||
3043         node->getType().getBasicType() == glslang::EbtUint;
3044
3045     // Check for queries
3046     if (cracked.query) {
3047         // OpImageQueryLod works on a sampled image, for other queries the image has to be extracted first
3048         if (node->getOp() != glslang::EOpTextureQueryLod && builder.isSampledImage(params.sampler))
3049             params.sampler = builder.createUnaryOp(spv::OpImage, builder.getImageType(params.sampler), params.sampler);
3050
3051         switch (node->getOp()) {
3052         case glslang::EOpImageQuerySize:
3053         case glslang::EOpTextureQuerySize:
3054             if (arguments.size() > 1) {
3055                 params.lod = arguments[1];
3056                 return builder.createTextureQueryCall(spv::OpImageQuerySizeLod, params, isUnsignedResult);
3057             } else
3058                 return builder.createTextureQueryCall(spv::OpImageQuerySize, params, isUnsignedResult);
3059         case glslang::EOpImageQuerySamples:
3060         case glslang::EOpTextureQuerySamples:
3061             return builder.createTextureQueryCall(spv::OpImageQuerySamples, params, isUnsignedResult);
3062         case glslang::EOpTextureQueryLod:
3063             params.coords = arguments[1];
3064             return builder.createTextureQueryCall(spv::OpImageQueryLod, params, isUnsignedResult);
3065         case glslang::EOpTextureQueryLevels:
3066             return builder.createTextureQueryCall(spv::OpImageQueryLevels, params, isUnsignedResult);
3067         case glslang::EOpSparseTexelsResident:
3068             return builder.createUnaryOp(spv::OpImageSparseTexelsResident, builder.makeBoolType(), arguments[0]);
3069         default:
3070             assert(0);
3071             break;
3072         }
3073     }
3074
3075     // Check for image functions other than queries
3076     if (node->isImage()) {
3077         std::vector<spv::Id> operands;
3078         auto opIt = arguments.begin();
3079         operands.push_back(*(opIt++));
3080
3081         // Handle subpass operations
3082         // TODO: GLSL should change to have the "MS" only on the type rather than the
3083         // built-in function.
3084         if (cracked.subpass) {
3085             // add on the (0,0) coordinate
3086             spv::Id zero = builder.makeIntConstant(0);
3087             std::vector<spv::Id> comps;
3088             comps.push_back(zero);
3089             comps.push_back(zero);
3090             operands.push_back(builder.makeCompositeConstant(builder.makeVectorType(builder.makeIntType(32), 2), comps));
3091             if (sampler.ms) {
3092                 operands.push_back(spv::ImageOperandsSampleMask);
3093                 operands.push_back(*(opIt++));
3094             }
3095             return builder.createOp(spv::OpImageRead, resultType(), operands);
3096         }
3097
3098         operands.push_back(*(opIt++));
3099         if (node->getOp() == glslang::EOpImageLoad) {
3100             if (sampler.ms) {
3101                 operands.push_back(spv::ImageOperandsSampleMask);
3102                 operands.push_back(*opIt);
3103             }
3104             if (builder.getImageTypeFormat(builder.getImageType(operands.front())) == spv::ImageFormatUnknown)
3105                 builder.addCapability(spv::CapabilityStorageImageReadWithoutFormat);
3106             return builder.createOp(spv::OpImageRead, resultType(), operands);
3107         } else if (node->getOp() == glslang::EOpImageStore) {
3108             if (sampler.ms) {
3109                 operands.push_back(*(opIt + 1));
3110                 operands.push_back(spv::ImageOperandsSampleMask);
3111                 operands.push_back(*opIt);
3112             } else
3113                 operands.push_back(*opIt);
3114             builder.createNoResultOp(spv::OpImageWrite, operands);
3115             if (builder.getImageTypeFormat(builder.getImageType(operands.front())) == spv::ImageFormatUnknown)
3116                 builder.addCapability(spv::CapabilityStorageImageWriteWithoutFormat);
3117             return spv::NoResult;
3118         } else if (node->getOp() == glslang::EOpSparseImageLoad) {
3119             builder.addCapability(spv::CapabilitySparseResidency);
3120             if (builder.getImageTypeFormat(builder.getImageType(operands.front())) == spv::ImageFormatUnknown)
3121                 builder.addCapability(spv::CapabilityStorageImageReadWithoutFormat);
3122
3123             if (sampler.ms) {
3124                 operands.push_back(spv::ImageOperandsSampleMask);
3125                 operands.push_back(*opIt++);
3126             }
3127
3128             // Create the return type that was a special structure
3129             spv::Id texelOut = *opIt;
3130             spv::Id typeId0 = resultType();
3131             spv::Id typeId1 = builder.getDerefTypeId(texelOut);
3132             spv::Id resultTypeId = builder.makeStructResultType(typeId0, typeId1);
3133
3134             spv::Id resultId = builder.createOp(spv::OpImageSparseRead, resultTypeId, operands);
3135
3136             // Decode the return type
3137             builder.createStore(builder.createCompositeExtract(resultId, typeId1, 1), texelOut);
3138             return builder.createCompositeExtract(resultId, typeId0, 0);
3139         } else {
3140             // Process image atomic operations
3141
3142             // GLSL "IMAGE_PARAMS" will involve in constructing an image texel pointer and this pointer,
3143             // as the first source operand, is required by SPIR-V atomic operations.
3144             operands.push_back(sampler.ms ? *(opIt++) : builder.makeUintConstant(0)); // For non-MS, the value should be 0
3145
3146             spv::Id resultTypeId = builder.makePointer(spv::StorageClassImage, resultType());
3147             spv::Id pointer = builder.createOp(spv::OpImageTexelPointer, resultTypeId, operands);
3148
3149             std::vector<spv::Id> operands;
3150             operands.push_back(pointer);
3151             for (; opIt != arguments.end(); ++opIt)
3152                 operands.push_back(*opIt);
3153
3154             return createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType());
3155         }
3156     }
3157
3158     // Check for texture functions other than queries
3159     bool sparse = node->isSparseTexture();
3160     bool cubeCompare = sampler.dim == glslang::EsdCube && sampler.arrayed && sampler.shadow;
3161
3162     // check for bias argument
3163     bool bias = false;
3164     if (! cracked.lod && ! cracked.gather && ! cracked.grad && ! cracked.fetch && ! cubeCompare) {
3165         int nonBiasArgCount = 2;
3166         if (cracked.offset)
3167             ++nonBiasArgCount;
3168         if (cracked.grad)
3169             nonBiasArgCount += 2;
3170         if (cracked.lodClamp)
3171             ++nonBiasArgCount;
3172         if (sparse)
3173             ++nonBiasArgCount;
3174
3175         if ((int)arguments.size() > nonBiasArgCount)
3176             bias = true;
3177     }
3178
3179     // See if the sampler param should really be just the SPV image part
3180     if (cracked.fetch) {
3181         // a fetch needs to have the image extracted first
3182         if (builder.isSampledImage(params.sampler))
3183             params.sampler = builder.createUnaryOp(spv::OpImage, builder.getImageType(params.sampler), params.sampler);
3184     }
3185
3186     // set the rest of the arguments
3187
3188     params.coords = arguments[1];
3189     int extraArgs = 0;
3190     bool noImplicitLod = false;
3191
3192     // sort out where Dref is coming from
3193     if (cubeCompare) {
3194         params.Dref = arguments[2];
3195         ++extraArgs;
3196     } else if (sampler.shadow && cracked.gather) {
3197         params.Dref = arguments[2];
3198         ++extraArgs;
3199     } else if (sampler.shadow) {
3200         std::vector<spv::Id> indexes;
3201         int dRefComp;
3202         if (cracked.proj)
3203             dRefComp = 2;  // "The resulting 3rd component of P in the shadow forms is used as Dref"
3204         else
3205             dRefComp = builder.getNumComponents(params.coords) - 1;
3206         indexes.push_back(dRefComp);
3207         params.Dref = builder.createCompositeExtract(params.coords, builder.getScalarTypeId(builder.getTypeId(params.coords)), indexes);
3208     }
3209
3210     // lod
3211     if (cracked.lod) {
3212         params.lod = arguments[2];
3213         ++extraArgs;
3214     } else if (glslangIntermediate->getStage() != EShLangFragment) {
3215         // we need to invent the default lod for an explicit lod instruction for a non-fragment stage
3216         noImplicitLod = true;
3217     }
3218
3219     // multisample
3220     if (sampler.ms) {
3221         params.sample = arguments[2]; // For MS, "sample" should be specified
3222         ++extraArgs;
3223     }
3224
3225     // gradient
3226     if (cracked.grad) {
3227         params.gradX = arguments[2 + extraArgs];
3228         params.gradY = arguments[3 + extraArgs];
3229         extraArgs += 2;
3230     }
3231
3232     // offset and offsets
3233     if (cracked.offset) {
3234         params.offset = arguments[2 + extraArgs];
3235         ++extraArgs;
3236     } else if (cracked.offsets) {
3237         params.offsets = arguments[2 + extraArgs];
3238         ++extraArgs;
3239     }
3240
3241     // lod clamp
3242     if (cracked.lodClamp) {
3243         params.lodClamp = arguments[2 + extraArgs];
3244         ++extraArgs;
3245     }
3246
3247     // sparse
3248     if (sparse) {
3249         params.texelOut = arguments[2 + extraArgs];
3250         ++extraArgs;
3251     }
3252
3253     // bias
3254     if (bias) {
3255         params.bias = arguments[2 + extraArgs];
3256         ++extraArgs;
3257     }
3258
3259     // gather component
3260     if (cracked.gather && ! sampler.shadow) {
3261         // default component is 0, if missing, otherwise an argument
3262         if (2 + extraArgs < (int)arguments.size()) {
3263             params.component = arguments[2 + extraArgs];
3264             ++extraArgs;
3265         } else {
3266             params.component = builder.makeIntConstant(0);
3267         }
3268     }
3269
3270     // projective component (might not to move)
3271     // GLSL: "The texture coordinates consumed from P, not including the last component of P,
3272     //       are divided by the last component of P."
3273     // SPIR-V:  "... (u [, v] [, w], q)... It may be a vector larger than needed, but all
3274     //          unused components will appear after all used components."
3275     if (cracked.proj) {
3276         int projSourceComp = builder.getNumComponents(params.coords) - 1;
3277         int projTargetComp;
3278         switch (sampler.dim) {
3279         case glslang::Esd1D:   projTargetComp = 1;              break;
3280         case glslang::Esd2D:   projTargetComp = 2;              break;
3281         case glslang::EsdRect: projTargetComp = 2;              break;
3282         default:               projTargetComp = projSourceComp; break;
3283         }
3284         // copy the projective coordinate if we have to
3285         if (projTargetComp != projSourceComp) {
3286             spv::Id projComp = builder.createCompositeExtract(params.coords,
3287                                                               builder.getScalarTypeId(builder.getTypeId(params.coords)),
3288                                                               projSourceComp);
3289             params.coords = builder.createCompositeInsert(projComp, params.coords,
3290                                                           builder.getTypeId(params.coords), projTargetComp);
3291         }
3292     }
3293
3294     return builder.createTextureCall(precision, resultType(), sparse, cracked.fetch, cracked.proj, cracked.gather, noImplicitLod, params);
3295 }
3296
3297 spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAggregate* node)
3298 {
3299     // Grab the function's pointer from the previously created function
3300     spv::Function* function = functionMap[node->getName().c_str()];
3301     if (! function)
3302         return 0;
3303
3304     const glslang::TIntermSequence& glslangArgs = node->getSequence();
3305     const glslang::TQualifierList& qualifiers = node->getQualifierList();
3306
3307     //  See comments in makeFunctions() for details about the semantics for parameter passing.
3308     //
3309     // These imply we need a four step process:
3310     // 1. Evaluate the arguments
3311     // 2. Allocate and make copies of in, out, and inout arguments
3312     // 3. Make the call
3313     // 4. Copy back the results
3314
3315     // 1. Evaluate the arguments
3316     std::vector<spv::Builder::AccessChain> lValues;
3317     std::vector<spv::Id> rValues;
3318     std::vector<const glslang::TType*> argTypes;
3319     for (int a = 0; a < (int)glslangArgs.size(); ++a) {
3320         const glslang::TType& paramType = glslangArgs[a]->getAsTyped()->getType();
3321         // build l-value
3322         builder.clearAccessChain();
3323         glslangArgs[a]->traverse(this);
3324         argTypes.push_back(&paramType);
3325         // keep outputs and opaque objects as l-values, evaluate input-only as r-values
3326         if (qualifiers[a] != glslang::EvqConstReadOnly || paramType.containsOpaque()) {
3327             // save l-value
3328             lValues.push_back(builder.getAccessChain());
3329         } else {
3330             // process r-value
3331             rValues.push_back(accessChainLoad(*argTypes.back()));
3332         }
3333     }
3334
3335     // 2. Allocate space for anything needing a copy, and if it's "in" or "inout"
3336     // copy the original into that space.
3337     //
3338     // Also, build up the list of actual arguments to pass in for the call
3339     int lValueCount = 0;
3340     int rValueCount = 0;
3341     std::vector<spv::Id> spvArgs;
3342     for (int a = 0; a < (int)glslangArgs.size(); ++a) {
3343         const glslang::TType& paramType = glslangArgs[a]->getAsTyped()->getType();
3344         spv::Id arg;
3345         if (paramType.containsOpaque() ||
3346             (paramType.getBasicType() == glslang::EbtBlock && qualifiers[a] == glslang::EvqBuffer) ||
3347             (a == 0 && function->hasImplicitThis())) {
3348             builder.setAccessChain(lValues[lValueCount]);
3349             arg = builder.accessChainGetLValue();
3350             ++lValueCount;
3351         } else if (qualifiers[a] != glslang::EvqConstReadOnly) {
3352             // need space to hold the copy
3353             arg = builder.createVariable(spv::StorageClassFunction, convertGlslangToSpvType(paramType), "param");
3354             if (qualifiers[a] == glslang::EvqIn || qualifiers[a] == glslang::EvqInOut) {
3355                 // need to copy the input into output space
3356                 builder.setAccessChain(lValues[lValueCount]);
3357                 spv::Id copy = accessChainLoad(*argTypes[a]);
3358                 builder.clearAccessChain();
3359                 builder.setAccessChainLValue(arg);
3360                 multiTypeStore(paramType, copy);
3361             }
3362             ++lValueCount;
3363         } else {
3364             arg = rValues[rValueCount];
3365             ++rValueCount;
3366         }
3367         spvArgs.push_back(arg);
3368     }
3369
3370     // 3. Make the call.
3371     spv::Id result = builder.createFunctionCall(function, spvArgs);
3372     builder.setPrecision(result, TranslatePrecisionDecoration(node->getType()));
3373
3374     // 4. Copy back out an "out" arguments.
3375     lValueCount = 0;
3376     for (int a = 0; a < (int)glslangArgs.size(); ++a) {
3377         const glslang::TType& paramType = glslangArgs[a]->getAsTyped()->getType();
3378         if (qualifiers[a] != glslang::EvqConstReadOnly) {
3379             if (qualifiers[a] == glslang::EvqOut || qualifiers[a] == glslang::EvqInOut) {
3380                 spv::Id copy = builder.createLoad(spvArgs[a]);
3381                 builder.setAccessChain(lValues[lValueCount]);
3382                 multiTypeStore(paramType, copy);
3383             }
3384             ++lValueCount;
3385         }
3386     }
3387
3388     return result;
3389 }
3390
3391 // Translate AST operation to SPV operation, already having SPV-based operands/types.
3392 spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, spv::Decoration precision,
3393                                                       spv::Decoration noContraction,
3394                                                       spv::Id typeId, spv::Id left, spv::Id right,
3395                                                       glslang::TBasicType typeProxy, bool reduceComparison)
3396 {
3397     bool isUnsigned = typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64;
3398 #ifdef AMD_EXTENSIONS
3399     bool isFloat = typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble || typeProxy == glslang::EbtFloat16;
3400 #else
3401     bool isFloat = typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble;
3402 #endif
3403     bool isBool = typeProxy == glslang::EbtBool;
3404
3405     spv::Op binOp = spv::OpNop;
3406     bool needMatchingVectors = true;  // for non-matrix ops, would a scalar need to smear to match a vector?
3407     bool comparison = false;
3408
3409     switch (op) {
3410     case glslang::EOpAdd:
3411     case glslang::EOpAddAssign:
3412         if (isFloat)
3413             binOp = spv::OpFAdd;
3414         else
3415             binOp = spv::OpIAdd;
3416         break;
3417     case glslang::EOpSub:
3418     case glslang::EOpSubAssign:
3419         if (isFloat)
3420             binOp = spv::OpFSub;
3421         else
3422             binOp = spv::OpISub;
3423         break;
3424     case glslang::EOpMul:
3425     case glslang::EOpMulAssign:
3426         if (isFloat)
3427             binOp = spv::OpFMul;
3428         else
3429             binOp = spv::OpIMul;
3430         break;
3431     case glslang::EOpVectorTimesScalar:
3432     case glslang::EOpVectorTimesScalarAssign:
3433         if (isFloat && (builder.isVector(left) || builder.isVector(right))) {
3434             if (builder.isVector(right))
3435                 std::swap(left, right);
3436             assert(builder.isScalar(right));
3437             needMatchingVectors = false;
3438             binOp = spv::OpVectorTimesScalar;
3439         } else
3440             binOp = spv::OpIMul;
3441         break;
3442     case glslang::EOpVectorTimesMatrix:
3443     case glslang::EOpVectorTimesMatrixAssign:
3444         binOp = spv::OpVectorTimesMatrix;
3445         break;
3446     case glslang::EOpMatrixTimesVector:
3447         binOp = spv::OpMatrixTimesVector;
3448         break;
3449     case glslang::EOpMatrixTimesScalar:
3450     case glslang::EOpMatrixTimesScalarAssign:
3451         binOp = spv::OpMatrixTimesScalar;
3452         break;
3453     case glslang::EOpMatrixTimesMatrix:
3454     case glslang::EOpMatrixTimesMatrixAssign:
3455         binOp = spv::OpMatrixTimesMatrix;
3456         break;
3457     case glslang::EOpOuterProduct:
3458         binOp = spv::OpOuterProduct;
3459         needMatchingVectors = false;
3460         break;
3461
3462     case glslang::EOpDiv:
3463     case glslang::EOpDivAssign:
3464         if (isFloat)
3465             binOp = spv::OpFDiv;
3466         else if (isUnsigned)
3467             binOp = spv::OpUDiv;
3468         else
3469             binOp = spv::OpSDiv;
3470         break;
3471     case glslang::EOpMod:
3472     case glslang::EOpModAssign:
3473         if (isFloat)
3474             binOp = spv::OpFMod;
3475         else if (isUnsigned)
3476             binOp = spv::OpUMod;
3477         else
3478             binOp = spv::OpSMod;
3479         break;
3480     case glslang::EOpRightShift:
3481     case glslang::EOpRightShiftAssign:
3482         if (isUnsigned)
3483             binOp = spv::OpShiftRightLogical;
3484         else
3485             binOp = spv::OpShiftRightArithmetic;
3486         break;
3487     case glslang::EOpLeftShift:
3488     case glslang::EOpLeftShiftAssign:
3489         binOp = spv::OpShiftLeftLogical;
3490         break;
3491     case glslang::EOpAnd:
3492     case glslang::EOpAndAssign:
3493         binOp = spv::OpBitwiseAnd;
3494         break;
3495     case glslang::EOpLogicalAnd:
3496         needMatchingVectors = false;
3497         binOp = spv::OpLogicalAnd;
3498         break;
3499     case glslang::EOpInclusiveOr:
3500     case glslang::EOpInclusiveOrAssign:
3501         binOp = spv::OpBitwiseOr;
3502         break;
3503     case glslang::EOpLogicalOr:
3504         needMatchingVectors = false;
3505         binOp = spv::OpLogicalOr;
3506         break;
3507     case glslang::EOpExclusiveOr:
3508     case glslang::EOpExclusiveOrAssign:
3509         binOp = spv::OpBitwiseXor;
3510         break;
3511     case glslang::EOpLogicalXor:
3512         needMatchingVectors = false;
3513         binOp = spv::OpLogicalNotEqual;
3514         break;
3515
3516     case glslang::EOpLessThan:
3517     case glslang::EOpGreaterThan:
3518     case glslang::EOpLessThanEqual:
3519     case glslang::EOpGreaterThanEqual:
3520     case glslang::EOpEqual:
3521     case glslang::EOpNotEqual:
3522     case glslang::EOpVectorEqual:
3523     case glslang::EOpVectorNotEqual:
3524         comparison = true;
3525         break;
3526     default:
3527         break;
3528     }
3529
3530     // handle mapped binary operations (should be non-comparison)
3531     if (binOp != spv::OpNop) {
3532         assert(comparison == false);
3533         if (builder.isMatrix(left) || builder.isMatrix(right))
3534             return createBinaryMatrixOperation(binOp, precision, noContraction, typeId, left, right);
3535
3536         // No matrix involved; make both operands be the same number of components, if needed
3537         if (needMatchingVectors)
3538             builder.promoteScalar(precision, left, right);
3539
3540         spv::Id result = builder.createBinOp(binOp, typeId, left, right);
3541         addDecoration(result, noContraction);
3542         return builder.setPrecision(result, precision);
3543     }
3544
3545     if (! comparison)
3546         return 0;
3547
3548     // Handle comparison instructions
3549
3550     if (reduceComparison && (op == glslang::EOpEqual || op == glslang::EOpNotEqual)
3551                          && (builder.isVector(left) || builder.isMatrix(left) || builder.isAggregate(left)))
3552         return builder.createCompositeCompare(precision, left, right, op == glslang::EOpEqual);
3553
3554     switch (op) {
3555     case glslang::EOpLessThan:
3556         if (isFloat)
3557             binOp = spv::OpFOrdLessThan;
3558         else if (isUnsigned)
3559             binOp = spv::OpULessThan;
3560         else
3561             binOp = spv::OpSLessThan;
3562         break;
3563     case glslang::EOpGreaterThan:
3564         if (isFloat)
3565             binOp = spv::OpFOrdGreaterThan;
3566         else if (isUnsigned)
3567             binOp = spv::OpUGreaterThan;
3568         else
3569             binOp = spv::OpSGreaterThan;
3570         break;
3571     case glslang::EOpLessThanEqual:
3572         if (isFloat)
3573             binOp = spv::OpFOrdLessThanEqual;
3574         else if (isUnsigned)
3575             binOp = spv::OpULessThanEqual;
3576         else
3577             binOp = spv::OpSLessThanEqual;
3578         break;
3579     case glslang::EOpGreaterThanEqual:
3580         if (isFloat)
3581             binOp = spv::OpFOrdGreaterThanEqual;
3582         else if (isUnsigned)
3583             binOp = spv::OpUGreaterThanEqual;
3584         else
3585             binOp = spv::OpSGreaterThanEqual;
3586         break;
3587     case glslang::EOpEqual:
3588     case glslang::EOpVectorEqual:
3589         if (isFloat)
3590             binOp = spv::OpFOrdEqual;
3591         else if (isBool)
3592             binOp = spv::OpLogicalEqual;
3593         else
3594             binOp = spv::OpIEqual;
3595         break;
3596     case glslang::EOpNotEqual:
3597     case glslang::EOpVectorNotEqual:
3598         if (isFloat)
3599             binOp = spv::OpFOrdNotEqual;
3600         else if (isBool)
3601             binOp = spv::OpLogicalNotEqual;
3602         else
3603             binOp = spv::OpINotEqual;
3604         break;
3605     default:
3606         break;
3607     }
3608
3609     if (binOp != spv::OpNop) {
3610         spv::Id result = builder.createBinOp(binOp, typeId, left, right);
3611         addDecoration(result, noContraction);
3612         return builder.setPrecision(result, precision);
3613     }
3614
3615     return 0;
3616 }
3617
3618 //
3619 // Translate AST matrix operation to SPV operation, already having SPV-based operands/types.
3620 // These can be any of:
3621 //
3622 //   matrix * scalar
3623 //   scalar * matrix
3624 //   matrix * matrix     linear algebraic
3625 //   matrix * vector
3626 //   vector * matrix
3627 //   matrix * matrix     componentwise
3628 //   matrix op matrix    op in {+, -, /}
3629 //   matrix op scalar    op in {+, -, /}
3630 //   scalar op matrix    op in {+, -, /}
3631 //
3632 spv::Id TGlslangToSpvTraverser::createBinaryMatrixOperation(spv::Op op, spv::Decoration precision, spv::Decoration noContraction, spv::Id typeId, spv::Id left, spv::Id right)
3633 {
3634     bool firstClass = true;
3635
3636     // First, handle first-class matrix operations (* and matrix/scalar)
3637     switch (op) {
3638     case spv::OpFDiv:
3639         if (builder.isMatrix(left) && builder.isScalar(right)) {
3640             // turn matrix / scalar into a multiply...
3641             right = builder.createBinOp(spv::OpFDiv, builder.getTypeId(right), builder.makeFloatConstant(1.0F), right);
3642             op = spv::OpMatrixTimesScalar;
3643         } else
3644             firstClass = false;
3645         break;
3646     case spv::OpMatrixTimesScalar:
3647         if (builder.isMatrix(right))
3648             std::swap(left, right);
3649         assert(builder.isScalar(right));
3650         break;
3651     case spv::OpVectorTimesMatrix:
3652         assert(builder.isVector(left));
3653         assert(builder.isMatrix(right));
3654         break;
3655     case spv::OpMatrixTimesVector:
3656         assert(builder.isMatrix(left));
3657         assert(builder.isVector(right));
3658         break;
3659     case spv::OpMatrixTimesMatrix:
3660         assert(builder.isMatrix(left));
3661         assert(builder.isMatrix(right));
3662         break;
3663     default:
3664         firstClass = false;
3665         break;
3666     }
3667
3668     if (firstClass) {
3669         spv::Id result = builder.createBinOp(op, typeId, left, right);
3670         addDecoration(result, noContraction);
3671         return builder.setPrecision(result, precision);
3672     }
3673
3674     // Handle component-wise +, -, *, %, and / for all combinations of type.
3675     // The result type of all of them is the same type as the (a) matrix operand.
3676     // The algorithm is to:
3677     //   - break the matrix(es) into vectors
3678     //   - smear any scalar to a vector
3679     //   - do vector operations
3680     //   - make a matrix out the vector results
3681     switch (op) {
3682     case spv::OpFAdd:
3683     case spv::OpFSub:
3684     case spv::OpFDiv:
3685     case spv::OpFMod:
3686     case spv::OpFMul:
3687     {
3688         // one time set up...
3689         bool  leftMat = builder.isMatrix(left);
3690         bool rightMat = builder.isMatrix(right);
3691         unsigned int numCols = leftMat ? builder.getNumColumns(left) : builder.getNumColumns(right);
3692         int numRows = leftMat ? builder.getNumRows(left) : builder.getNumRows(right);
3693         spv::Id scalarType = builder.getScalarTypeId(typeId);
3694         spv::Id vecType = builder.makeVectorType(scalarType, numRows);
3695         std::vector<spv::Id> results;
3696         spv::Id smearVec = spv::NoResult;
3697         if (builder.isScalar(left))
3698             smearVec = builder.smearScalar(precision, left, vecType);
3699         else if (builder.isScalar(right))
3700             smearVec = builder.smearScalar(precision, right, vecType);
3701
3702         // do each vector op
3703         for (unsigned int c = 0; c < numCols; ++c) {
3704             std::vector<unsigned int> indexes;
3705             indexes.push_back(c);
3706             spv::Id  leftVec =  leftMat ? builder.createCompositeExtract( left, vecType, indexes) : smearVec;
3707             spv::Id rightVec = rightMat ? builder.createCompositeExtract(right, vecType, indexes) : smearVec;
3708             spv::Id result = builder.createBinOp(op, vecType, leftVec, rightVec);
3709             addDecoration(result, noContraction);
3710             results.push_back(builder.setPrecision(result, precision));
3711         }
3712
3713         // put the pieces together
3714         return  builder.setPrecision(builder.createCompositeConstruct(typeId, results), precision);
3715     }
3716     default:
3717         assert(0);
3718         return spv::NoResult;
3719     }
3720 }
3721
3722 spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, spv::Decoration precision, spv::Decoration noContraction, spv::Id typeId, spv::Id operand, glslang::TBasicType typeProxy)
3723 {
3724     spv::Op unaryOp = spv::OpNop;
3725     int extBuiltins = -1;
3726     int libCall = -1;
3727     bool isUnsigned = typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64;
3728 #ifdef AMD_EXTENSIONS
3729     bool isFloat = typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble || typeProxy == glslang::EbtFloat16;
3730 #else
3731     bool isFloat = typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble;
3732 #endif
3733
3734     switch (op) {
3735     case glslang::EOpNegative:
3736         if (isFloat) {
3737             unaryOp = spv::OpFNegate;
3738             if (builder.isMatrixType(typeId))
3739                 return createUnaryMatrixOperation(unaryOp, precision, noContraction, typeId, operand, typeProxy);
3740         } else
3741             unaryOp = spv::OpSNegate;
3742         break;
3743
3744     case glslang::EOpLogicalNot:
3745     case glslang::EOpVectorLogicalNot:
3746         unaryOp = spv::OpLogicalNot;
3747         break;
3748     case glslang::EOpBitwiseNot:
3749         unaryOp = spv::OpNot;
3750         break;
3751
3752     case glslang::EOpDeterminant:
3753         libCall = spv::GLSLstd450Determinant;
3754         break;
3755     case glslang::EOpMatrixInverse:
3756         libCall = spv::GLSLstd450MatrixInverse;
3757         break;
3758     case glslang::EOpTranspose:
3759         unaryOp = spv::OpTranspose;
3760         break;
3761
3762     case glslang::EOpRadians:
3763         libCall = spv::GLSLstd450Radians;
3764         break;
3765     case glslang::EOpDegrees:
3766         libCall = spv::GLSLstd450Degrees;
3767         break;
3768     case glslang::EOpSin:
3769         libCall = spv::GLSLstd450Sin;
3770         break;
3771     case glslang::EOpCos:
3772         libCall = spv::GLSLstd450Cos;
3773         break;
3774     case glslang::EOpTan:
3775         libCall = spv::GLSLstd450Tan;
3776         break;
3777     case glslang::EOpAcos:
3778         libCall = spv::GLSLstd450Acos;
3779         break;
3780     case glslang::EOpAsin:
3781         libCall = spv::GLSLstd450Asin;
3782         break;
3783     case glslang::EOpAtan:
3784         libCall = spv::GLSLstd450Atan;
3785         break;
3786
3787     case glslang::EOpAcosh:
3788         libCall = spv::GLSLstd450Acosh;
3789         break;
3790     case glslang::EOpAsinh:
3791         libCall = spv::GLSLstd450Asinh;
3792         break;
3793     case glslang::EOpAtanh:
3794         libCall = spv::GLSLstd450Atanh;
3795         break;
3796     case glslang::EOpTanh:
3797         libCall = spv::GLSLstd450Tanh;
3798         break;
3799     case glslang::EOpCosh:
3800         libCall = spv::GLSLstd450Cosh;
3801         break;
3802     case glslang::EOpSinh:
3803         libCall = spv::GLSLstd450Sinh;
3804         break;
3805
3806     case glslang::EOpLength:
3807         libCall = spv::GLSLstd450Length;
3808         break;
3809     case glslang::EOpNormalize:
3810         libCall = spv::GLSLstd450Normalize;
3811         break;
3812
3813     case glslang::EOpExp:
3814         libCall = spv::GLSLstd450Exp;
3815         break;
3816     case glslang::EOpLog:
3817         libCall = spv::GLSLstd450Log;
3818         break;
3819     case glslang::EOpExp2:
3820         libCall = spv::GLSLstd450Exp2;
3821         break;
3822     case glslang::EOpLog2:
3823         libCall = spv::GLSLstd450Log2;
3824         break;
3825     case glslang::EOpSqrt:
3826         libCall = spv::GLSLstd450Sqrt;
3827         break;
3828     case glslang::EOpInverseSqrt:
3829         libCall = spv::GLSLstd450InverseSqrt;
3830         break;
3831
3832     case glslang::EOpFloor:
3833         libCall = spv::GLSLstd450Floor;
3834         break;
3835     case glslang::EOpTrunc:
3836         libCall = spv::GLSLstd450Trunc;
3837         break;
3838     case glslang::EOpRound:
3839         libCall = spv::GLSLstd450Round;
3840         break;
3841     case glslang::EOpRoundEven:
3842         libCall = spv::GLSLstd450RoundEven;
3843         break;
3844     case glslang::EOpCeil:
3845         libCall = spv::GLSLstd450Ceil;
3846         break;
3847     case glslang::EOpFract:
3848         libCall = spv::GLSLstd450Fract;
3849         break;
3850
3851     case glslang::EOpIsNan:
3852         unaryOp = spv::OpIsNan;
3853         break;
3854     case glslang::EOpIsInf:
3855         unaryOp = spv::OpIsInf;
3856         break;
3857     case glslang::EOpIsFinite:
3858         unaryOp = spv::OpIsFinite;
3859         break;
3860
3861     case glslang::EOpFloatBitsToInt:
3862     case glslang::EOpFloatBitsToUint:
3863     case glslang::EOpIntBitsToFloat:
3864     case glslang::EOpUintBitsToFloat:
3865     case glslang::EOpDoubleBitsToInt64:
3866     case glslang::EOpDoubleBitsToUint64:
3867     case glslang::EOpInt64BitsToDouble:
3868     case glslang::EOpUint64BitsToDouble:
3869         unaryOp = spv::OpBitcast;
3870         break;
3871
3872     case glslang::EOpPackSnorm2x16:
3873         libCall = spv::GLSLstd450PackSnorm2x16;
3874         break;
3875     case glslang::EOpUnpackSnorm2x16:
3876         libCall = spv::GLSLstd450UnpackSnorm2x16;
3877         break;
3878     case glslang::EOpPackUnorm2x16:
3879         libCall = spv::GLSLstd450PackUnorm2x16;
3880         break;
3881     case glslang::EOpUnpackUnorm2x16:
3882         libCall = spv::GLSLstd450UnpackUnorm2x16;
3883         break;
3884     case glslang::EOpPackHalf2x16:
3885         libCall = spv::GLSLstd450PackHalf2x16;
3886         break;
3887     case glslang::EOpUnpackHalf2x16:
3888         libCall = spv::GLSLstd450UnpackHalf2x16;
3889         break;
3890     case glslang::EOpPackSnorm4x8:
3891         libCall = spv::GLSLstd450PackSnorm4x8;
3892         break;
3893     case glslang::EOpUnpackSnorm4x8:
3894         libCall = spv::GLSLstd450UnpackSnorm4x8;
3895         break;
3896     case glslang::EOpPackUnorm4x8:
3897         libCall = spv::GLSLstd450PackUnorm4x8;
3898         break;
3899     case glslang::EOpUnpackUnorm4x8:
3900         libCall = spv::GLSLstd450UnpackUnorm4x8;
3901         break;
3902     case glslang::EOpPackDouble2x32:
3903         libCall = spv::GLSLstd450PackDouble2x32;
3904         break;
3905     case glslang::EOpUnpackDouble2x32:
3906         libCall = spv::GLSLstd450UnpackDouble2x32;
3907         break;
3908
3909     case glslang::EOpPackInt2x32:
3910     case glslang::EOpUnpackInt2x32:
3911     case glslang::EOpPackUint2x32:
3912     case glslang::EOpUnpackUint2x32:
3913         unaryOp = spv::OpBitcast;
3914         break;
3915
3916 #ifdef AMD_EXTENSIONS
3917     case glslang::EOpPackFloat2x16:
3918     case glslang::EOpUnpackFloat2x16:
3919         unaryOp = spv::OpBitcast;
3920         break;
3921 #endif
3922
3923     case glslang::EOpDPdx:
3924         unaryOp = spv::OpDPdx;
3925         break;
3926     case glslang::EOpDPdy:
3927         unaryOp = spv::OpDPdy;
3928         break;
3929     case glslang::EOpFwidth:
3930         unaryOp = spv::OpFwidth;
3931         break;
3932     case glslang::EOpDPdxFine:
3933         builder.addCapability(spv::CapabilityDerivativeControl);
3934         unaryOp = spv::OpDPdxFine;
3935         break;
3936     case glslang::EOpDPdyFine:
3937         builder.addCapability(spv::CapabilityDerivativeControl);
3938         unaryOp = spv::OpDPdyFine;
3939         break;
3940     case glslang::EOpFwidthFine:
3941         builder.addCapability(spv::CapabilityDerivativeControl);
3942         unaryOp = spv::OpFwidthFine;
3943         break;
3944     case glslang::EOpDPdxCoarse:
3945         builder.addCapability(spv::CapabilityDerivativeControl);
3946         unaryOp = spv::OpDPdxCoarse;
3947         break;
3948     case glslang::EOpDPdyCoarse:
3949         builder.addCapability(spv::CapabilityDerivativeControl);
3950         unaryOp = spv::OpDPdyCoarse;
3951         break;
3952     case glslang::EOpFwidthCoarse:
3953         builder.addCapability(spv::CapabilityDerivativeControl);
3954         unaryOp = spv::OpFwidthCoarse;
3955         break;
3956     case glslang::EOpInterpolateAtCentroid:
3957         builder.addCapability(spv::CapabilityInterpolationFunction);
3958         libCall = spv::GLSLstd450InterpolateAtCentroid;
3959         break;
3960     case glslang::EOpAny:
3961         unaryOp = spv::OpAny;
3962         break;
3963     case glslang::EOpAll:
3964         unaryOp = spv::OpAll;
3965         break;
3966
3967     case glslang::EOpAbs:
3968         if (isFloat)
3969             libCall = spv::GLSLstd450FAbs;
3970         else
3971             libCall = spv::GLSLstd450SAbs;
3972         break;
3973     case glslang::EOpSign:
3974         if (isFloat)
3975             libCall = spv::GLSLstd450FSign;
3976         else
3977             libCall = spv::GLSLstd450SSign;
3978         break;
3979
3980     case glslang::EOpAtomicCounterIncrement:
3981     case glslang::EOpAtomicCounterDecrement:
3982     case glslang::EOpAtomicCounter:
3983     {
3984         // Handle all of the atomics in one place, in createAtomicOperation()
3985         std::vector<spv::Id> operands;
3986         operands.push_back(operand);
3987         return createAtomicOperation(op, precision, typeId, operands, typeProxy);
3988     }
3989
3990     case glslang::EOpBitFieldReverse:
3991         unaryOp = spv::OpBitReverse;
3992         break;
3993     case glslang::EOpBitCount:
3994         unaryOp = spv::OpBitCount;
3995         break;
3996     case glslang::EOpFindLSB:
3997         libCall = spv::GLSLstd450FindILsb;
3998         break;
3999     case glslang::EOpFindMSB:
4000         if (isUnsigned)
4001             libCall = spv::GLSLstd450FindUMsb;
4002         else
4003             libCall = spv::GLSLstd450FindSMsb;
4004         break;
4005
4006     case glslang::EOpBallot:
4007     case glslang::EOpReadFirstInvocation:
4008     case glslang::EOpAnyInvocation:
4009     case glslang::EOpAllInvocations:
4010     case glslang::EOpAllInvocationsEqual:
4011 #ifdef AMD_EXTENSIONS
4012     case glslang::EOpMinInvocations:
4013     case glslang::EOpMaxInvocations:
4014     case glslang::EOpAddInvocations:
4015     case glslang::EOpMinInvocationsNonUniform:
4016     case glslang::EOpMaxInvocationsNonUniform:
4017     case glslang::EOpAddInvocationsNonUniform:
4018     case glslang::EOpMinInvocationsInclusiveScan:
4019     case glslang::EOpMaxInvocationsInclusiveScan:
4020     case glslang::EOpAddInvocationsInclusiveScan:
4021     case glslang::EOpMinInvocationsInclusiveScanNonUniform:
4022     case glslang::EOpMaxInvocationsInclusiveScanNonUniform:
4023     case glslang::EOpAddInvocationsInclusiveScanNonUniform:
4024     case glslang::EOpMinInvocationsExclusiveScan:
4025     case glslang::EOpMaxInvocationsExclusiveScan:
4026     case glslang::EOpAddInvocationsExclusiveScan:
4027     case glslang::EOpMinInvocationsExclusiveScanNonUniform:
4028     case glslang::EOpMaxInvocationsExclusiveScanNonUniform:
4029     case glslang::EOpAddInvocationsExclusiveScanNonUniform:
4030 #endif
4031     {
4032         std::vector<spv::Id> operands;
4033         operands.push_back(operand);
4034         return createInvocationsOperation(op, typeId, operands, typeProxy);
4035     }
4036
4037 #ifdef AMD_EXTENSIONS
4038     case glslang::EOpMbcnt:
4039         extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_ballot);
4040         libCall = spv::MbcntAMD;
4041         break;
4042
4043     case glslang::EOpCubeFaceIndex:
4044         extBuiltins = getExtBuiltins(spv::E_SPV_AMD_gcn_shader);
4045         libCall = spv::CubeFaceIndexAMD;
4046         break;
4047
4048     case glslang::EOpCubeFaceCoord:
4049         extBuiltins = getExtBuiltins(spv::E_SPV_AMD_gcn_shader);
4050         libCall = spv::CubeFaceCoordAMD;
4051         break;
4052 #endif
4053
4054     default:
4055         return 0;
4056     }
4057
4058     spv::Id id;
4059     if (libCall >= 0) {
4060         std::vector<spv::Id> args;
4061         args.push_back(operand);
4062         id = builder.createBuiltinCall(typeId, extBuiltins >= 0 ? extBuiltins : stdBuiltins, libCall, args);
4063     } else {
4064         id = builder.createUnaryOp(unaryOp, typeId, operand);
4065     }
4066
4067     addDecoration(id, noContraction);
4068     return builder.setPrecision(id, precision);
4069 }
4070
4071 // Create a unary operation on a matrix
4072 spv::Id TGlslangToSpvTraverser::createUnaryMatrixOperation(spv::Op op, spv::Decoration precision, spv::Decoration noContraction, spv::Id typeId, spv::Id operand, glslang::TBasicType /* typeProxy */)
4073 {
4074     // Handle unary operations vector by vector.
4075     // The result type is the same type as the original type.
4076     // The algorithm is to:
4077     //   - break the matrix into vectors
4078     //   - apply the operation to each vector
4079     //   - make a matrix out the vector results
4080
4081     // get the types sorted out
4082     int numCols = builder.getNumColumns(operand);
4083     int numRows = builder.getNumRows(operand);
4084     spv::Id srcVecType  = builder.makeVectorType(builder.getScalarTypeId(builder.getTypeId(operand)), numRows);
4085     spv::Id destVecType = builder.makeVectorType(builder.getScalarTypeId(typeId), numRows);
4086     std::vector<spv::Id> results;
4087
4088     // do each vector op
4089     for (int c = 0; c < numCols; ++c) {
4090         std::vector<unsigned int> indexes;
4091         indexes.push_back(c);
4092         spv::Id srcVec  = builder.createCompositeExtract(operand, srcVecType, indexes);
4093         spv::Id destVec = builder.createUnaryOp(op, destVecType, srcVec);
4094         addDecoration(destVec, noContraction);
4095         results.push_back(builder.setPrecision(destVec, precision));
4096     }
4097
4098     // put the pieces together
4099     return builder.setPrecision(builder.createCompositeConstruct(typeId, results), precision);
4100 }
4101
4102 spv::Id TGlslangToSpvTraverser::createConversion(glslang::TOperator op, spv::Decoration precision, spv::Decoration noContraction, spv::Id destType, spv::Id operand, glslang::TBasicType typeProxy)
4103 {
4104     spv::Op convOp = spv::OpNop;
4105     spv::Id zero = 0;
4106     spv::Id one = 0;
4107     spv::Id type = 0;
4108
4109     int vectorSize = builder.isVectorType(destType) ? builder.getNumTypeComponents(destType) : 0;
4110
4111     switch (op) {
4112     case glslang::EOpConvIntToBool:
4113     case glslang::EOpConvUintToBool:
4114     case glslang::EOpConvInt64ToBool:
4115     case glslang::EOpConvUint64ToBool:
4116         zero = (op == glslang::EOpConvInt64ToBool ||
4117                 op == glslang::EOpConvUint64ToBool) ? builder.makeUint64Constant(0) : builder.makeUintConstant(0);
4118         zero = makeSmearedConstant(zero, vectorSize);
4119         return builder.createBinOp(spv::OpINotEqual, destType, operand, zero);
4120
4121     case glslang::EOpConvFloatToBool:
4122         zero = builder.makeFloatConstant(0.0F);
4123         zero = makeSmearedConstant(zero, vectorSize);
4124         return builder.createBinOp(spv::OpFOrdNotEqual, destType, operand, zero);
4125
4126     case glslang::EOpConvDoubleToBool:
4127         zero = builder.makeDoubleConstant(0.0);
4128         zero = makeSmearedConstant(zero, vectorSize);
4129         return builder.createBinOp(spv::OpFOrdNotEqual, destType, operand, zero);
4130
4131 #ifdef AMD_EXTENSIONS
4132     case glslang::EOpConvFloat16ToBool:
4133         zero = builder.makeFloat16Constant(0.0F);
4134         zero = makeSmearedConstant(zero, vectorSize);
4135         return builder.createBinOp(spv::OpFOrdNotEqual, destType, operand, zero);
4136 #endif
4137
4138     case glslang::EOpConvBoolToFloat:
4139         convOp = spv::OpSelect;
4140         zero = builder.makeFloatConstant(0.0F);
4141         one  = builder.makeFloatConstant(1.0F);
4142         break;
4143
4144     case glslang::EOpConvBoolToDouble:
4145         convOp = spv::OpSelect;
4146         zero = builder.makeDoubleConstant(0.0);
4147         one  = builder.makeDoubleConstant(1.0);
4148         break;
4149
4150 #ifdef AMD_EXTENSIONS
4151     case glslang::EOpConvBoolToFloat16:
4152         convOp = spv::OpSelect;
4153         zero = builder.makeFloat16Constant(0.0F);
4154         one = builder.makeFloat16Constant(1.0F);
4155         break;
4156 #endif
4157
4158     case glslang::EOpConvBoolToInt:
4159     case glslang::EOpConvBoolToInt64:
4160         zero = (op == glslang::EOpConvBoolToInt64) ? builder.makeInt64Constant(0) : builder.makeIntConstant(0);
4161         one  = (op == glslang::EOpConvBoolToInt64) ? builder.makeInt64Constant(1) : builder.makeIntConstant(1);
4162         convOp = spv::OpSelect;
4163         break;
4164
4165     case glslang::EOpConvBoolToUint:
4166     case glslang::EOpConvBoolToUint64:
4167         zero = (op == glslang::EOpConvBoolToUint64) ? builder.makeUint64Constant(0) : builder.makeUintConstant(0);
4168         one  = (op == glslang::EOpConvBoolToUint64) ? builder.makeUint64Constant(1) : builder.makeUintConstant(1);
4169         convOp = spv::OpSelect;
4170         break;
4171
4172     case glslang::EOpConvIntToFloat:
4173     case glslang::EOpConvIntToDouble:
4174     case glslang::EOpConvInt64ToFloat:
4175     case glslang::EOpConvInt64ToDouble:
4176 #ifdef AMD_EXTENSIONS
4177     case glslang::EOpConvIntToFloat16:
4178     case glslang::EOpConvInt64ToFloat16:
4179 #endif
4180         convOp = spv::OpConvertSToF;
4181         break;
4182
4183     case glslang::EOpConvUintToFloat:
4184     case glslang::EOpConvUintToDouble:
4185     case glslang::EOpConvUint64ToFloat:
4186     case glslang::EOpConvUint64ToDouble:
4187 #ifdef AMD_EXTENSIONS
4188     case glslang::EOpConvUintToFloat16:
4189     case glslang::EOpConvUint64ToFloat16:
4190 #endif
4191         convOp = spv::OpConvertUToF;
4192         break;
4193
4194     case glslang::EOpConvDoubleToFloat:
4195     case glslang::EOpConvFloatToDouble:
4196 #ifdef AMD_EXTENSIONS
4197     case glslang::EOpConvDoubleToFloat16:
4198     case glslang::EOpConvFloat16ToDouble:
4199     case glslang::EOpConvFloatToFloat16:
4200     case glslang::EOpConvFloat16ToFloat:
4201 #endif
4202         convOp = spv::OpFConvert;
4203         if (builder.isMatrixType(destType))
4204             return createUnaryMatrixOperation(convOp, precision, noContraction, destType, operand, typeProxy);
4205         break;
4206
4207     case glslang::EOpConvFloatToInt:
4208     case glslang::EOpConvDoubleToInt:
4209     case glslang::EOpConvFloatToInt64:
4210     case glslang::EOpConvDoubleToInt64:
4211 #ifdef AMD_EXTENSIONS
4212     case glslang::EOpConvFloat16ToInt:
4213     case glslang::EOpConvFloat16ToInt64:
4214 #endif
4215         convOp = spv::OpConvertFToS;
4216         break;
4217
4218     case glslang::EOpConvUintToInt:
4219     case glslang::EOpConvIntToUint:
4220     case glslang::EOpConvUint64ToInt64:
4221     case glslang::EOpConvInt64ToUint64:
4222         if (builder.isInSpecConstCodeGenMode()) {
4223             // Build zero scalar or vector for OpIAdd.
4224             zero = (op == glslang::EOpConvUint64ToInt64 ||
4225                     op == glslang::EOpConvInt64ToUint64) ? builder.makeUint64Constant(0) : builder.makeUintConstant(0);
4226             zero = makeSmearedConstant(zero, vectorSize);
4227             // Use OpIAdd, instead of OpBitcast to do the conversion when
4228             // generating for OpSpecConstantOp instruction.
4229             return builder.createBinOp(spv::OpIAdd, destType, operand, zero);
4230         }
4231         // For normal run-time conversion instruction, use OpBitcast.
4232         convOp = spv::OpBitcast;
4233         break;
4234
4235     case glslang::EOpConvFloatToUint:
4236     case glslang::EOpConvDoubleToUint:
4237     case glslang::EOpConvFloatToUint64:
4238     case glslang::EOpConvDoubleToUint64:
4239 #ifdef AMD_EXTENSIONS
4240     case glslang::EOpConvFloat16ToUint:
4241     case glslang::EOpConvFloat16ToUint64:
4242 #endif
4243         convOp = spv::OpConvertFToU;
4244         break;
4245
4246     case glslang::EOpConvIntToInt64:
4247     case glslang::EOpConvInt64ToInt:
4248         convOp = spv::OpSConvert;
4249         break;
4250
4251     case glslang::EOpConvUintToUint64:
4252     case glslang::EOpConvUint64ToUint:
4253         convOp = spv::OpUConvert;
4254         break;
4255
4256     case glslang::EOpConvIntToUint64:
4257     case glslang::EOpConvInt64ToUint:
4258     case glslang::EOpConvUint64ToInt:
4259     case glslang::EOpConvUintToInt64:
4260         // OpSConvert/OpUConvert + OpBitCast
4261         switch (op) {
4262         case glslang::EOpConvIntToUint64:
4263             convOp = spv::OpSConvert;
4264             type   = builder.makeIntType(64);
4265             break;
4266         case glslang::EOpConvInt64ToUint:
4267             convOp = spv::OpSConvert;
4268             type   = builder.makeIntType(32);
4269             break;
4270         case glslang::EOpConvUint64ToInt:
4271             convOp = spv::OpUConvert;
4272             type   = builder.makeUintType(32);
4273             break;
4274         case glslang::EOpConvUintToInt64:
4275             convOp = spv::OpUConvert;
4276             type   = builder.makeUintType(64);
4277             break;
4278         default:
4279             assert(0);
4280             break;
4281         }
4282
4283         if (vectorSize > 0)
4284             type = builder.makeVectorType(type, vectorSize);
4285
4286         operand = builder.createUnaryOp(convOp, type, operand);
4287
4288         if (builder.isInSpecConstCodeGenMode()) {
4289             // Build zero scalar or vector for OpIAdd.
4290             zero = (op == glslang::EOpConvIntToUint64 ||
4291                     op == glslang::EOpConvUintToInt64) ? builder.makeUint64Constant(0) : builder.makeUintConstant(0);
4292             zero = makeSmearedConstant(zero, vectorSize);
4293             // Use OpIAdd, instead of OpBitcast to do the conversion when
4294             // generating for OpSpecConstantOp instruction.
4295             return builder.createBinOp(spv::OpIAdd, destType, operand, zero);
4296         }
4297         // For normal run-time conversion instruction, use OpBitcast.
4298         convOp = spv::OpBitcast;
4299         break;
4300     default:
4301         break;
4302     }
4303
4304     spv::Id result = 0;
4305     if (convOp == spv::OpNop)
4306         return result;
4307
4308     if (convOp == spv::OpSelect) {
4309         zero = makeSmearedConstant(zero, vectorSize);
4310         one  = makeSmearedConstant(one, vectorSize);
4311         result = builder.createTriOp(convOp, destType, operand, one, zero);
4312     } else
4313         result = builder.createUnaryOp(convOp, destType, operand);
4314
4315     return builder.setPrecision(result, precision);
4316 }
4317
4318 spv::Id TGlslangToSpvTraverser::makeSmearedConstant(spv::Id constant, int vectorSize)
4319 {
4320     if (vectorSize == 0)
4321         return constant;
4322
4323     spv::Id vectorTypeId = builder.makeVectorType(builder.getTypeId(constant), vectorSize);
4324     std::vector<spv::Id> components;
4325     for (int c = 0; c < vectorSize; ++c)
4326         components.push_back(constant);
4327     return builder.makeCompositeConstant(vectorTypeId, components);
4328 }
4329
4330 // For glslang ops that map to SPV atomic opCodes
4331 spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv::Decoration /*precision*/, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy)
4332 {
4333     spv::Op opCode = spv::OpNop;
4334
4335     switch (op) {
4336     case glslang::EOpAtomicAdd:
4337     case glslang::EOpImageAtomicAdd:
4338         opCode = spv::OpAtomicIAdd;
4339         break;
4340     case glslang::EOpAtomicMin:
4341     case glslang::EOpImageAtomicMin:
4342         opCode = typeProxy == glslang::EbtUint ? spv::OpAtomicUMin : spv::OpAtomicSMin;
4343         break;
4344     case glslang::EOpAtomicMax:
4345     case glslang::EOpImageAtomicMax:
4346         opCode = typeProxy == glslang::EbtUint ? spv::OpAtomicUMax : spv::OpAtomicSMax;
4347         break;
4348     case glslang::EOpAtomicAnd:
4349     case glslang::EOpImageAtomicAnd:
4350         opCode = spv::OpAtomicAnd;
4351         break;
4352     case glslang::EOpAtomicOr:
4353     case glslang::EOpImageAtomicOr:
4354         opCode = spv::OpAtomicOr;
4355         break;
4356     case glslang::EOpAtomicXor:
4357     case glslang::EOpImageAtomicXor:
4358         opCode = spv::OpAtomicXor;
4359         break;
4360     case glslang::EOpAtomicExchange:
4361     case glslang::EOpImageAtomicExchange:
4362         opCode = spv::OpAtomicExchange;
4363         break;
4364     case glslang::EOpAtomicCompSwap:
4365     case glslang::EOpImageAtomicCompSwap:
4366         opCode = spv::OpAtomicCompareExchange;
4367         break;
4368     case glslang::EOpAtomicCounterIncrement:
4369         opCode = spv::OpAtomicIIncrement;
4370         break;
4371     case glslang::EOpAtomicCounterDecrement:
4372         opCode = spv::OpAtomicIDecrement;
4373         break;
4374     case glslang::EOpAtomicCounter:
4375         opCode = spv::OpAtomicLoad;
4376         break;
4377     default:
4378         assert(0);
4379         break;
4380     }
4381
4382     // Sort out the operands
4383     //  - mapping from glslang -> SPV
4384     //  - there are extra SPV operands with no glslang source
4385     //  - compare-exchange swaps the value and comparator
4386     //  - compare-exchange has an extra memory semantics
4387     std::vector<spv::Id> spvAtomicOperands;  // hold the spv operands
4388     auto opIt = operands.begin();            // walk the glslang operands
4389     spvAtomicOperands.push_back(*(opIt++));
4390     spvAtomicOperands.push_back(builder.makeUintConstant(spv::ScopeDevice));     // TBD: what is the correct scope?
4391     spvAtomicOperands.push_back(builder.makeUintConstant(spv::MemorySemanticsMaskNone)); // TBD: what are the correct memory semantics?
4392     if (opCode == spv::OpAtomicCompareExchange) {
4393         // There are 2 memory semantics for compare-exchange. And the operand order of "comparator" and "new value" in GLSL
4394         // differs from that in SPIR-V. Hence, special processing is required.
4395         spvAtomicOperands.push_back(builder.makeUintConstant(spv::MemorySemanticsMaskNone));
4396         spvAtomicOperands.push_back(*(opIt + 1));
4397         spvAtomicOperands.push_back(*opIt);
4398         opIt += 2;
4399     }
4400
4401     // Add the rest of the operands, skipping any that were dealt with above.
4402     for (; opIt != operands.end(); ++opIt)
4403         spvAtomicOperands.push_back(*opIt);
4404
4405     return builder.createOp(opCode, typeId, spvAtomicOperands);
4406 }
4407
4408 // Create group invocation operations.
4409 spv::Id TGlslangToSpvTraverser::createInvocationsOperation(glslang::TOperator op, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy)
4410 {
4411 #ifdef AMD_EXTENSIONS
4412     bool isUnsigned = typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64;
4413     bool isFloat = typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble || typeProxy == glslang::EbtFloat16;
4414 #endif
4415
4416     spv::Op opCode = spv::OpNop;
4417     std::vector<spv::Id> spvGroupOperands;
4418     spv::GroupOperation groupOperation = spv::GroupOperationMax;
4419
4420     if (op == glslang::EOpBallot || op == glslang::EOpReadFirstInvocation ||
4421         op == glslang::EOpReadInvocation) {
4422         builder.addExtension(spv::E_SPV_KHR_shader_ballot);
4423         builder.addCapability(spv::CapabilitySubgroupBallotKHR);
4424     } else if (op == glslang::EOpAnyInvocation ||
4425         op == glslang::EOpAllInvocations ||
4426         op == glslang::EOpAllInvocationsEqual) {
4427         builder.addExtension(spv::E_SPV_KHR_subgroup_vote);
4428         builder.addCapability(spv::CapabilitySubgroupVoteKHR);
4429     } else {
4430         builder.addCapability(spv::CapabilityGroups);
4431 #ifdef AMD_EXTENSIONS
4432         if (op == glslang::EOpMinInvocationsNonUniform ||
4433             op == glslang::EOpMaxInvocationsNonUniform ||
4434             op == glslang::EOpAddInvocationsNonUniform ||
4435             op == glslang::EOpMinInvocationsInclusiveScanNonUniform ||
4436             op == glslang::EOpMaxInvocationsInclusiveScanNonUniform ||
4437             op == glslang::EOpAddInvocationsInclusiveScanNonUniform ||
4438             op == glslang::EOpMinInvocationsExclusiveScanNonUniform ||
4439             op == glslang::EOpMaxInvocationsExclusiveScanNonUniform ||
4440             op == glslang::EOpAddInvocationsExclusiveScanNonUniform)
4441             builder.addExtension(spv::E_SPV_AMD_shader_ballot);
4442 #endif
4443
4444         spvGroupOperands.push_back(builder.makeUintConstant(spv::ScopeSubgroup));
4445 #ifdef AMD_EXTENSIONS
4446         switch (op) {
4447         case glslang::EOpMinInvocations:
4448         case glslang::EOpMaxInvocations:
4449         case glslang::EOpAddInvocations:
4450         case glslang::EOpMinInvocationsNonUniform:
4451         case glslang::EOpMaxInvocationsNonUniform:
4452         case glslang::EOpAddInvocationsNonUniform:
4453             groupOperation = spv::GroupOperationReduce;
4454             spvGroupOperands.push_back(groupOperation);
4455             break;
4456         case glslang::EOpMinInvocationsInclusiveScan:
4457         case glslang::EOpMaxInvocationsInclusiveScan:
4458         case glslang::EOpAddInvocationsInclusiveScan:
4459         case glslang::EOpMinInvocationsInclusiveScanNonUniform:
4460         case glslang::EOpMaxInvocationsInclusiveScanNonUniform:
4461         case glslang::EOpAddInvocationsInclusiveScanNonUniform:
4462             groupOperation = spv::GroupOperationInclusiveScan;
4463             spvGroupOperands.push_back(groupOperation);
4464             break;
4465         case glslang::EOpMinInvocationsExclusiveScan:
4466         case glslang::EOpMaxInvocationsExclusiveScan:
4467         case glslang::EOpAddInvocationsExclusiveScan:
4468         case glslang::EOpMinInvocationsExclusiveScanNonUniform:
4469         case glslang::EOpMaxInvocationsExclusiveScanNonUniform:
4470         case glslang::EOpAddInvocationsExclusiveScanNonUniform:
4471             groupOperation = spv::GroupOperationExclusiveScan;
4472             spvGroupOperands.push_back(groupOperation);
4473             break;
4474         default:
4475             break;
4476         }
4477 #endif
4478     }
4479
4480     for (auto opIt = operands.begin(); opIt != operands.end(); ++opIt)
4481         spvGroupOperands.push_back(*opIt);
4482
4483     switch (op) {
4484     case glslang::EOpAnyInvocation:
4485         opCode = spv::OpSubgroupAnyKHR;
4486         break;
4487     case glslang::EOpAllInvocations:
4488         opCode = spv::OpSubgroupAllKHR;
4489         break;
4490     case glslang::EOpAllInvocationsEqual:
4491         opCode = spv::OpSubgroupAllEqualKHR;
4492         break;
4493     case glslang::EOpReadInvocation:
4494         opCode = spv::OpSubgroupReadInvocationKHR;
4495         if (builder.isVectorType(typeId))
4496             return CreateInvocationsVectorOperation(opCode, groupOperation, typeId, operands);
4497         break;
4498     case glslang::EOpReadFirstInvocation:
4499         opCode = spv::OpSubgroupFirstInvocationKHR;
4500         break;
4501     case glslang::EOpBallot:
4502     {
4503         // NOTE: According to the spec, the result type of "OpSubgroupBallotKHR" must be a 4 component vector of 32
4504         // bit integer types. The GLSL built-in function "ballotARB()" assumes the maximum number of invocations in
4505         // a subgroup is 64. Thus, we have to convert uvec4.xy to uint64_t as follow:
4506         //
4507         //     result = Bitcast(SubgroupBallotKHR(Predicate).xy)
4508         //
4509         spv::Id uintType  = builder.makeUintType(32);
4510         spv::Id uvec4Type = builder.makeVectorType(uintType, 4);
4511         spv::Id result = builder.createOp(spv::OpSubgroupBallotKHR, uvec4Type, spvGroupOperands);
4512
4513         std::vector<spv::Id> components;
4514         components.push_back(builder.createCompositeExtract(result, uintType, 0));
4515         components.push_back(builder.createCompositeExtract(result, uintType, 1));
4516
4517         spv::Id uvec2Type = builder.makeVectorType(uintType, 2);
4518         return builder.createUnaryOp(spv::OpBitcast, typeId,
4519                                      builder.createCompositeConstruct(uvec2Type, components));
4520     }
4521
4522 #ifdef AMD_EXTENSIONS
4523     case glslang::EOpMinInvocations:
4524     case glslang::EOpMaxInvocations:
4525     case glslang::EOpAddInvocations:
4526     case glslang::EOpMinInvocationsInclusiveScan:
4527     case glslang::EOpMaxInvocationsInclusiveScan:
4528     case glslang::EOpAddInvocationsInclusiveScan:
4529     case glslang::EOpMinInvocationsExclusiveScan:
4530     case glslang::EOpMaxInvocationsExclusiveScan:
4531     case glslang::EOpAddInvocationsExclusiveScan:
4532         if (op == glslang::EOpMinInvocations ||
4533             op == glslang::EOpMinInvocationsInclusiveScan ||
4534             op == glslang::EOpMinInvocationsExclusiveScan) {
4535             if (isFloat)
4536                 opCode = spv::OpGroupFMin;
4537             else {
4538                 if (isUnsigned)
4539                     opCode = spv::OpGroupUMin;
4540                 else
4541                     opCode = spv::OpGroupSMin;
4542             }
4543         } else if (op == glslang::EOpMaxInvocations ||
4544                    op == glslang::EOpMaxInvocationsInclusiveScan ||
4545                    op == glslang::EOpMaxInvocationsExclusiveScan) {
4546             if (isFloat)
4547                 opCode = spv::OpGroupFMax;
4548             else {
4549                 if (isUnsigned)
4550                     opCode = spv::OpGroupUMax;
4551                 else
4552                     opCode = spv::OpGroupSMax;
4553             }
4554         } else {
4555             if (isFloat)
4556                 opCode = spv::OpGroupFAdd;
4557             else
4558                 opCode = spv::OpGroupIAdd;
4559         }
4560
4561         if (builder.isVectorType(typeId))
4562             return CreateInvocationsVectorOperation(opCode, groupOperation, typeId, operands);
4563
4564         break;
4565     case glslang::EOpMinInvocationsNonUniform:
4566     case glslang::EOpMaxInvocationsNonUniform:
4567     case glslang::EOpAddInvocationsNonUniform:
4568     case glslang::EOpMinInvocationsInclusiveScanNonUniform:
4569     case glslang::EOpMaxInvocationsInclusiveScanNonUniform:
4570     case glslang::EOpAddInvocationsInclusiveScanNonUniform:
4571     case glslang::EOpMinInvocationsExclusiveScanNonUniform:
4572     case glslang::EOpMaxInvocationsExclusiveScanNonUniform:
4573     case glslang::EOpAddInvocationsExclusiveScanNonUniform:
4574         if (op == glslang::EOpMinInvocationsNonUniform ||
4575             op == glslang::EOpMinInvocationsInclusiveScanNonUniform ||
4576             op == glslang::EOpMinInvocationsExclusiveScanNonUniform) {
4577             if (isFloat)
4578                 opCode = spv::OpGroupFMinNonUniformAMD;
4579             else {
4580                 if (isUnsigned)
4581                     opCode = spv::OpGroupUMinNonUniformAMD;
4582                 else
4583                     opCode = spv::OpGroupSMinNonUniformAMD;
4584             }
4585         }
4586         else if (op == glslang::EOpMaxInvocationsNonUniform ||
4587                  op == glslang::EOpMaxInvocationsInclusiveScanNonUniform ||
4588                  op == glslang::EOpMaxInvocationsExclusiveScanNonUniform) {
4589             if (isFloat)
4590                 opCode = spv::OpGroupFMaxNonUniformAMD;
4591             else {
4592                 if (isUnsigned)
4593                     opCode = spv::OpGroupUMaxNonUniformAMD;
4594                 else
4595                     opCode = spv::OpGroupSMaxNonUniformAMD;
4596             }
4597         }
4598         else {
4599             if (isFloat)
4600                 opCode = spv::OpGroupFAddNonUniformAMD;
4601             else
4602                 opCode = spv::OpGroupIAddNonUniformAMD;
4603         }
4604
4605         if (builder.isVectorType(typeId))
4606             return CreateInvocationsVectorOperation(opCode, groupOperation, typeId, operands);
4607
4608         break;
4609 #endif
4610     default:
4611         logger->missingFunctionality("invocation operation");
4612         return spv::NoResult;
4613     }
4614
4615     assert(opCode != spv::OpNop);
4616     return builder.createOp(opCode, typeId, spvGroupOperands);
4617 }
4618
4619 // Create group invocation operations on a vector
4620 spv::Id TGlslangToSpvTraverser::CreateInvocationsVectorOperation(spv::Op op, spv::GroupOperation groupOperation, spv::Id typeId, std::vector<spv::Id>& operands)
4621 {
4622 #ifdef AMD_EXTENSIONS
4623     assert(op == spv::OpGroupFMin || op == spv::OpGroupUMin || op == spv::OpGroupSMin ||
4624            op == spv::OpGroupFMax || op == spv::OpGroupUMax || op == spv::OpGroupSMax ||
4625            op == spv::OpGroupFAdd || op == spv::OpGroupIAdd || op == spv::OpGroupBroadcast ||
4626            op == spv::OpSubgroupReadInvocationKHR ||
4627            op == spv::OpGroupFMinNonUniformAMD || op == spv::OpGroupUMinNonUniformAMD || op == spv::OpGroupSMinNonUniformAMD ||
4628            op == spv::OpGroupFMaxNonUniformAMD || op == spv::OpGroupUMaxNonUniformAMD || op == spv::OpGroupSMaxNonUniformAMD ||
4629            op == spv::OpGroupFAddNonUniformAMD || op == spv::OpGroupIAddNonUniformAMD);
4630 #else
4631     assert(op == spv::OpGroupFMin || op == spv::OpGroupUMin || op == spv::OpGroupSMin ||
4632            op == spv::OpGroupFMax || op == spv::OpGroupUMax || op == spv::OpGroupSMax ||
4633            op == spv::OpGroupFAdd || op == spv::OpGroupIAdd || op == spv::OpGroupBroadcast ||
4634            op == spv::OpSubgroupReadInvocationKHR);
4635 #endif
4636
4637     // Handle group invocation operations scalar by scalar.
4638     // The result type is the same type as the original type.
4639     // The algorithm is to:
4640     //   - break the vector into scalars
4641     //   - apply the operation to each scalar
4642     //   - make a vector out the scalar results
4643
4644     // get the types sorted out
4645     int numComponents = builder.getNumComponents(operands[0]);
4646     spv::Id scalarType = builder.getScalarTypeId(builder.getTypeId(operands[0]));
4647     std::vector<spv::Id> results;
4648
4649     // do each scalar op
4650     for (int comp = 0; comp < numComponents; ++comp) {
4651         std::vector<unsigned int> indexes;
4652         indexes.push_back(comp);
4653         spv::Id scalar = builder.createCompositeExtract(operands[0], scalarType, indexes);
4654         std::vector<spv::Id> spvGroupOperands;
4655         if (op == spv::OpSubgroupReadInvocationKHR) {
4656             spvGroupOperands.push_back(scalar);
4657             spvGroupOperands.push_back(operands[1]);
4658         } else if (op == spv::OpGroupBroadcast) {
4659             spvGroupOperands.push_back(builder.makeUintConstant(spv::ScopeSubgroup));
4660             spvGroupOperands.push_back(scalar);
4661             spvGroupOperands.push_back(operands[1]);
4662         } else {
4663             spvGroupOperands.push_back(builder.makeUintConstant(spv::ScopeSubgroup));
4664             spvGroupOperands.push_back(groupOperation);
4665             spvGroupOperands.push_back(scalar);
4666         }
4667
4668         results.push_back(builder.createOp(op, scalarType, spvGroupOperands));
4669     }
4670
4671     // put the pieces together
4672     return builder.createCompositeConstruct(typeId, results);
4673 }
4674
4675 spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy)
4676 {
4677     bool isUnsigned = typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64;
4678 #ifdef AMD_EXTENSIONS
4679     bool isFloat = typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble || typeProxy == glslang::EbtFloat16;
4680 #else
4681     bool isFloat = typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble;
4682 #endif
4683
4684     spv::Op opCode = spv::OpNop;
4685     int extBuiltins = -1;
4686     int libCall = -1;
4687     size_t consumedOperands = operands.size();
4688     spv::Id typeId0 = 0;
4689     if (consumedOperands > 0)
4690         typeId0 = builder.getTypeId(operands[0]);
4691     spv::Id typeId1 = 0;
4692     if (consumedOperands > 1)
4693         typeId1 = builder.getTypeId(operands[1]);
4694     spv::Id frexpIntType = 0;
4695
4696     switch (op) {
4697     case glslang::EOpMin:
4698         if (isFloat)
4699             libCall = spv::GLSLstd450FMin;
4700         else if (isUnsigned)
4701             libCall = spv::GLSLstd450UMin;
4702         else
4703             libCall = spv::GLSLstd450SMin;
4704         builder.promoteScalar(precision, operands.front(), operands.back());
4705         break;
4706     case glslang::EOpModf:
4707         libCall = spv::GLSLstd450Modf;
4708         break;
4709     case glslang::EOpMax:
4710         if (isFloat)
4711             libCall = spv::GLSLstd450FMax;
4712         else if (isUnsigned)
4713             libCall = spv::GLSLstd450UMax;
4714         else
4715             libCall = spv::GLSLstd450SMax;
4716         builder.promoteScalar(precision, operands.front(), operands.back());
4717         break;
4718     case glslang::EOpPow:
4719         libCall = spv::GLSLstd450Pow;
4720         break;
4721     case glslang::EOpDot:
4722         opCode = spv::OpDot;
4723         break;
4724     case glslang::EOpAtan:
4725         libCall = spv::GLSLstd450Atan2;
4726         break;
4727
4728     case glslang::EOpClamp:
4729         if (isFloat)
4730             libCall = spv::GLSLstd450FClamp;
4731         else if (isUnsigned)
4732             libCall = spv::GLSLstd450UClamp;
4733         else
4734             libCall = spv::GLSLstd450SClamp;
4735         builder.promoteScalar(precision, operands.front(), operands[1]);
4736         builder.promoteScalar(precision, operands.front(), operands[2]);
4737         break;
4738     case glslang::EOpMix:
4739         if (! builder.isBoolType(builder.getScalarTypeId(builder.getTypeId(operands.back())))) {
4740             assert(isFloat);
4741             libCall = spv::GLSLstd450FMix;
4742         } else {
4743             opCode = spv::OpSelect;
4744             std::swap(operands.front(), operands.back());
4745         }
4746         builder.promoteScalar(precision, operands.front(), operands.back());
4747         break;
4748     case glslang::EOpStep:
4749         libCall = spv::GLSLstd450Step;
4750         builder.promoteScalar(precision, operands.front(), operands.back());
4751         break;
4752     case glslang::EOpSmoothStep:
4753         libCall = spv::GLSLstd450SmoothStep;
4754         builder.promoteScalar(precision, operands[0], operands[2]);
4755         builder.promoteScalar(precision, operands[1], operands[2]);
4756         break;
4757
4758     case glslang::EOpDistance:
4759         libCall = spv::GLSLstd450Distance;
4760         break;
4761     case glslang::EOpCross:
4762         libCall = spv::GLSLstd450Cross;
4763         break;
4764     case glslang::EOpFaceForward:
4765         libCall = spv::GLSLstd450FaceForward;
4766         break;
4767     case glslang::EOpReflect:
4768         libCall = spv::GLSLstd450Reflect;
4769         break;
4770     case glslang::EOpRefract:
4771         libCall = spv::GLSLstd450Refract;
4772         break;
4773     case glslang::EOpInterpolateAtSample:
4774         builder.addCapability(spv::CapabilityInterpolationFunction);
4775         libCall = spv::GLSLstd450InterpolateAtSample;
4776         break;
4777     case glslang::EOpInterpolateAtOffset:
4778         builder.addCapability(spv::CapabilityInterpolationFunction);
4779         libCall = spv::GLSLstd450InterpolateAtOffset;
4780         break;
4781     case glslang::EOpAddCarry:
4782         opCode = spv::OpIAddCarry;
4783         typeId = builder.makeStructResultType(typeId0, typeId0);
4784         consumedOperands = 2;
4785         break;
4786     case glslang::EOpSubBorrow:
4787         opCode = spv::OpISubBorrow;
4788         typeId = builder.makeStructResultType(typeId0, typeId0);
4789         consumedOperands = 2;
4790         break;
4791     case glslang::EOpUMulExtended:
4792         opCode = spv::OpUMulExtended;
4793         typeId = builder.makeStructResultType(typeId0, typeId0);
4794         consumedOperands = 2;
4795         break;
4796     case glslang::EOpIMulExtended:
4797         opCode = spv::OpSMulExtended;
4798         typeId = builder.makeStructResultType(typeId0, typeId0);
4799         consumedOperands = 2;
4800         break;
4801     case glslang::EOpBitfieldExtract:
4802         if (isUnsigned)
4803             opCode = spv::OpBitFieldUExtract;
4804         else
4805             opCode = spv::OpBitFieldSExtract;
4806         break;
4807     case glslang::EOpBitfieldInsert:
4808         opCode = spv::OpBitFieldInsert;
4809         break;
4810
4811     case glslang::EOpFma:
4812         libCall = spv::GLSLstd450Fma;
4813         break;
4814     case glslang::EOpFrexp:
4815         {
4816             libCall = spv::GLSLstd450FrexpStruct;
4817             assert(builder.isPointerType(typeId1));
4818             typeId1 = builder.getContainedTypeId(typeId1);
4819 #ifdef AMD_EXTENSIONS
4820             int width = builder.getScalarTypeWidth(typeId1);
4821 #else
4822             int width = 32;
4823 #endif
4824             if (builder.getNumComponents(operands[0]) == 1)
4825                 frexpIntType = builder.makeIntegerType(width, true);
4826             else
4827                 frexpIntType = builder.makeVectorType(builder.makeIntegerType(width, true), builder.getNumComponents(operands[0]));
4828             typeId = builder.makeStructResultType(typeId0, frexpIntType);
4829             consumedOperands = 1;
4830         }
4831         break;
4832     case glslang::EOpLdexp:
4833         libCall = spv::GLSLstd450Ldexp;
4834         break;
4835
4836     case glslang::EOpReadInvocation:
4837         return createInvocationsOperation(op, typeId, operands, typeProxy);
4838
4839 #ifdef AMD_EXTENSIONS
4840     case glslang::EOpSwizzleInvocations:
4841         extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_ballot);
4842         libCall = spv::SwizzleInvocationsAMD;
4843         break;
4844     case glslang::EOpSwizzleInvocationsMasked:
4845         extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_ballot);
4846         libCall = spv::SwizzleInvocationsMaskedAMD;
4847         break;
4848     case glslang::EOpWriteInvocation:
4849         extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_ballot);
4850         libCall = spv::WriteInvocationAMD;
4851         break;
4852
4853     case glslang::EOpMin3:
4854         extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_trinary_minmax);
4855         if (isFloat)
4856             libCall = spv::FMin3AMD;
4857         else {
4858             if (isUnsigned)
4859                 libCall = spv::UMin3AMD;
4860             else
4861                 libCall = spv::SMin3AMD;
4862         }
4863         break;
4864     case glslang::EOpMax3:
4865         extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_trinary_minmax);
4866         if (isFloat)
4867             libCall = spv::FMax3AMD;
4868         else {
4869             if (isUnsigned)
4870                 libCall = spv::UMax3AMD;
4871             else
4872                 libCall = spv::SMax3AMD;
4873         }
4874         break;
4875     case glslang::EOpMid3:
4876         extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_trinary_minmax);
4877         if (isFloat)
4878             libCall = spv::FMid3AMD;
4879         else {
4880             if (isUnsigned)
4881                 libCall = spv::UMid3AMD;
4882             else
4883                 libCall = spv::SMid3AMD;
4884         }
4885         break;
4886
4887     case glslang::EOpInterpolateAtVertex:
4888         extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_explicit_vertex_parameter);
4889         libCall = spv::InterpolateAtVertexAMD;
4890         break;
4891 #endif
4892
4893     default:
4894         return 0;
4895     }
4896
4897     spv::Id id = 0;
4898     if (libCall >= 0) {
4899         // Use an extended instruction from the standard library.
4900         // Construct the call arguments, without modifying the original operands vector.
4901         // We might need the remaining arguments, e.g. in the EOpFrexp case.
4902         std::vector<spv::Id> callArguments(operands.begin(), operands.begin() + consumedOperands);
4903         id = builder.createBuiltinCall(typeId, extBuiltins >= 0 ? extBuiltins : stdBuiltins, libCall, callArguments);
4904     } else {
4905         switch (consumedOperands) {
4906         case 0:
4907             // should all be handled by visitAggregate and createNoArgOperation
4908             assert(0);
4909             return 0;
4910         case 1:
4911             // should all be handled by createUnaryOperation
4912             assert(0);
4913             return 0;
4914         case 2:
4915             id = builder.createBinOp(opCode, typeId, operands[0], operands[1]);
4916             break;
4917         default:
4918             // anything 3 or over doesn't have l-value operands, so all should be consumed
4919             assert(consumedOperands == operands.size());
4920             id = builder.createOp(opCode, typeId, operands);
4921             break;
4922         }
4923     }
4924
4925     // Decode the return types that were structures
4926     switch (op) {
4927     case glslang::EOpAddCarry:
4928     case glslang::EOpSubBorrow:
4929         builder.createStore(builder.createCompositeExtract(id, typeId0, 1), operands[2]);
4930         id = builder.createCompositeExtract(id, typeId0, 0);
4931         break;
4932     case glslang::EOpUMulExtended:
4933     case glslang::EOpIMulExtended:
4934         builder.createStore(builder.createCompositeExtract(id, typeId0, 0), operands[3]);
4935         builder.createStore(builder.createCompositeExtract(id, typeId0, 1), operands[2]);
4936         break;
4937     case glslang::EOpFrexp:
4938         {
4939             assert(operands.size() == 2);
4940             if (builder.isFloatType(builder.getScalarTypeId(typeId1))) {
4941                 // "exp" is floating-point type (from HLSL intrinsic)
4942                 spv::Id member1 = builder.createCompositeExtract(id, frexpIntType, 1);
4943                 member1 = builder.createUnaryOp(spv::OpConvertSToF, typeId1, member1);
4944                 builder.createStore(member1, operands[1]);
4945             } else
4946                 // "exp" is integer type (from GLSL built-in function)
4947                 builder.createStore(builder.createCompositeExtract(id, frexpIntType, 1), operands[1]);
4948             id = builder.createCompositeExtract(id, typeId0, 0);
4949         }
4950         break;
4951     default:
4952         break;
4953     }
4954
4955     return builder.setPrecision(id, precision);
4956 }
4957
4958 // Intrinsics with no arguments (or no return value, and no precision).
4959 spv::Id TGlslangToSpvTraverser::createNoArgOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId)
4960 {
4961     // TODO: get the barrier operands correct
4962
4963     switch (op) {
4964     case glslang::EOpEmitVertex:
4965         builder.createNoResultOp(spv::OpEmitVertex);
4966         return 0;
4967     case glslang::EOpEndPrimitive:
4968         builder.createNoResultOp(spv::OpEndPrimitive);
4969         return 0;
4970     case glslang::EOpBarrier:
4971         builder.createControlBarrier(spv::ScopeWorkgroup, spv::ScopeDevice, spv::MemorySemanticsMaskNone);
4972         return 0;
4973     case glslang::EOpMemoryBarrier:
4974         builder.createMemoryBarrier(spv::ScopeDevice, spv::MemorySemanticsAllMemory);
4975         return 0;
4976     case glslang::EOpMemoryBarrierAtomicCounter:
4977         builder.createMemoryBarrier(spv::ScopeDevice, spv::MemorySemanticsAtomicCounterMemoryMask);
4978         return 0;
4979     case glslang::EOpMemoryBarrierBuffer:
4980         builder.createMemoryBarrier(spv::ScopeDevice, spv::MemorySemanticsUniformMemoryMask);
4981         return 0;
4982     case glslang::EOpMemoryBarrierImage:
4983         builder.createMemoryBarrier(spv::ScopeDevice, spv::MemorySemanticsImageMemoryMask);
4984         return 0;
4985     case glslang::EOpMemoryBarrierShared:
4986         builder.createMemoryBarrier(spv::ScopeDevice, spv::MemorySemanticsWorkgroupMemoryMask);
4987         return 0;
4988     case glslang::EOpGroupMemoryBarrier:
4989         builder.createMemoryBarrier(spv::ScopeDevice, spv::MemorySemanticsCrossWorkgroupMemoryMask);
4990         return 0;
4991     case glslang::EOpAllMemoryBarrierWithGroupSync:
4992         // Control barrier with non-"None" semantic is also a memory barrier.
4993         builder.createControlBarrier(spv::ScopeDevice, spv::ScopeDevice, spv::MemorySemanticsAllMemory);
4994         return 0;
4995     case glslang::EOpGroupMemoryBarrierWithGroupSync:
4996         // Control barrier with non-"None" semantic is also a memory barrier.
4997         builder.createControlBarrier(spv::ScopeDevice, spv::ScopeDevice, spv::MemorySemanticsCrossWorkgroupMemoryMask);
4998         return 0;
4999     case glslang::EOpWorkgroupMemoryBarrier:
5000         builder.createMemoryBarrier(spv::ScopeWorkgroup, spv::MemorySemanticsWorkgroupMemoryMask);
5001         return 0;
5002     case glslang::EOpWorkgroupMemoryBarrierWithGroupSync:
5003         // Control barrier with non-"None" semantic is also a memory barrier.
5004         builder.createControlBarrier(spv::ScopeWorkgroup, spv::ScopeWorkgroup, spv::MemorySemanticsWorkgroupMemoryMask);
5005         return 0;
5006 #ifdef AMD_EXTENSIONS
5007     case glslang::EOpTime:
5008     {
5009         std::vector<spv::Id> args; // Dummy arguments
5010         spv::Id id = builder.createBuiltinCall(typeId, getExtBuiltins(spv::E_SPV_AMD_gcn_shader), spv::TimeAMD, args);
5011         return builder.setPrecision(id, precision);
5012     }
5013 #endif
5014     default:
5015         logger->missingFunctionality("unknown operation with no arguments");
5016         return 0;
5017     }
5018 }
5019
5020 spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol)
5021 {
5022     auto iter = symbolValues.find(symbol->getId());
5023     spv::Id id;
5024     if (symbolValues.end() != iter) {
5025         id = iter->second;
5026         return id;
5027     }
5028
5029     // it was not found, create it
5030     id = createSpvVariable(symbol);
5031     symbolValues[symbol->getId()] = id;
5032
5033     if (symbol->getBasicType() != glslang::EbtBlock) {
5034         addDecoration(id, TranslatePrecisionDecoration(symbol->getType()));
5035         addDecoration(id, TranslateInterpolationDecoration(symbol->getType().getQualifier()));
5036         addDecoration(id, TranslateAuxiliaryStorageDecoration(symbol->getType().getQualifier()));
5037         if (symbol->getType().getQualifier().hasSpecConstantId())
5038             addDecoration(id, spv::DecorationSpecId, symbol->getType().getQualifier().layoutSpecConstantId);
5039         if (symbol->getQualifier().hasIndex())
5040             builder.addDecoration(id, spv::DecorationIndex, symbol->getQualifier().layoutIndex);
5041         if (symbol->getQualifier().hasComponent())
5042             builder.addDecoration(id, spv::DecorationComponent, symbol->getQualifier().layoutComponent);
5043         if (glslangIntermediate->getXfbMode()) {
5044             builder.addCapability(spv::CapabilityTransformFeedback);
5045             if (symbol->getQualifier().hasXfbStride())
5046                 builder.addDecoration(id, spv::DecorationXfbStride, symbol->getQualifier().layoutXfbStride);
5047             if (symbol->getQualifier().hasXfbBuffer())
5048                 builder.addDecoration(id, spv::DecorationXfbBuffer, symbol->getQualifier().layoutXfbBuffer);
5049             if (symbol->getQualifier().hasXfbOffset())
5050                 builder.addDecoration(id, spv::DecorationOffset, symbol->getQualifier().layoutXfbOffset);
5051         }
5052         // atomic counters use this:
5053         if (symbol->getQualifier().hasOffset())
5054             builder.addDecoration(id, spv::DecorationOffset, symbol->getQualifier().layoutOffset);
5055     }
5056
5057     if (symbol->getQualifier().hasLocation())
5058         builder.addDecoration(id, spv::DecorationLocation, symbol->getQualifier().layoutLocation);
5059     addDecoration(id, TranslateInvariantDecoration(symbol->getType().getQualifier()));
5060     if (symbol->getQualifier().hasStream() && glslangIntermediate->isMultiStream()) {
5061         builder.addCapability(spv::CapabilityGeometryStreams);
5062         builder.addDecoration(id, spv::DecorationStream, symbol->getQualifier().layoutStream);
5063     }
5064     if (symbol->getQualifier().hasSet())
5065         builder.addDecoration(id, spv::DecorationDescriptorSet, symbol->getQualifier().layoutSet);
5066     else if (IsDescriptorResource(symbol->getType())) {
5067         // default to 0
5068         builder.addDecoration(id, spv::DecorationDescriptorSet, 0);
5069     }
5070     if (symbol->getQualifier().hasBinding())
5071         builder.addDecoration(id, spv::DecorationBinding, symbol->getQualifier().layoutBinding);
5072     if (symbol->getQualifier().hasAttachment())
5073         builder.addDecoration(id, spv::DecorationInputAttachmentIndex, symbol->getQualifier().layoutAttachment);
5074     if (glslangIntermediate->getXfbMode()) {
5075         builder.addCapability(spv::CapabilityTransformFeedback);
5076         if (symbol->getQualifier().hasXfbStride())
5077             builder.addDecoration(id, spv::DecorationXfbStride, symbol->getQualifier().layoutXfbStride);
5078         if (symbol->getQualifier().hasXfbBuffer())
5079             builder.addDecoration(id, spv::DecorationXfbBuffer, symbol->getQualifier().layoutXfbBuffer);
5080     }
5081
5082     if (symbol->getType().isImage()) {
5083         std::vector<spv::Decoration> memory;
5084         TranslateMemoryDecoration(symbol->getType().getQualifier(), memory);
5085         for (unsigned int i = 0; i < memory.size(); ++i)
5086             addDecoration(id, memory[i]);
5087     }
5088
5089     // built-in variable decorations
5090     spv::BuiltIn builtIn = TranslateBuiltInDecoration(symbol->getQualifier().builtIn, false);
5091     if (builtIn != spv::BuiltInMax)
5092         addDecoration(id, spv::DecorationBuiltIn, (int)builtIn);
5093
5094 #ifdef NV_EXTENSIONS
5095     if (builtIn == spv::BuiltInSampleMask) {
5096           spv::Decoration decoration;
5097           // GL_NV_sample_mask_override_coverage extension
5098           if (glslangIntermediate->getLayoutOverrideCoverage())
5099               decoration = (spv::Decoration)spv::DecorationOverrideCoverageNV;
5100           else
5101               decoration = (spv::Decoration)spv::DecorationMax;
5102         addDecoration(id, decoration);
5103         if (decoration != spv::DecorationMax) {
5104             builder.addExtension(spv::E_SPV_NV_sample_mask_override_coverage);
5105         }
5106     }
5107     else if (builtIn == spv::BuiltInLayer) {
5108         // SPV_NV_viewport_array2 extension
5109         if (symbol->getQualifier().layoutViewportRelative)
5110         {
5111             addDecoration(id, (spv::Decoration)spv::DecorationViewportRelativeNV);
5112             builder.addCapability(spv::CapabilityShaderViewportMaskNV);
5113             builder.addExtension(spv::E_SPV_NV_viewport_array2);
5114         }
5115         if(symbol->getQualifier().layoutSecondaryViewportRelativeOffset != -2048)
5116         {
5117             addDecoration(id, (spv::Decoration)spv::DecorationSecondaryViewportRelativeNV, symbol->getQualifier().layoutSecondaryViewportRelativeOffset);
5118             builder.addCapability(spv::CapabilityShaderStereoViewNV);
5119             builder.addExtension(spv::E_SPV_NV_stereo_view_rendering);
5120         }
5121     }
5122
5123     if (symbol->getQualifier().layoutPassthrough) {
5124         addDecoration(id, spv::DecorationPassthroughNV);
5125         builder.addCapability(spv::CapabilityGeometryShaderPassthroughNV);
5126         builder.addExtension(spv::E_SPV_NV_geometry_shader_passthrough);
5127     }
5128 #endif
5129
5130     return id;
5131 }
5132
5133 // If 'dec' is valid, add no-operand decoration to an object
5134 void TGlslangToSpvTraverser::addDecoration(spv::Id id, spv::Decoration dec)
5135 {
5136     if (dec != spv::DecorationMax)
5137         builder.addDecoration(id, dec);
5138 }
5139
5140 // If 'dec' is valid, add a one-operand decoration to an object
5141 void TGlslangToSpvTraverser::addDecoration(spv::Id id, spv::Decoration dec, unsigned value)
5142 {
5143     if (dec != spv::DecorationMax)
5144         builder.addDecoration(id, dec, value);
5145 }
5146
5147 // If 'dec' is valid, add a no-operand decoration to a struct member
5148 void TGlslangToSpvTraverser::addMemberDecoration(spv::Id id, int member, spv::Decoration dec)
5149 {
5150     if (dec != spv::DecorationMax)
5151         builder.addMemberDecoration(id, (unsigned)member, dec);
5152 }
5153
5154 // If 'dec' is valid, add a one-operand decoration to a struct member
5155 void TGlslangToSpvTraverser::addMemberDecoration(spv::Id id, int member, spv::Decoration dec, unsigned value)
5156 {
5157     if (dec != spv::DecorationMax)
5158         builder.addMemberDecoration(id, (unsigned)member, dec, value);
5159 }
5160
5161 // Make a full tree of instructions to build a SPIR-V specialization constant,
5162 // or regular constant if possible.
5163 //
5164 // TBD: this is not yet done, nor verified to be the best design, it does do the leaf symbols though
5165 //
5166 // Recursively walk the nodes.  The nodes form a tree whose leaves are
5167 // regular constants, which themselves are trees that createSpvConstant()
5168 // recursively walks.  So, this function walks the "top" of the tree:
5169 //  - emit specialization constant-building instructions for specConstant
5170 //  - when running into a non-spec-constant, switch to createSpvConstant()
5171 spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TIntermTyped& node)
5172 {
5173     assert(node.getQualifier().isConstant());
5174
5175     // Handle front-end constants first (non-specialization constants).
5176     if (! node.getQualifier().specConstant) {
5177         // hand off to the non-spec-constant path
5178         assert(node.getAsConstantUnion() != nullptr || node.getAsSymbolNode() != nullptr);
5179         int nextConst = 0;
5180         return createSpvConstantFromConstUnionArray(node.getType(), node.getAsConstantUnion() ? node.getAsConstantUnion()->getConstArray() : node.getAsSymbolNode()->getConstArray(),
5181                                  nextConst, false);
5182     }
5183
5184     // We now know we have a specialization constant to build
5185
5186     // gl_WorkGroupSize is a special case until the front-end handles hierarchical specialization constants,
5187     // even then, it's specialization ids are handled by special case syntax in GLSL: layout(local_size_x = ...
5188     if (node.getType().getQualifier().builtIn == glslang::EbvWorkGroupSize) {
5189         std::vector<spv::Id> dimConstId;
5190         for (int dim = 0; dim < 3; ++dim) {
5191             bool specConst = (glslangIntermediate->getLocalSizeSpecId(dim) != glslang::TQualifier::layoutNotSet);
5192             dimConstId.push_back(builder.makeUintConstant(glslangIntermediate->getLocalSize(dim), specConst));
5193             if (specConst)
5194                 addDecoration(dimConstId.back(), spv::DecorationSpecId, glslangIntermediate->getLocalSizeSpecId(dim));
5195         }
5196         return builder.makeCompositeConstant(builder.makeVectorType(builder.makeUintType(32), 3), dimConstId, true);
5197     }
5198
5199     // An AST node labelled as specialization constant should be a symbol node.
5200     // Its initializer should either be a sub tree with constant nodes, or a constant union array.
5201     if (auto* sn = node.getAsSymbolNode()) {
5202         if (auto* sub_tree = sn->getConstSubtree()) {
5203             // Traverse the constant constructor sub tree like generating normal run-time instructions.
5204             // During the AST traversal, if the node is marked as 'specConstant', SpecConstantOpModeGuard
5205             // will set the builder into spec constant op instruction generating mode.
5206             sub_tree->traverse(this);
5207             return accessChainLoad(sub_tree->getType());
5208         } else if (auto* const_union_array = &sn->getConstArray()){
5209             int nextConst = 0;
5210             spv::Id id = createSpvConstantFromConstUnionArray(sn->getType(), *const_union_array, nextConst, true);
5211             builder.addName(id, sn->getName().c_str());
5212             return id;
5213         }
5214     }
5215
5216     // Neither a front-end constant node, nor a specialization constant node with constant union array or
5217     // constant sub tree as initializer.
5218     logger->missingFunctionality("Neither a front-end constant nor a spec constant.");
5219     exit(1);
5220     return spv::NoResult;
5221 }
5222
5223 // Use 'consts' as the flattened glslang source of scalar constants to recursively
5224 // build the aggregate SPIR-V constant.
5225 //
5226 // If there are not enough elements present in 'consts', 0 will be substituted;
5227 // an empty 'consts' can be used to create a fully zeroed SPIR-V constant.
5228 //
5229 spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glslang::TType& glslangType, const glslang::TConstUnionArray& consts, int& nextConst, bool specConstant)
5230 {
5231     // vector of constants for SPIR-V
5232     std::vector<spv::Id> spvConsts;
5233
5234     // Type is used for struct and array constants
5235     spv::Id typeId = convertGlslangToSpvType(glslangType);
5236
5237     if (glslangType.isArray()) {
5238         glslang::TType elementType(glslangType, 0);
5239         for (int i = 0; i < glslangType.getOuterArraySize(); ++i)
5240             spvConsts.push_back(createSpvConstantFromConstUnionArray(elementType, consts, nextConst, false));
5241     } else if (glslangType.isMatrix()) {
5242         glslang::TType vectorType(glslangType, 0);
5243         for (int col = 0; col < glslangType.getMatrixCols(); ++col)
5244             spvConsts.push_back(createSpvConstantFromConstUnionArray(vectorType, consts, nextConst, false));
5245     } else if (glslangType.getStruct()) {
5246         glslang::TVector<glslang::TTypeLoc>::const_iterator iter;
5247         for (iter = glslangType.getStruct()->begin(); iter != glslangType.getStruct()->end(); ++iter)
5248             spvConsts.push_back(createSpvConstantFromConstUnionArray(*iter->type, consts, nextConst, false));
5249     } else if (glslangType.getVectorSize() > 1) {
5250         for (unsigned int i = 0; i < (unsigned int)glslangType.getVectorSize(); ++i) {
5251             bool zero = nextConst >= consts.size();
5252             switch (glslangType.getBasicType()) {
5253             case glslang::EbtInt:
5254                 spvConsts.push_back(builder.makeIntConstant(zero ? 0 : consts[nextConst].getIConst()));
5255                 break;
5256             case glslang::EbtUint:
5257                 spvConsts.push_back(builder.makeUintConstant(zero ? 0 : consts[nextConst].getUConst()));
5258                 break;
5259             case glslang::EbtInt64:
5260                 spvConsts.push_back(builder.makeInt64Constant(zero ? 0 : consts[nextConst].getI64Const()));
5261                 break;
5262             case glslang::EbtUint64:
5263                 spvConsts.push_back(builder.makeUint64Constant(zero ? 0 : consts[nextConst].getU64Const()));
5264                 break;
5265             case glslang::EbtFloat:
5266                 spvConsts.push_back(builder.makeFloatConstant(zero ? 0.0F : (float)consts[nextConst].getDConst()));
5267                 break;
5268             case glslang::EbtDouble:
5269                 spvConsts.push_back(builder.makeDoubleConstant(zero ? 0.0 : consts[nextConst].getDConst()));
5270                 break;
5271 #ifdef AMD_EXTENSIONS
5272             case glslang::EbtFloat16:
5273                 spvConsts.push_back(builder.makeFloat16Constant(zero ? 0.0F : (float)consts[nextConst].getDConst()));
5274                 break;
5275 #endif
5276             case glslang::EbtBool:
5277                 spvConsts.push_back(builder.makeBoolConstant(zero ? false : consts[nextConst].getBConst()));
5278                 break;
5279             default:
5280                 assert(0);
5281                 break;
5282             }
5283             ++nextConst;
5284         }
5285     } else {
5286         // we have a non-aggregate (scalar) constant
5287         bool zero = nextConst >= consts.size();
5288         spv::Id scalar = 0;
5289         switch (glslangType.getBasicType()) {
5290         case glslang::EbtInt:
5291             scalar = builder.makeIntConstant(zero ? 0 : consts[nextConst].getIConst(), specConstant);
5292             break;
5293         case glslang::EbtUint:
5294             scalar = builder.makeUintConstant(zero ? 0 : consts[nextConst].getUConst(), specConstant);
5295             break;
5296         case glslang::EbtInt64:
5297             scalar = builder.makeInt64Constant(zero ? 0 : consts[nextConst].getI64Const(), specConstant);
5298             break;
5299         case glslang::EbtUint64:
5300             scalar = builder.makeUint64Constant(zero ? 0 : consts[nextConst].getU64Const(), specConstant);
5301             break;
5302         case glslang::EbtFloat:
5303             scalar = builder.makeFloatConstant(zero ? 0.0F : (float)consts[nextConst].getDConst(), specConstant);
5304             break;
5305         case glslang::EbtDouble:
5306             scalar = builder.makeDoubleConstant(zero ? 0.0 : consts[nextConst].getDConst(), specConstant);
5307             break;
5308 #ifdef AMD_EXTENSIONS
5309         case glslang::EbtFloat16:
5310             scalar = builder.makeFloat16Constant(zero ? 0.0F : (float)consts[nextConst].getDConst(), specConstant);
5311             break;
5312 #endif
5313         case glslang::EbtBool:
5314             scalar = builder.makeBoolConstant(zero ? false : consts[nextConst].getBConst(), specConstant);
5315             break;
5316         default:
5317             assert(0);
5318             break;
5319         }
5320         ++nextConst;
5321         return scalar;
5322     }
5323
5324     return builder.makeCompositeConstant(typeId, spvConsts);
5325 }
5326
5327 // Return true if the node is a constant or symbol whose reading has no
5328 // non-trivial observable cost or effect.
5329 bool TGlslangToSpvTraverser::isTrivialLeaf(const glslang::TIntermTyped* node)
5330 {
5331     // don't know what this is
5332     if (node == nullptr)
5333         return false;
5334
5335     // a constant is safe
5336     if (node->getAsConstantUnion() != nullptr)
5337         return true;
5338
5339     // not a symbol means non-trivial
5340     if (node->getAsSymbolNode() == nullptr)
5341         return false;
5342
5343     // a symbol, depends on what's being read
5344     switch (node->getType().getQualifier().storage) {
5345     case glslang::EvqTemporary:
5346     case glslang::EvqGlobal:
5347     case glslang::EvqIn:
5348     case glslang::EvqInOut:
5349     case glslang::EvqConst:
5350     case glslang::EvqConstReadOnly:
5351     case glslang::EvqUniform:
5352         return true;
5353     default:
5354         return false;
5355     }
5356 }
5357
5358 // A node is trivial if it is a single operation with no side effects.
5359 // Error on the side of saying non-trivial.
5360 // Return true if trivial.
5361 bool TGlslangToSpvTraverser::isTrivial(const glslang::TIntermTyped* node)
5362 {
5363     if (node == nullptr)
5364         return false;
5365
5366     // symbols and constants are trivial
5367     if (isTrivialLeaf(node))
5368         return true;
5369
5370     // otherwise, it needs to be a simple operation or one or two leaf nodes
5371
5372     // not a simple operation
5373     const glslang::TIntermBinary* binaryNode = node->getAsBinaryNode();
5374     const glslang::TIntermUnary* unaryNode = node->getAsUnaryNode();
5375     if (binaryNode == nullptr && unaryNode == nullptr)
5376         return false;
5377
5378     // not on leaf nodes
5379     if (binaryNode && (! isTrivialLeaf(binaryNode->getLeft()) || ! isTrivialLeaf(binaryNode->getRight())))
5380         return false;
5381
5382     if (unaryNode && ! isTrivialLeaf(unaryNode->getOperand())) {
5383         return false;
5384     }
5385
5386     switch (node->getAsOperator()->getOp()) {
5387     case glslang::EOpLogicalNot:
5388     case glslang::EOpConvIntToBool:
5389     case glslang::EOpConvUintToBool:
5390     case glslang::EOpConvFloatToBool:
5391     case glslang::EOpConvDoubleToBool:
5392     case glslang::EOpEqual:
5393     case glslang::EOpNotEqual:
5394     case glslang::EOpLessThan:
5395     case glslang::EOpGreaterThan:
5396     case glslang::EOpLessThanEqual:
5397     case glslang::EOpGreaterThanEqual:
5398     case glslang::EOpIndexDirect:
5399     case glslang::EOpIndexDirectStruct:
5400     case glslang::EOpLogicalXor:
5401     case glslang::EOpAny:
5402     case glslang::EOpAll:
5403         return true;
5404     default:
5405         return false;
5406     }
5407 }
5408
5409 // Emit short-circuiting code, where 'right' is never evaluated unless
5410 // the left side is true (for &&) or false (for ||).
5411 spv::Id TGlslangToSpvTraverser::createShortCircuit(glslang::TOperator op, glslang::TIntermTyped& left, glslang::TIntermTyped& right)
5412 {
5413     spv::Id boolTypeId = builder.makeBoolType();
5414
5415     // emit left operand
5416     builder.clearAccessChain();
5417     left.traverse(this);
5418     spv::Id leftId = accessChainLoad(left.getType());
5419
5420     // Operands to accumulate OpPhi operands
5421     std::vector<spv::Id> phiOperands;
5422     // accumulate left operand's phi information
5423     phiOperands.push_back(leftId);
5424     phiOperands.push_back(builder.getBuildPoint()->getId());
5425
5426     // Make the two kinds of operation symmetric with a "!"
5427     //   || => emit "if (! left) result = right"
5428     //   && => emit "if (  left) result = right"
5429     //
5430     // TODO: this runtime "not" for || could be avoided by adding functionality
5431     // to 'builder' to have an "else" without an "then"
5432     if (op == glslang::EOpLogicalOr)
5433         leftId = builder.createUnaryOp(spv::OpLogicalNot, boolTypeId, leftId);
5434
5435     // make an "if" based on the left value
5436     spv::Builder::If ifBuilder(leftId, builder);
5437
5438     // emit right operand as the "then" part of the "if"
5439     builder.clearAccessChain();
5440     right.traverse(this);
5441     spv::Id rightId = accessChainLoad(right.getType());
5442
5443     // accumulate left operand's phi information
5444     phiOperands.push_back(rightId);
5445     phiOperands.push_back(builder.getBuildPoint()->getId());
5446
5447     // finish the "if"
5448     ifBuilder.makeEndIf();
5449
5450     // phi together the two results
5451     return builder.createOp(spv::OpPhi, boolTypeId, phiOperands);
5452 }
5453
5454 // Return type Id of the imported set of extended instructions corresponds to the name.
5455 // Import this set if it has not been imported yet.
5456 spv::Id TGlslangToSpvTraverser::getExtBuiltins(const char* name)
5457 {
5458     if (extBuiltinMap.find(name) != extBuiltinMap.end())
5459         return extBuiltinMap[name];
5460     else {
5461         builder.addExtension(name);
5462         spv::Id extBuiltins = builder.import(name);
5463         extBuiltinMap[name] = extBuiltins;
5464         return extBuiltins;
5465     }
5466 }
5467
5468 };  // end anonymous namespace
5469
5470 namespace glslang {
5471
5472 void GetSpirvVersion(std::string& version)
5473 {
5474     const int bufSize = 100;
5475     char buf[bufSize];
5476     snprintf(buf, bufSize, "0x%08x, Revision %d", spv::Version, spv::Revision);
5477     version = buf;
5478 }
5479
5480 // Write SPIR-V out to a binary file
5481 void OutputSpvBin(const std::vector<unsigned int>& spirv, const char* baseName)
5482 {
5483     std::ofstream out;
5484     out.open(baseName, std::ios::binary | std::ios::out);
5485     if (out.fail())
5486         printf("ERROR: Failed to open file: %s\n", baseName);
5487     for (int i = 0; i < (int)spirv.size(); ++i) {
5488         unsigned int word = spirv[i];
5489         out.write((const char*)&word, 4);
5490     }
5491     out.close();
5492 }
5493
5494 // Write SPIR-V out to a text file with 32-bit hexadecimal words
5495 void OutputSpvHex(const std::vector<unsigned int>& spirv, const char* baseName, const char* varName)
5496 {
5497     std::ofstream out;
5498     out.open(baseName, std::ios::binary | std::ios::out);
5499     if (out.fail())
5500         printf("ERROR: Failed to open file: %s\n", baseName);
5501     out << "\t// " GLSLANG_REVISION " " GLSLANG_DATE << std::endl;
5502     if (varName != nullptr) {
5503         out << "\t #pragma once" << std::endl;
5504         out << "const uint32_t " << varName << "[] = {" << std::endl;
5505     }
5506     const int WORDS_PER_LINE = 8;
5507     for (int i = 0; i < (int)spirv.size(); i += WORDS_PER_LINE) {
5508         out << "\t";
5509         for (int j = 0; j < WORDS_PER_LINE && i + j < (int)spirv.size(); ++j) {
5510             const unsigned int word = spirv[i + j];
5511             out << "0x" << std::hex << std::setw(8) << std::setfill('0') << word;
5512             if (i + j + 1 < (int)spirv.size()) {
5513                 out << ",";
5514             }
5515         }
5516         out << std::endl;
5517     }
5518     if (varName != nullptr) {
5519         out << "};";
5520     }
5521     out.close();
5522 }
5523
5524 //
5525 // Set up the glslang traversal
5526 //
5527 void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv)
5528 {
5529     spv::SpvBuildLogger logger;
5530     GlslangToSpv(intermediate, spirv, &logger);
5531 }
5532
5533 void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv, spv::SpvBuildLogger* logger)
5534 {
5535     TIntermNode* root = intermediate.getTreeRoot();
5536
5537     if (root == 0)
5538         return;
5539
5540     glslang::GetThreadPoolAllocator().push();
5541
5542     TGlslangToSpvTraverser it(&intermediate, logger);
5543     root->traverse(&it);
5544     it.finishSpv();
5545     it.dumpSpv(spirv);
5546
5547     glslang::GetThreadPoolAllocator().pop();
5548 }
5549
5550 }; // end namespace glslang