Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
SkSLType.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
9
12#include "src/base/SkMathPriv.h"
13#include "src/base/SkSafeMath.h"
14#include "src/core/SkTHash.h"
20#include "src/sksl/SkSLString.h"
28
29#include <algorithm>
30#include <cstdint>
31#include <limits>
32#include <optional>
33#include <string_view>
34#include <utility>
35
36using namespace skia_private;
37
38namespace SkSL {
39
40static constexpr int kMaxStructDepth = 8;
41
42class AliasType final : public Type {
43public:
44 AliasType(std::string_view name, const Type& targetType)
45 : INHERITED(name, targetType.abbreviatedName(), targetType.typeKind())
46 , fTargetType(targetType) {}
47
48 const Type& resolve() const override {
49 return fTargetType;
50 }
51
52 const Type& componentType() const override {
53 return fTargetType.componentType();
54 }
55
56 NumberKind numberKind() const override {
57 return fTargetType.numberKind();
58 }
59
60 int priority() const override {
61 return fTargetType.priority();
62 }
63
64 int columns() const override {
65 return fTargetType.columns();
66 }
67
68 int rows() const override {
69 return fTargetType.rows();
70 }
71
72 int bitWidth() const override {
73 return fTargetType.bitWidth();
74 }
75
76 bool isAllowedInES2() const override {
77 return fTargetType.isAllowedInES2();
78 }
79
80 size_t slotCount() const override {
81 return fTargetType.slotCount();
82 }
83
84 const Type& slotType(size_t n) const override {
85 return fTargetType.slotType(n);
86 }
87
88 SpvDim_ dimensions() const override {
89 return fTargetType.dimensions();
90 }
91
92 bool isDepth() const override {
93 return fTargetType.isDepth();
94 }
95
96 bool isArrayedTexture() const override {
97 return fTargetType.isArrayedTexture();
98 }
99
100 bool isScalar() const override {
101 return fTargetType.isScalar();
102 }
103
104 bool isLiteral() const override {
105 return fTargetType.isLiteral();
106 }
107
108 bool isVector() const override {
109 return fTargetType.isVector();
110 }
111
112 bool isMatrix() const override {
113 return fTargetType.isMatrix();
114 }
115
116 bool isArray() const override {
117 return fTargetType.isArray();
118 }
119
120 bool isUnsizedArray() const override {
121 return fTargetType.isUnsizedArray();
122 }
123
124 bool isStruct() const override {
125 return fTargetType.isStruct();
126 }
127
128 bool isInterfaceBlock() const override {
129 return fTargetType.isInterfaceBlock();
130 }
131
132 bool isMultisampled() const override {
133 return fTargetType.isMultisampled();
134 }
135
136 TextureAccess textureAccess() const override {
137 return fTargetType.textureAccess();
138 }
139
141 return fTargetType.coercibleTypes();
142 }
143
144private:
145 using INHERITED = Type;
146
147 const Type& fTargetType;
148};
149
150class ArrayType final : public Type {
151public:
152 inline static constexpr TypeKind kTypeKind = TypeKind::kArray;
153
154 ArrayType(std::string_view name, const char* abbrev, const Type& componentType, int count,
155 bool isBuiltin)
156 : INHERITED(name, abbrev, kTypeKind)
157 , fComponentType(componentType)
158 , fCount(count)
159 , fIsBuiltin(isBuiltin) {
161 // Disallow multi-dimensional arrays.
163 }
164
165 bool isArray() const override {
166 return true;
167 }
168
169 bool isBuiltin() const override {
170 return fIsBuiltin;
171 }
172
173 bool isOrContainsArray() const override {
174 return true;
175 }
176
177 bool isOrContainsAtomic() const override {
178 return fComponentType.isOrContainsAtomic();
179 }
180
181 bool isUnsizedArray() const override {
182 return fCount == kUnsizedArray;
183 }
184
185 bool isOrContainsUnsizedArray() const override {
186 return this->isUnsizedArray() || fComponentType.isOrContainsUnsizedArray();
187 }
188
189 const Type& componentType() const override {
190 return fComponentType;
191 }
192
193 int columns() const override {
194 return fCount;
195 }
196
197 int bitWidth() const override {
198 return fComponentType.bitWidth();
199 }
200
201 bool isAllowedInES2() const override {
202 return fComponentType.isAllowedInES2();
203 }
204
205 bool isAllowedInUniform(Position* errorPosition) const override {
206 return fComponentType.isAllowedInUniform(errorPosition);
207 }
208
209 size_t slotCount() const override {
210 SkASSERT(fCount != kUnsizedArray);
211 SkASSERT(fCount > 0);
212 return fCount * fComponentType.slotCount();
213 }
214
215 const Type& slotType(size_t n) const override {
216 SkASSERT(fCount == kUnsizedArray || n < this->slotCount());
217 return fComponentType.slotType(n % fComponentType.slotCount());
218 }
219
220private:
221 using INHERITED = Type;
222
223 const Type& fComponentType;
224 int fCount;
225 bool fIsBuiltin;
226};
227
228class GenericType final : public Type {
229public:
230 inline static constexpr TypeKind kTypeKind = TypeKind::kGeneric;
231
233 : INHERITED(name, "G", kTypeKind)
234 , fSlotType(slotType) {
235 fNumTypes = coercibleTypes.size();
236 SkASSERT(fNumTypes <= std::size(fCoercibleTypes));
237 std::copy(coercibleTypes.begin(), coercibleTypes.end(), fCoercibleTypes);
238 }
239
241 return SkSpan(fCoercibleTypes, fNumTypes);
242 }
243
244 const Type& slotType(size_t) const override {
245 return *fSlotType;
246 }
247
248private:
249 using INHERITED = Type;
250
251 const Type* fCoercibleTypes[9];
252 const Type* fSlotType;
253 size_t fNumTypes;
254};
255
256class LiteralType : public Type {
257public:
258 inline static constexpr TypeKind kTypeKind = TypeKind::kLiteral;
259
260 LiteralType(const char* name, const Type& scalarType, int8_t priority)
261 : INHERITED(name, "L", kTypeKind)
262 , fScalarType(scalarType)
263 , fPriority(priority) {}
264
265 const Type& scalarTypeForLiteral() const override {
266 return fScalarType;
267 }
268
269 int priority() const override {
270 return fPriority;
271 }
272
273 int columns() const override {
274 return 1;
275 }
276
277 int rows() const override {
278 return 1;
279 }
280
281 NumberKind numberKind() const override {
282 return fScalarType.numberKind();
283 }
284
285 int bitWidth() const override {
286 return fScalarType.bitWidth();
287 }
288
289 double minimumValue() const override {
290 return fScalarType.minimumValue();
291 }
292
293 double maximumValue() const override {
294 return fScalarType.maximumValue();
295 }
296
297 bool isScalar() const override {
298 return true;
299 }
300
301 bool isLiteral() const override {
302 return true;
303 }
304
305 size_t slotCount() const override {
306 return 1;
307 }
308
309 const Type& slotType(size_t n) const override {
310 SkASSERT(n == 0);
311 return fScalarType;
312 }
313
314private:
315 using INHERITED = Type;
316
317 const Type& fScalarType;
318 int8_t fPriority;
319};
320
321
322class ScalarType final : public Type {
323public:
324 inline static constexpr TypeKind kTypeKind = TypeKind::kScalar;
325
326 ScalarType(std::string_view name, const char* abbrev, NumberKind numberKind, int8_t priority,
327 int8_t bitWidth)
328 : INHERITED(name, abbrev, kTypeKind)
329 , fNumberKind(numberKind)
330 , fPriority(priority)
331 , fBitWidth(bitWidth) {}
332
333 NumberKind numberKind() const override {
334 return fNumberKind;
335 }
336
337 int priority() const override {
338 return fPriority;
339 }
340
341 int bitWidth() const override {
342 return fBitWidth;
343 }
344
345 int columns() const override {
346 return 1;
347 }
348
349 int rows() const override {
350 return 1;
351 }
352
353 bool isScalar() const override {
354 return true;
355 }
356
357 bool isAllowedInES2() const override {
358 return fNumberKind != NumberKind::kUnsigned;
359 }
360
361 bool isAllowedInUniform(Position*) const override {
362 return fNumberKind != NumberKind::kBoolean;
363 }
364
365 size_t slotCount() const override {
366 return 1;
367 }
368
369 const Type& slotType(size_t n) const override {
370 SkASSERT(n == 0);
371 return *this;
372 }
373
374 using int_limits = std::numeric_limits<int32_t>;
375 using short_limits = std::numeric_limits<int16_t>;
376 using uint_limits = std::numeric_limits<uint32_t>;
377 using ushort_limits = std::numeric_limits<uint16_t>;
378 using float_limits = std::numeric_limits<float>;
379
380 /** Returns the maximum value that can fit in the type. */
381 double minimumValue() const override {
382 switch (this->numberKind()) {
384 return this->highPrecision() ? int_limits::lowest()
385 : short_limits::lowest();
386
388 return 0;
389
391 default:
392 return float_limits::lowest();
393 }
394 }
395
396 /** Returns the maximum value that can fit in the type. */
397 double maximumValue() const override {
398 switch (this->numberKind()) {
400 return this->highPrecision() ? int_limits::max()
401 : short_limits::max();
402
404 return this->highPrecision() ? uint_limits::max()
405 : ushort_limits::max();
406
408 default:
409 return float_limits::max();
410 }
411 }
412
413private:
414 using INHERITED = Type;
415
416 NumberKind fNumberKind;
417 int8_t fPriority;
418 int8_t fBitWidth;
419};
420
421class AtomicType final : public Type {
422public:
423 inline static constexpr TypeKind kTypeKind = TypeKind::kAtomic;
424
425 AtomicType(std::string_view name, const char* abbrev) : INHERITED(name, abbrev, kTypeKind) {}
426
427 bool isAllowedInES2() const override { return false; }
428
429 bool isAllowedInUniform(Position*) const override { return false; }
430
431 bool isOrContainsAtomic() const override { return true; }
432
433 const Type& slotType(size_t n) const override {
434 SkASSERT(n == 0);
435 return *this;
436 }
437
438private:
439 using INHERITED = Type;
440};
441
442class MatrixType final : public Type {
443public:
444 inline static constexpr TypeKind kTypeKind = TypeKind::kMatrix;
445
446 MatrixType(std::string_view name, const char* abbrev, const Type& componentType,
447 int8_t columns, int8_t rows)
448 : INHERITED(name, abbrev, kTypeKind)
449 , fComponentType(componentType.as<ScalarType>())
450 , fColumns(columns)
451 , fRows(rows) {
452 SkASSERT(columns >= 2 && columns <= 4);
453 SkASSERT(rows >= 2 && rows <= 4);
454 }
455
456 const ScalarType& componentType() const override {
457 return fComponentType;
458 }
459
460 int columns() const override {
461 return fColumns;
462 }
463
464 int rows() const override {
465 return fRows;
466 }
467
468 int bitWidth() const override {
469 return this->componentType().bitWidth();
470 }
471
472 bool isMatrix() const override {
473 return true;
474 }
475
476 bool isAllowedInES2() const override {
477 return fColumns == fRows;
478 }
479
480 size_t slotCount() const override {
481 return fColumns * fRows;
482 }
483
484 const Type& slotType(size_t n) const override {
485 SkASSERT(n < this->slotCount());
486 return fComponentType;
487 }
488
489private:
490 using INHERITED = Type;
491
492 const ScalarType& fComponentType;
493 int8_t fColumns;
494 int8_t fRows;
495};
496
497class TextureType final : public Type {
498public:
499 inline static constexpr TypeKind kTypeKind = TypeKind::kTexture;
500
501 TextureType(const char* name, SpvDim_ dimensions, bool isDepth, bool isArrayed,
503 : INHERITED(name, "T", kTypeKind)
504 , fDimensions(dimensions)
505 , fIsDepth(isDepth)
506 , fIsArrayed(isArrayed)
507 , fIsMultisampled(isMultisampled)
508 , fTextureAccess(textureAccess) {}
509
510 SpvDim_ dimensions() const override {
511 return fDimensions;
512 }
513
514 bool isDepth() const override {
515 return fIsDepth;
516 }
517
518 bool isArrayedTexture() const override {
519 return fIsArrayed;
520 }
521
522 bool isMultisampled() const override {
523 return fIsMultisampled;
524 }
525
526 TextureAccess textureAccess() const override {
527 return fTextureAccess;
528 }
529
530 const Type& slotType(size_t n) const override {
531 SkASSERT(n == 0);
532 return *this;
533 }
534
535private:
536 using INHERITED = Type;
537
538 SpvDim_ fDimensions;
539 bool fIsDepth;
540 bool fIsArrayed;
541 bool fIsMultisampled;
542 TextureAccess fTextureAccess;
543};
544
545class SamplerType final : public Type {
546public:
547 inline static constexpr TypeKind kTypeKind = TypeKind::kSampler;
548
549 SamplerType(const char* name, const Type& textureType)
550 : INHERITED(name, "Z", kTypeKind)
551 , fTextureType(textureType.as<TextureType>()) {
552 // Samplers require sampled texture access.
554 // Subpass inputs cannot be sampled.
556 }
557
558 const TextureType& textureType() const override {
559 return fTextureType;
560 }
561
562 SpvDim_ dimensions() const override {
563 return fTextureType.dimensions();
564 }
565
566 bool isDepth() const override {
567 return fTextureType.isDepth();
568 }
569
570 bool isArrayedTexture() const override {
571 return fTextureType.isArrayedTexture();
572 }
573
574 bool isMultisampled() const override {
575 return fTextureType.isMultisampled();
576 }
577
578 TextureAccess textureAccess() const override {
579 return fTextureType.textureAccess();
580 }
581
582 const Type& slotType(size_t n) const override {
583 SkASSERT(n == 0);
584 return *this;
585 }
586
587private:
588 using INHERITED = Type;
589
590 const TextureType& fTextureType;
591};
592
593class StructType final : public Type {
594public:
595 inline static constexpr TypeKind kTypeKind = TypeKind::kStruct;
596
597 StructType(Position pos, std::string_view name, TArray<Field> fields, int nestingDepth,
598 bool interfaceBlock, bool isBuiltin)
599 : INHERITED(std::move(name), "S", kTypeKind, pos)
600 , fFields(std::move(fields))
601 , fNestingDepth(nestingDepth)
602 , fInterfaceBlock(interfaceBlock)
603 , fIsBuiltin(isBuiltin) {
604 for (const Field& f : fFields) {
605 fContainsArray = fContainsArray || f.fType->isOrContainsArray();
606 fContainsUnsizedArray = fContainsUnsizedArray || f.fType->isOrContainsUnsizedArray();
607 fContainsAtomic = fContainsAtomic || f.fType->isOrContainsAtomic();
608 fIsAllowedInES2 = fIsAllowedInES2 && f.fType->isAllowedInES2();
609 }
610 for (const Field& f : fFields) {
611 Position errorPosition = f.fPosition;
612 if (!f.fType->isAllowedInUniform(&errorPosition)) {
613 fUniformErrorPosition = errorPosition;
614 break;
615 }
616 }
617 if (!fContainsUnsizedArray) {
618 for (const Field& f : fFields) {
619 fSlotCount += f.fType->slotCount();
620 }
621 }
622 }
623
624 SkSpan<const Field> fields() const override {
625 return fFields;
626 }
627
628 bool isStruct() const override {
629 return true;
630 }
631
632 bool isInterfaceBlock() const override {
633 return fInterfaceBlock;
634 }
635
636 bool isBuiltin() const override {
637 return fIsBuiltin;
638 }
639
640 bool isAllowedInES2() const override {
641 return fIsAllowedInES2;
642 }
643
644 bool isAllowedInUniform(Position* errorPosition) const override {
645 if (errorPosition != nullptr) {
646 *errorPosition = fUniformErrorPosition;
647 }
648 return !fUniformErrorPosition.valid();
649 }
650
651 bool isOrContainsArray() const override {
652 return fContainsArray;
653 }
654
655 bool isOrContainsUnsizedArray() const override {
656 return fContainsUnsizedArray;
657 }
658
659 bool isOrContainsAtomic() const override {
660 return fContainsAtomic;
661 }
662
663 size_t slotCount() const override {
664 SkASSERT(!fContainsUnsizedArray);
665 return fSlotCount;
666 }
667
668 int structNestingDepth() const override {
669 return fNestingDepth;
670 }
671
672 const Type& slotType(size_t n) const override {
673 for (const Field& field : fFields) {
674 size_t fieldSlots = field.fType->slotCount();
675 if (n < fieldSlots) {
676 return field.fType->slotType(n);
677 } else {
678 n -= fieldSlots;
679 }
680 }
681 SkDEBUGFAIL("slot index out of range");
682 return *this;
683 }
684
685private:
686 using INHERITED = Type;
687
688 TArray<Field> fFields;
689 size_t fSlotCount = 0;
690 int fNestingDepth = 0;
691 Position fUniformErrorPosition = {};
692 bool fInterfaceBlock = false;
693 bool fContainsArray = false;
694 bool fContainsUnsizedArray = false;
695 bool fContainsAtomic = false;
696 bool fIsBuiltin = false;
697 bool fIsAllowedInES2 = true;
698};
699
700class VectorType final : public Type {
701public:
702 inline static constexpr TypeKind kTypeKind = TypeKind::kVector;
703
704 VectorType(std::string_view name, const char* abbrev, const Type& componentType,
705 int8_t columns)
706 : INHERITED(name, abbrev, kTypeKind)
707 , fComponentType(componentType.as<ScalarType>())
708 , fColumns(columns) {
709 SkASSERT(columns >= 2 && columns <= 4);
710 }
711
712 const ScalarType& componentType() const override {
713 return fComponentType;
714 }
715
716 int columns() const override {
717 return fColumns;
718 }
719
720 int rows() const override {
721 return 1;
722 }
723
724 int bitWidth() const override {
725 return this->componentType().bitWidth();
726 }
727
728 bool isVector() const override {
729 return true;
730 }
731
732 bool isAllowedInES2() const override {
733 return fComponentType.isAllowedInES2();
734 }
735
736 bool isAllowedInUniform(Position* errorPosition) const override {
737 return fComponentType.isAllowedInUniform(errorPosition);
738 }
739
740 size_t slotCount() const override {
741 return fColumns;
742 }
743
744 const Type& slotType(size_t n) const override {
745 SkASSERT(n < SkToSizeT(fColumns));
746 return fComponentType;
747 }
748
749private:
750 using INHERITED = Type;
751
752 const ScalarType& fComponentType;
753 int8_t fColumns;
754};
755
756std::string Type::getArrayName(int arraySize) const {
757 std::string_view name = this->name();
758 if (arraySize == kUnsizedArray) {
759 return String::printf("%.*s[]", (int)name.size(), name.data());
760 }
761 return String::printf("%.*s[%d]", (int)name.size(), name.data(), arraySize);
762}
763
764std::unique_ptr<Type> Type::MakeAliasType(std::string_view name, const Type& targetType) {
765 return std::make_unique<AliasType>(std::move(name), targetType);
766}
767
768std::unique_ptr<Type> Type::MakeArrayType(const Context& context,
769 std::string_view name,
770 const Type& componentType,
771 int columns) {
772 return std::make_unique<ArrayType>(std::move(name), componentType.abbreviatedName(),
774}
775
776std::unique_ptr<Type> Type::MakeGenericType(const char* name,
778 const Type* slotType) {
779 return std::make_unique<GenericType>(name, types, slotType);
780}
781
782std::unique_ptr<Type> Type::MakeLiteralType(const char* name, const Type& scalarType,
783 int8_t priority) {
784 return std::make_unique<LiteralType>(name, scalarType, priority);
785}
786
787std::unique_ptr<Type> Type::MakeMatrixType(std::string_view name, const char* abbrev,
788 const Type& componentType, int columns, int8_t rows) {
789 return std::make_unique<MatrixType>(name, abbrev, componentType, columns, rows);
790}
791
792std::unique_ptr<Type> Type::MakeSamplerType(const char* name, const Type& textureType) {
793 return std::make_unique<SamplerType>(name, textureType);
794}
795
796std::unique_ptr<Type> Type::MakeSpecialType(const char* name, const char* abbrev,
797 Type::TypeKind typeKind) {
798 return std::unique_ptr<Type>(new Type(name, abbrev, typeKind));
799}
800
801std::unique_ptr<Type> Type::MakeScalarType(std::string_view name, const char* abbrev,
802 Type::NumberKind numberKind, int8_t priority,
803 int8_t bitWidth) {
804 return std::make_unique<ScalarType>(name, abbrev, numberKind, priority, bitWidth);
805}
806
807std::unique_ptr<Type> Type::MakeAtomicType(std::string_view name, const char* abbrev) {
808 return std::make_unique<AtomicType>(name, abbrev);
809}
810
811std::unique_ptr<Type> Type::MakeStructType(const Context& context,
813 std::string_view name,
814 TArray<Field> fields,
815 bool interfaceBlock) {
816 const char* const structOrIB = interfaceBlock ? "interface block" : "struct";
817 const char* const aStructOrIB = interfaceBlock ? "an interface block" : "a struct";
818
819 if (fields.empty()) {
820 context.fErrors->error(pos, std::string(structOrIB) + " '" + std::string(name) +
821 "' must contain at least one field");
822 }
823 size_t slots = 0;
824
826 for (const Field& field : fields) {
827 // Add this field name to our set; if the set doesn't grow, we found a duplicate.
828 int numFieldNames = fieldNames.count();
829 fieldNames.add(field.fName);
830 if (fieldNames.count() == numFieldNames) {
831 context.fErrors->error(field.fPosition, "field '" + std::string(field.fName) +
832 "' was already defined in the same " +
833 std::string(structOrIB) + " ('" +
834 std::string(name) + "')");
835 }
836 if (field.fModifierFlags != ModifierFlag::kNone) {
837 std::string desc = field.fModifierFlags.description();
838 context.fErrors->error(field.fPosition, "modifier '" + desc + "' is not permitted on " +
839 std::string(aStructOrIB) + " field");
840 }
841 if (field.fLayout.fFlags & LayoutFlag::kBinding) {
842 context.fErrors->error(field.fPosition, "layout qualifier 'binding' is not permitted "
843 "on " + std::string(aStructOrIB) + " field");
844 }
845 if (field.fLayout.fFlags & LayoutFlag::kSet) {
846 context.fErrors->error(field.fPosition, "layout qualifier 'set' is not permitted on " +
847 std::string(aStructOrIB) + " field");
848 }
849
850 if (field.fType->isVoid()) {
851 context.fErrors->error(field.fPosition, "type 'void' is not permitted in " +
852 std::string(aStructOrIB));
853 }
854 if (field.fType->isOpaque() && !field.fType->isAtomic()) {
855 context.fErrors->error(field.fPosition, "opaque type '" + field.fType->displayName() +
856 "' is not permitted in " +
857 std::string(aStructOrIB));
858 }
859 if (field.fType->isOrContainsUnsizedArray()) {
860 if (!interfaceBlock) {
861 // Reject unsized arrays anywhere in structs.
862 context.fErrors->error(field.fPosition, "unsized arrays are not permitted here");
863 }
864 } else {
865 // If we haven't already exceeded the struct size limit...
866 if (slots < kVariableSlotLimit) {
867 // ... see if this field causes us to exceed the size limit.
868 slots = SkSafeMath::Add(slots, field.fType->slotCount());
869 if (slots >= kVariableSlotLimit) {
870 context.fErrors->error(pos, std::string(structOrIB) + " is too large");
871 }
872 }
873 }
874 }
875 int nestingDepth = 0;
876 for (const Field& field : fields) {
877 nestingDepth = std::max(nestingDepth, field.fType->structNestingDepth());
878 }
879 if (nestingDepth >= kMaxStructDepth) {
880 context.fErrors->error(pos, std::string(structOrIB) + " '" + std::string(name) +
881 "' is too deeply nested");
882 }
883 return std::make_unique<StructType>(pos, name, std::move(fields), nestingDepth + 1,
884 interfaceBlock, context.fConfig->fIsBuiltinCode);
885}
886
887std::unique_ptr<Type> Type::MakeTextureType(const char* name, SpvDim_ dimensions, bool isDepth,
888 bool isArrayedTexture, bool isMultisampled,
889 TextureAccess textureAccess) {
890 return std::make_unique<TextureType>(name, dimensions, isDepth, isArrayedTexture,
892}
893
894std::unique_ptr<Type> Type::MakeVectorType(std::string_view name, const char* abbrev,
895 const Type& componentType, int columns) {
896 return std::make_unique<VectorType>(name, abbrev, componentType, columns);
897}
898
900 if (this->matches(other)) {
901 return CoercionCost::Free();
902 }
903 if (this->typeKind() == other.typeKind() &&
904 (this->isVector() || this->isMatrix() || this->isArray())) {
905 // Vectors/matrices/arrays of the same size can be coerced if their component type can be.
906 if (this->isMatrix() && (this->rows() != other.rows())) {
908 }
909 if (this->columns() != other.columns()) {
911 }
912 return this->componentType().coercionCost(other.componentType());
913 }
914 if (this->isNumber() && other.isNumber()) {
915 if (this->isLiteral() && this->isInteger()) {
916 return CoercionCost::Free();
917 } else if (this->numberKind() != other.numberKind()) {
919 } else if (other.priority() >= this->priority()) {
920 return CoercionCost::Normal(other.priority() - this->priority());
921 } else {
922 return CoercionCost::Narrowing(this->priority() - other.priority());
923 }
924 }
925 if (fTypeKind == TypeKind::kGeneric) {
927 for (size_t i = 0; i < types.size(); i++) {
928 if (types[i]->matches(other)) {
929 return CoercionCost::Normal((int) i + 1);
930 }
931 }
932 }
934}
935
936const Type* Type::applyQualifiers(const Context& context,
937 ModifierFlags* modifierFlags,
938 Position pos) const {
939 const Type* type;
940 type = this->applyPrecisionQualifiers(context, modifierFlags, pos);
941 type = type->applyAccessQualifiers(context, modifierFlags, pos);
942 return type;
943}
944
946 ModifierFlags* modifierFlags,
947 Position pos) const {
948 ModifierFlags precisionQualifiers = *modifierFlags & (ModifierFlag::kHighp |
951 if (precisionQualifiers == ModifierFlag::kNone) {
952 // No precision qualifiers here. Return the type as-is.
953 return this;
954 }
955
957 // We want to discourage precision modifiers internally. Instead, use the type that
958 // corresponds to the precision you need. (e.g. half vs float, short vs int)
959 context.fErrors->error(pos, "precision qualifiers are not allowed");
960 return context.fTypes.fPoison.get();
961 }
962
963 if (SkPopCount(precisionQualifiers.value()) > 1) {
964 context.fErrors->error(pos, "only one precision qualifier can be used");
965 return context.fTypes.fPoison.get();
966 }
967
968 // We're going to return a whole new type, so the modifier bits can be cleared out.
969 *modifierFlags &= ~(ModifierFlag::kHighp |
972
973 const Type& component = this->componentType();
974 if (component.highPrecision()) {
975 if (precisionQualifiers & ModifierFlag::kHighp) {
976 // Type is already high precision, and we are requesting high precision. Return as-is.
977 return this;
978 }
979
980 // SkSL doesn't support low precision, so `lowp` is interpreted as medium precision.
981 // Ascertain the mediump equivalent type for this type, if any.
982 const Type* mediumpType;
983 switch (component.numberKind()) {
985 mediumpType = context.fTypes.fHalf.get();
986 break;
987
989 mediumpType = context.fTypes.fShort.get();
990 break;
991
993 mediumpType = context.fTypes.fUShort.get();
994 break;
995
996 default:
997 mediumpType = context.fTypes.fPoison.get();
998 break;
999 }
1000
1001 if (mediumpType) {
1002 // Convert the mediump component type into the final vector/matrix/array type as needed.
1003 return this->isArray()
1004 ? context.fSymbolTable->addArrayDimension(context, mediumpType, this->columns())
1005 : &mediumpType->toCompound(context, this->columns(), this->rows());
1006 }
1007 }
1008
1009 context.fErrors->error(pos, "type '" + this->displayName() +
1010 "' does not support precision qualifiers");
1011 return context.fTypes.fPoison.get();
1012}
1013
1015 ModifierFlags* modifierFlags,
1016 Position pos) const {
1017 ModifierFlags accessQualifiers = *modifierFlags & (ModifierFlag::kReadOnly |
1019
1020 // We're going to return a whole new type, so the modifier bits must be cleared out.
1021 *modifierFlags &= ~(ModifierFlag::kReadOnly |
1023
1024 if (this->matches(*context.fTypes.fTexture2D)) {
1025 // We require all texture2Ds to be qualified with `readonly` or `writeonly`.
1026 // (Read-write textures are not yet supported in WGSL.)
1027 if (accessQualifiers == ModifierFlag::kReadOnly) {
1028 return context.fTypes.fReadOnlyTexture2D.get();
1029 }
1030 if (accessQualifiers == ModifierFlag::kWriteOnly) {
1031 return context.fTypes.fWriteOnlyTexture2D.get();
1032 }
1033 context.fErrors->error(
1034 pos,
1035 accessQualifiers
1036 ? "'readonly' and 'writeonly' qualifiers cannot be combined"
1037 : "'texture2D' requires a 'readonly' or 'writeonly' access qualifier");
1038 return this;
1039 }
1040
1041 if (accessQualifiers) {
1042 context.fErrors->error(pos, "type '" + this->displayName() + "' does not support "
1043 "qualifier '" + accessQualifiers.description() + "'");
1044 }
1045
1046 return this;
1047}
1048
1049const Type& Type::toCompound(const Context& context, int columns, int rows) const {
1050 SkASSERT(this->isScalar());
1051 if (columns == 1 && rows == 1) {
1052 return *this;
1053 }
1054 if (this->matches(*context.fTypes.fFloat) || this->matches(*context.fTypes.fFloatLiteral)) {
1055 switch (rows) {
1056 case 1:
1057 switch (columns) {
1058 case 1: return *context.fTypes.fFloat;
1059 case 2: return *context.fTypes.fFloat2;
1060 case 3: return *context.fTypes.fFloat3;
1061 case 4: return *context.fTypes.fFloat4;
1062 default: SK_ABORT("unsupported vector column count (%d)", columns);
1063 }
1064 case 2:
1065 switch (columns) {
1066 case 2: return *context.fTypes.fFloat2x2;
1067 case 3: return *context.fTypes.fFloat3x2;
1068 case 4: return *context.fTypes.fFloat4x2;
1069 default: SK_ABORT("unsupported matrix column count (%d)", columns);
1070 }
1071 case 3:
1072 switch (columns) {
1073 case 2: return *context.fTypes.fFloat2x3;
1074 case 3: return *context.fTypes.fFloat3x3;
1075 case 4: return *context.fTypes.fFloat4x3;
1076 default: SK_ABORT("unsupported matrix column count (%d)", columns);
1077 }
1078 case 4:
1079 switch (columns) {
1080 case 2: return *context.fTypes.fFloat2x4;
1081 case 3: return *context.fTypes.fFloat3x4;
1082 case 4: return *context.fTypes.fFloat4x4;
1083 default: SK_ABORT("unsupported matrix column count (%d)", columns);
1084 }
1085 default: SK_ABORT("unsupported row count (%d)", rows);
1086 }
1087 } else if (this->matches(*context.fTypes.fHalf)) {
1088 switch (rows) {
1089 case 1:
1090 switch (columns) {
1091 case 1: return *context.fTypes.fHalf;
1092 case 2: return *context.fTypes.fHalf2;
1093 case 3: return *context.fTypes.fHalf3;
1094 case 4: return *context.fTypes.fHalf4;
1095 default: SK_ABORT("unsupported vector column count (%d)", columns);
1096 }
1097 case 2:
1098 switch (columns) {
1099 case 2: return *context.fTypes.fHalf2x2;
1100 case 3: return *context.fTypes.fHalf3x2;
1101 case 4: return *context.fTypes.fHalf4x2;
1102 default: SK_ABORT("unsupported matrix column count (%d)", columns);
1103 }
1104 case 3:
1105 switch (columns) {
1106 case 2: return *context.fTypes.fHalf2x3;
1107 case 3: return *context.fTypes.fHalf3x3;
1108 case 4: return *context.fTypes.fHalf4x3;
1109 default: SK_ABORT("unsupported matrix column count (%d)", columns);
1110 }
1111 case 4:
1112 switch (columns) {
1113 case 2: return *context.fTypes.fHalf2x4;
1114 case 3: return *context.fTypes.fHalf3x4;
1115 case 4: return *context.fTypes.fHalf4x4;
1116 default: SK_ABORT("unsupported matrix column count (%d)", columns);
1117 }
1118 default: SK_ABORT("unsupported row count (%d)", rows);
1119 }
1120 } else if (this->matches(*context.fTypes.fInt) || this->matches(*context.fTypes.fIntLiteral)) {
1121 switch (rows) {
1122 case 1:
1123 switch (columns) {
1124 case 1: return *context.fTypes.fInt;
1125 case 2: return *context.fTypes.fInt2;
1126 case 3: return *context.fTypes.fInt3;
1127 case 4: return *context.fTypes.fInt4;
1128 default: SK_ABORT("unsupported vector column count (%d)", columns);
1129 }
1130 default: SK_ABORT("unsupported row count (%d)", rows);
1131 }
1132 } else if (this->matches(*context.fTypes.fShort)) {
1133 switch (rows) {
1134 case 1:
1135 switch (columns) {
1136 case 1: return *context.fTypes.fShort;
1137 case 2: return *context.fTypes.fShort2;
1138 case 3: return *context.fTypes.fShort3;
1139 case 4: return *context.fTypes.fShort4;
1140 default: SK_ABORT("unsupported vector column count (%d)", columns);
1141 }
1142 default: SK_ABORT("unsupported row count (%d)", rows);
1143 }
1144 } else if (this->matches(*context.fTypes.fUInt)) {
1145 switch (rows) {
1146 case 1:
1147 switch (columns) {
1148 case 1: return *context.fTypes.fUInt;
1149 case 2: return *context.fTypes.fUInt2;
1150 case 3: return *context.fTypes.fUInt3;
1151 case 4: return *context.fTypes.fUInt4;
1152 default: SK_ABORT("unsupported vector column count (%d)", columns);
1153 }
1154 default: SK_ABORT("unsupported row count (%d)", rows);
1155 }
1156 } else if (this->matches(*context.fTypes.fUShort)) {
1157 switch (rows) {
1158 case 1:
1159 switch (columns) {
1160 case 1: return *context.fTypes.fUShort;
1161 case 2: return *context.fTypes.fUShort2;
1162 case 3: return *context.fTypes.fUShort3;
1163 case 4: return *context.fTypes.fUShort4;
1164 default: SK_ABORT("unsupported vector column count (%d)", columns);
1165 }
1166 default: SK_ABORT("unsupported row count (%d)", rows);
1167 }
1168 } else if (this->matches(*context.fTypes.fBool)) {
1169 switch (rows) {
1170 case 1:
1171 switch (columns) {
1172 case 1: return *context.fTypes.fBool;
1173 case 2: return *context.fTypes.fBool2;
1174 case 3: return *context.fTypes.fBool3;
1175 case 4: return *context.fTypes.fBool4;
1176 default: SK_ABORT("unsupported vector column count (%d)", columns);
1177 }
1178 default: SK_ABORT("unsupported row count (%d)", rows);
1179 }
1180 }
1181 SkDEBUGFAILF("unsupported toCompound type %s", this->description().c_str());
1182 return *context.fTypes.fVoid;
1183}
1184
1185const Type* Type::clone(const Context& context, SymbolTable* symbolTable) const {
1186 // Many types are built-ins, and exist in every SymbolTable by default.
1187 if (this->isInRootSymbolTable()) {
1188 return this;
1189 }
1190 // If we are compiling a program, and the type comes from the program's module, it is safe to
1191 // assume that the type is in-scope anywhere in the program without actually recursing through
1192 // the SymbolTable hierarchy to prove it.
1193 if (!context.fConfig->fIsBuiltinCode && this->isBuiltin()) {
1194 return this;
1195 }
1196 // Even if the type isn't a built-in, it might already exist in the SymbolTable. Search by name.
1197 const Symbol* existingSymbol = symbolTable->find(this->name());
1198 if (existingSymbol != nullptr) {
1199 const Type* existingType = &existingSymbol->as<Type>();
1200 SkASSERT(existingType->typeKind() == this->typeKind());
1201 return existingType;
1202 }
1203 // This type actually needs to be cloned into the destination SymbolTable.
1204 switch (this->typeKind()) {
1205 case TypeKind::kArray: {
1206 return symbolTable->addArrayDimension(context, &this->componentType(), this->columns());
1207 }
1208 case TypeKind::kStruct: {
1209 // We are cloning an existing struct, so there's no need to call MakeStructType and
1210 // fully error-check it again.
1211 const std::string* name = symbolTable->takeOwnershipOfString(std::string(this->name()));
1212 SkSpan<const Field> fieldSpan = this->fields();
1213 return symbolTable->add(
1214 context,
1215 std::make_unique<StructType>(this->fPosition,
1216 *name,
1217 TArray<Field>(fieldSpan.data(), fieldSpan.size()),
1218 this->structNestingDepth(),
1219 /*interfaceBlock=*/this->isInterfaceBlock(),
1220 /*isBuiltin=*/context.fConfig->fIsBuiltinCode));
1221 }
1222 default:
1223 SkDEBUGFAILF("don't know how to clone type '%s'", this->description().c_str());
1224 return nullptr;
1225 }
1226}
1227
1228std::unique_ptr<Expression> Type::coerceExpression(std::unique_ptr<Expression> expr,
1229 const Context& context) const {
1230 if (!expr || expr->isIncomplete(context)) {
1231 return nullptr;
1232 }
1233 if (expr->type().matches(*this)) {
1234 return expr;
1235 }
1236
1237 const Position pos = expr->fPosition;
1238 const ProgramSettings& settings = context.fConfig->fSettings;
1239 if (!expr->coercionCost(*this).isPossible(settings.fAllowNarrowingConversions)) {
1240 context.fErrors->error(pos, "expected '" + this->displayName() + "', but found '" +
1241 expr->type().displayName() + "'");
1242 return nullptr;
1243 }
1244
1245 if (this->isScalar()) {
1246 return ConstructorScalarCast::Make(context, pos, *this, std::move(expr));
1247 }
1248 if (this->isVector() || this->isMatrix()) {
1249 return ConstructorCompoundCast::Make(context, pos, *this, std::move(expr));
1250 }
1251 if (this->isArray()) {
1252 return ConstructorArrayCast::Make(context, pos, *this, std::move(expr));
1253 }
1254 context.fErrors->error(pos, "cannot construct '" + this->displayName() + "'");
1255 return nullptr;
1256}
1257
1258bool Type::isAllowedInES2(const Context& context) const {
1259 return !context.fConfig->strictES2Mode() || this->isAllowedInES2();
1260}
1261
1262bool Type::checkForOutOfRangeLiteral(const Context& context, const Expression& expr) const {
1263 bool foundError = false;
1264 const Type& baseType = this->componentType();
1265 if (baseType.isNumber()) {
1266 // Replace constant expressions with their corresponding values.
1268 if (valueExpr->supportsConstantValues()) {
1269 // Iterate over every constant subexpression in the value.
1270 int numSlots = valueExpr->type().slotCount();
1271 for (int slot = 0; slot < numSlots; ++slot) {
1272 std::optional<double> slotVal = valueExpr->getConstantValue(slot);
1273 // Check for Literal values that are out of range for the base type.
1274 if (slotVal.has_value() &&
1275 baseType.checkForOutOfRangeLiteral(context, *slotVal, valueExpr->fPosition)) {
1276 foundError = true;
1277 }
1278 }
1279 }
1280 }
1281
1282 // We don't need range checks for floats or booleans; any matched-type value is acceptable.
1283 return foundError;
1284}
1285
1286bool Type::checkForOutOfRangeLiteral(const Context& context, double value, Position pos) const {
1287 SkASSERT(this->isScalar());
1288 if (!this->isNumber()) {
1289 return false;
1290 }
1291 if (value >= this->minimumValue() && value <= this->maximumValue()) {
1292 return false;
1293 }
1294 // We found a value that can't fit in our type. Flag it as an error.
1295 context.fErrors->error(pos, SkSL::String::printf("value is out of range for type '%s': %.0f",
1296 this->displayName().c_str(),
1297 value));
1298 return true;
1299}
1300
1301bool Type::checkIfUsableInArray(const Context& context, Position arrayPos) const {
1302 if (this->isArray()) {
1303 context.fErrors->error(arrayPos, "multi-dimensional arrays are not supported");
1304 return false;
1305 }
1306 if (this->isVoid()) {
1307 context.fErrors->error(arrayPos, "type 'void' may not be used in an array");
1308 return false;
1309 }
1310 if (this->isOpaque() && !this->isAtomic()) {
1311 context.fErrors->error(arrayPos, "opaque type '" + std::string(this->name()) +
1312 "' may not be used in an array");
1313 return false;
1314 }
1315 return true;
1316}
1317
1319 Position arrayPos,
1320 std::unique_ptr<Expression> size) const {
1321 size = context.fTypes.fInt->coerceExpression(std::move(size), context);
1322 if (!size) {
1323 return 0;
1324 }
1326 if (!ConstantFolder::GetConstantInt(*size, &count)) {
1327 context.fErrors->error(size->fPosition, "array size must be an integer");
1328 return 0;
1329 }
1330 return this->convertArraySize(context, arrayPos, size->fPosition, count);
1331}
1332
1334 Position arrayPos,
1335 Position sizePos,
1336 SKSL_INT size) const {
1337 if (!this->checkIfUsableInArray(context, arrayPos)) {
1338 // `checkIfUsableInArray` will generate an error for us.
1339 return 0;
1340 }
1341 if (size <= 0) {
1342 context.fErrors->error(sizePos, "array size must be positive");
1343 return 0;
1344 }
1345 // We can't get a meaningful slot count if the interior type contains an unsized array; we'll
1346 // assert if we try. Unsized arrays should only occur in a handful of limited cases (e.g. an
1347 // interface block with a trailing buffer), and will never be valid in a runtime effect.
1348 if (!this->isOrContainsUnsizedArray()) {
1349 if (SkSafeMath::Mul(this->slotCount(), size) > kVariableSlotLimit) {
1350 context.fErrors->error(sizePos, "array size is too large");
1351 return 0;
1352 }
1353 }
1354 return size;
1355}
1356
1357std::string Field::description() const {
1359 ' ' + std::string(fName) + ';';
1360}
1361
1362} // namespace SkSL
int count
SkPoint pos
#define SkDEBUGFAIL(message)
Definition SkAssert.h:118
#define SK_ABORT(message,...)
Definition SkAssert.h:70
#define SkDEBUGFAILF(fmt,...)
Definition SkAssert.h:119
#define SkASSERT(cond)
Definition SkAssert.h:116
static int SkPopCount(uint32_t n)
Definition SkMathPriv.h:136
int64_t SKSL_INT
Definition SkSLDefines.h:16
constexpr size_t SkToSizeT(S x)
Definition SkTo.h:31
SK_ALWAYS_INLINE constexpr int value() const
size_t slotCount() const override
Definition SkSLType.cpp:80
SpvDim_ dimensions() const override
Definition SkSLType.cpp:88
bool isStruct() const override
Definition SkSLType.cpp:124
int bitWidth() const override
Definition SkSLType.cpp:72
bool isArrayedTexture() const override
Definition SkSLType.cpp:96
bool isDepth() const override
Definition SkSLType.cpp:92
bool isVector() const override
Definition SkSLType.cpp:108
bool isMultisampled() const override
Definition SkSLType.cpp:132
int columns() const override
Definition SkSLType.cpp:64
const Type & slotType(size_t n) const override
Definition SkSLType.cpp:84
int rows() const override
Definition SkSLType.cpp:68
bool isScalar() const override
Definition SkSLType.cpp:100
bool isUnsizedArray() const override
Definition SkSLType.cpp:120
int priority() const override
Definition SkSLType.cpp:60
TextureAccess textureAccess() const override
Definition SkSLType.cpp:136
bool isMatrix() const override
Definition SkSLType.cpp:112
const Type & componentType() const override
Definition SkSLType.cpp:52
bool isInterfaceBlock() const override
Definition SkSLType.cpp:128
SkSpan< const Type *const > coercibleTypes() const override
Definition SkSLType.cpp:140
bool isAllowedInES2() const override
Definition SkSLType.cpp:76
bool isLiteral() const override
Definition SkSLType.cpp:104
NumberKind numberKind() const override
Definition SkSLType.cpp:56
bool isArray() const override
Definition SkSLType.cpp:116
AliasType(std::string_view name, const Type &targetType)
Definition SkSLType.cpp:44
const Type & resolve() const override
Definition SkSLType.cpp:48
int columns() const override
Definition SkSLType.cpp:193
bool isArray() const override
Definition SkSLType.cpp:165
const Type & componentType() const override
Definition SkSLType.cpp:189
bool isOrContainsAtomic() const override
Definition SkSLType.cpp:177
bool isOrContainsArray() const override
Definition SkSLType.cpp:173
bool isBuiltin() const override
Definition SkSLType.cpp:169
bool isUnsizedArray() const override
Definition SkSLType.cpp:181
bool isAllowedInES2() const override
Definition SkSLType.cpp:201
const Type & slotType(size_t n) const override
Definition SkSLType.cpp:215
bool isOrContainsUnsizedArray() const override
Definition SkSLType.cpp:185
int bitWidth() const override
Definition SkSLType.cpp:197
size_t slotCount() const override
Definition SkSLType.cpp:209
static constexpr TypeKind kTypeKind
Definition SkSLType.cpp:152
ArrayType(std::string_view name, const char *abbrev, const Type &componentType, int count, bool isBuiltin)
Definition SkSLType.cpp:154
bool isAllowedInUniform(Position *errorPosition) const override
Definition SkSLType.cpp:205
bool isAllowedInUniform(Position *) const override
Definition SkSLType.cpp:429
const Type & slotType(size_t n) const override
Definition SkSLType.cpp:433
AtomicType(std::string_view name, const char *abbrev)
Definition SkSLType.cpp:425
bool isOrContainsAtomic() const override
Definition SkSLType.cpp:431
static constexpr TypeKind kTypeKind
Definition SkSLType.cpp:423
bool isAllowedInES2() const override
Definition SkSLType.cpp:427
const std::unique_ptr< Type > fFloat2
const std::unique_ptr< Type > fFloatLiteral
const std::unique_ptr< Type > fHalf4
const std::unique_ptr< Type > fFloat4x3
const std::unique_ptr< Type > fInt4
const std::unique_ptr< Type > fHalf2x3
const std::unique_ptr< Type > fHalf2x2
const std::unique_ptr< Type > fUInt2
const std::unique_ptr< Type > fShort3
const std::unique_ptr< Type > fInt2
const std::unique_ptr< Type > fUShort
const std::unique_ptr< Type > fInt
const std::unique_ptr< Type > fHalf4x3
const std::unique_ptr< Type > fFloat3x2
const std::unique_ptr< Type > fTexture2D
const std::unique_ptr< Type > fFloat2x2
const std::unique_ptr< Type > fFloat3x4
const std::unique_ptr< Type > fHalf3x4
const std::unique_ptr< Type > fIntLiteral
const std::unique_ptr< Type > fFloat4x4
const std::unique_ptr< Type > fShort2
const std::unique_ptr< Type > fShort
const std::unique_ptr< Type > fInt3
const std::unique_ptr< Type > fHalf2x4
const std::unique_ptr< Type > fUInt3
const std::unique_ptr< Type > fUShort4
const std::unique_ptr< Type > fFloat4
const std::unique_ptr< Type > fHalf2
const std::unique_ptr< Type > fUInt4
const std::unique_ptr< Type > fHalf3x3
const std::unique_ptr< Type > fShort4
const std::unique_ptr< Type > fBool2
const std::unique_ptr< Type > fFloat3x3
const std::unique_ptr< Type > fUShort2
const std::unique_ptr< Type > fBool3
const std::unique_ptr< Type > fWriteOnlyTexture2D
const std::unique_ptr< Type > fHalf4x2
const std::unique_ptr< Type > fUInt
const std::unique_ptr< Type > fFloat2x3
const std::unique_ptr< Type > fUShort3
const std::unique_ptr< Type > fBool
const std::unique_ptr< Type > fVoid
const std::unique_ptr< Type > fHalf3
const std::unique_ptr< Type > fFloat2x4
const std::unique_ptr< Type > fFloat
const std::unique_ptr< Type > fFloat3
const std::unique_ptr< Type > fHalf
const std::unique_ptr< Type > fPoison
const std::unique_ptr< Type > fHalf3x2
const std::unique_ptr< Type > fHalf4x4
const std::unique_ptr< Type > fFloat4x2
const std::unique_ptr< Type > fReadOnlyTexture2D
const std::unique_ptr< Type > fBool4
static bool GetConstantInt(const Expression &value, SKSL_INT *out)
static const Expression * GetConstantValueForVariable(const Expression &value)
static std::unique_ptr< Expression > Make(const Context &context, Position pos, const Type &type, std::unique_ptr< Expression > arg)
static std::unique_ptr< Expression > Make(const Context &context, Position pos, const Type &type, std::unique_ptr< Expression > arg)
static std::unique_ptr< Expression > Make(const Context &context, Position pos, const Type &type, std::unique_ptr< Expression > arg)
const BuiltinTypes & fTypes
Definition SkSLContext.h:30
ErrorReporter * fErrors
Definition SkSLContext.h:36
SymbolTable * fSymbolTable
Definition SkSLContext.h:48
ProgramConfig * fConfig
Definition SkSLContext.h:33
void error(Position position, std::string_view msg)
virtual const Type & type() const
virtual bool supportsConstantValues() const
virtual std::optional< double > getConstantValue(int n) const
SkSpan< const Type *const > coercibleTypes() const override
Definition SkSLType.cpp:240
static constexpr TypeKind kTypeKind
Definition SkSLType.cpp:230
const Type & slotType(size_t) const override
Definition SkSLType.cpp:244
GenericType(const char *name, SkSpan< const Type *const > coercibleTypes, const Type *slotType)
Definition SkSLType.cpp:232
const T & as() const
Definition SkSLIRNode.h:133
Position fPosition
Definition SkSLIRNode.h:109
bool isScalar() const override
Definition SkSLType.cpp:297
const Type & slotType(size_t n) const override
Definition SkSLType.cpp:309
int priority() const override
Definition SkSLType.cpp:269
LiteralType(const char *name, const Type &scalarType, int8_t priority)
Definition SkSLType.cpp:260
double minimumValue() const override
Definition SkSLType.cpp:289
double maximumValue() const override
Definition SkSLType.cpp:293
const Type & scalarTypeForLiteral() const override
Definition SkSLType.cpp:265
NumberKind numberKind() const override
Definition SkSLType.cpp:281
int bitWidth() const override
Definition SkSLType.cpp:285
bool isLiteral() const override
Definition SkSLType.cpp:301
size_t slotCount() const override
Definition SkSLType.cpp:305
int rows() const override
Definition SkSLType.cpp:277
static constexpr TypeKind kTypeKind
Definition SkSLType.cpp:258
int columns() const override
Definition SkSLType.cpp:273
int rows() const override
Definition SkSLType.cpp:464
int bitWidth() const override
Definition SkSLType.cpp:468
MatrixType(std::string_view name, const char *abbrev, const Type &componentType, int8_t columns, int8_t rows)
Definition SkSLType.cpp:446
int columns() const override
Definition SkSLType.cpp:460
bool isAllowedInES2() const override
Definition SkSLType.cpp:476
static constexpr TypeKind kTypeKind
Definition SkSLType.cpp:444
bool isMatrix() const override
Definition SkSLType.cpp:472
const Type & slotType(size_t n) const override
Definition SkSLType.cpp:484
const ScalarType & componentType() const override
Definition SkSLType.cpp:456
size_t slotCount() const override
Definition SkSLType.cpp:480
std::string paddedDescription() const
std::string description() const
bool valid() const
const TextureType & textureType() const override
Definition SkSLType.cpp:558
TextureAccess textureAccess() const override
Definition SkSLType.cpp:578
bool isDepth() const override
Definition SkSLType.cpp:566
static constexpr TypeKind kTypeKind
Definition SkSLType.cpp:547
SamplerType(const char *name, const Type &textureType)
Definition SkSLType.cpp:549
const Type & slotType(size_t n) const override
Definition SkSLType.cpp:582
SpvDim_ dimensions() const override
Definition SkSLType.cpp:562
bool isMultisampled() const override
Definition SkSLType.cpp:574
bool isArrayedTexture() const override
Definition SkSLType.cpp:570
bool isAllowedInUniform(Position *) const override
Definition SkSLType.cpp:361
ScalarType(std::string_view name, const char *abbrev, NumberKind numberKind, int8_t priority, int8_t bitWidth)
Definition SkSLType.cpp:326
int bitWidth() const override
Definition SkSLType.cpp:341
std::numeric_limits< float > float_limits
Definition SkSLType.cpp:378
bool isScalar() const override
Definition SkSLType.cpp:353
size_t slotCount() const override
Definition SkSLType.cpp:365
std::numeric_limits< uint16_t > ushort_limits
Definition SkSLType.cpp:377
int priority() const override
Definition SkSLType.cpp:337
double minimumValue() const override
Definition SkSLType.cpp:381
static constexpr TypeKind kTypeKind
Definition SkSLType.cpp:324
NumberKind numberKind() const override
Definition SkSLType.cpp:333
int columns() const override
Definition SkSLType.cpp:345
std::numeric_limits< int32_t > int_limits
Definition SkSLType.cpp:374
const Type & slotType(size_t n) const override
Definition SkSLType.cpp:369
std::numeric_limits< uint32_t > uint_limits
Definition SkSLType.cpp:376
std::numeric_limits< int16_t > short_limits
Definition SkSLType.cpp:375
bool isAllowedInES2() const override
Definition SkSLType.cpp:357
double maximumValue() const override
Definition SkSLType.cpp:397
int rows() const override
Definition SkSLType.cpp:349
bool isInterfaceBlock() const override
Definition SkSLType.cpp:632
const Type & slotType(size_t n) const override
Definition SkSLType.cpp:672
int structNestingDepth() const override
Definition SkSLType.cpp:668
size_t slotCount() const override
Definition SkSLType.cpp:663
bool isOrContainsAtomic() const override
Definition SkSLType.cpp:659
SkSpan< const Field > fields() const override
Definition SkSLType.cpp:624
StructType(Position pos, std::string_view name, TArray< Field > fields, int nestingDepth, bool interfaceBlock, bool isBuiltin)
Definition SkSLType.cpp:597
bool isOrContainsArray() const override
Definition SkSLType.cpp:651
bool isOrContainsUnsizedArray() const override
Definition SkSLType.cpp:655
bool isAllowedInUniform(Position *errorPosition) const override
Definition SkSLType.cpp:644
bool isStruct() const override
Definition SkSLType.cpp:628
bool isAllowedInES2() const override
Definition SkSLType.cpp:640
static constexpr TypeKind kTypeKind
Definition SkSLType.cpp:595
bool isBuiltin() const override
Definition SkSLType.cpp:636
const Type * addArrayDimension(const Context &context, const Type *type, int arraySize)
const Symbol * find(std::string_view name) const
const std::string * takeOwnershipOfString(std::string n)
T * add(const Context &context, std::unique_ptr< T > symbol)
std::string_view name() const
Definition SkSLSymbol.h:51
const Type & type() const
Definition SkSLSymbol.h:42
static constexpr TypeKind kTypeKind
Definition SkSLType.cpp:499
SpvDim_ dimensions() const override
Definition SkSLType.cpp:510
const Type & slotType(size_t n) const override
Definition SkSLType.cpp:530
bool isDepth() const override
Definition SkSLType.cpp:514
bool isArrayedTexture() const override
Definition SkSLType.cpp:518
TextureAccess textureAccess() const override
Definition SkSLType.cpp:526
TextureType(const char *name, SpvDim_ dimensions, bool isDepth, bool isArrayed, bool isMultisampled, TextureAccess textureAccess)
Definition SkSLType.cpp:501
bool isMultisampled() const override
Definition SkSLType.cpp:522
virtual const Type & slotType(size_t) const
Definition SkSLType.h:465
static std::unique_ptr< Type > MakeAliasType(std::string_view name, const Type &targetType)
Definition SkSLType.cpp:764
static std::unique_ptr< Type > MakeTextureType(const char *name, SpvDim_ dimensions, bool isDepth, bool isArrayedTexture, bool isMultisampled, TextureAccess textureAccess)
Definition SkSLType.cpp:887
virtual bool isArray() const
Definition SkSLType.h:532
const Type * applyPrecisionQualifiers(const Context &context, ModifierFlags *modifierFlags, Position pos) const
Definition SkSLType.cpp:945
bool isInRootSymbolTable() const
Definition SkSLType.h:655
virtual int bitWidth() const
Definition SkSLType.h:574
bool highPrecision() const
Definition SkSLType.h:570
static std::unique_ptr< Type > MakeScalarType(std::string_view name, const char *abbrev, Type::NumberKind numberKind, int8_t priority, int8_t bitWidth)
Definition SkSLType.cpp:801
virtual bool isVector() const
Definition SkSLType.h:524
CoercionCost coercionCost(const Type &other) const
Definition SkSLType.cpp:899
static std::unique_ptr< Type > MakeArrayType(const Context &context, std::string_view name, const Type &componentType, int columns)
Definition SkSLType.cpp:768
virtual int priority() const
Definition SkSLType.h:379
bool isAllowedInES2(const Context &context) const
std::unique_ptr< Expression > coerceExpression(std::unique_ptr< Expression > expr, const Context &context) const
virtual int rows() const
Definition SkSLType.h:438
bool isAtomic() const
Definition SkSLType.h:508
virtual const Type & componentType() const
Definition SkSLType.h:404
virtual bool isInterfaceBlock() const
Definition SkSLType.h:544
SKSL_INT convertArraySize(const Context &context, Position arrayPos, std::unique_ptr< Expression > size) const
bool isOpaque() const
Definition SkSLType.h:353
const char * abbreviatedName() const
Definition SkSLType.h:276
bool isNumber() const
Definition SkSLType.h:304
virtual SkSpan< const Field > fields() const
Definition SkSLType.h:469
bool matches(const Type &other) const
Definition SkSLType.h:269
virtual bool isMatrix() const
Definition SkSLType.h:528
virtual bool isDepth() const
Definition SkSLType.h:486
static std::unique_ptr< Type > MakeSamplerType(const char *name, const Type &textureType)
Definition SkSLType.cpp:792
virtual bool isLiteral() const
Definition SkSLType.h:516
virtual TextureAccess textureAccess() const
Definition SkSLType.h:561
bool checkIfUsableInArray(const Context &context, Position arrayPos) const
static std::unique_ptr< Type > MakeGenericType(const char *name, SkSpan< const Type *const > types, const Type *slotType)
Definition SkSLType.cpp:776
virtual const Type & textureType() const
Definition SkSLType.h:419
virtual int columns() const
Definition SkSLType.h:429
virtual size_t slotCount() const
Definition SkSLType.h:457
bool is() const
Definition SkSLType.h:205
static constexpr int kUnsizedArray
Definition SkSLType.h:99
virtual bool isScalar() const
Definition SkSLType.h:512
virtual NumberKind numberKind() const
Definition SkSLType.h:290
virtual bool isAllowedInES2() const
Definition SkSLType.h:246
virtual bool isUnsizedArray() const
Definition SkSLType.h:536
virtual bool isAllowedInUniform(Position *errorPosition=nullptr) const
Definition SkSLType.h:257
const T & as() const
Definition SkSLType.h:210
std::string description() const override
Definition SkSLType.h:238
static std::unique_ptr< Type > MakeLiteralType(const char *name, const Type &scalarType, int8_t priority)
Definition SkSLType.cpp:782
const Type * applyAccessQualifiers(const Context &context, ModifierFlags *modifierFlags, Position pos) const
static std::unique_ptr< Type > MakeStructType(const Context &context, Position pos, std::string_view name, skia_private::TArray< Field > fields, bool interfaceBlock=false)
Definition SkSLType.cpp:811
static std::unique_ptr< Type > MakeMatrixType(std::string_view name, const char *abbrev, const Type &componentType, int columns, int8_t rows)
Definition SkSLType.cpp:787
virtual double maximumValue() const
Definition SkSLType.h:449
std::string getArrayName(int arraySize) const
Definition SkSLType.cpp:756
static std::unique_ptr< Type > MakeAtomicType(std::string_view name, const char *abbrev)
Definition SkSLType.cpp:807
virtual bool isOrContainsAtomic() const
Definition SkSLType.h:586
virtual bool isMultisampled() const
Definition SkSLType.h:556
bool isVoid() const
Definition SkSLType.h:496
virtual SkSpan< const Type *const > coercibleTypes() const
Definition SkSLType.h:476
virtual bool isArrayedTexture() const
Definition SkSLType.h:491
static std::unique_ptr< Type > MakeSpecialType(const char *name, const char *abbrev, Type::TypeKind typeKind)
Definition SkSLType.cpp:796
bool checkForOutOfRangeLiteral(const Context &context, const Expression &expr) const
static std::unique_ptr< Type > MakeVectorType(std::string_view name, const char *abbrev, const Type &componentType, int columns)
Definition SkSLType.cpp:894
std::string displayName() const
Definition SkSLType.h:234
const Type & toCompound(const Context &context, int columns, int rows) const
TypeKind typeKind() const
Definition SkSLType.h:283
virtual bool isStruct() const
Definition SkSLType.h:540
const Type * clone(const Context &context, SymbolTable *symbolTable) const
virtual SpvDim_ dimensions() const
Definition SkSLType.h:481
virtual double minimumValue() const
Definition SkSLType.h:444
bool isInteger() const
Definition SkSLType.h:339
virtual bool isOrContainsUnsizedArray() const
Definition SkSLType.h:582
const Type * applyQualifiers(const Context &context, ModifierFlags *modifierFlags, Position pos) const
Definition SkSLType.cpp:936
bool isAllowedInUniform(Position *errorPosition) const override
Definition SkSLType.cpp:736
VectorType(std::string_view name, const char *abbrev, const Type &componentType, int8_t columns)
Definition SkSLType.cpp:704
const ScalarType & componentType() const override
Definition SkSLType.cpp:712
const Type & slotType(size_t n) const override
Definition SkSLType.cpp:744
bool isVector() const override
Definition SkSLType.cpp:728
size_t slotCount() const override
Definition SkSLType.cpp:740
bool isAllowedInES2() const override
Definition SkSLType.cpp:732
int bitWidth() const override
Definition SkSLType.cpp:724
int columns() const override
Definition SkSLType.cpp:716
int rows() const override
Definition SkSLType.cpp:720
static constexpr TypeKind kTypeKind
Definition SkSLType.cpp:702
static size_t Add(size_t x, size_t y)
static size_t Mul(size_t x, size_t y)
constexpr T * data() const
Definition SkSpan_impl.h:94
constexpr size_t size() const
Definition SkSpan_impl.h:95
int count() const
Definition SkTHash.h:564
void add(T item)
Definition SkTHash.h:573
uint8_t value
const char * name
Definition fuchsia.cc:50
std::string printf(const char *fmt,...) SK_PRINTF_LIKE(1
static constexpr int kMaxStructDepth
Definition SkSLType.cpp:40
static constexpr int kVariableSlotLimit
Definition SkSLDefines.h:45
Definition ref_ptr.h:256
SpvDim_
Definition spirv.h:141
@ SpvDimSubpassData
Definition spirv.h:148
static CoercionCost Impossible()
Definition SkSLType.h:42
static CoercionCost Narrowing(int cost)
Definition SkSLType.h:41
static CoercionCost Free()
Definition SkSLType.h:39
static CoercionCost Normal(int cost)
Definition SkSLType.h:40
Layout fLayout
Definition SkSLType.h:85
std::string_view fName
Definition SkSLType.h:87
std::string description() const
const Type * fType
Definition SkSLType.h:88
ModifierFlags fModifierFlags
Definition SkSLType.h:86
std::string paddedDescription() const
static bool IsRuntimeEffect(ProgramKind kind)
ProgramSettings fSettings