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 <vector> 17 #include <memory> 18 19 namespace SkSL { 20 21 class Context; 22 23 /** 24 * Represents a type, such as int or vec4. 25 */ 26 class Type : public Symbol { 27 public: 28 struct Field { FieldField29 Field(Modifiers modifiers, String name, const Type* type) 30 : fModifiers(modifiers) 31 , fName(std::move(name)) 32 , fType(std::move(type)) {} 33 descriptionField34 const String description() const { 35 return fType->description() + " " + fName + ";"; 36 } 37 38 Modifiers fModifiers; 39 String fName; 40 const Type* fType; 41 }; 42 43 enum Kind { 44 kScalar_Kind, 45 kVector_Kind, 46 kMatrix_Kind, 47 kArray_Kind, 48 kStruct_Kind, 49 kGeneric_Kind, 50 kSampler_Kind, 51 kOther_Kind 52 }; 53 54 // Create an "other" (special) type with the given name. These types cannot be directly 55 // referenced from user code. Type(String name)56 Type(String name) 57 : INHERITED(Position(), kType_Kind, std::move(name)) 58 , fTypeKind(kOther_Kind) {} 59 60 // Create a generic type which maps to the listed types. Type(String name,std::vector<const Type * > types)61 Type(String name, std::vector<const Type*> types) 62 : INHERITED(Position(), kType_Kind, std::move(name)) 63 , fTypeKind(kGeneric_Kind) 64 , fCoercibleTypes(std::move(types)) {} 65 66 // Create a struct type with the given fields. Type(Position position,String name,std::vector<Field> fields)67 Type(Position position, String name, std::vector<Field> fields) 68 : INHERITED(position, kType_Kind, std::move(name)) 69 , fTypeKind(kStruct_Kind) 70 , fFields(std::move(fields)) {} 71 72 // Create a scalar type. Type(String name,bool isNumber)73 Type(String name, bool isNumber) 74 : INHERITED(Position(), kType_Kind, std::move(name)) 75 , fTypeKind(kScalar_Kind) 76 , fIsNumber(isNumber) 77 , fColumns(1) 78 , fRows(1) {} 79 80 // Create a scalar type which can be coerced to the listed types. Type(String name,bool isNumber,std::vector<const Type * > coercibleTypes)81 Type(String name, bool isNumber, std::vector<const Type*> coercibleTypes) 82 : INHERITED(Position(), kType_Kind, std::move(name)) 83 , fTypeKind(kScalar_Kind) 84 , fIsNumber(isNumber) 85 , fCoercibleTypes(std::move(coercibleTypes)) 86 , fColumns(1) 87 , fRows(1) {} 88 89 // Create a vector type. Type(String name,const Type & componentType,int columns)90 Type(String name, const Type& componentType, int columns) 91 : Type(name, kVector_Kind, componentType, columns) {} 92 93 // Create a vector or array type. Type(String name,Kind kind,const Type & componentType,int columns)94 Type(String name, Kind kind, const Type& componentType, int columns) 95 : INHERITED(Position(), kType_Kind, std::move(name)) 96 , fTypeKind(kind) 97 , fComponentType(&componentType) 98 , fColumns(columns) 99 , fRows(1) 100 , fDimensions(SpvDim1D) {} 101 102 // Create a matrix type. Type(String name,const Type & componentType,int columns,int rows)103 Type(String name, const Type& componentType, int columns, int rows) 104 : INHERITED(Position(), kType_Kind, std::move(name)) 105 , fTypeKind(kMatrix_Kind) 106 , fComponentType(&componentType) 107 , fColumns(columns) 108 , fRows(rows) 109 , fDimensions(SpvDim1D) {} 110 111 // Create a sampler type. Type(String name,SpvDim_ dimensions,bool isDepth,bool isArrayed,bool isMultisampled,bool isSampled)112 Type(String name, SpvDim_ dimensions, bool isDepth, bool isArrayed, bool isMultisampled, 113 bool isSampled) 114 : INHERITED(Position(), kType_Kind, std::move(name)) 115 , fTypeKind(kSampler_Kind) 116 , fDimensions(dimensions) 117 , fIsDepth(isDepth) 118 , fIsArrayed(isArrayed) 119 , fIsMultisampled(isMultisampled) 120 , fIsSampled(isSampled) {} 121 name()122 String name() const { 123 return fName; 124 } 125 description()126 String description() const override { 127 return fName; 128 } 129 130 bool operator==(const Type& other) const { 131 return fName == other.fName; 132 } 133 134 bool operator!=(const Type& other) const { 135 return fName != other.fName; 136 } 137 138 /** 139 * Returns the category (scalar, vector, matrix, etc.) of this type. 140 */ kind()141 Kind kind() const { 142 return fTypeKind; 143 } 144 145 /** 146 * Returns true if this is a numeric scalar type. 147 */ isNumber()148 bool isNumber() const { 149 return fIsNumber; 150 } 151 152 /** 153 * Returns true if an instance of this type can be freely coerced (implicitly converted) to 154 * another type. 155 */ canCoerceTo(const Type & other)156 bool canCoerceTo(const Type& other) const { 157 int cost; 158 return determineCoercionCost(other, &cost); 159 } 160 161 /** 162 * Determines the "cost" of coercing (implicitly converting) this type to another type. The cost 163 * is a number with no particular meaning other than that lower costs are preferable to higher 164 * costs. Returns true if a conversion is possible, false otherwise. The value of the out 165 * parameter is undefined if false is returned. 166 */ 167 bool determineCoercionCost(const Type& other, int* outCost) const; 168 169 /** 170 * For matrices and vectors, returns the type of individual cells (e.g. mat2 has a component 171 * type of kFloat_Type). For all other types, causes an assertion failure. 172 */ componentType()173 const Type& componentType() const { 174 ASSERT(fComponentType); 175 return *fComponentType; 176 } 177 178 /** 179 * For matrices and vectors, returns the number of columns (e.g. both mat3 and vec3 return 3). 180 * For scalars, returns 1. For arrays, returns either the size of the array (if known) or -1. 181 * For all other types, causes an assertion failure. 182 */ columns()183 int columns() const { 184 ASSERT(fTypeKind == kScalar_Kind || fTypeKind == kVector_Kind || 185 fTypeKind == kMatrix_Kind || fTypeKind == kArray_Kind); 186 return fColumns; 187 } 188 189 /** 190 * For matrices, returns the number of rows (e.g. mat2x4 returns 4). For vectors and scalars, 191 * returns 1. For all other types, causes an assertion failure. 192 */ rows()193 int rows() const { 194 ASSERT(fRows > 0); 195 return fRows; 196 } 197 fields()198 const std::vector<Field>& fields() const { 199 ASSERT(fTypeKind == kStruct_Kind); 200 return fFields; 201 } 202 203 /** 204 * For generic types, returns the types that this generic type can substitute for. For other 205 * types, returns a list of other types that this type can be coerced into. 206 */ coercibleTypes()207 const std::vector<const Type*>& coercibleTypes() const { 208 ASSERT(fCoercibleTypes.size() > 0); 209 return fCoercibleTypes; 210 } 211 dimensions()212 SpvDim_ dimensions() const { 213 ASSERT(kSampler_Kind == fTypeKind); 214 return fDimensions; 215 } 216 isDepth()217 bool isDepth() const { 218 ASSERT(kSampler_Kind == fTypeKind); 219 return fIsDepth; 220 } 221 isArrayed()222 bool isArrayed() const { 223 ASSERT(kSampler_Kind == fTypeKind); 224 return fIsArrayed; 225 } 226 isMultisampled()227 bool isMultisampled() const { 228 ASSERT(kSampler_Kind == fTypeKind); 229 return fIsMultisampled; 230 } 231 isSampled()232 bool isSampled() const { 233 ASSERT(kSampler_Kind == fTypeKind); 234 return fIsSampled; 235 } 236 237 /** 238 * Returns the corresponding vector or matrix type with the specified number of columns and 239 * rows. 240 */ 241 const Type& toCompound(const Context& context, int columns, int rows) const; 242 243 private: 244 typedef Symbol INHERITED; 245 246 const Kind fTypeKind; 247 const bool fIsNumber = false; 248 const Type* fComponentType = nullptr; 249 const std::vector<const Type*> fCoercibleTypes; 250 const int fColumns = -1; 251 const int fRows = -1; 252 const std::vector<Field> fFields; 253 const SpvDim_ fDimensions = SpvDim1D; 254 const bool fIsDepth = false; 255 const bool fIsArrayed = false; 256 const bool fIsMultisampled = false; 257 const bool fIsSampled = false; 258 }; 259 260 } // namespace 261 262 #endif 263