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 SKIASL_TYPE 9 #define SKIASL_TYPE 10 11 #include "SkSLModifiers.h" 12 #include "SkSLSymbol.h" 13 #include "../SkSLPosition.h" 14 #include "../SkSLUtil.h" 15 #include "../spirv.h" 16 #include <climits> 17 #include <vector> 18 #include <memory> 19 20 namespace SkSL { 21 22 class Context; 23 24 /** 25 * Represents a type, such as int or float4. 26 */ 27 class Type : public Symbol { 28 public: 29 struct Field { 30 Field(Modifiers modifiers, StringFragment name, const Type* type) 31 : fModifiers(modifiers) 32 , fName(name) 33 , fType(std::move(type)) {} 34 35 const String description() const { 36 return fType->description() + " " + fName + ";"; 37 } 38 39 Modifiers fModifiers; 40 StringFragment fName; 41 const Type* fType; 42 }; 43 44 enum Kind { 45 kArray_Kind, 46 kEnum_Kind, 47 kGeneric_Kind, 48 kNullable_Kind, 49 kMatrix_Kind, 50 kOther_Kind, 51 kSampler_Kind, 52 kScalar_Kind, 53 kStruct_Kind, 54 kVector_Kind 55 }; 56 57 enum NumberKind { 58 kFloat_NumberKind, 59 kSigned_NumberKind, 60 kUnsigned_NumberKind, 61 kNonnumeric_NumberKind 62 }; 63 64 // Create an "other" (special) type with the given name. These types cannot be directly 65 // referenced from user code. 66 Type(const char* name) 67 : INHERITED(-1, kType_Kind, StringFragment()) 68 , fNameString(name) 69 , fTypeKind(kOther_Kind) 70 , fNumberKind(kNonnumeric_NumberKind) { 71 fName.fChars = fNameString.c_str(); 72 fName.fLength = fNameString.size(); 73 } 74 75 // Create an "other" (special) type that supports field access. 76 Type(const char* name, std::vector<Field> fields) 77 : INHERITED(-1, kType_Kind, StringFragment()) 78 , fNameString(name) 79 , fTypeKind(kOther_Kind) 80 , fNumberKind(kNonnumeric_NumberKind) 81 , fFields(std::move(fields)) { 82 fName.fChars = fNameString.c_str(); 83 fName.fLength = fNameString.size(); 84 } 85 86 // Create a simple type. 87 Type(String name, Kind kind) 88 : INHERITED(-1, kType_Kind, StringFragment()) 89 , fNameString(std::move(name)) 90 , fTypeKind(kind) 91 , fNumberKind(kNonnumeric_NumberKind) { 92 fName.fChars = fNameString.c_str(); 93 fName.fLength = fNameString.size(); 94 } 95 96 // Create a generic type which maps to the listed types. 97 Type(const char* name, std::vector<const Type*> types) 98 : INHERITED(-1, kType_Kind, StringFragment()) 99 , fNameString(name) 100 , fTypeKind(kGeneric_Kind) 101 , fNumberKind(kNonnumeric_NumberKind) 102 , fCoercibleTypes(std::move(types)) { 103 fName.fChars = fNameString.c_str(); 104 fName.fLength = fNameString.size(); 105 } 106 107 // Create a struct type with the given fields. 108 Type(int offset, String name, std::vector<Field> fields) 109 : INHERITED(offset, kType_Kind, StringFragment()) 110 , fNameString(std::move(name)) 111 , fTypeKind(kStruct_Kind) 112 , fNumberKind(kNonnumeric_NumberKind) 113 , fFields(std::move(fields)) { 114 fName.fChars = fNameString.c_str(); 115 fName.fLength = fNameString.size(); 116 } 117 118 // Create a scalar type. 119 Type(const char* name, NumberKind numberKind, int priority, bool highPrecision = false) 120 : INHERITED(-1, kType_Kind, StringFragment()) 121 , fNameString(name) 122 , fTypeKind(kScalar_Kind) 123 , fNumberKind(numberKind) 124 , fPriority(priority) 125 , fColumns(1) 126 , fRows(1) 127 , fHighPrecision(highPrecision) { 128 fName.fChars = fNameString.c_str(); 129 fName.fLength = fNameString.size(); 130 } 131 132 // Create a scalar type which can be coerced to the listed types. 133 Type(const char* name, 134 NumberKind numberKind, 135 int priority, 136 std::vector<const Type*> coercibleTypes) 137 : INHERITED(-1, kType_Kind, StringFragment()) 138 , fNameString(name) 139 , fTypeKind(kScalar_Kind) 140 , fNumberKind(numberKind) 141 , fPriority(priority) 142 , fCoercibleTypes(std::move(coercibleTypes)) 143 , fColumns(1) 144 , fRows(1) { 145 fName.fChars = fNameString.c_str(); 146 fName.fLength = fNameString.size(); 147 } 148 149 // Create a nullable type. 150 Type(String name, Kind kind, const Type& componentType) 151 : INHERITED(-1, kType_Kind, StringFragment()) 152 , fNameString(std::move(name)) 153 , fTypeKind(kind) 154 , fNumberKind(kNonnumeric_NumberKind) 155 , fComponentType(&componentType) 156 , fColumns(1) 157 , fRows(1) 158 , fDimensions(SpvDim1D) { 159 fName.fChars = fNameString.c_str(); 160 fName.fLength = fNameString.size(); 161 } 162 163 // Create a vector type. 164 Type(const char* name, const Type& componentType, int columns) 165 : Type(name, kVector_Kind, componentType, columns) {} 166 167 // Create a vector or array type. 168 Type(String name, Kind kind, const Type& componentType, int columns) 169 : INHERITED(-1, kType_Kind, StringFragment()) 170 , fNameString(std::move(name)) 171 , fTypeKind(kind) 172 , fNumberKind(kNonnumeric_NumberKind) 173 , fComponentType(&componentType) 174 , fColumns(columns) 175 , fRows(1) 176 , fDimensions(SpvDim1D) { 177 fName.fChars = fNameString.c_str(); 178 fName.fLength = fNameString.size(); 179 } 180 181 // Create a matrix type. 182 Type(const char* name, const Type& componentType, int columns, int rows) 183 : INHERITED(-1, kType_Kind, StringFragment()) 184 , fNameString(name) 185 , fTypeKind(kMatrix_Kind) 186 , fNumberKind(kNonnumeric_NumberKind) 187 , fComponentType(&componentType) 188 , fColumns(columns) 189 , fRows(rows) 190 , fDimensions(SpvDim1D) { 191 fName.fChars = fNameString.c_str(); 192 fName.fLength = fNameString.size(); 193 } 194 195 // Create a sampler type. 196 Type(const char* name, SpvDim_ dimensions, bool isDepth, bool isArrayed, bool isMultisampled, 197 bool isSampled) 198 : INHERITED(-1, kType_Kind, StringFragment()) 199 , fNameString(name) 200 , fTypeKind(kSampler_Kind) 201 , fNumberKind(kNonnumeric_NumberKind) 202 , fDimensions(dimensions) 203 , fIsDepth(isDepth) 204 , fIsArrayed(isArrayed) 205 , fIsMultisampled(isMultisampled) 206 , fIsSampled(isSampled) { 207 fName.fChars = fNameString.c_str(); 208 fName.fLength = fNameString.size(); 209 } 210 211 const String& name() const { 212 return fNameString; 213 } 214 215 String description() const override { 216 if (fNameString == "$floatLiteral") { 217 return "float"; 218 } 219 if (fNameString == "$intLiteral") { 220 return "int"; 221 } 222 return fNameString; 223 } 224 225 bool operator==(const Type& other) const { 226 return fName == other.fName; 227 } 228 229 bool operator!=(const Type& other) const { 230 return fName != other.fName; 231 } 232 233 /** 234 * Returns the category (scalar, vector, matrix, etc.) of this type. 235 */ 236 Kind kind() const { 237 return fTypeKind; 238 } 239 240 /** 241 * Returns true if this is a numeric scalar type. 242 */ 243 bool isNumber() const { 244 return fNumberKind != kNonnumeric_NumberKind; 245 } 246 247 /** 248 * Returns true if this is a floating-point scalar type (float, half, or double). 249 */ 250 bool isFloat() const { 251 return fNumberKind == kFloat_NumberKind; 252 } 253 254 /** 255 * Returns true if this is a signed scalar type (int or short). 256 */ 257 bool isSigned() const { 258 return fNumberKind == kSigned_NumberKind; 259 } 260 261 /** 262 * Returns true if this is an unsigned scalar type (uint or ushort). 263 */ 264 bool isUnsigned() const { 265 return fNumberKind == kUnsigned_NumberKind; 266 } 267 268 /** 269 * Returns true if this is a signed or unsigned integer. 270 */ 271 bool isInteger() const { 272 return isSigned() || isUnsigned(); 273 } 274 275 /** 276 * Returns the "priority" of a number type, in order of double > float > half > int > short. 277 * When operating on two number types, the result is the higher-priority type. 278 */ 279 int priority() const { 280 return fPriority; 281 } 282 283 /** 284 * Returns true if an instance of this type can be freely coerced (implicitly converted) to 285 * another type. 286 */ 287 bool canCoerceTo(const Type& other) const { 288 return coercionCost(other) != INT_MAX; 289 } 290 291 /** 292 * Determines the "cost" of coercing (implicitly converting) this type to another type. The cost 293 * is a number with no particular meaning other than that lower costs are preferable to higher 294 * costs. Returns INT_MAX if the coercion is not possible. 295 */ 296 int coercionCost(const Type& other) const; 297 298 /** 299 * For matrices and vectors, returns the type of individual cells (e.g. mat2 has a component 300 * type of kFloat_Type). For all other types, causes an SkASSERTion failure. 301 */ 302 const Type& componentType() const { 303 SkASSERT(fComponentType); 304 return *fComponentType; 305 } 306 307 /** 308 * For nullable types, returns the base type, otherwise returns the type itself. 309 */ 310 const Type& nonnullable() const { 311 if (fTypeKind == kNullable_Kind) { 312 return this->componentType(); 313 } 314 return *this; 315 } 316 317 /** 318 * For matrices and vectors, returns the number of columns (e.g. both mat3 and float3return 3). 319 * For scalars, returns 1. For arrays, returns either the size of the array (if known) or -1. 320 * For all other types, causes an SkASSERTion failure. 321 */ 322 int columns() const { 323 SkASSERT(fTypeKind == kScalar_Kind || fTypeKind == kVector_Kind || 324 fTypeKind == kMatrix_Kind || fTypeKind == kArray_Kind); 325 return fColumns; 326 } 327 328 /** 329 * For matrices, returns the number of rows (e.g. mat2x4 returns 4). For vectors and scalars, 330 * returns 1. For all other types, causes an SkASSERTion failure. 331 */ 332 int rows() const { 333 SkASSERT(fRows > 0); 334 return fRows; 335 } 336 337 const std::vector<Field>& fields() const { 338 SkASSERT(fTypeKind == kStruct_Kind || fTypeKind == kOther_Kind); 339 return fFields; 340 } 341 342 /** 343 * For generic types, returns the types that this generic type can substitute for. For other 344 * types, returns a list of other types that this type can be coerced into. 345 */ 346 const std::vector<const Type*>& coercibleTypes() const { 347 SkASSERT(fCoercibleTypes.size() > 0); 348 return fCoercibleTypes; 349 } 350 351 SpvDim_ dimensions() const { 352 SkASSERT(kSampler_Kind == fTypeKind); 353 return fDimensions; 354 } 355 356 bool isDepth() const { 357 SkASSERT(kSampler_Kind == fTypeKind); 358 return fIsDepth; 359 } 360 361 bool isArrayed() const { 362 SkASSERT(kSampler_Kind == fTypeKind); 363 return fIsArrayed; 364 } 365 366 bool isMultisampled() const { 367 SkASSERT(kSampler_Kind == fTypeKind); 368 return fIsMultisampled; 369 } 370 371 bool isSampled() const { 372 SkASSERT(kSampler_Kind == fTypeKind); 373 return fIsSampled; 374 } 375 376 bool highPrecision() const { 377 if (fComponentType) { 378 return fComponentType->highPrecision(); 379 } 380 return fHighPrecision; 381 } 382 383 /** 384 * Returns the corresponding vector or matrix type with the specified number of columns and 385 * rows. 386 */ 387 const Type& toCompound(const Context& context, int columns, int rows) const; 388 389 private: 390 typedef Symbol INHERITED; 391 392 String fNameString; 393 Kind fTypeKind; 394 // always kNonnumeric_NumberKind for non-scalar values 395 NumberKind fNumberKind; 396 int fPriority = -1; 397 const Type* fComponentType = nullptr; 398 std::vector<const Type*> fCoercibleTypes; 399 int fColumns = -1; 400 int fRows = -1; 401 std::vector<Field> fFields; 402 SpvDim_ fDimensions = SpvDim1D; 403 bool fIsDepth = false; 404 bool fIsArrayed = false; 405 bool fIsMultisampled = false; 406 bool fIsSampled = false; 407 bool fHighPrecision = false; 408 }; 409 410 } // namespace 411 412 #endif 413