2 // Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
3 // Copyright (C) 2012-2016 LunarG, Inc.
4 // Copyright (C) 2015-2016 Google, Inc.
5 // Copyright (C) 2017 ARM Limited.
6 // Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
8 // All rights reserved.
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions
14 // Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
17 // Redistributions in binary form must reproduce the above
18 // copyright notice, this list of conditions and the following
19 // disclaimer in the documentation and/or other materials provided
20 // with the distribution.
22 // Neither the name of 3Dlabs Inc. Ltd. nor the names of its
23 // contributors may be used to endorse or promote products derived
24 // from this software without specific prior written permission.
26 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
29 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
30 // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
31 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
32 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
33 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
34 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
36 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 // POSSIBILITY OF SUCH DAMAGE.
40 #ifndef _TYPES_INCLUDED
41 #define _TYPES_INCLUDED
43 #include "../Include/Common.h"
44 #include "../Include/BaseTypes.h"
45 #include "../Public/ShaderLang.h"
47 #include "SpirvIntrinsics.h"
53 class TIntermAggregate;
55 const int GlslangMaxTypeLength = 200; // TODO: need to print block/struct one member per line, so this can stay bounded
57 const char* const AnonymousPrefix = "anon@"; // for something like a block whose members can be directly accessed
58 inline bool IsAnonymous(const TString& name)
60 return name.compare(0, 5, AnonymousPrefix) == 0;
64 // Details within a sampler type
74 EsdSubpass, // goes only with non-sampled image (image is true)
78 struct TSampler { // misnomer now; includes images, textures without sampler, and textures with sampler
79 TBasicType type : 8; // type returned by sampler
84 bool image : 1; // image, combined should be false
85 bool combined : 1; // true means texture is combined with a sampler, false means texture with no sampler
86 bool sampler : 1; // true means a pure sampler, other fields should be clear()
89 bool is1D() const { return false; }
90 bool isBuffer() const { return false; }
91 bool isRect() const { return false; }
92 bool isSubpass() const { return false; }
93 bool isCombined() const { return true; }
94 bool isImage() const { return false; }
95 bool isImageClass() const { return false; }
96 bool isMultiSample() const { return false; }
97 bool isExternal() const { return false; }
98 void setExternal(bool e) { }
99 bool isYuv() const { return false; }
101 unsigned int vectorSize : 3; // vector return type size.
102 // Some languages support structures as sample results. Storing the whole structure in the
103 // TSampler is too large, so there is an index to a separate table.
104 static const unsigned structReturnIndexBits = 4; // number of index bits to use.
105 static const unsigned structReturnSlots = (1<<structReturnIndexBits)-1; // number of valid values
106 static const unsigned noReturnStruct = structReturnSlots; // value if no return struct type.
107 // Index into a language specific table of texture return structures.
108 unsigned int structReturnIndex : structReturnIndexBits;
110 bool external : 1; // GL_OES_EGL_image_external
111 bool yuv : 1; // GL_EXT_YUV_target
114 unsigned int getVectorSize() const { return vectorSize; }
115 void clearReturnStruct() { structReturnIndex = noReturnStruct; }
116 bool hasReturnStruct() const { return structReturnIndex != noReturnStruct; }
117 unsigned getStructReturnIndex() const { return structReturnIndex; }
120 bool is1D() const { return dim == Esd1D; }
121 bool is2D() const { return dim == Esd2D; }
122 bool isBuffer() const { return dim == EsdBuffer; }
123 bool isRect() const { return dim == EsdRect; }
124 bool isSubpass() const { return dim == EsdSubpass; }
125 bool isCombined() const { return combined; }
126 bool isImage() const { return image && !isSubpass(); }
127 bool isImageClass() const { return image; }
128 bool isMultiSample() const { return ms; }
129 bool isExternal() const { return external; }
130 void setExternal(bool e) { external = e; }
131 bool isYuv() const { return yuv; }
133 bool isTexture() const { return !sampler && !image; }
134 bool isPureSampler() const { return sampler; }
136 void setCombined(bool c) { combined = c; }
137 void setBasicType(TBasicType t) { type = t; }
138 TBasicType getBasicType() const { return type; }
139 bool isShadow() const { return shadow; }
140 bool isArrayed() const { return arrayed; }
159 // by default, returns a single vec4;
164 // make a combined sampler and texture
165 void set(TBasicType t, TSamplerDim d, bool a = false, bool s = false, bool m = false)
177 void setImage(TBasicType t, TSamplerDim d, bool a = false, bool s = false, bool m = false)
188 // make a texture with no sampler
189 void setTexture(TBasicType t, TSamplerDim d, bool a = false, bool s = false, bool m = false)
199 // make a pure sampler, no texture, no image, nothing combined, the 'sampler' keyword
200 void setPureSampler(bool s)
208 // make a subpass input attachment
209 void setSubpass(TBasicType t, bool m = false)
219 bool operator==(const TSampler& right) const
221 return type == right.type &&
223 arrayed == right.arrayed &&
224 shadow == right.shadow &&
225 isMultiSample() == right.isMultiSample() &&
226 isImageClass() == right.isImageClass() &&
227 isCombined() == right.isCombined() &&
228 isPureSampler() == right.isPureSampler() &&
229 isExternal() == right.isExternal() &&
230 isYuv() == right.isYuv()
232 && getVectorSize() == right.getVectorSize() &&
233 getStructReturnIndex() == right.getStructReturnIndex()
238 bool operator!=(const TSampler& right) const
240 return ! operator==(right);
243 TString getString() const
247 if (isPureSampler()) {
253 case EbtInt: s.append("i"); break;
254 case EbtUint: s.append("u"); break;
256 case EbtFloat16: s.append("f16"); break;
257 case EbtInt8: s.append("i8"); break;
258 case EbtUint16: s.append("u8"); break;
259 case EbtInt16: s.append("i16"); break;
260 case EbtUint8: s.append("u16"); break;
261 case EbtInt64: s.append("i64"); break;
262 case EbtUint64: s.append("u64"); break;
266 if (isImageClass()) {
271 } else if (isCombined()) {
277 s.append("ExternalOES");
281 return "__" + s + "External2DY2YEXT";
284 case Esd2D: s.append("2D"); break;
285 case Esd3D: s.append("3D"); break;
286 case EsdCube: s.append("Cube"); break;
288 case Esd1D: s.append("1D"); break;
289 case EsdRect: s.append("2DRect"); break;
290 case EsdBuffer: s.append("Buffer"); break;
291 case EsdSubpass: s.append("Input"); break;
293 default: break; // some compilers want this
307 // Need to have association of line numbers to types in a list for building structs.
314 typedef TVector<TTypeLoc> TTypeList;
316 typedef TVector<TString*> TIdentifierList;
319 // Following are a series of helper enums for managing layouts and qualifiers,
320 // used for TPublicType, TType, others.
323 enum TLayoutPacking {
325 ElpShared, // default, but different than saying nothing
330 ElpCount // If expanding, see bitfield width below
336 ElmColumnMajor, // default, but different than saying nothing
337 ElmCount // If expanding, see bitfield width below
340 // Union of geometry shader and tessellation shader geometry types.
341 // They don't go into TType, but rather have current state per shader or
342 // active parser type (TPublicType).
343 enum TLayoutGeometry {
350 ElgTrianglesAdjacency,
356 enum TVertexSpacing {
369 // Note: order matters, as type of format is done by comparison.
380 ElfEsFloatGuard, // to help with comparisons
398 ElfFloatGuard, // to help with comparisons
406 ElfEsIntGuard, // to help with comparisons
415 ElfIntGuard, // to help with comparisons
423 ElfEsUintGuard, // to help with comparisons
446 enum TLayoutStencil {
448 ElsRefUnchangedFrontAMD,
449 ElsRefGreaterFrontAMD,
451 ElsRefUnchangedBackAMD,
452 ElsRefGreaterBackAMD,
458 enum TBlendEquationShift {
460 // These are used as bit-shift amounts. A mask of such shifts will have type 'int',
461 // and in that space, 0 means no bits set, or none. In this enum, 0 means (1 << 0), a bit is set.
482 enum TInterlockOrdering {
484 EioPixelInterlockOrdered,
485 EioPixelInterlockUnordered,
486 EioSampleInterlockOrdered,
487 EioSampleInterlockUnordered,
488 EioShadingRateInterlockOrdered,
489 EioShadingRateInterlockUnordered,
494 enum TShaderInterface
496 // Includes both uniform blocks and buffer blocks
507 static const int layoutNotSet = -1;
514 declaredBuiltIn = EbvNone;
516 noContraction = false;
518 spirvByReference = false;
519 spirvLiteral = false;
521 defaultBlock = false;
524 // drop qualifiers that don't belong in a temporary variable
527 semanticName = nullptr;
528 storage = EvqTemporary;
532 specConstant = false;
535 defaultBlock = false;
538 spirvStorageClass = -1;
539 spirvDecorate = nullptr;
540 spirvByReference = false;
541 spirvLiteral = false;
545 void clearInterstage()
547 clearInterpolation();
554 void clearInterpolation()
561 explicitInterp = false;
563 perPrimitiveNV = false;
567 pervertexEXT = false;
574 devicecoherent = false;
575 queuefamilycoherent = false;
576 workgroupcoherent = false;
577 subgroupcoherent = false;
578 shadercallcoherent = false;
587 const char* semanticName;
588 TStorageQualifier storage : 6;
589 TBuiltInVariable builtIn : 9;
590 TBuiltInVariable declaredBuiltIn : 9;
591 static_assert(EbvLast < 256, "need to increase size of TBuiltInVariable bitfields!");
592 TPrecisionQualifier precision : 3;
593 bool invariant : 1; // require canonical treatment for cross-shader invariance
597 // having a constant_id is not sufficient: expressions have no id, but are still specConstant
598 bool specConstant : 1;
600 bool explicitOffset : 1;
601 bool defaultBlock : 1; // default blocks with matching names have structures merged when linking
604 bool isWriteOnly() const { return false; }
605 bool isReadOnly() const { return false; }
606 bool isRestrict() const { return false; }
607 bool isCoherent() const { return false; }
608 bool isVolatile() const { return false; }
609 bool isSample() const { return false; }
610 bool isMemory() const { return false; }
611 bool isMemoryQualifierImageAndSSBOOnly() const { return false; }
612 bool bufferReferenceNeedsVulkanMemoryModel() const { return false; }
613 bool isInterpolation() const { return flat || smooth; }
614 bool isExplicitInterpolation() const { return false; }
615 bool isAuxiliary() const { return centroid; }
616 bool isPatch() const { return false; }
617 bool isNoContraction() const { return false; }
618 void setNoContraction() { }
619 bool isPervertexNV() const { return false; }
620 bool isPervertexEXT() const { return pervertexEXT; }
621 void setNullInit() {}
622 bool isNullInit() const { return false; }
623 void setSpirvByReference() { }
624 bool isSpirvByReference() { return false; }
625 void setSpirvLiteral() { }
626 bool isSpirvLiteral() { return false; }
628 bool noContraction: 1; // prevent contraction and reassociation, e.g., for 'precise' keyword, and expressions it affects
630 bool explicitInterp : 1;
631 bool pervertexNV : 1;
632 bool pervertexEXT : 1;
633 bool perPrimitiveNV : 1;
643 bool devicecoherent : 1;
644 bool queuefamilycoherent : 1;
645 bool workgroupcoherent : 1;
646 bool subgroupcoherent : 1;
647 bool shadercallcoherent : 1;
650 bool spirvByReference : 1;
651 bool spirvLiteral : 1;
652 bool isWriteOnly() const { return writeonly; }
653 bool isReadOnly() const { return readonly; }
654 bool isRestrict() const { return restrict; }
655 bool isCoherent() const { return coherent; }
656 bool isVolatile() const { return volatil; }
657 bool isSample() const { return sample; }
658 bool isMemory() const
660 return shadercallcoherent || subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly || nonprivate;
662 bool isMemoryQualifierImageAndSSBOOnly() const
664 return shadercallcoherent || subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly;
666 bool bufferReferenceNeedsVulkanMemoryModel() const
668 // include qualifiers that map to load/store availability/visibility/nonprivate memory access operands
669 return subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || nonprivate;
671 bool isInterpolation() const
673 return flat || smooth || nopersp || explicitInterp;
675 bool isExplicitInterpolation() const
677 return explicitInterp;
679 bool isAuxiliary() const
681 return centroid || patch || sample || pervertexNV || pervertexEXT;
683 bool isPatch() const { return patch; }
684 bool isNoContraction() const { return noContraction; }
685 void setNoContraction() { noContraction = true; }
686 bool isPervertexNV() const { return pervertexNV; }
687 bool isPervertexEXT() const { return pervertexEXT; }
688 void setNullInit() { nullInit = true; }
689 bool isNullInit() const { return nullInit; }
690 void setSpirvByReference() { spirvByReference = true; }
691 bool isSpirvByReference() const { return spirvByReference; }
692 void setSpirvLiteral() { spirvLiteral = true; }
693 bool isSpirvLiteral() const { return spirvLiteral; }
696 bool isPipeInput() const
711 bool isPipeOutput() const
727 bool isParamInput() const
732 case EvqConstReadOnly:
739 bool isParamOutput() const
750 bool isUniformOrBuffer() const
761 bool isUniform() const
795 // non-built-in symbols that might link between compilation units
796 bool isLinkable() const
811 TBlockStorageClass getBlockStorage() const {
812 if (storage == EvqUniform && !isPushConstant()) {
815 else if (storage == EvqUniform) {
816 return EbsPushConstant;
818 else if (storage == EvqBuffer) {
819 return EbsStorageBuffer;
824 void setBlockStorage(TBlockStorageClass newBacking) {
826 layoutPushConstant = (newBacking == EbsPushConstant);
828 switch (newBacking) {
830 if (layoutPacking == ElpStd430) {
831 // std430 would not be valid
832 layoutPacking = ElpStd140;
834 storage = EvqUniform;
836 case EbsStorageBuffer :
840 case EbsPushConstant :
841 storage = EvqUniform;
842 layoutSet = TQualifier::layoutSetEnd;
843 layoutBinding = TQualifier::layoutBindingEnd;
852 bool isPerView() const { return false; }
853 bool isTaskMemory() const { return false; }
854 bool isArrayedIo(EShLanguage language) const { return false; }
856 bool isPerPrimitive() const { return perPrimitiveNV; }
857 bool isPerView() const { return perViewNV; }
858 bool isTaskMemory() const { return perTaskNV; }
859 bool isAnyPayload() const {
860 return storage == EvqPayload || storage == EvqPayloadIn;
862 bool isAnyCallable() const {
863 return storage == EvqCallableData || storage == EvqCallableDataIn;
866 // True if this type of IO is supposed to be arrayed with extra level for per-vertex data
867 bool isArrayedIo(EShLanguage language) const
870 case EShLangGeometry:
871 return isPipeInput();
872 case EShLangTessControl:
873 return ! patch && (isPipeInput() || isPipeOutput());
874 case EShLangTessEvaluation:
875 return ! patch && isPipeInput();
876 case EShLangFragment:
877 return (pervertexNV || pervertexEXT) && isPipeInput();
879 return ! perTaskNV && isPipeOutput();
887 // Implementing an embedded layout-qualifier class here, since C++ can't have a real class bitfield
888 void clearLayout() // all layout
890 clearUniformLayout();
893 layoutPushConstant = false;
894 layoutBufferReference = false;
895 layoutPassthrough = false;
896 layoutViewportRelative = false;
897 // -2048 as the default value indicating layoutSecondaryViewportRelative is not set
898 layoutSecondaryViewportRelativeOffset = -2048;
899 layoutShaderRecord = false;
900 layoutBufferReferenceAlign = layoutBufferReferenceAlignEnd;
901 layoutFormat = ElfNone;
904 clearInterstageLayout();
906 layoutSpecConstantId = layoutSpecConstantIdEnd;
908 void clearInterstageLayout()
910 layoutLocation = layoutLocationEnd;
911 layoutComponent = layoutComponentEnd;
913 layoutIndex = layoutIndexEnd;
920 void clearStreamLayout()
922 layoutStream = layoutStreamEnd;
924 void clearXfbLayout()
926 layoutXfbBuffer = layoutXfbBufferEnd;
927 layoutXfbStride = layoutXfbStrideEnd;
928 layoutXfbOffset = layoutXfbOffsetEnd;
932 bool hasNonXfbLayout() const
934 return hasUniformLayout() ||
940 hasBufferReference();
942 bool hasLayout() const
944 return hasNonXfbLayout() ||
948 TLayoutMatrix layoutMatrix : 3;
949 TLayoutPacking layoutPacking : 4;
953 unsigned int layoutLocation : 12;
954 static const unsigned int layoutLocationEnd = 0xFFF;
956 unsigned int layoutComponent : 3;
957 static const unsigned int layoutComponentEnd = 4;
959 unsigned int layoutSet : 7;
960 static const unsigned int layoutSetEnd = 0x3F;
962 unsigned int layoutBinding : 16;
963 static const unsigned int layoutBindingEnd = 0xFFFF;
965 unsigned int layoutIndex : 8;
966 static const unsigned int layoutIndexEnd = 0xFF;
968 unsigned int layoutStream : 8;
969 static const unsigned int layoutStreamEnd = 0xFF;
971 unsigned int layoutXfbBuffer : 4;
972 static const unsigned int layoutXfbBufferEnd = 0xF;
974 unsigned int layoutXfbStride : 14;
975 static const unsigned int layoutXfbStrideEnd = 0x3FFF;
977 unsigned int layoutXfbOffset : 13;
978 static const unsigned int layoutXfbOffsetEnd = 0x1FFF;
980 unsigned int layoutAttachment : 8; // for input_attachment_index
981 static const unsigned int layoutAttachmentEnd = 0XFF;
983 unsigned int layoutSpecConstantId : 11;
984 static const unsigned int layoutSpecConstantIdEnd = 0x7FF;
987 // stored as log2 of the actual alignment value
988 unsigned int layoutBufferReferenceAlign : 6;
989 static const unsigned int layoutBufferReferenceAlignEnd = 0x3F;
991 TLayoutFormat layoutFormat : 8;
993 bool layoutPushConstant;
994 bool layoutBufferReference;
995 bool layoutPassthrough;
996 bool layoutViewportRelative;
997 int layoutSecondaryViewportRelativeOffset;
998 bool layoutShaderRecord;
1000 // GL_EXT_spirv_intrinsics
1001 int spirvStorageClass;
1002 TSpirvDecorate* spirvDecorate;
1005 bool hasUniformLayout() const
1007 return hasMatrix() ||
1014 void clearUniformLayout() // only uniform specific
1016 layoutMatrix = ElmNone;
1017 layoutPacking = ElpNone;
1018 layoutOffset = layoutNotSet;
1019 layoutAlign = layoutNotSet;
1021 layoutSet = layoutSetEnd;
1022 layoutBinding = layoutBindingEnd;
1024 layoutAttachment = layoutAttachmentEnd;
1028 bool hasMatrix() const
1030 return layoutMatrix != ElmNone;
1032 bool hasPacking() const
1034 return layoutPacking != ElpNone;
1036 bool hasAlign() const
1038 return layoutAlign != layoutNotSet;
1040 bool hasAnyLocation() const
1042 return hasLocation() ||
1046 bool hasLocation() const
1048 return layoutLocation != layoutLocationEnd;
1052 return layoutSet != layoutSetEnd;
1054 bool hasBinding() const
1056 return layoutBinding != layoutBindingEnd;
1059 bool hasOffset() const { return false; }
1060 bool isNonPerspective() const { return false; }
1061 bool hasIndex() const { return false; }
1062 unsigned getIndex() const { return 0; }
1063 bool hasComponent() const { return false; }
1064 bool hasStream() const { return false; }
1065 bool hasFormat() const { return false; }
1066 bool hasXfb() const { return false; }
1067 bool hasXfbBuffer() const { return false; }
1068 bool hasXfbStride() const { return false; }
1069 bool hasXfbOffset() const { return false; }
1070 bool hasAttachment() const { return false; }
1071 TLayoutFormat getFormat() const { return ElfNone; }
1072 bool isPushConstant() const { return false; }
1073 bool isShaderRecord() const { return false; }
1074 bool hasBufferReference() const { return false; }
1075 bool hasBufferReferenceAlign() const { return false; }
1076 bool isNonUniform() const { return false; }
1078 bool hasOffset() const
1080 return layoutOffset != layoutNotSet;
1082 bool isNonPerspective() const { return nopersp; }
1083 bool hasIndex() const
1085 return layoutIndex != layoutIndexEnd;
1087 unsigned getIndex() const { return layoutIndex; }
1088 bool hasComponent() const
1090 return layoutComponent != layoutComponentEnd;
1092 bool hasStream() const
1094 return layoutStream != layoutStreamEnd;
1096 bool hasFormat() const
1098 return layoutFormat != ElfNone;
1102 return hasXfbBuffer() ||
1106 bool hasXfbBuffer() const
1108 return layoutXfbBuffer != layoutXfbBufferEnd;
1110 bool hasXfbStride() const
1112 return layoutXfbStride != layoutXfbStrideEnd;
1114 bool hasXfbOffset() const
1116 return layoutXfbOffset != layoutXfbOffsetEnd;
1118 bool hasAttachment() const
1120 return layoutAttachment != layoutAttachmentEnd;
1122 TLayoutFormat getFormat() const { return layoutFormat; }
1123 bool isPushConstant() const { return layoutPushConstant; }
1124 bool isShaderRecord() const { return layoutShaderRecord; }
1125 bool hasBufferReference() const { return layoutBufferReference; }
1126 bool hasBufferReferenceAlign() const
1128 return layoutBufferReferenceAlign != layoutBufferReferenceAlignEnd;
1130 bool isNonUniform() const
1135 // GL_EXT_spirv_intrinsics
1136 bool hasSprivDecorate() const { return spirvDecorate != nullptr; }
1137 void setSpirvDecorate(int decoration, const TIntermAggregate* args = nullptr);
1138 void setSpirvDecorateId(int decoration, const TIntermAggregate* args);
1139 void setSpirvDecorateString(int decoration, const TIntermAggregate* args);
1140 const TSpirvDecorate& getSpirvDecorate() const { assert(spirvDecorate); return *spirvDecorate; }
1141 TSpirvDecorate& getSpirvDecorate() { assert(spirvDecorate); return *spirvDecorate; }
1142 TString getSpirvDecorateQualifierString() const;
1144 bool hasSpecConstantId() const
1146 // Not the same thing as being a specialization constant, this
1147 // is just whether or not it was declared with an ID.
1148 return layoutSpecConstantId != layoutSpecConstantIdEnd;
1150 bool isSpecConstant() const
1152 // True if type is a specialization constant, whether or not it
1153 // had a specialization-constant ID, and false if it is not a
1154 // true front-end constant.
1155 return specConstant;
1157 bool isFrontEndConstant() const
1159 // True if the front-end knows the final constant value.
1160 // This allows front-end constant folding.
1161 return storage == EvqConst && ! specConstant;
1163 bool isConstant() const
1165 // True if is either kind of constant; specialization or regular.
1166 return isFrontEndConstant() || isSpecConstant();
1168 void makeSpecConstant()
1171 specConstant = true;
1173 static const char* getLayoutPackingString(TLayoutPacking packing)
1176 case ElpStd140: return "std140";
1178 case ElpPacked: return "packed";
1179 case ElpShared: return "shared";
1180 case ElpStd430: return "std430";
1181 case ElpScalar: return "scalar";
1183 default: return "none";
1186 static const char* getLayoutMatrixString(TLayoutMatrix m)
1189 case ElmColumnMajor: return "column_major";
1190 case ElmRowMajor: return "row_major";
1191 default: return "none";
1195 static const char* getLayoutFormatString(TLayoutFormat f) { return "none"; }
1197 static const char* getLayoutFormatString(TLayoutFormat f)
1200 case ElfRgba32f: return "rgba32f";
1201 case ElfRgba16f: return "rgba16f";
1202 case ElfRg32f: return "rg32f";
1203 case ElfRg16f: return "rg16f";
1204 case ElfR11fG11fB10f: return "r11f_g11f_b10f";
1205 case ElfR32f: return "r32f";
1206 case ElfR16f: return "r16f";
1207 case ElfRgba16: return "rgba16";
1208 case ElfRgb10A2: return "rgb10_a2";
1209 case ElfRgba8: return "rgba8";
1210 case ElfRg16: return "rg16";
1211 case ElfRg8: return "rg8";
1212 case ElfR16: return "r16";
1213 case ElfR8: return "r8";
1214 case ElfRgba16Snorm: return "rgba16_snorm";
1215 case ElfRgba8Snorm: return "rgba8_snorm";
1216 case ElfRg16Snorm: return "rg16_snorm";
1217 case ElfRg8Snorm: return "rg8_snorm";
1218 case ElfR16Snorm: return "r16_snorm";
1219 case ElfR8Snorm: return "r8_snorm";
1221 case ElfRgba32i: return "rgba32i";
1222 case ElfRgba16i: return "rgba16i";
1223 case ElfRgba8i: return "rgba8i";
1224 case ElfRg32i: return "rg32i";
1225 case ElfRg16i: return "rg16i";
1226 case ElfRg8i: return "rg8i";
1227 case ElfR32i: return "r32i";
1228 case ElfR16i: return "r16i";
1229 case ElfR8i: return "r8i";
1231 case ElfRgba32ui: return "rgba32ui";
1232 case ElfRgba16ui: return "rgba16ui";
1233 case ElfRgba8ui: return "rgba8ui";
1234 case ElfRg32ui: return "rg32ui";
1235 case ElfRg16ui: return "rg16ui";
1236 case ElfRgb10a2ui: return "rgb10_a2ui";
1237 case ElfRg8ui: return "rg8ui";
1238 case ElfR32ui: return "r32ui";
1239 case ElfR16ui: return "r16ui";
1240 case ElfR8ui: return "r8ui";
1241 case ElfR64ui: return "r64ui";
1242 case ElfR64i: return "r64i";
1243 default: return "none";
1246 static const char* getLayoutDepthString(TLayoutDepth d)
1249 case EldAny: return "depth_any";
1250 case EldGreater: return "depth_greater";
1251 case EldLess: return "depth_less";
1252 case EldUnchanged: return "depth_unchanged";
1253 default: return "none";
1256 static const char* getLayoutStencilString(TLayoutStencil s)
1259 case ElsRefUnchangedFrontAMD: return "stencil_ref_unchanged_front_amd";
1260 case ElsRefGreaterFrontAMD: return "stencil_ref_greater_front_amd";
1261 case ElsRefLessFrontAMD: return "stencil_ref_less_front_amd";
1262 case ElsRefUnchangedBackAMD: return "stencil_ref_unchanged_back_amd";
1263 case ElsRefGreaterBackAMD: return "stencil_ref_greater_back_amd";
1264 case ElsRefLessBackAMD: return "stencil_ref_less_back_amd";
1265 default: return "none";
1268 static const char* getBlendEquationString(TBlendEquationShift e)
1271 case EBlendMultiply: return "blend_support_multiply";
1272 case EBlendScreen: return "blend_support_screen";
1273 case EBlendOverlay: return "blend_support_overlay";
1274 case EBlendDarken: return "blend_support_darken";
1275 case EBlendLighten: return "blend_support_lighten";
1276 case EBlendColordodge: return "blend_support_colordodge";
1277 case EBlendColorburn: return "blend_support_colorburn";
1278 case EBlendHardlight: return "blend_support_hardlight";
1279 case EBlendSoftlight: return "blend_support_softlight";
1280 case EBlendDifference: return "blend_support_difference";
1281 case EBlendExclusion: return "blend_support_exclusion";
1282 case EBlendHslHue: return "blend_support_hsl_hue";
1283 case EBlendHslSaturation: return "blend_support_hsl_saturation";
1284 case EBlendHslColor: return "blend_support_hsl_color";
1285 case EBlendHslLuminosity: return "blend_support_hsl_luminosity";
1286 case EBlendAllEquations: return "blend_support_all_equations";
1287 default: return "unknown";
1290 static const char* getGeometryString(TLayoutGeometry geometry)
1293 case ElgPoints: return "points";
1294 case ElgLines: return "lines";
1295 case ElgLinesAdjacency: return "lines_adjacency";
1296 case ElgLineStrip: return "line_strip";
1297 case ElgTriangles: return "triangles";
1298 case ElgTrianglesAdjacency: return "triangles_adjacency";
1299 case ElgTriangleStrip: return "triangle_strip";
1300 case ElgQuads: return "quads";
1301 case ElgIsolines: return "isolines";
1302 default: return "none";
1305 static const char* getVertexSpacingString(TVertexSpacing spacing)
1308 case EvsEqual: return "equal_spacing";
1309 case EvsFractionalEven: return "fractional_even_spacing";
1310 case EvsFractionalOdd: return "fractional_odd_spacing";
1311 default: return "none";
1314 static const char* getVertexOrderString(TVertexOrder order)
1317 case EvoCw: return "cw";
1318 case EvoCcw: return "ccw";
1319 default: return "none";
1322 static int mapGeometryToSize(TLayoutGeometry geometry)
1325 case ElgPoints: return 1;
1326 case ElgLines: return 2;
1327 case ElgLinesAdjacency: return 4;
1328 case ElgTriangles: return 3;
1329 case ElgTrianglesAdjacency: return 6;
1333 static const char* getInterlockOrderingString(TInterlockOrdering order)
1336 case EioPixelInterlockOrdered: return "pixel_interlock_ordered";
1337 case EioPixelInterlockUnordered: return "pixel_interlock_unordered";
1338 case EioSampleInterlockOrdered: return "sample_interlock_ordered";
1339 case EioSampleInterlockUnordered: return "sample_interlock_unordered";
1340 case EioShadingRateInterlockOrdered: return "shading_rate_interlock_ordered";
1341 case EioShadingRateInterlockUnordered: return "shading_rate_interlock_unordered";
1342 default: return "none";
1348 // Qualifiers that don't need to be keep per object. They have shader scope, not object scope.
1349 // So, they will not be part of TType, TQualifier, etc.
1350 struct TShaderQualifiers {
1351 TLayoutGeometry geometry; // geometry/tessellation shader in/out primitives
1352 bool pixelCenterInteger; // fragment shader
1353 bool originUpperLeft; // fragment shader
1355 int vertices; // for tessellation "vertices", geometry & mesh "max_vertices"
1356 TVertexSpacing spacing;
1359 int localSize[3]; // compute shader
1360 bool localSizeNotDefault[3]; // compute shader
1361 int localSizeSpecId[3]; // compute shader specialization id for gl_WorkGroupSize
1363 bool earlyFragmentTests; // fragment input
1364 bool postDepthCoverage; // fragment input
1365 bool earlyAndLateFragmentTestsAMD; //fragment input
1366 TLayoutDepth layoutDepth;
1367 TLayoutStencil layoutStencil;
1368 bool blendEquation; // true if any blend equation was specified
1369 int numViews; // multiview extenstions
1370 TInterlockOrdering interlockOrdering;
1371 bool layoutOverrideCoverage; // true if layout override_coverage set
1372 bool layoutDerivativeGroupQuads; // true if layout derivative_group_quadsNV set
1373 bool layoutDerivativeGroupLinear; // true if layout derivative_group_linearNV set
1374 int primitives; // mesh shader "max_primitives"DerivativeGroupLinear; // true if layout derivative_group_linearNV set
1375 bool layoutPrimitiveCulling; // true if layout primitive_culling set
1376 TLayoutDepth getDepth() const { return layoutDepth; }
1377 TLayoutStencil getStencil() const { return layoutStencil; }
1379 TLayoutDepth getDepth() const { return EldNone; }
1385 originUpperLeft = false;
1386 pixelCenterInteger = false;
1387 invocations = TQualifier::layoutNotSet;
1388 vertices = TQualifier::layoutNotSet;
1395 localSizeNotDefault[0] = false;
1396 localSizeNotDefault[1] = false;
1397 localSizeNotDefault[2] = false;
1398 localSizeSpecId[0] = TQualifier::layoutNotSet;
1399 localSizeSpecId[1] = TQualifier::layoutNotSet;
1400 localSizeSpecId[2] = TQualifier::layoutNotSet;
1402 earlyFragmentTests = false;
1403 earlyAndLateFragmentTestsAMD = false;
1404 postDepthCoverage = false;
1405 layoutDepth = EldNone;
1406 layoutStencil = ElsNone;
1407 blendEquation = false;
1408 numViews = TQualifier::layoutNotSet;
1409 layoutOverrideCoverage = false;
1410 layoutDerivativeGroupQuads = false;
1411 layoutDerivativeGroupLinear = false;
1412 layoutPrimitiveCulling = false;
1413 primitives = TQualifier::layoutNotSet;
1414 interlockOrdering = EioNone;
1419 bool hasBlendEquation() const { return false; }
1421 bool hasBlendEquation() const { return blendEquation; }
1424 // Merge in characteristics from the 'src' qualifier. They can override when
1425 // set, but never erase when not set.
1426 void merge(const TShaderQualifiers& src)
1428 if (src.geometry != ElgNone)
1429 geometry = src.geometry;
1430 if (src.pixelCenterInteger)
1431 pixelCenterInteger = src.pixelCenterInteger;
1432 if (src.originUpperLeft)
1433 originUpperLeft = src.originUpperLeft;
1434 if (src.invocations != TQualifier::layoutNotSet)
1435 invocations = src.invocations;
1436 if (src.vertices != TQualifier::layoutNotSet)
1437 vertices = src.vertices;
1438 if (src.spacing != EvsNone)
1439 spacing = src.spacing;
1440 if (src.order != EvoNone)
1444 for (int i = 0; i < 3; ++i) {
1445 if (src.localSize[i] > 1)
1446 localSize[i] = src.localSize[i];
1448 for (int i = 0; i < 3; ++i) {
1449 localSizeNotDefault[i] = src.localSizeNotDefault[i] || localSizeNotDefault[i];
1451 for (int i = 0; i < 3; ++i) {
1452 if (src.localSizeSpecId[i] != TQualifier::layoutNotSet)
1453 localSizeSpecId[i] = src.localSizeSpecId[i];
1456 if (src.earlyFragmentTests)
1457 earlyFragmentTests = true;
1458 if (src.earlyAndLateFragmentTestsAMD)
1459 earlyAndLateFragmentTestsAMD = true;
1460 if (src.postDepthCoverage)
1461 postDepthCoverage = true;
1462 if (src.layoutDepth)
1463 layoutDepth = src.layoutDepth;
1464 if (src.layoutStencil)
1465 layoutStencil = src.layoutStencil;
1466 if (src.blendEquation)
1467 blendEquation = src.blendEquation;
1468 if (src.numViews != TQualifier::layoutNotSet)
1469 numViews = src.numViews;
1470 if (src.layoutOverrideCoverage)
1471 layoutOverrideCoverage = src.layoutOverrideCoverage;
1472 if (src.layoutDerivativeGroupQuads)
1473 layoutDerivativeGroupQuads = src.layoutDerivativeGroupQuads;
1474 if (src.layoutDerivativeGroupLinear)
1475 layoutDerivativeGroupLinear = src.layoutDerivativeGroupLinear;
1476 if (src.primitives != TQualifier::layoutNotSet)
1477 primitives = src.primitives;
1478 if (src.interlockOrdering != EioNone)
1479 interlockOrdering = src.interlockOrdering;
1480 if (src.layoutPrimitiveCulling)
1481 layoutPrimitiveCulling = src.layoutPrimitiveCulling;
1487 // TPublicType is just temporarily used while parsing and not quite the same
1488 // information kept per node in TType. Due to the bison stack, it can't have
1489 // types that it thinks have non-trivial constructors. It should
1490 // just be used while recognizing the grammar, not anything else.
1491 // Once enough is known about the situation, the proper information
1492 // moved into a TType, or the parse context, etc.
1496 TBasicType basicType;
1498 TQualifier qualifier;
1499 TShaderQualifiers shaderQualifiers;
1504 TArraySizes* arraySizes;
1505 const TType* userDef;
1507 TArraySizes* typeParameters;
1509 // SPIR-V type defined by spirv_type directive
1510 TSpirvType* spirvType;
1514 bool isCoopmat() const { return false; }
1516 bool isCoopmat() const { return coopmat; }
1519 void initType(const TSourceLoc& l)
1521 basicType = EbtVoid;
1525 arraySizes = nullptr;
1528 typeParameters = nullptr;
1531 spirvType = nullptr;
1535 void initQualifiers(bool global = false)
1539 qualifier.storage = EvqGlobal;
1542 void init(const TSourceLoc& l, bool global = false)
1546 initQualifiers(global);
1547 shaderQualifiers.init();
1550 void setVector(int s)
1557 void setMatrix(int c, int r)
1564 bool isScalar() const
1566 return matrixCols == 0 && vectorSize == 1 && arraySizes == nullptr && userDef == nullptr;
1570 // GL_EXT_spirv_intrinsics
1571 void setSpirvType(const TSpirvInstruction& spirvInst, const TSpirvTypeParameters* typeParams = nullptr);
1574 // "Image" is a superset of "Subpass"
1575 bool isImage() const { return basicType == EbtSampler && sampler.isImage(); }
1576 bool isSubpass() const { return basicType == EbtSampler && sampler.isSubpass(); }
1580 // Base class for things that have a type.
1584 POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
1586 // for "empty" type (no args) or simple scalar/vector/matrix
1587 explicit TType(TBasicType t = EbtVoid, TStorageQualifier q = EvqTemporary, int vs = 1, int mc = 0, int mr = 0,
1588 bool isVector = false) :
1589 basicType(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), vector1(isVector && vs == 1), coopmat(false),
1590 arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(nullptr)
1592 , spirvType(nullptr)
1597 qualifier.storage = q;
1598 assert(!(isMatrix() && vectorSize != 0)); // prevent vectorSize != 0 on matrices
1600 // for explicit precision qualifier
1601 TType(TBasicType t, TStorageQualifier q, TPrecisionQualifier p, int vs = 1, int mc = 0, int mr = 0,
1602 bool isVector = false) :
1603 basicType(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), vector1(isVector && vs == 1), coopmat(false),
1604 arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(nullptr)
1606 , spirvType(nullptr)
1611 qualifier.storage = q;
1612 qualifier.precision = p;
1613 assert(p >= EpqNone && p <= EpqHigh);
1614 assert(!(isMatrix() && vectorSize != 0)); // prevent vectorSize != 0 on matrices
1616 // for turning a TPublicType into a TType, using a shallow copy
1617 explicit TType(const TPublicType& p) :
1618 basicType(p.basicType),
1619 vectorSize(p.vectorSize), matrixCols(p.matrixCols), matrixRows(p.matrixRows), vector1(false), coopmat(p.coopmat),
1620 arraySizes(p.arraySizes), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(p.typeParameters)
1622 , spirvType(p.spirvType)
1625 if (basicType == EbtSampler)
1626 sampler = p.sampler;
1629 qualifier = p.qualifier;
1631 if (p.userDef->basicType == EbtReference) {
1632 basicType = EbtReference;
1633 referentType = p.userDef->referentType;
1635 structure = p.userDef->getWritableStruct(); // public type is short-lived; there are no sharing issues
1637 typeName = NewPoolTString(p.userDef->getTypeName().c_str());
1639 if (p.isCoopmat() && p.typeParameters && p.typeParameters->getNumDims() > 0) {
1640 int numBits = p.typeParameters->getDimSize(0);
1641 if (p.basicType == EbtFloat && numBits == 16) {
1642 basicType = EbtFloat16;
1643 qualifier.precision = EpqNone;
1644 } else if (p.basicType == EbtUint && numBits == 8) {
1645 basicType = EbtUint8;
1646 qualifier.precision = EpqNone;
1647 } else if (p.basicType == EbtInt && numBits == 8) {
1648 basicType = EbtInt8;
1649 qualifier.precision = EpqNone;
1653 // for construction of sampler types
1654 TType(const TSampler& sampler, TStorageQualifier q = EvqUniform, TArraySizes* as = nullptr) :
1655 basicType(EbtSampler), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmat(false),
1656 arraySizes(as), structure(nullptr), fieldName(nullptr), typeName(nullptr),
1657 sampler(sampler), typeParameters(nullptr)
1659 , spirvType(nullptr)
1663 qualifier.storage = q;
1665 // to efficiently make a dereferenced type
1666 // without ever duplicating the outer structure that will be thrown away
1667 // and using only shallow copy
1668 TType(const TType& type, int derefIndex, bool rowMajor = false)
1670 if (type.isArray()) {
1672 if (type.getArraySizes()->getNumDims() == 1) {
1673 arraySizes = nullptr;
1675 // want our own copy of the array, so we can edit it
1676 arraySizes = new TArraySizes;
1677 arraySizes->copyDereferenced(*type.arraySizes);
1679 } else if (type.basicType == EbtStruct || type.basicType == EbtBlock) {
1680 // do a structure dereference
1681 const TTypeList& memberList = *type.getStruct();
1682 shallowCopy(*memberList[derefIndex].type);
1685 // do a vector/matrix dereference
1687 if (matrixCols > 0) {
1688 // dereference from matrix to vector
1690 vectorSize = matrixCols;
1692 vectorSize = matrixRows;
1695 if (vectorSize == 1)
1697 } else if (isVector()) {
1698 // dereference from vector to scalar
1701 } else if (isCoopMat()) {
1703 typeParameters = nullptr;
1707 // for making structures, ...
1708 TType(TTypeList* userDef, const TString& n) :
1709 basicType(EbtStruct), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmat(false),
1710 arraySizes(nullptr), structure(userDef), fieldName(nullptr), typeParameters(nullptr)
1712 , spirvType(nullptr)
1717 typeName = NewPoolTString(n.c_str());
1719 // For interface blocks
1720 TType(TTypeList* userDef, const TString& n, const TQualifier& q) :
1721 basicType(EbtBlock), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmat(false),
1722 qualifier(q), arraySizes(nullptr), structure(userDef), fieldName(nullptr), typeParameters(nullptr)
1724 , spirvType(nullptr)
1728 typeName = NewPoolTString(n.c_str());
1730 // for block reference (first parameter must be EbtReference)
1731 explicit TType(TBasicType t, const TType &p, const TString& n) :
1732 basicType(t), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false),
1733 arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr)
1735 , spirvType(nullptr)
1738 assert(t == EbtReference);
1739 typeName = NewPoolTString(n.c_str());
1741 qualifier.storage = p.qualifier.storage;
1742 referentType = p.clone();
1746 // Not for use across pool pops; it will cause multiple instances of TType to point to the same information.
1747 // This only works if that information (like a structure's list of types) does not change and
1748 // the instances are sharing the same pool.
1749 void shallowCopy(const TType& copyOf)
1751 basicType = copyOf.basicType;
1752 sampler = copyOf.sampler;
1753 qualifier = copyOf.qualifier;
1754 vectorSize = copyOf.vectorSize;
1755 matrixCols = copyOf.matrixCols;
1756 matrixRows = copyOf.matrixRows;
1757 vector1 = copyOf.vector1;
1758 arraySizes = copyOf.arraySizes; // copying the pointer only, not the contents
1759 fieldName = copyOf.fieldName;
1760 typeName = copyOf.typeName;
1762 structure = copyOf.structure;
1764 referentType = copyOf.referentType;
1766 typeParameters = copyOf.typeParameters;
1768 spirvType = copyOf.spirvType;
1770 coopmat = copyOf.isCoopMat();
1773 // Make complete copy of the whole type graph rooted at 'copyOf'.
1774 void deepCopy(const TType& copyOf)
1776 TMap<TTypeList*,TTypeList*> copied; // to enable copying a type graph as a graph, not a tree
1777 deepCopy(copyOf, copied);
1780 // Recursively make temporary
1781 void makeTemporary()
1783 getQualifier().makeTemporary();
1786 for (unsigned int i = 0; i < structure->size(); ++i)
1787 (*structure)[i].type->makeTemporary();
1790 TType* clone() const
1792 TType *newType = new TType();
1793 newType->deepCopy(*this);
1798 void makeVector() { vector1 = true; }
1800 virtual void hideMember() { basicType = EbtVoid; vectorSize = 1; }
1801 virtual bool hiddenMember() const { return basicType == EbtVoid; }
1803 virtual void setFieldName(const TString& n) { fieldName = NewPoolTString(n.c_str()); }
1804 virtual const TString& getTypeName() const
1810 virtual const TString& getFieldName() const
1815 TShaderInterface getShaderInterface() const
1817 if (basicType != EbtBlock)
1820 switch (qualifier.storage) {
1833 virtual TBasicType getBasicType() const { return basicType; }
1834 virtual const TSampler& getSampler() const { return sampler; }
1835 virtual TSampler& getSampler() { return sampler; }
1837 virtual TQualifier& getQualifier() { return qualifier; }
1838 virtual const TQualifier& getQualifier() const { return qualifier; }
1840 virtual int getVectorSize() const { return vectorSize; } // returns 1 for either scalar or vector of size 1, valid for both
1841 virtual int getMatrixCols() const { return matrixCols; }
1842 virtual int getMatrixRows() const { return matrixRows; }
1843 virtual int getOuterArraySize() const { return arraySizes->getOuterSize(); }
1844 virtual TIntermTyped* getOuterArrayNode() const { return arraySizes->getOuterNode(); }
1845 virtual int getCumulativeArraySize() const { return arraySizes->getCumulativeSize(); }
1847 bool isArrayOfArrays() const { return false; }
1849 bool isArrayOfArrays() const { return arraySizes != nullptr && arraySizes->getNumDims() > 1; }
1851 virtual int getImplicitArraySize() const { return arraySizes->getImplicitSize(); }
1852 virtual const TArraySizes* getArraySizes() const { return arraySizes; }
1853 virtual TArraySizes* getArraySizes() { return arraySizes; }
1854 virtual TType* getReferentType() const { return referentType; }
1855 virtual const TArraySizes* getTypeParameters() const { return typeParameters; }
1856 virtual TArraySizes* getTypeParameters() { return typeParameters; }
1858 virtual bool isScalar() const { return ! isVector() && ! isMatrix() && ! isStruct() && ! isArray(); }
1859 virtual bool isScalarOrVec1() const { return isScalar() || vector1; }
1860 virtual bool isScalarOrVector() const { return !isMatrix() && !isStruct() && !isArray(); }
1861 virtual bool isVector() const { return vectorSize > 1 || vector1; }
1862 virtual bool isMatrix() const { return matrixCols ? true : false; }
1863 virtual bool isArray() const { return arraySizes != nullptr; }
1864 virtual bool isSizedArray() const { return isArray() && arraySizes->isSized(); }
1865 virtual bool isUnsizedArray() const { return isArray() && !arraySizes->isSized(); }
1866 virtual bool isArrayVariablyIndexed() const { assert(isArray()); return arraySizes->isVariablyIndexed(); }
1867 virtual void setArrayVariablyIndexed() { assert(isArray()); arraySizes->setVariablyIndexed(); }
1868 virtual void updateImplicitArraySize(int size) { assert(isArray()); arraySizes->updateImplicitSize(size); }
1869 virtual bool isStruct() const { return basicType == EbtStruct || basicType == EbtBlock; }
1870 virtual bool isFloatingDomain() const { return basicType == EbtFloat || basicType == EbtDouble || basicType == EbtFloat16; }
1871 virtual bool isIntegerDomain() const
1873 switch (basicType) {
1889 virtual bool isOpaque() const { return basicType == EbtSampler
1891 || basicType == EbtAtomicUint || basicType == EbtAccStruct || basicType == EbtRayQuery
1894 virtual bool isBuiltIn() const { return getQualifier().builtIn != EbvNone; }
1896 // "Image" is a superset of "Subpass"
1897 virtual bool isImage() const { return basicType == EbtSampler && getSampler().isImage(); }
1898 virtual bool isSubpass() const { return basicType == EbtSampler && getSampler().isSubpass(); }
1899 virtual bool isTexture() const { return basicType == EbtSampler && getSampler().isTexture(); }
1900 // Check the block-name convention of creating a block without populating it's members:
1901 virtual bool isUnusableName() const { return isStruct() && structure == nullptr; }
1902 virtual bool isParameterized() const { return typeParameters != nullptr; }
1904 bool isAtomic() const { return false; }
1905 bool isCoopMat() const { return false; }
1906 bool isReference() const { return false; }
1907 bool isSpirvType() const { return false; }
1909 bool isAtomic() const { return basicType == EbtAtomicUint; }
1910 bool isCoopMat() const { return coopmat; }
1911 bool isReference() const { return getBasicType() == EbtReference; }
1912 bool isSpirvType() const { return getBasicType() == EbtSpirvType; }
1915 // return true if this type contains any subtype which satisfies the given predicate.
1916 template <typename P>
1917 bool contains(P predicate) const
1919 if (predicate(this))
1922 const auto hasa = [predicate](const TTypeLoc& tl) { return tl.type->contains(predicate); };
1924 return isStruct() && std::any_of(structure->begin(), structure->end(), hasa);
1927 // Recursively checks if the type contains the given basic type
1928 virtual bool containsBasicType(TBasicType checkType) const
1930 return contains([checkType](const TType* t) { return t->basicType == checkType; } );
1933 // Recursively check the structure for any arrays, needed for some error checks
1934 virtual bool containsArray() const
1936 return contains([](const TType* t) { return t->isArray(); } );
1939 // Check the structure for any structures, needed for some error checks
1940 virtual bool containsStructure() const
1942 return contains([this](const TType* t) { return t != this && t->isStruct(); } );
1945 // Recursively check the structure for any unsized arrays, needed for triggering a copyUp().
1946 virtual bool containsUnsizedArray() const
1948 return contains([](const TType* t) { return t->isUnsizedArray(); } );
1951 virtual bool containsOpaque() const
1953 return contains([](const TType* t) { return t->isOpaque(); } );
1956 // Recursively checks if the type contains a built-in variable
1957 virtual bool containsBuiltIn() const
1959 return contains([](const TType* t) { return t->isBuiltIn(); } );
1962 virtual bool containsNonOpaque() const
1964 const auto nonOpaque = [](const TType* t) {
1965 switch (t->basicType) {
1986 return contains(nonOpaque);
1989 virtual bool containsSpecializationSize() const
1991 return contains([](const TType* t) { return t->isArray() && t->arraySizes->isOuterSpecialization(); } );
1995 bool containsDouble() const { return false; }
1996 bool contains16BitFloat() const { return false; }
1997 bool contains64BitInt() const { return false; }
1998 bool contains16BitInt() const { return false; }
1999 bool contains8BitInt() const { return false; }
2000 bool containsCoopMat() const { return false; }
2001 bool containsReference() const { return false; }
2003 bool containsDouble() const
2005 return containsBasicType(EbtDouble);
2007 bool contains16BitFloat() const
2009 return containsBasicType(EbtFloat16);
2011 bool contains64BitInt() const
2013 return containsBasicType(EbtInt64) || containsBasicType(EbtUint64);
2015 bool contains16BitInt() const
2017 return containsBasicType(EbtInt16) || containsBasicType(EbtUint16);
2019 bool contains8BitInt() const
2021 return containsBasicType(EbtInt8) || containsBasicType(EbtUint8);
2023 bool containsCoopMat() const
2025 return contains([](const TType* t) { return t->coopmat; } );
2027 bool containsReference() const
2029 return containsBasicType(EbtReference);
2033 // Array editing methods. Array descriptors can be shared across
2034 // type instances. This allows all uses of the same array
2035 // to be updated at once. E.g., all nodes can be explicitly sized
2036 // by tracking and correcting one implicit size. Or, all nodes
2037 // can get the explicit size on a redeclaration that gives size.
2039 // N.B.: Don't share with the shared symbol tables (symbols are
2040 // marked as isReadOnly(). Such symbols with arrays that will be
2041 // edited need to copyUp() on first use, so that
2042 // A) the edits don't effect the shared symbol table, and
2043 // B) the edits are shared across all users.
2044 void updateArraySizes(const TType& type)
2046 // For when we may already be sharing existing array descriptors,
2047 // keeping the pointers the same, just updating the contents.
2048 assert(arraySizes != nullptr);
2049 assert(type.arraySizes != nullptr);
2050 *arraySizes = *type.arraySizes;
2052 void copyArraySizes(const TArraySizes& s)
2054 // For setting a fresh new set of array sizes, not yet worrying about sharing.
2055 arraySizes = new TArraySizes;
2058 void transferArraySizes(TArraySizes* s)
2060 // For setting an already allocated set of sizes that this type can use
2064 void clearArraySizes()
2066 arraySizes = nullptr;
2069 // Add inner array sizes, to any existing sizes, via copy; the
2070 // sizes passed in can still be reused for other purposes.
2071 void copyArrayInnerSizes(const TArraySizes* s)
2074 if (arraySizes == nullptr)
2077 arraySizes->addInnerSizes(*s);
2080 void changeOuterArraySize(int s) { arraySizes->changeOuterSize(s); }
2082 // Recursively make the implicit array size the explicit array size.
2083 // Expicit arrays are compile-time or link-time sized, never run-time sized.
2084 // Sometimes, policy calls for an array to be run-time sized even if it was
2085 // never variably indexed: Don't turn a 'skipNonvariablyIndexed' array into
2086 // an explicit array.
2087 void adoptImplicitArraySizes(bool skipNonvariablyIndexed)
2089 if (isUnsizedArray() && !(skipNonvariablyIndexed || isArrayVariablyIndexed()))
2090 changeOuterArraySize(getImplicitArraySize());
2091 // For multi-dim per-view arrays, set unsized inner dimension size to 1
2092 if (qualifier.isPerView() && arraySizes && arraySizes->isInnerUnsized())
2093 arraySizes->clearInnerUnsized();
2094 if (isStruct() && structure->size() > 0) {
2095 int lastMember = (int)structure->size() - 1;
2096 for (int i = 0; i < lastMember; ++i)
2097 (*structure)[i].type->adoptImplicitArraySizes(false);
2098 // implement the "last member of an SSBO" policy
2099 (*structure)[lastMember].type->adoptImplicitArraySizes(getQualifier().storage == EvqBuffer);
2104 void updateTypeParameters(const TType& type)
2106 // For when we may already be sharing existing array descriptors,
2107 // keeping the pointers the same, just updating the contents.
2108 assert(typeParameters != nullptr);
2109 assert(type.typeParameters != nullptr);
2110 *typeParameters = *type.typeParameters;
2112 void copyTypeParameters(const TArraySizes& s)
2114 // For setting a fresh new set of type parameters, not yet worrying about sharing.
2115 typeParameters = new TArraySizes;
2116 *typeParameters = s;
2118 void transferTypeParameters(TArraySizes* s)
2120 // For setting an already allocated set of sizes that this type can use
2124 void clearTypeParameters()
2126 typeParameters = nullptr;
2129 // Add inner array sizes, to any existing sizes, via copy; the
2130 // sizes passed in can still be reused for other purposes.
2131 void copyTypeParametersInnerSizes(const TArraySizes* s)
2134 if (typeParameters == nullptr)
2135 copyTypeParameters(*s);
2137 typeParameters->addInnerSizes(*s);
2141 const char* getBasicString() const
2143 return TType::getBasicString(basicType);
2146 static const char* getBasicString(TBasicType t)
2149 case EbtFloat: return "float";
2150 case EbtInt: return "int";
2151 case EbtUint: return "uint";
2152 case EbtSampler: return "sampler/image";
2154 case EbtVoid: return "void";
2155 case EbtDouble: return "double";
2156 case EbtFloat16: return "float16_t";
2157 case EbtInt8: return "int8_t";
2158 case EbtUint8: return "uint8_t";
2159 case EbtInt16: return "int16_t";
2160 case EbtUint16: return "uint16_t";
2161 case EbtInt64: return "int64_t";
2162 case EbtUint64: return "uint64_t";
2163 case EbtBool: return "bool";
2164 case EbtAtomicUint: return "atomic_uint";
2165 case EbtStruct: return "structure";
2166 case EbtBlock: return "block";
2167 case EbtAccStruct: return "accelerationStructureNV";
2168 case EbtRayQuery: return "rayQueryEXT";
2169 case EbtReference: return "reference";
2170 case EbtString: return "string";
2171 case EbtSpirvType: return "spirv_type";
2173 default: return "unknown type";
2178 TString getCompleteString() const { return ""; }
2179 const char* getStorageQualifierString() const { return ""; }
2180 const char* getBuiltInVariableString() const { return ""; }
2181 const char* getPrecisionQualifierString() const { return ""; }
2182 TString getBasicTypeString() const { return ""; }
2184 TString getCompleteString(bool syntactic = false, bool getQualifiers = true, bool getPrecision = true,
2185 bool getType = true, TString name = "", TString structName = "") const
2189 const auto appendStr = [&](const char* s) { typeString.append(s); };
2190 const auto appendUint = [&](unsigned int u) { typeString.append(std::to_string(u).c_str()); };
2191 const auto appendInt = [&](int i) { typeString.append(std::to_string(i).c_str()); };
2193 if (getQualifiers) {
2194 if (qualifier.hasSprivDecorate())
2195 appendStr(qualifier.getSpirvDecorateQualifierString().c_str());
2197 if (qualifier.hasLayout()) {
2198 // To reduce noise, skip this if the only layout is an xfb_buffer
2199 // with no triggering xfb_offset.
2200 TQualifier noXfbBuffer = qualifier;
2201 noXfbBuffer.layoutXfbBuffer = TQualifier::layoutXfbBufferEnd;
2202 if (noXfbBuffer.hasLayout()) {
2203 appendStr("layout(");
2204 if (qualifier.hasAnyLocation()) {
2205 appendStr(" location=");
2206 appendUint(qualifier.layoutLocation);
2207 if (qualifier.hasComponent()) {
2208 appendStr(" component=");
2209 appendUint(qualifier.layoutComponent);
2211 if (qualifier.hasIndex()) {
2212 appendStr(" index=");
2213 appendUint(qualifier.layoutIndex);
2216 if (qualifier.hasSet()) {
2218 appendUint(qualifier.layoutSet);
2220 if (qualifier.hasBinding()) {
2221 appendStr(" binding=");
2222 appendUint(qualifier.layoutBinding);
2224 if (qualifier.hasStream()) {
2225 appendStr(" stream=");
2226 appendUint(qualifier.layoutStream);
2228 if (qualifier.hasMatrix()) {
2230 appendStr(TQualifier::getLayoutMatrixString(qualifier.layoutMatrix));
2232 if (qualifier.hasPacking()) {
2234 appendStr(TQualifier::getLayoutPackingString(qualifier.layoutPacking));
2236 if (qualifier.hasOffset()) {
2237 appendStr(" offset=");
2238 appendInt(qualifier.layoutOffset);
2240 if (qualifier.hasAlign()) {
2241 appendStr(" align=");
2242 appendInt(qualifier.layoutAlign);
2244 if (qualifier.hasFormat()) {
2246 appendStr(TQualifier::getLayoutFormatString(qualifier.layoutFormat));
2248 if (qualifier.hasXfbBuffer() && qualifier.hasXfbOffset()) {
2249 appendStr(" xfb_buffer=");
2250 appendUint(qualifier.layoutXfbBuffer);
2252 if (qualifier.hasXfbOffset()) {
2253 appendStr(" xfb_offset=");
2254 appendUint(qualifier.layoutXfbOffset);
2256 if (qualifier.hasXfbStride()) {
2257 appendStr(" xfb_stride=");
2258 appendUint(qualifier.layoutXfbStride);
2260 if (qualifier.hasAttachment()) {
2261 appendStr(" input_attachment_index=");
2262 appendUint(qualifier.layoutAttachment);
2264 if (qualifier.hasSpecConstantId()) {
2265 appendStr(" constant_id=");
2266 appendUint(qualifier.layoutSpecConstantId);
2268 if (qualifier.layoutPushConstant)
2269 appendStr(" push_constant");
2270 if (qualifier.layoutBufferReference)
2271 appendStr(" buffer_reference");
2272 if (qualifier.hasBufferReferenceAlign()) {
2273 appendStr(" buffer_reference_align=");
2274 appendUint(1u << qualifier.layoutBufferReferenceAlign);
2277 if (qualifier.layoutPassthrough)
2278 appendStr(" passthrough");
2279 if (qualifier.layoutViewportRelative)
2280 appendStr(" layoutViewportRelative");
2281 if (qualifier.layoutSecondaryViewportRelativeOffset != -2048) {
2282 appendStr(" layoutSecondaryViewportRelativeOffset=");
2283 appendInt(qualifier.layoutSecondaryViewportRelativeOffset);
2285 if (qualifier.layoutShaderRecord)
2286 appendStr(" shaderRecordNV");
2292 if (qualifier.invariant)
2293 appendStr(" invariant");
2294 if (qualifier.noContraction)
2295 appendStr(" noContraction");
2296 if (qualifier.centroid)
2297 appendStr(" centroid");
2298 if (qualifier.smooth)
2299 appendStr(" smooth");
2302 if (qualifier.nopersp)
2303 appendStr(" noperspective");
2304 if (qualifier.explicitInterp)
2305 appendStr(" __explicitInterpAMD");
2306 if (qualifier.pervertexNV)
2307 appendStr(" pervertexNV");
2308 if (qualifier.pervertexEXT)
2309 appendStr(" pervertexEXT");
2310 if (qualifier.perPrimitiveNV)
2311 appendStr(" perprimitiveNV");
2312 if (qualifier.perViewNV)
2313 appendStr(" perviewNV");
2314 if (qualifier.perTaskNV)
2315 appendStr(" taskNV");
2316 if (qualifier.patch)
2317 appendStr(" patch");
2318 if (qualifier.sample)
2319 appendStr(" sample");
2320 if (qualifier.coherent)
2321 appendStr(" coherent");
2322 if (qualifier.devicecoherent)
2323 appendStr(" devicecoherent");
2324 if (qualifier.queuefamilycoherent)
2325 appendStr(" queuefamilycoherent");
2326 if (qualifier.workgroupcoherent)
2327 appendStr(" workgroupcoherent");
2328 if (qualifier.subgroupcoherent)
2329 appendStr(" subgroupcoherent");
2330 if (qualifier.shadercallcoherent)
2331 appendStr(" shadercallcoherent");
2332 if (qualifier.nonprivate)
2333 appendStr(" nonprivate");
2334 if (qualifier.volatil)
2335 appendStr(" volatile");
2336 if (qualifier.restrict)
2337 appendStr(" restrict");
2338 if (qualifier.readonly)
2339 appendStr(" readonly");
2340 if (qualifier.writeonly)
2341 appendStr(" writeonly");
2342 if (qualifier.specConstant)
2343 appendStr(" specialization-constant");
2344 if (qualifier.nonUniform)
2345 appendStr(" nonuniform");
2346 if (qualifier.isNullInit())
2347 appendStr(" null-init");
2348 if (qualifier.isSpirvByReference())
2349 appendStr(" spirv_by_reference");
2350 if (qualifier.isSpirvLiteral())
2351 appendStr(" spirv_literal");
2353 appendStr(getStorageQualifierString());
2357 if (getPrecision && qualifier.precision != EpqNone) {
2359 appendStr(getPrecisionQualifierString());
2361 if (isVector() || isMatrix()) {
2363 switch (basicType) {
2382 appendInt(vectorSize);
2385 appendInt(matrixCols);
2387 appendInt(matrixRows);
2389 } else if (isStruct() && structure) {
2391 appendStr(structName.c_str());
2393 bool hasHiddenMember = true;
2394 for (size_t i = 0; i < structure->size(); ++i) {
2395 if (!(*structure)[i].type->hiddenMember()) {
2396 if (!hasHiddenMember)
2398 typeString.append((*structure)[i].type->getCompleteString(syntactic, getQualifiers, getPrecision, getType, (*structure)[i].type->getFieldName()));
2399 hasHiddenMember = false;
2405 switch (basicType) {
2407 appendStr("double");
2422 appendStr("unexpected");
2426 if (name.length() > 0) {
2428 appendStr(name.c_str());
2431 for (int i = 0; i < (int)arraySizes->getNumDims(); ++i) {
2432 int size = arraySizes->getDimSize(i);
2433 if (size == UnsizedArraySize && i == 0 && arraySizes->isVariablyIndexed())
2436 if (size == UnsizedArraySize) {
2439 appendInt(arraySizes->getImplicitSize());
2444 appendInt(arraySizes->getDimSize(i));
2453 for (int i = 0; i < (int)arraySizes->getNumDims(); ++i) {
2454 int size = arraySizes->getDimSize(i);
2455 if (size == UnsizedArraySize && i == 0 && arraySizes->isVariablyIndexed())
2456 appendStr(" runtime-sized array of");
2458 if (size == UnsizedArraySize) {
2459 appendStr(" unsized");
2462 appendInt(arraySizes->getImplicitSize());
2467 appendInt(arraySizes->getDimSize(i));
2469 appendStr("-element array of");
2473 if (isParameterized()) {
2475 for (int i = 0; i < (int)typeParameters->getNumDims(); ++i) {
2476 appendInt(typeParameters->getDimSize(i));
2477 if (i != (int)typeParameters->getNumDims() - 1)
2482 if (getPrecision && qualifier.precision != EpqNone) {
2484 appendStr(getPrecisionQualifierString());
2488 appendInt(matrixCols);
2490 appendInt(matrixRows);
2491 appendStr(" matrix of");
2493 else if (isVector()) {
2495 appendInt(vectorSize);
2496 appendStr("-component vector of");
2500 typeString.append(getBasicTypeString());
2502 if (qualifier.builtIn != EbvNone) {
2504 appendStr(getBuiltInVariableString());
2507 // Add struct/block members
2508 if (isStruct() && structure) {
2510 bool hasHiddenMember = true;
2511 for (size_t i = 0; i < structure->size(); ++i) {
2512 if (!(*structure)[i].type->hiddenMember()) {
2513 if (!hasHiddenMember)
2515 typeString.append((*structure)[i].type->getCompleteString());
2516 typeString.append(" ");
2517 typeString.append((*structure)[i].type->getFieldName());
2518 hasHiddenMember = false;
2529 TString getBasicTypeString() const
2531 if (basicType == EbtSampler)
2532 return sampler.getString();
2534 return getBasicString();
2537 const char* getStorageQualifierString() const { return GetStorageQualifierString(qualifier.storage); }
2538 const char* getBuiltInVariableString() const { return GetBuiltInVariableString(qualifier.builtIn); }
2539 const char* getPrecisionQualifierString() const { return GetPrecisionQualifierString(qualifier.precision); }
2542 const TTypeList* getStruct() const { assert(isStruct()); return structure; }
2543 void setStruct(TTypeList* s) { assert(isStruct()); structure = s; }
2544 TTypeList* getWritableStruct() const { assert(isStruct()); return structure; } // This should only be used when known to not be sharing with other threads
2545 void setBasicType(const TBasicType& t) { basicType = t; }
2547 int computeNumComponents() const
2551 if (getBasicType() == EbtStruct || getBasicType() == EbtBlock) {
2552 for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); tl++)
2553 components += ((*tl).type)->computeNumComponents();
2554 } else if (matrixCols)
2555 components = matrixCols * matrixRows;
2557 components = vectorSize;
2559 if (arraySizes != nullptr) {
2560 components *= arraySizes->getCumulativeSize();
2566 // append this type's mangled name to the passed in 'name'
2567 void appendMangledName(TString& name) const
2569 buildMangledName(name);
2573 // These variables are inconsistently declared inside and outside of gl_PerVertex in glslang right now.
2574 // They are declared inside of 'in gl_PerVertex', but sitting as standalone when they are 'out'puts.
2575 bool isInconsistentGLPerVertexMember(const TString& name) const
2577 if (name == "gl_SecondaryPositionNV" ||
2578 name == "gl_PositionPerViewNV")
2584 // Do two structure types match? They could be declared independently,
2585 // in different places, but still might satisfy the definition of matching.
2588 // "Structures must have the same name, sequence of type names, and
2589 // type definitions, and member names to be considered the same type.
2590 // This rule applies recursively for nested or embedded types."
2592 // If type mismatch in structure, return member indices through lpidx and rpidx.
2593 // If matching members for either block are exhausted, return -1 for exhausted
2594 // block and the index of the unmatched member. Otherwise return {-1,-1}.
2596 bool sameStructType(const TType& right, int* lpidx = nullptr, int* rpidx = nullptr) const
2598 // Initialize error to general type mismatch.
2599 if (lpidx != nullptr) {
2604 // Most commonly, they are both nullptr, or the same pointer to the same actual structure
2605 // TODO: Why return true when neither types are structures?
2606 if ((!isStruct() && !right.isStruct()) ||
2607 (isStruct() && right.isStruct() && structure == right.structure))
2610 if (!isStruct() || !right.isStruct())
2613 // Structure names have to match
2614 if (*typeName != *right.typeName)
2617 // There are inconsistencies with how gl_PerVertex is setup. For now ignore those as errors if they
2618 // are known inconsistencies.
2619 bool isGLPerVertex = *typeName == "gl_PerVertex";
2621 // Both being nullptr was caught above, now they both have to be structures of the same number of elements
2622 if (lpidx == nullptr &&
2623 (structure->size() != right.structure->size() && !isGLPerVertex)) {
2627 // Compare the names and types of all the members, which have to match
2628 for (size_t li = 0, ri = 0; li < structure->size() || ri < right.structure->size(); ++li, ++ri) {
2629 if (lpidx != nullptr) {
2630 *lpidx = static_cast<int>(li);
2631 *rpidx = static_cast<int>(ri);
2633 if (li < structure->size() && ri < right.structure->size()) {
2634 if ((*structure)[li].type->getFieldName() == (*right.structure)[ri].type->getFieldName()) {
2635 if (*(*structure)[li].type != *(*right.structure)[ri].type)
2638 // Skip hidden members
2639 if ((*structure)[li].type->hiddenMember()) {
2642 } else if ((*right.structure)[ri].type->hiddenMember()) {
2646 // If one of the members is something that's inconsistently declared, skip over it
2648 if (isGLPerVertex) {
2649 if (isInconsistentGLPerVertexMember((*structure)[li].type->getFieldName())) {
2652 } else if (isInconsistentGLPerVertexMember((*right.structure)[ri].type->getFieldName())) {
2660 // If we get here, then there should only be inconsistently declared members left
2661 } else if (li < structure->size()) {
2662 if (!(*structure)[li].type->hiddenMember() && !isInconsistentGLPerVertexMember((*structure)[li].type->getFieldName())) {
2663 if (lpidx != nullptr) {
2669 if (!(*right.structure)[ri].type->hiddenMember() && !isInconsistentGLPerVertexMember((*right.structure)[ri].type->getFieldName())) {
2670 if (lpidx != nullptr) {
2681 bool sameReferenceType(const TType& right) const
2683 if (isReference() != right.isReference())
2686 if (!isReference() && !right.isReference())
2689 assert(referentType != nullptr);
2690 assert(right.referentType != nullptr);
2692 if (referentType == right.referentType)
2695 return *referentType == *right.referentType;
2698 // See if two types match, in all aspects except arrayness
2699 // If mismatch in structure members, return member indices in lpidx and rpidx.
2700 bool sameElementType(const TType& right, int* lpidx = nullptr, int* rpidx = nullptr) const
2702 if (lpidx != nullptr) {
2706 return basicType == right.basicType && sameElementShape(right, lpidx, rpidx);
2709 // See if two type's arrayness match
2710 bool sameArrayness(const TType& right) const
2712 return ((arraySizes == nullptr && right.arraySizes == nullptr) ||
2713 (arraySizes != nullptr && right.arraySizes != nullptr && *arraySizes == *right.arraySizes));
2716 // See if two type's arrayness match in everything except their outer dimension
2717 bool sameInnerArrayness(const TType& right) const
2719 assert(arraySizes != nullptr && right.arraySizes != nullptr);
2720 return arraySizes->sameInnerArrayness(*right.arraySizes);
2723 // See if two type's parameters match
2724 bool sameTypeParameters(const TType& right) const
2726 return ((typeParameters == nullptr && right.typeParameters == nullptr) ||
2727 (typeParameters != nullptr && right.typeParameters != nullptr && *typeParameters == *right.typeParameters));
2731 // See if two type's SPIR-V type contents match
2732 bool sameSpirvType(const TType& right) const
2734 return ((spirvType == nullptr && right.spirvType == nullptr) ||
2735 (spirvType != nullptr && right.spirvType != nullptr && *spirvType == *right.spirvType));
2739 // See if two type's elements match in all ways except basic type
2740 // If mismatch in structure members, return member indices in lpidx and rpidx.
2741 bool sameElementShape(const TType& right, int* lpidx = nullptr, int* rpidx = nullptr) const
2743 if (lpidx != nullptr) {
2747 return ((basicType != EbtSampler && right.basicType != EbtSampler) || sampler == right.sampler) &&
2748 vectorSize == right.vectorSize &&
2749 matrixCols == right.matrixCols &&
2750 matrixRows == right.matrixRows &&
2751 vector1 == right.vector1 &&
2752 isCoopMat() == right.isCoopMat() &&
2753 sameStructType(right, lpidx, rpidx) &&
2754 sameReferenceType(right);
2757 // See if a cooperative matrix type parameter with unspecified parameters is
2758 // an OK function parameter
2759 bool coopMatParameterOK(const TType& right) const
2761 return isCoopMat() && right.isCoopMat() && (getBasicType() == right.getBasicType()) &&
2762 typeParameters == nullptr && right.typeParameters != nullptr;
2765 bool sameCoopMatBaseType(const TType &right) const {
2766 bool rv = coopmat && right.coopmat;
2767 if (getBasicType() == EbtFloat || getBasicType() == EbtFloat16)
2768 rv = right.getBasicType() == EbtFloat || right.getBasicType() == EbtFloat16;
2769 else if (getBasicType() == EbtUint || getBasicType() == EbtUint8)
2770 rv = right.getBasicType() == EbtUint || right.getBasicType() == EbtUint8;
2771 else if (getBasicType() == EbtInt || getBasicType() == EbtInt8)
2772 rv = right.getBasicType() == EbtInt || right.getBasicType() == EbtInt8;
2779 // See if two types match in all ways (just the actual type, not qualification)
2780 bool operator==(const TType& right) const
2783 return sameElementType(right) && sameArrayness(right) && sameTypeParameters(right) && sameSpirvType(right);
2785 return sameElementType(right) && sameArrayness(right) && sameTypeParameters(right);
2789 bool operator!=(const TType& right) const
2791 return ! operator==(right);
2794 unsigned int getBufferReferenceAlignment() const
2797 if (getBasicType() == glslang::EbtReference) {
2798 return getReferentType()->getQualifier().hasBufferReferenceAlign() ?
2799 (1u << getReferentType()->getQualifier().layoutBufferReferenceAlign) : 16u;
2806 const TSpirvType& getSpirvType() const { assert(spirvType); return *spirvType; }
2810 // Require consumer to pick between deep copy and shallow copy.
2811 TType(const TType& type);
2812 TType& operator=(const TType& type);
2814 // Recursively copy a type graph, while preserving the graph-like
2815 // quality. That is, don't make more than one copy of a structure that
2816 // gets reused multiple times in the type graph.
2817 void deepCopy(const TType& copyOf, TMap<TTypeList*,TTypeList*>& copiedMap)
2819 shallowCopy(copyOf);
2822 // GL_EXT_spirv_intrinsics
2823 if (copyOf.qualifier.spirvDecorate) {
2824 qualifier.spirvDecorate = new TSpirvDecorate;
2825 *qualifier.spirvDecorate = *copyOf.qualifier.spirvDecorate;
2828 if (copyOf.spirvType) {
2829 spirvType = new TSpirvType;
2830 *spirvType = *copyOf.spirvType;
2834 if (copyOf.arraySizes) {
2835 arraySizes = new TArraySizes;
2836 *arraySizes = *copyOf.arraySizes;
2839 if (copyOf.typeParameters) {
2840 typeParameters = new TArraySizes;
2841 *typeParameters = *copyOf.typeParameters;
2844 if (copyOf.isStruct() && copyOf.structure) {
2845 auto prevCopy = copiedMap.find(copyOf.structure);
2846 if (prevCopy != copiedMap.end())
2847 structure = prevCopy->second;
2849 structure = new TTypeList;
2850 copiedMap[copyOf.structure] = structure;
2851 for (unsigned int i = 0; i < copyOf.structure->size(); ++i) {
2853 typeLoc.loc = (*copyOf.structure)[i].loc;
2854 typeLoc.type = new TType();
2855 typeLoc.type->deepCopy(*(*copyOf.structure)[i].type, copiedMap);
2856 structure->push_back(typeLoc);
2861 if (copyOf.fieldName)
2862 fieldName = NewPoolTString(copyOf.fieldName->c_str());
2863 if (copyOf.typeName)
2864 typeName = NewPoolTString(copyOf.typeName->c_str());
2868 void buildMangledName(TString&) const;
2870 TBasicType basicType : 8;
2871 int vectorSize : 4; // 1 means either scalar or 1-component vector; see vector1 to disambiguate.
2874 bool vector1 : 1; // Backward-compatible tracking of a 1-component vector distinguished from a scalar.
2875 // GLSL 4.5 never has a 1-component vector; so this will always be false until such
2876 // functionality is added.
2877 // HLSL does have a 1-component vectors, so this will be true to disambiguate
2880 TQualifier qualifier;
2882 TArraySizes* arraySizes; // nullptr unless an array; can be shared across types
2883 // A type can't be both a structure (EbtStruct/EbtBlock) and a reference (EbtReference), so
2884 // conserve space by making these a union
2886 TTypeList* structure; // invalid unless this is a struct; can be shared across types
2887 TType *referentType; // invalid unless this is an EbtReference
2889 TString *fieldName; // for structure field names
2890 TString *typeName; // for structure type name
2892 TArraySizes* typeParameters;// nullptr unless a parameterized type; can be shared across types
2894 TSpirvType* spirvType; // SPIR-V type defined by spirv_type directive
2898 } // end namespace glslang
2900 #endif // _TYPES_INCLUDED_