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