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