• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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