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