1 // 2 // Copyright (C) 2002-2005 3Dlabs Inc. Ltd. 3 // Copyright (C) 2016 LunarG, Inc. 4 // Copyright (C) 2017 ARM Limited. 5 // Copyright (C) 2015-2018 Google, Inc. 6 // 7 // All rights reserved. 8 // 9 // Redistribution and use in source and binary forms, with or without 10 // modification, are permitted provided that the following conditions 11 // are met: 12 // 13 // Redistributions of source code must retain the above copyright 14 // notice, this list of conditions and the following disclaimer. 15 // 16 // Redistributions in binary form must reproduce the above 17 // copyright notice, this list of conditions and the following 18 // disclaimer in the documentation and/or other materials provided 19 // with the distribution. 20 // 21 // Neither the name of 3Dlabs Inc. Ltd. nor the names of its 22 // contributors may be used to endorse or promote products derived 23 // from this software without specific prior written permission. 24 // 25 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 28 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 29 // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 30 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 31 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 32 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 33 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 35 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 // POSSIBILITY OF SUCH DAMAGE. 37 // 38 39 #ifndef _LOCAL_INTERMEDIATE_INCLUDED_ 40 #define _LOCAL_INTERMEDIATE_INCLUDED_ 41 42 #include "../Include/intermediate.h" 43 #include "../Public/ShaderLang.h" 44 #include "Versions.h" 45 46 #include <string> 47 #include <vector> 48 #include <algorithm> 49 #include <set> 50 #include <array> 51 52 class TInfoSink; 53 54 namespace glslang { 55 56 struct TMatrixSelector { 57 int coord1; // stay agnostic about column/row; this is parse order 58 int coord2; 59 }; 60 61 typedef int TVectorSelector; 62 63 const int MaxSwizzleSelectors = 4; 64 65 template<typename selectorType> 66 class TSwizzleSelectors { 67 public: TSwizzleSelectors()68 TSwizzleSelectors() : size_(0) { } 69 push_back(selectorType comp)70 void push_back(selectorType comp) 71 { 72 if (size_ < MaxSwizzleSelectors) 73 components[size_++] = comp; 74 } resize(int s)75 void resize(int s) 76 { 77 assert(s <= size_); 78 size_ = s; 79 } size()80 int size() const { return size_; } 81 selectorType operator[](int i) const 82 { 83 assert(i < MaxSwizzleSelectors); 84 return components[i]; 85 } 86 87 private: 88 int size_; 89 selectorType components[MaxSwizzleSelectors]; 90 }; 91 92 // 93 // Some helper structures for TIntermediate. Their contents are encapsulated 94 // by TIntermediate. 95 // 96 97 // Used for call-graph algorithms for detecting recursion, missing bodies, and dead bodies. 98 // A "call" is a pair: <caller, callee>. 99 // There can be duplicates. General assumption is the list is small. 100 struct TCall { TCallTCall101 TCall(const TString& pCaller, const TString& pCallee) : caller(pCaller), callee(pCallee) { } 102 TString caller; 103 TString callee; 104 bool visited; 105 bool currentPath; 106 bool errorGiven; 107 int calleeBodyPosition; 108 }; 109 110 // A generic 1-D range. 111 struct TRange { TRangeTRange112 TRange(int start, int last) : start(start), last(last) { } overlapTRange113 bool overlap(const TRange& rhs) const 114 { 115 return last >= rhs.start && start <= rhs.last; 116 } 117 int start; 118 int last; 119 }; 120 121 // An IO range is a 3-D rectangle; the set of (location, component, index) triples all lying 122 // within the same location range, component range, and index value. Locations don't alias unless 123 // all other dimensions of their range overlap. 124 struct TIoRange { TIoRangeTIoRange125 TIoRange(TRange location, TRange component, TBasicType basicType, int index) 126 : location(location), component(component), basicType(basicType), index(index) { } overlapTIoRange127 bool overlap(const TIoRange& rhs) const 128 { 129 return location.overlap(rhs.location) && component.overlap(rhs.component) && index == rhs.index; 130 } 131 TRange location; 132 TRange component; 133 TBasicType basicType; 134 int index; 135 }; 136 137 // An offset range is a 2-D rectangle; the set of (binding, offset) pairs all lying 138 // within the same binding and offset range. 139 struct TOffsetRange { TOffsetRangeTOffsetRange140 TOffsetRange(TRange binding, TRange offset) 141 : binding(binding), offset(offset) { } overlapTOffsetRange142 bool overlap(const TOffsetRange& rhs) const 143 { 144 return binding.overlap(rhs.binding) && offset.overlap(rhs.offset); 145 } 146 TRange binding; 147 TRange offset; 148 }; 149 150 #ifndef GLSLANG_WEB 151 // Things that need to be tracked per xfb buffer. 152 struct TXfbBuffer { TXfbBufferTXfbBuffer153 TXfbBuffer() : stride(TQualifier::layoutXfbStrideEnd), implicitStride(0), contains64BitType(false), 154 contains32BitType(false), contains16BitType(false) { } 155 std::vector<TRange> ranges; // byte offsets that have already been assigned 156 unsigned int stride; 157 unsigned int implicitStride; 158 bool contains64BitType; 159 bool contains32BitType; 160 bool contains16BitType; 161 }; 162 #endif 163 164 // Track a set of strings describing how the module was processed. 165 // This includes command line options, transforms, etc., ideally inclusive enough 166 // to reproduce the steps used to transform the input source to the output. 167 // E.g., see SPIR-V OpModuleProcessed. 168 // Each "process" or "transform" uses is expressed in the form: 169 // process arg0 arg1 arg2 ... 170 // process arg0 arg1 arg2 ... 171 // where everything is textual, and there can be zero or more arguments 172 class TProcesses { 173 public: TProcesses()174 TProcesses() {} ~TProcesses()175 ~TProcesses() {} 176 addProcess(const char * process)177 void addProcess(const char* process) 178 { 179 processes.push_back(process); 180 } addProcess(const std::string & process)181 void addProcess(const std::string& process) 182 { 183 processes.push_back(process); 184 } addArgument(int arg)185 void addArgument(int arg) 186 { 187 processes.back().append(" "); 188 std::string argString = std::to_string(arg); 189 processes.back().append(argString); 190 } addArgument(const char * arg)191 void addArgument(const char* arg) 192 { 193 processes.back().append(" "); 194 processes.back().append(arg); 195 } addArgument(const std::string & arg)196 void addArgument(const std::string& arg) 197 { 198 processes.back().append(" "); 199 processes.back().append(arg); 200 } addIfNonZero(const char * process,int value)201 void addIfNonZero(const char* process, int value) 202 { 203 if (value != 0) { 204 addProcess(process); 205 addArgument(value); 206 } 207 } 208 getProcesses()209 const std::vector<std::string>& getProcesses() const { return processes; } 210 211 private: 212 std::vector<std::string> processes; 213 }; 214 215 class TSymbolTable; 216 class TSymbol; 217 class TVariable; 218 219 // 220 // Texture and Sampler transformation mode. 221 // 222 enum ComputeDerivativeMode { 223 LayoutDerivativeNone, // default layout as SPV_NV_compute_shader_derivatives not enabled 224 LayoutDerivativeGroupQuads, // derivative_group_quadsNV 225 LayoutDerivativeGroupLinear, // derivative_group_linearNV 226 }; 227 228 class TIdMaps { 229 public: 230 TMap<TString, int>& operator[](int i) { return maps[i]; } 231 const TMap<TString, int>& operator[](int i) const { return maps[i]; } 232 private: 233 TMap<TString, int> maps[EsiCount]; 234 }; 235 236 class TNumericFeatures { 237 public: TNumericFeatures()238 TNumericFeatures() : features(0) { } 239 TNumericFeatures(const TNumericFeatures&) = delete; 240 TNumericFeatures& operator=(const TNumericFeatures&) = delete; 241 typedef enum : unsigned int { 242 shader_explicit_arithmetic_types = 1 << 0, 243 shader_explicit_arithmetic_types_int8 = 1 << 1, 244 shader_explicit_arithmetic_types_int16 = 1 << 2, 245 shader_explicit_arithmetic_types_int32 = 1 << 3, 246 shader_explicit_arithmetic_types_int64 = 1 << 4, 247 shader_explicit_arithmetic_types_float16 = 1 << 5, 248 shader_explicit_arithmetic_types_float32 = 1 << 6, 249 shader_explicit_arithmetic_types_float64 = 1 << 7, 250 shader_implicit_conversions = 1 << 8, 251 gpu_shader_fp64 = 1 << 9, 252 gpu_shader_int16 = 1 << 10, 253 gpu_shader_half_float = 1 << 11, 254 } feature; insert(feature f)255 void insert(feature f) { features |= f; } erase(feature f)256 void erase(feature f) { features &= ~f; } contains(feature f)257 bool contains(feature f) const { return (features & f) != 0; } 258 private: 259 unsigned int features; 260 }; 261 262 // MustBeAssigned wraps a T, asserting that it has been assigned with 263 // operator =() before attempting to read with operator T() or operator ->(). 264 // Used to catch cases where fields are read before they have been assigned. 265 template<typename T> 266 class MustBeAssigned 267 { 268 public: 269 MustBeAssigned() = default; MustBeAssigned(const T & v)270 MustBeAssigned(const T& v) : value(v) {} 271 operator const T&() const { assert(isSet); return value; } 272 const T* operator ->() const { assert(isSet); return &value; } 273 MustBeAssigned& operator = (const T& v) { value = v; isSet = true; return *this; } 274 private: 275 T value; 276 bool isSet = false; 277 }; 278 279 // 280 // Set of helper functions to help parse and build the tree. 281 // 282 class TIntermediate { 283 public: 284 explicit TIntermediate(EShLanguage l, int v = 0, EProfile p = ENoProfile) : language(l)285 language(l), 286 #ifndef GLSLANG_ANGLE 287 profile(p), version(v), 288 #endif 289 treeRoot(0), 290 resources(TBuiltInResource{}), 291 numEntryPoints(0), numErrors(0), numPushConstants(0), recursive(false), 292 invertY(false), 293 useStorageBuffer(false), 294 nanMinMaxClamp(false), 295 depthReplacing(false) 296 #ifndef GLSLANG_WEB 297 , 298 implicitThisName("@this"), implicitCounterName("@count"), 299 source(EShSourceNone), 300 useVulkanMemoryModel(false), 301 invocations(TQualifier::layoutNotSet), vertices(TQualifier::layoutNotSet), 302 inputPrimitive(ElgNone), outputPrimitive(ElgNone), 303 pixelCenterInteger(false), originUpperLeft(false), 304 vertexSpacing(EvsNone), vertexOrder(EvoNone), interlockOrdering(EioNone), pointMode(false), earlyFragmentTests(false), 305 postDepthCoverage(false), depthLayout(EldNone), 306 hlslFunctionality1(false), 307 blendEquations(0), xfbMode(false), multiStream(false), 308 layoutOverrideCoverage(false), 309 geoPassthroughEXT(false), 310 numShaderRecordBlocks(0), 311 computeDerivativeMode(LayoutDerivativeNone), 312 primitives(TQualifier::layoutNotSet), 313 numTaskNVBlocks(0), 314 layoutPrimitiveCulling(false), 315 autoMapBindings(false), 316 autoMapLocations(false), 317 flattenUniformArrays(false), 318 useUnknownFormat(false), 319 hlslOffsets(false), 320 hlslIoMapping(false), 321 useVariablePointers(false), 322 textureSamplerTransformMode(EShTexSampTransKeep), 323 needToLegalize(false), 324 binaryDoubleOutput(false), 325 usePhysicalStorageBuffer(false), 326 uniformLocationBase(0) 327 #endif 328 { 329 localSize[0] = 1; 330 localSize[1] = 1; 331 localSize[2] = 1; 332 localSizeNotDefault[0] = false; 333 localSizeNotDefault[1] = false; 334 localSizeNotDefault[2] = false; 335 localSizeSpecId[0] = TQualifier::layoutNotSet; 336 localSizeSpecId[1] = TQualifier::layoutNotSet; 337 localSizeSpecId[2] = TQualifier::layoutNotSet; 338 #ifndef GLSLANG_WEB 339 xfbBuffers.resize(TQualifier::layoutXfbBufferEnd); 340 shiftBinding.fill(0); 341 #endif 342 } 343 setVersion(int v)344 void setVersion(int v) 345 { 346 #ifndef GLSLANG_ANGLE 347 version = v; 348 #endif 349 } setProfile(EProfile p)350 void setProfile(EProfile p) 351 { 352 #ifndef GLSLANG_ANGLE 353 profile = p; 354 #endif 355 } 356 getVersion()357 int getVersion() const { return version; } getProfile()358 EProfile getProfile() const { return profile; } setSpv(const SpvVersion & s)359 void setSpv(const SpvVersion& s) 360 { 361 spvVersion = s; 362 363 // client processes 364 if (spvVersion.vulkan > 0) 365 processes.addProcess("client vulkan100"); 366 if (spvVersion.openGl > 0) 367 processes.addProcess("client opengl100"); 368 369 // target SPV 370 switch (spvVersion.spv) { 371 case 0: 372 break; 373 case EShTargetSpv_1_0: 374 break; 375 case EShTargetSpv_1_1: 376 processes.addProcess("target-env spirv1.1"); 377 break; 378 case EShTargetSpv_1_2: 379 processes.addProcess("target-env spirv1.2"); 380 break; 381 case EShTargetSpv_1_3: 382 processes.addProcess("target-env spirv1.3"); 383 break; 384 case EShTargetSpv_1_4: 385 processes.addProcess("target-env spirv1.4"); 386 break; 387 case EShTargetSpv_1_5: 388 processes.addProcess("target-env spirv1.5"); 389 break; 390 default: 391 processes.addProcess("target-env spirvUnknown"); 392 break; 393 } 394 395 // target-environment processes 396 switch (spvVersion.vulkan) { 397 case 0: 398 break; 399 case EShTargetVulkan_1_0: 400 processes.addProcess("target-env vulkan1.0"); 401 break; 402 case EShTargetVulkan_1_1: 403 processes.addProcess("target-env vulkan1.1"); 404 break; 405 case EShTargetVulkan_1_2: 406 processes.addProcess("target-env vulkan1.2"); 407 break; 408 default: 409 processes.addProcess("target-env vulkanUnknown"); 410 break; 411 } 412 if (spvVersion.openGl > 0) 413 processes.addProcess("target-env opengl"); 414 } getSpv()415 const SpvVersion& getSpv() const { return spvVersion; } getStage()416 EShLanguage getStage() const { return language; } addRequestedExtension(const char * extension)417 void addRequestedExtension(const char* extension) { requestedExtensions.insert(extension); } getRequestedExtensions()418 const std::set<std::string>& getRequestedExtensions() const { return requestedExtensions; } 419 setTreeRoot(TIntermNode * r)420 void setTreeRoot(TIntermNode* r) { treeRoot = r; } getTreeRoot()421 TIntermNode* getTreeRoot() const { return treeRoot; } incrementEntryPointCount()422 void incrementEntryPointCount() { ++numEntryPoints; } getNumEntryPoints()423 int getNumEntryPoints() const { return numEntryPoints; } getNumErrors()424 int getNumErrors() const { return numErrors; } addPushConstantCount()425 void addPushConstantCount() { ++numPushConstants; } setLimits(const TBuiltInResource & r)426 void setLimits(const TBuiltInResource& r) { resources = r; } getLimits()427 const TBuiltInResource& getLimits() const { return resources; } 428 429 bool postProcess(TIntermNode*, EShLanguage); 430 void removeTree(); 431 setEntryPointName(const char * ep)432 void setEntryPointName(const char* ep) 433 { 434 entryPointName = ep; 435 processes.addProcess("entry-point"); 436 processes.addArgument(entryPointName); 437 } setEntryPointMangledName(const char * ep)438 void setEntryPointMangledName(const char* ep) { entryPointMangledName = ep; } getEntryPointName()439 const std::string& getEntryPointName() const { return entryPointName; } getEntryPointMangledName()440 const std::string& getEntryPointMangledName() const { return entryPointMangledName; } 441 setInvertY(bool invert)442 void setInvertY(bool invert) 443 { 444 invertY = invert; 445 if (invertY) 446 processes.addProcess("invert-y"); 447 } getInvertY()448 bool getInvertY() const { return invertY; } 449 450 #ifdef ENABLE_HLSL setSource(EShSource s)451 void setSource(EShSource s) { source = s; } getSource()452 EShSource getSource() const { return source; } 453 #else setSource(EShSource s)454 void setSource(EShSource s) { assert(s == EShSourceGlsl); (void)s; } getSource()455 EShSource getSource() const { return EShSourceGlsl; } 456 #endif 457 isRecursive()458 bool isRecursive() const { return recursive; } 459 460 TIntermSymbol* addSymbol(const TVariable&); 461 TIntermSymbol* addSymbol(const TVariable&, const TSourceLoc&); 462 TIntermSymbol* addSymbol(const TType&, const TSourceLoc&); 463 TIntermSymbol* addSymbol(const TIntermSymbol&); 464 TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*); 465 std::tuple<TIntermTyped*, TIntermTyped*> addPairConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1); 466 TIntermTyped* addUniShapeConversion(TOperator, const TType&, TIntermTyped*); 467 TIntermTyped* addConversion(TBasicType convertTo, TIntermTyped* node) const; 468 void addBiShapeConversion(TOperator, TIntermTyped*& lhsNode, TIntermTyped*& rhsNode); 469 TIntermTyped* addShapeConversion(const TType&, TIntermTyped*); 470 TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&); 471 TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&); 472 TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc&); 473 TIntermTyped* addUnaryMath(TOperator, TIntermTyped* child, const TSourceLoc&); 474 TIntermTyped* addBuiltInFunctionCall(const TSourceLoc& line, TOperator, bool unary, TIntermNode*, const TType& returnType); 475 bool canImplicitlyPromote(TBasicType from, TBasicType to, TOperator op = EOpNull) const; 476 bool isIntegralPromotion(TBasicType from, TBasicType to) const; 477 bool isFPPromotion(TBasicType from, TBasicType to) const; 478 bool isIntegralConversion(TBasicType from, TBasicType to) const; 479 bool isFPConversion(TBasicType from, TBasicType to) const; 480 bool isFPIntegralConversion(TBasicType from, TBasicType to) const; 481 TOperator mapTypeToConstructorOp(const TType&) const; 482 TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right); 483 TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc&); 484 TIntermAggregate* makeAggregate(TIntermNode* node); 485 TIntermAggregate* makeAggregate(TIntermNode* node, const TSourceLoc&); 486 TIntermAggregate* makeAggregate(const TSourceLoc&); 487 TIntermTyped* setAggregateOperator(TIntermNode*, TOperator, const TType& type, const TSourceLoc&); 488 bool areAllChildConst(TIntermAggregate* aggrNode); 489 TIntermSelection* addSelection(TIntermTyped* cond, TIntermNodePair code, const TSourceLoc&); 490 TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc&); 491 TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc&); 492 TIntermTyped* addMethod(TIntermTyped*, const TType&, const TString*, const TSourceLoc&); 493 TIntermConstantUnion* addConstantUnion(const TConstUnionArray&, const TType&, const TSourceLoc&, bool literal = false) const; 494 TIntermConstantUnion* addConstantUnion(signed char, const TSourceLoc&, bool literal = false) const; 495 TIntermConstantUnion* addConstantUnion(unsigned char, const TSourceLoc&, bool literal = false) const; 496 TIntermConstantUnion* addConstantUnion(signed short, const TSourceLoc&, bool literal = false) const; 497 TIntermConstantUnion* addConstantUnion(unsigned short, const TSourceLoc&, bool literal = false) const; 498 TIntermConstantUnion* addConstantUnion(int, const TSourceLoc&, bool literal = false) const; 499 TIntermConstantUnion* addConstantUnion(unsigned int, const TSourceLoc&, bool literal = false) const; 500 TIntermConstantUnion* addConstantUnion(long long, const TSourceLoc&, bool literal = false) const; 501 TIntermConstantUnion* addConstantUnion(unsigned long long, const TSourceLoc&, bool literal = false) const; 502 TIntermConstantUnion* addConstantUnion(bool, const TSourceLoc&, bool literal = false) const; 503 TIntermConstantUnion* addConstantUnion(double, TBasicType, const TSourceLoc&, bool literal = false) const; 504 TIntermConstantUnion* addConstantUnion(const TString*, const TSourceLoc&, bool literal = false) const; 505 TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) const; 506 bool parseConstTree(TIntermNode*, TConstUnionArray, TOperator, const TType&, bool singleConstantParam = false); 507 TIntermLoop* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&); 508 TIntermAggregate* addForLoop(TIntermNode*, TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, 509 const TSourceLoc&, TIntermLoop*&); 510 TIntermBranch* addBranch(TOperator, const TSourceLoc&); 511 TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&); 512 template<typename selectorType> TIntermTyped* addSwizzle(TSwizzleSelectors<selectorType>&, const TSourceLoc&); 513 514 // Low level functions to add nodes (no conversions or other higher level transformations) 515 // If a type is provided, the node's type will be set to it. 516 TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&) const; 517 TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&, 518 const TType&) const; 519 TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, const TSourceLoc&) const; 520 TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, const TSourceLoc&, const TType&) const; 521 522 // Constant folding (in Constant.cpp) 523 TIntermTyped* fold(TIntermAggregate* aggrNode); 524 TIntermTyped* foldConstructor(TIntermAggregate* aggrNode); 525 TIntermTyped* foldDereference(TIntermTyped* node, int index, const TSourceLoc&); 526 TIntermTyped* foldSwizzle(TIntermTyped* node, TSwizzleSelectors<TVectorSelector>& fields, const TSourceLoc&); 527 528 // Tree ops 529 static const TIntermTyped* findLValueBase(const TIntermTyped*, bool swizzleOkay); 530 531 // Linkage related 532 void addSymbolLinkageNodes(TIntermAggregate*& linkage, EShLanguage, TSymbolTable&); 533 void addSymbolLinkageNode(TIntermAggregate*& linkage, const TSymbol&); 534 setUseStorageBuffer()535 void setUseStorageBuffer() { useStorageBuffer = true; } usingStorageBuffer()536 bool usingStorageBuffer() const { return useStorageBuffer; } setDepthReplacing()537 void setDepthReplacing() { depthReplacing = true; } isDepthReplacing()538 bool isDepthReplacing() const { return depthReplacing; } setLocalSize(int dim,int size)539 bool setLocalSize(int dim, int size) 540 { 541 if (localSizeNotDefault[dim]) 542 return size == localSize[dim]; 543 localSizeNotDefault[dim] = true; 544 localSize[dim] = size; 545 return true; 546 } getLocalSize(int dim)547 unsigned int getLocalSize(int dim) const { return localSize[dim]; } setLocalSizeSpecId(int dim,int id)548 bool setLocalSizeSpecId(int dim, int id) 549 { 550 if (localSizeSpecId[dim] != TQualifier::layoutNotSet) 551 return id == localSizeSpecId[dim]; 552 localSizeSpecId[dim] = id; 553 return true; 554 } getLocalSizeSpecId(int dim)555 int getLocalSizeSpecId(int dim) const { return localSizeSpecId[dim]; } 556 #ifdef GLSLANG_WEB output(TInfoSink &,bool tree)557 void output(TInfoSink&, bool tree) { } 558 isEsProfile()559 bool isEsProfile() const { return false; } getXfbMode()560 bool getXfbMode() const { return false; } isMultiStream()561 bool isMultiStream() const { return false; } getOutputPrimitive()562 TLayoutGeometry getOutputPrimitive() const { return ElgNone; } getPostDepthCoverage()563 bool getPostDepthCoverage() const { return false; } getEarlyFragmentTests()564 bool getEarlyFragmentTests() const { return false; } getDepth()565 TLayoutDepth getDepth() const { return EldNone; } getPixelCenterInteger()566 bool getPixelCenterInteger() const { return false; } setOriginUpperLeft()567 void setOriginUpperLeft() { } getOriginUpperLeft()568 bool getOriginUpperLeft() const { return true; } getInterlockOrdering()569 TInterlockOrdering getInterlockOrdering() const { return EioNone; } 570 getAutoMapBindings()571 bool getAutoMapBindings() const { return false; } getAutoMapLocations()572 bool getAutoMapLocations() const { return false; } getNumPushConstants()573 int getNumPushConstants() const { return 0; } addShaderRecordCount()574 void addShaderRecordCount() { } addTaskNVCount()575 void addTaskNVCount() { } setUseVulkanMemoryModel()576 void setUseVulkanMemoryModel() { } usingVulkanMemoryModel()577 bool usingVulkanMemoryModel() const { return false; } usingPhysicalStorageBuffer()578 bool usingPhysicalStorageBuffer() const { return false; } usingVariablePointers()579 bool usingVariablePointers() const { return false; } getXfbStride(int buffer)580 unsigned getXfbStride(int buffer) const { return 0; } hasLayoutDerivativeModeNone()581 bool hasLayoutDerivativeModeNone() const { return false; } getLayoutDerivativeModeNone()582 ComputeDerivativeMode getLayoutDerivativeModeNone() const { return LayoutDerivativeNone; } 583 #else 584 void output(TInfoSink&, bool tree); 585 isEsProfile()586 bool isEsProfile() const { return profile == EEsProfile; } 587 setShiftBinding(TResourceType res,unsigned int shift)588 void setShiftBinding(TResourceType res, unsigned int shift) 589 { 590 shiftBinding[res] = shift; 591 592 const char* name = getResourceName(res); 593 if (name != nullptr) 594 processes.addIfNonZero(name, shift); 595 } 596 getShiftBinding(TResourceType res)597 unsigned int getShiftBinding(TResourceType res) const { return shiftBinding[res]; } 598 setShiftBindingForSet(TResourceType res,unsigned int shift,unsigned int set)599 void setShiftBindingForSet(TResourceType res, unsigned int shift, unsigned int set) 600 { 601 if (shift == 0) // ignore if there's no shift: it's a no-op. 602 return; 603 604 shiftBindingForSet[res][set] = shift; 605 606 const char* name = getResourceName(res); 607 if (name != nullptr) { 608 processes.addProcess(name); 609 processes.addArgument(shift); 610 processes.addArgument(set); 611 } 612 } 613 getShiftBindingForSet(TResourceType res,unsigned int set)614 int getShiftBindingForSet(TResourceType res, unsigned int set) const 615 { 616 const auto shift = shiftBindingForSet[res].find(set); 617 return shift == shiftBindingForSet[res].end() ? -1 : shift->second; 618 } hasShiftBindingForSet(TResourceType res)619 bool hasShiftBindingForSet(TResourceType res) const { return !shiftBindingForSet[res].empty(); } 620 setResourceSetBinding(const std::vector<std::string> & shift)621 void setResourceSetBinding(const std::vector<std::string>& shift) 622 { 623 resourceSetBinding = shift; 624 if (shift.size() > 0) { 625 processes.addProcess("resource-set-binding"); 626 for (int s = 0; s < (int)shift.size(); ++s) 627 processes.addArgument(shift[s]); 628 } 629 } getResourceSetBinding()630 const std::vector<std::string>& getResourceSetBinding() const { return resourceSetBinding; } setAutoMapBindings(bool map)631 void setAutoMapBindings(bool map) 632 { 633 autoMapBindings = map; 634 if (autoMapBindings) 635 processes.addProcess("auto-map-bindings"); 636 } getAutoMapBindings()637 bool getAutoMapBindings() const { return autoMapBindings; } setAutoMapLocations(bool map)638 void setAutoMapLocations(bool map) 639 { 640 autoMapLocations = map; 641 if (autoMapLocations) 642 processes.addProcess("auto-map-locations"); 643 } getAutoMapLocations()644 bool getAutoMapLocations() const { return autoMapLocations; } 645 646 #ifdef ENABLE_HLSL setFlattenUniformArrays(bool flatten)647 void setFlattenUniformArrays(bool flatten) 648 { 649 flattenUniformArrays = flatten; 650 if (flattenUniformArrays) 651 processes.addProcess("flatten-uniform-arrays"); 652 } getFlattenUniformArrays()653 bool getFlattenUniformArrays() const { return flattenUniformArrays; } 654 #endif setNoStorageFormat(bool b)655 void setNoStorageFormat(bool b) 656 { 657 useUnknownFormat = b; 658 if (useUnknownFormat) 659 processes.addProcess("no-storage-format"); 660 } getNoStorageFormat()661 bool getNoStorageFormat() const { return useUnknownFormat; } setUseVulkanMemoryModel()662 void setUseVulkanMemoryModel() 663 { 664 useVulkanMemoryModel = true; 665 processes.addProcess("use-vulkan-memory-model"); 666 } usingVulkanMemoryModel()667 bool usingVulkanMemoryModel() const { return useVulkanMemoryModel; } setUsePhysicalStorageBuffer()668 void setUsePhysicalStorageBuffer() 669 { 670 usePhysicalStorageBuffer = true; 671 } usingPhysicalStorageBuffer()672 bool usingPhysicalStorageBuffer() const { return usePhysicalStorageBuffer; } setUseVariablePointers()673 void setUseVariablePointers() 674 { 675 useVariablePointers = true; 676 processes.addProcess("use-variable-pointers"); 677 } usingVariablePointers()678 bool usingVariablePointers() const { return useVariablePointers; } 679 680 #ifdef ENABLE_HLSL addCounterBufferName(const T & name)681 template<class T> T addCounterBufferName(const T& name) const { return name + implicitCounterName; } hasCounterBufferName(const TString & name)682 bool hasCounterBufferName(const TString& name) const { 683 size_t len = strlen(implicitCounterName); 684 return name.size() > len && 685 name.compare(name.size() - len, len, implicitCounterName) == 0; 686 } 687 #endif 688 setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode)689 void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { textureSamplerTransformMode = mode; } getNumPushConstants()690 int getNumPushConstants() const { return numPushConstants; } addShaderRecordCount()691 void addShaderRecordCount() { ++numShaderRecordBlocks; } addTaskNVCount()692 void addTaskNVCount() { ++numTaskNVBlocks; } 693 setInvocations(int i)694 bool setInvocations(int i) 695 { 696 if (invocations != TQualifier::layoutNotSet) 697 return invocations == i; 698 invocations = i; 699 return true; 700 } getInvocations()701 int getInvocations() const { return invocations; } setVertices(int m)702 bool setVertices(int m) 703 { 704 if (vertices != TQualifier::layoutNotSet) 705 return vertices == m; 706 vertices = m; 707 return true; 708 } getVertices()709 int getVertices() const { return vertices; } setInputPrimitive(TLayoutGeometry p)710 bool setInputPrimitive(TLayoutGeometry p) 711 { 712 if (inputPrimitive != ElgNone) 713 return inputPrimitive == p; 714 inputPrimitive = p; 715 return true; 716 } getInputPrimitive()717 TLayoutGeometry getInputPrimitive() const { return inputPrimitive; } setVertexSpacing(TVertexSpacing s)718 bool setVertexSpacing(TVertexSpacing s) 719 { 720 if (vertexSpacing != EvsNone) 721 return vertexSpacing == s; 722 vertexSpacing = s; 723 return true; 724 } getVertexSpacing()725 TVertexSpacing getVertexSpacing() const { return vertexSpacing; } setVertexOrder(TVertexOrder o)726 bool setVertexOrder(TVertexOrder o) 727 { 728 if (vertexOrder != EvoNone) 729 return vertexOrder == o; 730 vertexOrder = o; 731 return true; 732 } getVertexOrder()733 TVertexOrder getVertexOrder() const { return vertexOrder; } setPointMode()734 void setPointMode() { pointMode = true; } getPointMode()735 bool getPointMode() const { return pointMode; } 736 setInterlockOrdering(TInterlockOrdering o)737 bool setInterlockOrdering(TInterlockOrdering o) 738 { 739 if (interlockOrdering != EioNone) 740 return interlockOrdering == o; 741 interlockOrdering = o; 742 return true; 743 } getInterlockOrdering()744 TInterlockOrdering getInterlockOrdering() const { return interlockOrdering; } 745 setXfbMode()746 void setXfbMode() { xfbMode = true; } getXfbMode()747 bool getXfbMode() const { return xfbMode; } setMultiStream()748 void setMultiStream() { multiStream = true; } isMultiStream()749 bool isMultiStream() const { return multiStream; } setOutputPrimitive(TLayoutGeometry p)750 bool setOutputPrimitive(TLayoutGeometry p) 751 { 752 if (outputPrimitive != ElgNone) 753 return outputPrimitive == p; 754 outputPrimitive = p; 755 return true; 756 } getOutputPrimitive()757 TLayoutGeometry getOutputPrimitive() const { return outputPrimitive; } setPostDepthCoverage()758 void setPostDepthCoverage() { postDepthCoverage = true; } getPostDepthCoverage()759 bool getPostDepthCoverage() const { return postDepthCoverage; } setEarlyFragmentTests()760 void setEarlyFragmentTests() { earlyFragmentTests = true; } getEarlyFragmentTests()761 bool getEarlyFragmentTests() const { return earlyFragmentTests; } setDepth(TLayoutDepth d)762 bool setDepth(TLayoutDepth d) 763 { 764 if (depthLayout != EldNone) 765 return depthLayout == d; 766 depthLayout = d; 767 return true; 768 } getDepth()769 TLayoutDepth getDepth() const { return depthLayout; } setOriginUpperLeft()770 void setOriginUpperLeft() { originUpperLeft = true; } getOriginUpperLeft()771 bool getOriginUpperLeft() const { return originUpperLeft; } setPixelCenterInteger()772 void setPixelCenterInteger() { pixelCenterInteger = true; } getPixelCenterInteger()773 bool getPixelCenterInteger() const { return pixelCenterInteger; } addBlendEquation(TBlendEquationShift b)774 void addBlendEquation(TBlendEquationShift b) { blendEquations |= (1 << b); } getBlendEquations()775 unsigned int getBlendEquations() const { return blendEquations; } setXfbBufferStride(int buffer,unsigned stride)776 bool setXfbBufferStride(int buffer, unsigned stride) 777 { 778 if (xfbBuffers[buffer].stride != TQualifier::layoutXfbStrideEnd) 779 return xfbBuffers[buffer].stride == stride; 780 xfbBuffers[buffer].stride = stride; 781 return true; 782 } getXfbStride(int buffer)783 unsigned getXfbStride(int buffer) const { return xfbBuffers[buffer].stride; } 784 int addXfbBufferOffset(const TType&); 785 unsigned int computeTypeXfbSize(const TType&, bool& contains64BitType, bool& contains32BitType, bool& contains16BitType) const; 786 unsigned int computeTypeXfbSize(const TType&, bool& contains64BitType) const; setLayoutOverrideCoverage()787 void setLayoutOverrideCoverage() { layoutOverrideCoverage = true; } getLayoutOverrideCoverage()788 bool getLayoutOverrideCoverage() const { return layoutOverrideCoverage; } setGeoPassthroughEXT()789 void setGeoPassthroughEXT() { geoPassthroughEXT = true; } getGeoPassthroughEXT()790 bool getGeoPassthroughEXT() const { return geoPassthroughEXT; } setLayoutDerivativeMode(ComputeDerivativeMode mode)791 void setLayoutDerivativeMode(ComputeDerivativeMode mode) { computeDerivativeMode = mode; } hasLayoutDerivativeModeNone()792 bool hasLayoutDerivativeModeNone() const { return computeDerivativeMode != LayoutDerivativeNone; } getLayoutDerivativeModeNone()793 ComputeDerivativeMode getLayoutDerivativeModeNone() const { return computeDerivativeMode; } setLayoutPrimitiveCulling()794 void setLayoutPrimitiveCulling() { layoutPrimitiveCulling = true; } getLayoutPrimitiveCulling()795 bool getLayoutPrimitiveCulling() const { return layoutPrimitiveCulling; } setPrimitives(int m)796 bool setPrimitives(int m) 797 { 798 if (primitives != TQualifier::layoutNotSet) 799 return primitives == m; 800 primitives = m; 801 return true; 802 } getPrimitives()803 int getPrimitives() const { return primitives; } addSemanticName(const TString & name)804 const char* addSemanticName(const TString& name) 805 { 806 return semanticNameSet.insert(name).first->c_str(); 807 } addUniformLocationOverride(const char * nameStr,int location)808 void addUniformLocationOverride(const char* nameStr, int location) 809 { 810 std::string name = nameStr; 811 uniformLocationOverrides[name] = location; 812 } 813 getUniformLocationOverride(const char * nameStr)814 int getUniformLocationOverride(const char* nameStr) const 815 { 816 std::string name = nameStr; 817 auto pos = uniformLocationOverrides.find(name); 818 if (pos == uniformLocationOverrides.end()) 819 return -1; 820 else 821 return pos->second; 822 } 823 setUniformLocationBase(int base)824 void setUniformLocationBase(int base) { uniformLocationBase = base; } getUniformLocationBase()825 int getUniformLocationBase() const { return uniformLocationBase; } 826 setNeedsLegalization()827 void setNeedsLegalization() { needToLegalize = true; } needsLegalization()828 bool needsLegalization() const { return needToLegalize; } 829 setBinaryDoubleOutput()830 void setBinaryDoubleOutput() { binaryDoubleOutput = true; } getBinaryDoubleOutput()831 bool getBinaryDoubleOutput() { return binaryDoubleOutput; } 832 #endif // GLSLANG_WEB 833 834 #ifdef ENABLE_HLSL setHlslFunctionality1()835 void setHlslFunctionality1() { hlslFunctionality1 = true; } getHlslFunctionality1()836 bool getHlslFunctionality1() const { return hlslFunctionality1; } setHlslOffsets()837 void setHlslOffsets() 838 { 839 hlslOffsets = true; 840 if (hlslOffsets) 841 processes.addProcess("hlsl-offsets"); 842 } usingHlslOffsets()843 bool usingHlslOffsets() const { return hlslOffsets; } setHlslIoMapping(bool b)844 void setHlslIoMapping(bool b) 845 { 846 hlslIoMapping = b; 847 if (hlslIoMapping) 848 processes.addProcess("hlsl-iomap"); 849 } usingHlslIoMapping()850 bool usingHlslIoMapping() { return hlslIoMapping; } 851 #else getHlslFunctionality1()852 bool getHlslFunctionality1() const { return false; } usingHlslOffsets()853 bool usingHlslOffsets() const { return false; } usingHlslIoMapping()854 bool usingHlslIoMapping() { return false; } 855 #endif 856 857 void addToCallGraph(TInfoSink&, const TString& caller, const TString& callee); 858 void merge(TInfoSink&, TIntermediate&); 859 void finalCheck(TInfoSink&, bool keepUncalled); 860 861 bool buildConvertOp(TBasicType dst, TBasicType src, TOperator& convertOp) const; 862 TIntermTyped* createConversion(TBasicType convertTo, TIntermTyped* node) const; 863 addIoAccessed(const TString & name)864 void addIoAccessed(const TString& name) { ioAccessed.insert(name); } inIoAccessed(const TString & name)865 bool inIoAccessed(const TString& name) const { return ioAccessed.find(name) != ioAccessed.end(); } 866 867 int addUsedLocation(const TQualifier&, const TType&, bool& typeCollision); 868 int checkLocationRange(int set, const TIoRange& range, const TType&, bool& typeCollision); 869 int addUsedOffsets(int binding, int offset, int numOffsets); 870 bool addUsedConstantId(int id); 871 static int computeTypeLocationSize(const TType&, EShLanguage); 872 static int computeTypeUniformLocationSize(const TType&); 873 874 static int getBaseAlignmentScalar(const TType&, int& size); 875 static int getBaseAlignment(const TType&, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor); 876 static int getScalarAlignment(const TType&, int& size, int& stride, bool rowMajor); 877 static int getMemberAlignment(const TType&, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor); 878 static bool improperStraddle(const TType& type, int size, int offset); 879 static void updateOffset(const TType& parentType, const TType& memberType, int& offset, int& memberSize); 880 static int getOffset(const TType& type, int index); 881 static int getBlockSize(const TType& blockType); 882 static int computeBufferReferenceTypeSize(const TType&); 883 bool promote(TIntermOperator*); setNanMinMaxClamp(bool setting)884 void setNanMinMaxClamp(bool setting) { nanMinMaxClamp = setting; } getNanMinMaxClamp()885 bool getNanMinMaxClamp() const { return nanMinMaxClamp; } 886 setSourceFile(const char * file)887 void setSourceFile(const char* file) { if (file != nullptr) sourceFile = file; } getSourceFile()888 const std::string& getSourceFile() const { return sourceFile; } addSourceText(const char * text,size_t len)889 void addSourceText(const char* text, size_t len) { sourceText.append(text, len); } getSourceText()890 const std::string& getSourceText() const { return sourceText; } getIncludeText()891 const std::map<std::string, std::string>& getIncludeText() const { return includeText; } addIncludeText(const char * name,const char * text,size_t len)892 void addIncludeText(const char* name, const char* text, size_t len) { includeText[name].assign(text,len); } addProcesses(const std::vector<std::string> & p)893 void addProcesses(const std::vector<std::string>& p) 894 { 895 for (int i = 0; i < (int)p.size(); ++i) 896 processes.addProcess(p[i]); 897 } addProcess(const std::string & process)898 void addProcess(const std::string& process) { processes.addProcess(process); } addProcessArgument(const std::string & arg)899 void addProcessArgument(const std::string& arg) { processes.addArgument(arg); } getProcesses()900 const std::vector<std::string>& getProcesses() const { return processes.getProcesses(); } 901 902 // Certain explicit conversions are allowed conditionally 903 #ifdef GLSLANG_WEB getArithemeticInt8Enabled()904 bool getArithemeticInt8Enabled() const { return false; } getArithemeticInt16Enabled()905 bool getArithemeticInt16Enabled() const { return false; } getArithemeticFloat16Enabled()906 bool getArithemeticFloat16Enabled() const { return false; } updateNumericFeature(TNumericFeatures::feature f,bool on)907 void updateNumericFeature(TNumericFeatures::feature f, bool on) { } 908 #else getArithemeticInt8Enabled()909 bool getArithemeticInt8Enabled() const { 910 return numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) || 911 numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int8); 912 } getArithemeticInt16Enabled()913 bool getArithemeticInt16Enabled() const { 914 return numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) || 915 numericFeatures.contains(TNumericFeatures::gpu_shader_int16) || 916 numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int16); 917 } 918 getArithemeticFloat16Enabled()919 bool getArithemeticFloat16Enabled() const { 920 return numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) || 921 numericFeatures.contains(TNumericFeatures::gpu_shader_half_float) || 922 numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_float16); 923 } updateNumericFeature(TNumericFeatures::feature f,bool on)924 void updateNumericFeature(TNumericFeatures::feature f, bool on) 925 { on ? numericFeatures.insert(f) : numericFeatures.erase(f); } 926 #endif 927 928 protected: 929 TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&); 930 void error(TInfoSink& infoSink, const char*); 931 void warn(TInfoSink& infoSink, const char*); 932 void mergeCallGraphs(TInfoSink&, TIntermediate&); 933 void mergeModes(TInfoSink&, TIntermediate&); 934 void mergeTrees(TInfoSink&, TIntermediate&); 935 void seedIdMap(TIdMaps& idMaps, int& maxId); 936 void remapIds(const TIdMaps& idMaps, int idShift, TIntermediate&); 937 void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals); 938 void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects); 939 void mergeImplicitArraySizes(TType&, const TType&); 940 void mergeErrorCheck(TInfoSink&, const TIntermSymbol&, const TIntermSymbol&, bool crossStage); 941 void checkCallGraphCycles(TInfoSink&); 942 void checkCallGraphBodies(TInfoSink&, bool keepUncalled); 943 void inOutLocationCheck(TInfoSink&); 944 TIntermAggregate* findLinkerObjects() const; 945 bool userOutputUsed() const; 946 bool isSpecializationOperation(const TIntermOperator&) const; 947 bool isNonuniformPropagating(TOperator) const; 948 bool promoteUnary(TIntermUnary&); 949 bool promoteBinary(TIntermBinary&); 950 void addSymbolLinkageNode(TIntermAggregate*& linkage, TSymbolTable&, const TString&); 951 bool promoteAggregate(TIntermAggregate&); 952 void pushSelector(TIntermSequence&, const TVectorSelector&, const TSourceLoc&); 953 void pushSelector(TIntermSequence&, const TMatrixSelector&, const TSourceLoc&); 954 bool specConstantPropagates(const TIntermTyped&, const TIntermTyped&); 955 void performTextureUpgradeAndSamplerRemovalTransformation(TIntermNode* root); 956 bool isConversionAllowed(TOperator op, TIntermTyped* node) const; 957 std::tuple<TBasicType, TBasicType> getConversionDestinationType(TBasicType type0, TBasicType type1, TOperator op) const; 958 959 static const char* getResourceName(TResourceType); 960 961 const EShLanguage language; // stage, known at construction time 962 std::string entryPointName; 963 std::string entryPointMangledName; 964 typedef std::list<TCall> TGraph; 965 TGraph callGraph; 966 967 #ifdef GLSLANG_ANGLE 968 const EProfile profile = ECoreProfile; 969 const int version = 450; 970 #else 971 EProfile profile; // source profile 972 int version; // source version 973 #endif 974 SpvVersion spvVersion; 975 TIntermNode* treeRoot; 976 std::set<std::string> requestedExtensions; // cumulation of all enabled or required extensions; not connected to what subset of the shader used them 977 MustBeAssigned<TBuiltInResource> resources; 978 int numEntryPoints; 979 int numErrors; 980 int numPushConstants; 981 bool recursive; 982 bool invertY; 983 bool useStorageBuffer; 984 bool nanMinMaxClamp; // true if desiring min/max/clamp to favor non-NaN over NaN 985 bool depthReplacing; 986 int localSize[3]; 987 bool localSizeNotDefault[3]; 988 int localSizeSpecId[3]; 989 #ifndef GLSLANG_WEB 990 public: 991 const char* const implicitThisName; 992 const char* const implicitCounterName; 993 protected: 994 EShSource source; // source language, known a bit later 995 bool useVulkanMemoryModel; 996 int invocations; 997 int vertices; 998 TLayoutGeometry inputPrimitive; 999 TLayoutGeometry outputPrimitive; 1000 bool pixelCenterInteger; 1001 bool originUpperLeft; 1002 TVertexSpacing vertexSpacing; 1003 TVertexOrder vertexOrder; 1004 TInterlockOrdering interlockOrdering; 1005 bool pointMode; 1006 bool earlyFragmentTests; 1007 bool postDepthCoverage; 1008 TLayoutDepth depthLayout; 1009 bool hlslFunctionality1; 1010 int blendEquations; // an 'or'ing of masks of shifts of TBlendEquationShift 1011 bool xfbMode; 1012 std::vector<TXfbBuffer> xfbBuffers; // all the data we need to track per xfb buffer 1013 bool multiStream; 1014 bool layoutOverrideCoverage; 1015 bool geoPassthroughEXT; 1016 int numShaderRecordBlocks; 1017 ComputeDerivativeMode computeDerivativeMode; 1018 int primitives; 1019 int numTaskNVBlocks; 1020 bool layoutPrimitiveCulling; 1021 1022 // Base shift values 1023 std::array<unsigned int, EResCount> shiftBinding; 1024 1025 // Per-descriptor-set shift values 1026 std::array<std::map<int, int>, EResCount> shiftBindingForSet; 1027 1028 std::vector<std::string> resourceSetBinding; 1029 bool autoMapBindings; 1030 bool autoMapLocations; 1031 bool flattenUniformArrays; 1032 bool useUnknownFormat; 1033 bool hlslOffsets; 1034 bool hlslIoMapping; 1035 bool useVariablePointers; 1036 1037 std::set<TString> semanticNameSet; 1038 1039 EShTextureSamplerTransformMode textureSamplerTransformMode; 1040 1041 bool needToLegalize; 1042 bool binaryDoubleOutput; 1043 bool usePhysicalStorageBuffer; 1044 1045 std::unordered_map<std::string, int> uniformLocationOverrides; 1046 int uniformLocationBase; 1047 TNumericFeatures numericFeatures; 1048 #endif 1049 1050 std::unordered_set<int> usedConstantId; // specialization constant ids used 1051 std::vector<TOffsetRange> usedAtomics; // sets of bindings used by atomic counters 1052 std::vector<TIoRange> usedIo[4]; // sets of used locations, one for each of in, out, uniform, and buffers 1053 // set of names of statically read/written I/O that might need extra checking 1054 std::set<TString> ioAccessed; 1055 // source code of shader, useful as part of debug information 1056 std::string sourceFile; 1057 std::string sourceText; 1058 1059 // Included text. First string is a name, second is the included text 1060 std::map<std::string, std::string> includeText; 1061 1062 // for OpModuleProcessed, or equivalent 1063 TProcesses processes; 1064 1065 private: 1066 void operator=(TIntermediate&); // prevent assignments 1067 }; 1068 1069 } // end namespace glslang 1070 1071 #endif // _LOCAL_INTERMEDIATE_INCLUDED_ 1072