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