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