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