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