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