Fix variable scoping of do-while
[platform/upstream/glslang.git] / glslang / MachineIndependent / localintermediate.h
1 //
2 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
3 // Copyright (C) 2016 LunarG, Inc.
4 // Copyright (C) 2017 ARM Limited.
5 // Copyright (C) 2015-2018 Google, Inc.
6 //
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions
11 // are met:
12 //
13 //    Redistributions of source code must retain the above copyright
14 //    notice, this list of conditions and the following disclaimer.
15 //
16 //    Redistributions in binary form must reproduce the above
17 //    copyright notice, this list of conditions and the following
18 //    disclaimer in the documentation and/or other materials provided
19 //    with the distribution.
20 //
21 //    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
22 //    contributors may be used to endorse or promote products derived
23 //    from this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
28 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
29 // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
30 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
31 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 // POSSIBILITY OF SUCH DAMAGE.
37 //
38
39 #ifndef _LOCAL_INTERMEDIATE_INCLUDED_
40 #define _LOCAL_INTERMEDIATE_INCLUDED_
41
42 #include "../Include/intermediate.h"
43 #include "../Public/ShaderLang.h"
44 #include "Versions.h"
45
46 #include <string>
47 #include <vector>
48 #include <algorithm>
49 #include <set>
50 #include <array>
51
52 class TInfoSink;
53
54 namespace glslang {
55
56 struct TMatrixSelector {
57     int coord1;  // stay agnostic about column/row; this is parse order
58     int coord2;
59 };
60
61 typedef int TVectorSelector;
62
63 const int MaxSwizzleSelectors = 4;
64
65 template<typename selectorType>
66 class TSwizzleSelectors {
67 public:
68     TSwizzleSelectors() : size_(0) { }
69
70     void push_back(selectorType comp)
71     {
72         if (size_ < MaxSwizzleSelectors)
73             components[size_++] = comp;
74     }
75     void resize(int s)
76     {
77         assert(s <= size_);
78         size_ = s;
79     }
80     int size() const { return size_; }
81     selectorType operator[](int i) const
82     {
83         assert(i < MaxSwizzleSelectors);
84         return components[i];
85     }
86
87 private:
88     int size_;
89     selectorType components[MaxSwizzleSelectors];
90 };
91
92 //
93 // Some helper structures for TIntermediate.  Their contents are encapsulated
94 // by TIntermediate.
95 //
96
97 // Used for call-graph algorithms for detecting recursion, missing bodies, and dead bodies.
98 // A "call" is a pair: <caller, callee>.
99 // There can be duplicates. General assumption is the list is small.
100 struct TCall {
101     TCall(const TString& pCaller, const TString& pCallee) : caller(pCaller), callee(pCallee) { }
102     TString caller;
103     TString callee;
104     bool visited;
105     bool currentPath;
106     bool errorGiven;
107     int calleeBodyPosition;
108 };
109
110 // A generic 1-D range.
111 struct TRange {
112     TRange(int start, int last) : start(start), last(last) { }
113     bool overlap(const TRange& rhs) const
114     {
115         return last >= rhs.start && start <= rhs.last;
116     }
117     int start;
118     int last;
119 };
120
121 // An IO range is a 3-D rectangle; the set of (location, component, index) triples all lying
122 // within the same location range, component range, and index value.  Locations don't alias unless
123 // all other dimensions of their range overlap.
124 struct TIoRange {
125     TIoRange(TRange location, TRange component, TBasicType basicType, int index)
126         : location(location), component(component), basicType(basicType), index(index) { }
127     bool overlap(const TIoRange& rhs) const
128     {
129         return location.overlap(rhs.location) && component.overlap(rhs.component) && index == rhs.index;
130     }
131     TRange location;
132     TRange component;
133     TBasicType basicType;
134     int index;
135 };
136
137 // An offset range is a 2-D rectangle; the set of (binding, offset) pairs all lying
138 // within the same binding and offset range.
139 struct TOffsetRange {
140     TOffsetRange(TRange binding, TRange offset)
141         : binding(binding), offset(offset) { }
142     bool overlap(const TOffsetRange& rhs) const
143     {
144         return binding.overlap(rhs.binding) && offset.overlap(rhs.offset);
145     }
146     TRange binding;
147     TRange offset;
148 };
149
150 #ifndef GLSLANG_WEB
151 // Things that need to be tracked per xfb buffer.
152 struct TXfbBuffer {
153     TXfbBuffer() : stride(TQualifier::layoutXfbStrideEnd), implicitStride(0), contains64BitType(false),
154                    contains32BitType(false), contains16BitType(false) { }
155     std::vector<TRange> ranges;  // byte offsets that have already been assigned
156     unsigned int stride;
157     unsigned int implicitStride;
158     bool contains64BitType;
159     bool contains32BitType;
160     bool contains16BitType;
161 };
162 #endif
163
164 // Track a set of strings describing how the module was processed.
165 // This includes command line options, transforms, etc., ideally inclusive enough
166 // to reproduce the steps used to transform the input source to the output.
167 // E.g., see SPIR-V OpModuleProcessed.
168 // Each "process" or "transform" uses is expressed in the form:
169 //   process arg0 arg1 arg2 ...
170 //   process arg0 arg1 arg2 ...
171 // where everything is textual, and there can be zero or more arguments
172 class TProcesses {
173 public:
174     TProcesses() {}
175     ~TProcesses() {}
176
177     void addProcess(const char* process)
178     {
179         processes.push_back(process);
180     }
181     void addProcess(const std::string& process)
182     {
183         processes.push_back(process);
184     }
185     void addArgument(int arg)
186     {
187         processes.back().append(" ");
188         std::string argString = std::to_string(arg);
189         processes.back().append(argString);
190     }
191     void addArgument(const char* arg)
192     {
193         processes.back().append(" ");
194         processes.back().append(arg);
195     }
196     void addArgument(const std::string& arg)
197     {
198         processes.back().append(" ");
199         processes.back().append(arg);
200     }
201     void addIfNonZero(const char* process, int value)
202     {
203         if (value != 0) {
204             addProcess(process);
205             addArgument(value);
206         }
207     }
208
209     const std::vector<std::string>& getProcesses() const { return processes; }
210
211 private:
212     std::vector<std::string> processes;
213 };
214
215 class TSymbolTable;
216 class TSymbol;
217 class TVariable;
218
219 //
220 // Texture and Sampler transformation mode.
221 //
222 enum ComputeDerivativeMode {
223     LayoutDerivativeNone,         // default layout as SPV_NV_compute_shader_derivatives not enabled
224     LayoutDerivativeGroupQuads,   // derivative_group_quadsNV
225     LayoutDerivativeGroupLinear,  // derivative_group_linearNV
226 };
227
228 class TIdMaps {
229 public:
230     TMap<TString, long long>& operator[](long long i) { return maps[i]; }
231     const TMap<TString, long long>& operator[](long long i) const { return maps[i]; }
232 private:
233     TMap<TString, long long> maps[EsiCount];
234 };
235
236 class TNumericFeatures {
237 public:
238     TNumericFeatures() : features(0) { }
239     TNumericFeatures(const TNumericFeatures&) = delete;
240     TNumericFeatures& operator=(const TNumericFeatures&) = delete;
241     typedef enum : unsigned int {
242         shader_explicit_arithmetic_types          = 1 << 0,
243         shader_explicit_arithmetic_types_int8     = 1 << 1,
244         shader_explicit_arithmetic_types_int16    = 1 << 2,
245         shader_explicit_arithmetic_types_int32    = 1 << 3,
246         shader_explicit_arithmetic_types_int64    = 1 << 4,
247         shader_explicit_arithmetic_types_float16  = 1 << 5,
248         shader_explicit_arithmetic_types_float32  = 1 << 6,
249         shader_explicit_arithmetic_types_float64  = 1 << 7,
250         shader_implicit_conversions               = 1 << 8,
251         gpu_shader_fp64                           = 1 << 9,
252         gpu_shader_int16                          = 1 << 10,
253         gpu_shader_half_float                     = 1 << 11,
254     } feature;
255     void insert(feature f) { features |= f; }
256     void erase(feature f) { features &= ~f; }
257     bool contains(feature f) const { return (features & f) != 0; }
258 private:
259     unsigned int features;
260 };
261
262 // MustBeAssigned wraps a T, asserting that it has been assigned with 
263 // operator =() before attempting to read with operator T() or operator ->().
264 // Used to catch cases where fields are read before they have been assigned.
265 template<typename T>
266 class MustBeAssigned
267 {
268 public:
269     MustBeAssigned() = default;
270     MustBeAssigned(const T& v) : value(v) {}
271     operator const T&() const { assert(isSet); return value; }
272     const T* operator ->() const { assert(isSet); return &value; }
273     MustBeAssigned& operator = (const T& v) { value = v; isSet = true; return *this; } 
274 private:
275     T value;
276     bool isSet = false;
277 };
278
279 //
280 // Set of helper functions to help parse and build the tree.
281 //
282 class TIntermediate {
283 public:
284     explicit TIntermediate(EShLanguage l, int v = 0, EProfile p = ENoProfile) :
285         language(l),
286 #ifndef GLSLANG_ANGLE
287         profile(p), version(v),
288 #endif
289         treeRoot(0),
290         resources(TBuiltInResource{}),
291         numEntryPoints(0), numErrors(0), numPushConstants(0), recursive(false),
292         invertY(false),
293         useStorageBuffer(false),
294         invariantAll(false),
295         nanMinMaxClamp(false),
296         depthReplacing(false),
297         uniqueId(0),
298         globalUniformBlockName(""),
299         atomicCounterBlockName(""),
300         globalUniformBlockSet(TQualifier::layoutSetEnd),
301         globalUniformBlockBinding(TQualifier::layoutBindingEnd),
302         atomicCounterBlockSet(TQualifier::layoutSetEnd)
303 #ifndef GLSLANG_WEB
304         ,
305         implicitThisName("@this"), implicitCounterName("@count"),
306         source(EShSourceNone),
307         useVulkanMemoryModel(false),
308         invocations(TQualifier::layoutNotSet), vertices(TQualifier::layoutNotSet),
309         inputPrimitive(ElgNone), outputPrimitive(ElgNone),
310         pixelCenterInteger(false), originUpperLeft(false),
311         vertexSpacing(EvsNone), vertexOrder(EvoNone), interlockOrdering(EioNone), pointMode(false), earlyFragmentTests(false),
312         postDepthCoverage(false), depthLayout(EldNone),
313         hlslFunctionality1(false),
314         blendEquations(0), xfbMode(false), multiStream(false),
315         layoutOverrideCoverage(false),
316         geoPassthroughEXT(false),
317         numShaderRecordBlocks(0),
318         computeDerivativeMode(LayoutDerivativeNone),
319         primitives(TQualifier::layoutNotSet),
320         numTaskNVBlocks(0),
321         layoutPrimitiveCulling(false),
322         autoMapBindings(false),
323         autoMapLocations(false),
324         flattenUniformArrays(false),
325         useUnknownFormat(false),
326         hlslOffsets(false),
327         hlslIoMapping(false),
328         useVariablePointers(false),
329         textureSamplerTransformMode(EShTexSampTransKeep),
330         needToLegalize(false),
331         binaryDoubleOutput(false),
332         subgroupUniformControlFlow(false),
333         usePhysicalStorageBuffer(false),
334         spirvRequirement(nullptr),
335         spirvExecutionMode(nullptr),
336         uniformLocationBase(0)
337 #endif
338     {
339         localSize[0] = 1;
340         localSize[1] = 1;
341         localSize[2] = 1;
342         localSizeNotDefault[0] = false;
343         localSizeNotDefault[1] = false;
344         localSizeNotDefault[2] = false;
345         localSizeSpecId[0] = TQualifier::layoutNotSet;
346         localSizeSpecId[1] = TQualifier::layoutNotSet;
347         localSizeSpecId[2] = TQualifier::layoutNotSet;
348 #ifndef GLSLANG_WEB
349         xfbBuffers.resize(TQualifier::layoutXfbBufferEnd);
350         shiftBinding.fill(0);
351 #endif
352     }
353
354     void setVersion(int v)
355     {
356 #ifndef GLSLANG_ANGLE
357         version = v;
358 #endif
359     }
360     void setProfile(EProfile p)
361     {
362 #ifndef GLSLANG_ANGLE
363         profile = p;
364 #endif
365     }
366
367     int getVersion() const { return version; }
368     EProfile getProfile() const { return profile; }
369     void setSpv(const SpvVersion& s)
370     {
371         spvVersion = s;
372
373         // client processes
374         if (spvVersion.vulkan > 0)
375             processes.addProcess("client vulkan100");
376         if (spvVersion.openGl > 0)
377             processes.addProcess("client opengl100");
378
379         // target SPV
380         switch (spvVersion.spv) {
381         case 0:
382             break;
383         case EShTargetSpv_1_0:
384             break;
385         case EShTargetSpv_1_1:
386             processes.addProcess("target-env spirv1.1");
387             break;
388         case EShTargetSpv_1_2:
389             processes.addProcess("target-env spirv1.2");
390             break;
391         case EShTargetSpv_1_3:
392             processes.addProcess("target-env spirv1.3");
393             break;
394         case EShTargetSpv_1_4:
395             processes.addProcess("target-env spirv1.4");
396             break;
397         case EShTargetSpv_1_5:
398             processes.addProcess("target-env spirv1.5");
399             break;
400         default:
401             processes.addProcess("target-env spirvUnknown");
402             break;
403         }
404
405         // target-environment processes
406         switch (spvVersion.vulkan) {
407         case 0:
408             break;
409         case EShTargetVulkan_1_0:
410             processes.addProcess("target-env vulkan1.0");
411             break;
412         case EShTargetVulkan_1_1:
413             processes.addProcess("target-env vulkan1.1");
414             break;
415         case EShTargetVulkan_1_2:
416             processes.addProcess("target-env vulkan1.2");
417             break;
418         default:
419             processes.addProcess("target-env vulkanUnknown");
420             break;
421         }
422         if (spvVersion.openGl > 0)
423             processes.addProcess("target-env opengl");
424     }
425     const SpvVersion& getSpv() const { return spvVersion; }
426     EShLanguage getStage() const { return language; }
427     void addRequestedExtension(const char* extension) { requestedExtensions.insert(extension); }
428     const std::set<std::string>& getRequestedExtensions() const { return requestedExtensions; }
429     bool isRayTracingStage() const {
430         return language >= EShLangRayGen && language <= EShLangCallableNV;
431     }
432
433     void setTreeRoot(TIntermNode* r) { treeRoot = r; }
434     TIntermNode* getTreeRoot() const { return treeRoot; }
435     void incrementEntryPointCount() { ++numEntryPoints; }
436     int getNumEntryPoints() const { return numEntryPoints; }
437     int getNumErrors() const { return numErrors; }
438     void addPushConstantCount() { ++numPushConstants; }
439     void setLimits(const TBuiltInResource& r) { resources = r; }
440     const TBuiltInResource& getLimits() const { return resources; }
441
442     bool postProcess(TIntermNode*, EShLanguage);
443     void removeTree();
444
445     void setEntryPointName(const char* ep)
446     {
447         entryPointName = ep;
448         processes.addProcess("entry-point");
449         processes.addArgument(entryPointName);
450     }
451     void setEntryPointMangledName(const char* ep) { entryPointMangledName = ep; }
452     const std::string& getEntryPointName() const { return entryPointName; }
453     const std::string& getEntryPointMangledName() const { return entryPointMangledName; }
454
455     void setInvertY(bool invert)
456     {
457         invertY = invert;
458         if (invertY)
459             processes.addProcess("invert-y");
460     }
461     bool getInvertY() const { return invertY; }
462
463 #ifdef ENABLE_HLSL
464     void setSource(EShSource s) { source = s; }
465     EShSource getSource() const { return source; }
466 #else
467     void setSource(EShSource s) { assert(s == EShSourceGlsl); (void)s; }
468     EShSource getSource() const { return EShSourceGlsl; }
469 #endif
470
471     bool isRecursive() const { return recursive; }
472
473     TIntermSymbol* addSymbol(const TVariable&);
474     TIntermSymbol* addSymbol(const TVariable&, const TSourceLoc&);
475     TIntermSymbol* addSymbol(const TType&, const TSourceLoc&);
476     TIntermSymbol* addSymbol(const TIntermSymbol&);
477     TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*);
478     std::tuple<TIntermTyped*, TIntermTyped*> addPairConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1);
479     TIntermTyped* addUniShapeConversion(TOperator, const TType&, TIntermTyped*);
480     TIntermTyped* addConversion(TBasicType convertTo, TIntermTyped* node) const;
481     void addBiShapeConversion(TOperator, TIntermTyped*& lhsNode, TIntermTyped*& rhsNode);
482     TIntermTyped* addShapeConversion(const TType&, TIntermTyped*);
483     TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&);
484     TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&);
485     TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc&);
486     TIntermTyped* addUnaryMath(TOperator, TIntermTyped* child, const TSourceLoc&);
487     TIntermTyped* addBuiltInFunctionCall(const TSourceLoc& line, TOperator, bool unary, TIntermNode*, const TType& returnType);
488     bool canImplicitlyPromote(TBasicType from, TBasicType to, TOperator op = EOpNull) const;
489     bool isIntegralPromotion(TBasicType from, TBasicType to) const;
490     bool isFPPromotion(TBasicType from, TBasicType to) const;
491     bool isIntegralConversion(TBasicType from, TBasicType to) const;
492     bool isFPConversion(TBasicType from, TBasicType to) const;
493     bool isFPIntegralConversion(TBasicType from, TBasicType to) const;
494     TOperator mapTypeToConstructorOp(const TType&) const;
495     TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right);
496     TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc&);
497     TIntermAggregate* makeAggregate(TIntermNode* node);
498     TIntermAggregate* makeAggregate(TIntermNode* node, const TSourceLoc&);
499     TIntermAggregate* makeAggregate(const TSourceLoc&);
500     TIntermTyped* setAggregateOperator(TIntermNode*, TOperator, const TType& type, const TSourceLoc&);
501     bool areAllChildConst(TIntermAggregate* aggrNode);
502     TIntermSelection* addSelection(TIntermTyped* cond, TIntermNodePair code, const TSourceLoc&);
503     TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc&);
504     TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc&);
505     TIntermTyped* addMethod(TIntermTyped*, const TType&, const TString*, const TSourceLoc&);
506     TIntermConstantUnion* addConstantUnion(const TConstUnionArray&, const TType&, const TSourceLoc&, bool literal = false) const;
507     TIntermConstantUnion* addConstantUnion(signed char, const TSourceLoc&, bool literal = false) const;
508     TIntermConstantUnion* addConstantUnion(unsigned char, const TSourceLoc&, bool literal = false) const;
509     TIntermConstantUnion* addConstantUnion(signed short, const TSourceLoc&, bool literal = false) const;
510     TIntermConstantUnion* addConstantUnion(unsigned short, const TSourceLoc&, bool literal = false) const;
511     TIntermConstantUnion* addConstantUnion(int, const TSourceLoc&, bool literal = false) const;
512     TIntermConstantUnion* addConstantUnion(unsigned int, const TSourceLoc&, bool literal = false) const;
513     TIntermConstantUnion* addConstantUnion(long long, const TSourceLoc&, bool literal = false) const;
514     TIntermConstantUnion* addConstantUnion(unsigned long long, const TSourceLoc&, bool literal = false) const;
515     TIntermConstantUnion* addConstantUnion(bool, const TSourceLoc&, bool literal = false) const;
516     TIntermConstantUnion* addConstantUnion(double, TBasicType, const TSourceLoc&, bool literal = false) const;
517     TIntermConstantUnion* addConstantUnion(const TString*, const TSourceLoc&, bool literal = false) const;
518     TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) const;
519     bool parseConstTree(TIntermNode*, TConstUnionArray, TOperator, const TType&, bool singleConstantParam = false);
520     TIntermLoop* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&);
521     TIntermAggregate* addForLoop(TIntermNode*, TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst,
522         const TSourceLoc&, TIntermLoop*&);
523     TIntermBranch* addBranch(TOperator, const TSourceLoc&);
524     TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&);
525     template<typename selectorType> TIntermTyped* addSwizzle(TSwizzleSelectors<selectorType>&, const TSourceLoc&);
526
527     // Low level functions to add nodes (no conversions or other higher level transformations)
528     // If a type is provided, the node's type will be set to it.
529     TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&) const;
530     TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&,
531         const TType&) const;
532     TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, const TSourceLoc&) const;
533     TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, const TSourceLoc&, const TType&) const;
534
535     // Constant folding (in Constant.cpp)
536     TIntermTyped* fold(TIntermAggregate* aggrNode);
537     TIntermTyped* foldConstructor(TIntermAggregate* aggrNode);
538     TIntermTyped* foldDereference(TIntermTyped* node, int index, const TSourceLoc&);
539     TIntermTyped* foldSwizzle(TIntermTyped* node, TSwizzleSelectors<TVectorSelector>& fields, const TSourceLoc&);
540
541     // Tree ops
542     static const TIntermTyped* findLValueBase(const TIntermTyped*, bool swizzleOkay , bool BufferReferenceOk = false);
543
544     // Linkage related
545     void addSymbolLinkageNodes(TIntermAggregate*& linkage, EShLanguage, TSymbolTable&);
546     void addSymbolLinkageNode(TIntermAggregate*& linkage, const TSymbol&);
547     TIntermAggregate* findLinkerObjects() const;
548
549     void setGlobalUniformBlockName(const char* name) { globalUniformBlockName = std::string(name); }
550     const char* getGlobalUniformBlockName() const { return globalUniformBlockName.c_str(); }
551     void setGlobalUniformSet(unsigned int set) { globalUniformBlockSet = set; }
552     unsigned int getGlobalUniformSet() const { return globalUniformBlockSet; }
553     void setGlobalUniformBinding(unsigned int binding) { globalUniformBlockBinding = binding; }
554     unsigned int getGlobalUniformBinding() const { return globalUniformBlockBinding; }
555
556     void setAtomicCounterBlockName(const char* name) { atomicCounterBlockName = std::string(name); }
557     const char* getAtomicCounterBlockName() const { return atomicCounterBlockName.c_str(); }
558     void setAtomicCounterBlockSet(unsigned int set) { atomicCounterBlockSet = set; }
559     unsigned int getAtomicCounterBlockSet() const { return atomicCounterBlockSet; }
560
561
562     void setUseStorageBuffer() { useStorageBuffer = true; }
563     bool usingStorageBuffer() const { return useStorageBuffer; }
564     void setInvariantAll() { invariantAll = true; }
565     bool isInvariantAll() const { return invariantAll; }
566     void setDepthReplacing() { depthReplacing = true; }
567     bool isDepthReplacing() const { return depthReplacing; }
568     bool setLocalSize(int dim, int size)
569     {
570         if (localSizeNotDefault[dim])
571             return size == localSize[dim];
572         localSizeNotDefault[dim] = true;
573         localSize[dim] = size;
574         return true;
575     }
576     unsigned int getLocalSize(int dim) const { return localSize[dim]; }
577     bool isLocalSizeSet() const
578     {
579         // Return true if any component has been set (i.e. any component is not default).
580         return localSizeNotDefault[0] || localSizeNotDefault[1] || localSizeNotDefault[2];
581     }
582     bool setLocalSizeSpecId(int dim, int id)
583     {
584         if (localSizeSpecId[dim] != TQualifier::layoutNotSet)
585             return id == localSizeSpecId[dim];
586         localSizeSpecId[dim] = id;
587         return true;
588     }
589     int getLocalSizeSpecId(int dim) const { return localSizeSpecId[dim]; }
590     bool isLocalSizeSpecialized() const
591     {
592         // Return true if any component has been specialized.
593         return localSizeSpecId[0] != TQualifier::layoutNotSet ||
594                localSizeSpecId[1] != TQualifier::layoutNotSet ||
595                localSizeSpecId[2] != TQualifier::layoutNotSet;
596     }
597 #ifdef GLSLANG_WEB
598     void output(TInfoSink&, bool tree) { }
599
600     bool isEsProfile() const { return false; }
601     bool getXfbMode() const { return false; }
602     bool isMultiStream() const { return false; }
603     TLayoutGeometry getOutputPrimitive() const { return ElgNone; }
604     bool getPostDepthCoverage() const { return false; }
605     bool getEarlyFragmentTests() const { return false; }
606     TLayoutDepth getDepth() const { return EldNone; }
607     bool getPixelCenterInteger() const { return false; }
608     void setOriginUpperLeft() { }
609     bool getOriginUpperLeft() const { return true; }
610     TInterlockOrdering getInterlockOrdering() const { return EioNone; }
611
612     bool getAutoMapBindings() const { return false; }
613     bool getAutoMapLocations() const { return false; }
614     int getNumPushConstants() const { return 0; }
615     void addShaderRecordCount() { }
616     void addTaskNVCount() { }
617     void setUseVulkanMemoryModel() { }
618     bool usingVulkanMemoryModel() const { return false; }
619     bool usingPhysicalStorageBuffer() const { return false; }
620     bool usingVariablePointers() const { return false; }
621     unsigned getXfbStride(int buffer) const { return 0; }
622     bool hasLayoutDerivativeModeNone() const { return false; }
623     ComputeDerivativeMode getLayoutDerivativeModeNone() const { return LayoutDerivativeNone; }
624 #else
625     void output(TInfoSink&, bool tree);
626
627     bool isEsProfile() const { return profile == EEsProfile; }
628
629     void setShiftBinding(TResourceType res, unsigned int shift)
630     {
631         shiftBinding[res] = shift;
632
633         const char* name = getResourceName(res);
634         if (name != nullptr)
635             processes.addIfNonZero(name, shift);
636     }
637
638     unsigned int getShiftBinding(TResourceType res) const { return shiftBinding[res]; }
639
640     void setShiftBindingForSet(TResourceType res, unsigned int shift, unsigned int set)
641     {
642         if (shift == 0) // ignore if there's no shift: it's a no-op.
643             return;
644
645         shiftBindingForSet[res][set] = shift;
646
647         const char* name = getResourceName(res);
648         if (name != nullptr) {
649             processes.addProcess(name);
650             processes.addArgument(shift);
651             processes.addArgument(set);
652         }
653     }
654
655     int getShiftBindingForSet(TResourceType res, unsigned int set) const
656     {
657         const auto shift = shiftBindingForSet[res].find(set);
658         return shift == shiftBindingForSet[res].end() ? -1 : shift->second;
659     }
660     bool hasShiftBindingForSet(TResourceType res) const { return !shiftBindingForSet[res].empty(); }
661
662     void setResourceSetBinding(const std::vector<std::string>& shift)
663     {
664         resourceSetBinding = shift;
665         if (shift.size() > 0) {
666             processes.addProcess("resource-set-binding");
667             for (int s = 0; s < (int)shift.size(); ++s)
668                 processes.addArgument(shift[s]);
669         }
670     }
671     const std::vector<std::string>& getResourceSetBinding() const { return resourceSetBinding; }
672     void setAutoMapBindings(bool map)
673     {
674         autoMapBindings = map;
675         if (autoMapBindings)
676             processes.addProcess("auto-map-bindings");
677     }
678     bool getAutoMapBindings() const { return autoMapBindings; }
679     void setAutoMapLocations(bool map)
680     {
681         autoMapLocations = map;
682         if (autoMapLocations)
683             processes.addProcess("auto-map-locations");
684     }
685     bool getAutoMapLocations() const { return autoMapLocations; }
686
687 #ifdef ENABLE_HLSL
688     void setFlattenUniformArrays(bool flatten)
689     {
690         flattenUniformArrays = flatten;
691         if (flattenUniformArrays)
692             processes.addProcess("flatten-uniform-arrays");
693     }
694     bool getFlattenUniformArrays() const { return flattenUniformArrays; }
695 #endif
696     void setNoStorageFormat(bool b)
697     {
698         useUnknownFormat = b;
699         if (useUnknownFormat)
700             processes.addProcess("no-storage-format");
701     }
702     bool getNoStorageFormat() const { return useUnknownFormat; }
703     void setUseVulkanMemoryModel()
704     {
705         useVulkanMemoryModel = true;
706         processes.addProcess("use-vulkan-memory-model");
707     }
708     bool usingVulkanMemoryModel() const { return useVulkanMemoryModel; }
709     void setUsePhysicalStorageBuffer()
710     {
711         usePhysicalStorageBuffer = true;
712     }
713     bool usingPhysicalStorageBuffer() const { return usePhysicalStorageBuffer; }
714     void setUseVariablePointers()
715     {
716         useVariablePointers = true;
717         processes.addProcess("use-variable-pointers");
718     }
719     bool usingVariablePointers() const { return useVariablePointers; }
720
721 #ifdef ENABLE_HLSL
722     template<class T> T addCounterBufferName(const T& name) const { return name + implicitCounterName; }
723     bool hasCounterBufferName(const TString& name) const {
724         size_t len = strlen(implicitCounterName);
725         return name.size() > len &&
726                name.compare(name.size() - len, len, implicitCounterName) == 0;
727     }
728 #endif
729
730     void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { textureSamplerTransformMode = mode; }
731     int getNumPushConstants() const { return numPushConstants; }
732     void addShaderRecordCount() { ++numShaderRecordBlocks; }
733     void addTaskNVCount() { ++numTaskNVBlocks; }
734
735     bool setInvocations(int i)
736     {
737         if (invocations != TQualifier::layoutNotSet)
738             return invocations == i;
739         invocations = i;
740         return true;
741     }
742     int getInvocations() const { return invocations; }
743     bool setVertices(int m)
744     {
745         if (vertices != TQualifier::layoutNotSet)
746             return vertices == m;
747         vertices = m;
748         return true;
749     }
750     int getVertices() const { return vertices; }
751     bool setInputPrimitive(TLayoutGeometry p)
752     {
753         if (inputPrimitive != ElgNone)
754             return inputPrimitive == p;
755         inputPrimitive = p;
756         return true;
757     }
758     TLayoutGeometry getInputPrimitive() const { return inputPrimitive; }
759     bool setVertexSpacing(TVertexSpacing s)
760     {
761         if (vertexSpacing != EvsNone)
762             return vertexSpacing == s;
763         vertexSpacing = s;
764         return true;
765     }
766     TVertexSpacing getVertexSpacing() const { return vertexSpacing; }
767     bool setVertexOrder(TVertexOrder o)
768     {
769         if (vertexOrder != EvoNone)
770             return vertexOrder == o;
771         vertexOrder = o;
772         return true;
773     }
774     TVertexOrder getVertexOrder() const { return vertexOrder; }
775     void setPointMode() { pointMode = true; }
776     bool getPointMode() const { return pointMode; }
777
778     bool setInterlockOrdering(TInterlockOrdering o)
779     {
780         if (interlockOrdering != EioNone)
781             return interlockOrdering == o;
782         interlockOrdering = o;
783         return true;
784     }
785     TInterlockOrdering getInterlockOrdering() const { return interlockOrdering; }
786
787     void setXfbMode() { xfbMode = true; }
788     bool getXfbMode() const { return xfbMode; }
789     void setMultiStream() { multiStream = true; }
790     bool isMultiStream() const { return multiStream; }
791     bool setOutputPrimitive(TLayoutGeometry p)
792     {
793         if (outputPrimitive != ElgNone)
794             return outputPrimitive == p;
795         outputPrimitive = p;
796         return true;
797     }
798     TLayoutGeometry getOutputPrimitive() const { return outputPrimitive; }
799     void setPostDepthCoverage() { postDepthCoverage = true; }
800     bool getPostDepthCoverage() const { return postDepthCoverage; }
801     void setEarlyFragmentTests() { earlyFragmentTests = true; }
802     bool getEarlyFragmentTests() const { return earlyFragmentTests; }
803     bool setDepth(TLayoutDepth d)
804     {
805         if (depthLayout != EldNone)
806             return depthLayout == d;
807         depthLayout = d;
808         return true;
809     }
810     TLayoutDepth getDepth() const { return depthLayout; }
811     void setOriginUpperLeft() { originUpperLeft = true; }
812     bool getOriginUpperLeft() const { return originUpperLeft; }
813     void setPixelCenterInteger() { pixelCenterInteger = true; }
814     bool getPixelCenterInteger() const { return pixelCenterInteger; }
815     void addBlendEquation(TBlendEquationShift b) { blendEquations |= (1 << b); }
816     unsigned int getBlendEquations() const { return blendEquations; }
817     bool setXfbBufferStride(int buffer, unsigned stride)
818     {
819         if (xfbBuffers[buffer].stride != TQualifier::layoutXfbStrideEnd)
820             return xfbBuffers[buffer].stride == stride;
821         xfbBuffers[buffer].stride = stride;
822         return true;
823     }
824     unsigned getXfbStride(int buffer) const { return xfbBuffers[buffer].stride; }
825     int addXfbBufferOffset(const TType&);
826     unsigned int computeTypeXfbSize(const TType&, bool& contains64BitType, bool& contains32BitType, bool& contains16BitType) const;
827     unsigned int computeTypeXfbSize(const TType&, bool& contains64BitType) const;
828     void setLayoutOverrideCoverage() { layoutOverrideCoverage = true; }
829     bool getLayoutOverrideCoverage() const { return layoutOverrideCoverage; }
830     void setGeoPassthroughEXT() { geoPassthroughEXT = true; }
831     bool getGeoPassthroughEXT() const { return geoPassthroughEXT; }
832     void setLayoutDerivativeMode(ComputeDerivativeMode mode) { computeDerivativeMode = mode; }
833     bool hasLayoutDerivativeModeNone() const { return computeDerivativeMode != LayoutDerivativeNone; }
834     ComputeDerivativeMode getLayoutDerivativeModeNone() const { return computeDerivativeMode; }
835     void setLayoutPrimitiveCulling() { layoutPrimitiveCulling = true; }
836     bool getLayoutPrimitiveCulling() const { return layoutPrimitiveCulling; }
837     bool setPrimitives(int m)
838     {
839         if (primitives != TQualifier::layoutNotSet)
840             return primitives == m;
841         primitives = m;
842         return true;
843     }
844     int getPrimitives() const { return primitives; }
845     const char* addSemanticName(const TString& name)
846     {
847         return semanticNameSet.insert(name).first->c_str();
848     }
849     void addUniformLocationOverride(const char* nameStr, int location)
850     {
851         std::string name = nameStr;
852         uniformLocationOverrides[name] = location;
853     }
854
855     int getUniformLocationOverride(const char* nameStr) const
856     {
857         std::string name = nameStr;
858         auto pos = uniformLocationOverrides.find(name);
859         if (pos == uniformLocationOverrides.end())
860             return -1;
861         else
862             return pos->second;
863     }
864
865     void setUniformLocationBase(int base) { uniformLocationBase = base; }
866     int getUniformLocationBase() const { return uniformLocationBase; }
867
868     void setNeedsLegalization() { needToLegalize = true; }
869     bool needsLegalization() const { return needToLegalize; }
870
871     void setBinaryDoubleOutput() { binaryDoubleOutput = true; }
872     bool getBinaryDoubleOutput() { return binaryDoubleOutput; }
873
874     void setSubgroupUniformControlFlow() { subgroupUniformControlFlow = true; }
875     bool getSubgroupUniformControlFlow() const { return subgroupUniformControlFlow; }
876
877     // GL_EXT_spirv_intrinsics
878     void insertSpirvRequirement(const TSpirvRequirement* spirvReq);
879     bool hasSpirvRequirement() const { return spirvRequirement != nullptr; }
880     const TSpirvRequirement& getSpirvRequirement() const { return *spirvRequirement; }
881     void insertSpirvExecutionMode(int executionMode, const TIntermAggregate* args = nullptr);
882     void insertSpirvExecutionModeId(int executionMode, const TIntermAggregate* args);
883     bool hasSpirvExecutionMode() const { return spirvExecutionMode != nullptr; }
884     const TSpirvExecutionMode& getSpirvExecutionMode() const { return *spirvExecutionMode; }
885 #endif // GLSLANG_WEB
886
887     void addBlockStorageOverride(const char* nameStr, TBlockStorageClass backing)
888     {
889         std::string name(nameStr);
890         blockBackingOverrides[name] = backing;
891     }
892     TBlockStorageClass getBlockStorageOverride(const char* nameStr) const
893     {
894         std::string name = nameStr;
895         auto pos = blockBackingOverrides.find(name);
896         if (pos == blockBackingOverrides.end())
897             return EbsNone;
898         else
899             return pos->second;
900     }
901 #ifdef ENABLE_HLSL
902     void setHlslFunctionality1() { hlslFunctionality1 = true; }
903     bool getHlslFunctionality1() const { return hlslFunctionality1; }
904     void setHlslOffsets()
905     {
906         hlslOffsets = true;
907         if (hlslOffsets)
908             processes.addProcess("hlsl-offsets");
909     }
910     bool usingHlslOffsets() const { return hlslOffsets; }
911     void setHlslIoMapping(bool b)
912     {
913         hlslIoMapping = b;
914         if (hlslIoMapping)
915             processes.addProcess("hlsl-iomap");
916     }
917     bool usingHlslIoMapping() { return hlslIoMapping; }
918 #else
919     bool getHlslFunctionality1() const { return false; }
920     bool usingHlslOffsets() const { return false; }
921     bool usingHlslIoMapping() { return false; }
922 #endif
923
924     bool usingScalarBlockLayout() const {
925         for (auto extIt = requestedExtensions.begin(); extIt != requestedExtensions.end(); ++extIt) {
926             if (*extIt == E_GL_EXT_scalar_block_layout)
927                 return true;
928         }
929         return false;
930     }
931
932     bool IsRequestedExtension(const char* extension) const
933     {
934         return (requestedExtensions.find(extension) != requestedExtensions.end());
935     }
936
937     void addToCallGraph(TInfoSink&, const TString& caller, const TString& callee);
938     void merge(TInfoSink&, TIntermediate&);
939     void finalCheck(TInfoSink&, bool keepUncalled);
940
941     void mergeGlobalUniformBlocks(TInfoSink& infoSink, TIntermediate& unit, bool mergeExistingOnly);
942     void mergeUniformObjects(TInfoSink& infoSink, TIntermediate& unit);
943     void checkStageIO(TInfoSink&, TIntermediate&);
944
945     bool buildConvertOp(TBasicType dst, TBasicType src, TOperator& convertOp) const;
946     TIntermTyped* createConversion(TBasicType convertTo, TIntermTyped* node) const;
947
948     void addIoAccessed(const TString& name) { ioAccessed.insert(name); }
949     bool inIoAccessed(const TString& name) const { return ioAccessed.find(name) != ioAccessed.end(); }
950
951     int addUsedLocation(const TQualifier&, const TType&, bool& typeCollision);
952     int checkLocationRange(int set, const TIoRange& range, const TType&, bool& typeCollision);
953     int checkLocationRT(int set, int location);
954     int addUsedOffsets(int binding, int offset, int numOffsets);
955     bool addUsedConstantId(int id);
956     static int computeTypeLocationSize(const TType&, EShLanguage);
957     static int computeTypeUniformLocationSize(const TType&);
958
959     static int getBaseAlignmentScalar(const TType&, int& size);
960     static int getBaseAlignment(const TType&, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor);
961     static int getScalarAlignment(const TType&, int& size, int& stride, bool rowMajor);
962     static int getMemberAlignment(const TType&, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor);
963     static bool improperStraddle(const TType& type, int size, int offset);
964     static void updateOffset(const TType& parentType, const TType& memberType, int& offset, int& memberSize);
965     static int getOffset(const TType& type, int index);
966     static int getBlockSize(const TType& blockType);
967     static int computeBufferReferenceTypeSize(const TType&);
968     static bool isIoResizeArray(const TType& type, EShLanguage language);
969
970     bool promote(TIntermOperator*);
971     void setNanMinMaxClamp(bool setting) { nanMinMaxClamp = setting; }
972     bool getNanMinMaxClamp() const { return nanMinMaxClamp; }
973
974     void setSourceFile(const char* file) { if (file != nullptr) sourceFile = file; }
975     const std::string& getSourceFile() const { return sourceFile; }
976     void addSourceText(const char* text, size_t len) { sourceText.append(text, len); }
977     const std::string& getSourceText() const { return sourceText; }
978     const std::map<std::string, std::string>& getIncludeText() const { return includeText; }
979     void addIncludeText(const char* name, const char* text, size_t len) { includeText[name].assign(text,len); }
980     void addProcesses(const std::vector<std::string>& p)
981     {
982         for (int i = 0; i < (int)p.size(); ++i)
983             processes.addProcess(p[i]);
984     }
985     void addProcess(const std::string& process) { processes.addProcess(process); }
986     void addProcessArgument(const std::string& arg) { processes.addArgument(arg); }
987     const std::vector<std::string>& getProcesses() const { return processes.getProcesses(); }
988     unsigned long long getUniqueId() const { return uniqueId; }
989     void setUniqueId(unsigned long long id) { uniqueId = id; }
990
991     // Certain explicit conversions are allowed conditionally
992 #ifdef GLSLANG_WEB
993     bool getArithemeticInt8Enabled() const { return false; }
994     bool getArithemeticInt16Enabled() const { return false; }
995     bool getArithemeticFloat16Enabled() const { return false; }
996     void updateNumericFeature(TNumericFeatures::feature f, bool on) { }
997 #else
998     bool getArithemeticInt8Enabled() const {
999         return numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) ||
1000                numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int8);
1001     }
1002     bool getArithemeticInt16Enabled() const {
1003         return numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) ||
1004                numericFeatures.contains(TNumericFeatures::gpu_shader_int16) ||
1005                numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int16);
1006     }
1007
1008     bool getArithemeticFloat16Enabled() const {
1009         return numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) ||
1010                numericFeatures.contains(TNumericFeatures::gpu_shader_half_float) ||
1011                numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_float16);
1012     }
1013     void updateNumericFeature(TNumericFeatures::feature f, bool on)
1014         { on ? numericFeatures.insert(f) : numericFeatures.erase(f); }
1015 #endif
1016
1017 protected:
1018     TIntermSymbol* addSymbol(long long Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&);
1019     void error(TInfoSink& infoSink, const char*);
1020     void warn(TInfoSink& infoSink, const char*);
1021     void mergeCallGraphs(TInfoSink&, TIntermediate&);
1022     void mergeModes(TInfoSink&, TIntermediate&);
1023     void mergeTrees(TInfoSink&, TIntermediate&);
1024     void seedIdMap(TIdMaps& idMaps, long long& IdShift);
1025     void remapIds(const TIdMaps& idMaps, long long idShift, TIntermediate&);
1026     void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals);
1027     void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects, EShLanguage);
1028     void mergeBlockDefinitions(TInfoSink&, TIntermSymbol* block, TIntermSymbol* unitBlock, TIntermediate* unitRoot);
1029     void mergeImplicitArraySizes(TType&, const TType&);
1030     void mergeErrorCheck(TInfoSink&, const TIntermSymbol&, const TIntermSymbol&, EShLanguage);
1031     void checkCallGraphCycles(TInfoSink&);
1032     void checkCallGraphBodies(TInfoSink&, bool keepUncalled);
1033     void inOutLocationCheck(TInfoSink&);
1034     void sharedBlockCheck(TInfoSink&);
1035     bool userOutputUsed() const;
1036     bool isSpecializationOperation(const TIntermOperator&) const;
1037     bool isNonuniformPropagating(TOperator) const;
1038     bool promoteUnary(TIntermUnary&);
1039     bool promoteBinary(TIntermBinary&);
1040     void addSymbolLinkageNode(TIntermAggregate*& linkage, TSymbolTable&, const TString&);
1041     bool promoteAggregate(TIntermAggregate&);
1042     void pushSelector(TIntermSequence&, const TVectorSelector&, const TSourceLoc&);
1043     void pushSelector(TIntermSequence&, const TMatrixSelector&, const TSourceLoc&);
1044     bool specConstantPropagates(const TIntermTyped&, const TIntermTyped&);
1045     void performTextureUpgradeAndSamplerRemovalTransformation(TIntermNode* root);
1046     bool isConversionAllowed(TOperator op, TIntermTyped* node) const;
1047     std::tuple<TBasicType, TBasicType> getConversionDestinationType(TBasicType type0, TBasicType type1, TOperator op) const;
1048
1049     static const char* getResourceName(TResourceType);
1050
1051     const EShLanguage language;  // stage, known at construction time
1052     std::string entryPointName;
1053     std::string entryPointMangledName;
1054     typedef std::list<TCall> TGraph;
1055     TGraph callGraph;
1056
1057 #ifdef GLSLANG_ANGLE
1058     const EProfile profile = ECoreProfile;
1059     const int version = 450;
1060 #else
1061     EProfile profile;                           // source profile
1062     int version;                                // source version
1063 #endif
1064     SpvVersion spvVersion;
1065     TIntermNode* treeRoot;
1066     std::set<std::string> requestedExtensions;  // cumulation of all enabled or required extensions; not connected to what subset of the shader used them
1067     MustBeAssigned<TBuiltInResource> resources;
1068     int numEntryPoints;
1069     int numErrors;
1070     int numPushConstants;
1071     bool recursive;
1072     bool invertY;
1073     bool useStorageBuffer;
1074     bool invariantAll;
1075     bool nanMinMaxClamp;            // true if desiring min/max/clamp to favor non-NaN over NaN
1076     bool depthReplacing;
1077     int localSize[3];
1078     bool localSizeNotDefault[3];
1079     int localSizeSpecId[3];
1080     unsigned long long uniqueId;
1081
1082     std::string globalUniformBlockName;
1083     std::string atomicCounterBlockName;
1084     unsigned int globalUniformBlockSet;
1085     unsigned int globalUniformBlockBinding;
1086     unsigned int atomicCounterBlockSet;
1087
1088 #ifndef GLSLANG_WEB
1089 public:
1090     const char* const implicitThisName;
1091     const char* const implicitCounterName;
1092 protected:
1093     EShSource source;            // source language, known a bit later
1094     bool useVulkanMemoryModel;
1095     int invocations;
1096     int vertices;
1097     TLayoutGeometry inputPrimitive;
1098     TLayoutGeometry outputPrimitive;
1099     bool pixelCenterInteger;
1100     bool originUpperLeft;
1101     TVertexSpacing vertexSpacing;
1102     TVertexOrder vertexOrder;
1103     TInterlockOrdering interlockOrdering;
1104     bool pointMode;
1105     bool earlyFragmentTests;
1106     bool postDepthCoverage;
1107     TLayoutDepth depthLayout;
1108     bool hlslFunctionality1;
1109     int blendEquations;        // an 'or'ing of masks of shifts of TBlendEquationShift
1110     bool xfbMode;
1111     std::vector<TXfbBuffer> xfbBuffers;     // all the data we need to track per xfb buffer
1112     bool multiStream;
1113     bool layoutOverrideCoverage;
1114     bool geoPassthroughEXT;
1115     int numShaderRecordBlocks;
1116     ComputeDerivativeMode computeDerivativeMode;
1117     int primitives;
1118     int numTaskNVBlocks;
1119     bool layoutPrimitiveCulling;
1120
1121     // Base shift values
1122     std::array<unsigned int, EResCount> shiftBinding;
1123
1124     // Per-descriptor-set shift values
1125     std::array<std::map<int, int>, EResCount> shiftBindingForSet;
1126
1127     std::vector<std::string> resourceSetBinding;
1128     bool autoMapBindings;
1129     bool autoMapLocations;
1130     bool flattenUniformArrays;
1131     bool useUnknownFormat;
1132     bool hlslOffsets;
1133     bool hlslIoMapping;
1134     bool useVariablePointers;
1135
1136     std::set<TString> semanticNameSet;
1137
1138     EShTextureSamplerTransformMode textureSamplerTransformMode;
1139
1140     bool needToLegalize;
1141     bool binaryDoubleOutput;
1142     bool subgroupUniformControlFlow;
1143     bool usePhysicalStorageBuffer;
1144
1145     TSpirvRequirement* spirvRequirement;
1146     TSpirvExecutionMode* spirvExecutionMode;
1147
1148     std::unordered_map<std::string, int> uniformLocationOverrides;
1149     int uniformLocationBase;
1150     TNumericFeatures numericFeatures;
1151 #endif
1152     std::unordered_map<std::string, TBlockStorageClass> blockBackingOverrides;
1153
1154     std::unordered_set<int> usedConstantId; // specialization constant ids used
1155     std::vector<TOffsetRange> usedAtomics;  // sets of bindings used by atomic counters
1156     std::vector<TIoRange> usedIo[4];        // sets of used locations, one for each of in, out, uniform, and buffers
1157     std::vector<TRange> usedIoRT[2];        // sets of used location, one for rayPayload/rayPayloadIN and other
1158                                             // for callableData/callableDataIn
1159     // set of names of statically read/written I/O that might need extra checking
1160     std::set<TString> ioAccessed;
1161     // source code of shader, useful as part of debug information
1162     std::string sourceFile;
1163     std::string sourceText;
1164
1165     // Included text. First string is a name, second is the included text
1166     std::map<std::string, std::string> includeText;
1167
1168     // for OpModuleProcessed, or equivalent
1169     TProcesses processes;
1170
1171 private:
1172     void operator=(TIntermediate&); // prevent assignments
1173 };
1174
1175 } // end namespace glslang
1176
1177 #endif // _LOCAL_INTERMEDIATE_INCLUDED_