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.
7 // All rights reserved.
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions
13 // Redistributions of source code must retain the above copyright
14 // notice, this list of conditions and the following disclaimer.
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.
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.
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.
39 #ifndef _LOCAL_INTERMEDIATE_INCLUDED_
40 #define _LOCAL_INTERMEDIATE_INCLUDED_
42 #include "../Include/intermediate.h"
43 #include "../Public/ShaderLang.h"
56 struct TMatrixSelector {
57 int coord1; // stay agnostic about column/row; this is parse order
61 typedef int TVectorSelector;
63 const int MaxSwizzleSelectors = 4;
65 template<typename selectorType>
66 class TSwizzleSelectors {
68 TSwizzleSelectors() : size_(0) { }
70 void push_back(selectorType comp)
72 if (size_ < MaxSwizzleSelectors)
73 components[size_++] = comp;
80 int size() const { return size_; }
81 selectorType operator[](int i) const
83 assert(i < MaxSwizzleSelectors);
89 selectorType components[MaxSwizzleSelectors];
93 // Some helper structures for TIntermediate. Their contents are encapsulated
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.
101 TCall(const TString& pCaller, const TString& pCallee) : caller(pCaller), callee(pCallee) { }
107 int calleeBodyPosition;
110 // A generic 1-D range.
112 TRange(int start, int last) : start(start), last(last) { }
113 bool overlap(const TRange& rhs) const
115 return last >= rhs.start && start <= rhs.last;
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.
125 TIoRange(TRange location, TRange component, TBasicType basicType, int index)
126 : location(location), component(component), basicType(basicType), index(index) { }
127 bool overlap(const TIoRange& rhs) const
129 return location.overlap(rhs.location) && component.overlap(rhs.component) && index == rhs.index;
133 TBasicType basicType;
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 {
140 TOffsetRange(TRange binding, TRange offset)
141 : binding(binding), offset(offset) { }
142 bool overlap(const TOffsetRange& rhs) const
144 return binding.overlap(rhs.binding) && offset.overlap(rhs.offset);
151 // Things that need to be tracked per xfb buffer.
153 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
157 unsigned int implicitStride;
158 bool contains64BitType;
159 bool contains32BitType;
160 bool contains16BitType;
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
177 void addProcess(const char* process)
179 processes.push_back(process);
181 void addProcess(const std::string& process)
183 processes.push_back(process);
185 void addArgument(int arg)
187 processes.back().append(" ");
188 std::string argString = std::to_string(arg);
189 processes.back().append(argString);
191 void addArgument(const char* arg)
193 processes.back().append(" ");
194 processes.back().append(arg);
196 void addArgument(const std::string& arg)
198 processes.back().append(" ");
199 processes.back().append(arg);
201 void addIfNonZero(const char* process, int value)
209 const std::vector<std::string>& getProcesses() const { return processes; }
212 std::vector<std::string> processes;
220 // Texture and Sampler transformation mode.
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
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]; }
233 TMap<TString, long long> maps[EsiCount];
236 class 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,
255 void insert(feature f) { features |= f; }
256 void erase(feature f) { features &= ~f; }
257 bool contains(feature f) const { return (features & f) != 0; }
259 unsigned int features;
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.
269 MustBeAssigned() = default;
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; }
280 // Set of helper functions to help parse and build the tree.
282 class TIntermediate {
284 explicit TIntermediate(EShLanguage l, int v = 0, EProfile p = ENoProfile) :
286 #ifndef GLSLANG_ANGLE
287 profile(p), version(v),
290 resources(TBuiltInResource{}),
291 numEntryPoints(0), numErrors(0), numPushConstants(0), recursive(false),
296 useStorageBuffer(false),
298 nanMinMaxClamp(false),
299 depthReplacing(false),
300 stencilReplacing(false),
302 globalUniformBlockName(""),
303 atomicCounterBlockName(""),
304 globalUniformBlockSet(TQualifier::layoutSetEnd),
305 globalUniformBlockBinding(TQualifier::layoutBindingEnd),
306 atomicCounterBlockSet(TQualifier::layoutSetEnd)
309 implicitThisName("@this"), implicitCounterName("@count"),
310 source(EShSourceNone),
311 useVulkanMemoryModel(false),
312 invocations(TQualifier::layoutNotSet), vertices(TQualifier::layoutNotSet),
313 inputPrimitive(ElgNone), outputPrimitive(ElgNone),
314 pixelCenterInteger(false), originUpperLeft(false),texCoordBuiltinRedeclared(false),
315 vertexSpacing(EvsNone), vertexOrder(EvoNone), interlockOrdering(EioNone), pointMode(false), earlyFragmentTests(false),
316 postDepthCoverage(false), earlyAndLateFragmentTestsAMD(false), depthLayout(EldNone), stencilLayout(ElsNone),
317 hlslFunctionality1(false),
318 blendEquations(0), xfbMode(false), multiStream(false),
319 layoutOverrideCoverage(false),
320 geoPassthroughEXT(false),
321 numShaderRecordBlocks(0),
322 computeDerivativeMode(LayoutDerivativeNone),
323 primitives(TQualifier::layoutNotSet),
325 layoutPrimitiveCulling(false),
326 numTaskEXTPayloads(0),
327 autoMapBindings(false),
328 autoMapLocations(false),
329 flattenUniformArrays(false),
330 useUnknownFormat(false),
332 hlslIoMapping(false),
333 useVariablePointers(false),
334 textureSamplerTransformMode(EShTexSampTransKeep),
335 needToLegalize(false),
336 binaryDoubleOutput(false),
337 subgroupUniformControlFlow(false),
338 usePhysicalStorageBuffer(false),
339 spirvRequirement(nullptr),
340 spirvExecutionMode(nullptr),
341 uniformLocationBase(0)
347 localSizeNotDefault[0] = false;
348 localSizeNotDefault[1] = false;
349 localSizeNotDefault[2] = false;
350 localSizeSpecId[0] = TQualifier::layoutNotSet;
351 localSizeSpecId[1] = TQualifier::layoutNotSet;
352 localSizeSpecId[2] = TQualifier::layoutNotSet;
354 xfbBuffers.resize(TQualifier::layoutXfbBufferEnd);
355 shiftBinding.fill(0);
359 void setVersion(int v)
361 #ifndef GLSLANG_ANGLE
365 void setProfile(EProfile p)
367 #ifndef GLSLANG_ANGLE
372 int getVersion() const { return version; }
373 EProfile getProfile() const { return profile; }
374 void setSpv(const SpvVersion& s)
379 if (spvVersion.vulkan > 0)
380 processes.addProcess("client vulkan100");
381 if (spvVersion.openGl > 0)
382 processes.addProcess("client opengl100");
385 switch (spvVersion.spv) {
388 case EShTargetSpv_1_0:
390 case EShTargetSpv_1_1:
391 processes.addProcess("target-env spirv1.1");
393 case EShTargetSpv_1_2:
394 processes.addProcess("target-env spirv1.2");
396 case EShTargetSpv_1_3:
397 processes.addProcess("target-env spirv1.3");
399 case EShTargetSpv_1_4:
400 processes.addProcess("target-env spirv1.4");
402 case EShTargetSpv_1_5:
403 processes.addProcess("target-env spirv1.5");
405 case EShTargetSpv_1_6:
406 processes.addProcess("target-env spirv1.6");
409 processes.addProcess("target-env spirvUnknown");
413 // target-environment processes
414 switch (spvVersion.vulkan) {
417 case EShTargetVulkan_1_0:
418 processes.addProcess("target-env vulkan1.0");
420 case EShTargetVulkan_1_1:
421 processes.addProcess("target-env vulkan1.1");
423 case EShTargetVulkan_1_2:
424 processes.addProcess("target-env vulkan1.2");
426 case EShTargetVulkan_1_3:
427 processes.addProcess("target-env vulkan1.3");
430 processes.addProcess("target-env vulkanUnknown");
433 if (spvVersion.openGl > 0)
434 processes.addProcess("target-env opengl");
436 const SpvVersion& getSpv() const { return spvVersion; }
437 EShLanguage getStage() const { return language; }
438 void addRequestedExtension(const char* extension) { requestedExtensions.insert(extension); }
439 const std::set<std::string>& getRequestedExtensions() const { return requestedExtensions; }
440 bool isRayTracingStage() const {
441 return language >= EShLangRayGen && language <= EShLangCallableNV;
444 void setTreeRoot(TIntermNode* r) { treeRoot = r; }
445 TIntermNode* getTreeRoot() const { return treeRoot; }
446 void incrementEntryPointCount() { ++numEntryPoints; }
447 int getNumEntryPoints() const { return numEntryPoints; }
448 int getNumErrors() const { return numErrors; }
449 void addPushConstantCount() { ++numPushConstants; }
450 void setLimits(const TBuiltInResource& r) { resources = r; }
451 const TBuiltInResource& getLimits() const { return resources; }
453 bool postProcess(TIntermNode*, EShLanguage);
456 void setEntryPointName(const char* ep)
459 processes.addProcess("entry-point");
460 processes.addArgument(entryPointName);
462 void setEntryPointMangledName(const char* ep) { entryPointMangledName = ep; }
463 const std::string& getEntryPointName() const { return entryPointName; }
464 const std::string& getEntryPointMangledName() const { return entryPointMangledName; }
466 void setDebugInfo(bool debuginfo)
468 debugInfo = debuginfo;
470 bool getDebugInfo() const { return debugInfo; }
472 void setInvertY(bool invert)
476 processes.addProcess("invert-y");
478 bool getInvertY() const { return invertY; }
480 void setDxPositionW(bool dxPosW)
482 dxPositionW = dxPosW;
484 processes.addProcess("dx-position-w");
486 bool getDxPositionW() const { return dxPositionW; }
488 void setEnhancedMsgs()
492 bool getEnhancedMsgs() const { return enhancedMsgs && getSource() == EShSourceGlsl; }
495 void setSource(EShSource s) { source = s; }
496 EShSource getSource() const { return source; }
498 void setSource(EShSource s) { assert(s == EShSourceGlsl); (void)s; }
499 EShSource getSource() const { return EShSourceGlsl; }
502 bool isRecursive() const { return recursive; }
504 TIntermSymbol* addSymbol(const TVariable&);
505 TIntermSymbol* addSymbol(const TVariable&, const TSourceLoc&);
506 TIntermSymbol* addSymbol(const TType&, const TSourceLoc&);
507 TIntermSymbol* addSymbol(const TIntermSymbol&);
508 TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*);
509 std::tuple<TIntermTyped*, TIntermTyped*> addPairConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1);
510 TIntermTyped* addUniShapeConversion(TOperator, const TType&, TIntermTyped*);
511 TIntermTyped* addConversion(TBasicType convertTo, TIntermTyped* node) const;
512 void addBiShapeConversion(TOperator, TIntermTyped*& lhsNode, TIntermTyped*& rhsNode);
513 TIntermTyped* addShapeConversion(const TType&, TIntermTyped*);
514 TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&);
515 TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&);
516 TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc&);
517 TIntermTyped* addUnaryMath(TOperator, TIntermTyped* child, const TSourceLoc&);
518 TIntermTyped* addBuiltInFunctionCall(const TSourceLoc& line, TOperator, bool unary, TIntermNode*, const TType& returnType);
519 bool canImplicitlyPromote(TBasicType from, TBasicType to, TOperator op = EOpNull) const;
520 bool isIntegralPromotion(TBasicType from, TBasicType to) const;
521 bool isFPPromotion(TBasicType from, TBasicType to) const;
522 bool isIntegralConversion(TBasicType from, TBasicType to) const;
523 bool isFPConversion(TBasicType from, TBasicType to) const;
524 bool isFPIntegralConversion(TBasicType from, TBasicType to) const;
525 TOperator mapTypeToConstructorOp(const TType&) const;
526 TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right);
527 TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc&);
528 TIntermAggregate* makeAggregate(TIntermNode* node);
529 TIntermAggregate* makeAggregate(TIntermNode* node, const TSourceLoc&);
530 TIntermAggregate* makeAggregate(const TSourceLoc&);
531 TIntermTyped* setAggregateOperator(TIntermNode*, TOperator, const TType& type, const TSourceLoc&);
532 bool areAllChildConst(TIntermAggregate* aggrNode);
533 TIntermSelection* addSelection(TIntermTyped* cond, TIntermNodePair code, const TSourceLoc&);
534 TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc&);
535 TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc&);
536 TIntermTyped* addMethod(TIntermTyped*, const TType&, const TString*, const TSourceLoc&);
537 TIntermConstantUnion* addConstantUnion(const TConstUnionArray&, const TType&, const TSourceLoc&, bool literal = false) const;
538 TIntermConstantUnion* addConstantUnion(signed char, const TSourceLoc&, bool literal = false) const;
539 TIntermConstantUnion* addConstantUnion(unsigned char, const TSourceLoc&, bool literal = false) const;
540 TIntermConstantUnion* addConstantUnion(signed short, const TSourceLoc&, bool literal = false) const;
541 TIntermConstantUnion* addConstantUnion(unsigned short, const TSourceLoc&, bool literal = false) const;
542 TIntermConstantUnion* addConstantUnion(int, const TSourceLoc&, bool literal = false) const;
543 TIntermConstantUnion* addConstantUnion(unsigned int, const TSourceLoc&, bool literal = false) const;
544 TIntermConstantUnion* addConstantUnion(long long, const TSourceLoc&, bool literal = false) const;
545 TIntermConstantUnion* addConstantUnion(unsigned long long, const TSourceLoc&, bool literal = false) const;
546 TIntermConstantUnion* addConstantUnion(bool, const TSourceLoc&, bool literal = false) const;
547 TIntermConstantUnion* addConstantUnion(double, TBasicType, const TSourceLoc&, bool literal = false) const;
548 TIntermConstantUnion* addConstantUnion(const TString*, const TSourceLoc&, bool literal = false) const;
549 TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) const;
550 bool parseConstTree(TIntermNode*, TConstUnionArray, TOperator, const TType&, bool singleConstantParam = false);
551 TIntermLoop* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&);
552 TIntermAggregate* addForLoop(TIntermNode*, TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst,
553 const TSourceLoc&, TIntermLoop*&);
554 TIntermBranch* addBranch(TOperator, const TSourceLoc&);
555 TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&);
556 template<typename selectorType> TIntermTyped* addSwizzle(TSwizzleSelectors<selectorType>&, const TSourceLoc&);
558 // Low level functions to add nodes (no conversions or other higher level transformations)
559 // If a type is provided, the node's type will be set to it.
560 TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&) const;
561 TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&,
563 TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, const TSourceLoc&) const;
564 TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, const TSourceLoc&, const TType&) const;
566 // Constant folding (in Constant.cpp)
567 TIntermTyped* fold(TIntermAggregate* aggrNode);
568 TIntermTyped* foldConstructor(TIntermAggregate* aggrNode);
569 TIntermTyped* foldDereference(TIntermTyped* node, int index, const TSourceLoc&);
570 TIntermTyped* foldSwizzle(TIntermTyped* node, TSwizzleSelectors<TVectorSelector>& fields, const TSourceLoc&);
573 static const TIntermTyped* findLValueBase(const TIntermTyped*, bool swizzleOkay , bool BufferReferenceOk = false);
576 void addSymbolLinkageNodes(TIntermAggregate*& linkage, EShLanguage, TSymbolTable&);
577 void addSymbolLinkageNode(TIntermAggregate*& linkage, const TSymbol&);
578 TIntermAggregate* findLinkerObjects() const;
580 void setGlobalUniformBlockName(const char* name) { globalUniformBlockName = std::string(name); }
581 const char* getGlobalUniformBlockName() const { return globalUniformBlockName.c_str(); }
582 void setGlobalUniformSet(unsigned int set) { globalUniformBlockSet = set; }
583 unsigned int getGlobalUniformSet() const { return globalUniformBlockSet; }
584 void setGlobalUniformBinding(unsigned int binding) { globalUniformBlockBinding = binding; }
585 unsigned int getGlobalUniformBinding() const { return globalUniformBlockBinding; }
587 void setAtomicCounterBlockName(const char* name) { atomicCounterBlockName = std::string(name); }
588 const char* getAtomicCounterBlockName() const { return atomicCounterBlockName.c_str(); }
589 void setAtomicCounterBlockSet(unsigned int set) { atomicCounterBlockSet = set; }
590 unsigned int getAtomicCounterBlockSet() const { return atomicCounterBlockSet; }
593 void setUseStorageBuffer() { useStorageBuffer = true; }
594 bool usingStorageBuffer() const { return useStorageBuffer; }
595 void setInvariantAll() { invariantAll = true; }
596 bool isInvariantAll() const { return invariantAll; }
597 void setDepthReplacing() { depthReplacing = true; }
598 bool isDepthReplacing() const { return depthReplacing; }
599 void setStencilReplacing() { stencilReplacing = true; }
600 bool isStencilReplacing() const { return stencilReplacing; }
601 bool setLocalSize(int dim, int size)
603 if (localSizeNotDefault[dim])
604 return size == localSize[dim];
605 localSizeNotDefault[dim] = true;
606 localSize[dim] = size;
609 unsigned int getLocalSize(int dim) const { return localSize[dim]; }
610 bool isLocalSizeSet() const
612 // Return true if any component has been set (i.e. any component is not default).
613 return localSizeNotDefault[0] || localSizeNotDefault[1] || localSizeNotDefault[2];
615 bool setLocalSizeSpecId(int dim, int id)
617 if (localSizeSpecId[dim] != TQualifier::layoutNotSet)
618 return id == localSizeSpecId[dim];
619 localSizeSpecId[dim] = id;
622 int getLocalSizeSpecId(int dim) const { return localSizeSpecId[dim]; }
623 bool isLocalSizeSpecialized() const
625 // Return true if any component has been specialized.
626 return localSizeSpecId[0] != TQualifier::layoutNotSet ||
627 localSizeSpecId[1] != TQualifier::layoutNotSet ||
628 localSizeSpecId[2] != TQualifier::layoutNotSet;
631 void output(TInfoSink&, bool tree) { }
633 bool isEsProfile() const { return false; }
634 bool getXfbMode() const { return false; }
635 bool isMultiStream() const { return false; }
636 TLayoutGeometry getOutputPrimitive() const { return ElgNone; }
637 bool getPostDepthCoverage() const { return false; }
638 bool getEarlyFragmentTests() const { return false; }
639 TLayoutDepth getDepth() const { return EldNone; }
640 bool getPixelCenterInteger() const { return false; }
641 void setOriginUpperLeft() { }
642 bool getOriginUpperLeft() const { return true; }
643 TInterlockOrdering getInterlockOrdering() const { return EioNone; }
645 bool getAutoMapBindings() const { return false; }
646 bool getAutoMapLocations() const { return false; }
647 int getNumPushConstants() const { return 0; }
648 void addShaderRecordCount() { }
649 void addTaskNVCount() { }
650 void addTaskPayloadEXTCount() { }
651 void setUseVulkanMemoryModel() { }
652 bool usingVulkanMemoryModel() const { return false; }
653 bool usingPhysicalStorageBuffer() const { return false; }
654 bool usingVariablePointers() const { return false; }
655 unsigned getXfbStride(int buffer) const { return 0; }
656 bool hasLayoutDerivativeModeNone() const { return false; }
657 ComputeDerivativeMode getLayoutDerivativeModeNone() const { return LayoutDerivativeNone; }
659 void output(TInfoSink&, bool tree);
661 bool isEsProfile() const { return profile == EEsProfile; }
663 void setShiftBinding(TResourceType res, unsigned int shift)
665 shiftBinding[res] = shift;
667 const char* name = getResourceName(res);
669 processes.addIfNonZero(name, shift);
672 unsigned int getShiftBinding(TResourceType res) const { return shiftBinding[res]; }
674 void setShiftBindingForSet(TResourceType res, unsigned int shift, unsigned int set)
676 if (shift == 0) // ignore if there's no shift: it's a no-op.
679 shiftBindingForSet[res][set] = shift;
681 const char* name = getResourceName(res);
682 if (name != nullptr) {
683 processes.addProcess(name);
684 processes.addArgument(shift);
685 processes.addArgument(set);
689 int getShiftBindingForSet(TResourceType res, unsigned int set) const
691 const auto shift = shiftBindingForSet[res].find(set);
692 return shift == shiftBindingForSet[res].end() ? -1 : shift->second;
694 bool hasShiftBindingForSet(TResourceType res) const { return !shiftBindingForSet[res].empty(); }
696 void setResourceSetBinding(const std::vector<std::string>& shift)
698 resourceSetBinding = shift;
699 if (shift.size() > 0) {
700 processes.addProcess("resource-set-binding");
701 for (int s = 0; s < (int)shift.size(); ++s)
702 processes.addArgument(shift[s]);
705 const std::vector<std::string>& getResourceSetBinding() const { return resourceSetBinding; }
706 void setAutoMapBindings(bool map)
708 autoMapBindings = map;
710 processes.addProcess("auto-map-bindings");
712 bool getAutoMapBindings() const { return autoMapBindings; }
713 void setAutoMapLocations(bool map)
715 autoMapLocations = map;
716 if (autoMapLocations)
717 processes.addProcess("auto-map-locations");
719 bool getAutoMapLocations() const { return autoMapLocations; }
722 void setFlattenUniformArrays(bool flatten)
724 flattenUniformArrays = flatten;
725 if (flattenUniformArrays)
726 processes.addProcess("flatten-uniform-arrays");
728 bool getFlattenUniformArrays() const { return flattenUniformArrays; }
730 void setNoStorageFormat(bool b)
732 useUnknownFormat = b;
733 if (useUnknownFormat)
734 processes.addProcess("no-storage-format");
736 bool getNoStorageFormat() const { return useUnknownFormat; }
737 void setUseVulkanMemoryModel()
739 useVulkanMemoryModel = true;
740 processes.addProcess("use-vulkan-memory-model");
742 bool usingVulkanMemoryModel() const { return useVulkanMemoryModel; }
743 void setUsePhysicalStorageBuffer()
745 usePhysicalStorageBuffer = true;
747 bool usingPhysicalStorageBuffer() const { return usePhysicalStorageBuffer; }
748 void setUseVariablePointers()
750 useVariablePointers = true;
751 processes.addProcess("use-variable-pointers");
753 bool usingVariablePointers() const { return useVariablePointers; }
756 template<class T> T addCounterBufferName(const T& name) const { return name + implicitCounterName; }
757 bool hasCounterBufferName(const TString& name) const {
758 size_t len = strlen(implicitCounterName);
759 return name.size() > len &&
760 name.compare(name.size() - len, len, implicitCounterName) == 0;
764 void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { textureSamplerTransformMode = mode; }
765 int getNumPushConstants() const { return numPushConstants; }
766 void addShaderRecordCount() { ++numShaderRecordBlocks; }
767 void addTaskNVCount() { ++numTaskNVBlocks; }
768 void addTaskPayloadEXTCount() { ++numTaskEXTPayloads; }
770 bool setInvocations(int i)
772 if (invocations != TQualifier::layoutNotSet)
773 return invocations == i;
777 int getInvocations() const { return invocations; }
778 bool setVertices(int m)
780 if (vertices != TQualifier::layoutNotSet)
781 return vertices == m;
785 int getVertices() const { return vertices; }
786 bool setInputPrimitive(TLayoutGeometry p)
788 if (inputPrimitive != ElgNone)
789 return inputPrimitive == p;
793 TLayoutGeometry getInputPrimitive() const { return inputPrimitive; }
794 bool setVertexSpacing(TVertexSpacing s)
796 if (vertexSpacing != EvsNone)
797 return vertexSpacing == s;
801 TVertexSpacing getVertexSpacing() const { return vertexSpacing; }
802 bool setVertexOrder(TVertexOrder o)
804 if (vertexOrder != EvoNone)
805 return vertexOrder == o;
809 TVertexOrder getVertexOrder() const { return vertexOrder; }
810 void setPointMode() { pointMode = true; }
811 bool getPointMode() const { return pointMode; }
813 bool setInterlockOrdering(TInterlockOrdering o)
815 if (interlockOrdering != EioNone)
816 return interlockOrdering == o;
817 interlockOrdering = o;
820 TInterlockOrdering getInterlockOrdering() const { return interlockOrdering; }
822 void setXfbMode() { xfbMode = true; }
823 bool getXfbMode() const { return xfbMode; }
824 void setMultiStream() { multiStream = true; }
825 bool isMultiStream() const { return multiStream; }
826 bool setOutputPrimitive(TLayoutGeometry p)
828 if (outputPrimitive != ElgNone)
829 return outputPrimitive == p;
833 TLayoutGeometry getOutputPrimitive() const { return outputPrimitive; }
834 void setPostDepthCoverage() { postDepthCoverage = true; }
835 bool getPostDepthCoverage() const { return postDepthCoverage; }
836 void setEarlyFragmentTests() { earlyFragmentTests = true; }
837 void setEarlyAndLateFragmentTestsAMD() { earlyAndLateFragmentTestsAMD = true; }
838 bool getEarlyFragmentTests() const { return earlyFragmentTests; }
839 bool getEarlyAndLateFragmentTestsAMD() const { return earlyAndLateFragmentTestsAMD; }
840 bool setDepth(TLayoutDepth d)
842 if (depthLayout != EldNone)
843 return depthLayout == d;
847 bool setStencil(TLayoutStencil s)
849 if (stencilLayout != ElsNone)
850 return stencilLayout == s;
854 TLayoutDepth getDepth() const { return depthLayout; }
855 TLayoutStencil getStencil() const { return stencilLayout; }
856 void setOriginUpperLeft() { originUpperLeft = true; }
857 bool getOriginUpperLeft() const { return originUpperLeft; }
858 void setPixelCenterInteger() { pixelCenterInteger = true; }
859 bool getPixelCenterInteger() const { return pixelCenterInteger; }
860 void setTexCoordRedeclared() { texCoordBuiltinRedeclared = true; }
861 bool getTexCoordRedeclared() const { return texCoordBuiltinRedeclared; }
862 void addBlendEquation(TBlendEquationShift b) { blendEquations |= (1 << b); }
863 unsigned int getBlendEquations() const { return blendEquations; }
864 bool setXfbBufferStride(int buffer, unsigned stride)
866 if (xfbBuffers[buffer].stride != TQualifier::layoutXfbStrideEnd)
867 return xfbBuffers[buffer].stride == stride;
868 xfbBuffers[buffer].stride = stride;
871 unsigned getXfbStride(int buffer) const { return xfbBuffers[buffer].stride; }
872 int addXfbBufferOffset(const TType&);
873 unsigned int computeTypeXfbSize(const TType&, bool& contains64BitType, bool& contains32BitType, bool& contains16BitType) const;
874 unsigned int computeTypeXfbSize(const TType&, bool& contains64BitType) const;
875 void setLayoutOverrideCoverage() { layoutOverrideCoverage = true; }
876 bool getLayoutOverrideCoverage() const { return layoutOverrideCoverage; }
877 void setGeoPassthroughEXT() { geoPassthroughEXT = true; }
878 bool getGeoPassthroughEXT() const { return geoPassthroughEXT; }
879 void setLayoutDerivativeMode(ComputeDerivativeMode mode) { computeDerivativeMode = mode; }
880 bool hasLayoutDerivativeModeNone() const { return computeDerivativeMode != LayoutDerivativeNone; }
881 ComputeDerivativeMode getLayoutDerivativeModeNone() const { return computeDerivativeMode; }
882 void setLayoutPrimitiveCulling() { layoutPrimitiveCulling = true; }
883 bool getLayoutPrimitiveCulling() const { return layoutPrimitiveCulling; }
884 bool setPrimitives(int m)
886 if (primitives != TQualifier::layoutNotSet)
887 return primitives == m;
891 int getPrimitives() const { return primitives; }
892 const char* addSemanticName(const TString& name)
894 return semanticNameSet.insert(name).first->c_str();
896 void addUniformLocationOverride(const char* nameStr, int location)
898 std::string name = nameStr;
899 uniformLocationOverrides[name] = location;
902 int getUniformLocationOverride(const char* nameStr) const
904 std::string name = nameStr;
905 auto pos = uniformLocationOverrides.find(name);
906 if (pos == uniformLocationOverrides.end())
912 void setUniformLocationBase(int base) { uniformLocationBase = base; }
913 int getUniformLocationBase() const { return uniformLocationBase; }
915 void setNeedsLegalization() { needToLegalize = true; }
916 bool needsLegalization() const { return needToLegalize; }
918 void setBinaryDoubleOutput() { binaryDoubleOutput = true; }
919 bool getBinaryDoubleOutput() { return binaryDoubleOutput; }
921 void setSubgroupUniformControlFlow() { subgroupUniformControlFlow = true; }
922 bool getSubgroupUniformControlFlow() const { return subgroupUniformControlFlow; }
924 // GL_EXT_spirv_intrinsics
925 void insertSpirvRequirement(const TSpirvRequirement* spirvReq);
926 bool hasSpirvRequirement() const { return spirvRequirement != nullptr; }
927 const TSpirvRequirement& getSpirvRequirement() const { return *spirvRequirement; }
928 void insertSpirvExecutionMode(int executionMode, const TIntermAggregate* args = nullptr);
929 void insertSpirvExecutionModeId(int executionMode, const TIntermAggregate* args);
930 bool hasSpirvExecutionMode() const { return spirvExecutionMode != nullptr; }
931 const TSpirvExecutionMode& getSpirvExecutionMode() const { return *spirvExecutionMode; }
932 #endif // GLSLANG_WEB
934 void addBlockStorageOverride(const char* nameStr, TBlockStorageClass backing)
936 std::string name(nameStr);
937 blockBackingOverrides[name] = backing;
939 TBlockStorageClass getBlockStorageOverride(const char* nameStr) const
941 std::string name = nameStr;
942 auto pos = blockBackingOverrides.find(name);
943 if (pos == blockBackingOverrides.end())
949 void setHlslFunctionality1() { hlslFunctionality1 = true; }
950 bool getHlslFunctionality1() const { return hlslFunctionality1; }
951 void setHlslOffsets()
955 processes.addProcess("hlsl-offsets");
957 bool usingHlslOffsets() const { return hlslOffsets; }
958 void setHlslIoMapping(bool b)
962 processes.addProcess("hlsl-iomap");
964 bool usingHlslIoMapping() { return hlslIoMapping; }
966 bool getHlslFunctionality1() const { return false; }
967 bool usingHlslOffsets() const { return false; }
968 bool usingHlslIoMapping() { return false; }
971 bool usingScalarBlockLayout() const {
972 for (auto extIt = requestedExtensions.begin(); extIt != requestedExtensions.end(); ++extIt) {
973 if (*extIt == E_GL_EXT_scalar_block_layout)
979 bool IsRequestedExtension(const char* extension) const
981 return (requestedExtensions.find(extension) != requestedExtensions.end());
984 void addToCallGraph(TInfoSink&, const TString& caller, const TString& callee);
985 void merge(TInfoSink&, TIntermediate&);
986 void finalCheck(TInfoSink&, bool keepUncalled);
988 void mergeGlobalUniformBlocks(TInfoSink& infoSink, TIntermediate& unit, bool mergeExistingOnly);
989 void mergeUniformObjects(TInfoSink& infoSink, TIntermediate& unit);
990 void checkStageIO(TInfoSink&, TIntermediate&);
992 bool buildConvertOp(TBasicType dst, TBasicType src, TOperator& convertOp) const;
993 TIntermTyped* createConversion(TBasicType convertTo, TIntermTyped* node) const;
995 void addIoAccessed(const TString& name) { ioAccessed.insert(name); }
996 bool inIoAccessed(const TString& name) const { return ioAccessed.find(name) != ioAccessed.end(); }
998 int addUsedLocation(const TQualifier&, const TType&, bool& typeCollision);
999 int checkLocationRange(int set, const TIoRange& range, const TType&, bool& typeCollision);
1000 int checkLocationRT(int set, int location);
1001 int addUsedOffsets(int binding, int offset, int numOffsets);
1002 bool addUsedConstantId(int id);
1003 static int computeTypeLocationSize(const TType&, EShLanguage);
1004 static int computeTypeUniformLocationSize(const TType&);
1006 static int getBaseAlignmentScalar(const TType&, int& size);
1007 static int getBaseAlignment(const TType&, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor);
1008 static int getScalarAlignment(const TType&, int& size, int& stride, bool rowMajor);
1009 static int getMemberAlignment(const TType&, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor);
1010 static bool improperStraddle(const TType& type, int size, int offset);
1011 static void updateOffset(const TType& parentType, const TType& memberType, int& offset, int& memberSize);
1012 static int getOffset(const TType& type, int index);
1013 static int getBlockSize(const TType& blockType);
1014 static int computeBufferReferenceTypeSize(const TType&);
1015 static bool isIoResizeArray(const TType& type, EShLanguage language);
1017 bool promote(TIntermOperator*);
1018 void setNanMinMaxClamp(bool setting) { nanMinMaxClamp = setting; }
1019 bool getNanMinMaxClamp() const { return nanMinMaxClamp; }
1021 void setSourceFile(const char* file) { if (file != nullptr) sourceFile = file; }
1022 const std::string& getSourceFile() const { return sourceFile; }
1023 void addSourceText(const char* text, size_t len) { sourceText.append(text, len); }
1024 const std::string& getSourceText() const { return sourceText; }
1025 const std::map<std::string, std::string>& getIncludeText() const { return includeText; }
1026 void addIncludeText(const char* name, const char* text, size_t len) { includeText[name].assign(text,len); }
1027 void addProcesses(const std::vector<std::string>& p)
1029 for (int i = 0; i < (int)p.size(); ++i)
1030 processes.addProcess(p[i]);
1032 void addProcess(const std::string& process) { processes.addProcess(process); }
1033 void addProcessArgument(const std::string& arg) { processes.addArgument(arg); }
1034 const std::vector<std::string>& getProcesses() const { return processes.getProcesses(); }
1035 unsigned long long getUniqueId() const { return uniqueId; }
1036 void setUniqueId(unsigned long long id) { uniqueId = id; }
1038 // Certain explicit conversions are allowed conditionally
1040 bool getArithemeticInt8Enabled() const { return false; }
1041 bool getArithemeticInt16Enabled() const { return false; }
1042 bool getArithemeticFloat16Enabled() const { return false; }
1043 void updateNumericFeature(TNumericFeatures::feature f, bool on) { }
1045 bool getArithemeticInt8Enabled() const {
1046 return numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) ||
1047 numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int8);
1049 bool getArithemeticInt16Enabled() const {
1050 return numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) ||
1051 numericFeatures.contains(TNumericFeatures::gpu_shader_int16) ||
1052 numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int16);
1055 bool getArithemeticFloat16Enabled() const {
1056 return numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) ||
1057 numericFeatures.contains(TNumericFeatures::gpu_shader_half_float) ||
1058 numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_float16);
1060 void updateNumericFeature(TNumericFeatures::feature f, bool on)
1061 { on ? numericFeatures.insert(f) : numericFeatures.erase(f); }
1065 TIntermSymbol* addSymbol(long long Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&);
1066 void error(TInfoSink& infoSink, const char*, EShLanguage unitStage = EShLangCount);
1067 void warn(TInfoSink& infoSink, const char*, EShLanguage unitStage = EShLangCount);
1068 void mergeCallGraphs(TInfoSink&, TIntermediate&);
1069 void mergeModes(TInfoSink&, TIntermediate&);
1070 void mergeTrees(TInfoSink&, TIntermediate&);
1071 void seedIdMap(TIdMaps& idMaps, long long& IdShift);
1072 void remapIds(const TIdMaps& idMaps, long long idShift, TIntermediate&);
1073 void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals);
1074 void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects, EShLanguage);
1075 void mergeBlockDefinitions(TInfoSink&, TIntermSymbol* block, TIntermSymbol* unitBlock, TIntermediate* unitRoot);
1076 void mergeImplicitArraySizes(TType&, const TType&);
1077 void mergeErrorCheck(TInfoSink&, const TIntermSymbol&, const TIntermSymbol&, EShLanguage);
1078 void checkCallGraphCycles(TInfoSink&);
1079 void checkCallGraphBodies(TInfoSink&, bool keepUncalled);
1080 void inOutLocationCheck(TInfoSink&);
1081 void sharedBlockCheck(TInfoSink&);
1082 bool userOutputUsed() const;
1083 bool isSpecializationOperation(const TIntermOperator&) const;
1084 bool isNonuniformPropagating(TOperator) const;
1085 bool promoteUnary(TIntermUnary&);
1086 bool promoteBinary(TIntermBinary&);
1087 void addSymbolLinkageNode(TIntermAggregate*& linkage, TSymbolTable&, const TString&);
1088 bool promoteAggregate(TIntermAggregate&);
1089 void pushSelector(TIntermSequence&, const TVectorSelector&, const TSourceLoc&);
1090 void pushSelector(TIntermSequence&, const TMatrixSelector&, const TSourceLoc&);
1091 bool specConstantPropagates(const TIntermTyped&, const TIntermTyped&);
1092 void performTextureUpgradeAndSamplerRemovalTransformation(TIntermNode* root);
1093 bool isConversionAllowed(TOperator op, TIntermTyped* node) const;
1094 std::tuple<TBasicType, TBasicType> getConversionDestinationType(TBasicType type0, TBasicType type1, TOperator op) const;
1096 static const char* getResourceName(TResourceType);
1098 const EShLanguage language; // stage, known at construction time
1099 std::string entryPointName;
1100 std::string entryPointMangledName;
1101 typedef std::list<TCall> TGraph;
1104 #ifdef GLSLANG_ANGLE
1105 const EProfile profile = ECoreProfile;
1106 const int version = 450;
1108 EProfile profile; // source profile
1109 int version; // source version
1111 SpvVersion spvVersion;
1112 TIntermNode* treeRoot;
1113 std::set<std::string> requestedExtensions; // cumulation of all enabled or required extensions; not connected to what subset of the shader used them
1114 MustBeAssigned<TBuiltInResource> resources;
1117 int numPushConstants;
1123 bool useStorageBuffer;
1125 bool nanMinMaxClamp; // true if desiring min/max/clamp to favor non-NaN over NaN
1126 bool depthReplacing;
1127 bool stencilReplacing;
1129 bool localSizeNotDefault[3];
1130 int localSizeSpecId[3];
1131 unsigned long long uniqueId;
1133 std::string globalUniformBlockName;
1134 std::string atomicCounterBlockName;
1135 unsigned int globalUniformBlockSet;
1136 unsigned int globalUniformBlockBinding;
1137 unsigned int atomicCounterBlockSet;
1141 const char* const implicitThisName;
1142 const char* const implicitCounterName;
1144 EShSource source; // source language, known a bit later
1145 bool useVulkanMemoryModel;
1148 TLayoutGeometry inputPrimitive;
1149 TLayoutGeometry outputPrimitive;
1150 bool pixelCenterInteger;
1151 bool originUpperLeft;
1152 bool texCoordBuiltinRedeclared;
1153 TVertexSpacing vertexSpacing;
1154 TVertexOrder vertexOrder;
1155 TInterlockOrdering interlockOrdering;
1157 bool earlyFragmentTests;
1158 bool postDepthCoverage;
1159 bool earlyAndLateFragmentTestsAMD;
1160 TLayoutDepth depthLayout;
1161 TLayoutStencil stencilLayout;
1162 bool hlslFunctionality1;
1163 int blendEquations; // an 'or'ing of masks of shifts of TBlendEquationShift
1165 std::vector<TXfbBuffer> xfbBuffers; // all the data we need to track per xfb buffer
1167 bool layoutOverrideCoverage;
1168 bool geoPassthroughEXT;
1169 int numShaderRecordBlocks;
1170 ComputeDerivativeMode computeDerivativeMode;
1172 int numTaskNVBlocks;
1173 bool layoutPrimitiveCulling;
1174 int numTaskEXTPayloads;
1176 // Base shift values
1177 std::array<unsigned int, EResCount> shiftBinding;
1179 // Per-descriptor-set shift values
1180 std::array<std::map<int, int>, EResCount> shiftBindingForSet;
1182 std::vector<std::string> resourceSetBinding;
1183 bool autoMapBindings;
1184 bool autoMapLocations;
1185 bool flattenUniformArrays;
1186 bool useUnknownFormat;
1189 bool useVariablePointers;
1191 std::set<TString> semanticNameSet;
1193 EShTextureSamplerTransformMode textureSamplerTransformMode;
1195 bool needToLegalize;
1196 bool binaryDoubleOutput;
1197 bool subgroupUniformControlFlow;
1198 bool usePhysicalStorageBuffer;
1200 TSpirvRequirement* spirvRequirement;
1201 TSpirvExecutionMode* spirvExecutionMode;
1203 std::unordered_map<std::string, int> uniformLocationOverrides;
1204 int uniformLocationBase;
1205 TNumericFeatures numericFeatures;
1207 std::unordered_map<std::string, TBlockStorageClass> blockBackingOverrides;
1209 std::unordered_set<int> usedConstantId; // specialization constant ids used
1210 std::vector<TOffsetRange> usedAtomics; // sets of bindings used by atomic counters
1211 std::vector<TIoRange> usedIo[4]; // sets of used locations, one for each of in, out, uniform, and buffers
1212 std::vector<TRange> usedIoRT[2]; // sets of used location, one for rayPayload/rayPayloadIN and other
1213 // for callableData/callableDataIn
1214 // set of names of statically read/written I/O that might need extra checking
1215 std::set<TString> ioAccessed;
1217 // source code of shader, useful as part of debug information
1218 std::string sourceFile;
1219 std::string sourceText;
1221 // Included text. First string is a name, second is the included text
1222 std::map<std::string, std::string> includeText;
1224 // for OpModuleProcessed, or equivalent
1225 TProcesses processes;
1228 void operator=(TIntermediate&); // prevent assignments
1231 } // end namespace glslang
1233 #endif // _LOCAL_INTERMEDIATE_INCLUDED_