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