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