• 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 <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 {
FieldField30         Field(Modifiers modifiers, StringFragment name, const Type* type)
31         : fModifiers(modifiers)
32         , fName(name)
33         , fType(std::move(type)) {}
34 
descriptionField35         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.
Type(const char * name)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.
Type(const char * name,std::vector<Field> fields)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.
Type(String name,Kind kind)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.
Type(const char * name,std::vector<const Type * > 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.
Type(int offset,String name,std::vector<Field> 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.
Type(const char * name,NumberKind numberKind,int priority)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.
Type(const char * name,NumberKind numberKind,int priority,std::vector<const Type * > coercibleTypes)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.
Type(const char * name,const Type & componentType,int columns)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.
Type(String name,Kind kind,const Type & componentType,int columns)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.
Type(const char * name,const Type & componentType,int columns,int rows)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.
Type(const char * name,SpvDim_ dimensions,bool isDepth,bool isArrayed,bool isMultisampled,bool isSampled)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 
name()195     const String& name() const {
196         return fNameString;
197     }
198 
description()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      */
kind()214     Kind kind() const {
215         return fTypeKind;
216     }
217 
218     /**
219      * Returns true if this is a numeric scalar type.
220      */
isNumber()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      */
isFloat()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      */
isSigned()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      */
isUnsigned()242     bool isUnsigned() const {
243         return fNumberKind == kUnsigned_NumberKind;
244     }
245 
246     /**
247      * Returns true if this is a signed or unsigned integer.
248      */
isInteger()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      */
priority()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      */
canCoerceTo(const Type & other)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      */
componentType()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      */
columns()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      */
rows()300     int rows() const {
301         SkASSERT(fRows > 0);
302         return fRows;
303     }
304 
fields()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      */
coercibleTypes()314     const std::vector<const Type*>& coercibleTypes() const {
315         SkASSERT(fCoercibleTypes.size() > 0);
316         return fCoercibleTypes;
317     }
318 
dimensions()319     SpvDim_ dimensions() const {
320         SkASSERT(kSampler_Kind == fTypeKind);
321         return fDimensions;
322     }
323 
isDepth()324     bool isDepth() const {
325         SkASSERT(kSampler_Kind == fTypeKind);
326         return fIsDepth;
327     }
328 
isArrayed()329     bool isArrayed() const {
330         SkASSERT(kSampler_Kind == fTypeKind);
331         return fIsArrayed;
332     }
333 
isMultisampled()334     bool isMultisampled() const {
335         SkASSERT(kSampler_Kind == fTypeKind);
336         return fIsMultisampled;
337     }
338 
isSampled()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