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.
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 _TYPES_INCLUDED
40 #define _TYPES_INCLUDED
42 #include "../Include/Common.h"
43 #include "../Include/BaseTypes.h"
44 #include "../Public/ShaderLang.h"
51 const int GlslangMaxTypeLength = 200; // TODO: need to print block/struct one member per line, so this can stay bounded
53 const char* const AnonymousPrefix = "anon@"; // for something like a block whose members can be directly accessed
54 inline bool IsAnonymous(const TString& name)
56 return name.compare(0, 5, AnonymousPrefix) == 0;
60 // Details within a sampler type
70 EsdSubpass, // goes only with non-sampled image (image is true)
74 struct TSampler { // misnomer now; includes images, textures without sampler, and textures with sampler
75 TBasicType type : 8; // type returned by sampler
80 bool image : 1; // image, combined should be false
81 bool combined : 1; // true means texture is combined with a sampler, false means texture with no sampler
82 bool sampler : 1; // true means a pure sampler, other fields should be clear()
85 bool is1D() const { return false; }
86 bool isBuffer() const { return false; }
87 bool isRect() const { return false; }
88 bool isSubpass() const { return false; }
89 bool isCombined() const { return true; }
90 bool isImage() const { return false; }
91 bool isImageClass() const { return false; }
92 bool isMultiSample() const { return false; }
93 bool isExternal() const { return false; }
94 void setExternal(bool e) { }
95 bool isYuv() const { return false; }
97 unsigned int vectorSize : 3; // vector return type size.
98 // Some languages support structures as sample results. Storing the whole structure in the
99 // TSampler is too large, so there is an index to a separate table.
100 static const unsigned structReturnIndexBits = 4; // number of index bits to use.
101 static const unsigned structReturnSlots = (1<<structReturnIndexBits)-1; // number of valid values
102 static const unsigned noReturnStruct = structReturnSlots; // value if no return struct type.
103 // Index into a language specific table of texture return structures.
104 unsigned int structReturnIndex : structReturnIndexBits;
106 bool external : 1; // GL_OES_EGL_image_external
107 bool yuv : 1; // GL_EXT_YUV_target
110 unsigned int getVectorSize() const { return vectorSize; }
111 void clearReturnStruct() { structReturnIndex = noReturnStruct; }
112 bool hasReturnStruct() const { return structReturnIndex != noReturnStruct; }
113 unsigned getStructReturnIndex() const { return structReturnIndex; }
116 bool is1D() const { return dim == Esd1D; }
117 bool isBuffer() const { return dim == EsdBuffer; }
118 bool isRect() const { return dim == EsdRect; }
119 bool isSubpass() const { return dim == EsdSubpass; }
120 bool isCombined() const { return combined; }
121 bool isImage() const { return image && !isSubpass(); }
122 bool isImageClass() const { return image; }
123 bool isMultiSample() const { return ms; }
124 bool isExternal() const { return external; }
125 void setExternal(bool e) { external = e; }
126 bool isYuv() const { return yuv; }
128 bool isTexture() const { return !sampler && !image; }
129 bool isPureSampler() const { return sampler; }
131 void setCombined(bool c) { combined = c; }
132 void setBasicType(TBasicType t) { type = t; }
133 TBasicType getBasicType() const { return type; }
134 bool isShadow() const { return shadow; }
135 bool isArrayed() const { return arrayed; }
154 // by default, returns a single vec4;
159 // make a combined sampler and texture
160 void set(TBasicType t, TSamplerDim d, bool a = false, bool s = false, bool m = false)
172 void setImage(TBasicType t, TSamplerDim d, bool a = false, bool s = false, bool m = false)
183 // make a texture with no sampler
184 void setTexture(TBasicType t, TSamplerDim d, bool a = false, bool s = false, bool m = false)
194 // make a pure sampler, no texture, no image, nothing combined, the 'sampler' keyword
195 void setPureSampler(bool s)
203 // make a subpass input attachment
204 void setSubpass(TBasicType t, bool m = false)
214 bool operator==(const TSampler& right) const
216 return type == right.type &&
218 arrayed == right.arrayed &&
219 shadow == right.shadow &&
220 isMultiSample() == right.isMultiSample() &&
221 isImageClass() == right.isImageClass() &&
222 isCombined() == right.isCombined() &&
223 isPureSampler() == right.isPureSampler() &&
224 isExternal() == right.isExternal() &&
225 isYuv() == right.isYuv()
227 && getVectorSize() == right.getVectorSize() &&
228 getStructReturnIndex() == right.getStructReturnIndex()
233 bool operator!=(const TSampler& right) const
235 return ! operator==(right);
238 TString getString() const
242 if (isPureSampler()) {
248 case EbtInt: s.append("i"); break;
249 case EbtUint: s.append("u"); break;
251 case EbtFloat16: s.append("f16"); break;
252 case EbtInt8: s.append("i8"); break;
253 case EbtUint16: s.append("u8"); break;
254 case EbtInt16: s.append("i16"); break;
255 case EbtUint8: s.append("u16"); break;
256 case EbtInt64: s.append("i64"); break;
257 case EbtUint64: s.append("u64"); break;
261 if (isImageClass()) {
266 } else if (isCombined()) {
272 s.append("ExternalOES");
276 return "__" + s + "External2DY2YEXT";
279 case Esd2D: s.append("2D"); break;
280 case Esd3D: s.append("3D"); break;
281 case EsdCube: s.append("Cube"); break;
283 case Esd1D: s.append("1D"); break;
284 case EsdRect: s.append("2DRect"); break;
285 case EsdBuffer: s.append("Buffer"); break;
286 case EsdSubpass: s.append("Input"); break;
288 default: break; // some compilers want this
302 // Need to have association of line numbers to types in a list for building structs.
309 typedef TVector<TTypeLoc> TTypeList;
311 typedef TVector<TString*> TIdentifierList;
314 // Following are a series of helper enums for managing layouts and qualifiers,
315 // used for TPublicType, TType, others.
318 enum TLayoutPacking {
320 ElpShared, // default, but different than saying nothing
325 ElpCount // If expanding, see bitfield width below
331 ElmColumnMajor, // default, but different than saying nothing
332 ElmCount // If expanding, see bitfield width below
335 // Union of geometry shader and tessellation shader geometry types.
336 // They don't go into TType, but rather have current state per shader or
337 // active parser type (TPublicType).
338 enum TLayoutGeometry {
345 ElgTrianglesAdjacency,
351 enum TVertexSpacing {
364 // Note: order matters, as type of format is done by comparison.
375 ElfEsFloatGuard, // to help with comparisons
393 ElfFloatGuard, // to help with comparisons
401 ElfEsIntGuard, // to help with comparisons
409 ElfIntGuard, // to help with comparisons
417 ElfEsUintGuard, // to help with comparisons
439 enum TBlendEquationShift {
441 // These are used as bit-shift amounts. A mask of such shifts will have type 'int',
442 // and in that space, 0 means no bits set, or none. In this enum, 0 means (1 << 0), a bit is set.
463 enum TInterlockOrdering {
465 EioPixelInterlockOrdered,
466 EioPixelInterlockUnordered,
467 EioSampleInterlockOrdered,
468 EioSampleInterlockUnordered,
469 EioShadingRateInterlockOrdered,
470 EioShadingRateInterlockUnordered,
477 static const int layoutNotSet = -1;
484 declaredBuiltIn = EbvNone;
486 noContraction = false;
490 // drop qualifiers that don't belong in a temporary variable
493 semanticName = nullptr;
494 storage = EvqTemporary;
498 specConstant = false;
503 void clearInterstage()
505 clearInterpolation();
512 void clearInterpolation()
519 explicitInterp = false;
521 perPrimitiveNV = false;
531 devicecoherent = false;
532 queuefamilycoherent = false;
533 workgroupcoherent = false;
534 subgroupcoherent = false;
543 const char* semanticName;
544 TStorageQualifier storage : 6;
545 TBuiltInVariable builtIn : 9;
546 TBuiltInVariable declaredBuiltIn : 9;
547 static_assert(EbvLast < 256, "need to increase size of TBuiltInVariable bitfields!");
548 TPrecisionQualifier precision : 3;
549 bool invariant : 1; // require canonical treatment for cross-shader invariance
553 // having a constant_id is not sufficient: expressions have no id, but are still specConstant
554 bool specConstant : 1;
558 bool isWriteOnly() const { return false; }
559 bool isReadOnly() const { return false; }
560 bool isRestrict() const { return false; }
561 bool isCoherent() const { return false; }
562 bool isVolatile() const { return false; }
563 bool isSample() const { return false; }
564 bool isMemory() const { return false; }
565 bool isMemoryQualifierImageAndSSBOOnly() const { return false; }
566 bool bufferReferenceNeedsVulkanMemoryModel() const { return false; }
567 bool isInterpolation() const { return flat || smooth; }
568 bool isExplicitInterpolation() const { return false; }
569 bool isAuxiliary() const { return centroid; }
570 bool isPatch() const { return false; }
571 bool isNoContraction() const { return false; }
572 void setNoContraction() { }
573 bool isPervertexNV() const { return false; }
575 bool noContraction: 1; // prevent contraction and reassociation, e.g., for 'precise' keyword, and expressions it affects
577 bool explicitInterp : 1;
578 bool pervertexNV : 1;
579 bool perPrimitiveNV : 1;
589 bool devicecoherent : 1;
590 bool queuefamilycoherent : 1;
591 bool workgroupcoherent : 1;
592 bool subgroupcoherent : 1;
594 bool isWriteOnly() const { return writeonly; }
595 bool isReadOnly() const { return readonly; }
596 bool isRestrict() const { return restrict; }
597 bool isCoherent() const { return coherent; }
598 bool isVolatile() const { return volatil; }
599 bool isSample() const { return sample; }
600 bool isMemory() const
602 return subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly || nonprivate;
604 bool isMemoryQualifierImageAndSSBOOnly() const
606 return subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly;
608 bool bufferReferenceNeedsVulkanMemoryModel() const
610 // include qualifiers that map to load/store availability/visibility/nonprivate memory access operands
611 return subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || nonprivate;
613 bool isInterpolation() const
615 return flat || smooth || nopersp || explicitInterp;
617 bool isExplicitInterpolation() const
619 return explicitInterp;
621 bool isAuxiliary() const
623 return centroid || patch || sample || pervertexNV;
625 bool isPatch() const { return patch; }
626 bool isNoContraction() const { return noContraction; }
627 void setNoContraction() { noContraction = true; }
628 bool isPervertexNV() const { return pervertexNV; }
631 bool isPipeInput() const
646 bool isPipeOutput() const
661 bool isParamInput() const
666 case EvqConstReadOnly:
673 bool isParamOutput() const
684 bool isUniformOrBuffer() const
718 // non-built-in symbols that might link between compilation units
719 bool isLinkable() const
735 bool isPerView() const { return false; }
736 bool isTaskMemory() const { return false; }
737 bool isArrayedIo(EShLanguage language) const { return false; }
739 bool isPerPrimitive() const { return perPrimitiveNV; }
740 bool isPerView() const { return perViewNV; }
741 bool isTaskMemory() const { return perTaskNV; }
743 // True if this type of IO is supposed to be arrayed with extra level for per-vertex data
744 bool isArrayedIo(EShLanguage language) const
747 case EShLangGeometry:
748 return isPipeInput();
749 case EShLangTessControl:
750 return ! patch && (isPipeInput() || isPipeOutput());
751 case EShLangTessEvaluation:
752 return ! patch && isPipeInput();
753 case EShLangFragment:
754 return pervertexNV && isPipeInput();
756 return ! perTaskNV && isPipeOutput();
764 // Implementing an embedded layout-qualifier class here, since C++ can't have a real class bitfield
765 void clearLayout() // all layout
767 clearUniformLayout();
770 layoutPushConstant = false;
771 layoutBufferReference = false;
772 layoutPassthrough = false;
773 layoutViewportRelative = false;
774 // -2048 as the default value indicating layoutSecondaryViewportRelative is not set
775 layoutSecondaryViewportRelativeOffset = -2048;
776 layoutShaderRecordNV = false;
777 layoutBufferReferenceAlign = layoutBufferReferenceAlignEnd;
778 layoutFormat = ElfNone;
781 clearInterstageLayout();
783 layoutSpecConstantId = layoutSpecConstantIdEnd;
785 void clearInterstageLayout()
787 layoutLocation = layoutLocationEnd;
788 layoutComponent = layoutComponentEnd;
790 layoutIndex = layoutIndexEnd;
797 void clearStreamLayout()
799 layoutStream = layoutStreamEnd;
801 void clearXfbLayout()
803 layoutXfbBuffer = layoutXfbBufferEnd;
804 layoutXfbStride = layoutXfbStrideEnd;
805 layoutXfbOffset = layoutXfbOffsetEnd;
809 bool hasNonXfbLayout() const
811 return hasUniformLayout() ||
815 isShaderRecordNV() ||
817 hasBufferReference();
819 bool hasLayout() const
821 return hasNonXfbLayout() ||
824 TLayoutMatrix layoutMatrix : 3;
825 TLayoutPacking layoutPacking : 4;
829 unsigned int layoutLocation : 12;
830 static const unsigned int layoutLocationEnd = 0xFFF;
832 unsigned int layoutComponent : 3;
833 static const unsigned int layoutComponentEnd = 4;
835 unsigned int layoutSet : 7;
836 static const unsigned int layoutSetEnd = 0x3F;
838 unsigned int layoutBinding : 16;
839 static const unsigned int layoutBindingEnd = 0xFFFF;
841 unsigned int layoutIndex : 8;
842 static const unsigned int layoutIndexEnd = 0xFF;
844 unsigned int layoutStream : 8;
845 static const unsigned int layoutStreamEnd = 0xFF;
847 unsigned int layoutXfbBuffer : 4;
848 static const unsigned int layoutXfbBufferEnd = 0xF;
850 unsigned int layoutXfbStride : 14;
851 static const unsigned int layoutXfbStrideEnd = 0x3FFF;
853 unsigned int layoutXfbOffset : 13;
854 static const unsigned int layoutXfbOffsetEnd = 0x1FFF;
856 unsigned int layoutAttachment : 8; // for input_attachment_index
857 static const unsigned int layoutAttachmentEnd = 0XFF;
859 unsigned int layoutSpecConstantId : 11;
860 static const unsigned int layoutSpecConstantIdEnd = 0x7FF;
863 // stored as log2 of the actual alignment value
864 unsigned int layoutBufferReferenceAlign : 6;
865 static const unsigned int layoutBufferReferenceAlignEnd = 0x3F;
867 TLayoutFormat layoutFormat : 8;
869 bool layoutPushConstant;
870 bool layoutBufferReference;
871 bool layoutPassthrough;
872 bool layoutViewportRelative;
873 int layoutSecondaryViewportRelativeOffset;
874 bool layoutShaderRecordNV;
877 bool hasUniformLayout() const
879 return hasMatrix() ||
886 void clearUniformLayout() // only uniform specific
888 layoutMatrix = ElmNone;
889 layoutPacking = ElpNone;
890 layoutOffset = layoutNotSet;
891 layoutAlign = layoutNotSet;
893 layoutSet = layoutSetEnd;
894 layoutBinding = layoutBindingEnd;
896 layoutAttachment = layoutAttachmentEnd;
900 bool hasMatrix() const
902 return layoutMatrix != ElmNone;
904 bool hasPacking() const
906 return layoutPacking != ElpNone;
908 bool hasAlign() const
910 return layoutAlign != layoutNotSet;
912 bool hasAnyLocation() const
914 return hasLocation() ||
918 bool hasLocation() const
920 return layoutLocation != layoutLocationEnd;
924 return layoutSet != layoutSetEnd;
926 bool hasBinding() const
928 return layoutBinding != layoutBindingEnd;
931 bool hasOffset() const { return false; }
932 bool isNonPerspective() const { return false; }
933 bool hasIndex() const { return false; }
934 unsigned getIndex() const { return 0; }
935 bool hasComponent() const { return false; }
936 bool hasStream() const { return false; }
937 bool hasFormat() const { return false; }
938 bool hasXfb() const { return false; }
939 bool hasXfbBuffer() const { return false; }
940 bool hasXfbStride() const { return false; }
941 bool hasXfbOffset() const { return false; }
942 bool hasAttachment() const { return false; }
943 TLayoutFormat getFormat() const { return ElfNone; }
944 bool isPushConstant() const { return false; }
945 bool isShaderRecordNV() const { return false; }
946 bool hasBufferReference() const { return false; }
947 bool hasBufferReferenceAlign() const { return false; }
948 bool isNonUniform() const { return false; }
950 bool hasOffset() const
952 return layoutOffset != layoutNotSet;
954 bool isNonPerspective() const { return nopersp; }
955 bool hasIndex() const
957 return layoutIndex != layoutIndexEnd;
959 unsigned getIndex() const { return layoutIndex; }
960 bool hasComponent() const
962 return layoutComponent != layoutComponentEnd;
964 bool hasStream() const
966 return layoutStream != layoutStreamEnd;
968 bool hasFormat() const
970 return layoutFormat != ElfNone;
974 return hasXfbBuffer() ||
978 bool hasXfbBuffer() const
980 return layoutXfbBuffer != layoutXfbBufferEnd;
982 bool hasXfbStride() const
984 return layoutXfbStride != layoutXfbStrideEnd;
986 bool hasXfbOffset() const
988 return layoutXfbOffset != layoutXfbOffsetEnd;
990 bool hasAttachment() const
992 return layoutAttachment != layoutAttachmentEnd;
994 TLayoutFormat getFormat() const { return layoutFormat; }
995 bool isPushConstant() const { return layoutPushConstant; }
996 bool isShaderRecordNV() const { return layoutShaderRecordNV; }
997 bool hasBufferReference() const { return layoutBufferReference; }
998 bool hasBufferReferenceAlign() const
1000 return layoutBufferReferenceAlign != layoutBufferReferenceAlignEnd;
1002 bool isNonUniform() const
1007 bool hasSpecConstantId() const
1009 // Not the same thing as being a specialization constant, this
1010 // is just whether or not it was declared with an ID.
1011 return layoutSpecConstantId != layoutSpecConstantIdEnd;
1013 bool isSpecConstant() const
1015 // True if type is a specialization constant, whether or not it
1016 // had a specialization-constant ID, and false if it is not a
1017 // true front-end constant.
1018 return specConstant;
1020 bool isFrontEndConstant() const
1022 // True if the front-end knows the final constant value.
1023 // This allows front-end constant folding.
1024 return storage == EvqConst && ! specConstant;
1026 bool isConstant() const
1028 // True if is either kind of constant; specialization or regular.
1029 return isFrontEndConstant() || isSpecConstant();
1031 void makeSpecConstant()
1034 specConstant = true;
1036 static const char* getLayoutPackingString(TLayoutPacking packing)
1039 case ElpStd140: return "std140";
1041 case ElpPacked: return "packed";
1042 case ElpShared: return "shared";
1043 case ElpStd430: return "std430";
1044 case ElpScalar: return "scalar";
1046 default: return "none";
1049 static const char* getLayoutMatrixString(TLayoutMatrix m)
1052 case ElmColumnMajor: return "column_major";
1053 case ElmRowMajor: return "row_major";
1054 default: return "none";
1058 static const char* getLayoutFormatString(TLayoutFormat f) { return "none"; }
1060 static const char* getLayoutFormatString(TLayoutFormat f)
1063 case ElfRgba32f: return "rgba32f";
1064 case ElfRgba16f: return "rgba16f";
1065 case ElfRg32f: return "rg32f";
1066 case ElfRg16f: return "rg16f";
1067 case ElfR11fG11fB10f: return "r11f_g11f_b10f";
1068 case ElfR32f: return "r32f";
1069 case ElfR16f: return "r16f";
1070 case ElfRgba16: return "rgba16";
1071 case ElfRgb10A2: return "rgb10_a2";
1072 case ElfRgba8: return "rgba8";
1073 case ElfRg16: return "rg16";
1074 case ElfRg8: return "rg8";
1075 case ElfR16: return "r16";
1076 case ElfR8: return "r8";
1077 case ElfRgba16Snorm: return "rgba16_snorm";
1078 case ElfRgba8Snorm: return "rgba8_snorm";
1079 case ElfRg16Snorm: return "rg16_snorm";
1080 case ElfRg8Snorm: return "rg8_snorm";
1081 case ElfR16Snorm: return "r16_snorm";
1082 case ElfR8Snorm: return "r8_snorm";
1084 case ElfRgba32i: return "rgba32i";
1085 case ElfRgba16i: return "rgba16i";
1086 case ElfRgba8i: return "rgba8i";
1087 case ElfRg32i: return "rg32i";
1088 case ElfRg16i: return "rg16i";
1089 case ElfRg8i: return "rg8i";
1090 case ElfR32i: return "r32i";
1091 case ElfR16i: return "r16i";
1092 case ElfR8i: return "r8i";
1094 case ElfRgba32ui: return "rgba32ui";
1095 case ElfRgba16ui: return "rgba16ui";
1096 case ElfRgba8ui: return "rgba8ui";
1097 case ElfRg32ui: return "rg32ui";
1098 case ElfRg16ui: return "rg16ui";
1099 case ElfRgb10a2ui: return "rgb10_a2ui";
1100 case ElfRg8ui: return "rg8ui";
1101 case ElfR32ui: return "r32ui";
1102 case ElfR16ui: return "r16ui";
1103 case ElfR8ui: return "r8ui";
1104 default: return "none";
1107 static const char* getLayoutDepthString(TLayoutDepth d)
1110 case EldAny: return "depth_any";
1111 case EldGreater: return "depth_greater";
1112 case EldLess: return "depth_less";
1113 case EldUnchanged: return "depth_unchanged";
1114 default: return "none";
1117 static const char* getBlendEquationString(TBlendEquationShift e)
1120 case EBlendMultiply: return "blend_support_multiply";
1121 case EBlendScreen: return "blend_support_screen";
1122 case EBlendOverlay: return "blend_support_overlay";
1123 case EBlendDarken: return "blend_support_darken";
1124 case EBlendLighten: return "blend_support_lighten";
1125 case EBlendColordodge: return "blend_support_colordodge";
1126 case EBlendColorburn: return "blend_support_colorburn";
1127 case EBlendHardlight: return "blend_support_hardlight";
1128 case EBlendSoftlight: return "blend_support_softlight";
1129 case EBlendDifference: return "blend_support_difference";
1130 case EBlendExclusion: return "blend_support_exclusion";
1131 case EBlendHslHue: return "blend_support_hsl_hue";
1132 case EBlendHslSaturation: return "blend_support_hsl_saturation";
1133 case EBlendHslColor: return "blend_support_hsl_color";
1134 case EBlendHslLuminosity: return "blend_support_hsl_luminosity";
1135 case EBlendAllEquations: return "blend_support_all_equations";
1136 default: return "unknown";
1139 static const char* getGeometryString(TLayoutGeometry geometry)
1142 case ElgPoints: return "points";
1143 case ElgLines: return "lines";
1144 case ElgLinesAdjacency: return "lines_adjacency";
1145 case ElgLineStrip: return "line_strip";
1146 case ElgTriangles: return "triangles";
1147 case ElgTrianglesAdjacency: return "triangles_adjacency";
1148 case ElgTriangleStrip: return "triangle_strip";
1149 case ElgQuads: return "quads";
1150 case ElgIsolines: return "isolines";
1151 default: return "none";
1154 static const char* getVertexSpacingString(TVertexSpacing spacing)
1157 case EvsEqual: return "equal_spacing";
1158 case EvsFractionalEven: return "fractional_even_spacing";
1159 case EvsFractionalOdd: return "fractional_odd_spacing";
1160 default: return "none";
1163 static const char* getVertexOrderString(TVertexOrder order)
1166 case EvoCw: return "cw";
1167 case EvoCcw: return "ccw";
1168 default: return "none";
1171 static int mapGeometryToSize(TLayoutGeometry geometry)
1174 case ElgPoints: return 1;
1175 case ElgLines: return 2;
1176 case ElgLinesAdjacency: return 4;
1177 case ElgTriangles: return 3;
1178 case ElgTrianglesAdjacency: return 6;
1182 static const char* getInterlockOrderingString(TInterlockOrdering order)
1185 case EioPixelInterlockOrdered: return "pixel_interlock_ordered";
1186 case EioPixelInterlockUnordered: return "pixel_interlock_unordered";
1187 case EioSampleInterlockOrdered: return "sample_interlock_ordered";
1188 case EioSampleInterlockUnordered: return "sample_interlock_unordered";
1189 case EioShadingRateInterlockOrdered: return "shading_rate_interlock_ordered";
1190 case EioShadingRateInterlockUnordered: return "shading_rate_interlock_unordered";
1191 default: return "none";
1197 // Qualifiers that don't need to be keep per object. They have shader scope, not object scope.
1198 // So, they will not be part of TType, TQualifier, etc.
1199 struct TShaderQualifiers {
1200 TLayoutGeometry geometry; // geometry/tessellation shader in/out primitives
1201 bool pixelCenterInteger; // fragment shader
1202 bool originUpperLeft; // fragment shader
1204 int vertices; // for tessellation "vertices", geometry & mesh "max_vertices"
1205 TVertexSpacing spacing;
1208 int localSize[3]; // compute shader
1209 bool localSizeNotDefault[3]; // compute shader
1210 int localSizeSpecId[3]; // compute shader specialization id for gl_WorkGroupSize
1212 bool earlyFragmentTests; // fragment input
1213 bool postDepthCoverage; // fragment input
1214 TLayoutDepth layoutDepth;
1215 bool blendEquation; // true if any blend equation was specified
1216 int numViews; // multiview extenstions
1217 TInterlockOrdering interlockOrdering;
1218 bool layoutOverrideCoverage; // true if layout override_coverage set
1219 bool layoutDerivativeGroupQuads; // true if layout derivative_group_quadsNV set
1220 bool layoutDerivativeGroupLinear; // true if layout derivative_group_linearNV set
1221 int primitives; // mesh shader "max_primitives"DerivativeGroupLinear; // true if layout derivative_group_linearNV set
1222 TLayoutDepth getDepth() const { return layoutDepth; }
1224 TLayoutDepth getDepth() const { return EldNone; }
1230 originUpperLeft = false;
1231 pixelCenterInteger = false;
1232 invocations = TQualifier::layoutNotSet;
1233 vertices = TQualifier::layoutNotSet;
1240 localSizeNotDefault[0] = false;
1241 localSizeNotDefault[1] = false;
1242 localSizeNotDefault[2] = false;
1243 localSizeSpecId[0] = TQualifier::layoutNotSet;
1244 localSizeSpecId[1] = TQualifier::layoutNotSet;
1245 localSizeSpecId[2] = TQualifier::layoutNotSet;
1247 earlyFragmentTests = false;
1248 postDepthCoverage = false;
1249 layoutDepth = EldNone;
1250 blendEquation = false;
1251 numViews = TQualifier::layoutNotSet;
1252 layoutOverrideCoverage = false;
1253 layoutDerivativeGroupQuads = false;
1254 layoutDerivativeGroupLinear = false;
1255 primitives = TQualifier::layoutNotSet;
1256 interlockOrdering = EioNone;
1261 bool hasBlendEquation() const { return false; }
1263 bool hasBlendEquation() const { return blendEquation; }
1266 // Merge in characteristics from the 'src' qualifier. They can override when
1267 // set, but never erase when not set.
1268 void merge(const TShaderQualifiers& src)
1270 if (src.geometry != ElgNone)
1271 geometry = src.geometry;
1272 if (src.pixelCenterInteger)
1273 pixelCenterInteger = src.pixelCenterInteger;
1274 if (src.originUpperLeft)
1275 originUpperLeft = src.originUpperLeft;
1276 if (src.invocations != TQualifier::layoutNotSet)
1277 invocations = src.invocations;
1278 if (src.vertices != TQualifier::layoutNotSet)
1279 vertices = src.vertices;
1280 if (src.spacing != EvsNone)
1281 spacing = src.spacing;
1282 if (src.order != EvoNone)
1286 for (int i = 0; i < 3; ++i) {
1287 if (src.localSize[i] > 1)
1288 localSize[i] = src.localSize[i];
1290 for (int i = 0; i < 3; ++i) {
1291 localSizeNotDefault[i] = src.localSizeNotDefault[i] || localSizeNotDefault[i];
1293 for (int i = 0; i < 3; ++i) {
1294 if (src.localSizeSpecId[i] != TQualifier::layoutNotSet)
1295 localSizeSpecId[i] = src.localSizeSpecId[i];
1298 if (src.earlyFragmentTests)
1299 earlyFragmentTests = true;
1300 if (src.postDepthCoverage)
1301 postDepthCoverage = true;
1302 if (src.layoutDepth)
1303 layoutDepth = src.layoutDepth;
1304 if (src.blendEquation)
1305 blendEquation = src.blendEquation;
1306 if (src.numViews != TQualifier::layoutNotSet)
1307 numViews = src.numViews;
1308 if (src.layoutOverrideCoverage)
1309 layoutOverrideCoverage = src.layoutOverrideCoverage;
1310 if (src.layoutDerivativeGroupQuads)
1311 layoutDerivativeGroupQuads = src.layoutDerivativeGroupQuads;
1312 if (src.layoutDerivativeGroupLinear)
1313 layoutDerivativeGroupLinear = src.layoutDerivativeGroupLinear;
1314 if (src.primitives != TQualifier::layoutNotSet)
1315 primitives = src.primitives;
1316 if (src.interlockOrdering != EioNone)
1317 interlockOrdering = src.interlockOrdering;
1323 // TPublicType is just temporarily used while parsing and not quite the same
1324 // information kept per node in TType. Due to the bison stack, it can't have
1325 // types that it thinks have non-trivial constructors. It should
1326 // just be used while recognizing the grammar, not anything else.
1327 // Once enough is known about the situation, the proper information
1328 // moved into a TType, or the parse context, etc.
1332 TBasicType basicType;
1334 TQualifier qualifier;
1335 TShaderQualifiers shaderQualifiers;
1340 TArraySizes* arraySizes;
1341 const TType* userDef;
1343 TArraySizes* typeParameters;
1346 bool isCoopmat() const { return false; }
1348 bool isCoopmat() const { return coopmat; }
1351 void initType(const TSourceLoc& l)
1353 basicType = EbtVoid;
1357 arraySizes = nullptr;
1360 typeParameters = nullptr;
1364 void initQualifiers(bool global = false)
1368 qualifier.storage = EvqGlobal;
1371 void init(const TSourceLoc& l, bool global = false)
1375 initQualifiers(global);
1376 shaderQualifiers.init();
1379 void setVector(int s)
1386 void setMatrix(int c, int r)
1393 bool isScalar() const
1395 return matrixCols == 0 && vectorSize == 1 && arraySizes == nullptr && userDef == nullptr;
1398 // "Image" is a superset of "Subpass"
1399 bool isImage() const { return basicType == EbtSampler && sampler.isImage(); }
1400 bool isSubpass() const { return basicType == EbtSampler && sampler.isSubpass(); }
1404 // Base class for things that have a type.
1408 POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
1410 // for "empty" type (no args) or simple scalar/vector/matrix
1411 explicit TType(TBasicType t = EbtVoid, TStorageQualifier q = EvqTemporary, int vs = 1, int mc = 0, int mr = 0,
1412 bool isVector = false) :
1413 basicType(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), vector1(isVector && vs == 1), coopmat(false),
1414 arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(nullptr)
1418 qualifier.storage = q;
1419 assert(!(isMatrix() && vectorSize != 0)); // prevent vectorSize != 0 on matrices
1421 // for explicit precision qualifier
1422 TType(TBasicType t, TStorageQualifier q, TPrecisionQualifier p, int vs = 1, int mc = 0, int mr = 0,
1423 bool isVector = false) :
1424 basicType(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), vector1(isVector && vs == 1), coopmat(false),
1425 arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(nullptr)
1429 qualifier.storage = q;
1430 qualifier.precision = p;
1431 assert(p >= EpqNone && p <= EpqHigh);
1432 assert(!(isMatrix() && vectorSize != 0)); // prevent vectorSize != 0 on matrices
1434 // for turning a TPublicType into a TType, using a shallow copy
1435 explicit TType(const TPublicType& p) :
1436 basicType(p.basicType),
1437 vectorSize(p.vectorSize), matrixCols(p.matrixCols), matrixRows(p.matrixRows), vector1(false), coopmat(p.coopmat),
1438 arraySizes(p.arraySizes), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(p.typeParameters)
1440 if (basicType == EbtSampler)
1441 sampler = p.sampler;
1444 qualifier = p.qualifier;
1446 if (p.userDef->basicType == EbtReference) {
1447 basicType = EbtReference;
1448 referentType = p.userDef->referentType;
1450 structure = p.userDef->getWritableStruct(); // public type is short-lived; there are no sharing issues
1452 typeName = NewPoolTString(p.userDef->getTypeName().c_str());
1454 if (p.isCoopmat() && p.typeParameters && p.typeParameters->getNumDims() > 0) {
1455 int numBits = p.typeParameters->getDimSize(0);
1456 if (p.basicType == EbtFloat && numBits == 16) {
1457 basicType = EbtFloat16;
1458 qualifier.precision = EpqNone;
1459 } else if (p.basicType == EbtUint && numBits == 8) {
1460 basicType = EbtUint8;
1461 qualifier.precision = EpqNone;
1462 } else if (p.basicType == EbtInt && numBits == 8) {
1463 basicType = EbtInt8;
1464 qualifier.precision = EpqNone;
1468 // for construction of sampler types
1469 TType(const TSampler& sampler, TStorageQualifier q = EvqUniform, TArraySizes* as = nullptr) :
1470 basicType(EbtSampler), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmat(false),
1471 arraySizes(as), structure(nullptr), fieldName(nullptr), typeName(nullptr),
1472 sampler(sampler), typeParameters(nullptr)
1475 qualifier.storage = q;
1477 // to efficiently make a dereferenced type
1478 // without ever duplicating the outer structure that will be thrown away
1479 // and using only shallow copy
1480 TType(const TType& type, int derefIndex, bool rowMajor = false)
1482 if (type.isArray()) {
1484 if (type.getArraySizes()->getNumDims() == 1) {
1485 arraySizes = nullptr;
1487 // want our own copy of the array, so we can edit it
1488 arraySizes = new TArraySizes;
1489 arraySizes->copyDereferenced(*type.arraySizes);
1491 } else if (type.basicType == EbtStruct || type.basicType == EbtBlock) {
1492 // do a structure dereference
1493 const TTypeList& memberList = *type.getStruct();
1494 shallowCopy(*memberList[derefIndex].type);
1497 // do a vector/matrix dereference
1499 if (matrixCols > 0) {
1500 // dereference from matrix to vector
1502 vectorSize = matrixCols;
1504 vectorSize = matrixRows;
1507 if (vectorSize == 1)
1509 } else if (isVector()) {
1510 // dereference from vector to scalar
1513 } else if (isCoopMat()) {
1515 typeParameters = nullptr;
1519 // for making structures, ...
1520 TType(TTypeList* userDef, const TString& n) :
1521 basicType(EbtStruct), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmat(false),
1522 arraySizes(nullptr), structure(userDef), fieldName(nullptr), typeParameters(nullptr)
1526 typeName = NewPoolTString(n.c_str());
1528 // For interface blocks
1529 TType(TTypeList* userDef, const TString& n, const TQualifier& q) :
1530 basicType(EbtBlock), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmat(false),
1531 qualifier(q), arraySizes(nullptr), structure(userDef), fieldName(nullptr), typeParameters(nullptr)
1534 typeName = NewPoolTString(n.c_str());
1536 // for block reference (first parameter must be EbtReference)
1537 explicit TType(TBasicType t, const TType &p, const TString& n) :
1538 basicType(t), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false),
1539 arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr)
1541 assert(t == EbtReference);
1542 typeName = NewPoolTString(n.c_str());
1544 qualifier.storage = p.qualifier.storage;
1545 referentType = p.clone();
1549 // Not for use across pool pops; it will cause multiple instances of TType to point to the same information.
1550 // This only works if that information (like a structure's list of types) does not change and
1551 // the instances are sharing the same pool.
1552 void shallowCopy(const TType& copyOf)
1554 basicType = copyOf.basicType;
1555 sampler = copyOf.sampler;
1556 qualifier = copyOf.qualifier;
1557 vectorSize = copyOf.vectorSize;
1558 matrixCols = copyOf.matrixCols;
1559 matrixRows = copyOf.matrixRows;
1560 vector1 = copyOf.vector1;
1561 arraySizes = copyOf.arraySizes; // copying the pointer only, not the contents
1562 fieldName = copyOf.fieldName;
1563 typeName = copyOf.typeName;
1565 structure = copyOf.structure;
1567 referentType = copyOf.referentType;
1569 typeParameters = copyOf.typeParameters;
1570 coopmat = copyOf.isCoopMat();
1573 // Make complete copy of the whole type graph rooted at 'copyOf'.
1574 void deepCopy(const TType& copyOf)
1576 TMap<TTypeList*,TTypeList*> copied; // to enable copying a type graph as a graph, not a tree
1577 deepCopy(copyOf, copied);
1580 // Recursively make temporary
1581 void makeTemporary()
1583 getQualifier().makeTemporary();
1586 for (unsigned int i = 0; i < structure->size(); ++i)
1587 (*structure)[i].type->makeTemporary();
1590 TType* clone() const
1592 TType *newType = new TType();
1593 newType->deepCopy(*this);
1598 void makeVector() { vector1 = true; }
1600 virtual void hideMember() { basicType = EbtVoid; vectorSize = 1; }
1601 virtual bool hiddenMember() const { return basicType == EbtVoid; }
1603 virtual void setFieldName(const TString& n) { fieldName = NewPoolTString(n.c_str()); }
1604 virtual const TString& getTypeName() const
1610 virtual const TString& getFieldName() const
1616 virtual TBasicType getBasicType() const { return basicType; }
1617 virtual const TSampler& getSampler() const { return sampler; }
1618 virtual TSampler& getSampler() { return sampler; }
1620 virtual TQualifier& getQualifier() { return qualifier; }
1621 virtual const TQualifier& getQualifier() const { return qualifier; }
1623 virtual int getVectorSize() const { return vectorSize; } // returns 1 for either scalar or vector of size 1, valid for both
1624 virtual int getMatrixCols() const { return matrixCols; }
1625 virtual int getMatrixRows() const { return matrixRows; }
1626 virtual int getOuterArraySize() const { return arraySizes->getOuterSize(); }
1627 virtual TIntermTyped* getOuterArrayNode() const { return arraySizes->getOuterNode(); }
1628 virtual int getCumulativeArraySize() const { return arraySizes->getCumulativeSize(); }
1630 bool isArrayOfArrays() const { return false; }
1632 bool isArrayOfArrays() const { return arraySizes != nullptr && arraySizes->getNumDims() > 1; }
1634 virtual int getImplicitArraySize() const { return arraySizes->getImplicitSize(); }
1635 virtual const TArraySizes* getArraySizes() const { return arraySizes; }
1636 virtual TArraySizes* getArraySizes() { return arraySizes; }
1637 virtual TType* getReferentType() const { return referentType; }
1638 virtual const TArraySizes* getTypeParameters() const { return typeParameters; }
1639 virtual TArraySizes* getTypeParameters() { return typeParameters; }
1641 virtual bool isScalar() const { return ! isVector() && ! isMatrix() && ! isStruct() && ! isArray(); }
1642 virtual bool isScalarOrVec1() const { return isScalar() || vector1; }
1643 virtual bool isVector() const { return vectorSize > 1 || vector1; }
1644 virtual bool isMatrix() const { return matrixCols ? true : false; }
1645 virtual bool isArray() const { return arraySizes != nullptr; }
1646 virtual bool isSizedArray() const { return isArray() && arraySizes->isSized(); }
1647 virtual bool isUnsizedArray() const { return isArray() && !arraySizes->isSized(); }
1648 virtual bool isArrayVariablyIndexed() const { assert(isArray()); return arraySizes->isVariablyIndexed(); }
1649 virtual void setArrayVariablyIndexed() { assert(isArray()); arraySizes->setVariablyIndexed(); }
1650 virtual void updateImplicitArraySize(int size) { assert(isArray()); arraySizes->updateImplicitSize(size); }
1651 virtual bool isStruct() const { return basicType == EbtStruct || basicType == EbtBlock; }
1652 virtual bool isFloatingDomain() const { return basicType == EbtFloat || basicType == EbtDouble || basicType == EbtFloat16; }
1653 virtual bool isIntegerDomain() const
1655 switch (basicType) {
1671 virtual bool isOpaque() const { return basicType == EbtSampler
1673 || basicType == EbtAtomicUint || basicType == EbtAccStructNV
1676 virtual bool isBuiltIn() const { return getQualifier().builtIn != EbvNone; }
1678 // "Image" is a superset of "Subpass"
1679 virtual bool isImage() const { return basicType == EbtSampler && getSampler().isImage(); }
1680 virtual bool isSubpass() const { return basicType == EbtSampler && getSampler().isSubpass(); }
1681 virtual bool isTexture() const { return basicType == EbtSampler && getSampler().isTexture(); }
1682 // Check the block-name convention of creating a block without populating it's members:
1683 virtual bool isUnusableName() const { return isStruct() && structure == nullptr; }
1684 virtual bool isParameterized() const { return typeParameters != nullptr; }
1686 bool isAtomic() const { return false; }
1687 bool isCoopMat() const { return false; }
1688 bool isReference() const { return false; }
1690 bool isAtomic() const { return basicType == EbtAtomicUint; }
1691 bool isCoopMat() const { return coopmat; }
1692 bool isReference() const { return getBasicType() == EbtReference; }
1695 // return true if this type contains any subtype which satisfies the given predicate.
1696 template <typename P>
1697 bool contains(P predicate) const
1699 if (predicate(this))
1702 const auto hasa = [predicate](const TTypeLoc& tl) { return tl.type->contains(predicate); };
1704 return isStruct() && std::any_of(structure->begin(), structure->end(), hasa);
1707 // Recursively checks if the type contains the given basic type
1708 virtual bool containsBasicType(TBasicType checkType) const
1710 return contains([checkType](const TType* t) { return t->basicType == checkType; } );
1713 // Recursively check the structure for any arrays, needed for some error checks
1714 virtual bool containsArray() const
1716 return contains([](const TType* t) { return t->isArray(); } );
1719 // Check the structure for any structures, needed for some error checks
1720 virtual bool containsStructure() const
1722 return contains([this](const TType* t) { return t != this && t->isStruct(); } );
1725 // Recursively check the structure for any unsized arrays, needed for triggering a copyUp().
1726 virtual bool containsUnsizedArray() const
1728 return contains([](const TType* t) { return t->isUnsizedArray(); } );
1731 virtual bool containsOpaque() const
1733 return contains([](const TType* t) { return t->isOpaque(); } );
1736 // Recursively checks if the type contains a built-in variable
1737 virtual bool containsBuiltIn() const
1739 return contains([](const TType* t) { return t->isBuiltIn(); } );
1742 virtual bool containsNonOpaque() const
1744 const auto nonOpaque = [](const TType* t) {
1745 switch (t->basicType) {
1766 return contains(nonOpaque);
1769 virtual bool containsSpecializationSize() const
1771 return contains([](const TType* t) { return t->isArray() && t->arraySizes->isOuterSpecialization(); } );
1775 bool containsDouble() const { return false; }
1776 bool contains16BitFloat() const { return false; }
1777 bool contains64BitInt() const { return false; }
1778 bool contains16BitInt() const { return false; }
1779 bool contains8BitInt() const { return false; }
1780 bool containsCoopMat() const { return false; }
1781 bool containsReference() const { return false; }
1783 bool containsDouble() const
1785 return containsBasicType(EbtDouble);
1787 bool contains16BitFloat() const
1789 return containsBasicType(EbtFloat16);
1791 bool contains64BitInt() const
1793 return containsBasicType(EbtInt64) || containsBasicType(EbtUint64);
1795 bool contains16BitInt() const
1797 return containsBasicType(EbtInt16) || containsBasicType(EbtUint16);
1799 bool contains8BitInt() const
1801 return containsBasicType(EbtInt8) || containsBasicType(EbtUint8);
1803 bool containsCoopMat() const
1805 return contains([](const TType* t) { return t->coopmat; } );
1807 bool containsReference() const
1809 return containsBasicType(EbtReference);
1813 // Array editing methods. Array descriptors can be shared across
1814 // type instances. This allows all uses of the same array
1815 // to be updated at once. E.g., all nodes can be explicitly sized
1816 // by tracking and correcting one implicit size. Or, all nodes
1817 // can get the explicit size on a redeclaration that gives size.
1819 // N.B.: Don't share with the shared symbol tables (symbols are
1820 // marked as isReadOnly(). Such symbols with arrays that will be
1821 // edited need to copyUp() on first use, so that
1822 // A) the edits don't effect the shared symbol table, and
1823 // B) the edits are shared across all users.
1824 void updateArraySizes(const TType& type)
1826 // For when we may already be sharing existing array descriptors,
1827 // keeping the pointers the same, just updating the contents.
1828 assert(arraySizes != nullptr);
1829 assert(type.arraySizes != nullptr);
1830 *arraySizes = *type.arraySizes;
1832 void copyArraySizes(const TArraySizes& s)
1834 // For setting a fresh new set of array sizes, not yet worrying about sharing.
1835 arraySizes = new TArraySizes;
1838 void transferArraySizes(TArraySizes* s)
1840 // For setting an already allocated set of sizes that this type can use
1844 void clearArraySizes()
1846 arraySizes = nullptr;
1849 // Add inner array sizes, to any existing sizes, via copy; the
1850 // sizes passed in can still be reused for other purposes.
1851 void copyArrayInnerSizes(const TArraySizes* s)
1854 if (arraySizes == nullptr)
1857 arraySizes->addInnerSizes(*s);
1860 void changeOuterArraySize(int s) { arraySizes->changeOuterSize(s); }
1862 // Recursively make the implicit array size the explicit array size.
1863 // Expicit arrays are compile-time or link-time sized, never run-time sized.
1864 // Sometimes, policy calls for an array to be run-time sized even if it was
1865 // never variably indexed: Don't turn a 'skipNonvariablyIndexed' array into
1866 // an explicit array.
1867 void adoptImplicitArraySizes(bool skipNonvariablyIndexed)
1869 if (isUnsizedArray() && !(skipNonvariablyIndexed || isArrayVariablyIndexed()))
1870 changeOuterArraySize(getImplicitArraySize());
1871 // For multi-dim per-view arrays, set unsized inner dimension size to 1
1872 if (qualifier.isPerView() && arraySizes && arraySizes->isInnerUnsized())
1873 arraySizes->clearInnerUnsized();
1874 if (isStruct() && structure->size() > 0) {
1875 int lastMember = (int)structure->size() - 1;
1876 for (int i = 0; i < lastMember; ++i)
1877 (*structure)[i].type->adoptImplicitArraySizes(false);
1878 // implement the "last member of an SSBO" policy
1879 (*structure)[lastMember].type->adoptImplicitArraySizes(getQualifier().storage == EvqBuffer);
1884 void updateTypeParameters(const TType& type)
1886 // For when we may already be sharing existing array descriptors,
1887 // keeping the pointers the same, just updating the contents.
1888 assert(typeParameters != nullptr);
1889 assert(type.typeParameters != nullptr);
1890 *typeParameters = *type.typeParameters;
1892 void copyTypeParameters(const TArraySizes& s)
1894 // For setting a fresh new set of type parameters, not yet worrying about sharing.
1895 typeParameters = new TArraySizes;
1896 *typeParameters = s;
1898 void transferTypeParameters(TArraySizes* s)
1900 // For setting an already allocated set of sizes that this type can use
1904 void clearTypeParameters()
1906 typeParameters = nullptr;
1909 // Add inner array sizes, to any existing sizes, via copy; the
1910 // sizes passed in can still be reused for other purposes.
1911 void copyTypeParametersInnerSizes(const TArraySizes* s)
1914 if (typeParameters == nullptr)
1915 copyTypeParameters(*s);
1917 typeParameters->addInnerSizes(*s);
1923 const char* getBasicString() const
1925 return TType::getBasicString(basicType);
1928 static const char* getBasicString(TBasicType t)
1931 case EbtFloat: return "float";
1932 case EbtInt: return "int";
1933 case EbtUint: return "uint";
1934 case EbtSampler: return "sampler/image";
1936 case EbtVoid: return "void";
1937 case EbtDouble: return "double";
1938 case EbtFloat16: return "float16_t";
1939 case EbtInt8: return "int8_t";
1940 case EbtUint8: return "uint8_t";
1941 case EbtInt16: return "int16_t";
1942 case EbtUint16: return "uint16_t";
1943 case EbtInt64: return "int64_t";
1944 case EbtUint64: return "uint64_t";
1945 case EbtBool: return "bool";
1946 case EbtAtomicUint: return "atomic_uint";
1947 case EbtStruct: return "structure";
1948 case EbtBlock: return "block";
1949 case EbtAccStructNV: return "accelerationStructureNV";
1950 case EbtReference: return "reference";
1952 default: return "unknown type";
1957 TString getCompleteString() const { return ""; }
1958 const char* getStorageQualifierString() const { return ""; }
1959 const char* getBuiltInVariableString() const { return ""; }
1960 const char* getPrecisionQualifierString() const { return ""; }
1961 TString getBasicTypeString() const { return ""; }
1963 TString getCompleteString() const
1967 const auto appendStr = [&](const char* s) { typeString.append(s); };
1968 const auto appendUint = [&](unsigned int u) { typeString.append(std::to_string(u).c_str()); };
1969 const auto appendInt = [&](int i) { typeString.append(std::to_string(i).c_str()); };
1971 if (qualifier.hasLayout()) {
1972 // To reduce noise, skip this if the only layout is an xfb_buffer
1973 // with no triggering xfb_offset.
1974 TQualifier noXfbBuffer = qualifier;
1975 noXfbBuffer.layoutXfbBuffer = TQualifier::layoutXfbBufferEnd;
1976 if (noXfbBuffer.hasLayout()) {
1977 appendStr("layout(");
1978 if (qualifier.hasAnyLocation()) {
1979 appendStr(" location=");
1980 appendUint(qualifier.layoutLocation);
1981 if (qualifier.hasComponent()) {
1982 appendStr(" component=");
1983 appendUint(qualifier.layoutComponent);
1985 if (qualifier.hasIndex()) {
1986 appendStr(" index=");
1987 appendUint(qualifier.layoutIndex);
1990 if (qualifier.hasSet()) {
1992 appendUint(qualifier.layoutSet);
1994 if (qualifier.hasBinding()) {
1995 appendStr(" binding=");
1996 appendUint(qualifier.layoutBinding);
1998 if (qualifier.hasStream()) {
1999 appendStr(" stream=");
2000 appendUint(qualifier.layoutStream);
2002 if (qualifier.hasMatrix()) {
2004 appendStr(TQualifier::getLayoutMatrixString(qualifier.layoutMatrix));
2006 if (qualifier.hasPacking()) {
2008 appendStr(TQualifier::getLayoutPackingString(qualifier.layoutPacking));
2010 if (qualifier.hasOffset()) {
2011 appendStr(" offset=");
2012 appendInt(qualifier.layoutOffset);
2014 if (qualifier.hasAlign()) {
2015 appendStr(" align=");
2016 appendInt(qualifier.layoutAlign);
2018 if (qualifier.hasFormat()) {
2020 appendStr(TQualifier::getLayoutFormatString(qualifier.layoutFormat));
2022 if (qualifier.hasXfbBuffer() && qualifier.hasXfbOffset()) {
2023 appendStr(" xfb_buffer=");
2024 appendUint(qualifier.layoutXfbBuffer);
2026 if (qualifier.hasXfbOffset()) {
2027 appendStr(" xfb_offset=");
2028 appendUint(qualifier.layoutXfbOffset);
2030 if (qualifier.hasXfbStride()) {
2031 appendStr(" xfb_stride=");
2032 appendUint(qualifier.layoutXfbStride);
2034 if (qualifier.hasAttachment()) {
2035 appendStr(" input_attachment_index=");
2036 appendUint(qualifier.layoutAttachment);
2038 if (qualifier.hasSpecConstantId()) {
2039 appendStr(" constant_id=");
2040 appendUint(qualifier.layoutSpecConstantId);
2042 if (qualifier.layoutPushConstant)
2043 appendStr(" push_constant");
2044 if (qualifier.layoutBufferReference)
2045 appendStr(" buffer_reference");
2046 if (qualifier.hasBufferReferenceAlign()) {
2047 appendStr(" buffer_reference_align=");
2048 appendUint(1u << qualifier.layoutBufferReferenceAlign);
2051 if (qualifier.layoutPassthrough)
2052 appendStr(" passthrough");
2053 if (qualifier.layoutViewportRelative)
2054 appendStr(" layoutViewportRelative");
2055 if (qualifier.layoutSecondaryViewportRelativeOffset != -2048) {
2056 appendStr(" layoutSecondaryViewportRelativeOffset=");
2057 appendInt(qualifier.layoutSecondaryViewportRelativeOffset);
2059 if (qualifier.layoutShaderRecordNV)
2060 appendStr(" shaderRecordNV");
2066 if (qualifier.invariant)
2067 appendStr(" invariant");
2068 if (qualifier.noContraction)
2069 appendStr(" noContraction");
2070 if (qualifier.centroid)
2071 appendStr(" centroid");
2072 if (qualifier.smooth)
2073 appendStr(" smooth");
2076 if (qualifier.nopersp)
2077 appendStr(" noperspective");
2078 if (qualifier.explicitInterp)
2079 appendStr(" __explicitInterpAMD");
2080 if (qualifier.pervertexNV)
2081 appendStr(" pervertexNV");
2082 if (qualifier.perPrimitiveNV)
2083 appendStr(" perprimitiveNV");
2084 if (qualifier.perViewNV)
2085 appendStr(" perviewNV");
2086 if (qualifier.perTaskNV)
2087 appendStr(" taskNV");
2088 if (qualifier.patch)
2089 appendStr(" patch");
2090 if (qualifier.sample)
2091 appendStr(" sample");
2092 if (qualifier.coherent)
2093 appendStr(" coherent");
2094 if (qualifier.devicecoherent)
2095 appendStr(" devicecoherent");
2096 if (qualifier.queuefamilycoherent)
2097 appendStr(" queuefamilycoherent");
2098 if (qualifier.workgroupcoherent)
2099 appendStr(" workgroupcoherent");
2100 if (qualifier.subgroupcoherent)
2101 appendStr(" subgroupcoherent");
2102 if (qualifier.nonprivate)
2103 appendStr(" nonprivate");
2104 if (qualifier.volatil)
2105 appendStr(" volatile");
2106 if (qualifier.restrict)
2107 appendStr(" restrict");
2108 if (qualifier.readonly)
2109 appendStr(" readonly");
2110 if (qualifier.writeonly)
2111 appendStr(" writeonly");
2112 if (qualifier.specConstant)
2113 appendStr(" specialization-constant");
2114 if (qualifier.nonUniform)
2115 appendStr(" nonuniform");
2117 appendStr(getStorageQualifierString());
2119 for(int i = 0; i < (int)arraySizes->getNumDims(); ++i) {
2120 int size = arraySizes->getDimSize(i);
2121 if (size == UnsizedArraySize && i == 0 && arraySizes->isVariablyIndexed())
2122 appendStr(" runtime-sized array of");
2124 if (size == UnsizedArraySize) {
2125 appendStr(" unsized");
2128 appendInt(arraySizes->getImplicitSize());
2132 appendInt(arraySizes->getDimSize(i));
2134 appendStr("-element array of");
2138 if (isParameterized()) {
2140 for(int i = 0; i < (int)typeParameters->getNumDims(); ++i) {
2141 appendInt(typeParameters->getDimSize(i));
2142 if (i != (int)typeParameters->getNumDims() - 1)
2147 if (qualifier.precision != EpqNone) {
2149 appendStr(getPrecisionQualifierString());
2153 appendInt(matrixCols);
2155 appendInt(matrixRows);
2156 appendStr(" matrix of");
2157 } else if (isVector()) {
2159 appendInt(vectorSize);
2160 appendStr("-component vector of");
2164 typeString.append(getBasicTypeString());
2166 if (qualifier.builtIn != EbvNone) {
2168 appendStr(getBuiltInVariableString());
2171 // Add struct/block members
2172 if (isStruct() && structure) {
2174 bool hasHiddenMember = true;
2175 for (size_t i = 0; i < structure->size(); ++i) {
2176 if (! (*structure)[i].type->hiddenMember()) {
2177 if (!hasHiddenMember)
2179 typeString.append((*structure)[i].type->getCompleteString());
2180 typeString.append(" ");
2181 typeString.append((*structure)[i].type->getFieldName());
2182 hasHiddenMember = false;
2191 TString getBasicTypeString() const
2193 if (basicType == EbtSampler)
2194 return sampler.getString();
2196 return getBasicString();
2199 const char* getStorageQualifierString() const { return GetStorageQualifierString(qualifier.storage); }
2200 const char* getBuiltInVariableString() const { return GetBuiltInVariableString(qualifier.builtIn); }
2201 const char* getPrecisionQualifierString() const { return GetPrecisionQualifierString(qualifier.precision); }
2204 const TTypeList* getStruct() const { assert(isStruct()); return structure; }
2205 void setStruct(TTypeList* s) { assert(isStruct()); structure = s; }
2206 TTypeList* getWritableStruct() const { assert(isStruct()); return structure; } // This should only be used when known to not be sharing with other threads
2207 void setBasicType(const TBasicType& t) { basicType = t; }
2209 int computeNumComponents() const
2213 if (getBasicType() == EbtStruct || getBasicType() == EbtBlock) {
2214 for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); tl++)
2215 components += ((*tl).type)->computeNumComponents();
2216 } else if (matrixCols)
2217 components = matrixCols * matrixRows;
2219 components = vectorSize;
2221 if (arraySizes != nullptr) {
2222 components *= arraySizes->getCumulativeSize();
2228 // append this type's mangled name to the passed in 'name'
2229 void appendMangledName(TString& name) const
2231 buildMangledName(name);
2235 // Do two structure types match? They could be declared independently,
2236 // in different places, but still might satisfy the definition of matching.
2239 // "Structures must have the same name, sequence of type names, and
2240 // type definitions, and member names to be considered the same type.
2241 // This rule applies recursively for nested or embedded types."
2243 bool sameStructType(const TType& right) const
2245 // Most commonly, they are both nullptr, or the same pointer to the same actual structure
2246 if ((!isStruct() && !right.isStruct()) ||
2247 (isStruct() && right.isStruct() && structure == right.structure))
2250 // Both being nullptr was caught above, now they both have to be structures of the same number of elements
2251 if (!isStruct() || !right.isStruct() ||
2252 structure->size() != right.structure->size())
2255 // Structure names have to match
2256 if (*typeName != *right.typeName)
2259 // Compare the names and types of all the members, which have to match
2260 for (unsigned int i = 0; i < structure->size(); ++i) {
2261 if ((*structure)[i].type->getFieldName() != (*right.structure)[i].type->getFieldName())
2264 if (*(*structure)[i].type != *(*right.structure)[i].type)
2271 bool sameReferenceType(const TType& right) const
2273 if (isReference() != right.isReference())
2276 if (!isReference() && !right.isReference())
2279 assert(referentType != nullptr);
2280 assert(right.referentType != nullptr);
2282 if (referentType == right.referentType)
2285 return *referentType == *right.referentType;
2288 // See if two types match, in all aspects except arrayness
2289 bool sameElementType(const TType& right) const
2291 return basicType == right.basicType && sameElementShape(right);
2294 // See if two type's arrayness match
2295 bool sameArrayness(const TType& right) const
2297 return ((arraySizes == nullptr && right.arraySizes == nullptr) ||
2298 (arraySizes != nullptr && right.arraySizes != nullptr && *arraySizes == *right.arraySizes));
2301 // See if two type's arrayness match in everything except their outer dimension
2302 bool sameInnerArrayness(const TType& right) const
2304 assert(arraySizes != nullptr && right.arraySizes != nullptr);
2305 return arraySizes->sameInnerArrayness(*right.arraySizes);
2308 // See if two type's parameters match
2309 bool sameTypeParameters(const TType& right) const
2311 return ((typeParameters == nullptr && right.typeParameters == nullptr) ||
2312 (typeParameters != nullptr && right.typeParameters != nullptr && *typeParameters == *right.typeParameters));
2315 // See if two type's elements match in all ways except basic type
2316 bool sameElementShape(const TType& right) const
2318 return sampler == right.sampler &&
2319 vectorSize == right.vectorSize &&
2320 matrixCols == right.matrixCols &&
2321 matrixRows == right.matrixRows &&
2322 vector1 == right.vector1 &&
2323 isCoopMat() == right.isCoopMat() &&
2324 sameStructType(right) &&
2325 sameReferenceType(right);
2328 // See if a cooperative matrix type parameter with unspecified parameters is
2329 // an OK function parameter
2330 bool coopMatParameterOK(const TType& right) const
2332 return isCoopMat() && right.isCoopMat() && (getBasicType() == right.getBasicType()) &&
2333 typeParameters == nullptr && right.typeParameters != nullptr;
2336 bool sameCoopMatBaseType(const TType &right) const {
2337 bool rv = coopmat && right.coopmat;
2338 if (getBasicType() == EbtFloat || getBasicType() == EbtFloat16)
2339 rv = right.getBasicType() == EbtFloat || right.getBasicType() == EbtFloat16;
2340 else if (getBasicType() == EbtUint || getBasicType() == EbtUint8)
2341 rv = right.getBasicType() == EbtUint || right.getBasicType() == EbtUint8;
2342 else if (getBasicType() == EbtInt || getBasicType() == EbtInt8)
2343 rv = right.getBasicType() == EbtInt || right.getBasicType() == EbtInt8;
2350 // See if two types match in all ways (just the actual type, not qualification)
2351 bool operator==(const TType& right) const
2353 return sameElementType(right) && sameArrayness(right) && sameTypeParameters(right);
2356 bool operator!=(const TType& right) const
2358 return ! operator==(right);
2361 unsigned int getBufferReferenceAlignment() const
2364 if (getBasicType() == glslang::EbtReference) {
2365 return getReferentType()->getQualifier().hasBufferReferenceAlign() ?
2366 (1u << getReferentType()->getQualifier().layoutBufferReferenceAlign) : 16u;
2373 // Require consumer to pick between deep copy and shallow copy.
2374 TType(const TType& type);
2375 TType& operator=(const TType& type);
2377 // Recursively copy a type graph, while preserving the graph-like
2378 // quality. That is, don't make more than one copy of a structure that
2379 // gets reused multiple times in the type graph.
2380 void deepCopy(const TType& copyOf, TMap<TTypeList*,TTypeList*>& copiedMap)
2382 shallowCopy(copyOf);
2384 if (copyOf.arraySizes) {
2385 arraySizes = new TArraySizes;
2386 *arraySizes = *copyOf.arraySizes;
2389 if (copyOf.typeParameters) {
2390 typeParameters = new TArraySizes;
2391 *typeParameters = *copyOf.typeParameters;
2394 if (copyOf.isStruct() && copyOf.structure) {
2395 auto prevCopy = copiedMap.find(copyOf.structure);
2396 if (prevCopy != copiedMap.end())
2397 structure = prevCopy->second;
2399 structure = new TTypeList;
2400 copiedMap[copyOf.structure] = structure;
2401 for (unsigned int i = 0; i < copyOf.structure->size(); ++i) {
2403 typeLoc.loc = (*copyOf.structure)[i].loc;
2404 typeLoc.type = new TType();
2405 typeLoc.type->deepCopy(*(*copyOf.structure)[i].type, copiedMap);
2406 structure->push_back(typeLoc);
2411 if (copyOf.fieldName)
2412 fieldName = NewPoolTString(copyOf.fieldName->c_str());
2413 if (copyOf.typeName)
2414 typeName = NewPoolTString(copyOf.typeName->c_str());
2418 void buildMangledName(TString&) const;
2420 TBasicType basicType : 8;
2421 int vectorSize : 4; // 1 means either scalar or 1-component vector; see vector1 to disambiguate.
2424 bool vector1 : 1; // Backward-compatible tracking of a 1-component vector distinguished from a scalar.
2425 // GLSL 4.5 never has a 1-component vector; so this will always be false until such
2426 // functionality is added.
2427 // HLSL does have a 1-component vectors, so this will be true to disambiguate
2430 TQualifier qualifier;
2432 TArraySizes* arraySizes; // nullptr unless an array; can be shared across types
2433 // A type can't be both a structure (EbtStruct/EbtBlock) and a reference (EbtReference), so
2434 // conserve space by making these a union
2436 TTypeList* structure; // invalid unless this is a struct; can be shared across types
2437 TType *referentType; // invalid unless this is an EbtReference
2439 TString *fieldName; // for structure field names
2440 TString *typeName; // for structure type name
2442 TArraySizes* typeParameters;// nullptr unless a parameterized type; can be shared across types
2445 } // end namespace glslang
2447 #endif // _TYPES_INCLUDED_