9bee407c21b6d48532a81f08090c4810a0053fba
[platform/upstream/glslang.git] / SPIRV / GlslangToSpv.cpp
1 //
2 //Copyright (C) 2014 LunarG, Inc.
3 //
4 //All rights reserved.
5 //
6 //Redistribution and use in source and binary forms, with or without
7 //modification, are permitted provided that the following conditions
8 //are met:
9 //
10 //    Redistributions of source code must retain the above copyright
11 //    notice, this list of conditions and the following disclaimer.
12 //
13 //    Redistributions in binary form must reproduce the above
14 //    copyright notice, this list of conditions and the following
15 //    disclaimer in the documentation and/or other materials provided
16 //    with the distribution.
17 //
18 //    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
19 //    contributors may be used to endorse or promote products derived
20 //    from this software without specific prior written permission.
21 //
22 //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 //"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 //LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 //FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 //COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 //INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 //BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 //LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30 //CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 //LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32 //ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 //POSSIBILITY OF SUCH DAMAGE.
34
35 //
36 // Author: John Kessenich, LunarG
37 //
38 // Visit the nodes in the glslang intermediate tree representation to
39 // translate them to SPIR-V.
40 //
41
42 #include "spirv.hpp"
43 #include "GlslangToSpv.h"
44 #include "SpvBuilder.h"
45 namespace spv {
46    #include "GLSL.std.450.h"
47 }
48
49 // Glslang includes
50 #include "../glslang/MachineIndependent/localintermediate.h"
51 #include "../glslang/MachineIndependent/SymbolTable.h"
52 #include "../glslang/Include/Common.h"
53
54 #include <string>
55 #include <map>
56 #include <list>
57 #include <vector>
58 #include <stack>
59 #include <fstream>
60
61 namespace {
62
63 // For low-order part of the generator's magic number. Bump up
64 // when there is a change in the style (e.g., if SSA form changes,
65 // or a different instruction sequence to do something gets used).
66 const int GeneratorVersion = 1;
67
68 //
69 // The main holder of information for translating glslang to SPIR-V.
70 //
71 // Derives from the AST walking base class.
72 //
73 class TGlslangToSpvTraverser : public glslang::TIntermTraverser {
74 public:
75     TGlslangToSpvTraverser(const glslang::TIntermediate*);
76     virtual ~TGlslangToSpvTraverser();
77
78     bool visitAggregate(glslang::TVisit, glslang::TIntermAggregate*);
79     bool visitBinary(glslang::TVisit, glslang::TIntermBinary*);
80     void visitConstantUnion(glslang::TIntermConstantUnion*);
81     bool visitSelection(glslang::TVisit, glslang::TIntermSelection*);
82     bool visitSwitch(glslang::TVisit, glslang::TIntermSwitch*);
83     void visitSymbol(glslang::TIntermSymbol* symbol);
84     bool visitUnary(glslang::TVisit, glslang::TIntermUnary*);
85     bool visitLoop(glslang::TVisit, glslang::TIntermLoop*);
86     bool visitBranch(glslang::TVisit visit, glslang::TIntermBranch*);
87
88     void dumpSpv(std::vector<unsigned int>& out);
89
90 protected:
91     spv::Id createSpvVariable(const glslang::TIntermSymbol*);
92     spv::Id getSampledType(const glslang::TSampler&);
93     spv::Id convertGlslangToSpvType(const glslang::TType& type);
94     spv::Id convertGlslangToSpvType(const glslang::TType& type, glslang::TLayoutPacking, const glslang::TQualifier&);
95     glslang::TLayoutPacking getExplicitLayout(const glslang::TType& type) const;
96     int getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking, glslang::TLayoutMatrix);
97     int getMatrixStride(const glslang::TType& matrixType, glslang::TLayoutPacking, glslang::TLayoutMatrix);
98     void updateMemberOffset(const glslang::TType& structType, const glslang::TType& memberType, int& currentOffset, int& nextOffset, glslang::TLayoutPacking, glslang::TLayoutMatrix);
99
100     bool isShaderEntrypoint(const glslang::TIntermAggregate* node);
101     void makeFunctions(const glslang::TIntermSequence&);
102     void makeGlobalInitializers(const glslang::TIntermSequence&);
103     void visitFunctions(const glslang::TIntermSequence&);
104     void handleFunctionEntry(const glslang::TIntermAggregate* node);
105     void translateArguments(const glslang::TIntermAggregate& node, std::vector<spv::Id>& arguments);
106     void translateArguments(glslang::TIntermUnary& node, std::vector<spv::Id>& arguments);
107     spv::Id createImageTextureFunctionCall(glslang::TIntermOperator* node);
108     spv::Id handleUserFunctionCall(const glslang::TIntermAggregate*);
109
110     spv::Id createBinaryOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, spv::Id left, spv::Id right, glslang::TBasicType typeProxy, bool reduceComparison = true);
111     spv::Id createBinaryMatrixOperation(spv::Op, spv::Decoration precision, spv::Id typeId, spv::Id left, spv::Id right);
112     spv::Id createUnaryOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, spv::Id operand,glslang::TBasicType typeProxy);
113     spv::Id createConversion(glslang::TOperator op, spv::Decoration precision, spv::Id destTypeId, spv::Id operand);
114     spv::Id makeSmearedConstant(spv::Id constant, int vectorSize);
115     spv::Id createAtomicOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy);
116     spv::Id createMiscOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy);
117     spv::Id createNoArgOperation(glslang::TOperator op);
118     spv::Id getSymbolId(const glslang::TIntermSymbol* node);
119     void addDecoration(spv::Id id, spv::Decoration dec);
120     void addDecoration(spv::Id id, spv::Decoration dec, unsigned value);
121     void addMemberDecoration(spv::Id id, int member, spv::Decoration dec);
122     spv::Id createSpvSpecConstant(const glslang::TIntermTyped&);
123     spv::Id createSpvConstant(const glslang::TType& type, const glslang::TConstUnionArray&, int& nextConst, bool specConstant);
124     bool isTrivialLeaf(const glslang::TIntermTyped* node);
125     bool isTrivial(const glslang::TIntermTyped* node);
126     spv::Id createShortCircuit(glslang::TOperator, glslang::TIntermTyped& left, glslang::TIntermTyped& right);
127
128     spv::Function* shaderEntry;
129     spv::Instruction* entryPoint;
130     int sequenceDepth;
131
132     // There is a 1:1 mapping between a spv builder and a module; this is thread safe
133     spv::Builder builder;
134     bool inMain;
135     bool mainTerminated;
136     bool linkageOnly;                  // true when visiting the set of objects in the AST present only for establishing interface, whether or not they were statically used
137     std::set<spv::Id> iOSet;           // all input/output variables from either static use or declaration of interface
138     const glslang::TIntermediate* glslangIntermediate;
139     spv::Id stdBuiltins;
140
141     std::unordered_map<int, spv::Id> symbolValues;
142     std::unordered_set<int> constReadOnlyParameters;  // set of formal function parameters that have glslang qualifier constReadOnly, so we know they are not local function "const" that are write-once
143     std::unordered_map<std::string, spv::Function*> functionMap;
144     std::unordered_map<const glslang::TTypeList*, spv::Id> structMap[glslang::ElpCount][glslang::ElmCount];
145     std::unordered_map<const glslang::TTypeList*, std::vector<int> > memberRemapper;  // for mapping glslang block indices to spv indices (e.g., due to hidden members)
146     std::stack<bool> breakForLoop;  // false means break for switch
147 };
148
149 //
150 // Helper functions for translating glslang representations to SPIR-V enumerants.
151 //
152
153 // Translate glslang profile to SPIR-V source language.
154 spv::SourceLanguage TranslateSourceLanguage(EProfile profile)
155 {
156     switch (profile) {
157     case ENoProfile:
158     case ECoreProfile:
159     case ECompatibilityProfile:
160         return spv::SourceLanguageGLSL;
161     case EEsProfile:
162         return spv::SourceLanguageESSL;
163     default:
164         return spv::SourceLanguageUnknown;
165     }
166 }
167
168 // Translate glslang language (stage) to SPIR-V execution model.
169 spv::ExecutionModel TranslateExecutionModel(EShLanguage stage)
170 {
171     switch (stage) {
172     case EShLangVertex:           return spv::ExecutionModelVertex;
173     case EShLangTessControl:      return spv::ExecutionModelTessellationControl;
174     case EShLangTessEvaluation:   return spv::ExecutionModelTessellationEvaluation;
175     case EShLangGeometry:         return spv::ExecutionModelGeometry;
176     case EShLangFragment:         return spv::ExecutionModelFragment;
177     case EShLangCompute:          return spv::ExecutionModelGLCompute;
178     default:
179         assert(0);
180         return spv::ExecutionModelFragment;
181     }
182 }
183
184 // Translate glslang type to SPIR-V storage class.
185 spv::StorageClass TranslateStorageClass(const glslang::TType& type)
186 {
187     if (type.getQualifier().isPipeInput())
188         return spv::StorageClassInput;
189     else if (type.getQualifier().isPipeOutput())
190         return spv::StorageClassOutput;
191     else if (type.getQualifier().isUniformOrBuffer()) {
192         if (type.getBasicType() == glslang::EbtBlock)
193             return spv::StorageClassUniform;
194         else if (type.getBasicType() == glslang::EbtAtomicUint)
195             return spv::StorageClassAtomicCounter;
196         else
197             return spv::StorageClassUniformConstant;
198         // TODO: how are we distuingishing between default and non-default non-writable uniforms?  Do default uniforms even exist?
199     } else {
200         switch (type.getQualifier().storage) {
201         case glslang::EvqShared:        return spv::StorageClassWorkgroup;  break;
202         case glslang::EvqGlobal:        return spv::StorageClassPrivate;
203         case glslang::EvqConstReadOnly: return spv::StorageClassFunction;
204         case glslang::EvqTemporary:     return spv::StorageClassFunction;
205         default: 
206             assert(0);
207             return spv::StorageClassFunction;
208         }
209     }
210 }
211
212 // Translate glslang sampler type to SPIR-V dimensionality.
213 spv::Dim TranslateDimensionality(const glslang::TSampler& sampler)
214 {
215     switch (sampler.dim) {
216     case glslang::Esd1D:      return spv::Dim1D;
217     case glslang::Esd2D:      return spv::Dim2D;
218     case glslang::Esd3D:      return spv::Dim3D;
219     case glslang::EsdCube:    return spv::DimCube;
220     case glslang::EsdRect:    return spv::DimRect;
221     case glslang::EsdBuffer:  return spv::DimBuffer;
222     default:
223         assert(0);
224         return spv::Dim2D;
225     }
226 }
227
228 // Translate glslang type to SPIR-V precision decorations.
229 spv::Decoration TranslatePrecisionDecoration(const glslang::TType& type)
230 {
231     switch (type.getQualifier().precision) {
232     case glslang::EpqLow:    return spv::DecorationRelaxedPrecision;
233     case glslang::EpqMedium: return spv::DecorationRelaxedPrecision;
234     case glslang::EpqHigh:   return spv::NoPrecision;
235     default:
236         return spv::NoPrecision;
237     }
238 }
239
240 // Translate glslang type to SPIR-V block decorations.
241 spv::Decoration TranslateBlockDecoration(const glslang::TType& type)
242 {
243     if (type.getBasicType() == glslang::EbtBlock) {
244         switch (type.getQualifier().storage) {
245         case glslang::EvqUniform:      return spv::DecorationBlock;
246         case glslang::EvqBuffer:       return spv::DecorationBufferBlock;
247         case glslang::EvqVaryingIn:    return spv::DecorationBlock;
248         case glslang::EvqVaryingOut:   return spv::DecorationBlock;
249         default:
250             assert(0);
251             break;
252         }
253     }
254
255     return (spv::Decoration)spv::BadValue;
256 }
257
258 // Translate glslang type to SPIR-V layout decorations.
259 spv::Decoration TranslateLayoutDecoration(const glslang::TType& type, glslang::TLayoutMatrix matrixLayout)
260 {
261     if (type.isMatrix()) {
262         switch (matrixLayout) {
263         case glslang::ElmRowMajor:
264             return spv::DecorationRowMajor;
265         case glslang::ElmColumnMajor:
266             return spv::DecorationColMajor;
267         default:
268             // opaque layouts don't need a majorness
269             return (spv::Decoration)spv::BadValue;
270         }
271     } else {
272         switch (type.getBasicType()) {
273         default:
274             return (spv::Decoration)spv::BadValue;
275             break;
276         case glslang::EbtBlock:
277             switch (type.getQualifier().storage) {
278             case glslang::EvqUniform:
279             case glslang::EvqBuffer:
280                 switch (type.getQualifier().layoutPacking) {
281                 case glslang::ElpShared:  return spv::DecorationGLSLShared;
282                 case glslang::ElpPacked:  return spv::DecorationGLSLPacked;
283                 default:
284                     return (spv::Decoration)spv::BadValue;
285                 }
286             case glslang::EvqVaryingIn:
287             case glslang::EvqVaryingOut:
288                 assert(type.getQualifier().layoutPacking == glslang::ElpNone);
289                 return (spv::Decoration)spv::BadValue;
290             default:
291                 assert(0);
292                 return (spv::Decoration)spv::BadValue;
293             }
294         }
295     }
296 }
297
298 // Translate glslang type to SPIR-V interpolation decorations.
299 // Returns spv::Decoration(spv::BadValue) when no decoration
300 // should be applied.
301 spv::Decoration TranslateInterpolationDecoration(const glslang::TQualifier& qualifier)
302 {
303     if (qualifier.smooth) {
304         // Smooth decoration doesn't exist in SPIR-V 1.0
305         return (spv::Decoration)spv::BadValue;
306     }
307     if (qualifier.nopersp)
308         return spv::DecorationNoPerspective;
309     else if (qualifier.patch)
310         return spv::DecorationPatch;
311     else if (qualifier.flat)
312         return spv::DecorationFlat;
313     else if (qualifier.centroid)
314         return spv::DecorationCentroid;
315     else if (qualifier.sample)
316         return spv::DecorationSample;
317     else
318         return (spv::Decoration)spv::BadValue;
319 }
320
321 // If glslang type is invaraiant, return SPIR-V invariant decoration.
322 spv::Decoration TranslateInvariantDecoration(const glslang::TQualifier& qualifier)
323 {
324     if (qualifier.invariant)
325         return spv::DecorationInvariant;
326     else
327         return (spv::Decoration)spv::BadValue;
328 }
329
330 // Translate glslang built-in variable to SPIR-V built in decoration.
331 spv::BuiltIn TranslateBuiltInDecoration(glslang::TBuiltInVariable builtIn)
332 {
333     switch (builtIn) {
334     case glslang::EbvPosition:             return spv::BuiltInPosition;
335     case glslang::EbvPointSize:            return spv::BuiltInPointSize;
336     case glslang::EbvClipDistance:         return spv::BuiltInClipDistance;
337     case glslang::EbvCullDistance:         return spv::BuiltInCullDistance;
338     case glslang::EbvVertexId:             return spv::BuiltInVertexId;
339     case glslang::EbvInstanceId:           return spv::BuiltInInstanceId;
340     case glslang::EbvBaseVertex:
341     case glslang::EbvBaseInstance:
342     case glslang::EbvDrawId:
343         // TODO: Add SPIR-V builtin ID.
344         spv::MissingFunctionality("Draw parameters");
345         return (spv::BuiltIn)spv::BadValue;
346     case glslang::EbvPrimitiveId:          return spv::BuiltInPrimitiveId;
347     case glslang::EbvInvocationId:         return spv::BuiltInInvocationId;
348     case glslang::EbvLayer:                return spv::BuiltInLayer;
349     case glslang::EbvViewportIndex:        return spv::BuiltInViewportIndex;
350     case glslang::EbvTessLevelInner:       return spv::BuiltInTessLevelInner;
351     case glslang::EbvTessLevelOuter:       return spv::BuiltInTessLevelOuter;
352     case glslang::EbvTessCoord:            return spv::BuiltInTessCoord;
353     case glslang::EbvPatchVertices:        return spv::BuiltInPatchVertices;
354     case glslang::EbvFragCoord:            return spv::BuiltInFragCoord;
355     case glslang::EbvPointCoord:           return spv::BuiltInPointCoord;
356     case glslang::EbvFace:                 return spv::BuiltInFrontFacing;
357     case glslang::EbvSampleId:             return spv::BuiltInSampleId;
358     case glslang::EbvSamplePosition:       return spv::BuiltInSamplePosition;
359     case glslang::EbvSampleMask:           return spv::BuiltInSampleMask;
360     case glslang::EbvFragDepth:            return spv::BuiltInFragDepth;
361     case glslang::EbvHelperInvocation:     return spv::BuiltInHelperInvocation;
362     case glslang::EbvNumWorkGroups:        return spv::BuiltInNumWorkgroups;
363     case glslang::EbvWorkGroupSize:        return spv::BuiltInWorkgroupSize;
364     case glslang::EbvWorkGroupId:          return spv::BuiltInWorkgroupId;
365     case glslang::EbvLocalInvocationId:    return spv::BuiltInLocalInvocationId;
366     case glslang::EbvLocalInvocationIndex: return spv::BuiltInLocalInvocationIndex;
367     case glslang::EbvGlobalInvocationId:   return spv::BuiltInGlobalInvocationId;
368     default:                               return (spv::BuiltIn)spv::BadValue;
369     }
370 }
371
372 // Translate glslang image layout format to SPIR-V image format.
373 spv::ImageFormat TranslateImageFormat(const glslang::TType& type)
374 {
375     assert(type.getBasicType() == glslang::EbtSampler);
376
377     switch (type.getQualifier().layoutFormat) {
378     case glslang::ElfNone:          return spv::ImageFormatUnknown;
379     case glslang::ElfRgba32f:       return spv::ImageFormatRgba32f;
380     case glslang::ElfRgba16f:       return spv::ImageFormatRgba16f;
381     case glslang::ElfR32f:          return spv::ImageFormatR32f;
382     case glslang::ElfRgba8:         return spv::ImageFormatRgba8;
383     case glslang::ElfRgba8Snorm:    return spv::ImageFormatRgba8Snorm;
384     case glslang::ElfRg32f:         return spv::ImageFormatRg32f;
385     case glslang::ElfRg16f:         return spv::ImageFormatRg16f;
386     case glslang::ElfR11fG11fB10f:  return spv::ImageFormatR11fG11fB10f;
387     case glslang::ElfR16f:          return spv::ImageFormatR16f;
388     case glslang::ElfRgba16:        return spv::ImageFormatRgba16;
389     case glslang::ElfRgb10A2:       return spv::ImageFormatRgb10A2;
390     case glslang::ElfRg16:          return spv::ImageFormatRg16;
391     case glslang::ElfRg8:           return spv::ImageFormatRg8;
392     case glslang::ElfR16:           return spv::ImageFormatR16;
393     case glslang::ElfR8:            return spv::ImageFormatR8;
394     case glslang::ElfRgba16Snorm:   return spv::ImageFormatRgba16Snorm;
395     case glslang::ElfRg16Snorm:     return spv::ImageFormatRg16Snorm;
396     case glslang::ElfRg8Snorm:      return spv::ImageFormatRg8Snorm;
397     case glslang::ElfR16Snorm:      return spv::ImageFormatR16Snorm;
398     case glslang::ElfR8Snorm:       return spv::ImageFormatR8Snorm;
399     case glslang::ElfRgba32i:       return spv::ImageFormatRgba32i;
400     case glslang::ElfRgba16i:       return spv::ImageFormatRgba16i;
401     case glslang::ElfRgba8i:        return spv::ImageFormatRgba8i;
402     case glslang::ElfR32i:          return spv::ImageFormatR32i;
403     case glslang::ElfRg32i:         return spv::ImageFormatRg32i;
404     case glslang::ElfRg16i:         return spv::ImageFormatRg16i;
405     case glslang::ElfRg8i:          return spv::ImageFormatRg8i;
406     case glslang::ElfR16i:          return spv::ImageFormatR16i;
407     case glslang::ElfR8i:           return spv::ImageFormatR8i;
408     case glslang::ElfRgba32ui:      return spv::ImageFormatRgba32ui;
409     case glslang::ElfRgba16ui:      return spv::ImageFormatRgba16ui;
410     case glslang::ElfRgba8ui:       return spv::ImageFormatRgba8ui;
411     case glslang::ElfR32ui:         return spv::ImageFormatR32ui;
412     case glslang::ElfRg32ui:        return spv::ImageFormatRg32ui;
413     case glslang::ElfRg16ui:        return spv::ImageFormatRg16ui;
414     case glslang::ElfRgb10a2ui:     return spv::ImageFormatRgb10a2ui;
415     case glslang::ElfRg8ui:         return spv::ImageFormatRg8ui;
416     case glslang::ElfR16ui:         return spv::ImageFormatR16ui;
417     case glslang::ElfR8ui:          return spv::ImageFormatR8ui;
418     default:                        return (spv::ImageFormat)spv::BadValue;
419     }
420 }
421
422 void InheritQualifiers(glslang::TQualifier& child, const glslang::TQualifier& parent)
423 {
424     if (child.layoutMatrix == glslang::ElmNone)
425         child.layoutMatrix = parent.layoutMatrix;
426
427     if (parent.invariant)
428         child.invariant = true;
429     if (parent.nopersp)
430         child.nopersp = true;
431     if (parent.flat)
432         child.flat = true;
433     if (parent.centroid)
434         child.centroid = true;
435     if (parent.patch)
436         child.patch = true;
437     if (parent.sample)
438         child.sample = true;
439 }
440
441 bool HasNonLayoutQualifiers(const glslang::TQualifier& qualifier)
442 {
443     // This should list qualifiers that simultaneous satisify:
444     // - struct members can inherit from a struct declaration
445     // - effect decorations on the struct members (note smooth does not, and expecting something like volatile to effect the whole object)
446     // - are not part of the offset/st430/etc or row/column-major layout
447     return qualifier.invariant || qualifier.nopersp || qualifier.flat || qualifier.centroid || qualifier.patch || qualifier.sample;
448 }
449
450 //
451 // Implement the TGlslangToSpvTraverser class.
452 //
453
454 TGlslangToSpvTraverser::TGlslangToSpvTraverser(const glslang::TIntermediate* glslangIntermediate)
455     : TIntermTraverser(true, false, true), shaderEntry(0), sequenceDepth(0),
456       builder((glslang::GetKhronosToolId() << 16) | GeneratorVersion),
457       inMain(false), mainTerminated(false), linkageOnly(false),
458       glslangIntermediate(glslangIntermediate)
459 {
460     spv::ExecutionModel executionModel = TranslateExecutionModel(glslangIntermediate->getStage());
461
462     builder.clearAccessChain();
463     builder.setSource(TranslateSourceLanguage(glslangIntermediate->getProfile()), glslangIntermediate->getVersion());
464     stdBuiltins = builder.import("GLSL.std.450");
465     builder.setMemoryModel(spv::AddressingModelLogical, spv::MemoryModelGLSL450);
466     shaderEntry = builder.makeMain();
467     entryPoint = builder.addEntryPoint(executionModel, shaderEntry, "main");
468
469     // Add the source extensions
470     const auto& sourceExtensions = glslangIntermediate->getRequestedExtensions();
471     for (auto it = sourceExtensions.begin(); it != sourceExtensions.end(); ++it)
472         builder.addSourceExtension(it->c_str());
473
474     // Add the top-level modes for this shader.
475
476     if (glslangIntermediate->getXfbMode())
477         builder.addExecutionMode(shaderEntry, spv::ExecutionModeXfb);
478
479     unsigned int mode;
480     switch (glslangIntermediate->getStage()) {
481     case EShLangVertex:
482         builder.addCapability(spv::CapabilityShader);
483         break;
484
485     case EShLangTessControl:
486         builder.addCapability(spv::CapabilityTessellation);
487         builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, glslangIntermediate->getVertices());
488         break;
489
490     case EShLangTessEvaluation:
491         builder.addCapability(spv::CapabilityTessellation);
492         switch (glslangIntermediate->getInputPrimitive()) {
493         case glslang::ElgTriangles:           mode = spv::ExecutionModeTriangles;     break;
494         case glslang::ElgQuads:               mode = spv::ExecutionModeQuads;         break;
495         case glslang::ElgIsolines:            mode = spv::ExecutionModeIsolines;      break;
496         default:                              mode = spv::BadValue;                        break;
497         }
498         if (mode != spv::BadValue)
499             builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode);
500
501         switch (glslangIntermediate->getVertexSpacing()) {
502         case glslang::EvsEqual:            mode = spv::ExecutionModeSpacingEqual;          break;
503         case glslang::EvsFractionalEven:   mode = spv::ExecutionModeSpacingFractionalEven; break;
504         case glslang::EvsFractionalOdd:    mode = spv::ExecutionModeSpacingFractionalOdd;  break;
505         default:                           mode = spv::BadValue;                           break;
506         }
507         if (mode != spv::BadValue)
508             builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode);
509
510         switch (glslangIntermediate->getVertexOrder()) {
511         case glslang::EvoCw:     mode = spv::ExecutionModeVertexOrderCw;  break;
512         case glslang::EvoCcw:    mode = spv::ExecutionModeVertexOrderCcw; break;
513         default:                 mode = spv::BadValue;                    break;
514         }
515         if (mode != spv::BadValue)
516             builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode);
517
518         if (glslangIntermediate->getPointMode())
519             builder.addExecutionMode(shaderEntry, spv::ExecutionModePointMode);
520         break;
521
522     case EShLangGeometry:
523         builder.addCapability(spv::CapabilityGeometry);
524         switch (glslangIntermediate->getInputPrimitive()) {
525         case glslang::ElgPoints:             mode = spv::ExecutionModeInputPoints;             break;
526         case glslang::ElgLines:              mode = spv::ExecutionModeInputLines;              break;
527         case glslang::ElgLinesAdjacency:     mode = spv::ExecutionModeInputLinesAdjacency;     break;
528         case glslang::ElgTriangles:          mode = spv::ExecutionModeTriangles;               break;
529         case glslang::ElgTrianglesAdjacency: mode = spv::ExecutionModeInputTrianglesAdjacency; break;
530         default:                             mode = spv::BadValue;         break;
531         }
532         if (mode != spv::BadValue)
533             builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode);
534
535         builder.addExecutionMode(shaderEntry, spv::ExecutionModeInvocations, glslangIntermediate->getInvocations());
536
537         switch (glslangIntermediate->getOutputPrimitive()) {
538         case glslang::ElgPoints:        mode = spv::ExecutionModeOutputPoints;                 break;
539         case glslang::ElgLineStrip:     mode = spv::ExecutionModeOutputLineStrip;              break;
540         case glslang::ElgTriangleStrip: mode = spv::ExecutionModeOutputTriangleStrip;          break;
541         default:                        mode = spv::BadValue;              break;
542         }
543         if (mode != spv::BadValue)
544             builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode);
545         builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, glslangIntermediate->getVertices());
546         break;
547
548     case EShLangFragment:
549         builder.addCapability(spv::CapabilityShader);
550         if (glslangIntermediate->getPixelCenterInteger())
551             builder.addExecutionMode(shaderEntry, spv::ExecutionModePixelCenterInteger);
552
553         if (glslangIntermediate->getOriginUpperLeft())
554             builder.addExecutionMode(shaderEntry, spv::ExecutionModeOriginUpperLeft);
555         else
556             builder.addExecutionMode(shaderEntry, spv::ExecutionModeOriginLowerLeft);
557
558         if (glslangIntermediate->getEarlyFragmentTests())
559             builder.addExecutionMode(shaderEntry, spv::ExecutionModeEarlyFragmentTests);
560
561         switch(glslangIntermediate->getDepth()) {
562         case glslang::EldGreater:  mode = spv::ExecutionModeDepthGreater; break;
563         case glslang::EldLess:     mode = spv::ExecutionModeDepthLess;    break;
564         default:                   mode = spv::BadValue;                  break;
565         }
566         if (mode != spv::BadValue)
567             builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode);
568
569         if (glslangIntermediate->getDepth() != glslang::EldUnchanged && glslangIntermediate->isDepthReplacing())
570             builder.addExecutionMode(shaderEntry, spv::ExecutionModeDepthReplacing);
571         break;
572
573     case EShLangCompute:
574         builder.addCapability(spv::CapabilityShader);
575         builder.addExecutionMode(shaderEntry, spv::ExecutionModeLocalSize, glslangIntermediate->getLocalSize(0),
576                                                                            glslangIntermediate->getLocalSize(1),
577                                                                            glslangIntermediate->getLocalSize(2));
578         break;
579
580     default:
581         break;
582     }
583
584 }
585
586 // Finish everything and dump
587 void TGlslangToSpvTraverser::dumpSpv(std::vector<unsigned int>& out)
588 {
589     // finish off the entry-point SPV instruction by adding the Input/Output <id>
590     for (auto it : iOSet)
591         entryPoint->addIdOperand(it);
592
593     builder.dump(out);
594 }
595
596 TGlslangToSpvTraverser::~TGlslangToSpvTraverser()
597 {
598     if (! mainTerminated) {
599         spv::Block* lastMainBlock = shaderEntry->getLastBlock();
600         builder.setBuildPoint(lastMainBlock);
601         builder.leaveFunction();
602     }
603 }
604
605 //
606 // Implement the traversal functions.
607 //
608 // Return true from interior nodes to have the external traversal
609 // continue on to children.  Return false if children were
610 // already processed.
611 //
612
613 //
614 // Symbols can turn into 
615 //  - uniform/input reads
616 //  - output writes
617 //  - complex lvalue base setups:  foo.bar[3]....  , where we see foo and start up an access chain
618 //  - something simple that degenerates into the last bullet
619 //
620 void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol)
621 {
622     // getSymbolId() will set up all the IO decorations on the first call.
623     // Formal function parameters were mapped during makeFunctions().
624     spv::Id id = getSymbolId(symbol);
625
626     // Include all "static use" and "linkage only" interface variables on the OpEntryPoint instruction
627     if (builder.isPointer(id)) {
628         spv::StorageClass sc = builder.getStorageClass(id);
629         if (sc == spv::StorageClassInput || sc == spv::StorageClassOutput)
630             iOSet.insert(id);
631     }
632
633     // Only process non-linkage-only nodes for generating actual static uses
634     if (! linkageOnly) {
635         // Prepare to generate code for the access
636
637         // L-value chains will be computed left to right.  We're on the symbol now,
638         // which is the left-most part of the access chain, so now is "clear" time,
639         // followed by setting the base.
640         builder.clearAccessChain();
641
642         // For now, we consider all user variables as being in memory, so they are pointers,
643         // except for "const in" arguments to a function, which are an intermediate object.
644         // See comments in handleUserFunctionCall().
645         glslang::TStorageQualifier qualifier = symbol->getQualifier().storage;
646         if (qualifier == glslang::EvqConstReadOnly && constReadOnlyParameters.find(symbol->getId()) != constReadOnlyParameters.end())
647             builder.setAccessChainRValue(id);
648         else
649             builder.setAccessChainLValue(id);
650     }
651 }
652
653 bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::TIntermBinary* node)
654 {
655     // First, handle special cases
656     switch (node->getOp()) {
657     case glslang::EOpAssign:
658     case glslang::EOpAddAssign:
659     case glslang::EOpSubAssign:
660     case glslang::EOpMulAssign:
661     case glslang::EOpVectorTimesMatrixAssign:
662     case glslang::EOpVectorTimesScalarAssign:
663     case glslang::EOpMatrixTimesScalarAssign:
664     case glslang::EOpMatrixTimesMatrixAssign:
665     case glslang::EOpDivAssign:
666     case glslang::EOpModAssign:
667     case glslang::EOpAndAssign:
668     case glslang::EOpInclusiveOrAssign:
669     case glslang::EOpExclusiveOrAssign:
670     case glslang::EOpLeftShiftAssign:
671     case glslang::EOpRightShiftAssign:
672         // A bin-op assign "a += b" means the same thing as "a = a + b"
673         // where a is evaluated before b. For a simple assignment, GLSL
674         // says to evaluate the left before the right.  So, always, left
675         // node then right node.
676         {
677             // get the left l-value, save it away
678             builder.clearAccessChain();
679             node->getLeft()->traverse(this);
680             spv::Builder::AccessChain lValue = builder.getAccessChain();
681
682             // evaluate the right
683             builder.clearAccessChain();
684             node->getRight()->traverse(this);
685             spv::Id rValue = builder.accessChainLoad(convertGlslangToSpvType(node->getRight()->getType()));
686
687             if (node->getOp() != glslang::EOpAssign) {
688                 // the left is also an r-value
689                 builder.setAccessChain(lValue);
690                 spv::Id leftRValue = builder.accessChainLoad(convertGlslangToSpvType(node->getLeft()->getType()));
691
692                 // do the operation
693                 rValue = createBinaryOperation(node->getOp(), TranslatePrecisionDecoration(node->getType()), 
694                                                convertGlslangToSpvType(node->getType()), leftRValue, rValue,
695                                                node->getType().getBasicType());
696
697                 // these all need their counterparts in createBinaryOperation()
698                 assert(rValue != spv::NoResult);
699             }
700
701             // store the result
702             builder.setAccessChain(lValue);
703             builder.accessChainStore(rValue);
704
705             // assignments are expressions having an rValue after they are evaluated...
706             builder.clearAccessChain();
707             builder.setAccessChainRValue(rValue);
708         }
709         return false;
710     case glslang::EOpIndexDirect:
711     case glslang::EOpIndexDirectStruct:
712         {
713             // Get the left part of the access chain.
714             node->getLeft()->traverse(this);
715
716             // Add the next element in the chain
717
718             int index = node->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst();
719             if (node->getLeft()->getBasicType() == glslang::EbtBlock && node->getOp() == glslang::EOpIndexDirectStruct) {
720                 // This may be, e.g., an anonymous block-member selection, which generally need
721                 // index remapping due to hidden members in anonymous blocks.
722                 std::vector<int>& remapper = memberRemapper[node->getLeft()->getType().getStruct()];
723                 assert(remapper.size() > 0);
724                 index = remapper[index];
725             }
726
727             if (! node->getLeft()->getType().isArray() &&
728                 node->getLeft()->getType().isVector() &&
729                 node->getOp() == glslang::EOpIndexDirect) {
730                 // This is essentially a hard-coded vector swizzle of size 1,
731                 // so short circuit the access-chain stuff with a swizzle.
732                 std::vector<unsigned> swizzle;
733                 swizzle.push_back(node->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst());
734                 builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType()));
735             } else {
736                 // normal case for indexing array or structure or block
737                 builder.accessChainPush(builder.makeIntConstant(index));
738             }
739         }
740         return false;
741     case glslang::EOpIndexIndirect:
742         {
743             // Structure or array or vector indirection.
744             // Will use native SPIR-V access-chain for struct and array indirection;
745             // matrices are arrays of vectors, so will also work for a matrix.
746             // Will use the access chain's 'component' for variable index into a vector.
747
748             // This adapter is building access chains left to right.
749             // Set up the access chain to the left.
750             node->getLeft()->traverse(this);
751
752             // save it so that computing the right side doesn't trash it
753             spv::Builder::AccessChain partial = builder.getAccessChain();
754
755             // compute the next index in the chain
756             builder.clearAccessChain();
757             node->getRight()->traverse(this);
758             spv::Id index = builder.accessChainLoad(convertGlslangToSpvType(node->getRight()->getType()));
759
760             // restore the saved access chain
761             builder.setAccessChain(partial);
762
763             if (! node->getLeft()->getType().isArray() && node->getLeft()->getType().isVector())
764                 builder.accessChainPushComponent(index, convertGlslangToSpvType(node->getLeft()->getType()));
765             else
766                 builder.accessChainPush(index);
767         }
768         return false;
769     case glslang::EOpVectorSwizzle:
770         {
771             node->getLeft()->traverse(this);
772             glslang::TIntermSequence& swizzleSequence = node->getRight()->getAsAggregate()->getSequence();
773             std::vector<unsigned> swizzle;
774             for (int i = 0; i < (int)swizzleSequence.size(); ++i)
775                 swizzle.push_back(swizzleSequence[i]->getAsConstantUnion()->getConstArray()[0].getIConst());
776             builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType()));
777         }
778         return false;
779     case glslang::EOpLogicalOr:
780     case glslang::EOpLogicalAnd:
781         {
782
783             // These may require short circuiting, but can sometimes be done as straight
784             // binary operations.  The right operand must be short circuited if it has
785             // side effects, and should probably be if it is complex.
786             if (isTrivial(node->getRight()->getAsTyped()))
787                 break; // handle below as a normal binary operation
788             // otherwise, we need to do dynamic short circuiting on the right operand
789             spv::Id result = createShortCircuit(node->getOp(), *node->getLeft()->getAsTyped(), *node->getRight()->getAsTyped());
790             builder.clearAccessChain();
791             builder.setAccessChainRValue(result);
792         }
793         return false;
794     default:
795         break;
796     }
797
798     // Assume generic binary op...
799
800     // Get the operands
801     builder.clearAccessChain();
802     node->getLeft()->traverse(this);
803     spv::Id left = builder.accessChainLoad(convertGlslangToSpvType(node->getLeft()->getType()));
804
805     builder.clearAccessChain();
806     node->getRight()->traverse(this);
807     spv::Id right = builder.accessChainLoad(convertGlslangToSpvType(node->getRight()->getType()));
808
809     spv::Id result;
810     spv::Decoration precision = TranslatePrecisionDecoration(node->getType());
811
812     result = createBinaryOperation(node->getOp(), precision, 
813                                    convertGlslangToSpvType(node->getType()), left, right,
814                                    node->getLeft()->getType().getBasicType());
815
816     builder.clearAccessChain();
817     if (! result) {
818         spv::MissingFunctionality("unknown glslang binary operation");
819         return true;  // pick up a child as the place-holder result
820     } else {
821         builder.setAccessChainRValue(result);
822         return false;
823     }
824 }
825
826 bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TIntermUnary* node)
827 {
828     spv::Id result = spv::NoResult;
829
830     // try texturing first
831     result = createImageTextureFunctionCall(node);
832     if (result != spv::NoResult) {
833         builder.clearAccessChain();
834         builder.setAccessChainRValue(result);
835
836         return false; // done with this node
837     }
838
839     // Non-texturing.
840
841     if (node->getOp() == glslang::EOpArrayLength) {
842         // Quite special; won't want to evaluate the operand.
843
844         // Normal .length() would have been constant folded by the front-end.
845         // So, this has to be block.lastMember.length().
846         // SPV wants "block" and member number as the operands, go get them.
847         assert(node->getOperand()->getType().isRuntimeSizedArray());
848         glslang::TIntermTyped* block = node->getOperand()->getAsBinaryNode()->getLeft();
849         block->traverse(this);
850         unsigned int member = node->getOperand()->getAsBinaryNode()->getRight()->getAsConstantUnion()->getConstArray()[0].getUConst();
851         spv::Id length = builder.createArrayLength(builder.accessChainGetLValue(), member);
852
853         builder.clearAccessChain();
854         builder.setAccessChainRValue(length);
855
856         return false;
857     }
858
859     // Start by evaluating the operand
860
861     builder.clearAccessChain();
862     node->getOperand()->traverse(this);
863
864     spv::Id operand = spv::NoResult;
865
866     if (node->getOp() == glslang::EOpAtomicCounterIncrement ||
867         node->getOp() == glslang::EOpAtomicCounterDecrement ||
868         node->getOp() == glslang::EOpAtomicCounter          ||
869         node->getOp() == glslang::EOpInterpolateAtCentroid)
870         operand = builder.accessChainGetLValue(); // Special case l-value operands
871     else
872         operand = builder.accessChainLoad(convertGlslangToSpvType(node->getOperand()->getType()));
873
874     spv::Decoration precision = TranslatePrecisionDecoration(node->getType());
875
876     // it could be a conversion
877     if (! result)
878         result = createConversion(node->getOp(), precision, convertGlslangToSpvType(node->getType()), operand);
879
880     // if not, then possibly an operation
881     if (! result)
882         result = createUnaryOperation(node->getOp(), precision, convertGlslangToSpvType(node->getType()), operand, node->getOperand()->getBasicType());
883
884     if (result) {
885         builder.clearAccessChain();
886         builder.setAccessChainRValue(result);
887
888         return false; // done with this node
889     }
890
891     // it must be a special case, check...
892     switch (node->getOp()) {
893     case glslang::EOpPostIncrement:
894     case glslang::EOpPostDecrement:
895     case glslang::EOpPreIncrement:
896     case glslang::EOpPreDecrement:
897         {
898             // we need the integer value "1" or the floating point "1.0" to add/subtract
899             spv::Id one = node->getBasicType() == glslang::EbtFloat ?
900                                      builder.makeFloatConstant(1.0F) :
901                                      builder.makeIntConstant(1);
902             glslang::TOperator op;
903             if (node->getOp() == glslang::EOpPreIncrement ||
904                 node->getOp() == glslang::EOpPostIncrement)
905                 op = glslang::EOpAdd;
906             else
907                 op = glslang::EOpSub;
908
909             spv::Id result = createBinaryOperation(op, TranslatePrecisionDecoration(node->getType()), 
910                                                      convertGlslangToSpvType(node->getType()), operand, one, 
911                                                      node->getType().getBasicType());
912             assert(result != spv::NoResult);
913
914             // The result of operation is always stored, but conditionally the
915             // consumed result.  The consumed result is always an r-value.
916             builder.accessChainStore(result);
917             builder.clearAccessChain();
918             if (node->getOp() == glslang::EOpPreIncrement ||
919                 node->getOp() == glslang::EOpPreDecrement)
920                 builder.setAccessChainRValue(result);
921             else
922                 builder.setAccessChainRValue(operand);
923         }
924
925         return false;
926
927     case glslang::EOpEmitStreamVertex:
928         builder.createNoResultOp(spv::OpEmitStreamVertex, operand);
929         return false;
930     case glslang::EOpEndStreamPrimitive:
931         builder.createNoResultOp(spv::OpEndStreamPrimitive, operand);
932         return false;
933
934     default:
935         spv::MissingFunctionality("unknown glslang unary");
936         return true;  // pick up operand as placeholder result
937     }
938 }
939
940 bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TIntermAggregate* node)
941 {
942     spv::Id result = spv::NoResult;
943
944     // try texturing
945     result = createImageTextureFunctionCall(node);
946     if (result != spv::NoResult) {
947         builder.clearAccessChain();
948         builder.setAccessChainRValue(result);
949
950         return false;
951     } else if (node->getOp() == glslang::EOpImageStore) {
952         // "imageStore" is a special case, which has no result
953         return false;
954     }
955
956     glslang::TOperator binOp = glslang::EOpNull;
957     bool reduceComparison = true;
958     bool isMatrix = false;
959     bool noReturnValue = false;
960     bool atomic = false;
961
962     assert(node->getOp());
963
964     spv::Decoration precision = TranslatePrecisionDecoration(node->getType());
965
966     switch (node->getOp()) {
967     case glslang::EOpSequence:
968     {
969         if (preVisit)
970             ++sequenceDepth;
971         else
972             --sequenceDepth;
973
974         if (sequenceDepth == 1) {
975             // If this is the parent node of all the functions, we want to see them
976             // early, so all call points have actual SPIR-V functions to reference.
977             // In all cases, still let the traverser visit the children for us.
978             makeFunctions(node->getAsAggregate()->getSequence());
979
980             // Also, we want all globals initializers to go into the entry of main(), before
981             // anything else gets there, so visit out of order, doing them all now.
982             makeGlobalInitializers(node->getAsAggregate()->getSequence());
983
984             // Initializers are done, don't want to visit again, but functions link objects need to be processed,
985             // so do them manually.
986             visitFunctions(node->getAsAggregate()->getSequence());
987
988             return false;
989         }
990
991         return true;
992     }
993     case glslang::EOpLinkerObjects:
994     {
995         if (visit == glslang::EvPreVisit)
996             linkageOnly = true;
997         else
998             linkageOnly = false;
999
1000         return true;
1001     }
1002     case glslang::EOpComma:
1003     {
1004         // processing from left to right naturally leaves the right-most
1005         // lying around in the access chain
1006         glslang::TIntermSequence& glslangOperands = node->getSequence();
1007         for (int i = 0; i < (int)glslangOperands.size(); ++i)
1008             glslangOperands[i]->traverse(this);
1009
1010         return false;
1011     }
1012     case glslang::EOpFunction:
1013         if (visit == glslang::EvPreVisit) {
1014             if (isShaderEntrypoint(node)) {
1015                 inMain = true;
1016                 builder.setBuildPoint(shaderEntry->getLastBlock());
1017             } else {
1018                 handleFunctionEntry(node);
1019             }
1020         } else {
1021             if (inMain)
1022                 mainTerminated = true;
1023             builder.leaveFunction();
1024             inMain = false;
1025         }
1026
1027         return true;
1028     case glslang::EOpParameters:
1029         // Parameters will have been consumed by EOpFunction processing, but not
1030         // the body, so we still visited the function node's children, making this
1031         // child redundant.
1032         return false;
1033     case glslang::EOpFunctionCall:
1034     {
1035         if (node->isUserDefined())
1036             result = handleUserFunctionCall(node);
1037         assert(result);
1038         builder.clearAccessChain();
1039         builder.setAccessChainRValue(result);
1040
1041         return false;
1042     }
1043     case glslang::EOpConstructMat2x2:
1044     case glslang::EOpConstructMat2x3:
1045     case glslang::EOpConstructMat2x4:
1046     case glslang::EOpConstructMat3x2:
1047     case glslang::EOpConstructMat3x3:
1048     case glslang::EOpConstructMat3x4:
1049     case glslang::EOpConstructMat4x2:
1050     case glslang::EOpConstructMat4x3:
1051     case glslang::EOpConstructMat4x4:
1052     case glslang::EOpConstructDMat2x2:
1053     case glslang::EOpConstructDMat2x3:
1054     case glslang::EOpConstructDMat2x4:
1055     case glslang::EOpConstructDMat3x2:
1056     case glslang::EOpConstructDMat3x3:
1057     case glslang::EOpConstructDMat3x4:
1058     case glslang::EOpConstructDMat4x2:
1059     case glslang::EOpConstructDMat4x3:
1060     case glslang::EOpConstructDMat4x4:
1061         isMatrix = true;
1062         // fall through
1063     case glslang::EOpConstructFloat:
1064     case glslang::EOpConstructVec2:
1065     case glslang::EOpConstructVec3:
1066     case glslang::EOpConstructVec4:
1067     case glslang::EOpConstructDouble:
1068     case glslang::EOpConstructDVec2:
1069     case glslang::EOpConstructDVec3:
1070     case glslang::EOpConstructDVec4:
1071     case glslang::EOpConstructBool:
1072     case glslang::EOpConstructBVec2:
1073     case glslang::EOpConstructBVec3:
1074     case glslang::EOpConstructBVec4:
1075     case glslang::EOpConstructInt:
1076     case glslang::EOpConstructIVec2:
1077     case glslang::EOpConstructIVec3:
1078     case glslang::EOpConstructIVec4:
1079     case glslang::EOpConstructUint:
1080     case glslang::EOpConstructUVec2:
1081     case glslang::EOpConstructUVec3:
1082     case glslang::EOpConstructUVec4:
1083     case glslang::EOpConstructStruct:
1084     {
1085         std::vector<spv::Id> arguments;
1086         translateArguments(*node, arguments);
1087         spv::Id resultTypeId = convertGlslangToSpvType(node->getType());
1088         spv::Id constructed;
1089         if (node->getOp() == glslang::EOpConstructStruct || node->getType().isArray()) {
1090             std::vector<spv::Id> constituents;
1091             for (int c = 0; c < (int)arguments.size(); ++c)
1092                 constituents.push_back(arguments[c]);
1093             constructed = builder.createCompositeConstruct(resultTypeId, constituents);
1094         } else if (isMatrix)
1095             constructed = builder.createMatrixConstructor(precision, arguments, resultTypeId);
1096         else
1097             constructed = builder.createConstructor(precision, arguments, resultTypeId);
1098
1099         builder.clearAccessChain();
1100         builder.setAccessChainRValue(constructed);
1101
1102         return false;
1103     }
1104
1105     // These six are component-wise compares with component-wise results.
1106     // Forward on to createBinaryOperation(), requesting a vector result.
1107     case glslang::EOpLessThan:
1108     case glslang::EOpGreaterThan:
1109     case glslang::EOpLessThanEqual:
1110     case glslang::EOpGreaterThanEqual:
1111     case glslang::EOpVectorEqual:
1112     case glslang::EOpVectorNotEqual:
1113     {
1114         // Map the operation to a binary
1115         binOp = node->getOp();
1116         reduceComparison = false;
1117         switch (node->getOp()) {
1118         case glslang::EOpVectorEqual:     binOp = glslang::EOpVectorEqual;      break;
1119         case glslang::EOpVectorNotEqual:  binOp = glslang::EOpVectorNotEqual;   break;
1120         default:                          binOp = node->getOp();                break;
1121         }
1122
1123         break;
1124     }
1125     case glslang::EOpMul:
1126         // compontent-wise matrix multiply      
1127         binOp = glslang::EOpMul;
1128         break;
1129     case glslang::EOpOuterProduct:
1130         // two vectors multiplied to make a matrix
1131         binOp = glslang::EOpOuterProduct;
1132         break;
1133     case glslang::EOpDot:
1134     {
1135         // for scalar dot product, use multiply        
1136         glslang::TIntermSequence& glslangOperands = node->getSequence();
1137         if (! glslangOperands[0]->getAsTyped()->isVector())
1138             binOp = glslang::EOpMul;
1139         break;
1140     }
1141     case glslang::EOpMod:
1142         // when an aggregate, this is the floating-point mod built-in function,
1143         // which can be emitted by the one in createBinaryOperation()
1144         binOp = glslang::EOpMod;
1145         break;
1146     case glslang::EOpEmitVertex:
1147     case glslang::EOpEndPrimitive:
1148     case glslang::EOpBarrier:
1149     case glslang::EOpMemoryBarrier:
1150     case glslang::EOpMemoryBarrierAtomicCounter:
1151     case glslang::EOpMemoryBarrierBuffer:
1152     case glslang::EOpMemoryBarrierImage:
1153     case glslang::EOpMemoryBarrierShared:
1154     case glslang::EOpGroupMemoryBarrier:
1155         noReturnValue = true;
1156         // These all have 0 operands and will naturally finish up in the code below for 0 operands
1157         break;
1158
1159     case glslang::EOpAtomicAdd:
1160     case glslang::EOpAtomicMin:
1161     case glslang::EOpAtomicMax:
1162     case glslang::EOpAtomicAnd:
1163     case glslang::EOpAtomicOr:
1164     case glslang::EOpAtomicXor:
1165     case glslang::EOpAtomicExchange:
1166     case glslang::EOpAtomicCompSwap:
1167         atomic = true;
1168         break;
1169
1170     default:
1171         break;
1172     }
1173
1174     //
1175     // See if it maps to a regular operation.
1176     //
1177     if (binOp != glslang::EOpNull) {
1178         glslang::TIntermTyped* left = node->getSequence()[0]->getAsTyped();
1179         glslang::TIntermTyped* right = node->getSequence()[1]->getAsTyped();
1180         assert(left && right);
1181
1182         builder.clearAccessChain();
1183         left->traverse(this);
1184         spv::Id leftId = builder.accessChainLoad(convertGlslangToSpvType(left->getType()));
1185
1186         builder.clearAccessChain();
1187         right->traverse(this);
1188         spv::Id rightId = builder.accessChainLoad(convertGlslangToSpvType(right->getType()));
1189
1190         result = createBinaryOperation(binOp, precision, 
1191                                        convertGlslangToSpvType(node->getType()), leftId, rightId, 
1192                                        left->getType().getBasicType(), reduceComparison);
1193
1194         // code above should only make binOp that exists in createBinaryOperation
1195         assert(result != spv::NoResult);
1196         builder.clearAccessChain();
1197         builder.setAccessChainRValue(result);
1198
1199         return false;
1200     }
1201
1202     //
1203     // Create the list of operands.
1204     //
1205     glslang::TIntermSequence& glslangOperands = node->getSequence();
1206     std::vector<spv::Id> operands;
1207     for (int arg = 0; arg < (int)glslangOperands.size(); ++arg) {
1208         builder.clearAccessChain();
1209         glslangOperands[arg]->traverse(this);
1210
1211         // special case l-value operands; there are just a few
1212         bool lvalue = false;
1213         switch (node->getOp()) {
1214         case glslang::EOpFrexp:
1215         case glslang::EOpModf:
1216             if (arg == 1)
1217                 lvalue = true;
1218             break;
1219         case glslang::EOpInterpolateAtSample:
1220         case glslang::EOpInterpolateAtOffset:
1221             if (arg == 0)
1222                 lvalue = true;
1223             break;
1224         case glslang::EOpAtomicAdd:
1225         case glslang::EOpAtomicMin:
1226         case glslang::EOpAtomicMax:
1227         case glslang::EOpAtomicAnd:
1228         case glslang::EOpAtomicOr:
1229         case glslang::EOpAtomicXor:
1230         case glslang::EOpAtomicExchange:
1231         case glslang::EOpAtomicCompSwap:
1232             if (arg == 0)
1233                 lvalue = true;
1234             break;
1235         case glslang::EOpAddCarry:
1236         case glslang::EOpSubBorrow:
1237             if (arg == 2)
1238                 lvalue = true;
1239             break;
1240         case glslang::EOpUMulExtended:
1241         case glslang::EOpIMulExtended:
1242             if (arg >= 2)
1243                 lvalue = true;
1244             break;
1245         default:
1246             break;
1247         }
1248         if (lvalue)
1249             operands.push_back(builder.accessChainGetLValue());
1250         else
1251             operands.push_back(builder.accessChainLoad(convertGlslangToSpvType(glslangOperands[arg]->getAsTyped()->getType())));
1252     }
1253
1254     if (atomic) {
1255         // Handle all atomics
1256         result = createAtomicOperation(node->getOp(), precision, convertGlslangToSpvType(node->getType()), operands, node->getBasicType());
1257     } else {
1258         // Pass through to generic operations.
1259         switch (glslangOperands.size()) {
1260         case 0:
1261             result = createNoArgOperation(node->getOp());
1262             break;
1263         case 1:
1264             result = createUnaryOperation(node->getOp(), precision, convertGlslangToSpvType(node->getType()), operands.front(), glslangOperands[0]->getAsTyped()->getBasicType());
1265             break;
1266         default:
1267             result = createMiscOperation(node->getOp(), precision, convertGlslangToSpvType(node->getType()), operands, node->getBasicType());
1268             break;
1269         }
1270     }
1271
1272     if (noReturnValue)
1273         return false;
1274
1275     if (! result) {
1276         spv::MissingFunctionality("unknown glslang aggregate");
1277         return true;  // pick up a child as a placeholder operand
1278     } else {
1279         builder.clearAccessChain();
1280         builder.setAccessChainRValue(result);
1281         return false;
1282     }
1283 }
1284
1285 bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang::TIntermSelection* node)
1286 {
1287     // This path handles both if-then-else and ?:
1288     // The if-then-else has a node type of void, while
1289     // ?: has a non-void node type
1290     spv::Id result = 0;
1291     if (node->getBasicType() != glslang::EbtVoid) {
1292         // don't handle this as just on-the-fly temporaries, because there will be two names
1293         // and better to leave SSA to later passes
1294         result = builder.createVariable(spv::StorageClassFunction, convertGlslangToSpvType(node->getType()));
1295     }
1296
1297     // emit the condition before doing anything with selection
1298     node->getCondition()->traverse(this);
1299
1300     // make an "if" based on the value created by the condition
1301     spv::Builder::If ifBuilder(builder.accessChainLoad(convertGlslangToSpvType(node->getCondition()->getType())), builder);
1302
1303     if (node->getTrueBlock()) {
1304         // emit the "then" statement
1305         node->getTrueBlock()->traverse(this);
1306         if (result)
1307             builder.createStore(builder.accessChainLoad(convertGlslangToSpvType(node->getTrueBlock()->getAsTyped()->getType())), result);
1308     }
1309
1310     if (node->getFalseBlock()) {
1311         ifBuilder.makeBeginElse();
1312         // emit the "else" statement
1313         node->getFalseBlock()->traverse(this);
1314         if (result)
1315             builder.createStore(builder.accessChainLoad(convertGlslangToSpvType(node->getFalseBlock()->getAsTyped()->getType())), result);
1316     }
1317
1318     ifBuilder.makeEndIf();
1319
1320     if (result) {
1321         // GLSL only has r-values as the result of a :?, but
1322         // if we have an l-value, that can be more efficient if it will
1323         // become the base of a complex r-value expression, because the
1324         // next layer copies r-values into memory to use the access-chain mechanism
1325         builder.clearAccessChain();
1326         builder.setAccessChainLValue(result);
1327     }
1328
1329     return false;
1330 }
1331
1332 bool TGlslangToSpvTraverser::visitSwitch(glslang::TVisit /* visit */, glslang::TIntermSwitch* node)
1333 {
1334     // emit and get the condition before doing anything with switch
1335     node->getCondition()->traverse(this);
1336     spv::Id selector = builder.accessChainLoad(convertGlslangToSpvType(node->getCondition()->getAsTyped()->getType()));
1337
1338     // browse the children to sort out code segments
1339     int defaultSegment = -1;
1340     std::vector<TIntermNode*> codeSegments;
1341     glslang::TIntermSequence& sequence = node->getBody()->getSequence();
1342     std::vector<int> caseValues;
1343     std::vector<int> valueIndexToSegment(sequence.size());  // note: probably not all are used, it is an overestimate
1344     for (glslang::TIntermSequence::iterator c = sequence.begin(); c != sequence.end(); ++c) {
1345         TIntermNode* child = *c;
1346         if (child->getAsBranchNode() && child->getAsBranchNode()->getFlowOp() == glslang::EOpDefault)
1347             defaultSegment = (int)codeSegments.size();
1348         else if (child->getAsBranchNode() && child->getAsBranchNode()->getFlowOp() == glslang::EOpCase) {
1349             valueIndexToSegment[caseValues.size()] = (int)codeSegments.size();
1350             caseValues.push_back(child->getAsBranchNode()->getExpression()->getAsConstantUnion()->getConstArray()[0].getIConst());
1351         } else
1352             codeSegments.push_back(child);
1353     }
1354
1355     // handle the case where the last code segment is missing, due to no code 
1356     // statements between the last case and the end of the switch statement
1357     if ((caseValues.size() && (int)codeSegments.size() == valueIndexToSegment[caseValues.size() - 1]) ||
1358         (int)codeSegments.size() == defaultSegment)
1359         codeSegments.push_back(nullptr);
1360
1361     // make the switch statement
1362     std::vector<spv::Block*> segmentBlocks; // returned, as the blocks allocated in the call
1363     builder.makeSwitch(selector, (int)codeSegments.size(), caseValues, valueIndexToSegment, defaultSegment, segmentBlocks);
1364
1365     // emit all the code in the segments
1366     breakForLoop.push(false);
1367     for (unsigned int s = 0; s < codeSegments.size(); ++s) {
1368         builder.nextSwitchSegment(segmentBlocks, s);
1369         if (codeSegments[s])
1370             codeSegments[s]->traverse(this);
1371         else
1372             builder.addSwitchBreak();
1373     }
1374     breakForLoop.pop();
1375
1376     builder.endSwitch(segmentBlocks);
1377
1378     return false;
1379 }
1380
1381 void TGlslangToSpvTraverser::visitConstantUnion(glslang::TIntermConstantUnion* node)
1382 {
1383     int nextConst = 0;
1384     spv::Id constant = createSpvConstant(node->getType(), node->getConstArray(), nextConst, false);
1385
1386     builder.clearAccessChain();
1387     builder.setAccessChainRValue(constant);
1388 }
1389
1390 bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIntermLoop* node)
1391 {
1392     auto blocks = builder.makeNewLoop();
1393     builder.createBranch(&blocks.head);
1394     if (node->testFirst() && node->getTest()) {
1395         builder.setBuildPoint(&blocks.head);
1396         node->getTest()->traverse(this);
1397         spv::Id condition =
1398             builder.accessChainLoad(convertGlslangToSpvType(node->getTest()->getType()));
1399         builder.createLoopMerge(&blocks.merge, &blocks.continue_target, spv::LoopControlMaskNone);
1400         builder.createConditionalBranch(condition, &blocks.body, &blocks.merge);
1401
1402         builder.setBuildPoint(&blocks.body);
1403         breakForLoop.push(true);
1404         if (node->getBody())
1405             node->getBody()->traverse(this);
1406         builder.createBranch(&blocks.continue_target);
1407         breakForLoop.pop();
1408
1409         builder.setBuildPoint(&blocks.continue_target);
1410         if (node->getTerminal())
1411             node->getTerminal()->traverse(this);
1412         builder.createBranch(&blocks.head);
1413     } else {
1414         // Spec requires back edges to target header blocks, and every header
1415         // block must dominate its merge block.  Create an empty header block
1416         // here to ensure these conditions are met even when body contains
1417         // non-trivial control flow.
1418         builder.setBuildPoint(&blocks.head);
1419         builder.createLoopMerge(&blocks.merge, &blocks.continue_target, spv::LoopControlMaskNone);
1420         builder.createBranch(&blocks.body);
1421
1422         breakForLoop.push(true);
1423         builder.setBuildPoint(&blocks.body);
1424         if (node->getBody())
1425             node->getBody()->traverse(this);
1426         builder.createBranch(&blocks.continue_target);
1427         breakForLoop.pop();
1428
1429         builder.setBuildPoint(&blocks.continue_target);
1430         if (node->getTerminal())
1431             node->getTerminal()->traverse(this);
1432         if (node->getTest()) {
1433             node->getTest()->traverse(this);
1434             spv::Id condition =
1435                 builder.accessChainLoad(convertGlslangToSpvType(node->getTest()->getType()));
1436             builder.createConditionalBranch(condition, &blocks.head, &blocks.merge);
1437         } else {
1438             // TODO: unless there was a break instruction somewhere in the body,
1439             // this is an infinite loop, so we should abort code generation with
1440             // a warning.  As it stands now, nothing will jump to the merge
1441             // block, and it may be dropped as unreachable by the SPIR-V dumper.
1442             // That, in turn, will result in a non-existing %ID in the LoopMerge
1443             // above.
1444             builder.createBranch(&blocks.head);
1445         }
1446     }
1447     builder.setBuildPoint(&blocks.merge);
1448     builder.closeLoop();
1449     return false;
1450 }
1451
1452 bool TGlslangToSpvTraverser::visitBranch(glslang::TVisit /* visit */, glslang::TIntermBranch* node)
1453 {
1454     if (node->getExpression())
1455         node->getExpression()->traverse(this);
1456
1457     switch (node->getFlowOp()) {
1458     case glslang::EOpKill:
1459         builder.makeDiscard();
1460         break;
1461     case glslang::EOpBreak:
1462         if (breakForLoop.top())
1463             builder.createLoopExit();
1464         else
1465             builder.addSwitchBreak();
1466         break;
1467     case glslang::EOpContinue:
1468         builder.createLoopContinue();
1469         break;
1470     case glslang::EOpReturn:
1471         if (node->getExpression())
1472             builder.makeReturn(false, builder.accessChainLoad(convertGlslangToSpvType(node->getExpression()->getType())));
1473         else
1474             builder.makeReturn(false);
1475
1476         builder.clearAccessChain();
1477         break;
1478
1479     default:
1480         assert(0);
1481         break;
1482     }
1483
1484     return false;
1485 }
1486
1487 spv::Id TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol* node)
1488 {
1489     // First, steer off constants, which are not SPIR-V variables, but 
1490     // can still have a mapping to a SPIR-V Id.
1491     // This includes specialization constants.
1492     if (node->getQualifier().storage == glslang::EvqConst) {
1493         return createSpvSpecConstant(*node);
1494     }
1495
1496     // Now, handle actual variables
1497     spv::StorageClass storageClass = TranslateStorageClass(node->getType());
1498     spv::Id spvType = convertGlslangToSpvType(node->getType());
1499
1500     const char* name = node->getName().c_str();
1501     if (glslang::IsAnonymous(name))
1502         name = "";
1503
1504     return builder.createVariable(storageClass, spvType, name);
1505 }
1506
1507 // Return type Id of the sampled type.
1508 spv::Id TGlslangToSpvTraverser::getSampledType(const glslang::TSampler& sampler)
1509 {
1510     switch (sampler.type) {
1511         case glslang::EbtFloat:    return builder.makeFloatType(32);
1512         case glslang::EbtInt:      return builder.makeIntType(32);
1513         case glslang::EbtUint:     return builder.makeUintType(32);
1514         default:
1515             assert(0);
1516             return builder.makeFloatType(32);
1517     }
1518 }
1519
1520 // Convert from a glslang type to an SPV type, by calling into a
1521 // recursive version of this function. This establishes the inherited
1522 // layout state rooted from the top-level type.
1523 spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& type)
1524 {
1525     return convertGlslangToSpvType(type, getExplicitLayout(type), type.getQualifier());
1526 }
1527
1528 // Do full recursive conversion of an arbitrary glslang type to a SPIR-V Id.
1529 // explicitLayout can be kept the same throughout the heirarchical recursive walk.
1530 spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& type, glslang::TLayoutPacking explicitLayout, const glslang::TQualifier& qualifier)
1531 {
1532     spv::Id spvType = spv::NoResult;
1533
1534     switch (type.getBasicType()) {
1535     case glslang::EbtVoid:
1536         spvType = builder.makeVoidType();
1537         assert (! type.isArray());
1538         break;
1539     case glslang::EbtFloat:
1540         spvType = builder.makeFloatType(32);
1541         break;
1542     case glslang::EbtDouble:
1543         spvType = builder.makeFloatType(64);
1544         break;
1545     case glslang::EbtBool:
1546         spvType = builder.makeBoolType();
1547         break;
1548     case glslang::EbtInt:
1549         spvType = builder.makeIntType(32);
1550         break;
1551     case glslang::EbtUint:
1552         spvType = builder.makeUintType(32);
1553         break;
1554     case glslang::EbtAtomicUint:
1555         spv::TbdFunctionality("Is atomic_uint an opaque handle in the uniform storage class, or an addresses in the atomic storage class?");
1556         spvType = builder.makeUintType(32);
1557         break;
1558     case glslang::EbtSampler:
1559         {
1560             const glslang::TSampler& sampler = type.getSampler();
1561             // an image is present, make its type
1562             spvType = builder.makeImageType(getSampledType(sampler), TranslateDimensionality(sampler), sampler.shadow, sampler.arrayed, sampler.ms,
1563                                             sampler.image ? 2 : 1, TranslateImageFormat(type));
1564             if (! sampler.image) {
1565                 spvType = builder.makeSampledImageType(spvType);
1566             }
1567         }
1568         break;
1569     case glslang::EbtStruct:
1570     case glslang::EbtBlock:
1571         {
1572             // If we've seen this struct type, return it
1573             const glslang::TTypeList* glslangStruct = type.getStruct();
1574             std::vector<spv::Id> structFields;
1575
1576             // Try to share structs for different layouts, but not yet for other
1577             // kinds of qualification (primarily not yet including interpolant qualification).
1578             if (! HasNonLayoutQualifiers(qualifier))
1579                 spvType = structMap[explicitLayout][qualifier.layoutMatrix][glslangStruct];
1580             if (spvType != spv::NoResult)
1581                 break;
1582
1583             // else, we haven't seen it...
1584
1585             // Create a vector of struct types for SPIR-V to consume
1586             int memberDelta = 0;  // how much the member's index changes from glslang to SPIR-V, normally 0, except sometimes for blocks
1587             if (type.getBasicType() == glslang::EbtBlock)
1588                 memberRemapper[glslangStruct].resize(glslangStruct->size());
1589             for (int i = 0; i < (int)glslangStruct->size(); i++) {
1590                 glslang::TType& glslangType = *(*glslangStruct)[i].type;
1591                 if (glslangType.hiddenMember()) {
1592                     ++memberDelta;
1593                     if (type.getBasicType() == glslang::EbtBlock)
1594                         memberRemapper[glslangStruct][i] = -1;
1595                 } else {
1596                     if (type.getBasicType() == glslang::EbtBlock)
1597                         memberRemapper[glslangStruct][i] = i - memberDelta;
1598                     // modify just this child's view of the qualifier
1599                     glslang::TQualifier subQualifier = glslangType.getQualifier();
1600                     InheritQualifiers(subQualifier, qualifier);
1601                     structFields.push_back(convertGlslangToSpvType(glslangType, explicitLayout, subQualifier));
1602                 }
1603             }
1604
1605             // Make the SPIR-V type
1606             spvType = builder.makeStructType(structFields, type.getTypeName().c_str());
1607             if (! HasNonLayoutQualifiers(qualifier))
1608                 structMap[explicitLayout][qualifier.layoutMatrix][glslangStruct] = spvType;
1609
1610             // Name and decorate the non-hidden members
1611             int offset = -1;
1612             for (int i = 0; i < (int)glslangStruct->size(); i++) {
1613                 glslang::TType& glslangType = *(*glslangStruct)[i].type;
1614                 int member = i;
1615                 if (type.getBasicType() == glslang::EbtBlock)
1616                     member = memberRemapper[glslangStruct][i];
1617
1618                 // modify just this child's view of the qualifier
1619                 glslang::TQualifier subQualifier = glslangType.getQualifier();
1620                 InheritQualifiers(subQualifier, qualifier);
1621
1622                 // using -1 above to indicate a hidden member
1623                 if (member >= 0) {
1624                     builder.addMemberName(spvType, member, glslangType.getFieldName().c_str());
1625                     addMemberDecoration(spvType, member, TranslateLayoutDecoration(glslangType, subQualifier.layoutMatrix));
1626                     addMemberDecoration(spvType, member, TranslatePrecisionDecoration(glslangType));
1627                     addMemberDecoration(spvType, member, TranslateInterpolationDecoration(subQualifier));
1628                     addMemberDecoration(spvType, member, TranslateInvariantDecoration(subQualifier));
1629                     if (glslangType.getQualifier().hasLocation())
1630                         builder.addMemberDecoration(spvType, member, spv::DecorationLocation, glslangType.getQualifier().layoutLocation);
1631                     if (glslangType.getQualifier().hasComponent())
1632                         builder.addMemberDecoration(spvType, member, spv::DecorationComponent, glslangType.getQualifier().layoutComponent);
1633                     if (glslangType.getQualifier().hasXfbOffset())
1634                         builder.addMemberDecoration(spvType, member, spv::DecorationOffset, glslangType.getQualifier().layoutXfbOffset);
1635                     else if (explicitLayout != glslang::ElpNone) {
1636                         // figure out what to do with offset, which is accumulating
1637                         int nextOffset;
1638                         updateMemberOffset(type, glslangType, offset, nextOffset, explicitLayout, subQualifier.layoutMatrix);
1639                         if (offset >= 0)
1640                             builder.addMemberDecoration(spvType, member, spv::DecorationOffset, offset);
1641                         offset = nextOffset;
1642                     }
1643
1644                     if (glslangType.isMatrix() && explicitLayout != glslang::ElpNone)
1645                         builder.addMemberDecoration(spvType, member, spv::DecorationMatrixStride, getMatrixStride(glslangType, explicitLayout, subQualifier.layoutMatrix));
1646
1647                     // built-in variable decorations
1648                     spv::BuiltIn builtIn = TranslateBuiltInDecoration(glslangType.getQualifier().builtIn);
1649                     if (builtIn != spv::BadValue)
1650                         builder.addMemberDecoration(spvType, member, spv::DecorationBuiltIn, (int)builtIn);
1651                 }
1652             }
1653
1654             // Decorate the structure
1655             addDecoration(spvType, TranslateLayoutDecoration(type, qualifier.layoutMatrix));
1656             addDecoration(spvType, TranslateBlockDecoration(type));
1657             if (type.getQualifier().hasStream())
1658                 builder.addDecoration(spvType, spv::DecorationStream, type.getQualifier().layoutStream);
1659             if (glslangIntermediate->getXfbMode()) {
1660                 if (type.getQualifier().hasXfbStride())
1661                     builder.addDecoration(spvType, spv::DecorationXfbStride, type.getQualifier().layoutXfbStride);
1662                 if (type.getQualifier().hasXfbBuffer())
1663                     builder.addDecoration(spvType, spv::DecorationXfbBuffer, type.getQualifier().layoutXfbBuffer);
1664             }
1665         }
1666         break;
1667     default:
1668         assert(0);
1669         break;
1670     }
1671
1672     if (type.isMatrix())
1673         spvType = builder.makeMatrixType(spvType, type.getMatrixCols(), type.getMatrixRows());
1674     else {
1675         // If this variable has a vector element count greater than 1, create a SPIR-V vector
1676         if (type.getVectorSize() > 1)
1677             spvType = builder.makeVectorType(spvType, type.getVectorSize());
1678     }
1679
1680     if (type.isArray()) {
1681         int stride = 0;  // keep this 0 unless doing an explicit layout; 0 will mean no decoration, no stride
1682
1683         // Do all but the outer dimension
1684         if (type.getArraySizes()->getNumDims() > 1) {
1685             // We need to decorate array strides for types needing explicit layout, except blocks.
1686             if (explicitLayout != glslang::ElpNone && type.getBasicType() != glslang::EbtBlock) {
1687                 // Use a dummy glslang type for querying internal strides of
1688                 // arrays of arrays, but using just a one-dimensional array.
1689                 glslang::TType simpleArrayType(type, 0); // deference type of the array
1690                 while (simpleArrayType.getArraySizes().getNumDims() > 1)
1691                     simpleArrayType.getArraySizes().dereference();
1692
1693                 // Will compute the higher-order strides here, rather than making a whole
1694                 // pile of types and doing repetitive recursion on their contents.
1695                 stride = getArrayStride(simpleArrayType, explicitLayout, qualifier.layoutMatrix);
1696             }
1697
1698             // make the arrays
1699             for (int dim = type.getArraySizes()->getNumDims() - 1; dim > 0; --dim) {
1700                 int size = type.getArraySizes()->getDimSize(dim);
1701                 assert(size > 0);
1702                 spvType = builder.makeArrayType(spvType, size, stride);
1703                 if (stride > 0)
1704                     builder.addDecoration(spvType, spv::DecorationArrayStride, stride);
1705                 stride *= size;
1706             }
1707         } else {
1708             // single-dimensional array, and don't yet have stride
1709
1710             // We need to decorate array strides for types needing explicit layout, except blocks.
1711             if (explicitLayout != glslang::ElpNone && type.getBasicType() != glslang::EbtBlock)
1712                 stride = getArrayStride(type, explicitLayout, qualifier.layoutMatrix);
1713         }
1714
1715         // Do the outer dimension, which might not be known for a runtime-sized array
1716         if (type.isRuntimeSizedArray()) {
1717             spvType = builder.makeRuntimeArray(spvType);
1718         } else {
1719             assert(type.getOuterArraySize() > 0);
1720             spvType = builder.makeArrayType(spvType, type.getOuterArraySize(), stride);
1721         }
1722         if (stride > 0)
1723             builder.addDecoration(spvType, spv::DecorationArrayStride, stride);
1724     }
1725
1726     return spvType;
1727 }
1728
1729 // Decide whether or not this type should be
1730 // decorated with offsets and strides, and if so
1731 // whether std140 or std430 rules should be applied.
1732 glslang::TLayoutPacking TGlslangToSpvTraverser::getExplicitLayout(const glslang::TType& type) const
1733 {
1734     // has to be a block
1735     if (type.getBasicType() != glslang::EbtBlock)
1736         return glslang::ElpNone;
1737
1738     // has to be a uniform or buffer block
1739     if (type.getQualifier().storage != glslang::EvqUniform &&
1740         type.getQualifier().storage != glslang::EvqBuffer)
1741         return glslang::ElpNone;
1742
1743     // return the layout to use
1744     switch (type.getQualifier().layoutPacking) {
1745     case glslang::ElpStd140:
1746     case glslang::ElpStd430:
1747         return type.getQualifier().layoutPacking;
1748     default:
1749         return glslang::ElpNone;
1750     }
1751 }
1752
1753 // Given an array type, returns the integer stride required for that array
1754 int TGlslangToSpvTraverser::getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout)
1755 {
1756     int size;
1757     int stride;
1758     glslangIntermediate->getBaseAlignment(arrayType, size, stride, explicitLayout == glslang::ElpStd140, matrixLayout == glslang::ElmRowMajor);
1759
1760     return stride;
1761 }
1762
1763 // Given a matrix type, or array (of array) of matrixes type, returns the integer stride required for that matrix
1764 // when used as a member of an interface block
1765 int TGlslangToSpvTraverser::getMatrixStride(const glslang::TType& matrixType, glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout)
1766 {
1767     glslang::TType elementType;
1768     elementType.shallowCopy(matrixType);
1769     elementType.clearArraySizes();
1770
1771     int size;
1772     int stride;
1773     glslangIntermediate->getBaseAlignment(elementType, size, stride, explicitLayout == glslang::ElpStd140, matrixLayout == glslang::ElmRowMajor);
1774
1775     return stride;
1776 }
1777
1778 // Given a member type of a struct, realign the current offset for it, and compute
1779 // the next (not yet aligned) offset for the next member, which will get aligned
1780 // on the next call.
1781 // 'currentOffset' should be passed in already initialized, ready to modify, and reflecting
1782 // the migration of data from nextOffset -> currentOffset.  It should be -1 on the first call.
1783 // -1 means a non-forced member offset (no decoration needed).
1784 void TGlslangToSpvTraverser::updateMemberOffset(const glslang::TType& structType, const glslang::TType& memberType, int& currentOffset, int& nextOffset,
1785                                                 glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout)
1786 {
1787     // this will get a positive value when deemed necessary
1788     nextOffset = -1;
1789
1790     // override anything in currentOffset with user-set offset
1791     if (memberType.getQualifier().hasOffset())
1792         currentOffset = memberType.getQualifier().layoutOffset;
1793
1794     // It could be that current linker usage in glslang updated all the layoutOffset,
1795     // in which case the following code does not matter.  But, that's not quite right
1796     // once cross-compilation unit GLSL validation is done, as the original user
1797     // settings are needed in layoutOffset, and then the following will come into play.
1798
1799     if (explicitLayout == glslang::ElpNone) {
1800         if (! memberType.getQualifier().hasOffset())
1801             currentOffset = -1;
1802
1803         return;
1804     }
1805
1806     // Getting this far means we need explicit offsets
1807     if (currentOffset < 0)
1808         currentOffset = 0;
1809     
1810     // Now, currentOffset is valid (either 0, or from a previous nextOffset),
1811     // but possibly not yet correctly aligned.
1812
1813     int memberSize;
1814     int dummyStride;
1815     int memberAlignment = glslangIntermediate->getBaseAlignment(memberType, memberSize, dummyStride, explicitLayout == glslang::ElpStd140, matrixLayout == glslang::ElmRowMajor);
1816     glslang::RoundToPow2(currentOffset, memberAlignment);
1817     nextOffset = currentOffset + memberSize;
1818 }
1819
1820 bool TGlslangToSpvTraverser::isShaderEntrypoint(const glslang::TIntermAggregate* node)
1821 {
1822     return node->getName() == "main(";
1823 }
1824
1825 // Make all the functions, skeletally, without actually visiting their bodies.
1826 void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslFunctions)
1827 {
1828     for (int f = 0; f < (int)glslFunctions.size(); ++f) {
1829         glslang::TIntermAggregate* glslFunction = glslFunctions[f]->getAsAggregate();
1830         if (! glslFunction || glslFunction->getOp() != glslang::EOpFunction || isShaderEntrypoint(glslFunction))
1831             continue;
1832
1833         // We're on a user function.  Set up the basic interface for the function now,
1834         // so that it's available to call.
1835         // Translating the body will happen later.
1836         //
1837         // Typically (except for a "const in" parameter), an address will be passed to the 
1838         // function.  What it is an address of varies:
1839         //
1840         // - "in" parameters not marked as "const" can be written to without modifying the argument,
1841         //  so that write needs to be to a copy, hence the address of a copy works.
1842         //
1843         // - "const in" parameters can just be the r-value, as no writes need occur.
1844         //
1845         // - "out" and "inout" arguments can't be done as direct pointers, because GLSL has
1846         // copy-in/copy-out semantics.  They can be handled though with a pointer to a copy.
1847
1848         std::vector<spv::Id> paramTypes;
1849         glslang::TIntermSequence& parameters = glslFunction->getSequence()[0]->getAsAggregate()->getSequence();
1850
1851         for (int p = 0; p < (int)parameters.size(); ++p) {
1852             const glslang::TType& paramType = parameters[p]->getAsTyped()->getType();
1853             spv::Id typeId = convertGlslangToSpvType(paramType);
1854             if (paramType.getQualifier().storage != glslang::EvqConstReadOnly)
1855                 typeId = builder.makePointer(spv::StorageClassFunction, typeId);
1856             else
1857                 constReadOnlyParameters.insert(parameters[p]->getAsSymbolNode()->getId());
1858             paramTypes.push_back(typeId);
1859         }
1860
1861         spv::Block* functionBlock;
1862         spv::Function *function = builder.makeFunctionEntry(convertGlslangToSpvType(glslFunction->getType()), glslFunction->getName().c_str(),
1863                                                               paramTypes, &functionBlock);
1864
1865         // Track function to emit/call later
1866         functionMap[glslFunction->getName().c_str()] = function;
1867
1868         // Set the parameter id's
1869         for (int p = 0; p < (int)parameters.size(); ++p) {
1870             symbolValues[parameters[p]->getAsSymbolNode()->getId()] = function->getParamId(p);
1871             // give a name too
1872             builder.addName(function->getParamId(p), parameters[p]->getAsSymbolNode()->getName().c_str());
1873         }
1874     }
1875 }
1876
1877 // Process all the initializers, while skipping the functions and link objects
1878 void TGlslangToSpvTraverser::makeGlobalInitializers(const glslang::TIntermSequence& initializers)
1879 {
1880     builder.setBuildPoint(shaderEntry->getLastBlock());
1881     for (int i = 0; i < (int)initializers.size(); ++i) {
1882         glslang::TIntermAggregate* initializer = initializers[i]->getAsAggregate();
1883         if (initializer && initializer->getOp() != glslang::EOpFunction && initializer->getOp() != glslang::EOpLinkerObjects) {
1884
1885             // We're on a top-level node that's not a function.  Treat as an initializer, whose
1886             // code goes into the beginning of main.
1887             initializer->traverse(this);
1888         }
1889     }
1890 }
1891
1892 // Process all the functions, while skipping initializers.
1893 void TGlslangToSpvTraverser::visitFunctions(const glslang::TIntermSequence& glslFunctions)
1894 {
1895     for (int f = 0; f < (int)glslFunctions.size(); ++f) {
1896         glslang::TIntermAggregate* node = glslFunctions[f]->getAsAggregate();
1897         if (node && (node->getOp() == glslang::EOpFunction || node->getOp() == glslang ::EOpLinkerObjects))
1898             node->traverse(this);
1899     }
1900 }
1901
1902 void TGlslangToSpvTraverser::handleFunctionEntry(const glslang::TIntermAggregate* node)
1903 {
1904     // SPIR-V functions should already be in the functionMap from the prepass 
1905     // that called makeFunctions().
1906     spv::Function* function = functionMap[node->getName().c_str()];
1907     spv::Block* functionBlock = function->getEntryBlock();
1908     builder.setBuildPoint(functionBlock);
1909 }
1910
1911 void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate& node, std::vector<spv::Id>& arguments)
1912 {
1913     const glslang::TIntermSequence& glslangArguments = node.getSequence();
1914
1915     glslang::TSampler sampler = {};
1916     bool cubeCompare = false;
1917     if (node.isTexture()) {
1918         sampler = glslangArguments[0]->getAsTyped()->getType().getSampler();
1919         cubeCompare = sampler.dim == glslang::EsdCube && sampler.arrayed && sampler.shadow;
1920     }
1921
1922     for (int i = 0; i < (int)glslangArguments.size(); ++i) {
1923         builder.clearAccessChain();
1924         glslangArguments[i]->traverse(this);
1925
1926         // Special case l-value operands
1927         bool lvalue = false;
1928         switch (node.getOp()) {
1929         case glslang::EOpImageAtomicAdd:
1930         case glslang::EOpImageAtomicMin:
1931         case glslang::EOpImageAtomicMax:
1932         case glslang::EOpImageAtomicAnd:
1933         case glslang::EOpImageAtomicOr:
1934         case glslang::EOpImageAtomicXor:
1935         case glslang::EOpImageAtomicExchange:
1936         case glslang::EOpImageAtomicCompSwap:
1937             if (i == 0)
1938                 lvalue = true;
1939             break;
1940         case glslang::EOpSparseTexture:
1941             if ((cubeCompare && i == 3) || (! cubeCompare && i == 2))
1942                 lvalue = true;
1943             break;
1944         case glslang::EOpSparseTextureClamp:
1945             if ((cubeCompare && i == 4) || (! cubeCompare && i == 3))
1946                 lvalue = true;
1947             break;
1948         case glslang::EOpSparseTextureLod:
1949         case glslang::EOpSparseTextureOffset:
1950             if (i == 3)
1951                 lvalue = true;
1952             break;
1953         case glslang::EOpSparseTextureFetch:
1954             if ((sampler.dim != glslang::EsdRect && i == 3) || (sampler.dim == glslang::EsdRect && i == 2))
1955                 lvalue = true;
1956             break;
1957         case glslang::EOpSparseTextureFetchOffset:
1958             if ((sampler.dim != glslang::EsdRect && i == 4) || (sampler.dim == glslang::EsdRect && i == 3))
1959                 lvalue = true;
1960             break;
1961         case glslang::EOpSparseTextureLodOffset:
1962         case glslang::EOpSparseTextureGrad:
1963         case glslang::EOpSparseTextureOffsetClamp:
1964             if (i == 4)
1965                 lvalue = true;
1966             break;
1967         case glslang::EOpSparseTextureGradOffset:
1968         case glslang::EOpSparseTextureGradClamp:
1969             if (i == 5)
1970                 lvalue = true;
1971             break;
1972         case glslang::EOpSparseTextureGradOffsetClamp:
1973             if (i == 6)
1974                 lvalue = true;
1975             break;
1976          case glslang::EOpSparseTextureGather:
1977             if ((sampler.shadow && i == 3) || (! sampler.shadow && i == 2))
1978                 lvalue = true;
1979             break;
1980         case glslang::EOpSparseTextureGatherOffset:
1981         case glslang::EOpSparseTextureGatherOffsets:
1982             if ((sampler.shadow && i == 4) || (! sampler.shadow && i == 3))
1983                 lvalue = true;
1984             break;
1985         default:
1986             break;
1987         }
1988
1989         if (lvalue)
1990             arguments.push_back(builder.accessChainGetLValue());
1991         else
1992             arguments.push_back(builder.accessChainLoad(convertGlslangToSpvType(glslangArguments[i]->getAsTyped()->getType())));
1993     }
1994 }
1995
1996 void TGlslangToSpvTraverser::translateArguments(glslang::TIntermUnary& node, std::vector<spv::Id>& arguments)
1997 {
1998     builder.clearAccessChain();
1999     node.getOperand()->traverse(this);
2000     arguments.push_back(builder.accessChainLoad(convertGlslangToSpvType(node.getOperand()->getType())));
2001 }
2002
2003 spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermOperator* node)
2004 {
2005     if (! node->isImage() && ! node->isTexture()) {
2006         return spv::NoResult;
2007     }
2008
2009     // Process a GLSL texturing op (will be SPV image)
2010     const glslang::TSampler sampler = node->getAsAggregate() ? node->getAsAggregate()->getSequence()[0]->getAsTyped()->getType().getSampler()
2011                                                              : node->getAsUnaryNode()->getOperand()->getAsTyped()->getType().getSampler();
2012     std::vector<spv::Id> arguments;
2013     if (node->getAsAggregate())
2014         translateArguments(*node->getAsAggregate(), arguments);
2015     else
2016         translateArguments(*node->getAsUnaryNode(), arguments);
2017     spv::Decoration precision = TranslatePrecisionDecoration(node->getType());
2018
2019     spv::Builder::TextureParameters params = { };
2020     params.sampler = arguments[0];
2021
2022     glslang::TCrackedTextureOp cracked;
2023     node->crackTexture(sampler, cracked);
2024
2025     // Check for queries
2026     if (cracked.query) {
2027         // a sampled image needs to have the image extracted first
2028         if (builder.isSampledImage(params.sampler))
2029             params.sampler = builder.createUnaryOp(spv::OpImage, builder.getImageType(params.sampler), params.sampler);
2030         switch (node->getOp()) {
2031         case glslang::EOpImageQuerySize:
2032         case glslang::EOpTextureQuerySize:
2033             if (arguments.size() > 1) {
2034                 params.lod = arguments[1];
2035                 return builder.createTextureQueryCall(spv::OpImageQuerySizeLod, params);
2036             } else
2037                 return builder.createTextureQueryCall(spv::OpImageQuerySize, params);
2038         case glslang::EOpImageQuerySamples:
2039         case glslang::EOpTextureQuerySamples:
2040             return builder.createTextureQueryCall(spv::OpImageQuerySamples, params);
2041         case glslang::EOpTextureQueryLod:
2042             params.coords = arguments[1];
2043             return builder.createTextureQueryCall(spv::OpImageQueryLod, params);
2044         case glslang::EOpTextureQueryLevels:
2045             return builder.createTextureQueryCall(spv::OpImageQueryLevels, params);
2046         case glslang::EOpSparseTexelsResident:
2047             return builder.createUnaryOp(spv::OpImageSparseTexelsResident, builder.makeBoolType(), arguments[0]);
2048         default:
2049             assert(0);
2050             break;
2051         }
2052     }
2053
2054     // Check for image functions other than queries
2055     if (node->isImage()) {
2056         std::vector<spv::Id> operands;
2057         auto opIt = arguments.begin();
2058         operands.push_back(*(opIt++));
2059         operands.push_back(*(opIt++));
2060         if (node->getOp() == glslang::EOpImageLoad) {
2061             if (sampler.ms) {
2062                 operands.push_back(spv::ImageOperandsSampleMask);
2063                 operands.push_back(*opIt);
2064             }
2065             return builder.createOp(spv::OpImageRead, convertGlslangToSpvType(node->getType()), operands);
2066         } else if (node->getOp() == glslang::EOpImageStore) {
2067             if (sampler.ms) {
2068                 operands.push_back(*(opIt + 1));
2069                 operands.push_back(spv::ImageOperandsSampleMask);
2070                 operands.push_back(*opIt);
2071             } else
2072                 operands.push_back(*opIt);
2073             builder.createNoResultOp(spv::OpImageWrite, operands);
2074             return spv::NoResult;
2075         } else if (node->isSparseImage()) {
2076             spv::MissingFunctionality("sparse image functions");
2077             return spv::NoResult;
2078         }
2079         else {
2080             // Process image atomic operations
2081
2082             // GLSL "IMAGE_PARAMS" will involve in constructing an image texel pointer and this pointer,
2083             // as the first source operand, is required by SPIR-V atomic operations.
2084             operands.push_back(sampler.ms ? *(opIt++) : 0); // For non-MS, the value should be 0
2085
2086             spv::Id resultTypeId = builder.makePointer(spv::StorageClassImage, convertGlslangToSpvType(node->getType()));
2087             spv::Id pointer = builder.createOp(spv::OpImageTexelPointer, resultTypeId, operands);
2088
2089             std::vector<spv::Id> operands;
2090             operands.push_back(pointer);
2091             for (; opIt != arguments.end(); ++opIt)
2092                 operands.push_back(*opIt);
2093
2094             return createAtomicOperation(node->getOp(), precision, convertGlslangToSpvType(node->getType()), operands, node->getBasicType());
2095         }
2096     }
2097
2098     // Check for texture functions other than queries
2099     bool sparse = node->isSparseTexture();
2100     bool cubeCompare = sampler.dim == glslang::EsdCube && sampler.arrayed && sampler.shadow;
2101
2102     // check for bias argument
2103     bool bias = false;
2104     if (! cracked.lod && ! cracked.gather && ! cracked.grad && ! cracked.fetch && ! cubeCompare) {
2105         int nonBiasArgCount = 2;
2106         if (cracked.offset)
2107             ++nonBiasArgCount;
2108         if (cracked.grad)
2109             nonBiasArgCount += 2;
2110         if (cracked.lodClamp)
2111             ++nonBiasArgCount;
2112         if (sparse)
2113             ++nonBiasArgCount;
2114
2115         if ((int)arguments.size() > nonBiasArgCount)
2116             bias = true;
2117     }
2118
2119     // set the rest of the arguments
2120
2121     params.coords = arguments[1];
2122     int extraArgs = 0;
2123
2124     // sort out where Dref is coming from
2125     if (cubeCompare) {
2126         params.Dref = arguments[2];
2127         ++extraArgs;
2128     } else if (sampler.shadow && cracked.gather) {
2129         params.Dref = arguments[2];
2130         ++extraArgs;
2131     } else if (sampler.shadow) {
2132         std::vector<spv::Id> indexes;
2133         int comp;
2134         if (cracked.proj)
2135             comp = 2;  // "The resulting 3rd component of P in the shadow forms is used as Dref"
2136         else
2137             comp = builder.getNumComponents(params.coords) - 1;
2138         indexes.push_back(comp);
2139         params.Dref = builder.createCompositeExtract(params.coords, builder.getScalarTypeId(builder.getTypeId(params.coords)), indexes);
2140     }
2141     if (cracked.lod) {
2142         params.lod = arguments[2];
2143         ++extraArgs;
2144     } else if (sampler.ms) {
2145         params.sample = arguments[2]; // For MS, "sample" should be specified
2146         ++extraArgs;
2147     }
2148     if (cracked.grad) {
2149         params.gradX = arguments[2 + extraArgs];
2150         params.gradY = arguments[3 + extraArgs];
2151         extraArgs += 2;
2152     }
2153     if (cracked.offset) {
2154         params.offset = arguments[2 + extraArgs];
2155         ++extraArgs;
2156     } else if (cracked.offsets) {
2157         params.offsets = arguments[2 + extraArgs];
2158         ++extraArgs;
2159     }
2160     if (cracked.lodClamp) {
2161         params.lodClamp = arguments[2 + extraArgs];
2162         ++extraArgs;
2163     }
2164     if (sparse) {
2165         params.texelOut = arguments[2 + extraArgs];
2166         ++extraArgs;
2167     }
2168     if (bias) {
2169         params.bias = arguments[2 + extraArgs];
2170         ++extraArgs;
2171     }
2172     if (cracked.gather && ! sampler.shadow) {
2173         // default component is 0, if missing, otherwise an argument
2174         if (2 + extraArgs < (int)arguments.size()) {
2175             params.comp = arguments[2 + extraArgs];
2176             ++extraArgs;
2177         } else {
2178             params.comp = builder.makeIntConstant(0);
2179         }
2180     }
2181
2182     return builder.createTextureCall(precision, convertGlslangToSpvType(node->getType()), sparse, cracked.fetch, cracked.proj, cracked.gather, params);
2183 }
2184
2185 spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAggregate* node)
2186 {
2187     // Grab the function's pointer from the previously created function
2188     spv::Function* function = functionMap[node->getName().c_str()];
2189     if (! function)
2190         return 0;
2191
2192     const glslang::TIntermSequence& glslangArgs = node->getSequence();
2193     const glslang::TQualifierList& qualifiers = node->getQualifierList();
2194
2195     //  See comments in makeFunctions() for details about the semantics for parameter passing.
2196     //
2197     // These imply we need a four step process:
2198     // 1. Evaluate the arguments
2199     // 2. Allocate and make copies of in, out, and inout arguments
2200     // 3. Make the call
2201     // 4. Copy back the results
2202
2203     // 1. Evaluate the arguments
2204     std::vector<spv::Builder::AccessChain> lValues;
2205     std::vector<spv::Id> rValues;
2206     std::vector<spv::Id> argTypes;
2207     for (int a = 0; a < (int)glslangArgs.size(); ++a) {
2208         // build l-value
2209         builder.clearAccessChain();
2210         glslangArgs[a]->traverse(this);
2211         argTypes.push_back(convertGlslangToSpvType(glslangArgs[a]->getAsTyped()->getType()));
2212         // keep outputs as l-values, evaluate input-only as r-values
2213         if (qualifiers[a] != glslang::EvqConstReadOnly) {
2214             // save l-value
2215             lValues.push_back(builder.getAccessChain());
2216         } else {
2217             // process r-value
2218             rValues.push_back(builder.accessChainLoad(argTypes.back()));
2219         }
2220     }
2221
2222     // 2. Allocate space for anything needing a copy, and if it's "in" or "inout"
2223     // copy the original into that space.
2224     //
2225     // Also, build up the list of actual arguments to pass in for the call
2226     int lValueCount = 0;
2227     int rValueCount = 0;
2228     std::vector<spv::Id> spvArgs;
2229     for (int a = 0; a < (int)glslangArgs.size(); ++a) {
2230         spv::Id arg;
2231         if (qualifiers[a] != glslang::EvqConstReadOnly) {
2232             // need space to hold the copy
2233             const glslang::TType& paramType = glslangArgs[a]->getAsTyped()->getType();
2234             arg = builder.createVariable(spv::StorageClassFunction, convertGlslangToSpvType(paramType), "param");
2235             if (qualifiers[a] == glslang::EvqIn || qualifiers[a] == glslang::EvqInOut) {
2236                 // need to copy the input into output space
2237                 builder.setAccessChain(lValues[lValueCount]);
2238                 spv::Id copy = builder.accessChainLoad(argTypes[a]);
2239                 builder.createStore(copy, arg);
2240             }
2241             ++lValueCount;
2242         } else {
2243             arg = rValues[rValueCount];
2244             ++rValueCount;
2245         }
2246         spvArgs.push_back(arg);
2247     }
2248
2249     // 3. Make the call.
2250     spv::Id result = builder.createFunctionCall(function, spvArgs);
2251
2252     // 4. Copy back out an "out" arguments.
2253     lValueCount = 0;
2254     for (int a = 0; a < (int)glslangArgs.size(); ++a) {
2255         if (qualifiers[a] != glslang::EvqConstReadOnly) {
2256             if (qualifiers[a] == glslang::EvqOut || qualifiers[a] == glslang::EvqInOut) {
2257                 spv::Id copy = builder.createLoad(spvArgs[a]);
2258                 builder.setAccessChain(lValues[lValueCount]);
2259                 builder.accessChainStore(copy);
2260             }
2261             ++lValueCount;
2262         }
2263     }
2264
2265     return result;
2266 }
2267
2268 // Translate AST operation to SPV operation, already having SPV-based operands/types.
2269 spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, spv::Decoration precision, 
2270                                                       spv::Id typeId, spv::Id left, spv::Id right,
2271                                                       glslang::TBasicType typeProxy, bool reduceComparison)
2272 {
2273     bool isUnsigned = typeProxy == glslang::EbtUint;
2274     bool isFloat = typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble;
2275
2276     spv::Op binOp = spv::OpNop;
2277     bool needMatchingVectors = true;  // for non-matrix ops, would a scalar need to smear to match a vector?
2278     bool comparison = false;
2279
2280     switch (op) {
2281     case glslang::EOpAdd:
2282     case glslang::EOpAddAssign:
2283         if (isFloat)
2284             binOp = spv::OpFAdd;
2285         else
2286             binOp = spv::OpIAdd;
2287         break;
2288     case glslang::EOpSub:
2289     case glslang::EOpSubAssign:
2290         if (isFloat)
2291             binOp = spv::OpFSub;
2292         else
2293             binOp = spv::OpISub;
2294         break;
2295     case glslang::EOpMul:
2296     case glslang::EOpMulAssign:
2297         if (isFloat)
2298             binOp = spv::OpFMul;
2299         else
2300             binOp = spv::OpIMul;
2301         break;
2302     case glslang::EOpVectorTimesScalar:
2303     case glslang::EOpVectorTimesScalarAssign:
2304         if (isFloat) {
2305             if (builder.isVector(right))
2306                 std::swap(left, right);
2307             assert(builder.isScalar(right));
2308             needMatchingVectors = false;
2309             binOp = spv::OpVectorTimesScalar;
2310         } else
2311             binOp = spv::OpIMul;
2312         break;
2313     case glslang::EOpVectorTimesMatrix:
2314     case glslang::EOpVectorTimesMatrixAssign:
2315         binOp = spv::OpVectorTimesMatrix;
2316         break;
2317     case glslang::EOpMatrixTimesVector:
2318         binOp = spv::OpMatrixTimesVector;
2319         break;
2320     case glslang::EOpMatrixTimesScalar:
2321     case glslang::EOpMatrixTimesScalarAssign:
2322         binOp = spv::OpMatrixTimesScalar;
2323         break;
2324     case glslang::EOpMatrixTimesMatrix:
2325     case glslang::EOpMatrixTimesMatrixAssign:
2326         binOp = spv::OpMatrixTimesMatrix;
2327         break;
2328     case glslang::EOpOuterProduct:
2329         binOp = spv::OpOuterProduct;
2330         needMatchingVectors = false;
2331         break;
2332
2333     case glslang::EOpDiv:
2334     case glslang::EOpDivAssign:
2335         if (isFloat)
2336             binOp = spv::OpFDiv;
2337         else if (isUnsigned)
2338             binOp = spv::OpUDiv;
2339         else
2340             binOp = spv::OpSDiv;
2341         break;
2342     case glslang::EOpMod:
2343     case glslang::EOpModAssign:
2344         if (isFloat)
2345             binOp = spv::OpFMod;
2346         else if (isUnsigned)
2347             binOp = spv::OpUMod;
2348         else
2349             binOp = spv::OpSMod;
2350         break;
2351     case glslang::EOpRightShift:
2352     case glslang::EOpRightShiftAssign:
2353         if (isUnsigned)
2354             binOp = spv::OpShiftRightLogical;
2355         else
2356             binOp = spv::OpShiftRightArithmetic;
2357         break;
2358     case glslang::EOpLeftShift:
2359     case glslang::EOpLeftShiftAssign:
2360         binOp = spv::OpShiftLeftLogical;
2361         break;
2362     case glslang::EOpAnd:
2363     case glslang::EOpAndAssign:
2364         binOp = spv::OpBitwiseAnd;
2365         break;
2366     case glslang::EOpLogicalAnd:
2367         needMatchingVectors = false;
2368         binOp = spv::OpLogicalAnd;
2369         break;
2370     case glslang::EOpInclusiveOr:
2371     case glslang::EOpInclusiveOrAssign:
2372         binOp = spv::OpBitwiseOr;
2373         break;
2374     case glslang::EOpLogicalOr:
2375         needMatchingVectors = false;
2376         binOp = spv::OpLogicalOr;
2377         break;
2378     case glslang::EOpExclusiveOr:
2379     case glslang::EOpExclusiveOrAssign:
2380         binOp = spv::OpBitwiseXor;
2381         break;
2382     case glslang::EOpLogicalXor:
2383         needMatchingVectors = false;
2384         binOp = spv::OpLogicalNotEqual;
2385         break;
2386
2387     case glslang::EOpLessThan:
2388     case glslang::EOpGreaterThan:
2389     case glslang::EOpLessThanEqual:
2390     case glslang::EOpGreaterThanEqual:
2391     case glslang::EOpEqual:
2392     case glslang::EOpNotEqual:
2393     case glslang::EOpVectorEqual:
2394     case glslang::EOpVectorNotEqual:
2395         comparison = true;
2396         break;
2397     default:
2398         break;
2399     }
2400
2401     // handle mapped binary operations (should be non-comparison)
2402     if (binOp != spv::OpNop) {
2403         assert(comparison == false);
2404         if (builder.isMatrix(left) || builder.isMatrix(right))
2405             return createBinaryMatrixOperation(binOp, precision, typeId, left, right);
2406
2407         // No matrix involved; make both operands be the same number of components, if needed
2408         if (needMatchingVectors)
2409             builder.promoteScalar(precision, left, right);
2410
2411         spv::Id id = builder.createBinOp(binOp, typeId, left, right);
2412         builder.setPrecision(id, precision);
2413
2414         return id;
2415     }
2416
2417     if (! comparison)
2418         return 0;
2419
2420     // Handle comparison instructions
2421
2422     if (reduceComparison && (builder.isVector(left) || builder.isMatrix(left) || builder.isAggregate(left))) {
2423         assert(op == glslang::EOpEqual || op == glslang::EOpNotEqual);
2424
2425         return builder.createCompositeCompare(precision, left, right, op == glslang::EOpEqual);
2426     }
2427
2428     switch (op) {
2429     case glslang::EOpLessThan:
2430         if (isFloat)
2431             binOp = spv::OpFOrdLessThan;
2432         else if (isUnsigned)
2433             binOp = spv::OpULessThan;
2434         else
2435             binOp = spv::OpSLessThan;
2436         break;
2437     case glslang::EOpGreaterThan:
2438         if (isFloat)
2439             binOp = spv::OpFOrdGreaterThan;
2440         else if (isUnsigned)
2441             binOp = spv::OpUGreaterThan;
2442         else
2443             binOp = spv::OpSGreaterThan;
2444         break;
2445     case glslang::EOpLessThanEqual:
2446         if (isFloat)
2447             binOp = spv::OpFOrdLessThanEqual;
2448         else if (isUnsigned)
2449             binOp = spv::OpULessThanEqual;
2450         else
2451             binOp = spv::OpSLessThanEqual;
2452         break;
2453     case glslang::EOpGreaterThanEqual:
2454         if (isFloat)
2455             binOp = spv::OpFOrdGreaterThanEqual;
2456         else if (isUnsigned)
2457             binOp = spv::OpUGreaterThanEqual;
2458         else
2459             binOp = spv::OpSGreaterThanEqual;
2460         break;
2461     case glslang::EOpEqual:
2462     case glslang::EOpVectorEqual:
2463         if (isFloat)
2464             binOp = spv::OpFOrdEqual;
2465         else
2466             binOp = spv::OpIEqual;
2467         break;
2468     case glslang::EOpNotEqual:
2469     case glslang::EOpVectorNotEqual:
2470         if (isFloat)
2471             binOp = spv::OpFOrdNotEqual;
2472         else
2473             binOp = spv::OpINotEqual;
2474         break;
2475     default:
2476         break;
2477     }
2478
2479     if (binOp != spv::OpNop) {
2480         spv::Id id = builder.createBinOp(binOp, typeId, left, right);
2481         builder.setPrecision(id, precision);
2482
2483         return id;
2484     }
2485
2486     return 0;
2487 }
2488
2489 //
2490 // Translate AST matrix operation to SPV operation, already having SPV-based operands/types.
2491 // These can be any of:
2492 //
2493 //   matrix * scalar
2494 //   scalar * matrix
2495 //   matrix * matrix     linear algebraic
2496 //   matrix * vector
2497 //   vector * matrix
2498 //   matrix * matrix     componentwise
2499 //   matrix op matrix    op in {+, -, /}
2500 //   matrix op scalar    op in {+, -, /}
2501 //   scalar op matrix    op in {+, -, /}
2502 //
2503 spv::Id TGlslangToSpvTraverser::createBinaryMatrixOperation(spv::Op op, spv::Decoration precision, spv::Id typeId, spv::Id left, spv::Id right)
2504 {
2505     bool firstClass = true;
2506
2507     // First, handle first-class matrix operations (* and matrix/scalar)
2508     switch (op) {
2509     case spv::OpFDiv:
2510         if (builder.isMatrix(left) && builder.isScalar(right)) {
2511             // turn matrix / scalar into a multiply...
2512             right = builder.createBinOp(spv::OpFDiv, builder.getTypeId(right), builder.makeFloatConstant(1.0F), right);
2513             op = spv::OpMatrixTimesScalar;
2514         } else
2515             firstClass = false;
2516         break;
2517     case spv::OpMatrixTimesScalar:
2518         if (builder.isMatrix(right))
2519             std::swap(left, right);
2520         assert(builder.isScalar(right));
2521         break;
2522     case spv::OpVectorTimesMatrix:
2523         assert(builder.isVector(left));
2524         assert(builder.isMatrix(right));
2525         break;
2526     case spv::OpMatrixTimesVector:
2527         assert(builder.isMatrix(left));
2528         assert(builder.isVector(right));
2529         break;
2530     case spv::OpMatrixTimesMatrix:
2531         assert(builder.isMatrix(left));
2532         assert(builder.isMatrix(right));
2533         break;
2534     default:
2535         firstClass = false;
2536         break;
2537     }
2538
2539     if (firstClass) {
2540         spv::Id id = builder.createBinOp(op, typeId, left, right);
2541         builder.setPrecision(id, precision);
2542
2543         return id;
2544     }
2545
2546     // Handle component-wise +, -, *, and / for all combinations of type.
2547     // The result type of all of them is the same type as the (a) matrix operand.
2548     // The algorithm is to:
2549     //   - break the matrix(es) into vectors
2550     //   - smear any scalar to a vector
2551     //   - do vector operations
2552     //   - make a matrix out the vector results
2553     switch (op) {
2554     case spv::OpFAdd:
2555     case spv::OpFSub:
2556     case spv::OpFDiv:
2557     case spv::OpFMul:
2558     {
2559         // one time set up...
2560         bool  leftMat = builder.isMatrix(left);
2561         bool rightMat = builder.isMatrix(right);
2562         unsigned int numCols = leftMat ? builder.getNumColumns(left) : builder.getNumColumns(right);
2563         int numRows = leftMat ? builder.getNumRows(left) : builder.getNumRows(right);
2564         spv::Id scalarType = builder.getScalarTypeId(typeId);
2565         spv::Id vecType = builder.makeVectorType(scalarType, numRows);
2566         std::vector<spv::Id> results;
2567         spv::Id smearVec = spv::NoResult;
2568         if (builder.isScalar(left))
2569             smearVec = builder.smearScalar(precision, left, vecType);
2570         else if (builder.isScalar(right))
2571             smearVec = builder.smearScalar(precision, right, vecType);
2572
2573         // do each vector op
2574         for (unsigned int c = 0; c < numCols; ++c) {
2575             std::vector<unsigned int> indexes;
2576             indexes.push_back(c);
2577             spv::Id  leftVec =  leftMat ? builder.createCompositeExtract( left, vecType, indexes) : smearVec;
2578             spv::Id rightVec = rightMat ? builder.createCompositeExtract(right, vecType, indexes) : smearVec;
2579             results.push_back(builder.createBinOp(op, vecType, leftVec, rightVec));
2580             builder.setPrecision(results.back(), precision);
2581         }
2582
2583         // put the pieces together
2584         spv::Id id = builder.createCompositeConstruct(typeId, results);
2585         builder.setPrecision(id, precision);
2586         return id;
2587     }
2588     default:
2589         assert(0);
2590         return spv::NoResult;
2591     }
2592 }
2593
2594 spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, spv::Id operand, glslang::TBasicType typeProxy)
2595 {
2596     spv::Op unaryOp = spv::OpNop;
2597     int libCall = -1;
2598     bool isUnsigned = typeProxy == glslang::EbtUint;
2599     bool isFloat = typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble;
2600
2601     switch (op) {
2602     case glslang::EOpNegative:
2603         if (isFloat)
2604             unaryOp = spv::OpFNegate;
2605         else
2606             unaryOp = spv::OpSNegate;
2607         break;
2608
2609     case glslang::EOpLogicalNot:
2610     case glslang::EOpVectorLogicalNot:
2611         unaryOp = spv::OpLogicalNot;
2612         break;
2613     case glslang::EOpBitwiseNot:
2614         unaryOp = spv::OpNot;
2615         break;
2616
2617     case glslang::EOpDeterminant:
2618         libCall = spv::GLSLstd450Determinant;
2619         break;
2620     case glslang::EOpMatrixInverse:
2621         libCall = spv::GLSLstd450MatrixInverse;
2622         break;
2623     case glslang::EOpTranspose:
2624         unaryOp = spv::OpTranspose;
2625         break;
2626
2627     case glslang::EOpRadians:
2628         libCall = spv::GLSLstd450Radians;
2629         break;
2630     case glslang::EOpDegrees:
2631         libCall = spv::GLSLstd450Degrees;
2632         break;
2633     case glslang::EOpSin:
2634         libCall = spv::GLSLstd450Sin;
2635         break;
2636     case glslang::EOpCos:
2637         libCall = spv::GLSLstd450Cos;
2638         break;
2639     case glslang::EOpTan:
2640         libCall = spv::GLSLstd450Tan;
2641         break;
2642     case glslang::EOpAcos:
2643         libCall = spv::GLSLstd450Acos;
2644         break;
2645     case glslang::EOpAsin:
2646         libCall = spv::GLSLstd450Asin;
2647         break;
2648     case glslang::EOpAtan:
2649         libCall = spv::GLSLstd450Atan;
2650         break;
2651
2652     case glslang::EOpAcosh:
2653         libCall = spv::GLSLstd450Acosh;
2654         break;
2655     case glslang::EOpAsinh:
2656         libCall = spv::GLSLstd450Asinh;
2657         break;
2658     case glslang::EOpAtanh:
2659         libCall = spv::GLSLstd450Atanh;
2660         break;
2661     case glslang::EOpTanh:
2662         libCall = spv::GLSLstd450Tanh;
2663         break;
2664     case glslang::EOpCosh:
2665         libCall = spv::GLSLstd450Cosh;
2666         break;
2667     case glslang::EOpSinh:
2668         libCall = spv::GLSLstd450Sinh;
2669         break;
2670
2671     case glslang::EOpLength:
2672         libCall = spv::GLSLstd450Length;
2673         break;
2674     case glslang::EOpNormalize:
2675         libCall = spv::GLSLstd450Normalize;
2676         break;
2677
2678     case glslang::EOpExp:
2679         libCall = spv::GLSLstd450Exp;
2680         break;
2681     case glslang::EOpLog:
2682         libCall = spv::GLSLstd450Log;
2683         break;
2684     case glslang::EOpExp2:
2685         libCall = spv::GLSLstd450Exp2;
2686         break;
2687     case glslang::EOpLog2:
2688         libCall = spv::GLSLstd450Log2;
2689         break;
2690     case glslang::EOpSqrt:
2691         libCall = spv::GLSLstd450Sqrt;
2692         break;
2693     case glslang::EOpInverseSqrt:
2694         libCall = spv::GLSLstd450InverseSqrt;
2695         break;
2696
2697     case glslang::EOpFloor:
2698         libCall = spv::GLSLstd450Floor;
2699         break;
2700     case glslang::EOpTrunc:
2701         libCall = spv::GLSLstd450Trunc;
2702         break;
2703     case glslang::EOpRound:
2704         libCall = spv::GLSLstd450Round;
2705         break;
2706     case glslang::EOpRoundEven:
2707         libCall = spv::GLSLstd450RoundEven;
2708         break;
2709     case glslang::EOpCeil:
2710         libCall = spv::GLSLstd450Ceil;
2711         break;
2712     case glslang::EOpFract:
2713         libCall = spv::GLSLstd450Fract;
2714         break;
2715
2716     case glslang::EOpIsNan:
2717         unaryOp = spv::OpIsNan;
2718         break;
2719     case glslang::EOpIsInf:
2720         unaryOp = spv::OpIsInf;
2721         break;
2722
2723     case glslang::EOpFloatBitsToInt:
2724     case glslang::EOpFloatBitsToUint:
2725     case glslang::EOpIntBitsToFloat:
2726     case glslang::EOpUintBitsToFloat:
2727         unaryOp = spv::OpBitcast;
2728         break;
2729
2730     case glslang::EOpPackSnorm2x16:
2731         libCall = spv::GLSLstd450PackSnorm2x16;
2732         break;
2733     case glslang::EOpUnpackSnorm2x16:
2734         libCall = spv::GLSLstd450UnpackSnorm2x16;
2735         break;
2736     case glslang::EOpPackUnorm2x16:
2737         libCall = spv::GLSLstd450PackUnorm2x16;
2738         break;
2739     case glslang::EOpUnpackUnorm2x16:
2740         libCall = spv::GLSLstd450UnpackUnorm2x16;
2741         break;
2742     case glslang::EOpPackHalf2x16:
2743         libCall = spv::GLSLstd450PackHalf2x16;
2744         break;
2745     case glslang::EOpUnpackHalf2x16:
2746         libCall = spv::GLSLstd450UnpackHalf2x16;
2747         break;
2748     case glslang::EOpPackSnorm4x8:
2749         libCall = spv::GLSLstd450PackSnorm4x8;
2750         break;
2751     case glslang::EOpUnpackSnorm4x8:
2752         libCall = spv::GLSLstd450UnpackSnorm4x8;
2753         break;
2754     case glslang::EOpPackUnorm4x8:
2755         libCall = spv::GLSLstd450PackUnorm4x8;
2756         break;
2757     case glslang::EOpUnpackUnorm4x8:
2758         libCall = spv::GLSLstd450UnpackUnorm4x8;
2759         break;
2760     case glslang::EOpPackDouble2x32:
2761         libCall = spv::GLSLstd450PackDouble2x32;
2762         break;
2763     case glslang::EOpUnpackDouble2x32:
2764         libCall = spv::GLSLstd450UnpackDouble2x32;
2765         break;
2766
2767     case glslang::EOpDPdx:
2768         unaryOp = spv::OpDPdx;
2769         break;
2770     case glslang::EOpDPdy:
2771         unaryOp = spv::OpDPdy;
2772         break;
2773     case glslang::EOpFwidth:
2774         unaryOp = spv::OpFwidth;
2775         break;
2776     case glslang::EOpDPdxFine:
2777         unaryOp = spv::OpDPdxFine;
2778         break;
2779     case glslang::EOpDPdyFine:
2780         unaryOp = spv::OpDPdyFine;
2781         break;
2782     case glslang::EOpFwidthFine:
2783         unaryOp = spv::OpFwidthFine;
2784         break;
2785     case glslang::EOpDPdxCoarse:
2786         unaryOp = spv::OpDPdxCoarse;
2787         break;
2788     case glslang::EOpDPdyCoarse:
2789         unaryOp = spv::OpDPdyCoarse;
2790         break;
2791     case glslang::EOpFwidthCoarse:
2792         unaryOp = spv::OpFwidthCoarse;
2793         break;
2794     case glslang::EOpInterpolateAtCentroid:
2795         libCall = spv::GLSLstd450InterpolateAtCentroid;
2796         break;
2797     case glslang::EOpAny:
2798         unaryOp = spv::OpAny;
2799         break;
2800     case glslang::EOpAll:
2801         unaryOp = spv::OpAll;
2802         break;
2803
2804     case glslang::EOpAbs:
2805         if (isFloat)
2806             libCall = spv::GLSLstd450FAbs;
2807         else
2808             libCall = spv::GLSLstd450SAbs;
2809         break;
2810     case glslang::EOpSign:
2811         if (isFloat)
2812             libCall = spv::GLSLstd450FSign;
2813         else
2814             libCall = spv::GLSLstd450SSign;
2815         break;
2816
2817     case glslang::EOpAtomicCounterIncrement:
2818     case glslang::EOpAtomicCounterDecrement:
2819     case glslang::EOpAtomicCounter:
2820     {
2821         // Handle all of the atomics in one place, in createAtomicOperation()
2822         std::vector<spv::Id> operands;
2823         operands.push_back(operand);
2824         return createAtomicOperation(op, precision, typeId, operands, typeProxy);
2825     }
2826
2827     case glslang::EOpImageLoad:
2828         unaryOp = spv::OpImageRead;
2829         break;
2830
2831     case glslang::EOpBitFieldReverse:
2832         unaryOp = spv::OpBitReverse;
2833         break;
2834     case glslang::EOpBitCount:
2835         unaryOp = spv::OpBitCount;
2836         break;
2837     case glslang::EOpFindLSB:
2838         libCall = spv::GLSLstd450FindILsb;
2839         break;
2840     case glslang::EOpFindMSB:
2841         if (isUnsigned)
2842             libCall = spv::GLSLstd450FindUMsb;
2843         else
2844             libCall = spv::GLSLstd450FindSMsb;
2845         break;
2846
2847     default:
2848         return 0;
2849     }
2850
2851     spv::Id id;
2852     if (libCall >= 0) {
2853         std::vector<spv::Id> args;
2854         args.push_back(operand);
2855         id = builder.createBuiltinCall(precision, typeId, stdBuiltins, libCall, args);
2856     } else
2857         id = builder.createUnaryOp(unaryOp, typeId, operand);
2858
2859     builder.setPrecision(id, precision);
2860
2861     return id;
2862 }
2863
2864 spv::Id TGlslangToSpvTraverser::createConversion(glslang::TOperator op, spv::Decoration precision, spv::Id destType, spv::Id operand)
2865 {
2866     spv::Op convOp = spv::OpNop;
2867     spv::Id zero = 0;
2868     spv::Id one = 0;
2869
2870     int vectorSize = builder.isVectorType(destType) ? builder.getNumTypeComponents(destType) : 0;
2871
2872     switch (op) {
2873     case glslang::EOpConvIntToBool:
2874     case glslang::EOpConvUintToBool:
2875         zero = builder.makeUintConstant(0);
2876         zero = makeSmearedConstant(zero, vectorSize);
2877         return builder.createBinOp(spv::OpINotEqual, destType, operand, zero);
2878
2879     case glslang::EOpConvFloatToBool:
2880         zero = builder.makeFloatConstant(0.0F);
2881         zero = makeSmearedConstant(zero, vectorSize);
2882         return builder.createBinOp(spv::OpFOrdNotEqual, destType, operand, zero);
2883
2884     case glslang::EOpConvDoubleToBool:
2885         zero = builder.makeDoubleConstant(0.0);
2886         zero = makeSmearedConstant(zero, vectorSize);
2887         return builder.createBinOp(spv::OpFOrdNotEqual, destType, operand, zero);
2888
2889     case glslang::EOpConvBoolToFloat:
2890         convOp = spv::OpSelect;
2891         zero = builder.makeFloatConstant(0.0);
2892         one  = builder.makeFloatConstant(1.0);
2893         break;
2894     case glslang::EOpConvBoolToDouble:
2895         convOp = spv::OpSelect;
2896         zero = builder.makeDoubleConstant(0.0);
2897         one  = builder.makeDoubleConstant(1.0);
2898         break;
2899     case glslang::EOpConvBoolToInt:
2900         zero = builder.makeIntConstant(0);
2901         one  = builder.makeIntConstant(1);
2902         convOp = spv::OpSelect;
2903         break;
2904     case glslang::EOpConvBoolToUint:
2905         zero = builder.makeUintConstant(0);
2906         one  = builder.makeUintConstant(1);
2907         convOp = spv::OpSelect;
2908         break;
2909
2910     case glslang::EOpConvIntToFloat:
2911     case glslang::EOpConvIntToDouble:
2912         convOp = spv::OpConvertSToF;
2913         break;
2914
2915     case glslang::EOpConvUintToFloat:
2916     case glslang::EOpConvUintToDouble:
2917         convOp = spv::OpConvertUToF;
2918         break;
2919
2920     case glslang::EOpConvDoubleToFloat:
2921     case glslang::EOpConvFloatToDouble:
2922         convOp = spv::OpFConvert;
2923         break;
2924
2925     case glslang::EOpConvFloatToInt:
2926     case glslang::EOpConvDoubleToInt:
2927         convOp = spv::OpConvertFToS;
2928         break;
2929
2930     case glslang::EOpConvUintToInt:
2931     case glslang::EOpConvIntToUint:
2932         convOp = spv::OpBitcast;
2933         break;
2934
2935     case glslang::EOpConvFloatToUint:
2936     case glslang::EOpConvDoubleToUint:
2937         convOp = spv::OpConvertFToU;
2938         break;
2939     default:
2940         break;
2941     }
2942
2943     spv::Id result = 0;
2944     if (convOp == spv::OpNop)
2945         return result;
2946
2947     if (convOp == spv::OpSelect) {
2948         zero = makeSmearedConstant(zero, vectorSize);
2949         one  = makeSmearedConstant(one, vectorSize);
2950         result = builder.createTriOp(convOp, destType, operand, one, zero);
2951     } else
2952         result = builder.createUnaryOp(convOp, destType, operand);
2953
2954     builder.setPrecision(result, precision);
2955
2956     return result;
2957 }
2958
2959 spv::Id TGlslangToSpvTraverser::makeSmearedConstant(spv::Id constant, int vectorSize)
2960 {
2961     if (vectorSize == 0)
2962         return constant;
2963
2964     spv::Id vectorTypeId = builder.makeVectorType(builder.getTypeId(constant), vectorSize);
2965     std::vector<spv::Id> components;
2966     for (int c = 0; c < vectorSize; ++c)
2967         components.push_back(constant);
2968     return builder.makeCompositeConstant(vectorTypeId, components);
2969 }
2970
2971 // For glslang ops that map to SPV atomic opCodes
2972 spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy)
2973 {
2974     spv::Op opCode = spv::OpNop;
2975
2976     switch (op) {
2977     case glslang::EOpAtomicAdd:
2978     case glslang::EOpImageAtomicAdd:
2979         opCode = spv::OpAtomicIAdd;
2980         break;
2981     case glslang::EOpAtomicMin:
2982     case glslang::EOpImageAtomicMin:
2983         opCode = typeProxy == glslang::EbtUint ? spv::OpAtomicUMin : spv::OpAtomicSMin;
2984         break;
2985     case glslang::EOpAtomicMax:
2986     case glslang::EOpImageAtomicMax:
2987         opCode = typeProxy == glslang::EbtUint ? spv::OpAtomicUMax : spv::OpAtomicSMax;
2988         break;
2989     case glslang::EOpAtomicAnd:
2990     case glslang::EOpImageAtomicAnd:
2991         opCode = spv::OpAtomicAnd;
2992         break;
2993     case glslang::EOpAtomicOr:
2994     case glslang::EOpImageAtomicOr:
2995         opCode = spv::OpAtomicOr;
2996         break;
2997     case glslang::EOpAtomicXor:
2998     case glslang::EOpImageAtomicXor:
2999         opCode = spv::OpAtomicXor;
3000         break;
3001     case glslang::EOpAtomicExchange:
3002     case glslang::EOpImageAtomicExchange:
3003         opCode = spv::OpAtomicExchange;
3004         break;
3005     case glslang::EOpAtomicCompSwap:
3006     case glslang::EOpImageAtomicCompSwap:
3007         opCode = spv::OpAtomicCompareExchange;
3008         break;
3009     case glslang::EOpAtomicCounterIncrement:
3010         opCode = spv::OpAtomicIIncrement;
3011         break;
3012     case glslang::EOpAtomicCounterDecrement:
3013         opCode = spv::OpAtomicIDecrement;
3014         break;
3015     case glslang::EOpAtomicCounter:
3016         opCode = spv::OpAtomicLoad;
3017         break;
3018     default:
3019         assert(0);
3020         break;
3021     }
3022
3023     // Sort out the operands
3024     //  - mapping from glslang -> SPV
3025     //  - there are extra SPV operands with no glslang source
3026     //  - compare-exchange swaps the value and comparator
3027     //  - compare-exchange has an extra memory semantics
3028     std::vector<spv::Id> spvAtomicOperands;  // hold the spv operands
3029     auto opIt = operands.begin();            // walk the glslang operands
3030     spvAtomicOperands.push_back(*(opIt++));
3031     spvAtomicOperands.push_back(builder.makeUintConstant(spv::ScopeDevice));     // TBD: what is the correct scope?
3032     spvAtomicOperands.push_back(builder.makeUintConstant(spv::MemorySemanticsMaskNone)); // TBD: what are the correct memory semantics?
3033     if (opCode == spv::OpAtomicCompareExchange) {
3034         // There are 2 memory semantics for compare-exchange. And the operand order of "comparator" and "new value" in GLSL
3035         // differs from that in SPIR-V. Hence, special processing is required.
3036         spvAtomicOperands.push_back(builder.makeUintConstant(spv::MemorySemanticsMaskNone));
3037         spvAtomicOperands.push_back(*(opIt + 1));
3038         spvAtomicOperands.push_back(*opIt);
3039         opIt += 2;
3040     }
3041
3042     // Add the rest of the operands, skipping any that were dealt with above.
3043     for (; opIt != operands.end(); ++opIt)
3044         spvAtomicOperands.push_back(*opIt);
3045
3046     return builder.createOp(opCode, typeId, spvAtomicOperands);
3047 }
3048
3049 spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy)
3050 {
3051     bool isUnsigned = typeProxy == glslang::EbtUint;
3052     bool isFloat = typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble;
3053
3054     spv::Op opCode = spv::OpNop;
3055     int libCall = -1;
3056     size_t consumedOperands = operands.size();
3057     spv::Id typeId0 = 0;
3058     if (consumedOperands > 0)
3059         typeId0 = builder.getTypeId(operands[0]);
3060     spv::Id frexpIntType = 0;
3061
3062     switch (op) {
3063     case glslang::EOpMin:
3064         if (isFloat)
3065             libCall = spv::GLSLstd450FMin;
3066         else if (isUnsigned)
3067             libCall = spv::GLSLstd450UMin;
3068         else
3069             libCall = spv::GLSLstd450SMin;
3070         builder.promoteScalar(precision, operands.front(), operands.back());
3071         break;
3072     case glslang::EOpModf:
3073         libCall = spv::GLSLstd450Modf;
3074         break;
3075     case glslang::EOpMax:
3076         if (isFloat)
3077             libCall = spv::GLSLstd450FMax;
3078         else if (isUnsigned)
3079             libCall = spv::GLSLstd450UMax;
3080         else
3081             libCall = spv::GLSLstd450SMax;
3082         builder.promoteScalar(precision, operands.front(), operands.back());
3083         break;
3084     case glslang::EOpPow:
3085         libCall = spv::GLSLstd450Pow;
3086         break;
3087     case glslang::EOpDot:
3088         opCode = spv::OpDot;
3089         break;
3090     case glslang::EOpAtan:
3091         libCall = spv::GLSLstd450Atan2;
3092         break;
3093
3094     case glslang::EOpClamp:
3095         if (isFloat)
3096             libCall = spv::GLSLstd450FClamp;
3097         else if (isUnsigned)
3098             libCall = spv::GLSLstd450UClamp;
3099         else
3100             libCall = spv::GLSLstd450SClamp;
3101         builder.promoteScalar(precision, operands.front(), operands[1]);
3102         builder.promoteScalar(precision, operands.front(), operands[2]);
3103         break;
3104     case glslang::EOpMix:
3105         if (isFloat)
3106             libCall = spv::GLSLstd450FMix;
3107         else
3108             libCall = spv::GLSLstd450IMix;
3109         builder.promoteScalar(precision, operands.front(), operands.back());
3110         break;
3111     case glslang::EOpStep:
3112         libCall = spv::GLSLstd450Step;
3113         builder.promoteScalar(precision, operands.front(), operands.back());
3114         break;
3115     case glslang::EOpSmoothStep:
3116         libCall = spv::GLSLstd450SmoothStep;
3117         builder.promoteScalar(precision, operands[0], operands[2]);
3118         builder.promoteScalar(precision, operands[1], operands[2]);
3119         break;
3120
3121     case glslang::EOpDistance:
3122         libCall = spv::GLSLstd450Distance;
3123         break;
3124     case glslang::EOpCross:
3125         libCall = spv::GLSLstd450Cross;
3126         break;
3127     case glslang::EOpFaceForward:
3128         libCall = spv::GLSLstd450FaceForward;
3129         break;
3130     case glslang::EOpReflect:
3131         libCall = spv::GLSLstd450Reflect;
3132         break;
3133     case glslang::EOpRefract:
3134         libCall = spv::GLSLstd450Refract;
3135         break;
3136     case glslang::EOpInterpolateAtSample:
3137         libCall = spv::GLSLstd450InterpolateAtSample;
3138         break;
3139     case glslang::EOpInterpolateAtOffset:
3140         libCall = spv::GLSLstd450InterpolateAtOffset;
3141         break;
3142     case glslang::EOpAddCarry:
3143         opCode = spv::OpIAddCarry;
3144         typeId = builder.makeStructResultType(typeId0, typeId0);
3145         consumedOperands = 2;
3146         break;
3147     case glslang::EOpSubBorrow:
3148         opCode = spv::OpISubBorrow;
3149         typeId = builder.makeStructResultType(typeId0, typeId0);
3150         consumedOperands = 2;
3151         break;
3152     case glslang::EOpUMulExtended:
3153         opCode = spv::OpUMulExtended;
3154         typeId = builder.makeStructResultType(typeId0, typeId0);
3155         consumedOperands = 2;
3156         break;
3157     case glslang::EOpIMulExtended:
3158         opCode = spv::OpSMulExtended;
3159         typeId = builder.makeStructResultType(typeId0, typeId0);
3160         consumedOperands = 2;
3161         break;
3162     case glslang::EOpBitfieldExtract:
3163         if (isUnsigned)
3164             opCode = spv::OpBitFieldUExtract;
3165         else
3166             opCode = spv::OpBitFieldSExtract;
3167         break;
3168     case glslang::EOpBitfieldInsert:
3169         opCode = spv::OpBitFieldInsert;
3170         break;
3171
3172     case glslang::EOpFma:
3173         libCall = spv::GLSLstd450Fma;
3174         break;
3175     case glslang::EOpFrexp:
3176         libCall = spv::GLSLstd450FrexpStruct;
3177         if (builder.getNumComponents(operands[0]) == 1)
3178             frexpIntType = builder.makeIntegerType(32, true);
3179         else
3180             frexpIntType = builder.makeVectorType(builder.makeIntegerType(32, true), builder.getNumComponents(operands[0]));
3181         typeId = builder.makeStructResultType(typeId0, frexpIntType);
3182         consumedOperands = 1;
3183         break;
3184     case glslang::EOpLdexp:
3185         libCall = spv::GLSLstd450Ldexp;
3186         break;
3187
3188     default:
3189         return 0;
3190     }
3191
3192     spv::Id id = 0;
3193     if (libCall >= 0) {
3194         // Use an extended instruction from the standard library.
3195         // Construct the call arguments, without modifying the original operands vector.
3196         // We might need the remaining arguments, e.g. in the EOpFrexp case.
3197         std::vector<spv::Id> callArguments(operands.begin(), operands.begin() + consumedOperands);
3198         id = builder.createBuiltinCall(precision, typeId, stdBuiltins, libCall, callArguments);
3199     } else {
3200         switch (consumedOperands) {
3201         case 0:
3202             // should all be handled by visitAggregate and createNoArgOperation
3203             assert(0);
3204             return 0;
3205         case 1:
3206             // should all be handled by createUnaryOperation
3207             assert(0);
3208             return 0;
3209         case 2:
3210             id = builder.createBinOp(opCode, typeId, operands[0], operands[1]);
3211             break;
3212         default:
3213             // anything 3 or over doesn't have l-value operands, so all should be consumed
3214             assert(consumedOperands == operands.size());
3215             id = builder.createOp(opCode, typeId, operands);
3216             break;
3217         }
3218     }
3219
3220     // Decode the return types that were structures
3221     switch (op) {
3222     case glslang::EOpAddCarry:
3223     case glslang::EOpSubBorrow:
3224         builder.createStore(builder.createCompositeExtract(id, typeId0, 1), operands[2]);
3225         id = builder.createCompositeExtract(id, typeId0, 0);
3226         break;
3227     case glslang::EOpUMulExtended:
3228     case glslang::EOpIMulExtended:
3229         builder.createStore(builder.createCompositeExtract(id, typeId0, 0), operands[3]);
3230         builder.createStore(builder.createCompositeExtract(id, typeId0, 1), operands[2]);
3231         break;
3232     case glslang::EOpFrexp:
3233         assert(operands.size() == 2);
3234         builder.createStore(builder.createCompositeExtract(id, frexpIntType, 1), operands[1]);
3235         id = builder.createCompositeExtract(id, typeId0, 0);
3236         break;
3237     default:
3238         break;
3239     }
3240
3241     builder.setPrecision(id, precision);
3242
3243     return id;
3244 }
3245
3246 // Intrinsics with no arguments, no return value, and no precision.
3247 spv::Id TGlslangToSpvTraverser::createNoArgOperation(glslang::TOperator op)
3248 {
3249     // TODO: get the barrier operands correct
3250
3251     switch (op) {
3252     case glslang::EOpEmitVertex:
3253         builder.createNoResultOp(spv::OpEmitVertex);
3254         return 0;
3255     case glslang::EOpEndPrimitive:
3256         builder.createNoResultOp(spv::OpEndPrimitive);
3257         return 0;
3258     case glslang::EOpBarrier:
3259         builder.createMemoryBarrier(spv::ScopeDevice, spv::MemorySemanticsAllMemory);
3260         builder.createControlBarrier(spv::ScopeDevice, spv::ScopeDevice, spv::MemorySemanticsMaskNone);
3261         return 0;
3262     case glslang::EOpMemoryBarrier:
3263         builder.createMemoryBarrier(spv::ScopeDevice, spv::MemorySemanticsAllMemory);
3264         return 0;
3265     case glslang::EOpMemoryBarrierAtomicCounter:
3266         builder.createMemoryBarrier(spv::ScopeDevice, spv::MemorySemanticsAtomicCounterMemoryMask);
3267         return 0;
3268     case glslang::EOpMemoryBarrierBuffer:
3269         builder.createMemoryBarrier(spv::ScopeDevice, spv::MemorySemanticsUniformMemoryMask);
3270         return 0;
3271     case glslang::EOpMemoryBarrierImage:
3272         builder.createMemoryBarrier(spv::ScopeDevice, spv::MemorySemanticsImageMemoryMask);
3273         return 0;
3274     case glslang::EOpMemoryBarrierShared:
3275         builder.createMemoryBarrier(spv::ScopeDevice, spv::MemorySemanticsWorkgroupMemoryMask);
3276         return 0;
3277     case glslang::EOpGroupMemoryBarrier:
3278         builder.createMemoryBarrier(spv::ScopeDevice, spv::MemorySemanticsCrossWorkgroupMemoryMask);
3279         return 0;
3280     default:
3281         spv::MissingFunctionality("unknown operation with no arguments");
3282         return 0;
3283     }
3284 }
3285
3286 spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol)
3287 {
3288     auto iter = symbolValues.find(symbol->getId());
3289     spv::Id id;
3290     if (symbolValues.end() != iter) {
3291         id = iter->second;
3292         return id;
3293     }
3294
3295     // it was not found, create it
3296     id = createSpvVariable(symbol);
3297     symbolValues[symbol->getId()] = id;
3298
3299     if (! symbol->getType().isStruct()) {
3300         addDecoration(id, TranslatePrecisionDecoration(symbol->getType()));
3301         addDecoration(id, TranslateInterpolationDecoration(symbol->getType().getQualifier()));
3302         if (symbol->getQualifier().hasLocation())
3303             builder.addDecoration(id, spv::DecorationLocation, symbol->getQualifier().layoutLocation);
3304         if (symbol->getQualifier().hasIndex())
3305             builder.addDecoration(id, spv::DecorationIndex, symbol->getQualifier().layoutIndex);
3306         if (symbol->getQualifier().hasComponent())
3307             builder.addDecoration(id, spv::DecorationComponent, symbol->getQualifier().layoutComponent);
3308         if (glslangIntermediate->getXfbMode()) {
3309             if (symbol->getQualifier().hasXfbStride())
3310                 builder.addDecoration(id, spv::DecorationXfbStride, symbol->getQualifier().layoutXfbStride);
3311             if (symbol->getQualifier().hasXfbBuffer())
3312                 builder.addDecoration(id, spv::DecorationXfbBuffer, symbol->getQualifier().layoutXfbBuffer);
3313             if (symbol->getQualifier().hasXfbOffset())
3314                 builder.addDecoration(id, spv::DecorationOffset, symbol->getQualifier().layoutXfbOffset);
3315         }
3316     }
3317
3318     addDecoration(id, TranslateInvariantDecoration(symbol->getType().getQualifier()));
3319     if (symbol->getQualifier().hasStream())
3320         builder.addDecoration(id, spv::DecorationStream, symbol->getQualifier().layoutStream);
3321     if (symbol->getQualifier().hasSet())
3322         builder.addDecoration(id, spv::DecorationDescriptorSet, symbol->getQualifier().layoutSet);
3323     if (symbol->getQualifier().hasBinding())
3324         builder.addDecoration(id, spv::DecorationBinding, symbol->getQualifier().layoutBinding);
3325     if (glslangIntermediate->getXfbMode()) {
3326         if (symbol->getQualifier().hasXfbStride())
3327             builder.addDecoration(id, spv::DecorationXfbStride, symbol->getQualifier().layoutXfbStride);
3328         if (symbol->getQualifier().hasXfbBuffer())
3329             builder.addDecoration(id, spv::DecorationXfbBuffer, symbol->getQualifier().layoutXfbBuffer);
3330     }
3331
3332     // built-in variable decorations
3333     spv::BuiltIn builtIn = TranslateBuiltInDecoration(symbol->getQualifier().builtIn);
3334     if (builtIn != spv::BadValue)
3335         builder.addDecoration(id, spv::DecorationBuiltIn, (int)builtIn);
3336
3337     return id;
3338 }
3339
3340 // If 'dec' is valid, add no-operand decoration to an object
3341 void TGlslangToSpvTraverser::addDecoration(spv::Id id, spv::Decoration dec)
3342 {
3343     if (dec != spv::BadValue)
3344         builder.addDecoration(id, dec);
3345 }
3346
3347 // If 'dec' is valid, add a one-operand decoration to an object
3348 void TGlslangToSpvTraverser::addDecoration(spv::Id id, spv::Decoration dec, unsigned value)
3349 {
3350     if (dec != spv::BadValue)
3351         builder.addDecoration(id, dec, value);
3352 }
3353
3354 // If 'dec' is valid, add a no-operand decoration to a struct member
3355 void TGlslangToSpvTraverser::addMemberDecoration(spv::Id id, int member, spv::Decoration dec)
3356 {
3357     if (dec != spv::BadValue)
3358         builder.addMemberDecoration(id, (unsigned)member, dec);
3359 }
3360
3361 // Make a full tree of instructions to build a SPIR-V specialization constant,
3362 // or regularly constant if possible.
3363 //
3364 // TBD: this is not yet done, nor verified to be the best design, it does do the leaf symbols though
3365 //
3366 // Recursively walk the nodes.  The nodes form a tree whose leaves are
3367 // regular constants, which themselves are trees that createSpvConstant()
3368 // recursively walks.  So, this function walks the "top" of the tree:
3369 //  - emit specialization constant-building instructions for specConstant
3370 //  - when running into a non-spec-constant, switch to createSpvConstant()
3371 spv::Id TGlslangToSpvTraverser::createSpvSpecConstant(const glslang::TIntermTyped& node)
3372 {
3373     assert(node.getQualifier().storage == glslang::EvqConst);
3374
3375     // hand off to the non-spec-constant path
3376     assert(node.getAsConstantUnion() != nullptr || node.getAsSymbolNode() != nullptr);
3377     int nextConst = 0;
3378     return createSpvConstant(node.getType(), node.getAsConstantUnion() ? node.getAsConstantUnion()->getConstArray() : node.getAsSymbolNode()->getConstArray(), nextConst, false);
3379 }
3380
3381 // Use 'consts' as the flattened glslang source of scalar constants to recursively
3382 // build the aggregate SPIR-V constant.
3383 //
3384 // If there are not enough elements present in 'consts', 0 will be substituted;
3385 // an empty 'consts' can be used to create a fully zeroed SPIR-V constant.
3386 //
3387 spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TType& glslangType, const glslang::TConstUnionArray& consts, int& nextConst, bool specConstant)
3388 {
3389     // vector of constants for SPIR-V
3390     std::vector<spv::Id> spvConsts;
3391
3392     // Type is used for struct and array constants
3393     spv::Id typeId = convertGlslangToSpvType(glslangType);
3394
3395     if (glslangType.isArray()) {
3396         glslang::TType elementType(glslangType, 0);
3397         for (int i = 0; i < glslangType.getOuterArraySize(); ++i)
3398             spvConsts.push_back(createSpvConstant(elementType, consts, nextConst, false));
3399     } else if (glslangType.isMatrix()) {
3400         glslang::TType vectorType(glslangType, 0);
3401         for (int col = 0; col < glslangType.getMatrixCols(); ++col)
3402             spvConsts.push_back(createSpvConstant(vectorType, consts, nextConst, false));
3403     } else if (glslangType.getStruct()) {
3404         glslang::TVector<glslang::TTypeLoc>::const_iterator iter;
3405         for (iter = glslangType.getStruct()->begin(); iter != glslangType.getStruct()->end(); ++iter)
3406             spvConsts.push_back(createSpvConstant(*iter->type, consts, nextConst, false));
3407     } else if (glslangType.isVector()) {
3408         for (unsigned int i = 0; i < (unsigned int)glslangType.getVectorSize(); ++i) {
3409             bool zero = nextConst >= consts.size();
3410             switch (glslangType.getBasicType()) {
3411             case glslang::EbtInt:
3412                 spvConsts.push_back(builder.makeIntConstant(zero ? 0 : consts[nextConst].getIConst()));
3413                 break;
3414             case glslang::EbtUint:
3415                 spvConsts.push_back(builder.makeUintConstant(zero ? 0 : consts[nextConst].getUConst()));
3416                 break;
3417             case glslang::EbtFloat:
3418                 spvConsts.push_back(builder.makeFloatConstant(zero ? 0.0F : (float)consts[nextConst].getDConst()));
3419                 break;
3420             case glslang::EbtDouble:
3421                 spvConsts.push_back(builder.makeDoubleConstant(zero ? 0.0 : consts[nextConst].getDConst()));
3422                 break;
3423             case glslang::EbtBool:
3424                 spvConsts.push_back(builder.makeBoolConstant(zero ? false : consts[nextConst].getBConst()));
3425                 break;
3426             default:
3427                 assert(0);
3428                 break;
3429             }
3430             ++nextConst;
3431         }
3432     } else {
3433         // we have a non-aggregate (scalar) constant
3434         bool zero = nextConst >= consts.size();
3435         spv::Id scalar = 0;
3436         switch (glslangType.getBasicType()) {
3437         case glslang::EbtInt:
3438             scalar = builder.makeIntConstant(zero ? 0 : consts[nextConst].getIConst(), specConstant);
3439             break;
3440         case glslang::EbtUint:
3441             scalar = builder.makeUintConstant(zero ? 0 : consts[nextConst].getUConst(), specConstant);
3442             break;
3443         case glslang::EbtFloat:
3444             scalar = builder.makeFloatConstant(zero ? 0.0F : (float)consts[nextConst].getDConst(), specConstant);
3445             break;
3446         case glslang::EbtDouble:
3447             scalar = builder.makeDoubleConstant(zero ? 0.0 : consts[nextConst].getDConst(), specConstant);
3448             break;
3449         case glslang::EbtBool:
3450             scalar = builder.makeBoolConstant(zero ? false : consts[nextConst].getBConst(), specConstant);
3451             break;
3452         default:
3453             assert(0);
3454             break;
3455         }
3456         ++nextConst;
3457         return scalar;
3458     }
3459
3460     return builder.makeCompositeConstant(typeId, spvConsts);
3461 }
3462
3463 // Return true if the node is a constant or symbol whose reading has no
3464 // non-trivial observable cost or effect.
3465 bool TGlslangToSpvTraverser::isTrivialLeaf(const glslang::TIntermTyped* node)
3466 {
3467     // don't know what this is
3468     if (node == nullptr)
3469         return false;
3470
3471     // a constant is safe
3472     if (node->getAsConstantUnion() != nullptr)
3473         return true;
3474
3475     // not a symbol means non-trivial
3476     if (node->getAsSymbolNode() == nullptr)
3477         return false;
3478
3479     // a symbol, depends on what's being read
3480     switch (node->getType().getQualifier().storage) {
3481     case glslang::EvqTemporary:
3482     case glslang::EvqGlobal:
3483     case glslang::EvqIn:
3484     case glslang::EvqInOut:
3485     case glslang::EvqConst:
3486     case glslang::EvqConstReadOnly:
3487     case glslang::EvqUniform:
3488         return true;
3489     default:
3490         return false;
3491     }
3492
3493
3494 // A node is trivial if it is a single operation with no side effects.
3495 // Error on the side of saying non-trivial.
3496 // Return true if trivial.
3497 bool TGlslangToSpvTraverser::isTrivial(const glslang::TIntermTyped* node)
3498 {
3499     if (node == nullptr)
3500         return false;
3501
3502     // symbols and constants are trivial
3503     if (isTrivialLeaf(node))
3504         return true;
3505
3506     // otherwise, it needs to be a simple operation or one or two leaf nodes
3507
3508     // not a simple operation
3509     const glslang::TIntermBinary* binaryNode = node->getAsBinaryNode();
3510     const glslang::TIntermUnary* unaryNode = node->getAsUnaryNode();
3511     if (binaryNode == nullptr && unaryNode == nullptr)
3512         return false;
3513
3514     // not on leaf nodes
3515     if (binaryNode && (! isTrivialLeaf(binaryNode->getLeft()) || ! isTrivialLeaf(binaryNode->getRight())))
3516         return false;
3517
3518     if (unaryNode && ! isTrivialLeaf(unaryNode->getOperand())) {
3519         return false;
3520     }
3521
3522     switch (node->getAsOperator()->getOp()) {
3523     case glslang::EOpLogicalNot:
3524     case glslang::EOpConvIntToBool:
3525     case glslang::EOpConvUintToBool:
3526     case glslang::EOpConvFloatToBool:
3527     case glslang::EOpConvDoubleToBool:
3528     case glslang::EOpEqual:
3529     case glslang::EOpNotEqual:
3530     case glslang::EOpLessThan:
3531     case glslang::EOpGreaterThan:
3532     case glslang::EOpLessThanEqual:
3533     case glslang::EOpGreaterThanEqual:
3534     case glslang::EOpIndexDirect:
3535     case glslang::EOpIndexDirectStruct:
3536     case glslang::EOpLogicalXor:
3537     case glslang::EOpAny:
3538     case glslang::EOpAll:
3539         return true;
3540     default:
3541         return false;
3542     }
3543 }
3544
3545 // Emit short-circuiting code, where 'right' is never evaluated unless
3546 // the left side is true (for &&) or false (for ||).
3547 spv::Id TGlslangToSpvTraverser::createShortCircuit(glslang::TOperator op, glslang::TIntermTyped& left, glslang::TIntermTyped& right)
3548 {
3549     spv::Id boolTypeId = builder.makeBoolType();
3550
3551     // emit left operand
3552     builder.clearAccessChain();
3553     left.traverse(this);
3554     spv::Id leftId = builder.accessChainLoad(boolTypeId);
3555
3556     // Operands to accumulate OpPhi operands
3557     std::vector<spv::Id> phiOperands;
3558     // accumulate left operand's phi information
3559     phiOperands.push_back(leftId);
3560     phiOperands.push_back(builder.getBuildPoint()->getId());
3561
3562     // Make the two kinds of operation symmetric with a "!"
3563     //   || => emit "if (! left) result = right"
3564     //   && => emit "if (  left) result = right"
3565     //
3566     // TODO: this runtime "not" for || could be avoided by adding functionality
3567     // to 'builder' to have an "else" without an "then"
3568     if (op == glslang::EOpLogicalOr)
3569         leftId = builder.createUnaryOp(spv::OpLogicalNot, boolTypeId, leftId);
3570
3571     // make an "if" based on the left value
3572     spv::Builder::If ifBuilder(leftId, builder);
3573
3574     // emit right operand as the "then" part of the "if"
3575     builder.clearAccessChain();
3576     right.traverse(this);
3577     spv::Id rightId = builder.accessChainLoad(boolTypeId);
3578
3579     // accumulate left operand's phi information
3580     phiOperands.push_back(rightId);
3581     phiOperands.push_back(builder.getBuildPoint()->getId());
3582
3583     // finish the "if"
3584     ifBuilder.makeEndIf();
3585
3586     // phi together the two results
3587     return builder.createOp(spv::OpPhi, boolTypeId, phiOperands);
3588 }
3589
3590 };  // end anonymous namespace
3591
3592 namespace glslang {
3593
3594 void GetSpirvVersion(std::string& version)
3595 {
3596     const int bufSize = 100;
3597     char buf[bufSize];
3598     snprintf(buf, bufSize, "0x%08x, Revision %d", spv::Version, spv::Revision);
3599     version = buf;
3600 }
3601
3602 // Write SPIR-V out to a binary file
3603 void OutputSpv(const std::vector<unsigned int>& spirv, const char* baseName)
3604 {
3605     std::ofstream out;
3606     out.open(baseName, std::ios::binary | std::ios::out);
3607     for (int i = 0; i < (int)spirv.size(); ++i) {
3608         unsigned int word = spirv[i];
3609         out.write((const char*)&word, 4);
3610     }
3611     out.close();
3612 }
3613
3614 //
3615 // Set up the glslang traversal
3616 //
3617 void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv)
3618 {
3619     TIntermNode* root = intermediate.getTreeRoot();
3620
3621     if (root == 0)
3622         return;
3623
3624     glslang::GetThreadPoolAllocator().push();
3625
3626     TGlslangToSpvTraverser it(&intermediate);
3627
3628     root->traverse(&it);
3629
3630     it.dumpSpv(spirv);
3631
3632     glslang::GetThreadPoolAllocator().pop();
3633 }
3634
3635 }; // end namespace glslang