Line data Source code
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 0 : class Type : public Symbol {
27 : public:
28 0 : struct Field {
29 0 : Field(Modifiers modifiers, String name, const Type* type)
30 0 : : fModifiers(modifiers)
31 0 : , fName(std::move(name))
32 0 : , fType(std::move(type)) {}
33 :
34 0 : const String description() const {
35 0 : 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.
56 0 : Type(String name)
57 0 : : INHERITED(Position(), kType_Kind, std::move(name))
58 0 : , fTypeKind(kOther_Kind) {}
59 :
60 : // Create a generic type which maps to the listed types.
61 0 : Type(String name, std::vector<const Type*> types)
62 0 : : INHERITED(Position(), kType_Kind, std::move(name))
63 : , fTypeKind(kGeneric_Kind)
64 0 : , fCoercibleTypes(std::move(types)) {}
65 :
66 : // Create a struct type with the given fields.
67 0 : Type(Position position, String name, std::vector<Field> fields)
68 0 : : INHERITED(position, kType_Kind, std::move(name))
69 : , fTypeKind(kStruct_Kind)
70 0 : , fFields(std::move(fields)) {}
71 :
72 : // Create a scalar type.
73 0 : Type(String name, bool isNumber)
74 0 : : INHERITED(Position(), kType_Kind, std::move(name))
75 : , fTypeKind(kScalar_Kind)
76 : , fIsNumber(isNumber)
77 : , fColumns(1)
78 0 : , fRows(1) {}
79 :
80 : // Create a scalar type which can be coerced to the listed types.
81 0 : Type(String name, bool isNumber, std::vector<const Type*> coercibleTypes)
82 0 : : INHERITED(Position(), kType_Kind, std::move(name))
83 : , fTypeKind(kScalar_Kind)
84 : , fIsNumber(isNumber)
85 0 : , fCoercibleTypes(std::move(coercibleTypes))
86 : , fColumns(1)
87 0 : , fRows(1) {}
88 :
89 : // Create a vector type.
90 0 : Type(String name, const Type& componentType, int columns)
91 0 : : Type(name, kVector_Kind, componentType, columns) {}
92 :
93 : // Create a vector or array type.
94 0 : Type(String name, Kind kind, const Type& componentType, int columns)
95 0 : : INHERITED(Position(), kType_Kind, std::move(name))
96 : , fTypeKind(kind)
97 : , fComponentType(&componentType)
98 : , fColumns(columns)
99 : , fRows(1)
100 0 : , fDimensions(SpvDim1D) {}
101 :
102 : // Create a matrix type.
103 0 : Type(String name, const Type& componentType, int columns, int rows)
104 0 : : INHERITED(Position(), kType_Kind, std::move(name))
105 : , fTypeKind(kMatrix_Kind)
106 : , fComponentType(&componentType)
107 : , fColumns(columns)
108 : , fRows(rows)
109 0 : , fDimensions(SpvDim1D) {}
110 :
111 : // Create a sampler type.
112 0 : Type(String name, SpvDim_ dimensions, bool isDepth, bool isArrayed, bool isMultisampled,
113 : bool isSampled)
114 0 : : INHERITED(Position(), kType_Kind, std::move(name))
115 : , fTypeKind(kSampler_Kind)
116 : , fDimensions(dimensions)
117 : , fIsDepth(isDepth)
118 : , fIsArrayed(isArrayed)
119 : , fIsMultisampled(isMultisampled)
120 0 : , fIsSampled(isSampled) {}
121 :
122 0 : String name() const {
123 0 : return fName;
124 : }
125 :
126 0 : String description() const override {
127 0 : return fName;
128 : }
129 :
130 0 : bool operator==(const Type& other) const {
131 0 : return fName == other.fName;
132 : }
133 :
134 0 : bool operator!=(const Type& other) const {
135 0 : return fName != other.fName;
136 : }
137 :
138 : /**
139 : * Returns the category (scalar, vector, matrix, etc.) of this type.
140 : */
141 0 : Kind kind() const {
142 0 : return fTypeKind;
143 : }
144 :
145 : /**
146 : * Returns true if this is a numeric scalar type.
147 : */
148 0 : bool isNumber() const {
149 0 : 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 : */
156 0 : bool canCoerceTo(const Type& other) const {
157 : int cost;
158 0 : 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 : */
173 0 : const Type& componentType() const {
174 0 : ASSERT(fComponentType);
175 0 : 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 : */
183 0 : int columns() const {
184 0 : ASSERT(fTypeKind == kScalar_Kind || fTypeKind == kVector_Kind ||
185 : fTypeKind == kMatrix_Kind || fTypeKind == kArray_Kind);
186 0 : 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 : */
193 0 : int rows() const {
194 0 : ASSERT(fRows > 0);
195 0 : return fRows;
196 : }
197 :
198 0 : const std::vector<Field>& fields() const {
199 0 : ASSERT(fTypeKind == kStruct_Kind);
200 0 : 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 : */
207 0 : const std::vector<const Type*>& coercibleTypes() const {
208 0 : ASSERT(fCoercibleTypes.size() > 0);
209 0 : return fCoercibleTypes;
210 : }
211 :
212 0 : SpvDim_ dimensions() const {
213 0 : ASSERT(kSampler_Kind == fTypeKind);
214 0 : return fDimensions;
215 : }
216 :
217 0 : bool isDepth() const {
218 0 : ASSERT(kSampler_Kind == fTypeKind);
219 0 : return fIsDepth;
220 : }
221 :
222 0 : bool isArrayed() const {
223 0 : ASSERT(kSampler_Kind == fTypeKind);
224 0 : return fIsArrayed;
225 : }
226 :
227 0 : bool isMultisampled() const {
228 0 : ASSERT(kSampler_Kind == fTypeKind);
229 0 : return fIsMultisampled;
230 : }
231 :
232 0 : bool isSampled() const {
233 0 : ASSERT(kSampler_Kind == fTypeKind);
234 0 : 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
|