Home | History | Annotate | Download | only in MachineIndependent
      1 //
      2 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
      3 // Copyright (C) 2016 LunarG, Inc.
      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 #ifndef _LOCAL_INTERMEDIATE_INCLUDED_
     37 #define _LOCAL_INTERMEDIATE_INCLUDED_
     38 
     39 #include "../Include/intermediate.h"
     40 #include "../Public/ShaderLang.h"
     41 #include "Versions.h"
     42 
     43 #include <algorithm>
     44 #include <set>
     45 
     46 class TInfoSink;
     47 
     48 namespace glslang {
     49 
     50 struct TMatrixSelector {
     51     int coord1;  // stay agnostic about column/row; this is parse order
     52     int coord2;
     53 };
     54 
     55 typedef int TVectorSelector;
     56 
     57 const int MaxSwizzleSelectors = 4;
     58 
     59 template<typename selectorType>
     60 class TSwizzleSelectors {
     61 public:
     62     TSwizzleSelectors() : size_(0) { }
     63 
     64     void push_back(selectorType comp)
     65     {
     66         if (size_ < MaxSwizzleSelectors)
     67             components[size_++] = comp;
     68     }
     69     void resize(int s)
     70     {
     71         assert(s <= size_);
     72         size_ = s;
     73     }
     74     int size() const { return size_; }
     75     selectorType operator[](int i) const
     76     {
     77         assert(i < MaxSwizzleSelectors);
     78         return components[i];
     79     }
     80 
     81 private:
     82     int size_;
     83     selectorType components[MaxSwizzleSelectors];
     84 };
     85 
     86 //
     87 // Some helper structures for TIntermediate.  Their contents are encapsulated
     88 // by TIntermediate.
     89 //
     90 
     91 // Used for call-graph algorithms for detecting recursion, missing bodies, and dead bodies.
     92 // A "call" is a pair: <caller, callee>.
     93 // There can be duplicates. General assumption is the list is small.
     94 struct TCall {
     95     TCall(const TString& pCaller, const TString& pCallee) : caller(pCaller), callee(pCallee) { }
     96     TString caller;
     97     TString callee;
     98     bool visited;
     99     bool currentPath;
    100     bool errorGiven;
    101     int calleeBodyPosition;
    102 };
    103 
    104 // A generic 1-D range.
    105 struct TRange {
    106     TRange(int start, int last) : start(start), last(last) { }
    107     bool overlap(const TRange& rhs) const
    108     {
    109         return last >= rhs.start && start <= rhs.last;
    110     }
    111     int start;
    112     int last;
    113 };
    114 
    115 // An IO range is a 3-D rectangle; the set of (location, component, index) triples all lying
    116 // within the same location range, component range, and index value.  Locations don't alias unless
    117 // all other dimensions of their range overlap.
    118 struct TIoRange {
    119     TIoRange(TRange location, TRange component, TBasicType basicType, int index)
    120         : location(location), component(component), basicType(basicType), index(index) { }
    121     bool overlap(const TIoRange& rhs) const
    122     {
    123         return location.overlap(rhs.location) && component.overlap(rhs.component) && index == rhs.index;
    124     }
    125     TRange location;
    126     TRange component;
    127     TBasicType basicType;
    128     int index;
    129 };
    130 
    131 // An offset range is a 2-D rectangle; the set of (binding, offset) pairs all lying
    132 // within the same binding and offset range.
    133 struct TOffsetRange {
    134     TOffsetRange(TRange binding, TRange offset)
    135         : binding(binding), offset(offset) { }
    136     bool overlap(const TOffsetRange& rhs) const
    137     {
    138         return binding.overlap(rhs.binding) && offset.overlap(rhs.offset);
    139     }
    140     TRange binding;
    141     TRange offset;
    142 };
    143 
    144 // Things that need to be tracked per xfb buffer.
    145 struct TXfbBuffer {
    146     TXfbBuffer() : stride(TQualifier::layoutXfbStrideEnd), implicitStride(0), containsDouble(false) { }
    147     std::vector<TRange> ranges;  // byte offsets that have already been assigned
    148     unsigned int stride;
    149     unsigned int implicitStride;
    150     bool containsDouble;
    151 };
    152 
    153 // Track a set of strings describing how the module was processed.
    154 // Using the form:
    155 //   process arg0 arg1 arg2 ...
    156 //   process arg0 arg1 arg2 ...
    157 // where everything is textual, and there can be zero or more arguments
    158 class TProcesses {
    159 public:
    160     TProcesses() {}
    161     ~TProcesses() {}
    162 
    163     void addProcess(const char* process)
    164     {
    165         processes.push_back(process);
    166     }
    167     void addProcess(const std::string& process)
    168     {
    169         processes.push_back(process);
    170     }
    171     void addArgument(int arg)
    172     {
    173         processes.back().append(" ");
    174         std::string argString = std::to_string(arg);
    175         processes.back().append(argString);
    176     }
    177     void addArgument(const char* arg)
    178     {
    179         processes.back().append(" ");
    180         processes.back().append(arg);
    181     }
    182     void addArgument(const std::string& arg)
    183     {
    184         processes.back().append(" ");
    185         processes.back().append(arg);
    186     }
    187     void addIfNonZero(const char* process, int value)
    188     {
    189         if (value != 0) {
    190             addProcess(process);
    191             addArgument(value);
    192         }
    193     }
    194 
    195     const std::vector<std::string>& getProcesses() const { return processes; }
    196 
    197 private:
    198     std::vector<std::string> processes;
    199 };
    200 
    201 class TSymbolTable;
    202 class TSymbol;
    203 class TVariable;
    204 
    205 //
    206 // Set of helper functions to help parse and build the tree.
    207 //
    208 class TIntermediate {
    209 public:
    210     explicit TIntermediate(EShLanguage l, int v = 0, EProfile p = ENoProfile) :
    211         implicitThisName("@this"),
    212         language(l), source(EShSourceNone), profile(p), version(v), treeRoot(0),
    213         numEntryPoints(0), numErrors(0), numPushConstants(0), recursive(false),
    214         invocations(TQualifier::layoutNotSet), vertices(TQualifier::layoutNotSet),
    215         inputPrimitive(ElgNone), outputPrimitive(ElgNone),
    216         pixelCenterInteger(false), originUpperLeft(false),
    217         vertexSpacing(EvsNone), vertexOrder(EvoNone), pointMode(false), earlyFragmentTests(false),
    218         postDepthCoverage(false), depthLayout(EldNone), depthReplacing(false),
    219         blendEquations(0), xfbMode(false), multiStream(false),
    220 #ifdef NV_EXTENSIONS
    221         layoutOverrideCoverage(false),
    222         geoPassthroughEXT(false),
    223 #endif
    224         shiftSamplerBinding(0),
    225         shiftTextureBinding(0),
    226         shiftImageBinding(0),
    227         shiftUboBinding(0),
    228         shiftSsboBinding(0),
    229         shiftUavBinding(0),
    230         autoMapBindings(false),
    231         autoMapLocations(false),
    232         flattenUniformArrays(false),
    233         useUnknownFormat(false),
    234         hlslOffsets(false),
    235         useStorageBuffer(false),
    236         hlslIoMapping(false),
    237         textureSamplerTransformMode(EShTexSampTransKeep)
    238     {
    239         localSize[0] = 1;
    240         localSize[1] = 1;
    241         localSize[2] = 1;
    242         localSizeSpecId[0] = TQualifier::layoutNotSet;
    243         localSizeSpecId[1] = TQualifier::layoutNotSet;
    244         localSizeSpecId[2] = TQualifier::layoutNotSet;
    245         xfbBuffers.resize(TQualifier::layoutXfbBufferEnd);
    246     }
    247     void setLimits(const TBuiltInResource& r) { resources = r; }
    248 
    249     bool postProcess(TIntermNode*, EShLanguage);
    250     void output(TInfoSink&, bool tree);
    251     void removeTree();
    252 
    253     void setSource(EShSource s) { source = s; }
    254     EShSource getSource() const { return source; }
    255     void setEntryPointName(const char* ep)
    256     {
    257         entryPointName = ep;
    258         processes.addProcess("entry-point");
    259         processes.addArgument(entryPointName);
    260     }
    261     void setEntryPointMangledName(const char* ep) { entryPointMangledName = ep; }
    262     const std::string& getEntryPointName() const { return entryPointName; }
    263     const std::string& getEntryPointMangledName() const { return entryPointMangledName; }
    264 
    265     void setShiftSamplerBinding(unsigned int shift)
    266     {
    267         shiftSamplerBinding = shift;
    268         processes.addIfNonZero("shift-sampler-binding", shift);
    269     }
    270     unsigned int getShiftSamplerBinding() const { return shiftSamplerBinding; }
    271     void setShiftTextureBinding(unsigned int shift)
    272     {
    273         shiftTextureBinding = shift;
    274         processes.addIfNonZero("shift-texture-binding", shift);
    275     }
    276     unsigned int getShiftTextureBinding() const { return shiftTextureBinding; }
    277     void setShiftImageBinding(unsigned int shift)
    278     {
    279         shiftImageBinding = shift;
    280         processes.addIfNonZero("shift-image-binding", shift);
    281     }
    282     unsigned int getShiftImageBinding() const { return shiftImageBinding; }
    283     void setShiftUboBinding(unsigned int shift)
    284     {
    285         shiftUboBinding = shift;
    286         processes.addIfNonZero("shift-UBO-binding", shift);
    287     }
    288     unsigned int getShiftUboBinding() const { return shiftUboBinding; }
    289     void setShiftSsboBinding(unsigned int shift)
    290     {
    291         shiftSsboBinding = shift;
    292         processes.addIfNonZero("shift-ssbo-binding", shift);
    293     }
    294     unsigned int getShiftSsboBinding() const { return shiftSsboBinding; }
    295     void setShiftUavBinding(unsigned int shift)
    296     {
    297         shiftUavBinding = shift;
    298         processes.addIfNonZero("shift-uav-binding", shift);
    299     }
    300     unsigned int getShiftUavBinding() const { return shiftUavBinding; }
    301     void setResourceSetBinding(const std::vector<std::string>& shift)
    302     {
    303         resourceSetBinding = shift;
    304         if (shift.size() > 0) {
    305             processes.addProcess("resource-set-binding");
    306             for (int s = 0; s < (int)shift.size(); ++s)
    307                 processes.addArgument(shift[s]);
    308         }
    309     }
    310     const std::vector<std::string>& getResourceSetBinding() const { return resourceSetBinding; }
    311     void setAutoMapBindings(bool map)
    312     {
    313         autoMapBindings = map;
    314         if (autoMapBindings)
    315             processes.addProcess("auto-map-bindings");
    316     }
    317     bool getAutoMapBindings() const { return autoMapBindings; }
    318     void setAutoMapLocations(bool map)
    319     {
    320         autoMapLocations = map;
    321         if (autoMapLocations)
    322             processes.addProcess("auto-map-locations");
    323     }
    324     bool getAutoMapLocations() const { return autoMapLocations; }
    325     void setFlattenUniformArrays(bool flatten)
    326     {
    327         flattenUniformArrays = flatten;
    328         if (flattenUniformArrays)
    329             processes.addProcess("flatten-uniform-arrays");
    330     }
    331     bool getFlattenUniformArrays() const { return flattenUniformArrays; }
    332     void setNoStorageFormat(bool b)
    333     {
    334         useUnknownFormat = b;
    335         if (useUnknownFormat)
    336             processes.addProcess("no-storage-format");
    337     }
    338     bool getNoStorageFormat() const { return useUnknownFormat; }
    339     void setHlslOffsets()
    340     {
    341         hlslOffsets = true;
    342         if (hlslOffsets)
    343             processes.addProcess("hlsl-offsets");
    344     }
    345     bool usingHlslOFfsets() const { return hlslOffsets; }
    346     void setUseStorageBuffer()
    347     {
    348         useStorageBuffer = true;
    349         processes.addProcess("use-storage-buffer");
    350     }
    351     bool usingStorageBuffer() const { return useStorageBuffer; }
    352     void setHlslIoMapping(bool b)
    353     {
    354         hlslIoMapping = b;
    355         if (hlslIoMapping)
    356             processes.addProcess("hlsl-iomap");
    357     }
    358     bool usingHlslIoMapping() { return hlslIoMapping; }
    359 
    360     void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { textureSamplerTransformMode = mode; }
    361 
    362     void setVersion(int v) { version = v; }
    363     int getVersion() const { return version; }
    364     void setProfile(EProfile p) { profile = p; }
    365     EProfile getProfile() const { return profile; }
    366     void setSpv(const SpvVersion& s)
    367     {
    368         spvVersion = s;
    369 
    370         // client processes
    371         if (spvVersion.vulkan > 0)
    372             processes.addProcess("client vulkan100");
    373         if (spvVersion.openGl > 0)
    374             processes.addProcess("client opengl100");
    375 
    376         // target-environment processes
    377         if (spvVersion.vulkan == 100)
    378             processes.addProcess("target-env vulkan1.0");
    379         else if (spvVersion.vulkan > 0)
    380             processes.addProcess("target-env vulkanUnknown");
    381         if (spvVersion.openGl > 0)
    382             processes.addProcess("target-env opengl");
    383     }
    384     const SpvVersion& getSpv() const { return spvVersion; }
    385     EShLanguage getStage() const { return language; }
    386     void addRequestedExtension(const char* extension) { requestedExtensions.insert(extension); }
    387     const std::set<std::string>& getRequestedExtensions() const { return requestedExtensions; }
    388 
    389     void setTreeRoot(TIntermNode* r) { treeRoot = r; }
    390     TIntermNode* getTreeRoot() const { return treeRoot; }
    391     void incrementEntryPointCount() { ++numEntryPoints; }
    392     int getNumEntryPoints() const { return numEntryPoints; }
    393     int getNumErrors() const { return numErrors; }
    394     void addPushConstantCount() { ++numPushConstants; }
    395     bool isRecursive() const { return recursive; }
    396 
    397     TIntermSymbol* addSymbol(const TVariable&);
    398     TIntermSymbol* addSymbol(const TVariable&, const TSourceLoc&);
    399     TIntermSymbol* addSymbol(const TType&, const TSourceLoc&);
    400     TIntermSymbol* addSymbol(const TIntermSymbol&);
    401     TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*) const;
    402     TIntermTyped* addUniShapeConversion(TOperator, const TType&, TIntermTyped*);
    403     void addBiShapeConversion(TOperator, TIntermTyped*& lhsNode, TIntermTyped*& rhsNode);
    404     TIntermTyped* addShapeConversion(const TType&, TIntermTyped*);
    405     TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
    406     TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
    407     TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc);
    408     TIntermTyped* addUnaryMath(TOperator, TIntermTyped* child, TSourceLoc);
    409     TIntermTyped* addBuiltInFunctionCall(const TSourceLoc& line, TOperator, bool unary, TIntermNode*, const TType& returnType);
    410     bool canImplicitlyPromote(TBasicType from, TBasicType to, TOperator op = EOpNull) const;
    411     TOperator mapTypeToConstructorOp(const TType&) const;
    412     TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right);
    413     TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc&);
    414     TIntermAggregate* makeAggregate(TIntermNode* node);
    415     TIntermAggregate* makeAggregate(TIntermNode* node, const TSourceLoc&);
    416     TIntermAggregate* makeAggregate(const TSourceLoc&);
    417     TIntermTyped* setAggregateOperator(TIntermNode*, TOperator, const TType& type, TSourceLoc);
    418     bool areAllChildConst(TIntermAggregate* aggrNode);
    419     TIntermTyped* addSelection(TIntermTyped* cond, TIntermNodePair code, const TSourceLoc&, TSelectionControl = ESelectionControlNone);
    420     TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc&, TSelectionControl = ESelectionControlNone);
    421     TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc&);
    422     TIntermTyped* addMethod(TIntermTyped*, const TType&, const TString*, const TSourceLoc&);
    423     TIntermConstantUnion* addConstantUnion(const TConstUnionArray&, const TType&, const TSourceLoc&, bool literal = false) const;
    424     TIntermConstantUnion* addConstantUnion(int, const TSourceLoc&, bool literal = false) const;
    425     TIntermConstantUnion* addConstantUnion(unsigned int, const TSourceLoc&, bool literal = false) const;
    426     TIntermConstantUnion* addConstantUnion(long long, const TSourceLoc&, bool literal = false) const;
    427     TIntermConstantUnion* addConstantUnion(unsigned long long, const TSourceLoc&, bool literal = false) const;
    428 #ifdef AMD_EXTENSIONS
    429     TIntermConstantUnion* addConstantUnion(short, const TSourceLoc&, bool literal = false) const;
    430     TIntermConstantUnion* addConstantUnion(unsigned short, const TSourceLoc&, bool literal = false) const;
    431 
    432 #endif
    433     TIntermConstantUnion* addConstantUnion(bool, const TSourceLoc&, bool literal = false) const;
    434     TIntermConstantUnion* addConstantUnion(double, TBasicType, const TSourceLoc&, bool literal = false) const;
    435     TIntermConstantUnion* addConstantUnion(const TString*, const TSourceLoc&, bool literal = false) const;
    436     TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) const;
    437     bool parseConstTree(TIntermNode*, TConstUnionArray, TOperator, const TType&, bool singleConstantParam = false);
    438     TIntermLoop* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&, TLoopControl = ELoopControlNone);
    439     TIntermAggregate* addForLoop(TIntermNode*, TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&, TLoopControl = ELoopControlNone);
    440     TIntermBranch* addBranch(TOperator, const TSourceLoc&);
    441     TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&);
    442     template<typename selectorType> TIntermTyped* addSwizzle(TSwizzleSelectors<selectorType>&, const TSourceLoc&);
    443 
    444     // Low level functions to add nodes (no conversions or other higher level transformations)
    445     // If a type is provided, the node's type will be set to it.
    446     TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc) const;
    447     TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc, const TType&) const;
    448     TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc) const;
    449     TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc, const TType&) const;
    450 
    451     // Add conversion from node's type to given basic type.
    452     TIntermTyped* convertToBasicType(TOperator op, TBasicType basicType, TIntermTyped* node) const;
    453 
    454     // Constant folding (in Constant.cpp)
    455     TIntermTyped* fold(TIntermAggregate* aggrNode);
    456     TIntermTyped* foldConstructor(TIntermAggregate* aggrNode);
    457     TIntermTyped* foldDereference(TIntermTyped* node, int index, const TSourceLoc&);
    458     TIntermTyped* foldSwizzle(TIntermTyped* node, TSwizzleSelectors<TVectorSelector>& fields, const TSourceLoc&);
    459 
    460     // Tree ops
    461     static const TIntermTyped* findLValueBase(const TIntermTyped*, bool swizzleOkay);
    462 
    463     // Linkage related
    464     void addSymbolLinkageNodes(TIntermAggregate*& linkage, EShLanguage, TSymbolTable&);
    465     void addSymbolLinkageNode(TIntermAggregate*& linkage, const TSymbol&);
    466 
    467     bool setInvocations(int i)
    468     {
    469         if (invocations != TQualifier::layoutNotSet)
    470             return invocations == i;
    471         invocations = i;
    472         return true;
    473     }
    474     int getInvocations() const { return invocations; }
    475     bool setVertices(int m)
    476     {
    477         if (vertices != TQualifier::layoutNotSet)
    478             return vertices == m;
    479         vertices = m;
    480         return true;
    481     }
    482     int getVertices() const { return vertices; }
    483     bool setInputPrimitive(TLayoutGeometry p)
    484     {
    485         if (inputPrimitive != ElgNone)
    486             return inputPrimitive == p;
    487         inputPrimitive = p;
    488         return true;
    489     }
    490     TLayoutGeometry getInputPrimitive() const { return inputPrimitive; }
    491     bool setVertexSpacing(TVertexSpacing s)
    492     {
    493         if (vertexSpacing != EvsNone)
    494             return vertexSpacing == s;
    495         vertexSpacing = s;
    496         return true;
    497     }
    498     TVertexSpacing getVertexSpacing() const { return vertexSpacing; }
    499     bool setVertexOrder(TVertexOrder o)
    500     {
    501         if (vertexOrder != EvoNone)
    502             return vertexOrder == o;
    503         vertexOrder = o;
    504         return true;
    505     }
    506     TVertexOrder getVertexOrder() const { return vertexOrder; }
    507     void setPointMode() { pointMode = true; }
    508     bool getPointMode() const { return pointMode; }
    509 
    510     bool setLocalSize(int dim, int size)
    511     {
    512         if (localSize[dim] > 1)
    513             return size == localSize[dim];
    514         localSize[dim] = size;
    515         return true;
    516     }
    517     unsigned int getLocalSize(int dim) const { return localSize[dim]; }
    518 
    519     bool setLocalSizeSpecId(int dim, int id)
    520     {
    521         if (localSizeSpecId[dim] != TQualifier::layoutNotSet)
    522             return id == localSizeSpecId[dim];
    523         localSizeSpecId[dim] = id;
    524         return true;
    525     }
    526     int getLocalSizeSpecId(int dim) const { return localSizeSpecId[dim]; }
    527 
    528     void setXfbMode() { xfbMode = true; }
    529     bool getXfbMode() const { return xfbMode; }
    530     void setMultiStream() { multiStream = true; }
    531     bool isMultiStream() const { return multiStream; }
    532     bool setOutputPrimitive(TLayoutGeometry p)
    533     {
    534         if (outputPrimitive != ElgNone)
    535             return outputPrimitive == p;
    536         outputPrimitive = p;
    537         return true;
    538     }
    539     TLayoutGeometry getOutputPrimitive() const { return outputPrimitive; }
    540     void setOriginUpperLeft() { originUpperLeft = true; }
    541     bool getOriginUpperLeft() const { return originUpperLeft; }
    542     void setPixelCenterInteger() { pixelCenterInteger = true; }
    543     bool getPixelCenterInteger() const { return pixelCenterInteger; }
    544     void setEarlyFragmentTests() { earlyFragmentTests = true; }
    545     bool getEarlyFragmentTests() const { return earlyFragmentTests; }
    546     void setPostDepthCoverage() { postDepthCoverage = true; }
    547     bool getPostDepthCoverage() const { return postDepthCoverage; }
    548     bool setDepth(TLayoutDepth d)
    549     {
    550         if (depthLayout != EldNone)
    551             return depthLayout == d;
    552         depthLayout = d;
    553         return true;
    554     }
    555     TLayoutDepth getDepth() const { return depthLayout; }
    556     void setDepthReplacing() { depthReplacing = true; }
    557     bool isDepthReplacing() const { return depthReplacing; }
    558 
    559     void addBlendEquation(TBlendEquationShift b) { blendEquations |= (1 << b); }
    560     unsigned int getBlendEquations() const { return blendEquations; }
    561 
    562     void addToCallGraph(TInfoSink&, const TString& caller, const TString& callee);
    563     void merge(TInfoSink&, TIntermediate&);
    564     void finalCheck(TInfoSink&, bool keepUncalled);
    565 
    566     void addIoAccessed(const TString& name) { ioAccessed.insert(name); }
    567     bool inIoAccessed(const TString& name) const { return ioAccessed.find(name) != ioAccessed.end(); }
    568 
    569     int addUsedLocation(const TQualifier&, const TType&, bool& typeCollision);
    570     int checkLocationRange(int set, const TIoRange& range, const TType&, bool& typeCollision);
    571     int addUsedOffsets(int binding, int offset, int numOffsets);
    572     bool addUsedConstantId(int id);
    573     int computeTypeLocationSize(const TType&) const;
    574 
    575     bool setXfbBufferStride(int buffer, unsigned stride)
    576     {
    577         if (xfbBuffers[buffer].stride != TQualifier::layoutXfbStrideEnd)
    578             return xfbBuffers[buffer].stride == stride;
    579         xfbBuffers[buffer].stride = stride;
    580         return true;
    581     }
    582     int addXfbBufferOffset(const TType&);
    583     unsigned int computeTypeXfbSize(const TType&, bool& containsDouble) const;
    584     static int getBaseAlignmentScalar(const TType&, int& size);
    585     static int getBaseAlignment(const TType&, int& size, int& stride, bool std140, bool rowMajor);
    586     static bool improperStraddle(const TType& type, int size, int offset);
    587     bool promote(TIntermOperator*);
    588 
    589 #ifdef NV_EXTENSIONS
    590     void setLayoutOverrideCoverage() { layoutOverrideCoverage = true; }
    591     bool getLayoutOverrideCoverage() const { return layoutOverrideCoverage; }
    592     void setGeoPassthroughEXT() { geoPassthroughEXT = true; }
    593     bool getGeoPassthroughEXT() const { return geoPassthroughEXT; }
    594 #endif
    595 
    596     const char* addSemanticName(const TString& name)
    597     {
    598         return semanticNameSet.insert(name).first->c_str();
    599     }
    600 
    601     void setSourceFile(const char* file) { sourceFile = file; }
    602     const std::string& getSourceFile() const { return sourceFile; }
    603     void addSourceText(const char* text) { sourceText = sourceText + text; }
    604     const std::string& getSourceText() const { return sourceText; }
    605     void addProcesses(const std::vector<std::string>& p) {
    606         for (int i = 0; i < (int)p.size(); ++i)
    607             processes.addProcess(p[i]);
    608     }
    609     void addProcess(const std::string& process) { processes.addProcess(process); }
    610     void addProcessArgument(const std::string& arg) { processes.addArgument(arg); }
    611     const std::vector<std::string>& getProcesses() const { return processes.getProcesses(); }
    612 
    613     const char* const implicitThisName;
    614 
    615 protected:
    616     TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&);
    617     void error(TInfoSink& infoSink, const char*);
    618     void warn(TInfoSink& infoSink, const char*);
    619     void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals);
    620     void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects);
    621     void mergeImplicitArraySizes(TType&, const TType&);
    622     void mergeErrorCheck(TInfoSink&, const TIntermSymbol&, const TIntermSymbol&, bool crossStage);
    623     void checkCallGraphCycles(TInfoSink&);
    624     void checkCallGraphBodies(TInfoSink&, bool keepUncalled);
    625     void inOutLocationCheck(TInfoSink&);
    626     TIntermSequence& findLinkerObjects() const;
    627     bool userOutputUsed() const;
    628     bool isSpecializationOperation(const TIntermOperator&) const;
    629     bool promoteUnary(TIntermUnary&);
    630     bool promoteBinary(TIntermBinary&);
    631     void addSymbolLinkageNode(TIntermAggregate*& linkage, TSymbolTable&, const TString&);
    632     bool promoteAggregate(TIntermAggregate&);
    633     void pushSelector(TIntermSequence&, const TVectorSelector&, const TSourceLoc&);
    634     void pushSelector(TIntermSequence&, const TMatrixSelector&, const TSourceLoc&);
    635     bool specConstantPropagates(const TIntermTyped&, const TIntermTyped&);
    636     void performTextureUpgradeAndSamplerRemovalTransformation(TIntermNode* root);
    637 
    638     const EShLanguage language;  // stage, known at construction time
    639     EShSource source;            // source language, known a bit later
    640     std::string entryPointName;
    641     std::string entryPointMangledName;
    642 
    643     EProfile profile;
    644     int version;
    645     SpvVersion spvVersion;
    646     TIntermNode* treeRoot;
    647     std::set<std::string> requestedExtensions;  // cumulation of all enabled or required extensions; not connected to what subset of the shader used them
    648     TBuiltInResource resources;
    649     int numEntryPoints;
    650     int numErrors;
    651     int numPushConstants;
    652     bool recursive;
    653     int invocations;
    654     int vertices;
    655     TLayoutGeometry inputPrimitive;
    656     TLayoutGeometry outputPrimitive;
    657     bool pixelCenterInteger;
    658     bool originUpperLeft;
    659     TVertexSpacing vertexSpacing;
    660     TVertexOrder vertexOrder;
    661     bool pointMode;
    662     int localSize[3];
    663     int localSizeSpecId[3];
    664     bool earlyFragmentTests;
    665     bool postDepthCoverage;
    666     TLayoutDepth depthLayout;
    667     bool depthReplacing;
    668     int blendEquations;        // an 'or'ing of masks of shifts of TBlendEquationShift
    669     bool xfbMode;
    670     bool multiStream;
    671 
    672 #ifdef NV_EXTENSIONS
    673     bool layoutOverrideCoverage;
    674     bool geoPassthroughEXT;
    675 #endif
    676 
    677     unsigned int shiftSamplerBinding;
    678     unsigned int shiftTextureBinding;
    679     unsigned int shiftImageBinding;
    680     unsigned int shiftUboBinding;
    681     unsigned int shiftSsboBinding;
    682     unsigned int shiftUavBinding;
    683     std::vector<std::string> resourceSetBinding;
    684     bool autoMapBindings;
    685     bool autoMapLocations;
    686     bool flattenUniformArrays;
    687     bool useUnknownFormat;
    688     bool hlslOffsets;
    689     bool useStorageBuffer;
    690     bool hlslIoMapping;
    691 
    692     typedef std::list<TCall> TGraph;
    693     TGraph callGraph;
    694 
    695     std::set<TString> ioAccessed;           // set of names of statically read/written I/O that might need extra checking
    696     std::vector<TIoRange> usedIo[4];        // sets of used locations, one for each of in, out, uniform, and buffers
    697     std::vector<TOffsetRange> usedAtomics;  // sets of bindings used by atomic counters
    698     std::vector<TXfbBuffer> xfbBuffers;     // all the data we need to track per xfb buffer
    699     std::unordered_set<int> usedConstantId; // specialization constant ids used
    700     std::set<TString> semanticNameSet;
    701 
    702     EShTextureSamplerTransformMode textureSamplerTransformMode;
    703 
    704     // source code of shader, useful as part of debug information
    705     std::string sourceFile;
    706     std::string sourceText;
    707 
    708     // for OpModuleProcessed, or equivalent
    709     TProcesses processes;
    710 
    711 private:
    712     void operator=(TIntermediate&); // prevent assignments
    713 };
    714 
    715 } // end namespace glslang
    716 
    717 #endif // _LOCAL_INTERMEDIATE_INCLUDED_
    718