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 8 #ifndef SKSL_TYPE 9 #define SKSL_TYPE 10 11 #include "include/core/SkStringView.h" 12 #include "include/private/SkSLModifiers.h" 13 #include "include/private/SkSLSymbol.h" 14 #include "src/sksl/SkSLUtil.h" 15 #include "src/sksl/spirv.h" 16 #include <algorithm> 17 #include <climits> 18 #include <vector> 19 #include <memory> 20 21 namespace SkSL { 22 23 class Context; 24 class SymbolTable; 25 26 struct CoercionCost { FreeCoercionCost27 static CoercionCost Free() { return { 0, 0, false }; } NormalCoercionCost28 static CoercionCost Normal(int cost) { return { cost, 0, false }; } NarrowingCoercionCost29 static CoercionCost Narrowing(int cost) { return { 0, cost, false }; } ImpossibleCoercionCost30 static CoercionCost Impossible() { return { 0, 0, true }; } 31 isPossibleCoercionCost32 bool isPossible(bool allowNarrowing) const { 33 return !fImpossible && (fNarrowingCost == 0 || allowNarrowing); 34 } 35 36 // Addition of two costs. Saturates at Impossible(). 37 CoercionCost operator+(CoercionCost rhs) const { 38 if (fImpossible || rhs.fImpossible) { 39 return Impossible(); 40 } 41 return { fNormalCost + rhs.fNormalCost, fNarrowingCost + rhs.fNarrowingCost, false }; 42 } 43 44 bool operator<(CoercionCost rhs) const { 45 return std::tie( fImpossible, fNarrowingCost, fNormalCost) < 46 std::tie(rhs.fImpossible, rhs.fNarrowingCost, rhs.fNormalCost); 47 } 48 49 int fNormalCost; 50 int fNarrowingCost; 51 bool fImpossible; 52 }; 53 54 /** 55 * Represents a type, such as int or float4. 56 */ 57 class Type : public Symbol { 58 public: 59 inline static constexpr Kind kSymbolKind = Kind::kType; 60 inline static constexpr int kMaxAbbrevLength = 3; 61 62 struct Field { FieldField63 Field(Modifiers modifiers, skstd::string_view name, const Type* type) 64 : fModifiers(modifiers) 65 , fName(name) 66 , fType(std::move(type)) {} 67 descriptionField68 String description() const { 69 return fType->displayName() + " " + fName + ";"; 70 } 71 72 Modifiers fModifiers; 73 skstd::string_view fName; 74 const Type* fType; 75 }; 76 77 enum class TypeKind : int8_t { 78 kArray, 79 kGeneric, 80 kLiteral, 81 kMatrix, 82 kOther, 83 kSampler, 84 kSeparateSampler, 85 kScalar, 86 kStruct, 87 kTexture, 88 kVector, 89 kVoid, 90 91 // Types that represent stages in the Skia pipeline 92 kColorFilter, 93 kShader, 94 kBlender, 95 }; 96 97 enum class NumberKind : int8_t { 98 kFloat, 99 kSigned, 100 kUnsigned, 101 kBoolean, 102 kNonnumeric 103 }; 104 105 Type(const Type& other) = delete; 106 107 /** Creates an array type. */ 108 static std::unique_ptr<Type> MakeArrayType(skstd::string_view name, const Type& componentType, 109 int columns); 110 111 /** Converts a component type and a size (float, 10) into an array name ("float[10]"). */ 112 String getArrayName(int arraySize) const; 113 114 /** 115 * Create a generic type which maps to the listed types--e.g. $genType is a generic type which 116 * can match float, float2, float3 or float4. 117 */ 118 static std::unique_ptr<Type> MakeGenericType(const char* name, std::vector<const Type*> types); 119 120 /** Create a type for literal scalars. */ 121 static std::unique_ptr<Type> MakeLiteralType(const char* name, const Type& scalarType, 122 int8_t priority); 123 124 /** Create a matrix type. */ 125 static std::unique_ptr<Type> MakeMatrixType(skstd::string_view name, const char* abbrev, 126 const Type& componentType, int columns, 127 int8_t rows); 128 129 /** Create a sampler type. */ 130 static std::unique_ptr<Type> MakeSamplerType(const char* name, const Type& textureType); 131 132 /** Create a scalar type. */ 133 static std::unique_ptr<Type> MakeScalarType(skstd::string_view name, const char* abbrev, 134 Type::NumberKind numberKind, int8_t priority, 135 int8_t bitWidth); 136 137 /** 138 * Create a "special" type with the given name, abbreviation, and TypeKind. 139 */ 140 static std::unique_ptr<Type> MakeSpecialType(const char* name, const char* abbrev, 141 Type::TypeKind typeKind); 142 143 /** Creates a struct type with the given fields. */ 144 static std::unique_ptr<Type> MakeStructType(int line, skstd::string_view name, 145 std::vector<Field> fields); 146 147 /** Create a texture type. */ 148 static std::unique_ptr<Type> MakeTextureType(const char* name, SpvDim_ dimensions, 149 bool isDepth, bool isArrayedTexture, 150 bool isMultisampled, bool isSampled); 151 152 /** Create a vector type. */ 153 static std::unique_ptr<Type> MakeVectorType(skstd::string_view name, const char* abbrev, 154 const Type& componentType, int columns); 155 156 template <typename T> is()157 bool is() const { 158 return this->typeKind() == T::kTypeKind; 159 } 160 161 template <typename T> as()162 const T& as() const { 163 SkASSERT(this->is<T>()); 164 return static_cast<const T&>(*this); 165 } 166 167 template <typename T> as()168 T& as() { 169 SkASSERT(this->is<T>()); 170 return static_cast<T&>(*this); 171 } 172 173 /** Creates a clone of this Type, if needed, and inserts it into a different symbol table. */ 174 const Type* clone(SymbolTable* symbolTable) const; 175 176 /** 177 * Returns true if this type is known to come from BuiltinTypes. If this returns true, the Type 178 * will always be available in the root SymbolTable and never needs to be copied to migrate an 179 * Expression from one location to another. If it returns false, the Type might not exist in a 180 * separate SymbolTable and you'll need to consider copying it. 181 */ isInBuiltinTypes()182 bool isInBuiltinTypes() const { 183 return !(this->isArray() || this->isStruct()); 184 } 185 displayName()186 String displayName() const { 187 return String(this->scalarTypeForLiteral().name()); 188 } 189 description()190 String description() const override { 191 return this->displayName(); 192 } 193 194 /** Returns true if the program supports this type. Strict ES2 programs can't use ES3 types. */ 195 bool isAllowedInES2(const Context& context) const; 196 197 /** Returns true if this type is legal to use in a strict-ES2 program. */ isAllowedInES2()198 virtual bool isAllowedInES2() const { 199 return true; 200 } 201 202 /** Returns true if this type is either private, or contains a private field (recursively). */ isPrivate()203 virtual bool isPrivate() const { 204 return this->name().starts_with("$"); 205 } 206 207 bool operator==(const Type& other) const { 208 return this->name() == other.name(); 209 } 210 211 bool operator!=(const Type& other) const { 212 return this->name() != other.name(); 213 } 214 215 /** 216 * Returns an abbreviated name of the type, meant for name-mangling. (e.g. float4x4 -> f44) 217 */ abbreviatedName()218 const char* abbreviatedName() const { 219 return fAbbreviatedName; 220 } 221 222 /** 223 * Returns the category (scalar, vector, matrix, etc.) of this type. 224 */ typeKind()225 TypeKind typeKind() const { 226 return fTypeKind; 227 } 228 229 /** 230 * Returns the NumberKind of this type (always kNonnumeric for non-scalar values). 231 */ numberKind()232 virtual NumberKind numberKind() const { 233 return NumberKind::kNonnumeric; 234 } 235 236 /** 237 * Returns true if this type is a bool. 238 */ isBoolean()239 bool isBoolean() const { 240 return this->numberKind() == NumberKind::kBoolean; 241 } 242 243 /** 244 * Returns true if this is a numeric scalar type. 245 */ isNumber()246 bool isNumber() const { 247 switch (this->numberKind()) { 248 case NumberKind::kFloat: 249 case NumberKind::kSigned: 250 case NumberKind::kUnsigned: 251 return true; 252 default: 253 return false; 254 } 255 } 256 257 /** 258 * Returns true if this is a floating-point scalar type (float or half). 259 */ isFloat()260 bool isFloat() const { 261 return this->numberKind() == NumberKind::kFloat; 262 } 263 264 /** 265 * Returns true if this is a signed scalar type (int or short). 266 */ isSigned()267 bool isSigned() const { 268 return this->numberKind() == NumberKind::kSigned; 269 } 270 271 /** 272 * Returns true if this is an unsigned scalar type (uint or ushort). 273 */ isUnsigned()274 bool isUnsigned() const { 275 return this->numberKind() == NumberKind::kUnsigned; 276 } 277 278 /** 279 * Returns true if this is a signed or unsigned integer. 280 */ isInteger()281 bool isInteger() const { 282 switch (this->numberKind()) { 283 case NumberKind::kSigned: 284 case NumberKind::kUnsigned: 285 return true; 286 default: 287 return false; 288 } 289 } 290 291 /** 292 * Returns true if this is an "opaque type" (an external object which the shader references in 293 * some fashion), or void. https://www.khronos.org/opengl/wiki/Data_Type_(GLSL)#Opaque_types 294 */ isOpaque()295 bool isOpaque() const { 296 switch (fTypeKind) { 297 case TypeKind::kBlender: 298 case TypeKind::kColorFilter: 299 case TypeKind::kOther: 300 case TypeKind::kSampler: 301 case TypeKind::kSeparateSampler: 302 case TypeKind::kShader: 303 case TypeKind::kTexture: 304 case TypeKind::kVoid: 305 return true; 306 default: 307 return false; 308 } 309 } 310 311 /** 312 * Returns the "priority" of a number type, in order of float > half > int > short. 313 * When operating on two number types, the result is the higher-priority type. 314 */ priority()315 virtual int priority() const { 316 SkDEBUGFAIL("not a number type"); 317 return -1; 318 } 319 320 /** 321 * Returns true if an instance of this type can be freely coerced (implicitly converted) to 322 * another type. 323 */ canCoerceTo(const Type & other,bool allowNarrowing)324 bool canCoerceTo(const Type& other, bool allowNarrowing) const { 325 return this->coercionCost(other).isPossible(allowNarrowing); 326 } 327 328 /** 329 * Determines the "cost" of coercing (implicitly converting) this type to another type. The cost 330 * is a number with no particular meaning other than that lower costs are preferable to higher 331 * costs. Returns INT_MAX if the coercion is not possible. 332 */ 333 CoercionCost coercionCost(const Type& other) const; 334 335 /** 336 * For matrices and vectors, returns the type of individual cells (e.g. mat2 has a component 337 * type of Float). For arrays, returns the base type. For all other types, returns the type 338 * itself. 339 */ componentType()340 virtual const Type& componentType() const { 341 return *this; 342 } 343 344 /** 345 * For texturesamplers, returns the type of texture it samples (e.g., sampler2D has 346 * a texture type of texture2D). 347 */ textureType()348 virtual const Type& textureType() const { 349 SkDEBUGFAIL("not a texture type"); 350 return *this; 351 } 352 353 /** 354 * For matrices and vectors, returns the number of columns (e.g. both mat3 and float3 return 3). 355 * For scalars, returns 1. For arrays, returns either the size of the array (if known) or -1. 356 * For all other types, causes an assertion failure. 357 */ columns()358 virtual int columns() const { 359 SkDEBUGFAIL("type does not have columns"); 360 return -1; 361 } 362 363 /** 364 * For matrices, returns the number of rows (e.g. mat2x4 returns 4). For vectors and scalars, 365 * returns 1. For all other types, causes an assertion failure. 366 */ rows()367 virtual int rows() const { 368 SkDEBUGFAIL("type does not have rows"); 369 return -1; 370 } 371 372 /** For integer types, returns the minimum value that can fit in the type. */ minimumValue()373 int64_t minimumValue() const { 374 SkASSERT(this->isInteger()); 375 constexpr int64_t k1 = 1; // ensures that `1 << n` is evaluated as 64-bit 376 return this->isUnsigned() ? 0 : -(k1 << (this->bitWidth() - 1)); 377 } 378 379 /** For integer types, returns the maximum value that can fit in the type. */ maximumValue()380 int64_t maximumValue() const { 381 SkASSERT(this->isInteger()); 382 constexpr int64_t k1 = 1; // ensures that `1 << n` is evaluated as 64-bit 383 return (this->isUnsigned() ? (k1 << this->bitWidth()) 384 : (k1 << (this->bitWidth() - 1))) - 1; 385 } 386 387 /** 388 * Returns the number of scalars needed to hold this type. 389 */ slotCount()390 virtual size_t slotCount() const { 391 return 0; 392 } 393 fields()394 virtual const std::vector<Field>& fields() const { 395 SK_ABORT("Internal error: not a struct"); 396 } 397 398 /** 399 * For generic types, returns the types that this generic type can substitute for. 400 */ coercibleTypes()401 virtual const std::vector<const Type*>& coercibleTypes() const { 402 SK_ABORT("Internal error: not a generic type"); 403 } 404 dimensions()405 virtual SpvDim_ dimensions() const { 406 SkASSERT(false); 407 return SpvDim1D; 408 } 409 isDepth()410 virtual bool isDepth() const { 411 SkASSERT(false); 412 return false; 413 } 414 isArrayedTexture()415 virtual bool isArrayedTexture() const { 416 SkASSERT(false); 417 return false; 418 } 419 isVoid()420 bool isVoid() const { 421 return fTypeKind == TypeKind::kVoid; 422 } 423 isScalar()424 virtual bool isScalar() const { 425 return false; 426 } 427 isLiteral()428 virtual bool isLiteral() const { 429 return false; 430 } 431 scalarTypeForLiteral()432 virtual const Type& scalarTypeForLiteral() const { 433 return *this; 434 } 435 isVector()436 virtual bool isVector() const { 437 return false; 438 } 439 isMatrix()440 virtual bool isMatrix() const { 441 return false; 442 } 443 isArray()444 virtual bool isArray() const { 445 return false; 446 } 447 isStruct()448 virtual bool isStruct() const { 449 return false; 450 } 451 452 // Is this type something that can be bound & sampled from an SkRuntimeEffect? 453 // Includes types that represent stages of the Skia pipeline (colorFilter, shader, blender). isEffectChild()454 bool isEffectChild() const { 455 return fTypeKind == TypeKind::kColorFilter || 456 fTypeKind == TypeKind::kShader || 457 fTypeKind == TypeKind::kBlender; 458 } 459 isMultisampled()460 virtual bool isMultisampled() const { 461 SkASSERT(false); 462 return false; 463 } 464 isSampled()465 virtual bool isSampled() const { 466 SkASSERT(false); 467 return false; 468 } 469 hasPrecision()470 bool hasPrecision() const { 471 return this->componentType().isNumber() || fTypeKind == TypeKind::kSampler; 472 } 473 highPrecision()474 bool highPrecision() const { 475 return this->bitWidth() >= 32; 476 } 477 bitWidth()478 virtual int bitWidth() const { 479 return 0; 480 } 481 482 bool isOrContainsArray() const; 483 484 /** 485 * Returns true if this type is a struct that is too deeply nested. 486 */ 487 bool isTooDeeplyNested() const; 488 489 /** 490 * Returns the corresponding vector or matrix type with the specified number of columns and 491 * rows. 492 */ 493 const Type& toCompound(const Context& context, int columns, int rows) const; 494 495 /** 496 * Returns a type which honors the precision qualifiers set in Modifiers. e.g., kMediump_Flag 497 * when applied to `float2` will return `half2`. Generates an error if the precision qualifiers 498 * don't make sense, e.g. `highp bool` or `mediump MyStruct`. 499 */ 500 const Type* applyPrecisionQualifiers(const Context& context, 501 Modifiers* modifiers, 502 SymbolTable* symbols, 503 int line) const; 504 505 /** 506 * Coerces the passed-in expression to this type. If the types are incompatible, reports an 507 * error and returns null. 508 */ 509 std::unique_ptr<Expression> coerceExpression(std::unique_ptr<Expression> expr, 510 const Context& context) const; 511 512 /** Detects any IntLiterals in the expression which can't fit in this type. */ 513 bool checkForOutOfRangeLiteral(const Context& context, const Expression& expr) const; 514 515 /** Checks if `value` can fit in this type. The type must be scalar. */ 516 bool checkForOutOfRangeLiteral(const Context& context, double value, int line) const; 517 518 /** 519 * Verifies that the expression is a valid constant array size for this type. Returns the array 520 * size, or zero if the expression isn't a valid literal value. 521 */ 522 SKSL_INT convertArraySize(const Context& context, std::unique_ptr<Expression> size) const; 523 524 protected: 525 Type(skstd::string_view name, const char* abbrev, TypeKind kind, int line = -1) INHERITED(line,kSymbolKind,name)526 : INHERITED(line, kSymbolKind, name) 527 , fTypeKind(kind) { 528 SkASSERT(strlen(abbrev) <= kMaxAbbrevLength); 529 strcpy(fAbbreviatedName, abbrev); 530 } 531 532 private: 533 bool isTooDeeplyNested(int limit) const; 534 535 using INHERITED = Symbol; 536 537 char fAbbreviatedName[kMaxAbbrevLength + 1] = {}; 538 TypeKind fTypeKind; 539 }; 540 541 } // namespace SkSL 542 543 #endif 544