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