2 * Copyright 2016 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
11 #include "include/private/SkSLModifiers.h"
12 #include "include/private/SkSLSymbol.h"
13 #include "src/sksl/SkSLUtil.h"
14 #include "src/sksl/spirv.h"
17 #include <string_view>
27 static CoercionCost Free() { return { 0, 0, false }; }
28 static CoercionCost Normal(int cost) { return { cost, 0, false }; }
29 static CoercionCost Narrowing(int cost) { return { 0, cost, false }; }
30 static CoercionCost Impossible() { return { 0, 0, true }; }
32 bool isPossible(bool allowNarrowing) const {
33 return !fImpossible && (fNarrowingCost == 0 || allowNarrowing);
36 // Addition of two costs. Saturates at Impossible().
37 CoercionCost operator+(CoercionCost rhs) const {
38 if (fImpossible || rhs.fImpossible) {
41 return { fNormalCost + rhs.fNormalCost, fNarrowingCost + rhs.fNarrowingCost, false };
44 bool operator<(CoercionCost rhs) const {
45 return std::tie( fImpossible, fNarrowingCost, fNormalCost) <
46 std::tie(rhs.fImpossible, rhs.fNarrowingCost, rhs.fNormalCost);
55 * Represents a type, such as int or float4.
57 class Type : public Symbol {
59 inline static constexpr Kind kSymbolKind = Kind::kType;
60 inline static constexpr int kMaxAbbrevLength = 3;
63 Field(Position pos, Modifiers modifiers, std::string_view name, const Type* type)
65 , fModifiers(modifiers)
67 , fType(std::move(type)) {}
69 std::string description() const {
70 return fType->displayName() + " " + std::string(fName) + ";";
75 std::string_view fName;
79 enum class TypeKind : int8_t {
93 // Types that represent stages in the Skia pipeline
99 enum class NumberKind : int8_t {
107 Type(const Type& other) = delete;
109 /** Creates an array type. */
110 static std::unique_ptr<Type> MakeArrayType(std::string_view name, const Type& componentType,
113 /** Converts a component type and a size (float, 10) into an array name ("float[10]"). */
114 std::string getArrayName(int arraySize) const;
117 * Creates an alias which maps to another type.
119 static std::unique_ptr<Type> MakeAliasType(std::string_view name, const Type& targetType);
122 * Create a generic type which maps to the listed types--e.g. $genType is a generic type which
123 * can match float, float2, float3 or float4.
125 static std::unique_ptr<Type> MakeGenericType(const char* name, std::vector<const Type*> types);
127 /** Create a type for literal scalars. */
128 static std::unique_ptr<Type> MakeLiteralType(const char* name, const Type& scalarType,
131 /** Create a matrix type. */
132 static std::unique_ptr<Type> MakeMatrixType(std::string_view name, const char* abbrev,
133 const Type& componentType, int columns,
136 /** Create a sampler type. */
137 static std::unique_ptr<Type> MakeSamplerType(const char* name, const Type& textureType);
139 /** Create a scalar type. */
140 static std::unique_ptr<Type> MakeScalarType(std::string_view name, const char* abbrev,
141 Type::NumberKind numberKind, int8_t priority,
145 * Create a "special" type with the given name, abbreviation, and TypeKind.
147 static std::unique_ptr<Type> MakeSpecialType(const char* name, const char* abbrev,
148 Type::TypeKind typeKind);
150 /** Creates a struct type with the given fields. */
151 static std::unique_ptr<Type> MakeStructType(Position pos,
152 std::string_view name,
153 std::vector<Field> fields,
154 bool interfaceBlock = false);
156 /** Create a texture type. */
157 static std::unique_ptr<Type> MakeTextureType(const char* name, SpvDim_ dimensions,
158 bool isDepth, bool isArrayedTexture,
159 bool isMultisampled, bool isSampled);
161 /** Create a vector type. */
162 static std::unique_ptr<Type> MakeVectorType(std::string_view name, const char* abbrev,
163 const Type& componentType, int columns);
165 template <typename T>
167 return this->typeKind() == T::kTypeKind;
170 template <typename T>
171 const T& as() const {
172 SkASSERT(this->is<T>());
173 return static_cast<const T&>(*this);
176 template <typename T>
178 SkASSERT(this->is<T>());
179 return static_cast<T&>(*this);
182 /** Creates a clone of this Type, if needed, and inserts it into a different symbol table. */
183 const Type* clone(SymbolTable* symbolTable) const;
186 * Returns true if this type is known to come from BuiltinTypes. If this returns true, the Type
187 * will always be available in the root SymbolTable and never needs to be copied to migrate an
188 * Expression from one location to another. If it returns false, the Type might not exist in a
189 * separate SymbolTable and you'll need to consider copying it.
191 bool isInBuiltinTypes() const {
192 return !(this->isArray() || this->isStruct());
195 std::string displayName() const {
196 return std::string(this->scalarTypeForLiteral().name());
199 std::string description() const override {
200 return this->displayName();
203 /** Returns true if the program supports this type. Strict ES2 programs can't use ES3 types. */
204 bool isAllowedInES2(const Context& context) const;
206 /** Returns true if this type is legal to use in a strict-ES2 program. */
207 virtual bool isAllowedInES2() const {
211 /** Returns true if this type is either private, or contains a private field (recursively). */
212 virtual bool isPrivate() const;
214 /** If this is an alias, returns the underlying type, otherwise returns this. */
215 virtual const Type& resolve() const {
219 /** Returns true if these types are equal after alias resolution. */
220 bool matches(const Type& other) const {
221 return this->resolve().name() == other.resolve().name();
225 * Returns an abbreviated name of the type, meant for name-mangling. (e.g. float4x4 -> f44)
227 const char* abbreviatedName() const {
228 return fAbbreviatedName;
232 * Returns the category (scalar, vector, matrix, etc.) of this type.
234 TypeKind typeKind() const {
239 * Returns the NumberKind of this type (always kNonnumeric for non-scalar values).
241 virtual NumberKind numberKind() const {
242 return NumberKind::kNonnumeric;
246 * Returns true if this type is a bool.
248 bool isBoolean() const {
249 return this->numberKind() == NumberKind::kBoolean;
253 * Returns true if this is a numeric scalar type.
255 bool isNumber() const {
256 switch (this->numberKind()) {
257 case NumberKind::kFloat:
258 case NumberKind::kSigned:
259 case NumberKind::kUnsigned:
267 * Returns true if this is a floating-point scalar type (float or half).
269 bool isFloat() const {
270 return this->numberKind() == NumberKind::kFloat;
274 * Returns true if this is a signed scalar type (int or short).
276 bool isSigned() const {
277 return this->numberKind() == NumberKind::kSigned;
281 * Returns true if this is an unsigned scalar type (uint or ushort).
283 bool isUnsigned() const {
284 return this->numberKind() == NumberKind::kUnsigned;
288 * Returns true if this is a signed or unsigned integer.
290 bool isInteger() const {
291 switch (this->numberKind()) {
292 case NumberKind::kSigned:
293 case NumberKind::kUnsigned:
301 * Returns true if this is an "opaque type" (an external object which the shader references in
302 * some fashion). https://www.khronos.org/opengl/wiki/Data_Type_(GLSL)#Opaque_types
304 bool isOpaque() const {
306 case TypeKind::kBlender:
307 case TypeKind::kColorFilter:
308 case TypeKind::kSampler:
309 case TypeKind::kSeparateSampler:
310 case TypeKind::kShader:
311 case TypeKind::kTexture:
319 * Returns the "priority" of a number type, in order of float > half > int > short.
320 * When operating on two number types, the result is the higher-priority type.
322 virtual int priority() const {
323 SkDEBUGFAIL("not a number type");
328 * Returns true if an instance of this type can be freely coerced (implicitly converted) to
331 bool canCoerceTo(const Type& other, bool allowNarrowing) const {
332 return this->coercionCost(other).isPossible(allowNarrowing);
336 * Determines the "cost" of coercing (implicitly converting) this type to another type. The cost
337 * is a number with no particular meaning other than that lower costs are preferable to higher
338 * costs. Returns INT_MAX if the coercion is not possible.
340 CoercionCost coercionCost(const Type& other) const;
343 * For matrices and vectors, returns the type of individual cells (e.g. mat2 has a component
344 * type of Float). For arrays, returns the base type. For all other types, returns the type
347 virtual const Type& componentType() const {
352 * For texturesamplers, returns the type of texture it samples (e.g., sampler2D has
353 * a texture type of texture2D).
355 virtual const Type& textureType() const {
356 SkDEBUGFAIL("not a texture type");
361 * For matrices and vectors, returns the number of columns (e.g. both mat3 and float3 return 3).
362 * For scalars, returns 1. For arrays, returns either the size of the array (if known) or -1.
363 * For all other types, causes an assertion failure.
365 virtual int columns() const {
366 SkDEBUGFAIL("type does not have columns");
371 * For matrices, returns the number of rows (e.g. mat2x4 returns 4). For vectors and scalars,
372 * returns 1. For all other types, causes an assertion failure.
374 virtual int rows() const {
375 SkDEBUGFAIL("type does not have rows");
379 /** For integer types, returns the minimum value that can fit in the type. */
380 int64_t minimumValue() const {
381 SkASSERT(this->isInteger());
382 constexpr int64_t k1 = 1; // ensures that `1 << n` is evaluated as 64-bit
383 return this->isUnsigned() ? 0 : -(k1 << (this->bitWidth() - 1));
386 /** For integer types, returns the maximum value that can fit in the type. */
387 int64_t maximumValue() const {
388 SkASSERT(this->isInteger());
389 constexpr int64_t k1 = 1; // ensures that `1 << n` is evaluated as 64-bit
390 return (this->isUnsigned() ? (k1 << this->bitWidth())
391 : (k1 << (this->bitWidth() - 1))) - 1;
395 * Returns the number of scalars needed to hold this type.
397 virtual size_t slotCount() const {
401 virtual const std::vector<Field>& fields() const {
402 SK_ABORT("Internal error: not a struct");
406 * For generic types, returns the types that this generic type can substitute for.
408 virtual const std::vector<const Type*>& coercibleTypes() const {
409 SK_ABORT("Internal error: not a generic type");
412 virtual SpvDim_ dimensions() const {
417 virtual bool isDepth() const {
422 virtual bool isArrayedTexture() const {
427 bool isVoid() const {
428 return fTypeKind == TypeKind::kVoid;
431 virtual bool isScalar() const {
435 virtual bool isLiteral() const {
439 virtual const Type& scalarTypeForLiteral() const {
443 virtual bool isVector() const {
447 virtual bool isMatrix() const {
451 virtual bool isArray() const {
455 virtual bool isStruct() const {
459 virtual bool isInterfaceBlock() const {
463 // Is this type something that can be bound & sampled from an SkRuntimeEffect?
464 // Includes types that represent stages of the Skia pipeline (colorFilter, shader, blender).
465 bool isEffectChild() const {
466 return fTypeKind == TypeKind::kColorFilter ||
467 fTypeKind == TypeKind::kShader ||
468 fTypeKind == TypeKind::kBlender;
471 virtual bool isMultisampled() const {
476 virtual bool isSampled() const {
481 bool hasPrecision() const {
482 return this->componentType().isNumber() || fTypeKind == TypeKind::kSampler;
485 bool highPrecision() const {
486 return this->bitWidth() >= 32;
489 virtual int bitWidth() const {
493 bool isOrContainsArray() const;
496 * Returns true if this type is a struct that is too deeply nested.
498 bool isTooDeeplyNested() const;
501 * Returns the corresponding vector or matrix type with the specified number of columns and
504 const Type& toCompound(const Context& context, int columns, int rows) const;
507 * Returns a type which honors the precision qualifiers set in Modifiers. e.g., kMediump_Flag
508 * when applied to `float2` will return `half2`. Generates an error if the precision qualifiers
509 * don't make sense, e.g. `highp bool` or `mediump MyStruct`.
511 const Type* applyPrecisionQualifiers(const Context& context,
512 Modifiers* modifiers,
513 SymbolTable* symbols,
517 * Coerces the passed-in expression to this type. If the types are incompatible, reports an
518 * error and returns null.
520 std::unique_ptr<Expression> coerceExpression(std::unique_ptr<Expression> expr,
521 const Context& context) const;
523 /** Detects any IntLiterals in the expression which can't fit in this type. */
524 bool checkForOutOfRangeLiteral(const Context& context, const Expression& expr) const;
526 /** Checks if `value` can fit in this type. The type must be scalar. */
527 bool checkForOutOfRangeLiteral(const Context& context, double value, Position pos) const;
530 * Verifies that the expression is a valid constant array size for this type. Returns the array
531 * size, or zero if the expression isn't a valid literal value.
533 SKSL_INT convertArraySize(const Context& context, Position arrayPos,
534 std::unique_ptr<Expression> size) const;
537 Type(std::string_view name, const char* abbrev, TypeKind kind,
538 Position pos = Position())
539 : INHERITED(pos, kSymbolKind, name)
541 SkASSERT(strlen(abbrev) <= kMaxAbbrevLength);
542 strcpy(fAbbreviatedName, abbrev);
546 bool isTooDeeplyNested(int limit) const;
548 using INHERITED = Symbol;
550 char fAbbreviatedName[kMaxAbbrevLength + 1] = {};