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