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