1 //
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 //
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions
11 // are met:
12 //
13 // Redistributions of source code must retain the above copyright
14 // notice, this list of conditions and the following disclaimer.
15 //
16 // Redistributions in binary form must reproduce the above
17 // copyright notice, this list of conditions and the following
18 // disclaimer in the documentation and/or other materials provided
19 // with the distribution.
20 //
21 // Neither the name of 3Dlabs Inc. Ltd. nor the names of its
22 // contributors may be used to endorse or promote products derived
23 // from this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
28 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
29 // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
30 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
31 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 // POSSIBILITY OF SUCH DAMAGE.
37 //
38
39 #ifndef _TYPES_INCLUDED
40 #define _TYPES_INCLUDED
41
42 #include "../Include/Common.h"
43 #include "../Include/BaseTypes.h"
44 #include "../Public/ShaderLang.h"
45 #include "arrays.h"
46
47 #include <algorithm>
48
49 namespace glslang {
50
51 const int GlslangMaxTypeLength = 200; // TODO: need to print block/struct one member per line, so this can stay bounded
52
53 const char* const AnonymousPrefix = "anon@"; // for something like a block whose members can be directly accessed
IsAnonymous(const TString & name)54 inline bool IsAnonymous(const TString& name)
55 {
56 return name.compare(0, 5, AnonymousPrefix) == 0;
57 }
58
59 //
60 // Details within a sampler type
61 //
62 enum TSamplerDim {
63 EsdNone,
64 Esd1D,
65 Esd2D,
66 Esd3D,
67 EsdCube,
68 EsdRect,
69 EsdBuffer,
70 EsdSubpass, // goes only with non-sampled image (image is true)
71 EsdNumDims
72 };
73
74 struct TSampler { // misnomer now; includes images, textures without sampler, and textures with sampler
75 TBasicType type : 8; // type returned by sampler
76 TSamplerDim dim : 8;
77 bool arrayed : 1;
78 bool shadow : 1;
79 bool ms : 1;
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()
83 bool external : 1; // GL_OES_EGL_image_external
84 unsigned int vectorSize : 3; // vector return type size.
85
86 // Some languages support structures as sample results. Storing the whole structure in the
87 // TSampler is too large, so there is an index to a separate table.
88 static const unsigned structReturnIndexBits = 4; // number of index bits to use.
89 static const unsigned structReturnSlots = (1<<structReturnIndexBits)-1; // number of valid values
90 static const unsigned noReturnStruct = structReturnSlots; // value if no return struct type.
91
92 // Index into a language specific table of texture return structures.
93 unsigned int structReturnIndex : structReturnIndexBits;
94
95 // Encapsulate getting members' vector sizes packed into the vectorSize bitfield.
getVectorSizeTSampler96 unsigned int getVectorSize() const { return vectorSize; }
97
isImageTSampler98 bool isImage() const { return image && dim != EsdSubpass; }
isSubpassTSampler99 bool isSubpass() const { return dim == EsdSubpass; }
isCombinedTSampler100 bool isCombined() const { return combined; }
isPureSamplerTSampler101 bool isPureSampler() const { return sampler; }
isTextureTSampler102 bool isTexture() const { return !sampler && !image; }
isShadowTSampler103 bool isShadow() const { return shadow; }
isArrayedTSampler104 bool isArrayed() const { return arrayed; }
isMultiSampleTSampler105 bool isMultiSample() const { return ms; }
hasReturnStructTSampler106 bool hasReturnStruct() const { return structReturnIndex != noReturnStruct; }
107
clearTSampler108 void clear()
109 {
110 type = EbtVoid;
111 dim = EsdNone;
112 arrayed = false;
113 shadow = false;
114 ms = false;
115 image = false;
116 combined = false;
117 sampler = false;
118 external = false;
119 structReturnIndex = noReturnStruct;
120
121 // by default, returns a single vec4;
122 vectorSize = 4;
123 }
124
125 // make a combined sampler and texture
126 void set(TBasicType t, TSamplerDim d, bool a = false, bool s = false, bool m = false)
127 {
128 clear();
129 type = t;
130 dim = d;
131 arrayed = a;
132 shadow = s;
133 ms = m;
134 combined = true;
135 }
136
137 // make an image
138 void setImage(TBasicType t, TSamplerDim d, bool a = false, bool s = false, bool m = false)
139 {
140 clear();
141 type = t;
142 dim = d;
143 arrayed = a;
144 shadow = s;
145 ms = m;
146 image = true;
147 }
148
149 // make a texture with no sampler
150 void setTexture(TBasicType t, TSamplerDim d, bool a = false, bool s = false, bool m = false)
151 {
152 clear();
153 type = t;
154 dim = d;
155 arrayed = a;
156 shadow = s;
157 ms = m;
158 }
159
160 // make a subpass input attachment
161 void setSubpass(TBasicType t, bool m = false)
162 {
163 clear();
164 type = t;
165 image = true;
166 dim = EsdSubpass;
167 ms = m;
168 }
169
170 // make a pure sampler, no texture, no image, nothing combined, the 'sampler' keyword
setPureSamplerTSampler171 void setPureSampler(bool s)
172 {
173 clear();
174 sampler = true;
175 shadow = s;
176 }
177
178 bool operator==(const TSampler& right) const
179 {
180 return type == right.type &&
181 dim == right.dim &&
182 arrayed == right.arrayed &&
183 shadow == right.shadow &&
184 ms == right.ms &&
185 image == right.image &&
186 combined == right.combined &&
187 sampler == right.sampler &&
188 external == right.external &&
189 vectorSize == right.vectorSize &&
190 structReturnIndex == right.structReturnIndex;
191 }
192
193 bool operator!=(const TSampler& right) const
194 {
195 return ! operator==(right);
196 }
197
getStringTSampler198 TString getString() const
199 {
200 TString s;
201
202 if (sampler) {
203 s.append("sampler");
204 return s;
205 }
206
207 switch (type) {
208 case EbtFloat: break;
209 #ifdef AMD_EXTENSIONS
210 case EbtFloat16: s.append("f16"); break;
211 #endif
212 case EbtInt8: s.append("i8"); break;
213 case EbtUint16: s.append("u8"); break;
214 case EbtInt16: s.append("i16"); break;
215 case EbtUint8: s.append("u16"); break;
216 case EbtInt: s.append("i"); break;
217 case EbtUint: s.append("u"); break;
218 case EbtInt64: s.append("i64"); break;
219 case EbtUint64: s.append("u64"); break;
220 default: break; // some compilers want this
221 }
222 if (image) {
223 if (dim == EsdSubpass)
224 s.append("subpass");
225 else
226 s.append("image");
227 } else if (combined) {
228 s.append("sampler");
229 } else {
230 s.append("texture");
231 }
232 if (external) {
233 s.append("ExternalOES");
234 return s;
235 }
236 switch (dim) {
237 case Esd1D: s.append("1D"); break;
238 case Esd2D: s.append("2D"); break;
239 case Esd3D: s.append("3D"); break;
240 case EsdCube: s.append("Cube"); break;
241 case EsdRect: s.append("2DRect"); break;
242 case EsdBuffer: s.append("Buffer"); break;
243 case EsdSubpass: s.append("Input"); break;
244 default: break; // some compilers want this
245 }
246 if (ms)
247 s.append("MS");
248 if (arrayed)
249 s.append("Array");
250 if (shadow)
251 s.append("Shadow");
252
253 return s;
254 }
255 };
256
257 //
258 // Need to have association of line numbers to types in a list for building structs.
259 //
260 class TType;
261 struct TTypeLoc {
262 TType* type;
263 TSourceLoc loc;
264 };
265 typedef TVector<TTypeLoc> TTypeList;
266
267 typedef TVector<TString*> TIdentifierList;
268
269 //
270 // Following are a series of helper enums for managing layouts and qualifiers,
271 // used for TPublicType, TType, others.
272 //
273
274 enum TLayoutPacking {
275 ElpNone,
276 ElpShared, // default, but different than saying nothing
277 ElpStd140,
278 ElpStd430,
279 ElpPacked,
280 ElpScalar,
281 ElpCount // If expanding, see bitfield width below
282 };
283
284 enum TLayoutMatrix {
285 ElmNone,
286 ElmRowMajor,
287 ElmColumnMajor, // default, but different than saying nothing
288 ElmCount // If expanding, see bitfield width below
289 };
290
291 // Union of geometry shader and tessellation shader geometry types.
292 // They don't go into TType, but rather have current state per shader or
293 // active parser type (TPublicType).
294 enum TLayoutGeometry {
295 ElgNone,
296 ElgPoints,
297 ElgLines,
298 ElgLinesAdjacency,
299 ElgLineStrip,
300 ElgTriangles,
301 ElgTrianglesAdjacency,
302 ElgTriangleStrip,
303 ElgQuads,
304 ElgIsolines,
305 };
306
307 enum TVertexSpacing {
308 EvsNone,
309 EvsEqual,
310 EvsFractionalEven,
311 EvsFractionalOdd
312 };
313
314 enum TVertexOrder {
315 EvoNone,
316 EvoCw,
317 EvoCcw
318 };
319
320 // Note: order matters, as type of format is done by comparison.
321 enum TLayoutFormat {
322 ElfNone,
323
324 // Float image
325 ElfRgba32f,
326 ElfRgba16f,
327 ElfR32f,
328 ElfRgba8,
329 ElfRgba8Snorm,
330
331 ElfEsFloatGuard, // to help with comparisons
332
333 ElfRg32f,
334 ElfRg16f,
335 ElfR11fG11fB10f,
336 ElfR16f,
337 ElfRgba16,
338 ElfRgb10A2,
339 ElfRg16,
340 ElfRg8,
341 ElfR16,
342 ElfR8,
343 ElfRgba16Snorm,
344 ElfRg16Snorm,
345 ElfRg8Snorm,
346 ElfR16Snorm,
347 ElfR8Snorm,
348
349 ElfFloatGuard, // to help with comparisons
350
351 // Int image
352 ElfRgba32i,
353 ElfRgba16i,
354 ElfRgba8i,
355 ElfR32i,
356
357 ElfEsIntGuard, // to help with comparisons
358
359 ElfRg32i,
360 ElfRg16i,
361 ElfRg8i,
362 ElfR16i,
363 ElfR8i,
364
365 ElfIntGuard, // to help with comparisons
366
367 // Uint image
368 ElfRgba32ui,
369 ElfRgba16ui,
370 ElfRgba8ui,
371 ElfR32ui,
372
373 ElfEsUintGuard, // to help with comparisons
374
375 ElfRg32ui,
376 ElfRg16ui,
377 ElfRgb10a2ui,
378 ElfRg8ui,
379 ElfR16ui,
380 ElfR8ui,
381
382 ElfCount
383 };
384
385 enum TLayoutDepth {
386 EldNone,
387 EldAny,
388 EldGreater,
389 EldLess,
390 EldUnchanged,
391
392 EldCount
393 };
394
395 enum TBlendEquationShift {
396 // No 'EBlendNone':
397 // These are used as bit-shift amounts. A mask of such shifts will have type 'int',
398 // and in that space, 0 means no bits set, or none. In this enum, 0 means (1 << 0), a bit is set.
399 EBlendMultiply,
400 EBlendScreen,
401 EBlendOverlay,
402 EBlendDarken,
403 EBlendLighten,
404 EBlendColordodge,
405 EBlendColorburn,
406 EBlendHardlight,
407 EBlendSoftlight,
408 EBlendDifference,
409 EBlendExclusion,
410 EBlendHslHue,
411 EBlendHslSaturation,
412 EBlendHslColor,
413 EBlendHslLuminosity,
414 EBlendAllEquations,
415
416 EBlendCount
417 };
418
419 class TQualifier {
420 public:
421 static const int layoutNotSet = -1;
422
clear()423 void clear()
424 {
425 precision = EpqNone;
426 invariant = false;
427 noContraction = false;
428 makeTemporary();
429 declaredBuiltIn = EbvNone;
430 }
431
432 // drop qualifiers that don't belong in a temporary variable
makeTemporary()433 void makeTemporary()
434 {
435 semanticName = nullptr;
436 storage = EvqTemporary;
437 builtIn = EbvNone;
438 clearInterstage();
439 clearMemory();
440 specConstant = false;
441 nonUniform = false;
442 clearLayout();
443 }
444
clearInterstage()445 void clearInterstage()
446 {
447 clearInterpolation();
448 patch = false;
449 sample = false;
450 }
451
clearInterpolation()452 void clearInterpolation()
453 {
454 centroid = false;
455 smooth = false;
456 flat = false;
457 nopersp = false;
458 #ifdef AMD_EXTENSIONS
459 explicitInterp = false;
460 #endif
461 #ifdef NV_EXTENSIONS
462 pervertexNV = false;
463 perPrimitiveNV = false;
464 perViewNV = false;
465 perTaskNV = false;
466 #endif
467 }
468
clearMemory()469 void clearMemory()
470 {
471 coherent = false;
472 devicecoherent = false;
473 queuefamilycoherent = false;
474 workgroupcoherent = false;
475 subgroupcoherent = false;
476 nonprivate = false;
477 volatil = false;
478 restrict = false;
479 readonly = false;
480 writeonly = false;
481 }
482
483 // Drop just the storage qualification, which perhaps should
484 // never be done, as it is fundamentally inconsistent, but need to
485 // explore what downstream consumers need.
486 // E.g., in a dereference, it is an inconsistency between:
487 // A) partially dereferenced resource is still in the storage class it started in
488 // B) partially dereferenced resource is a new temporary object
489 // If A, then nothing should change, if B, then everything should change, but this is half way.
makePartialTemporary()490 void makePartialTemporary()
491 {
492 storage = EvqTemporary;
493 specConstant = false;
494 nonUniform = false;
495 }
496
497 const char* semanticName;
498 TStorageQualifier storage : 6;
499 TBuiltInVariable builtIn : 8;
500 TBuiltInVariable declaredBuiltIn : 8;
501 TPrecisionQualifier precision : 3;
502 bool invariant : 1; // require canonical treatment for cross-shader invariance
503 bool noContraction: 1; // prevent contraction and reassociation, e.g., for 'precise' keyword, and expressions it affects
504 bool centroid : 1;
505 bool smooth : 1;
506 bool flat : 1;
507 bool nopersp : 1;
508 #ifdef AMD_EXTENSIONS
509 bool explicitInterp : 1;
510 #endif
511 #ifdef NV_EXTENSIONS
512 bool pervertexNV : 1;
513 bool perPrimitiveNV : 1;
514 bool perViewNV : 1;
515 bool perTaskNV : 1;
516 #endif
517 bool patch : 1;
518 bool sample : 1;
519 bool coherent : 1;
520 bool devicecoherent : 1;
521 bool queuefamilycoherent : 1;
522 bool workgroupcoherent : 1;
523 bool subgroupcoherent : 1;
524 bool nonprivate : 1;
525 bool volatil : 1;
526 bool restrict : 1;
527 bool readonly : 1;
528 bool writeonly : 1;
529 bool specConstant : 1; // having a constant_id is not sufficient: expressions have no id, but are still specConstant
530 bool nonUniform : 1;
531
isMemory()532 bool isMemory() const
533 {
534 return subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly || nonprivate;
535 }
isMemoryQualifierImageAndSSBOOnly()536 bool isMemoryQualifierImageAndSSBOOnly() const
537 {
538 return subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly;
539 }
540
isInterpolation()541 bool isInterpolation() const
542 {
543 #ifdef AMD_EXTENSIONS
544 return flat || smooth || nopersp || explicitInterp;
545 #else
546 return flat || smooth || nopersp;
547 #endif
548 }
549
550 #ifdef AMD_EXTENSIONS
isExplicitInterpolation()551 bool isExplicitInterpolation() const
552 {
553 return explicitInterp;
554 }
555 #endif
556
isAuxiliary()557 bool isAuxiliary() const
558 {
559 #ifdef NV_EXTENSIONS
560 return centroid || patch || sample || pervertexNV;
561 #else
562 return centroid || patch || sample;
563 #endif
564 }
565
isPipeInput()566 bool isPipeInput() const
567 {
568 switch (storage) {
569 case EvqVaryingIn:
570 case EvqFragCoord:
571 case EvqPointCoord:
572 case EvqFace:
573 case EvqVertexId:
574 case EvqInstanceId:
575 return true;
576 default:
577 return false;
578 }
579 }
580
isPipeOutput()581 bool isPipeOutput() const
582 {
583 switch (storage) {
584 case EvqPosition:
585 case EvqPointSize:
586 case EvqClipVertex:
587 case EvqVaryingOut:
588 case EvqFragColor:
589 case EvqFragDepth:
590 return true;
591 default:
592 return false;
593 }
594 }
595
isParamInput()596 bool isParamInput() const
597 {
598 switch (storage) {
599 case EvqIn:
600 case EvqInOut:
601 case EvqConstReadOnly:
602 return true;
603 default:
604 return false;
605 }
606 }
607
isParamOutput()608 bool isParamOutput() const
609 {
610 switch (storage) {
611 case EvqOut:
612 case EvqInOut:
613 return true;
614 default:
615 return false;
616 }
617 }
618
isUniformOrBuffer()619 bool isUniformOrBuffer() const
620 {
621 switch (storage) {
622 case EvqUniform:
623 case EvqBuffer:
624 return true;
625 default:
626 return false;
627 }
628 }
629
isPerPrimitive()630 bool isPerPrimitive() const
631 {
632 #ifdef NV_EXTENSIONS
633 return perPrimitiveNV;
634 #else
635 return false;
636 #endif
637 }
638
isPerView()639 bool isPerView() const
640 {
641 #ifdef NV_EXTENSIONS
642 return perViewNV;
643 #else
644 return false;
645 #endif
646 }
647
isTaskMemory()648 bool isTaskMemory() const
649 {
650 #ifdef NV_EXTENSIONS
651 return perTaskNV;
652 #else
653 return false;
654 #endif
655 }
656
isIo()657 bool isIo() const
658 {
659 switch (storage) {
660 case EvqUniform:
661 case EvqBuffer:
662 case EvqVaryingIn:
663 case EvqFragCoord:
664 case EvqPointCoord:
665 case EvqFace:
666 case EvqVertexId:
667 case EvqInstanceId:
668 case EvqPosition:
669 case EvqPointSize:
670 case EvqClipVertex:
671 case EvqVaryingOut:
672 case EvqFragColor:
673 case EvqFragDepth:
674 return true;
675 default:
676 return false;
677 }
678 }
679
680 // non-built-in symbols that might link between compilation units
isLinkable()681 bool isLinkable() const
682 {
683 switch (storage) {
684 case EvqGlobal:
685 case EvqVaryingIn:
686 case EvqVaryingOut:
687 case EvqUniform:
688 case EvqBuffer:
689 case EvqShared:
690 return true;
691 default:
692 return false;
693 }
694 }
695
696 // True if this type of IO is supposed to be arrayed with extra level for per-vertex data
isArrayedIo(EShLanguage language)697 bool isArrayedIo(EShLanguage language) const
698 {
699 switch (language) {
700 case EShLangGeometry:
701 return isPipeInput();
702 case EShLangTessControl:
703 return ! patch && (isPipeInput() || isPipeOutput());
704 case EShLangTessEvaluation:
705 return ! patch && isPipeInput();
706 #ifdef NV_EXTENSIONS
707 case EShLangFragment:
708 return pervertexNV && isPipeInput();
709 case EShLangMeshNV:
710 return ! perTaskNV && isPipeOutput();
711 #endif
712
713 default:
714 return false;
715 }
716 }
717
718 // Implementing an embedded layout-qualifier class here, since C++ can't have a real class bitfield
clearLayout()719 void clearLayout() // all layout
720 {
721 clearUniformLayout();
722
723 layoutPushConstant = false;
724 layoutBufferReference = false;
725 #ifdef NV_EXTENSIONS
726 layoutPassthrough = false;
727 layoutViewportRelative = false;
728 // -2048 as the default value indicating layoutSecondaryViewportRelative is not set
729 layoutSecondaryViewportRelativeOffset = -2048;
730 layoutShaderRecordNV = false;
731 #endif
732
733 layoutBufferReferenceAlign = layoutBufferReferenceAlignEnd;
734
735 clearInterstageLayout();
736
737 layoutSpecConstantId = layoutSpecConstantIdEnd;
738
739 layoutFormat = ElfNone;
740 }
clearInterstageLayout()741 void clearInterstageLayout()
742 {
743 layoutLocation = layoutLocationEnd;
744 layoutComponent = layoutComponentEnd;
745 layoutIndex = layoutIndexEnd;
746 clearStreamLayout();
747 clearXfbLayout();
748 }
clearStreamLayout()749 void clearStreamLayout()
750 {
751 layoutStream = layoutStreamEnd;
752 }
clearXfbLayout()753 void clearXfbLayout()
754 {
755 layoutXfbBuffer = layoutXfbBufferEnd;
756 layoutXfbStride = layoutXfbStrideEnd;
757 layoutXfbOffset = layoutXfbOffsetEnd;
758 }
759
hasNonXfbLayout()760 bool hasNonXfbLayout() const
761 {
762 return hasUniformLayout() ||
763 hasAnyLocation() ||
764 hasStream() ||
765 hasFormat() ||
766 #ifdef NV_EXTENSIONS
767 layoutShaderRecordNV ||
768 #endif
769 layoutPushConstant ||
770 layoutBufferReference;
771 }
hasLayout()772 bool hasLayout() const
773 {
774 return hasNonXfbLayout() ||
775 hasXfb();
776 }
777 TLayoutMatrix layoutMatrix : 3;
778 TLayoutPacking layoutPacking : 4;
779 int layoutOffset;
780 int layoutAlign;
781
782 unsigned int layoutLocation : 12;
783 static const unsigned int layoutLocationEnd = 0xFFF;
784
785 unsigned int layoutComponent : 3;
786 static const unsigned int layoutComponentEnd = 4;
787
788 unsigned int layoutSet : 7;
789 static const unsigned int layoutSetEnd = 0x3F;
790
791 unsigned int layoutBinding : 16;
792 static const unsigned int layoutBindingEnd = 0xFFFF;
793
794 unsigned int layoutIndex : 8;
795 static const unsigned int layoutIndexEnd = 0xFF;
796
797 unsigned int layoutStream : 8;
798 static const unsigned int layoutStreamEnd = 0xFF;
799
800 unsigned int layoutXfbBuffer : 4;
801 static const unsigned int layoutXfbBufferEnd = 0xF;
802
803 unsigned int layoutXfbStride : 14;
804 static const unsigned int layoutXfbStrideEnd = 0x3FFF;
805
806 unsigned int layoutXfbOffset : 13;
807 static const unsigned int layoutXfbOffsetEnd = 0x1FFF;
808
809 unsigned int layoutAttachment : 8; // for input_attachment_index
810 static const unsigned int layoutAttachmentEnd = 0XFF;
811
812 unsigned int layoutSpecConstantId : 11;
813 static const unsigned int layoutSpecConstantIdEnd = 0x7FF;
814
815 // stored as log2 of the actual alignment value
816 unsigned int layoutBufferReferenceAlign : 6;
817 static const unsigned int layoutBufferReferenceAlignEnd = 0x3F;
818
819 TLayoutFormat layoutFormat : 8;
820
821 bool layoutPushConstant;
822 bool layoutBufferReference;
823
824 #ifdef NV_EXTENSIONS
825 bool layoutPassthrough;
826 bool layoutViewportRelative;
827 int layoutSecondaryViewportRelativeOffset;
828 bool layoutShaderRecordNV;
829 #endif
830
hasUniformLayout()831 bool hasUniformLayout() const
832 {
833 return hasMatrix() ||
834 hasPacking() ||
835 hasOffset() ||
836 hasBinding() ||
837 hasSet() ||
838 hasAlign();
839 }
clearUniformLayout()840 void clearUniformLayout() // only uniform specific
841 {
842 layoutMatrix = ElmNone;
843 layoutPacking = ElpNone;
844 layoutOffset = layoutNotSet;
845 layoutAlign = layoutNotSet;
846
847 layoutSet = layoutSetEnd;
848 layoutBinding = layoutBindingEnd;
849 layoutAttachment = layoutAttachmentEnd;
850 }
851
hasMatrix()852 bool hasMatrix() const
853 {
854 return layoutMatrix != ElmNone;
855 }
hasPacking()856 bool hasPacking() const
857 {
858 return layoutPacking != ElpNone;
859 }
hasOffset()860 bool hasOffset() const
861 {
862 return layoutOffset != layoutNotSet;
863 }
hasAlign()864 bool hasAlign() const
865 {
866 return layoutAlign != layoutNotSet;
867 }
hasAnyLocation()868 bool hasAnyLocation() const
869 {
870 return hasLocation() ||
871 hasComponent() ||
872 hasIndex();
873 }
hasLocation()874 bool hasLocation() const
875 {
876 return layoutLocation != layoutLocationEnd;
877 }
hasComponent()878 bool hasComponent() const
879 {
880 return layoutComponent != layoutComponentEnd;
881 }
hasIndex()882 bool hasIndex() const
883 {
884 return layoutIndex != layoutIndexEnd;
885 }
hasSet()886 bool hasSet() const
887 {
888 return layoutSet != layoutSetEnd;
889 }
hasBinding()890 bool hasBinding() const
891 {
892 return layoutBinding != layoutBindingEnd;
893 }
hasStream()894 bool hasStream() const
895 {
896 return layoutStream != layoutStreamEnd;
897 }
hasFormat()898 bool hasFormat() const
899 {
900 return layoutFormat != ElfNone;
901 }
hasXfb()902 bool hasXfb() const
903 {
904 return hasXfbBuffer() ||
905 hasXfbStride() ||
906 hasXfbOffset();
907 }
hasXfbBuffer()908 bool hasXfbBuffer() const
909 {
910 return layoutXfbBuffer != layoutXfbBufferEnd;
911 }
hasXfbStride()912 bool hasXfbStride() const
913 {
914 return layoutXfbStride != layoutXfbStrideEnd;
915 }
hasXfbOffset()916 bool hasXfbOffset() const
917 {
918 return layoutXfbOffset != layoutXfbOffsetEnd;
919 }
hasAttachment()920 bool hasAttachment() const
921 {
922 return layoutAttachment != layoutAttachmentEnd;
923 }
hasSpecConstantId()924 bool hasSpecConstantId() const
925 {
926 // Not the same thing as being a specialization constant, this
927 // is just whether or not it was declared with an ID.
928 return layoutSpecConstantId != layoutSpecConstantIdEnd;
929 }
hasBufferReferenceAlign()930 bool hasBufferReferenceAlign() const
931 {
932 return layoutBufferReferenceAlign != layoutBufferReferenceAlignEnd;
933 }
isSpecConstant()934 bool isSpecConstant() const
935 {
936 // True if type is a specialization constant, whether or not it
937 // had a specialization-constant ID, and false if it is not a
938 // true front-end constant.
939 return specConstant;
940 }
isNonUniform()941 bool isNonUniform() const
942 {
943 return nonUniform;
944 }
isFrontEndConstant()945 bool isFrontEndConstant() const
946 {
947 // True if the front-end knows the final constant value.
948 // This allows front-end constant folding.
949 return storage == EvqConst && ! specConstant;
950 }
isConstant()951 bool isConstant() const
952 {
953 // True if is either kind of constant; specialization or regular.
954 return isFrontEndConstant() || isSpecConstant();
955 }
makeSpecConstant()956 void makeSpecConstant()
957 {
958 storage = EvqConst;
959 specConstant = true;
960 }
getLayoutPackingString(TLayoutPacking packing)961 static const char* getLayoutPackingString(TLayoutPacking packing)
962 {
963 switch (packing) {
964 case ElpPacked: return "packed";
965 case ElpShared: return "shared";
966 case ElpStd140: return "std140";
967 case ElpStd430: return "std430";
968 case ElpScalar: return "scalar";
969 default: return "none";
970 }
971 }
getLayoutMatrixString(TLayoutMatrix m)972 static const char* getLayoutMatrixString(TLayoutMatrix m)
973 {
974 switch (m) {
975 case ElmColumnMajor: return "column_major";
976 case ElmRowMajor: return "row_major";
977 default: return "none";
978 }
979 }
getLayoutFormatString(TLayoutFormat f)980 static const char* getLayoutFormatString(TLayoutFormat f)
981 {
982 switch (f) {
983 case ElfRgba32f: return "rgba32f";
984 case ElfRgba16f: return "rgba16f";
985 case ElfRg32f: return "rg32f";
986 case ElfRg16f: return "rg16f";
987 case ElfR11fG11fB10f: return "r11f_g11f_b10f";
988 case ElfR32f: return "r32f";
989 case ElfR16f: return "r16f";
990 case ElfRgba16: return "rgba16";
991 case ElfRgb10A2: return "rgb10_a2";
992 case ElfRgba8: return "rgba8";
993 case ElfRg16: return "rg16";
994 case ElfRg8: return "rg8";
995 case ElfR16: return "r16";
996 case ElfR8: return "r8";
997 case ElfRgba16Snorm: return "rgba16_snorm";
998 case ElfRgba8Snorm: return "rgba8_snorm";
999 case ElfRg16Snorm: return "rg16_snorm";
1000 case ElfRg8Snorm: return "rg8_snorm";
1001 case ElfR16Snorm: return "r16_snorm";
1002 case ElfR8Snorm: return "r8_snorm";
1003
1004 case ElfRgba32i: return "rgba32i";
1005 case ElfRgba16i: return "rgba16i";
1006 case ElfRgba8i: return "rgba8i";
1007 case ElfRg32i: return "rg32i";
1008 case ElfRg16i: return "rg16i";
1009 case ElfRg8i: return "rg8i";
1010 case ElfR32i: return "r32i";
1011 case ElfR16i: return "r16i";
1012 case ElfR8i: return "r8i";
1013
1014 case ElfRgba32ui: return "rgba32ui";
1015 case ElfRgba16ui: return "rgba16ui";
1016 case ElfRgba8ui: return "rgba8ui";
1017 case ElfRg32ui: return "rg32ui";
1018 case ElfRg16ui: return "rg16ui";
1019 case ElfRgb10a2ui: return "rgb10_a2ui";
1020 case ElfRg8ui: return "rg8ui";
1021 case ElfR32ui: return "r32ui";
1022 case ElfR16ui: return "r16ui";
1023 case ElfR8ui: return "r8ui";
1024 default: return "none";
1025 }
1026 }
getLayoutDepthString(TLayoutDepth d)1027 static const char* getLayoutDepthString(TLayoutDepth d)
1028 {
1029 switch (d) {
1030 case EldAny: return "depth_any";
1031 case EldGreater: return "depth_greater";
1032 case EldLess: return "depth_less";
1033 case EldUnchanged: return "depth_unchanged";
1034 default: return "none";
1035 }
1036 }
getBlendEquationString(TBlendEquationShift e)1037 static const char* getBlendEquationString(TBlendEquationShift e)
1038 {
1039 switch (e) {
1040 case EBlendMultiply: return "blend_support_multiply";
1041 case EBlendScreen: return "blend_support_screen";
1042 case EBlendOverlay: return "blend_support_overlay";
1043 case EBlendDarken: return "blend_support_darken";
1044 case EBlendLighten: return "blend_support_lighten";
1045 case EBlendColordodge: return "blend_support_colordodge";
1046 case EBlendColorburn: return "blend_support_colorburn";
1047 case EBlendHardlight: return "blend_support_hardlight";
1048 case EBlendSoftlight: return "blend_support_softlight";
1049 case EBlendDifference: return "blend_support_difference";
1050 case EBlendExclusion: return "blend_support_exclusion";
1051 case EBlendHslHue: return "blend_support_hsl_hue";
1052 case EBlendHslSaturation: return "blend_support_hsl_saturation";
1053 case EBlendHslColor: return "blend_support_hsl_color";
1054 case EBlendHslLuminosity: return "blend_support_hsl_luminosity";
1055 case EBlendAllEquations: return "blend_support_all_equations";
1056 default: return "unknown";
1057 }
1058 }
getGeometryString(TLayoutGeometry geometry)1059 static const char* getGeometryString(TLayoutGeometry geometry)
1060 {
1061 switch (geometry) {
1062 case ElgPoints: return "points";
1063 case ElgLines: return "lines";
1064 case ElgLinesAdjacency: return "lines_adjacency";
1065 case ElgLineStrip: return "line_strip";
1066 case ElgTriangles: return "triangles";
1067 case ElgTrianglesAdjacency: return "triangles_adjacency";
1068 case ElgTriangleStrip: return "triangle_strip";
1069 case ElgQuads: return "quads";
1070 case ElgIsolines: return "isolines";
1071 default: return "none";
1072 }
1073 }
getVertexSpacingString(TVertexSpacing spacing)1074 static const char* getVertexSpacingString(TVertexSpacing spacing)
1075 {
1076 switch (spacing) {
1077 case EvsEqual: return "equal_spacing";
1078 case EvsFractionalEven: return "fractional_even_spacing";
1079 case EvsFractionalOdd: return "fractional_odd_spacing";
1080 default: return "none";
1081 }
1082 }
getVertexOrderString(TVertexOrder order)1083 static const char* getVertexOrderString(TVertexOrder order)
1084 {
1085 switch (order) {
1086 case EvoCw: return "cw";
1087 case EvoCcw: return "ccw";
1088 default: return "none";
1089 }
1090 }
mapGeometryToSize(TLayoutGeometry geometry)1091 static int mapGeometryToSize(TLayoutGeometry geometry)
1092 {
1093 switch (geometry) {
1094 case ElgPoints: return 1;
1095 case ElgLines: return 2;
1096 case ElgLinesAdjacency: return 4;
1097 case ElgTriangles: return 3;
1098 case ElgTrianglesAdjacency: return 6;
1099 default: return 0;
1100 }
1101 }
1102 };
1103
1104 // Qualifiers that don't need to be keep per object. They have shader scope, not object scope.
1105 // So, they will not be part of TType, TQualifier, etc.
1106 struct TShaderQualifiers {
1107 TLayoutGeometry geometry; // geometry/tessellation shader in/out primitives
1108 bool pixelCenterInteger; // fragment shader
1109 bool originUpperLeft; // fragment shader
1110 int invocations;
1111 int vertices; // for tessellation "vertices", geometry & mesh "max_vertices"
1112 TVertexSpacing spacing;
1113 TVertexOrder order;
1114 bool pointMode;
1115 int localSize[3]; // compute shader
1116 int localSizeSpecId[3]; // compute shader specialization id for gl_WorkGroupSize
1117 bool earlyFragmentTests; // fragment input
1118 bool postDepthCoverage; // fragment input
1119 TLayoutDepth layoutDepth;
1120 bool blendEquation; // true if any blend equation was specified
1121 int numViews; // multiview extenstions
1122
1123 #ifdef NV_EXTENSIONS
1124 bool layoutOverrideCoverage; // true if layout override_coverage set
1125 bool layoutDerivativeGroupQuads; // true if layout derivative_group_quadsNV set
1126 bool layoutDerivativeGroupLinear; // true if layout derivative_group_linearNV set
1127 int primitives; // mesh shader "max_primitives"DerivativeGroupLinear; // true if layout derivative_group_linearNV set
1128 #endif
1129
initTShaderQualifiers1130 void init()
1131 {
1132 geometry = ElgNone;
1133 originUpperLeft = false;
1134 pixelCenterInteger = false;
1135 invocations = TQualifier::layoutNotSet;
1136 vertices = TQualifier::layoutNotSet;
1137 spacing = EvsNone;
1138 order = EvoNone;
1139 pointMode = false;
1140 localSize[0] = 1;
1141 localSize[1] = 1;
1142 localSize[2] = 1;
1143 localSizeSpecId[0] = TQualifier::layoutNotSet;
1144 localSizeSpecId[1] = TQualifier::layoutNotSet;
1145 localSizeSpecId[2] = TQualifier::layoutNotSet;
1146 earlyFragmentTests = false;
1147 postDepthCoverage = false;
1148 layoutDepth = EldNone;
1149 blendEquation = false;
1150 numViews = TQualifier::layoutNotSet;
1151 #ifdef NV_EXTENSIONS
1152 layoutOverrideCoverage = false;
1153 layoutDerivativeGroupQuads = false;
1154 layoutDerivativeGroupLinear = false;
1155 primitives = TQualifier::layoutNotSet;
1156 #endif
1157 }
1158
1159 // Merge in characteristics from the 'src' qualifier. They can override when
1160 // set, but never erase when not set.
mergeTShaderQualifiers1161 void merge(const TShaderQualifiers& src)
1162 {
1163 if (src.geometry != ElgNone)
1164 geometry = src.geometry;
1165 if (src.pixelCenterInteger)
1166 pixelCenterInteger = src.pixelCenterInteger;
1167 if (src.originUpperLeft)
1168 originUpperLeft = src.originUpperLeft;
1169 if (src.invocations != TQualifier::layoutNotSet)
1170 invocations = src.invocations;
1171 if (src.vertices != TQualifier::layoutNotSet)
1172 vertices = src.vertices;
1173 if (src.spacing != EvsNone)
1174 spacing = src.spacing;
1175 if (src.order != EvoNone)
1176 order = src.order;
1177 if (src.pointMode)
1178 pointMode = true;
1179 for (int i = 0; i < 3; ++i) {
1180 if (src.localSize[i] > 1)
1181 localSize[i] = src.localSize[i];
1182 }
1183 for (int i = 0; i < 3; ++i) {
1184 if (src.localSizeSpecId[i] != TQualifier::layoutNotSet)
1185 localSizeSpecId[i] = src.localSizeSpecId[i];
1186 }
1187 if (src.earlyFragmentTests)
1188 earlyFragmentTests = true;
1189 if (src.postDepthCoverage)
1190 postDepthCoverage = true;
1191 if (src.layoutDepth)
1192 layoutDepth = src.layoutDepth;
1193 if (src.blendEquation)
1194 blendEquation = src.blendEquation;
1195 if (src.numViews != TQualifier::layoutNotSet)
1196 numViews = src.numViews;
1197 #ifdef NV_EXTENSIONS
1198 if (src.layoutOverrideCoverage)
1199 layoutOverrideCoverage = src.layoutOverrideCoverage;
1200 if (src.layoutDerivativeGroupQuads)
1201 layoutDerivativeGroupQuads = src.layoutDerivativeGroupQuads;
1202 if (src.layoutDerivativeGroupLinear)
1203 layoutDerivativeGroupLinear = src.layoutDerivativeGroupLinear;
1204 if (src.primitives != TQualifier::layoutNotSet)
1205 primitives = src.primitives;
1206 #endif
1207 }
1208 };
1209
1210 //
1211 // TPublicType is just temporarily used while parsing and not quite the same
1212 // information kept per node in TType. Due to the bison stack, it can't have
1213 // types that it thinks have non-trivial constructors. It should
1214 // just be used while recognizing the grammar, not anything else.
1215 // Once enough is known about the situation, the proper information
1216 // moved into a TType, or the parse context, etc.
1217 //
1218 class TPublicType {
1219 public:
1220 TBasicType basicType;
1221 TSampler sampler;
1222 TQualifier qualifier;
1223 TShaderQualifiers shaderQualifiers;
1224 int vectorSize : 4;
1225 int matrixCols : 4;
1226 int matrixRows : 4;
1227 TArraySizes* arraySizes;
1228 const TType* userDef;
1229 TSourceLoc loc;
1230
initType(const TSourceLoc & l)1231 void initType(const TSourceLoc& l)
1232 {
1233 basicType = EbtVoid;
1234 vectorSize = 1;
1235 matrixRows = 0;
1236 matrixCols = 0;
1237 arraySizes = nullptr;
1238 userDef = nullptr;
1239 loc = l;
1240 }
1241
1242 void initQualifiers(bool global = false)
1243 {
1244 qualifier.clear();
1245 if (global)
1246 qualifier.storage = EvqGlobal;
1247 }
1248
1249 void init(const TSourceLoc& l, bool global = false)
1250 {
1251 initType(l);
1252 sampler.clear();
1253 initQualifiers(global);
1254 shaderQualifiers.init();
1255 }
1256
setVector(int s)1257 void setVector(int s)
1258 {
1259 matrixRows = 0;
1260 matrixCols = 0;
1261 vectorSize = s;
1262 }
1263
setMatrix(int c,int r)1264 void setMatrix(int c, int r)
1265 {
1266 matrixRows = r;
1267 matrixCols = c;
1268 vectorSize = 0;
1269 }
1270
isScalar()1271 bool isScalar() const
1272 {
1273 return matrixCols == 0 && vectorSize == 1 && arraySizes == nullptr && userDef == nullptr;
1274 }
1275
1276 // "Image" is a superset of "Subpass"
isImage()1277 bool isImage() const { return basicType == EbtSampler && sampler.isImage(); }
isSubpass()1278 bool isSubpass() const { return basicType == EbtSampler && sampler.isSubpass(); }
1279 };
1280
1281 //
1282 // Base class for things that have a type.
1283 //
1284 class TType {
1285 public:
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator ())1286 POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
1287
1288 // for "empty" type (no args) or simple scalar/vector/matrix
1289 explicit TType(TBasicType t = EbtVoid, TStorageQualifier q = EvqTemporary, int vs = 1, int mc = 0, int mr = 0,
1290 bool isVector = false) :
1291 basicType(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), vector1(isVector && vs == 1),
1292 arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr)
1293 {
1294 sampler.clear();
1295 qualifier.clear();
1296 qualifier.storage = q;
1297 assert(!(isMatrix() && vectorSize != 0)); // prevent vectorSize != 0 on matrices
1298 }
1299 // for explicit precision qualifier
1300 TType(TBasicType t, TStorageQualifier q, TPrecisionQualifier p, int vs = 1, int mc = 0, int mr = 0,
1301 bool isVector = false) :
basicType(t)1302 basicType(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), vector1(isVector && vs == 1),
1303 arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr)
1304 {
1305 sampler.clear();
1306 qualifier.clear();
1307 qualifier.storage = q;
1308 qualifier.precision = p;
1309 assert(p >= EpqNone && p <= EpqHigh);
1310 assert(!(isMatrix() && vectorSize != 0)); // prevent vectorSize != 0 on matrices
1311 }
1312 // for turning a TPublicType into a TType, using a shallow copy
TType(const TPublicType & p)1313 explicit TType(const TPublicType& p) :
1314 basicType(p.basicType),
1315 vectorSize(p.vectorSize), matrixCols(p.matrixCols), matrixRows(p.matrixRows), vector1(false),
1316 arraySizes(p.arraySizes), structure(nullptr), fieldName(nullptr), typeName(nullptr)
1317 {
1318 if (basicType == EbtSampler)
1319 sampler = p.sampler;
1320 else
1321 sampler.clear();
1322 qualifier = p.qualifier;
1323 if (p.userDef) {
1324 if (p.userDef->basicType == EbtReference) {
1325 basicType = EbtReference;
1326 referentType = p.userDef->referentType;
1327 } else {
1328 structure = p.userDef->getWritableStruct(); // public type is short-lived; there are no sharing issues
1329 }
1330 typeName = NewPoolTString(p.userDef->getTypeName().c_str());
1331 }
1332 }
1333 // for construction of sampler types
1334 TType(const TSampler& sampler, TStorageQualifier q = EvqUniform, TArraySizes* as = nullptr) :
basicType(EbtSampler)1335 basicType(EbtSampler), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false),
1336 arraySizes(as), structure(nullptr), fieldName(nullptr), typeName(nullptr),
1337 sampler(sampler)
1338 {
1339 qualifier.clear();
1340 qualifier.storage = q;
1341 }
1342 // to efficiently make a dereferenced type
1343 // without ever duplicating the outer structure that will be thrown away
1344 // and using only shallow copy
1345 TType(const TType& type, int derefIndex, bool rowMajor = false)
1346 {
1347 if (type.isArray()) {
1348 shallowCopy(type);
1349 if (type.getArraySizes()->getNumDims() == 1) {
1350 arraySizes = nullptr;
1351 } else {
1352 // want our own copy of the array, so we can edit it
1353 arraySizes = new TArraySizes;
1354 arraySizes->copyDereferenced(*type.arraySizes);
1355 }
1356 } else if (type.basicType == EbtStruct || type.basicType == EbtBlock) {
1357 // do a structure dereference
1358 const TTypeList& memberList = *type.getStruct();
1359 shallowCopy(*memberList[derefIndex].type);
1360 return;
1361 } else {
1362 // do a vector/matrix dereference
1363 shallowCopy(type);
1364 if (matrixCols > 0) {
1365 // dereference from matrix to vector
1366 if (rowMajor)
1367 vectorSize = matrixCols;
1368 else
1369 vectorSize = matrixRows;
1370 matrixCols = 0;
1371 matrixRows = 0;
1372 if (vectorSize == 1)
1373 vector1 = true;
1374 } else if (isVector()) {
1375 // dereference from vector to scalar
1376 vectorSize = 1;
1377 vector1 = false;
1378 }
1379 }
1380 }
1381 // for making structures, ...
TType(TTypeList * userDef,const TString & n)1382 TType(TTypeList* userDef, const TString& n) :
1383 basicType(EbtStruct), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false),
1384 arraySizes(nullptr), structure(userDef), fieldName(nullptr)
1385 {
1386 sampler.clear();
1387 qualifier.clear();
1388 typeName = NewPoolTString(n.c_str());
1389 }
1390 // For interface blocks
TType(TTypeList * userDef,const TString & n,const TQualifier & q)1391 TType(TTypeList* userDef, const TString& n, const TQualifier& q) :
1392 basicType(EbtBlock), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false),
1393 qualifier(q), arraySizes(nullptr), structure(userDef), fieldName(nullptr)
1394 {
1395 sampler.clear();
1396 typeName = NewPoolTString(n.c_str());
1397 }
1398 // for block reference (first parameter must be EbtReference)
TType(TBasicType t,const TType & p,const TString & n)1399 explicit TType(TBasicType t, const TType &p, const TString& n) :
1400 basicType(t), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false),
1401 arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr)
1402 {
1403 assert(t == EbtReference);
1404 typeName = NewPoolTString(n.c_str());
1405 qualifier.clear();
1406 qualifier.storage = p.qualifier.storage;
1407 referentType = p.clone();
1408 }
~TType()1409 virtual ~TType() {}
1410
1411 // Not for use across pool pops; it will cause multiple instances of TType to point to the same information.
1412 // This only works if that information (like a structure's list of types) does not change and
1413 // the instances are sharing the same pool.
shallowCopy(const TType & copyOf)1414 void shallowCopy(const TType& copyOf)
1415 {
1416 basicType = copyOf.basicType;
1417 sampler = copyOf.sampler;
1418 qualifier = copyOf.qualifier;
1419 vectorSize = copyOf.vectorSize;
1420 matrixCols = copyOf.matrixCols;
1421 matrixRows = copyOf.matrixRows;
1422 vector1 = copyOf.vector1;
1423 arraySizes = copyOf.arraySizes; // copying the pointer only, not the contents
1424 fieldName = copyOf.fieldName;
1425 typeName = copyOf.typeName;
1426 if (isStruct()) {
1427 structure = copyOf.structure;
1428 } else {
1429 referentType = copyOf.referentType;
1430 }
1431 }
1432
1433 // Make complete copy of the whole type graph rooted at 'copyOf'.
deepCopy(const TType & copyOf)1434 void deepCopy(const TType& copyOf)
1435 {
1436 TMap<TTypeList*,TTypeList*> copied; // to enable copying a type graph as a graph, not a tree
1437 deepCopy(copyOf, copied);
1438 }
1439
1440 // Recursively make temporary
makeTemporary()1441 void makeTemporary()
1442 {
1443 getQualifier().makeTemporary();
1444
1445 if (isStruct())
1446 for (unsigned int i = 0; i < structure->size(); ++i)
1447 (*structure)[i].type->makeTemporary();
1448 }
1449
clone()1450 TType* clone() const
1451 {
1452 TType *newType = new TType();
1453 newType->deepCopy(*this);
1454
1455 return newType;
1456 }
1457
makeVector()1458 void makeVector() { vector1 = true; }
1459
hideMember()1460 virtual void hideMember() { basicType = EbtVoid; vectorSize = 1; }
hiddenMember()1461 virtual bool hiddenMember() const { return basicType == EbtVoid; }
1462
setFieldName(const TString & n)1463 virtual void setFieldName(const TString& n) { fieldName = NewPoolTString(n.c_str()); }
getTypeName()1464 virtual const TString& getTypeName() const
1465 {
1466 assert(typeName);
1467 return *typeName;
1468 }
1469
getFieldName()1470 virtual const TString& getFieldName() const
1471 {
1472 assert(fieldName);
1473 return *fieldName;
1474 }
1475
getBasicType()1476 virtual TBasicType getBasicType() const { return basicType; }
getSampler()1477 virtual const TSampler& getSampler() const { return sampler; }
getSampler()1478 virtual TSampler& getSampler() { return sampler; }
1479
getQualifier()1480 virtual TQualifier& getQualifier() { return qualifier; }
getQualifier()1481 virtual const TQualifier& getQualifier() const { return qualifier; }
1482
getVectorSize()1483 virtual int getVectorSize() const { return vectorSize; } // returns 1 for either scalar or vector of size 1, valid for both
getMatrixCols()1484 virtual int getMatrixCols() const { return matrixCols; }
getMatrixRows()1485 virtual int getMatrixRows() const { return matrixRows; }
getOuterArraySize()1486 virtual int getOuterArraySize() const { return arraySizes->getOuterSize(); }
getOuterArrayNode()1487 virtual TIntermTyped* getOuterArrayNode() const { return arraySizes->getOuterNode(); }
getCumulativeArraySize()1488 virtual int getCumulativeArraySize() const { return arraySizes->getCumulativeSize(); }
isArrayOfArrays()1489 virtual bool isArrayOfArrays() const { return arraySizes != nullptr && arraySizes->getNumDims() > 1; }
getImplicitArraySize()1490 virtual int getImplicitArraySize() const { return arraySizes->getImplicitSize(); }
getArraySizes()1491 virtual const TArraySizes* getArraySizes() const { return arraySizes; }
getArraySizes()1492 virtual TArraySizes* getArraySizes() { return arraySizes; }
getReferentType()1493 virtual TType* getReferentType() const { return referentType; }
1494
isScalar()1495 virtual bool isScalar() const { return ! isVector() && ! isMatrix() && ! isStruct() && ! isArray(); }
isScalarOrVec1()1496 virtual bool isScalarOrVec1() const { return isScalar() || vector1; }
isVector()1497 virtual bool isVector() const { return vectorSize > 1 || vector1; }
isMatrix()1498 virtual bool isMatrix() const { return matrixCols ? true : false; }
isArray()1499 virtual bool isArray() const { return arraySizes != nullptr; }
isSizedArray()1500 virtual bool isSizedArray() const { return isArray() && arraySizes->isSized(); }
isUnsizedArray()1501 virtual bool isUnsizedArray() const { return isArray() && !arraySizes->isSized(); }
isArrayVariablyIndexed()1502 virtual bool isArrayVariablyIndexed() const { assert(isArray()); return arraySizes->isVariablyIndexed(); }
setArrayVariablyIndexed()1503 virtual void setArrayVariablyIndexed() { assert(isArray()); arraySizes->setVariablyIndexed(); }
updateImplicitArraySize(int size)1504 virtual void updateImplicitArraySize(int size) { assert(isArray()); arraySizes->updateImplicitSize(size); }
isStruct()1505 virtual bool isStruct() const { return basicType == EbtStruct || basicType == EbtBlock; }
isFloatingDomain()1506 virtual bool isFloatingDomain() const { return basicType == EbtFloat || basicType == EbtDouble || basicType == EbtFloat16; }
isIntegerDomain()1507 virtual bool isIntegerDomain() const
1508 {
1509 switch (basicType) {
1510 case EbtInt8:
1511 case EbtUint8:
1512 case EbtInt16:
1513 case EbtUint16:
1514 case EbtInt:
1515 case EbtUint:
1516 case EbtInt64:
1517 case EbtUint64:
1518 case EbtAtomicUint:
1519 return true;
1520 default:
1521 break;
1522 }
1523 return false;
1524 }
isOpaque()1525 virtual bool isOpaque() const { return basicType == EbtSampler || basicType == EbtAtomicUint
1526 #ifdef NV_EXTENSIONS
1527 || basicType == EbtAccStructNV
1528 #endif
1529 ; }
isBuiltIn()1530 virtual bool isBuiltIn() const { return getQualifier().builtIn != EbvNone; }
1531
1532 // "Image" is a superset of "Subpass"
isImage()1533 virtual bool isImage() const { return basicType == EbtSampler && getSampler().isImage(); }
isSubpass()1534 virtual bool isSubpass() const { return basicType == EbtSampler && getSampler().isSubpass(); }
isTexture()1535 virtual bool isTexture() const { return basicType == EbtSampler && getSampler().isTexture(); }
1536
1537 // return true if this type contains any subtype which satisfies the given predicate.
1538 template <typename P>
contains(P predicate)1539 bool contains(P predicate) const
1540 {
1541 if (predicate(this))
1542 return true;
1543
1544 const auto hasa = [predicate](const TTypeLoc& tl) { return tl.type->contains(predicate); };
1545
1546 return isStruct() && std::any_of(structure->begin(), structure->end(), hasa);
1547 }
1548
1549 // Recursively checks if the type contains the given basic type
containsBasicType(TBasicType checkType)1550 virtual bool containsBasicType(TBasicType checkType) const
1551 {
1552 return contains([checkType](const TType* t) { return t->basicType == checkType; } );
1553 }
1554
1555 // Recursively check the structure for any arrays, needed for some error checks
containsArray()1556 virtual bool containsArray() const
1557 {
1558 return contains([](const TType* t) { return t->isArray(); } );
1559 }
1560
1561 // Check the structure for any structures, needed for some error checks
containsStructure()1562 virtual bool containsStructure() const
1563 {
1564 return contains([this](const TType* t) { return t != this && t->isStruct(); } );
1565 }
1566
1567 // Recursively check the structure for any unsized arrays, needed for triggering a copyUp().
containsUnsizedArray()1568 virtual bool containsUnsizedArray() const
1569 {
1570 return contains([](const TType* t) { return t->isUnsizedArray(); } );
1571 }
1572
containsOpaque()1573 virtual bool containsOpaque() const
1574 {
1575 return contains([](const TType* t) { return t->isOpaque(); } );
1576 }
1577
1578 // Recursively checks if the type contains a built-in variable
containsBuiltIn()1579 virtual bool containsBuiltIn() const
1580 {
1581 return contains([](const TType* t) { return t->isBuiltIn(); } );
1582 }
1583
containsNonOpaque()1584 virtual bool containsNonOpaque() const
1585 {
1586 const auto nonOpaque = [](const TType* t) {
1587 switch (t->basicType) {
1588 case EbtVoid:
1589 case EbtFloat:
1590 case EbtDouble:
1591 case EbtFloat16:
1592 case EbtInt8:
1593 case EbtUint8:
1594 case EbtInt16:
1595 case EbtUint16:
1596 case EbtInt:
1597 case EbtUint:
1598 case EbtInt64:
1599 case EbtUint64:
1600 case EbtBool:
1601 return true;
1602 default:
1603 return false;
1604 }
1605 };
1606
1607 return contains(nonOpaque);
1608 }
1609
containsSpecializationSize()1610 virtual bool containsSpecializationSize() const
1611 {
1612 return contains([](const TType* t) { return t->isArray() && t->arraySizes->isOuterSpecialization(); } );
1613 }
1614
contains16BitInt()1615 virtual bool contains16BitInt() const
1616 {
1617 return containsBasicType(EbtInt16) || containsBasicType(EbtUint16);
1618 }
1619
contains8BitInt()1620 virtual bool contains8BitInt() const
1621 {
1622 return containsBasicType(EbtInt8) || containsBasicType(EbtUint8);
1623 }
1624
1625 // Array editing methods. Array descriptors can be shared across
1626 // type instances. This allows all uses of the same array
1627 // to be updated at once. E.g., all nodes can be explicitly sized
1628 // by tracking and correcting one implicit size. Or, all nodes
1629 // can get the explicit size on a redeclaration that gives size.
1630 //
1631 // N.B.: Don't share with the shared symbol tables (symbols are
1632 // marked as isReadOnly(). Such symbols with arrays that will be
1633 // edited need to copyUp() on first use, so that
1634 // A) the edits don't effect the shared symbol table, and
1635 // B) the edits are shared across all users.
updateArraySizes(const TType & type)1636 void updateArraySizes(const TType& type)
1637 {
1638 // For when we may already be sharing existing array descriptors,
1639 // keeping the pointers the same, just updating the contents.
1640 assert(arraySizes != nullptr);
1641 assert(type.arraySizes != nullptr);
1642 *arraySizes = *type.arraySizes;
1643 }
copyArraySizes(const TArraySizes & s)1644 void copyArraySizes(const TArraySizes& s)
1645 {
1646 // For setting a fresh new set of array sizes, not yet worrying about sharing.
1647 arraySizes = new TArraySizes;
1648 *arraySizes = s;
1649 }
transferArraySizes(TArraySizes * s)1650 void transferArraySizes(TArraySizes* s)
1651 {
1652 // For setting an already allocated set of sizes that this type can use
1653 // (no copy made).
1654 arraySizes = s;
1655 }
clearArraySizes()1656 void clearArraySizes()
1657 {
1658 arraySizes = nullptr;
1659 }
1660
1661 // Add inner array sizes, to any existing sizes, via copy; the
1662 // sizes passed in can still be reused for other purposes.
copyArrayInnerSizes(const TArraySizes * s)1663 void copyArrayInnerSizes(const TArraySizes* s)
1664 {
1665 if (s != nullptr) {
1666 if (arraySizes == nullptr)
1667 copyArraySizes(*s);
1668 else
1669 arraySizes->addInnerSizes(*s);
1670 }
1671 }
changeOuterArraySize(int s)1672 void changeOuterArraySize(int s) { arraySizes->changeOuterSize(s); }
1673
1674 // Recursively make the implicit array size the explicit array size.
1675 // Expicit arrays are compile-time or link-time sized, never run-time sized.
1676 // Sometimes, policy calls for an array to be run-time sized even if it was
1677 // never variably indexed: Don't turn a 'skipNonvariablyIndexed' array into
1678 // an explicit array.
adoptImplicitArraySizes(bool skipNonvariablyIndexed)1679 void adoptImplicitArraySizes(bool skipNonvariablyIndexed)
1680 {
1681 if (isUnsizedArray() && !(skipNonvariablyIndexed || isArrayVariablyIndexed()))
1682 changeOuterArraySize(getImplicitArraySize());
1683 #ifdef NV_EXTENSIONS
1684 // For multi-dim per-view arrays, set unsized inner dimension size to 1
1685 if (qualifier.isPerView() && arraySizes && arraySizes->isInnerUnsized())
1686 arraySizes->clearInnerUnsized();
1687 #endif
1688 if (isStruct() && structure->size() > 0) {
1689 int lastMember = (int)structure->size() - 1;
1690 for (int i = 0; i < lastMember; ++i)
1691 (*structure)[i].type->adoptImplicitArraySizes(false);
1692 // implement the "last member of an SSBO" policy
1693 (*structure)[lastMember].type->adoptImplicitArraySizes(getQualifier().storage == EvqBuffer);
1694 }
1695 }
1696
getBasicString()1697 const char* getBasicString() const
1698 {
1699 return TType::getBasicString(basicType);
1700 }
1701
getBasicString(TBasicType t)1702 static const char* getBasicString(TBasicType t)
1703 {
1704 switch (t) {
1705 case EbtVoid: return "void";
1706 case EbtFloat: return "float";
1707 case EbtDouble: return "double";
1708 case EbtFloat16: return "float16_t";
1709 case EbtInt8: return "int8_t";
1710 case EbtUint8: return "uint8_t";
1711 case EbtInt16: return "int16_t";
1712 case EbtUint16: return "uint16_t";
1713 case EbtInt: return "int";
1714 case EbtUint: return "uint";
1715 case EbtInt64: return "int64_t";
1716 case EbtUint64: return "uint64_t";
1717 case EbtBool: return "bool";
1718 case EbtAtomicUint: return "atomic_uint";
1719 case EbtSampler: return "sampler/image";
1720 case EbtStruct: return "structure";
1721 case EbtBlock: return "block";
1722 #ifdef NV_EXTENSIONS
1723 case EbtAccStructNV: return "accelerationStructureNV";
1724 #endif
1725 case EbtReference: return "reference";
1726 default: return "unknown type";
1727 }
1728 }
1729
getCompleteString()1730 TString getCompleteString() const
1731 {
1732 TString typeString;
1733
1734 const auto appendStr = [&](const char* s) { typeString.append(s); };
1735 const auto appendUint = [&](unsigned int u) { typeString.append(std::to_string(u).c_str()); };
1736 const auto appendInt = [&](int i) { typeString.append(std::to_string(i).c_str()); };
1737
1738 if (qualifier.hasLayout()) {
1739 // To reduce noise, skip this if the only layout is an xfb_buffer
1740 // with no triggering xfb_offset.
1741 TQualifier noXfbBuffer = qualifier;
1742 noXfbBuffer.layoutXfbBuffer = TQualifier::layoutXfbBufferEnd;
1743 if (noXfbBuffer.hasLayout()) {
1744 appendStr("layout(");
1745 if (qualifier.hasAnyLocation()) {
1746 appendStr(" location=");
1747 appendUint(qualifier.layoutLocation);
1748 if (qualifier.hasComponent()) {
1749 appendStr(" component=");
1750 appendUint(qualifier.layoutComponent);
1751 }
1752 if (qualifier.hasIndex()) {
1753 appendStr(" index=");
1754 appendUint(qualifier.layoutIndex);
1755 }
1756 }
1757 if (qualifier.hasSet()) {
1758 appendStr(" set=");
1759 appendUint(qualifier.layoutSet);
1760 }
1761 if (qualifier.hasBinding()) {
1762 appendStr(" binding=");
1763 appendUint(qualifier.layoutBinding);
1764 }
1765 if (qualifier.hasStream()) {
1766 appendStr(" stream=");
1767 appendUint(qualifier.layoutStream);
1768 }
1769 if (qualifier.hasMatrix()) {
1770 appendStr(" ");
1771 appendStr(TQualifier::getLayoutMatrixString(qualifier.layoutMatrix));
1772 }
1773 if (qualifier.hasPacking()) {
1774 appendStr(" ");
1775 appendStr(TQualifier::getLayoutPackingString(qualifier.layoutPacking));
1776 }
1777 if (qualifier.hasOffset()) {
1778 appendStr(" offset=");
1779 appendInt(qualifier.layoutOffset);
1780 }
1781 if (qualifier.hasAlign()) {
1782 appendStr(" align=");
1783 appendInt(qualifier.layoutAlign);
1784 }
1785 if (qualifier.hasFormat()) {
1786 appendStr(" ");
1787 appendStr(TQualifier::getLayoutFormatString(qualifier.layoutFormat));
1788 }
1789 if (qualifier.hasXfbBuffer() && qualifier.hasXfbOffset()) {
1790 appendStr(" xfb_buffer=");
1791 appendUint(qualifier.layoutXfbBuffer);
1792 }
1793 if (qualifier.hasXfbOffset()) {
1794 appendStr(" xfb_offset=");
1795 appendUint(qualifier.layoutXfbOffset);
1796 }
1797 if (qualifier.hasXfbStride()) {
1798 appendStr(" xfb_stride=");
1799 appendUint(qualifier.layoutXfbStride);
1800 }
1801 if (qualifier.hasAttachment()) {
1802 appendStr(" input_attachment_index=");
1803 appendUint(qualifier.layoutAttachment);
1804 }
1805 if (qualifier.hasSpecConstantId()) {
1806 appendStr(" constant_id=");
1807 appendUint(qualifier.layoutSpecConstantId);
1808 }
1809 if (qualifier.layoutPushConstant)
1810 appendStr(" push_constant");
1811 if (qualifier.layoutBufferReference)
1812 appendStr(" buffer_reference");
1813 if (qualifier.hasBufferReferenceAlign()) {
1814 appendStr(" buffer_reference_align=");
1815 appendUint(1u << qualifier.layoutBufferReferenceAlign);
1816 }
1817
1818 #ifdef NV_EXTENSIONS
1819 if (qualifier.layoutPassthrough)
1820 appendStr(" passthrough");
1821 if (qualifier.layoutViewportRelative)
1822 appendStr(" layoutViewportRelative");
1823 if (qualifier.layoutSecondaryViewportRelativeOffset != -2048) {
1824 appendStr(" layoutSecondaryViewportRelativeOffset=");
1825 appendInt(qualifier.layoutSecondaryViewportRelativeOffset);
1826 }
1827 if (qualifier.layoutShaderRecordNV)
1828 appendStr(" shaderRecordNV");
1829 #endif
1830
1831 appendStr(")");
1832 }
1833 }
1834
1835 if (qualifier.invariant)
1836 appendStr(" invariant");
1837 if (qualifier.noContraction)
1838 appendStr(" noContraction");
1839 if (qualifier.centroid)
1840 appendStr(" centroid");
1841 if (qualifier.smooth)
1842 appendStr(" smooth");
1843 if (qualifier.flat)
1844 appendStr(" flat");
1845 if (qualifier.nopersp)
1846 appendStr(" noperspective");
1847 #ifdef AMD_EXTENSIONS
1848 if (qualifier.explicitInterp)
1849 appendStr(" __explicitInterpAMD");
1850 #endif
1851 #ifdef NV_EXTENSIONS
1852 if (qualifier.pervertexNV)
1853 appendStr(" pervertexNV");
1854 if (qualifier.perPrimitiveNV)
1855 appendStr(" perprimitiveNV");
1856 if (qualifier.perViewNV)
1857 appendStr(" perviewNV");
1858 if (qualifier.perTaskNV)
1859 appendStr(" taskNV");
1860 #endif
1861 if (qualifier.patch)
1862 appendStr(" patch");
1863 if (qualifier.sample)
1864 appendStr(" sample");
1865 if (qualifier.coherent)
1866 appendStr(" coherent");
1867 if (qualifier.devicecoherent)
1868 appendStr(" devicecoherent");
1869 if (qualifier.queuefamilycoherent)
1870 appendStr(" queuefamilycoherent");
1871 if (qualifier.workgroupcoherent)
1872 appendStr(" workgroupcoherent");
1873 if (qualifier.subgroupcoherent)
1874 appendStr(" subgroupcoherent");
1875 if (qualifier.nonprivate)
1876 appendStr(" nonprivate");
1877 if (qualifier.volatil)
1878 appendStr(" volatile");
1879 if (qualifier.restrict)
1880 appendStr(" restrict");
1881 if (qualifier.readonly)
1882 appendStr(" readonly");
1883 if (qualifier.writeonly)
1884 appendStr(" writeonly");
1885 if (qualifier.specConstant)
1886 appendStr(" specialization-constant");
1887 if (qualifier.nonUniform)
1888 appendStr(" nonuniform");
1889 appendStr(" ");
1890 appendStr(getStorageQualifierString());
1891 if (isArray()) {
1892 for(int i = 0; i < (int)arraySizes->getNumDims(); ++i) {
1893 int size = arraySizes->getDimSize(i);
1894 if (size == UnsizedArraySize && i == 0 && arraySizes->isVariablyIndexed())
1895 appendStr(" runtime-sized array of");
1896 else {
1897 if (size == UnsizedArraySize) {
1898 appendStr(" unsized");
1899 if (i == 0) {
1900 appendStr(" ");
1901 appendInt(arraySizes->getImplicitSize());
1902 }
1903 } else {
1904 appendStr(" ");
1905 appendInt(arraySizes->getDimSize(i));
1906 }
1907 appendStr("-element array of");
1908 }
1909 }
1910 }
1911 if (qualifier.precision != EpqNone) {
1912 appendStr(" ");
1913 appendStr(getPrecisionQualifierString());
1914 }
1915 if (isMatrix()) {
1916 appendStr(" ");
1917 appendInt(matrixCols);
1918 appendStr("X");
1919 appendInt(matrixRows);
1920 appendStr(" matrix of");
1921 } else if (isVector()) {
1922 appendStr(" ");
1923 appendInt(vectorSize);
1924 appendStr("-component vector of");
1925 }
1926
1927 appendStr(" ");
1928 typeString.append(getBasicTypeString());
1929
1930 if (qualifier.builtIn != EbvNone) {
1931 appendStr(" ");
1932 appendStr(getBuiltInVariableString());
1933 }
1934
1935 // Add struct/block members
1936 if (isStruct()) {
1937 appendStr("{");
1938 for (size_t i = 0; i < structure->size(); ++i) {
1939 if (! (*structure)[i].type->hiddenMember()) {
1940 typeString.append((*structure)[i].type->getCompleteString());
1941 typeString.append(" ");
1942 typeString.append((*structure)[i].type->getFieldName());
1943 if (i < structure->size() - 1)
1944 appendStr(", ");
1945 }
1946 }
1947 appendStr("}");
1948 }
1949
1950 return typeString;
1951 }
1952
getBasicTypeString()1953 TString getBasicTypeString() const
1954 {
1955 if (basicType == EbtSampler)
1956 return sampler.getString();
1957 else
1958 return getBasicString();
1959 }
1960
getStorageQualifierString()1961 const char* getStorageQualifierString() const { return GetStorageQualifierString(qualifier.storage); }
getBuiltInVariableString()1962 const char* getBuiltInVariableString() const { return GetBuiltInVariableString(qualifier.builtIn); }
getPrecisionQualifierString()1963 const char* getPrecisionQualifierString() const { return GetPrecisionQualifierString(qualifier.precision); }
getStruct()1964 const TTypeList* getStruct() const { assert(isStruct()); return structure; }
setStruct(TTypeList * s)1965 void setStruct(TTypeList* s) { assert(isStruct()); structure = s; }
getWritableStruct()1966 TTypeList* getWritableStruct() const { assert(isStruct()); return structure; } // This should only be used when known to not be sharing with other threads
1967
computeNumComponents()1968 int computeNumComponents() const
1969 {
1970 int components = 0;
1971
1972 if (getBasicType() == EbtStruct || getBasicType() == EbtBlock) {
1973 for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); tl++)
1974 components += ((*tl).type)->computeNumComponents();
1975 } else if (matrixCols)
1976 components = matrixCols * matrixRows;
1977 else
1978 components = vectorSize;
1979
1980 if (arraySizes != nullptr) {
1981 components *= arraySizes->getCumulativeSize();
1982 }
1983
1984 return components;
1985 }
1986
1987 // append this type's mangled name to the passed in 'name'
appendMangledName(TString & name)1988 void appendMangledName(TString& name) const
1989 {
1990 buildMangledName(name);
1991 name += ';' ;
1992 }
1993
1994 // Do two structure types match? They could be declared independently,
1995 // in different places, but still might satisfy the definition of matching.
1996 // From the spec:
1997 //
1998 // "Structures must have the same name, sequence of type names, and
1999 // type definitions, and member names to be considered the same type.
2000 // This rule applies recursively for nested or embedded types."
2001 //
sameStructType(const TType & right)2002 bool sameStructType(const TType& right) const
2003 {
2004 // Most commonly, they are both nullptr, or the same pointer to the same actual structure
2005 if ((!isStruct() && !right.isStruct()) ||
2006 (isStruct() && right.isStruct() && structure == right.structure))
2007 return true;
2008
2009 // Both being nullptr was caught above, now they both have to be structures of the same number of elements
2010 if (!isStruct() || !right.isStruct() ||
2011 structure->size() != right.structure->size())
2012 return false;
2013
2014 // Structure names have to match
2015 if (*typeName != *right.typeName)
2016 return false;
2017
2018 // Compare the names and types of all the members, which have to match
2019 for (unsigned int i = 0; i < structure->size(); ++i) {
2020 if ((*structure)[i].type->getFieldName() != (*right.structure)[i].type->getFieldName())
2021 return false;
2022
2023 if (*(*structure)[i].type != *(*right.structure)[i].type)
2024 return false;
2025 }
2026
2027 return true;
2028 }
2029
sameReferenceType(const TType & right)2030 bool sameReferenceType(const TType& right) const
2031 {
2032 if ((basicType == EbtReference) != (right.basicType == EbtReference))
2033 return false;
2034
2035 if ((basicType != EbtReference) && (right.basicType != EbtReference))
2036 return true;
2037
2038 assert(referentType != nullptr);
2039 assert(right.referentType != nullptr);
2040
2041 if (referentType == right.referentType)
2042 return true;
2043
2044 return *referentType == *right.referentType;
2045 }
2046
2047 // See if two types match, in all aspects except arrayness
sameElementType(const TType & right)2048 bool sameElementType(const TType& right) const
2049 {
2050 return basicType == right.basicType && sameElementShape(right);
2051 }
2052
2053 // See if two type's arrayness match
sameArrayness(const TType & right)2054 bool sameArrayness(const TType& right) const
2055 {
2056 return ((arraySizes == nullptr && right.arraySizes == nullptr) ||
2057 (arraySizes != nullptr && right.arraySizes != nullptr && *arraySizes == *right.arraySizes));
2058 }
2059
2060 // See if two type's arrayness match in everything except their outer dimension
sameInnerArrayness(const TType & right)2061 bool sameInnerArrayness(const TType& right) const
2062 {
2063 assert(arraySizes != nullptr && right.arraySizes != nullptr);
2064 return arraySizes->sameInnerArrayness(*right.arraySizes);
2065 }
2066
2067 // See if two type's elements match in all ways except basic type
sameElementShape(const TType & right)2068 bool sameElementShape(const TType& right) const
2069 {
2070 return sampler == right.sampler &&
2071 vectorSize == right.vectorSize &&
2072 matrixCols == right.matrixCols &&
2073 matrixRows == right.matrixRows &&
2074 vector1 == right.vector1 &&
2075 sameStructType(right) &&
2076 sameReferenceType(right);
2077 }
2078
2079 // See if two types match in all ways (just the actual type, not qualification)
2080 bool operator==(const TType& right) const
2081 {
2082 return sameElementType(right) && sameArrayness(right);
2083 }
2084
2085 bool operator!=(const TType& right) const
2086 {
2087 return ! operator==(right);
2088 }
2089
2090 protected:
2091 // Require consumer to pick between deep copy and shallow copy.
2092 TType(const TType& type);
2093 TType& operator=(const TType& type);
2094
2095 // Recursively copy a type graph, while preserving the graph-like
2096 // quality. That is, don't make more than one copy of a structure that
2097 // gets reused multiple times in the type graph.
deepCopy(const TType & copyOf,TMap<TTypeList *,TTypeList * > & copiedMap)2098 void deepCopy(const TType& copyOf, TMap<TTypeList*,TTypeList*>& copiedMap)
2099 {
2100 shallowCopy(copyOf);
2101
2102 if (copyOf.arraySizes) {
2103 arraySizes = new TArraySizes;
2104 *arraySizes = *copyOf.arraySizes;
2105 }
2106
2107 if (copyOf.isStruct() && copyOf.structure) {
2108 auto prevCopy = copiedMap.find(copyOf.structure);
2109 if (prevCopy != copiedMap.end())
2110 structure = prevCopy->second;
2111 else {
2112 structure = new TTypeList;
2113 copiedMap[copyOf.structure] = structure;
2114 for (unsigned int i = 0; i < copyOf.structure->size(); ++i) {
2115 TTypeLoc typeLoc;
2116 typeLoc.loc = (*copyOf.structure)[i].loc;
2117 typeLoc.type = new TType();
2118 typeLoc.type->deepCopy(*(*copyOf.structure)[i].type, copiedMap);
2119 structure->push_back(typeLoc);
2120 }
2121 }
2122 }
2123
2124 if (copyOf.fieldName)
2125 fieldName = NewPoolTString(copyOf.fieldName->c_str());
2126 if (copyOf.typeName)
2127 typeName = NewPoolTString(copyOf.typeName->c_str());
2128 }
2129
2130
2131 void buildMangledName(TString&) const;
2132
2133 TBasicType basicType : 8;
2134 int vectorSize : 4; // 1 means either scalar or 1-component vector; see vector1 to disambiguate.
2135 int matrixCols : 4;
2136 int matrixRows : 4;
2137 bool vector1 : 1; // Backward-compatible tracking of a 1-component vector distinguished from a scalar.
2138 // GLSL 4.5 never has a 1-component vector; so this will always be false until such
2139 // functionality is added.
2140 // HLSL does have a 1-component vectors, so this will be true to disambiguate
2141 // from a scalar.
2142 TQualifier qualifier;
2143
2144 TArraySizes* arraySizes; // nullptr unless an array; can be shared across types
2145 // A type can't be both a structure (EbtStruct/EbtBlock) and a reference (EbtReference), so
2146 // conserve space by making these a union
2147 union {
2148 TTypeList* structure; // invalid unless this is a struct; can be shared across types
2149 TType *referentType; // invalid unless this is an EbtReference
2150 };
2151 TString *fieldName; // for structure field names
2152 TString *typeName; // for structure type name
2153 TSampler sampler;
2154 };
2155
2156 } // end namespace glslang
2157
2158 #endif // _TYPES_INCLUDED_
2159