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 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. 96 unsigned int getVectorSize() const { return vectorSize; } 97 98 bool isImage() const { return image && dim != EsdSubpass; } 99 bool isSubpass() const { return dim == EsdSubpass; } 100 bool isCombined() const { return combined; } 101 bool isPureSampler() const { return sampler; } 102 bool isTexture() const { return !sampler && !image; } 103 bool isShadow() const { return shadow; } 104 bool isArrayed() const { return arrayed; } 105 bool isMultiSample() const { return ms; } 106 bool hasReturnStruct() const { return structReturnIndex != noReturnStruct; } 107 108 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 171 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 198 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 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 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 445 void clearInterstage() 446 { 447 clearInterpolation(); 448 patch = false; 449 sample = false; 450 } 451 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 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. 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 532 bool isMemory() const 533 { 534 return subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly || nonprivate; 535 } 536 bool isMemoryQualifierImageAndSSBOOnly() const 537 { 538 return subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly; 539 } 540 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 551 bool isExplicitInterpolation() const 552 { 553 return explicitInterp; 554 } 555 #endif 556 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 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 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 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 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 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 630 bool isPerPrimitive() const 631 { 632 #ifdef NV_EXTENSIONS 633 return perPrimitiveNV; 634 #else 635 return false; 636 #endif 637 } 638 639 bool isPerView() const 640 { 641 #ifdef NV_EXTENSIONS 642 return perViewNV; 643 #else 644 return false; 645 #endif 646 } 647 648 bool isTaskMemory() const 649 { 650 #ifdef NV_EXTENSIONS 651 return perTaskNV; 652 #else 653 return false; 654 #endif 655 } 656 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 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 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 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 } 741 void clearInterstageLayout() 742 { 743 layoutLocation = layoutLocationEnd; 744 layoutComponent = layoutComponentEnd; 745 layoutIndex = layoutIndexEnd; 746 clearStreamLayout(); 747 clearXfbLayout(); 748 } 749 void clearStreamLayout() 750 { 751 layoutStream = layoutStreamEnd; 752 } 753 void clearXfbLayout() 754 { 755 layoutXfbBuffer = layoutXfbBufferEnd; 756 layoutXfbStride = layoutXfbStrideEnd; 757 layoutXfbOffset = layoutXfbOffsetEnd; 758 } 759 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 } 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 831 bool hasUniformLayout() const 832 { 833 return hasMatrix() || 834 hasPacking() || 835 hasOffset() || 836 hasBinding() || 837 hasSet() || 838 hasAlign(); 839 } 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 852 bool hasMatrix() const 853 { 854 return layoutMatrix != ElmNone; 855 } 856 bool hasPacking() const 857 { 858 return layoutPacking != ElpNone; 859 } 860 bool hasOffset() const 861 { 862 return layoutOffset != layoutNotSet; 863 } 864 bool hasAlign() const 865 { 866 return layoutAlign != layoutNotSet; 867 } 868 bool hasAnyLocation() const 869 { 870 return hasLocation() || 871 hasComponent() || 872 hasIndex(); 873 } 874 bool hasLocation() const 875 { 876 return layoutLocation != layoutLocationEnd; 877 } 878 bool hasComponent() const 879 { 880 return layoutComponent != layoutComponentEnd; 881 } 882 bool hasIndex() const 883 { 884 return layoutIndex != layoutIndexEnd; 885 } 886 bool hasSet() const 887 { 888 return layoutSet != layoutSetEnd; 889 } 890 bool hasBinding() const 891 { 892 return layoutBinding != layoutBindingEnd; 893 } 894 bool hasStream() const 895 { 896 return layoutStream != layoutStreamEnd; 897 } 898 bool hasFormat() const 899 { 900 return layoutFormat != ElfNone; 901 } 902 bool hasXfb() const 903 { 904 return hasXfbBuffer() || 905 hasXfbStride() || 906 hasXfbOffset(); 907 } 908 bool hasXfbBuffer() const 909 { 910 return layoutXfbBuffer != layoutXfbBufferEnd; 911 } 912 bool hasXfbStride() const 913 { 914 return layoutXfbStride != layoutXfbStrideEnd; 915 } 916 bool hasXfbOffset() const 917 { 918 return layoutXfbOffset != layoutXfbOffsetEnd; 919 } 920 bool hasAttachment() const 921 { 922 return layoutAttachment != layoutAttachmentEnd; 923 } 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 } 930 bool hasBufferReferenceAlign() const 931 { 932 return layoutBufferReferenceAlign != layoutBufferReferenceAlignEnd; 933 } 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 } 941 bool isNonUniform() const 942 { 943 return nonUniform; 944 } 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 } 951 bool isConstant() const 952 { 953 // True if is either kind of constant; specialization or regular. 954 return isFrontEndConstant() || isSpecConstant(); 955 } 956 void makeSpecConstant() 957 { 958 storage = EvqConst; 959 specConstant = true; 960 } 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 } 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 } 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 } 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 } 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 } 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 } 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 } 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 } 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 1130 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. 1161 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 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 1257 void setVector(int s) 1258 { 1259 matrixRows = 0; 1260 matrixCols = 0; 1261 vectorSize = s; 1262 } 1263 1264 void setMatrix(int c, int r) 1265 { 1266 matrixRows = r; 1267 matrixCols = c; 1268 vectorSize = 0; 1269 } 1270 1271 bool isScalar() const 1272 { 1273 return matrixCols == 0 && vectorSize == 1 && arraySizes == nullptr && userDef == nullptr; 1274 } 1275 1276 // "Image" is a superset of "Subpass" 1277 bool isImage() const { return basicType == EbtSampler && sampler.isImage(); } 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: 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) : 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 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) : 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, ... 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 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) 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 } 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. 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'. 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 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 1450 TType* clone() const 1451 { 1452 TType *newType = new TType(); 1453 newType->deepCopy(*this); 1454 1455 return newType; 1456 } 1457 1458 void makeVector() { vector1 = true; } 1459 1460 virtual void hideMember() { basicType = EbtVoid; vectorSize = 1; } 1461 virtual bool hiddenMember() const { return basicType == EbtVoid; } 1462 1463 virtual void setFieldName(const TString& n) { fieldName = NewPoolTString(n.c_str()); } 1464 virtual const TString& getTypeName() const 1465 { 1466 assert(typeName); 1467 return *typeName; 1468 } 1469 1470 virtual const TString& getFieldName() const 1471 { 1472 assert(fieldName); 1473 return *fieldName; 1474 } 1475 1476 virtual TBasicType getBasicType() const { return basicType; } 1477 virtual const TSampler& getSampler() const { return sampler; } 1478 virtual TSampler& getSampler() { return sampler; } 1479 1480 virtual TQualifier& getQualifier() { return qualifier; } 1481 virtual const TQualifier& getQualifier() const { return qualifier; } 1482 1483 virtual int getVectorSize() const { return vectorSize; } // returns 1 for either scalar or vector of size 1, valid for both 1484 virtual int getMatrixCols() const { return matrixCols; } 1485 virtual int getMatrixRows() const { return matrixRows; } 1486 virtual int getOuterArraySize() const { return arraySizes->getOuterSize(); } 1487 virtual TIntermTyped* getOuterArrayNode() const { return arraySizes->getOuterNode(); } 1488 virtual int getCumulativeArraySize() const { return arraySizes->getCumulativeSize(); } 1489 virtual bool isArrayOfArrays() const { return arraySizes != nullptr && arraySizes->getNumDims() > 1; } 1490 virtual int getImplicitArraySize() const { return arraySizes->getImplicitSize(); } 1491 virtual const TArraySizes* getArraySizes() const { return arraySizes; } 1492 virtual TArraySizes* getArraySizes() { return arraySizes; } 1493 virtual TType* getReferentType() const { return referentType; } 1494 1495 virtual bool isScalar() const { return ! isVector() && ! isMatrix() && ! isStruct() && ! isArray(); } 1496 virtual bool isScalarOrVec1() const { return isScalar() || vector1; } 1497 virtual bool isVector() const { return vectorSize > 1 || vector1; } 1498 virtual bool isMatrix() const { return matrixCols ? true : false; } 1499 virtual bool isArray() const { return arraySizes != nullptr; } 1500 virtual bool isSizedArray() const { return isArray() && arraySizes->isSized(); } 1501 virtual bool isUnsizedArray() const { return isArray() && !arraySizes->isSized(); } 1502 virtual bool isArrayVariablyIndexed() const { assert(isArray()); return arraySizes->isVariablyIndexed(); } 1503 virtual void setArrayVariablyIndexed() { assert(isArray()); arraySizes->setVariablyIndexed(); } 1504 virtual void updateImplicitArraySize(int size) { assert(isArray()); arraySizes->updateImplicitSize(size); } 1505 virtual bool isStruct() const { return basicType == EbtStruct || basicType == EbtBlock; } 1506 virtual bool isFloatingDomain() const { return basicType == EbtFloat || basicType == EbtDouble || basicType == EbtFloat16; } 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 } 1525 virtual bool isOpaque() const { return basicType == EbtSampler || basicType == EbtAtomicUint 1526 #ifdef NV_EXTENSIONS 1527 || basicType == EbtAccStructNV 1528 #endif 1529 ; } 1530 virtual bool isBuiltIn() const { return getQualifier().builtIn != EbvNone; } 1531 1532 // "Image" is a superset of "Subpass" 1533 virtual bool isImage() const { return basicType == EbtSampler && getSampler().isImage(); } 1534 virtual bool isSubpass() const { return basicType == EbtSampler && getSampler().isSubpass(); } 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> 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 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 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 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(). 1568 virtual bool containsUnsizedArray() const 1569 { 1570 return contains([](const TType* t) { return t->isUnsizedArray(); } ); 1571 } 1572 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 1579 virtual bool containsBuiltIn() const 1580 { 1581 return contains([](const TType* t) { return t->isBuiltIn(); } ); 1582 } 1583 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 1610 virtual bool containsSpecializationSize() const 1611 { 1612 return contains([](const TType* t) { return t->isArray() && t->arraySizes->isOuterSpecialization(); } ); 1613 } 1614 1615 virtual bool contains16BitInt() const 1616 { 1617 return containsBasicType(EbtInt16) || containsBasicType(EbtUint16); 1618 } 1619 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. 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 } 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 } 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 } 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. 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 } 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. 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 1697 const char* getBasicString() const 1698 { 1699 return TType::getBasicString(basicType); 1700 } 1701 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 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 1953 TString getBasicTypeString() const 1954 { 1955 if (basicType == EbtSampler) 1956 return sampler.getString(); 1957 else 1958 return getBasicString(); 1959 } 1960 1961 const char* getStorageQualifierString() const { return GetStorageQualifierString(qualifier.storage); } 1962 const char* getBuiltInVariableString() const { return GetBuiltInVariableString(qualifier.builtIn); } 1963 const char* getPrecisionQualifierString() const { return GetPrecisionQualifierString(qualifier.precision); } 1964 const TTypeList* getStruct() const { assert(isStruct()); return structure; } 1965 void setStruct(TTypeList* s) { assert(isStruct()); structure = s; } 1966 TTypeList* getWritableStruct() const { assert(isStruct()); return structure; } // This should only be used when known to not be sharing with other threads 1967 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' 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 // 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 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 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 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 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 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. 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