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