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: TSwizzleSelectors()68 TSwizzleSelectors() : size_(0) { } 69 push_back(selectorType comp)70 void push_back(selectorType comp) 71 { 72 if (size_ < MaxSwizzleSelectors) 73 components[size_++] = comp; 74 } resize(int s)75 void resize(int s) 76 { 77 assert(s <= size_); 78 size_ = s; 79 } size()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 { TCallTCall101 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 { TRangeTRange112 TRange(int start, int last) : start(start), last(last) { } overlapTRange113 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 { TIoRangeTIoRange125 TIoRange(TRange location, TRange component, TBasicType basicType, int index) 126 : location(location), component(component), basicType(basicType), index(index) { } overlapTIoRange127 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 { TOffsetRangeTOffsetRange140 TOffsetRange(TRange binding, TRange offset) 141 : binding(binding), offset(offset) { } overlapTOffsetRange142 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 { TXfbBufferTXfbBuffer153 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: TProcesses()174 TProcesses() {} ~TProcesses()175 ~TProcesses() {} 176 addProcess(const char * process)177 void addProcess(const char* process) 178 { 179 processes.push_back(process); 180 } addProcess(const std::string & process)181 void addProcess(const std::string& process) 182 { 183 processes.push_back(process); 184 } addArgument(int arg)185 void addArgument(int arg) 186 { 187 processes.back().append(" "); 188 std::string argString = std::to_string(arg); 189 processes.back().append(argString); 190 } addArgument(const char * arg)191 void addArgument(const char* arg) 192 { 193 processes.back().append(" "); 194 processes.back().append(arg); 195 } addArgument(const std::string & arg)196 void addArgument(const std::string& arg) 197 { 198 processes.back().append(" "); 199 processes.back().append(arg); 200 } addIfNonZero(const char * process,int value)201 void addIfNonZero(const char* process, int value) 202 { 203 if (value != 0) { 204 addProcess(process); 205 addArgument(value); 206 } 207 } 208 getProcesses()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, int>& operator[](int i) { return maps[i]; } 231 const TMap<TString, int>& operator[](int i) const { return maps[i]; } 232 private: 233 TMap<TString, int> maps[EsiCount]; 234 }; 235 236 class TNumericFeatures { 237 public: TNumericFeatures()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; insert(feature f)255 void insert(feature f) { features |= f; } erase(feature f)256 void erase(feature f) { features &= ~f; } contains(feature 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; MustBeAssigned(const T & v)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) : language(l)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 nanMinMaxClamp(false), 295 depthReplacing(false) 296 #ifndef GLSLANG_WEB 297 , 298 implicitThisName("@this"), implicitCounterName("@count"), 299 source(EShSourceNone), 300 useVulkanMemoryModel(false), 301 invocations(TQualifier::layoutNotSet), vertices(TQualifier::layoutNotSet), 302 inputPrimitive(ElgNone), outputPrimitive(ElgNone), 303 pixelCenterInteger(false), originUpperLeft(false), 304 vertexSpacing(EvsNone), vertexOrder(EvoNone), interlockOrdering(EioNone), pointMode(false), earlyFragmentTests(false), 305 postDepthCoverage(false), depthLayout(EldNone), 306 hlslFunctionality1(false), 307 blendEquations(0), xfbMode(false), multiStream(false), 308 layoutOverrideCoverage(false), 309 geoPassthroughEXT(false), 310 numShaderRecordBlocks(0), 311 computeDerivativeMode(LayoutDerivativeNone), 312 primitives(TQualifier::layoutNotSet), 313 numTaskNVBlocks(0), 314 layoutPrimitiveCulling(false), 315 autoMapBindings(false), 316 autoMapLocations(false), 317 flattenUniformArrays(false), 318 useUnknownFormat(false), 319 hlslOffsets(false), 320 hlslIoMapping(false), 321 useVariablePointers(false), 322 textureSamplerTransformMode(EShTexSampTransKeep), 323 needToLegalize(false), 324 binaryDoubleOutput(false), 325 usePhysicalStorageBuffer(false), 326 uniformLocationBase(0) 327 #endif 328 { 329 localSize[0] = 1; 330 localSize[1] = 1; 331 localSize[2] = 1; 332 localSizeNotDefault[0] = false; 333 localSizeNotDefault[1] = false; 334 localSizeNotDefault[2] = false; 335 localSizeSpecId[0] = TQualifier::layoutNotSet; 336 localSizeSpecId[1] = TQualifier::layoutNotSet; 337 localSizeSpecId[2] = TQualifier::layoutNotSet; 338 #ifndef GLSLANG_WEB 339 xfbBuffers.resize(TQualifier::layoutXfbBufferEnd); 340 shiftBinding.fill(0); 341 #endif 342 } 343 setVersion(int v)344 void setVersion(int v) 345 { 346 #ifndef GLSLANG_ANGLE 347 version = v; 348 #endif 349 } setProfile(EProfile p)350 void setProfile(EProfile p) 351 { 352 #ifndef GLSLANG_ANGLE 353 profile = p; 354 #endif 355 } 356 getVersion()357 int getVersion() const { return version; } getProfile()358 EProfile getProfile() const { return profile; } setSpv(const SpvVersion & s)359 void setSpv(const SpvVersion& s) 360 { 361 spvVersion = s; 362 363 // client processes 364 if (spvVersion.vulkan > 0) 365 processes.addProcess("client vulkan100"); 366 if (spvVersion.openGl > 0) 367 processes.addProcess("client opengl100"); 368 369 // target SPV 370 switch (spvVersion.spv) { 371 case 0: 372 break; 373 case EShTargetSpv_1_0: 374 break; 375 case EShTargetSpv_1_1: 376 processes.addProcess("target-env spirv1.1"); 377 break; 378 case EShTargetSpv_1_2: 379 processes.addProcess("target-env spirv1.2"); 380 break; 381 case EShTargetSpv_1_3: 382 processes.addProcess("target-env spirv1.3"); 383 break; 384 case EShTargetSpv_1_4: 385 processes.addProcess("target-env spirv1.4"); 386 break; 387 case EShTargetSpv_1_5: 388 processes.addProcess("target-env spirv1.5"); 389 break; 390 default: 391 processes.addProcess("target-env spirvUnknown"); 392 break; 393 } 394 395 // target-environment processes 396 switch (spvVersion.vulkan) { 397 case 0: 398 break; 399 case EShTargetVulkan_1_0: 400 processes.addProcess("target-env vulkan1.0"); 401 break; 402 case EShTargetVulkan_1_1: 403 processes.addProcess("target-env vulkan1.1"); 404 break; 405 case EShTargetVulkan_1_2: 406 processes.addProcess("target-env vulkan1.2"); 407 break; 408 default: 409 processes.addProcess("target-env vulkanUnknown"); 410 break; 411 } 412 if (spvVersion.openGl > 0) 413 processes.addProcess("target-env opengl"); 414 } getSpv()415 const SpvVersion& getSpv() const { return spvVersion; } getStage()416 EShLanguage getStage() const { return language; } addRequestedExtension(const char * extension)417 void addRequestedExtension(const char* extension) { requestedExtensions.insert(extension); } getRequestedExtensions()418 const std::set<std::string>& getRequestedExtensions() const { return requestedExtensions; } isRayTracingStage()419 bool isRayTracingStage() const { 420 return language >= EShLangRayGen && language <= EShLangCallableNV; 421 } 422 setTreeRoot(TIntermNode * r)423 void setTreeRoot(TIntermNode* r) { treeRoot = r; } getTreeRoot()424 TIntermNode* getTreeRoot() const { return treeRoot; } incrementEntryPointCount()425 void incrementEntryPointCount() { ++numEntryPoints; } getNumEntryPoints()426 int getNumEntryPoints() const { return numEntryPoints; } getNumErrors()427 int getNumErrors() const { return numErrors; } addPushConstantCount()428 void addPushConstantCount() { ++numPushConstants; } setLimits(const TBuiltInResource & r)429 void setLimits(const TBuiltInResource& r) { resources = r; } getLimits()430 const TBuiltInResource& getLimits() const { return resources; } 431 432 bool postProcess(TIntermNode*, EShLanguage); 433 void removeTree(); 434 setEntryPointName(const char * ep)435 void setEntryPointName(const char* ep) 436 { 437 entryPointName = ep; 438 processes.addProcess("entry-point"); 439 processes.addArgument(entryPointName); 440 } setEntryPointMangledName(const char * ep)441 void setEntryPointMangledName(const char* ep) { entryPointMangledName = ep; } getEntryPointName()442 const std::string& getEntryPointName() const { return entryPointName; } getEntryPointMangledName()443 const std::string& getEntryPointMangledName() const { return entryPointMangledName; } 444 setInvertY(bool invert)445 void setInvertY(bool invert) 446 { 447 invertY = invert; 448 if (invertY) 449 processes.addProcess("invert-y"); 450 } getInvertY()451 bool getInvertY() const { return invertY; } 452 453 #ifdef ENABLE_HLSL setSource(EShSource s)454 void setSource(EShSource s) { source = s; } getSource()455 EShSource getSource() const { return source; } 456 #else setSource(EShSource s)457 void setSource(EShSource s) { assert(s == EShSourceGlsl); (void)s; } getSource()458 EShSource getSource() const { return EShSourceGlsl; } 459 #endif 460 isRecursive()461 bool isRecursive() const { return recursive; } 462 463 TIntermSymbol* addSymbol(const TVariable&); 464 TIntermSymbol* addSymbol(const TVariable&, const TSourceLoc&); 465 TIntermSymbol* addSymbol(const TType&, const TSourceLoc&); 466 TIntermSymbol* addSymbol(const TIntermSymbol&); 467 TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*); 468 std::tuple<TIntermTyped*, TIntermTyped*> addPairConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1); 469 TIntermTyped* addUniShapeConversion(TOperator, const TType&, TIntermTyped*); 470 TIntermTyped* addConversion(TBasicType convertTo, TIntermTyped* node) const; 471 void addBiShapeConversion(TOperator, TIntermTyped*& lhsNode, TIntermTyped*& rhsNode); 472 TIntermTyped* addShapeConversion(const TType&, TIntermTyped*); 473 TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&); 474 TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&); 475 TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc&); 476 TIntermTyped* addUnaryMath(TOperator, TIntermTyped* child, const TSourceLoc&); 477 TIntermTyped* addBuiltInFunctionCall(const TSourceLoc& line, TOperator, bool unary, TIntermNode*, const TType& returnType); 478 bool canImplicitlyPromote(TBasicType from, TBasicType to, TOperator op = EOpNull) const; 479 bool isIntegralPromotion(TBasicType from, TBasicType to) const; 480 bool isFPPromotion(TBasicType from, TBasicType to) const; 481 bool isIntegralConversion(TBasicType from, TBasicType to) const; 482 bool isFPConversion(TBasicType from, TBasicType to) const; 483 bool isFPIntegralConversion(TBasicType from, TBasicType to) const; 484 TOperator mapTypeToConstructorOp(const TType&) const; 485 TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right); 486 TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc&); 487 TIntermAggregate* makeAggregate(TIntermNode* node); 488 TIntermAggregate* makeAggregate(TIntermNode* node, const TSourceLoc&); 489 TIntermAggregate* makeAggregate(const TSourceLoc&); 490 TIntermTyped* setAggregateOperator(TIntermNode*, TOperator, const TType& type, const TSourceLoc&); 491 bool areAllChildConst(TIntermAggregate* aggrNode); 492 TIntermSelection* addSelection(TIntermTyped* cond, TIntermNodePair code, const TSourceLoc&); 493 TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc&); 494 TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc&); 495 TIntermTyped* addMethod(TIntermTyped*, const TType&, const TString*, const TSourceLoc&); 496 TIntermConstantUnion* addConstantUnion(const TConstUnionArray&, const TType&, const TSourceLoc&, bool literal = false) const; 497 TIntermConstantUnion* addConstantUnion(signed char, const TSourceLoc&, bool literal = false) const; 498 TIntermConstantUnion* addConstantUnion(unsigned char, const TSourceLoc&, bool literal = false) const; 499 TIntermConstantUnion* addConstantUnion(signed short, const TSourceLoc&, bool literal = false) const; 500 TIntermConstantUnion* addConstantUnion(unsigned short, const TSourceLoc&, bool literal = false) const; 501 TIntermConstantUnion* addConstantUnion(int, const TSourceLoc&, bool literal = false) const; 502 TIntermConstantUnion* addConstantUnion(unsigned int, const TSourceLoc&, bool literal = false) const; 503 TIntermConstantUnion* addConstantUnion(long long, const TSourceLoc&, bool literal = false) const; 504 TIntermConstantUnion* addConstantUnion(unsigned long long, const TSourceLoc&, bool literal = false) const; 505 TIntermConstantUnion* addConstantUnion(bool, const TSourceLoc&, bool literal = false) const; 506 TIntermConstantUnion* addConstantUnion(double, TBasicType, const TSourceLoc&, bool literal = false) const; 507 TIntermConstantUnion* addConstantUnion(const TString*, const TSourceLoc&, bool literal = false) const; 508 TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) const; 509 bool parseConstTree(TIntermNode*, TConstUnionArray, TOperator, const TType&, bool singleConstantParam = false); 510 TIntermLoop* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&); 511 TIntermAggregate* addForLoop(TIntermNode*, TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, 512 const TSourceLoc&, TIntermLoop*&); 513 TIntermBranch* addBranch(TOperator, const TSourceLoc&); 514 TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&); 515 template<typename selectorType> TIntermTyped* addSwizzle(TSwizzleSelectors<selectorType>&, const TSourceLoc&); 516 517 // Low level functions to add nodes (no conversions or other higher level transformations) 518 // If a type is provided, the node's type will be set to it. 519 TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&) const; 520 TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&, 521 const TType&) const; 522 TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, const TSourceLoc&) const; 523 TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, const TSourceLoc&, const TType&) const; 524 525 // Constant folding (in Constant.cpp) 526 TIntermTyped* fold(TIntermAggregate* aggrNode); 527 TIntermTyped* foldConstructor(TIntermAggregate* aggrNode); 528 TIntermTyped* foldDereference(TIntermTyped* node, int index, const TSourceLoc&); 529 TIntermTyped* foldSwizzle(TIntermTyped* node, TSwizzleSelectors<TVectorSelector>& fields, const TSourceLoc&); 530 531 // Tree ops 532 static const TIntermTyped* findLValueBase(const TIntermTyped*, bool swizzleOkay); 533 534 // Linkage related 535 void addSymbolLinkageNodes(TIntermAggregate*& linkage, EShLanguage, TSymbolTable&); 536 void addSymbolLinkageNode(TIntermAggregate*& linkage, const TSymbol&); 537 TIntermAggregate* findLinkerObjects() const; 538 setUseStorageBuffer()539 void setUseStorageBuffer() { useStorageBuffer = true; } usingStorageBuffer()540 bool usingStorageBuffer() const { return useStorageBuffer; } setDepthReplacing()541 void setDepthReplacing() { depthReplacing = true; } isDepthReplacing()542 bool isDepthReplacing() const { return depthReplacing; } setLocalSize(int dim,int size)543 bool setLocalSize(int dim, int size) 544 { 545 if (localSizeNotDefault[dim]) 546 return size == localSize[dim]; 547 localSizeNotDefault[dim] = true; 548 localSize[dim] = size; 549 return true; 550 } getLocalSize(int dim)551 unsigned int getLocalSize(int dim) const { return localSize[dim]; } setLocalSizeSpecId(int dim,int id)552 bool setLocalSizeSpecId(int dim, int id) 553 { 554 if (localSizeSpecId[dim] != TQualifier::layoutNotSet) 555 return id == localSizeSpecId[dim]; 556 localSizeSpecId[dim] = id; 557 return true; 558 } getLocalSizeSpecId(int dim)559 int getLocalSizeSpecId(int dim) const { return localSizeSpecId[dim]; } 560 #ifdef GLSLANG_WEB output(TInfoSink &,bool tree)561 void output(TInfoSink&, bool tree) { } 562 isEsProfile()563 bool isEsProfile() const { return false; } getXfbMode()564 bool getXfbMode() const { return false; } isMultiStream()565 bool isMultiStream() const { return false; } getOutputPrimitive()566 TLayoutGeometry getOutputPrimitive() const { return ElgNone; } getPostDepthCoverage()567 bool getPostDepthCoverage() const { return false; } getEarlyFragmentTests()568 bool getEarlyFragmentTests() const { return false; } getDepth()569 TLayoutDepth getDepth() const { return EldNone; } getPixelCenterInteger()570 bool getPixelCenterInteger() const { return false; } setOriginUpperLeft()571 void setOriginUpperLeft() { } getOriginUpperLeft()572 bool getOriginUpperLeft() const { return true; } getInterlockOrdering()573 TInterlockOrdering getInterlockOrdering() const { return EioNone; } 574 getAutoMapBindings()575 bool getAutoMapBindings() const { return false; } getAutoMapLocations()576 bool getAutoMapLocations() const { return false; } getNumPushConstants()577 int getNumPushConstants() const { return 0; } addShaderRecordCount()578 void addShaderRecordCount() { } addTaskNVCount()579 void addTaskNVCount() { } setUseVulkanMemoryModel()580 void setUseVulkanMemoryModel() { } usingVulkanMemoryModel()581 bool usingVulkanMemoryModel() const { return false; } usingPhysicalStorageBuffer()582 bool usingPhysicalStorageBuffer() const { return false; } usingVariablePointers()583 bool usingVariablePointers() const { return false; } getXfbStride(int buffer)584 unsigned getXfbStride(int buffer) const { return 0; } hasLayoutDerivativeModeNone()585 bool hasLayoutDerivativeModeNone() const { return false; } getLayoutDerivativeModeNone()586 ComputeDerivativeMode getLayoutDerivativeModeNone() const { return LayoutDerivativeNone; } 587 #else 588 void output(TInfoSink&, bool tree); 589 isEsProfile()590 bool isEsProfile() const { return profile == EEsProfile; } 591 setShiftBinding(TResourceType res,unsigned int shift)592 void setShiftBinding(TResourceType res, unsigned int shift) 593 { 594 shiftBinding[res] = shift; 595 596 const char* name = getResourceName(res); 597 if (name != nullptr) 598 processes.addIfNonZero(name, shift); 599 } 600 getShiftBinding(TResourceType res)601 unsigned int getShiftBinding(TResourceType res) const { return shiftBinding[res]; } 602 setShiftBindingForSet(TResourceType res,unsigned int shift,unsigned int set)603 void setShiftBindingForSet(TResourceType res, unsigned int shift, unsigned int set) 604 { 605 if (shift == 0) // ignore if there's no shift: it's a no-op. 606 return; 607 608 shiftBindingForSet[res][set] = shift; 609 610 const char* name = getResourceName(res); 611 if (name != nullptr) { 612 processes.addProcess(name); 613 processes.addArgument(shift); 614 processes.addArgument(set); 615 } 616 } 617 getShiftBindingForSet(TResourceType res,unsigned int set)618 int getShiftBindingForSet(TResourceType res, unsigned int set) const 619 { 620 const auto shift = shiftBindingForSet[res].find(set); 621 return shift == shiftBindingForSet[res].end() ? -1 : shift->second; 622 } hasShiftBindingForSet(TResourceType res)623 bool hasShiftBindingForSet(TResourceType res) const { return !shiftBindingForSet[res].empty(); } 624 setResourceSetBinding(const std::vector<std::string> & shift)625 void setResourceSetBinding(const std::vector<std::string>& shift) 626 { 627 resourceSetBinding = shift; 628 if (shift.size() > 0) { 629 processes.addProcess("resource-set-binding"); 630 for (int s = 0; s < (int)shift.size(); ++s) 631 processes.addArgument(shift[s]); 632 } 633 } getResourceSetBinding()634 const std::vector<std::string>& getResourceSetBinding() const { return resourceSetBinding; } setAutoMapBindings(bool map)635 void setAutoMapBindings(bool map) 636 { 637 autoMapBindings = map; 638 if (autoMapBindings) 639 processes.addProcess("auto-map-bindings"); 640 } getAutoMapBindings()641 bool getAutoMapBindings() const { return autoMapBindings; } setAutoMapLocations(bool map)642 void setAutoMapLocations(bool map) 643 { 644 autoMapLocations = map; 645 if (autoMapLocations) 646 processes.addProcess("auto-map-locations"); 647 } getAutoMapLocations()648 bool getAutoMapLocations() const { return autoMapLocations; } 649 650 #ifdef ENABLE_HLSL setFlattenUniformArrays(bool flatten)651 void setFlattenUniformArrays(bool flatten) 652 { 653 flattenUniformArrays = flatten; 654 if (flattenUniformArrays) 655 processes.addProcess("flatten-uniform-arrays"); 656 } getFlattenUniformArrays()657 bool getFlattenUniformArrays() const { return flattenUniformArrays; } 658 #endif setNoStorageFormat(bool b)659 void setNoStorageFormat(bool b) 660 { 661 useUnknownFormat = b; 662 if (useUnknownFormat) 663 processes.addProcess("no-storage-format"); 664 } getNoStorageFormat()665 bool getNoStorageFormat() const { return useUnknownFormat; } setUseVulkanMemoryModel()666 void setUseVulkanMemoryModel() 667 { 668 useVulkanMemoryModel = true; 669 processes.addProcess("use-vulkan-memory-model"); 670 } usingVulkanMemoryModel()671 bool usingVulkanMemoryModel() const { return useVulkanMemoryModel; } setUsePhysicalStorageBuffer()672 void setUsePhysicalStorageBuffer() 673 { 674 usePhysicalStorageBuffer = true; 675 } usingPhysicalStorageBuffer()676 bool usingPhysicalStorageBuffer() const { return usePhysicalStorageBuffer; } setUseVariablePointers()677 void setUseVariablePointers() 678 { 679 useVariablePointers = true; 680 processes.addProcess("use-variable-pointers"); 681 } usingVariablePointers()682 bool usingVariablePointers() const { return useVariablePointers; } 683 684 #ifdef ENABLE_HLSL addCounterBufferName(const T & name)685 template<class T> T addCounterBufferName(const T& name) const { return name + implicitCounterName; } hasCounterBufferName(const TString & name)686 bool hasCounterBufferName(const TString& name) const { 687 size_t len = strlen(implicitCounterName); 688 return name.size() > len && 689 name.compare(name.size() - len, len, implicitCounterName) == 0; 690 } 691 #endif 692 setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode)693 void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { textureSamplerTransformMode = mode; } getNumPushConstants()694 int getNumPushConstants() const { return numPushConstants; } addShaderRecordCount()695 void addShaderRecordCount() { ++numShaderRecordBlocks; } addTaskNVCount()696 void addTaskNVCount() { ++numTaskNVBlocks; } 697 setInvocations(int i)698 bool setInvocations(int i) 699 { 700 if (invocations != TQualifier::layoutNotSet) 701 return invocations == i; 702 invocations = i; 703 return true; 704 } getInvocations()705 int getInvocations() const { return invocations; } setVertices(int m)706 bool setVertices(int m) 707 { 708 if (vertices != TQualifier::layoutNotSet) 709 return vertices == m; 710 vertices = m; 711 return true; 712 } getVertices()713 int getVertices() const { return vertices; } setInputPrimitive(TLayoutGeometry p)714 bool setInputPrimitive(TLayoutGeometry p) 715 { 716 if (inputPrimitive != ElgNone) 717 return inputPrimitive == p; 718 inputPrimitive = p; 719 return true; 720 } getInputPrimitive()721 TLayoutGeometry getInputPrimitive() const { return inputPrimitive; } setVertexSpacing(TVertexSpacing s)722 bool setVertexSpacing(TVertexSpacing s) 723 { 724 if (vertexSpacing != EvsNone) 725 return vertexSpacing == s; 726 vertexSpacing = s; 727 return true; 728 } getVertexSpacing()729 TVertexSpacing getVertexSpacing() const { return vertexSpacing; } setVertexOrder(TVertexOrder o)730 bool setVertexOrder(TVertexOrder o) 731 { 732 if (vertexOrder != EvoNone) 733 return vertexOrder == o; 734 vertexOrder = o; 735 return true; 736 } getVertexOrder()737 TVertexOrder getVertexOrder() const { return vertexOrder; } setPointMode()738 void setPointMode() { pointMode = true; } getPointMode()739 bool getPointMode() const { return pointMode; } 740 setInterlockOrdering(TInterlockOrdering o)741 bool setInterlockOrdering(TInterlockOrdering o) 742 { 743 if (interlockOrdering != EioNone) 744 return interlockOrdering == o; 745 interlockOrdering = o; 746 return true; 747 } getInterlockOrdering()748 TInterlockOrdering getInterlockOrdering() const { return interlockOrdering; } 749 setXfbMode()750 void setXfbMode() { xfbMode = true; } getXfbMode()751 bool getXfbMode() const { return xfbMode; } setMultiStream()752 void setMultiStream() { multiStream = true; } isMultiStream()753 bool isMultiStream() const { return multiStream; } setOutputPrimitive(TLayoutGeometry p)754 bool setOutputPrimitive(TLayoutGeometry p) 755 { 756 if (outputPrimitive != ElgNone) 757 return outputPrimitive == p; 758 outputPrimitive = p; 759 return true; 760 } getOutputPrimitive()761 TLayoutGeometry getOutputPrimitive() const { return outputPrimitive; } setPostDepthCoverage()762 void setPostDepthCoverage() { postDepthCoverage = true; } getPostDepthCoverage()763 bool getPostDepthCoverage() const { return postDepthCoverage; } setEarlyFragmentTests()764 void setEarlyFragmentTests() { earlyFragmentTests = true; } getEarlyFragmentTests()765 bool getEarlyFragmentTests() const { return earlyFragmentTests; } setDepth(TLayoutDepth d)766 bool setDepth(TLayoutDepth d) 767 { 768 if (depthLayout != EldNone) 769 return depthLayout == d; 770 depthLayout = d; 771 return true; 772 } getDepth()773 TLayoutDepth getDepth() const { return depthLayout; } setOriginUpperLeft()774 void setOriginUpperLeft() { originUpperLeft = true; } getOriginUpperLeft()775 bool getOriginUpperLeft() const { return originUpperLeft; } setPixelCenterInteger()776 void setPixelCenterInteger() { pixelCenterInteger = true; } getPixelCenterInteger()777 bool getPixelCenterInteger() const { return pixelCenterInteger; } addBlendEquation(TBlendEquationShift b)778 void addBlendEquation(TBlendEquationShift b) { blendEquations |= (1 << b); } getBlendEquations()779 unsigned int getBlendEquations() const { return blendEquations; } setXfbBufferStride(int buffer,unsigned stride)780 bool setXfbBufferStride(int buffer, unsigned stride) 781 { 782 if (xfbBuffers[buffer].stride != TQualifier::layoutXfbStrideEnd) 783 return xfbBuffers[buffer].stride == stride; 784 xfbBuffers[buffer].stride = stride; 785 return true; 786 } getXfbStride(int buffer)787 unsigned getXfbStride(int buffer) const { return xfbBuffers[buffer].stride; } 788 int addXfbBufferOffset(const TType&); 789 unsigned int computeTypeXfbSize(const TType&, bool& contains64BitType, bool& contains32BitType, bool& contains16BitType) const; 790 unsigned int computeTypeXfbSize(const TType&, bool& contains64BitType) const; setLayoutOverrideCoverage()791 void setLayoutOverrideCoverage() { layoutOverrideCoverage = true; } getLayoutOverrideCoverage()792 bool getLayoutOverrideCoverage() const { return layoutOverrideCoverage; } setGeoPassthroughEXT()793 void setGeoPassthroughEXT() { geoPassthroughEXT = true; } getGeoPassthroughEXT()794 bool getGeoPassthroughEXT() const { return geoPassthroughEXT; } setLayoutDerivativeMode(ComputeDerivativeMode mode)795 void setLayoutDerivativeMode(ComputeDerivativeMode mode) { computeDerivativeMode = mode; } hasLayoutDerivativeModeNone()796 bool hasLayoutDerivativeModeNone() const { return computeDerivativeMode != LayoutDerivativeNone; } getLayoutDerivativeModeNone()797 ComputeDerivativeMode getLayoutDerivativeModeNone() const { return computeDerivativeMode; } setLayoutPrimitiveCulling()798 void setLayoutPrimitiveCulling() { layoutPrimitiveCulling = true; } getLayoutPrimitiveCulling()799 bool getLayoutPrimitiveCulling() const { return layoutPrimitiveCulling; } setPrimitives(int m)800 bool setPrimitives(int m) 801 { 802 if (primitives != TQualifier::layoutNotSet) 803 return primitives == m; 804 primitives = m; 805 return true; 806 } getPrimitives()807 int getPrimitives() const { return primitives; } addSemanticName(const TString & name)808 const char* addSemanticName(const TString& name) 809 { 810 return semanticNameSet.insert(name).first->c_str(); 811 } addUniformLocationOverride(const char * nameStr,int location)812 void addUniformLocationOverride(const char* nameStr, int location) 813 { 814 std::string name = nameStr; 815 uniformLocationOverrides[name] = location; 816 } 817 getUniformLocationOverride(const char * nameStr)818 int getUniformLocationOverride(const char* nameStr) const 819 { 820 std::string name = nameStr; 821 auto pos = uniformLocationOverrides.find(name); 822 if (pos == uniformLocationOverrides.end()) 823 return -1; 824 else 825 return pos->second; 826 } 827 setUniformLocationBase(int base)828 void setUniformLocationBase(int base) { uniformLocationBase = base; } getUniformLocationBase()829 int getUniformLocationBase() const { return uniformLocationBase; } 830 setNeedsLegalization()831 void setNeedsLegalization() { needToLegalize = true; } needsLegalization()832 bool needsLegalization() const { return needToLegalize; } 833 setBinaryDoubleOutput()834 void setBinaryDoubleOutput() { binaryDoubleOutput = true; } getBinaryDoubleOutput()835 bool getBinaryDoubleOutput() { return binaryDoubleOutput; } 836 #endif // GLSLANG_WEB 837 838 #ifdef ENABLE_HLSL setHlslFunctionality1()839 void setHlslFunctionality1() { hlslFunctionality1 = true; } getHlslFunctionality1()840 bool getHlslFunctionality1() const { return hlslFunctionality1; } setHlslOffsets()841 void setHlslOffsets() 842 { 843 hlslOffsets = true; 844 if (hlslOffsets) 845 processes.addProcess("hlsl-offsets"); 846 } usingHlslOffsets()847 bool usingHlslOffsets() const { return hlslOffsets; } setHlslIoMapping(bool b)848 void setHlslIoMapping(bool b) 849 { 850 hlslIoMapping = b; 851 if (hlslIoMapping) 852 processes.addProcess("hlsl-iomap"); 853 } usingHlslIoMapping()854 bool usingHlslIoMapping() { return hlslIoMapping; } 855 #else getHlslFunctionality1()856 bool getHlslFunctionality1() const { return false; } usingHlslOffsets()857 bool usingHlslOffsets() const { return false; } usingHlslIoMapping()858 bool usingHlslIoMapping() { return false; } 859 #endif 860 usingScalarBlockLayout()861 bool usingScalarBlockLayout() const { 862 for (auto extIt = requestedExtensions.begin(); extIt != requestedExtensions.end(); ++extIt) { 863 if (*extIt == E_GL_EXT_scalar_block_layout) 864 return true; 865 } 866 return false; 867 }; 868 869 void addToCallGraph(TInfoSink&, const TString& caller, const TString& callee); 870 void merge(TInfoSink&, TIntermediate&); 871 void finalCheck(TInfoSink&, bool keepUncalled); 872 873 bool buildConvertOp(TBasicType dst, TBasicType src, TOperator& convertOp) const; 874 TIntermTyped* createConversion(TBasicType convertTo, TIntermTyped* node) const; 875 addIoAccessed(const TString & name)876 void addIoAccessed(const TString& name) { ioAccessed.insert(name); } inIoAccessed(const TString & name)877 bool inIoAccessed(const TString& name) const { return ioAccessed.find(name) != ioAccessed.end(); } 878 879 int addUsedLocation(const TQualifier&, const TType&, bool& typeCollision); 880 int checkLocationRange(int set, const TIoRange& range, const TType&, bool& typeCollision); 881 int checkLocationRT(int set, int location); 882 int addUsedOffsets(int binding, int offset, int numOffsets); 883 bool addUsedConstantId(int id); 884 static int computeTypeLocationSize(const TType&, EShLanguage); 885 static int computeTypeUniformLocationSize(const TType&); 886 887 static int getBaseAlignmentScalar(const TType&, int& size); 888 static int getBaseAlignment(const TType&, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor); 889 static int getScalarAlignment(const TType&, int& size, int& stride, bool rowMajor); 890 static int getMemberAlignment(const TType&, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor); 891 static bool improperStraddle(const TType& type, int size, int offset); 892 static void updateOffset(const TType& parentType, const TType& memberType, int& offset, int& memberSize); 893 static int getOffset(const TType& type, int index); 894 static int getBlockSize(const TType& blockType); 895 static int computeBufferReferenceTypeSize(const TType&); 896 bool promote(TIntermOperator*); setNanMinMaxClamp(bool setting)897 void setNanMinMaxClamp(bool setting) { nanMinMaxClamp = setting; } getNanMinMaxClamp()898 bool getNanMinMaxClamp() const { return nanMinMaxClamp; } 899 setSourceFile(const char * file)900 void setSourceFile(const char* file) { if (file != nullptr) sourceFile = file; } getSourceFile()901 const std::string& getSourceFile() const { return sourceFile; } addSourceText(const char * text,size_t len)902 void addSourceText(const char* text, size_t len) { sourceText.append(text, len); } getSourceText()903 const std::string& getSourceText() const { return sourceText; } getIncludeText()904 const std::map<std::string, std::string>& getIncludeText() const { return includeText; } addIncludeText(const char * name,const char * text,size_t len)905 void addIncludeText(const char* name, const char* text, size_t len) { includeText[name].assign(text,len); } addProcesses(const std::vector<std::string> & p)906 void addProcesses(const std::vector<std::string>& p) 907 { 908 for (int i = 0; i < (int)p.size(); ++i) 909 processes.addProcess(p[i]); 910 } addProcess(const std::string & process)911 void addProcess(const std::string& process) { processes.addProcess(process); } addProcessArgument(const std::string & arg)912 void addProcessArgument(const std::string& arg) { processes.addArgument(arg); } getProcesses()913 const std::vector<std::string>& getProcesses() const { return processes.getProcesses(); } 914 915 // Certain explicit conversions are allowed conditionally 916 #ifdef GLSLANG_WEB getArithemeticInt8Enabled()917 bool getArithemeticInt8Enabled() const { return false; } getArithemeticInt16Enabled()918 bool getArithemeticInt16Enabled() const { return false; } getArithemeticFloat16Enabled()919 bool getArithemeticFloat16Enabled() const { return false; } updateNumericFeature(TNumericFeatures::feature f,bool on)920 void updateNumericFeature(TNumericFeatures::feature f, bool on) { } 921 #else getArithemeticInt8Enabled()922 bool getArithemeticInt8Enabled() const { 923 return numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) || 924 numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int8); 925 } getArithemeticInt16Enabled()926 bool getArithemeticInt16Enabled() const { 927 return numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) || 928 numericFeatures.contains(TNumericFeatures::gpu_shader_int16) || 929 numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int16); 930 } 931 getArithemeticFloat16Enabled()932 bool getArithemeticFloat16Enabled() const { 933 return numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) || 934 numericFeatures.contains(TNumericFeatures::gpu_shader_half_float) || 935 numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_float16); 936 } updateNumericFeature(TNumericFeatures::feature f,bool on)937 void updateNumericFeature(TNumericFeatures::feature f, bool on) 938 { on ? numericFeatures.insert(f) : numericFeatures.erase(f); } 939 #endif 940 941 protected: 942 TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&); 943 void error(TInfoSink& infoSink, const char*); 944 void warn(TInfoSink& infoSink, const char*); 945 void mergeCallGraphs(TInfoSink&, TIntermediate&); 946 void mergeModes(TInfoSink&, TIntermediate&); 947 void mergeTrees(TInfoSink&, TIntermediate&); 948 void seedIdMap(TIdMaps& idMaps, int& maxId); 949 void remapIds(const TIdMaps& idMaps, int idShift, TIntermediate&); 950 void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals); 951 void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects); 952 void mergeImplicitArraySizes(TType&, const TType&); 953 void mergeErrorCheck(TInfoSink&, const TIntermSymbol&, const TIntermSymbol&, bool crossStage); 954 void checkCallGraphCycles(TInfoSink&); 955 void checkCallGraphBodies(TInfoSink&, bool keepUncalled); 956 void inOutLocationCheck(TInfoSink&); 957 void sharedBlockCheck(TInfoSink&); 958 bool userOutputUsed() const; 959 bool isSpecializationOperation(const TIntermOperator&) const; 960 bool isNonuniformPropagating(TOperator) const; 961 bool promoteUnary(TIntermUnary&); 962 bool promoteBinary(TIntermBinary&); 963 void addSymbolLinkageNode(TIntermAggregate*& linkage, TSymbolTable&, const TString&); 964 bool promoteAggregate(TIntermAggregate&); 965 void pushSelector(TIntermSequence&, const TVectorSelector&, const TSourceLoc&); 966 void pushSelector(TIntermSequence&, const TMatrixSelector&, const TSourceLoc&); 967 bool specConstantPropagates(const TIntermTyped&, const TIntermTyped&); 968 void performTextureUpgradeAndSamplerRemovalTransformation(TIntermNode* root); 969 bool isConversionAllowed(TOperator op, TIntermTyped* node) const; 970 std::tuple<TBasicType, TBasicType> getConversionDestinationType(TBasicType type0, TBasicType type1, TOperator op) const; 971 972 static const char* getResourceName(TResourceType); 973 974 const EShLanguage language; // stage, known at construction time 975 std::string entryPointName; 976 std::string entryPointMangledName; 977 typedef std::list<TCall> TGraph; 978 TGraph callGraph; 979 980 #ifdef GLSLANG_ANGLE 981 const EProfile profile = ECoreProfile; 982 const int version = 450; 983 #else 984 EProfile profile; // source profile 985 int version; // source version 986 #endif 987 SpvVersion spvVersion; 988 TIntermNode* treeRoot; 989 std::set<std::string> requestedExtensions; // cumulation of all enabled or required extensions; not connected to what subset of the shader used them 990 MustBeAssigned<TBuiltInResource> resources; 991 int numEntryPoints; 992 int numErrors; 993 int numPushConstants; 994 bool recursive; 995 bool invertY; 996 bool useStorageBuffer; 997 bool nanMinMaxClamp; // true if desiring min/max/clamp to favor non-NaN over NaN 998 bool depthReplacing; 999 int localSize[3]; 1000 bool localSizeNotDefault[3]; 1001 int localSizeSpecId[3]; 1002 #ifndef GLSLANG_WEB 1003 public: 1004 const char* const implicitThisName; 1005 const char* const implicitCounterName; 1006 protected: 1007 EShSource source; // source language, known a bit later 1008 bool useVulkanMemoryModel; 1009 int invocations; 1010 int vertices; 1011 TLayoutGeometry inputPrimitive; 1012 TLayoutGeometry outputPrimitive; 1013 bool pixelCenterInteger; 1014 bool originUpperLeft; 1015 TVertexSpacing vertexSpacing; 1016 TVertexOrder vertexOrder; 1017 TInterlockOrdering interlockOrdering; 1018 bool pointMode; 1019 bool earlyFragmentTests; 1020 bool postDepthCoverage; 1021 TLayoutDepth depthLayout; 1022 bool hlslFunctionality1; 1023 int blendEquations; // an 'or'ing of masks of shifts of TBlendEquationShift 1024 bool xfbMode; 1025 std::vector<TXfbBuffer> xfbBuffers; // all the data we need to track per xfb buffer 1026 bool multiStream; 1027 bool layoutOverrideCoverage; 1028 bool geoPassthroughEXT; 1029 int numShaderRecordBlocks; 1030 ComputeDerivativeMode computeDerivativeMode; 1031 int primitives; 1032 int numTaskNVBlocks; 1033 bool layoutPrimitiveCulling; 1034 1035 // Base shift values 1036 std::array<unsigned int, EResCount> shiftBinding; 1037 1038 // Per-descriptor-set shift values 1039 std::array<std::map<int, int>, EResCount> shiftBindingForSet; 1040 1041 std::vector<std::string> resourceSetBinding; 1042 bool autoMapBindings; 1043 bool autoMapLocations; 1044 bool flattenUniformArrays; 1045 bool useUnknownFormat; 1046 bool hlslOffsets; 1047 bool hlslIoMapping; 1048 bool useVariablePointers; 1049 1050 std::set<TString> semanticNameSet; 1051 1052 EShTextureSamplerTransformMode textureSamplerTransformMode; 1053 1054 bool needToLegalize; 1055 bool binaryDoubleOutput; 1056 bool usePhysicalStorageBuffer; 1057 1058 std::unordered_map<std::string, int> uniformLocationOverrides; 1059 int uniformLocationBase; 1060 TNumericFeatures numericFeatures; 1061 #endif 1062 1063 std::unordered_set<int> usedConstantId; // specialization constant ids used 1064 std::vector<TOffsetRange> usedAtomics; // sets of bindings used by atomic counters 1065 std::vector<TIoRange> usedIo[4]; // sets of used locations, one for each of in, out, uniform, and buffers 1066 std::vector<TRange> usedIoRT[2]; // sets of used location, one for rayPayload/rayPayloadIN and other 1067 // for callableData/callableDataIn 1068 // set of names of statically read/written I/O that might need extra checking 1069 std::set<TString> ioAccessed; 1070 // source code of shader, useful as part of debug information 1071 std::string sourceFile; 1072 std::string sourceText; 1073 1074 // Included text. First string is a name, second is the included text 1075 std::map<std::string, std::string> includeText; 1076 1077 // for OpModuleProcessed, or equivalent 1078 TProcesses processes; 1079 1080 private: 1081 void operator=(TIntermediate&); // prevent assignments 1082 }; 1083 1084 } // end namespace glslang 1085 1086 #endif // _LOCAL_INTERMEDIATE_INCLUDED_ 1087