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