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