/src/skia/src/sksl/ir/SkSLType.h
Line | Count | Source (jump to first uncovered line) |
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 SKSL_TYPE |
9 | | #define SKSL_TYPE |
10 | | |
11 | | #include "include/core/SkStringView.h" |
12 | | #include "include/private/SkSLModifiers.h" |
13 | | #include "include/private/SkSLSymbol.h" |
14 | | #include "src/sksl/SkSLPosition.h" |
15 | | #include "src/sksl/SkSLUtil.h" |
16 | | #include "src/sksl/spirv.h" |
17 | | #include <algorithm> |
18 | | #include <climits> |
19 | | #include <vector> |
20 | | #include <memory> |
21 | | |
22 | | namespace SkSL { |
23 | | |
24 | | class BuiltinTypes; |
25 | | class Context; |
26 | | class SymbolTable; |
27 | | |
28 | | struct CoercionCost { |
29 | 21.2M | static CoercionCost Free() { return { 0, 0, false }; } |
30 | 86.6k | static CoercionCost Normal(int cost) { return { cost, 0, false }; } |
31 | 104k | static CoercionCost Narrowing(int cost) { return { 0, cost, false }; } |
32 | 667k | static CoercionCost Impossible() { return { 0, 0, true }; } |
33 | | |
34 | 20.9M | bool isPossible(bool allowNarrowing) const { |
35 | 20.9M | return !fImpossible && (fNarrowingCost == 0 || allowNarrowing); |
36 | 20.9M | } |
37 | | |
38 | | // Addition of two costs. Saturates at Impossible(). |
39 | 179k | CoercionCost operator+(CoercionCost rhs) const { |
40 | 179k | if (fImpossible || rhs.fImpossible) { |
41 | 1.71k | return Impossible(); |
42 | 1.71k | } |
43 | 177k | return { fNormalCost + rhs.fNormalCost, fNarrowingCost + rhs.fNarrowingCost, false }; |
44 | 177k | } |
45 | | |
46 | 10.3M | bool operator<(CoercionCost rhs) const { |
47 | 10.3M | return std::tie( fImpossible, fNarrowingCost, fNormalCost) < |
48 | 10.3M | std::tie(rhs.fImpossible, rhs.fNarrowingCost, rhs.fNormalCost); |
49 | 10.3M | } |
50 | | |
51 | | int fNormalCost; |
52 | | int fNarrowingCost; |
53 | | bool fImpossible; |
54 | | }; |
55 | | |
56 | | /** |
57 | | * Represents a type, such as int or float4. |
58 | | */ |
59 | | class Type : public Symbol { |
60 | | public: |
61 | | static constexpr Kind kSymbolKind = Kind::kType; |
62 | | static constexpr int kMaxAbbrevLength = 3; |
63 | | |
64 | | struct Field { |
65 | | Field(Modifiers modifiers, skstd::string_view name, const Type* type) |
66 | | : fModifiers(modifiers) |
67 | | , fName(name) |
68 | 191k | , fType(std::move(type)) {} |
69 | | |
70 | 0 | String description() const { |
71 | 0 | return fType->displayName() + " " + fName + ";"; |
72 | 0 | } |
73 | | |
74 | | Modifiers fModifiers; |
75 | | skstd::string_view fName; |
76 | | const Type* fType; |
77 | | }; |
78 | | |
79 | | enum class TypeKind : int8_t { |
80 | | kArray, |
81 | | kGeneric, |
82 | | kLiteral, |
83 | | kMatrix, |
84 | | kOther, |
85 | | kSampler, |
86 | | kSeparateSampler, |
87 | | kScalar, |
88 | | kStruct, |
89 | | kTexture, |
90 | | kVector, |
91 | | kVoid, |
92 | | |
93 | | // Types that represent stages in the Skia pipeline |
94 | | kColorFilter, |
95 | | kShader, |
96 | | kBlender, |
97 | | }; |
98 | | |
99 | | enum class NumberKind : int8_t { |
100 | | kFloat, |
101 | | kSigned, |
102 | | kUnsigned, |
103 | | kBoolean, |
104 | | kNonnumeric |
105 | | }; |
106 | | |
107 | | Type(const Type& other) = delete; |
108 | | |
109 | | /** Creates an array type. */ |
110 | | static constexpr int kUnsizedArray = -1; |
111 | | static std::unique_ptr<Type> MakeArrayType(skstd::string_view name, const Type& componentType, |
112 | | int columns); |
113 | | |
114 | | /** Converts a component type and a size (float, 10) into an array name ("float[10]"). */ |
115 | | String getArrayName(int arraySize) const; |
116 | | |
117 | | /** |
118 | | * Create a generic type which maps to the listed types--e.g. $genType is a generic type which |
119 | | * can match float, float2, float3 or float4. |
120 | | */ |
121 | | static std::unique_ptr<Type> MakeGenericType(const char* name, std::vector<const Type*> types); |
122 | | |
123 | | /** Create a type for literal scalars. */ |
124 | | static std::unique_ptr<Type> MakeLiteralType(const char* name, const Type& scalarType, |
125 | | int8_t priority); |
126 | | |
127 | | /** Create a matrix type. */ |
128 | | static std::unique_ptr<Type> MakeMatrixType(skstd::string_view name, const char* abbrev, |
129 | | const Type& componentType, int columns, |
130 | | int8_t rows); |
131 | | |
132 | | /** Create a sampler type. */ |
133 | | static std::unique_ptr<Type> MakeSamplerType(const char* name, const Type& textureType); |
134 | | |
135 | | /** Create a scalar type. */ |
136 | | static std::unique_ptr<Type> MakeScalarType(skstd::string_view name, const char* abbrev, |
137 | | Type::NumberKind numberKind, int8_t priority, |
138 | | int8_t bitWidth); |
139 | | |
140 | | /** |
141 | | * Create a "special" type with the given name, abbreviation, and TypeKind. |
142 | | */ |
143 | | static std::unique_ptr<Type> MakeSpecialType(const char* name, const char* abbrev, |
144 | | Type::TypeKind typeKind); |
145 | | |
146 | | /** Creates a struct type with the given fields. */ |
147 | | static std::unique_ptr<Type> MakeStructType(int offset, skstd::string_view name, |
148 | | std::vector<Field> fields); |
149 | | |
150 | | /** Create a texture type. */ |
151 | | static std::unique_ptr<Type> MakeTextureType(const char* name, SpvDim_ dimensions, |
152 | | bool isDepth, bool isArrayedTexture, |
153 | | bool isMultisampled, bool isSampled); |
154 | | |
155 | | /** Create a vector type. */ |
156 | | static std::unique_ptr<Type> MakeVectorType(skstd::string_view name, const char* abbrev, |
157 | | const Type& componentType, int columns); |
158 | | |
159 | | template <typename T> |
160 | 2.04M | bool is() const { |
161 | 2.04M | return this->typeKind() == T::kTypeKind; |
162 | 2.04M | } bool SkSL::Type::is<SkSL::ArrayType>() const Line | Count | Source | 160 | 34.2k | bool is() const { | 161 | 34.2k | return this->typeKind() == T::kTypeKind; | 162 | 34.2k | } |
bool SkSL::Type::is<SkSL::ScalarType>() const Line | Count | Source | 160 | 1.74M | bool is() const { | 161 | 1.74M | return this->typeKind() == T::kTypeKind; | 162 | 1.74M | } |
bool SkSL::Type::is<SkSL::TextureType>() const Line | Count | Source | 160 | 268k | bool is() const { | 161 | 268k | return this->typeKind() == T::kTypeKind; | 162 | 268k | } |
|
163 | | |
164 | | template <typename T> |
165 | 2.07M | const T& as() const { |
166 | 2.07M | SkASSERT(this->is<T>()); |
167 | 2.07M | return static_cast<const T&>(*this); |
168 | 2.07M | } SkSL::ScalarType const& SkSL::Type::as<SkSL::ScalarType>() const Line | Count | Source | 165 | 52.0k | const T& as() const { | 166 | 52.0k | SkASSERT(this->is<T>()); | 167 | 52.0k | return static_cast<const T&>(*this); | 168 | 52.0k | } |
SkSL::TextureType const& SkSL::Type::as<SkSL::TextureType>() const Line | Count | Source | 165 | 8.00k | const T& as() const { | 166 | 8.00k | SkASSERT(this->is<T>()); | 167 | 8.00k | return static_cast<const T&>(*this); | 168 | 8.00k | } |
SkSL::ScalarType const& SkSL::Type::as<SkSL::ScalarType>() const Line | Count | Source | 165 | 1.74M | const T& as() const { | 166 | 1.74M | SkASSERT(this->is<T>()); | 167 | 1.74M | return static_cast<const T&>(*this); | 168 | 1.74M | } |
SkSL::TextureType const& SkSL::Type::as<SkSL::TextureType>() const Line | Count | Source | 165 | 268k | const T& as() const { | 166 | 268k | SkASSERT(this->is<T>()); | 167 | 268k | return static_cast<const T&>(*this); | 168 | 268k | } |
|
169 | | |
170 | | template <typename T> |
171 | | T& as() { |
172 | | SkASSERT(this->is<T>()); |
173 | | return static_cast<T&>(*this); |
174 | | } |
175 | | |
176 | | /** Creates a clone of this Type, if needed, and inserts it into a different symbol table. */ |
177 | | const Type* clone(SymbolTable* symbolTable) const; |
178 | | |
179 | | /** |
180 | | * Returns true if this type is known to come from BuiltinTypes. If this returns true, the Type |
181 | | * will always be available in the root SymbolTable and never needs to be copied to migrate an |
182 | | * Expression from one location to another. If it returns false, the Type might not exist in a |
183 | | * separate SymbolTable and you'll need to consider copying it. |
184 | | */ |
185 | 789k | bool isInBuiltinTypes() const { |
186 | 789k | return !(this->isArray() || this->isStruct()); |
187 | 789k | } |
188 | | |
189 | 4.70M | String displayName() const { |
190 | 4.70M | return String(this->scalarTypeForLiteral().name()); |
191 | 4.70M | } |
192 | | |
193 | 8 | String description() const override { |
194 | 8 | return this->displayName(); |
195 | 8 | } |
196 | | |
197 | 418k | bool isPrivate() const { |
198 | 418k | return this->name().starts_with("$"); |
199 | 418k | } |
200 | | |
201 | 53.8k | virtual bool allowedInES2() const { |
202 | 53.8k | return true; |
203 | 53.8k | } |
204 | | |
205 | 53.0M | bool operator==(const Type& other) const { |
206 | 53.0M | return this->name() == other.name(); |
207 | 53.0M | } |
208 | | |
209 | 515k | bool operator!=(const Type& other) const { |
210 | 515k | return this->name() != other.name(); |
211 | 515k | } |
212 | | |
213 | | /** |
214 | | * Returns an abbreviated name of the type, meant for name-mangling. (e.g. float4x4 -> f44) |
215 | | */ |
216 | 165k | const char* abbreviatedName() const { |
217 | 165k | return fAbbreviatedName; |
218 | 165k | } |
219 | | |
220 | | /** |
221 | | * Returns the category (scalar, vector, matrix, etc.) of this type. |
222 | | */ |
223 | 47.8M | TypeKind typeKind() const { |
224 | 47.8M | return fTypeKind; |
225 | 47.8M | } |
226 | | |
227 | | /** |
228 | | * Returns the NumberKind of this type (always kNonnumeric for non-scalar values). |
229 | | */ |
230 | 931k | virtual NumberKind numberKind() const { |
231 | 931k | return NumberKind::kNonnumeric; |
232 | 931k | } |
233 | | |
234 | | /** |
235 | | * Returns true if this type is a bool. |
236 | | */ |
237 | 23.6M | bool isBoolean() const { |
238 | 23.6M | return this->numberKind() == NumberKind::kBoolean; |
239 | 23.6M | } |
240 | | |
241 | | /** |
242 | | * Returns true if this is a numeric scalar type. |
243 | | */ |
244 | 2.63M | bool isNumber() const { |
245 | 2.63M | switch (this->numberKind()) { |
246 | 1.17M | case NumberKind::kFloat: |
247 | 2.50M | case NumberKind::kSigned: |
248 | 2.52M | case NumberKind::kUnsigned: |
249 | 2.52M | return true; |
250 | 110k | default: |
251 | 110k | return false; |
252 | 2.63M | } |
253 | 2.63M | } |
254 | | |
255 | | /** |
256 | | * Returns true if this is a floating-point scalar type (float or half). |
257 | | */ |
258 | 4.23M | bool isFloat() const { |
259 | 4.23M | return this->numberKind() == NumberKind::kFloat; |
260 | 4.23M | } |
261 | | |
262 | | /** |
263 | | * Returns true if this is a signed scalar type (int or short). |
264 | | */ |
265 | 334k | bool isSigned() const { |
266 | 334k | return this->numberKind() == NumberKind::kSigned; |
267 | 334k | } |
268 | | |
269 | | /** |
270 | | * Returns true if this is an unsigned scalar type (uint or ushort). |
271 | | */ |
272 | 405k | bool isUnsigned() const { |
273 | 405k | return this->numberKind() == NumberKind::kUnsigned; |
274 | 405k | } |
275 | | |
276 | | /** |
277 | | * Returns true if this is a signed or unsigned integer. |
278 | | */ |
279 | 3.60M | bool isInteger() const { |
280 | 3.60M | switch (this->numberKind()) { |
281 | 2.16M | case NumberKind::kSigned: |
282 | 2.21M | case NumberKind::kUnsigned: |
283 | 2.21M | return true; |
284 | 1.39M | default: |
285 | 1.39M | return false; |
286 | 3.60M | } |
287 | 3.60M | } |
288 | | |
289 | | /** |
290 | | * Returns true if this is an "opaque type" (an external object which the shader references in |
291 | | * some fashion), or void. https://www.khronos.org/opengl/wiki/Data_Type_(GLSL)#Opaque_types |
292 | | */ |
293 | 2.78M | bool isOpaque() const { |
294 | 2.78M | switch (fTypeKind) { |
295 | 0 | case TypeKind::kBlender: |
296 | 1.09k | case TypeKind::kColorFilter: |
297 | 1.12k | case TypeKind::kOther: |
298 | 4.00k | case TypeKind::kSampler: |
299 | 16.4k | case TypeKind::kSeparateSampler: |
300 | 17.6k | case TypeKind::kShader: |
301 | 17.6k | case TypeKind::kTexture: |
302 | 22.0k | case TypeKind::kVoid: |
303 | 22.0k | return true; |
304 | 2.76M | default: |
305 | 2.76M | return false; |
306 | 2.78M | } |
307 | 2.78M | } |
308 | | |
309 | | /** |
310 | | * Returns the "priority" of a number type, in order of float > half > int > short. |
311 | | * When operating on two number types, the result is the higher-priority type. |
312 | | */ |
313 | 0 | virtual int priority() const { |
314 | 0 | SkDEBUGFAIL("not a number type"); |
315 | 0 | return -1; |
316 | 0 | } Unexecuted instantiation: SkSL::Type::priority() const Unexecuted instantiation: SkSL::Type::priority() const |
317 | | |
318 | | /** |
319 | | * Returns true if an instance of this type can be freely coerced (implicitly converted) to |
320 | | * another type. |
321 | | */ |
322 | 624k | bool canCoerceTo(const Type& other, bool allowNarrowing) const { |
323 | 624k | return this->coercionCost(other).isPossible(allowNarrowing); |
324 | 624k | } |
325 | | |
326 | | /** |
327 | | * Determines the "cost" of coercing (implicitly converting) this type to another type. The cost |
328 | | * is a number with no particular meaning other than that lower costs are preferable to higher |
329 | | * costs. Returns INT_MAX if the coercion is not possible. |
330 | | */ |
331 | | CoercionCost coercionCost(const Type& other) const; |
332 | | |
333 | | /** |
334 | | * For matrices and vectors, returns the type of individual cells (e.g. mat2 has a component |
335 | | * type of Float). For arrays, returns the base type. For all other types, returns the type |
336 | | * itself. |
337 | | */ |
338 | 23.2M | virtual const Type& componentType() const { |
339 | 23.2M | return *this; |
340 | 23.2M | } |
341 | | |
342 | | /** |
343 | | * For texturesamplers, returns the type of texture it samples (e.g., sampler2D has |
344 | | * a texture type of texture2D). |
345 | | */ |
346 | 0 | virtual const Type& textureType() const { |
347 | 0 | SkDEBUGFAIL("not a texture type"); |
348 | 0 | return *this; |
349 | 0 | } Unexecuted instantiation: SkSL::Type::textureType() const Unexecuted instantiation: SkSL::Type::textureType() const |
350 | | |
351 | | /** |
352 | | * For matrices and vectors, returns the number of columns (e.g. both mat3 and float3 return 3). |
353 | | * For scalars, returns 1. For arrays, returns either the size of the array (if known) or -1. |
354 | | * For all other types, causes an assertion failure. |
355 | | */ |
356 | 0 | virtual int columns() const { |
357 | 0 | SkDEBUGFAIL("type does not have columns"); |
358 | 0 | return -1; |
359 | 0 | } Unexecuted instantiation: SkSL::Type::columns() const Unexecuted instantiation: SkSL::Type::columns() const |
360 | | |
361 | | /** |
362 | | * For matrices, returns the number of rows (e.g. mat2x4 returns 4). For vectors and scalars, |
363 | | * returns 1. For all other types, causes an assertion failure. |
364 | | */ |
365 | 0 | virtual int rows() const { |
366 | 0 | SkDEBUGFAIL("type does not have rows"); |
367 | 0 | return -1; |
368 | 0 | } Unexecuted instantiation: SkSL::Type::rows() const Unexecuted instantiation: SkSL::Type::rows() const |
369 | | |
370 | | /** For integer types, returns the minimum value that can fit in the type. */ |
371 | 86.2k | int64_t minimumValue() const { |
372 | 86.2k | SkASSERT(this->isInteger()); |
373 | 86.2k | constexpr int64_t k1 = 1; // ensures that `1 << n` is evaluated as 64-bit |
374 | 82.9k | return this->isUnsigned() ? 0 : -(k1 << (this->bitWidth() - 1)); |
375 | 86.2k | } SkSL::Type::minimumValue() const Line | Count | Source | 371 | 8 | int64_t minimumValue() const { | 372 | 8 | SkASSERT(this->isInteger()); | 373 | 8 | constexpr int64_t k1 = 1; // ensures that `1 << n` is evaluated as 64-bit | 374 | 8 | return this->isUnsigned() ? 0 : -(k1 << (this->bitWidth() - 1)); | 375 | 8 | } |
SkSL::Type::minimumValue() const Line | Count | Source | 371 | 86.2k | int64_t minimumValue() const { | 372 | 86.2k | SkASSERT(this->isInteger()); | 373 | 86.2k | constexpr int64_t k1 = 1; // ensures that `1 << n` is evaluated as 64-bit | 374 | 82.9k | return this->isUnsigned() ? 0 : -(k1 << (this->bitWidth() - 1)); | 375 | 86.2k | } |
|
376 | | |
377 | | /** For integer types, returns the maximum value that can fit in the type. */ |
378 | 83.3k | int64_t maximumValue() const { |
379 | 83.3k | SkASSERT(this->isInteger()); |
380 | 83.3k | constexpr int64_t k1 = 1; // ensures that `1 << n` is evaluated as 64-bit |
381 | 1.77k | return (this->isUnsigned() ? (k1 << this->bitWidth()) |
382 | 81.6k | : (k1 << (this->bitWidth() - 1))) - 1; |
383 | 83.3k | } SkSL::Type::maximumValue() const Line | Count | Source | 378 | 8 | int64_t maximumValue() const { | 379 | 8 | SkASSERT(this->isInteger()); | 380 | 8 | constexpr int64_t k1 = 1; // ensures that `1 << n` is evaluated as 64-bit | 381 | 0 | return (this->isUnsigned() ? (k1 << this->bitWidth()) | 382 | 8 | : (k1 << (this->bitWidth() - 1))) - 1; | 383 | 8 | } |
SkSL::Type::maximumValue() const Line | Count | Source | 378 | 83.3k | int64_t maximumValue() const { | 379 | 83.3k | SkASSERT(this->isInteger()); | 380 | 83.3k | constexpr int64_t k1 = 1; // ensures that `1 << n` is evaluated as 64-bit | 381 | 1.77k | return (this->isUnsigned() ? (k1 << this->bitWidth()) | 382 | 81.6k | : (k1 << (this->bitWidth() - 1))) - 1; | 383 | 83.3k | } |
|
384 | | |
385 | | /** |
386 | | * Returns the number of scalars needed to hold this type. |
387 | | */ |
388 | 37.4M | size_t slotCount() const { |
389 | 37.4M | switch (this->typeKind()) { |
390 | 0 | case Type::TypeKind::kBlender: |
391 | 0 | case Type::TypeKind::kColorFilter: |
392 | 0 | case Type::TypeKind::kGeneric: |
393 | 0 | case Type::TypeKind::kOther: |
394 | 0 | case Type::TypeKind::kSampler: |
395 | 0 | case Type::TypeKind::kSeparateSampler: |
396 | 0 | case Type::TypeKind::kShader: |
397 | 0 | case Type::TypeKind::kTexture: |
398 | 0 | case Type::TypeKind::kVoid: |
399 | 0 | return 0; |
400 | |
|
401 | 429k | case Type::TypeKind::kLiteral: |
402 | 26.5M | case Type::TypeKind::kScalar: |
403 | 26.5M | return 1; |
404 | | |
405 | 10.9M | case Type::TypeKind::kVector: |
406 | 10.9M | return this->columns(); |
407 | | |
408 | 73.3k | case Type::TypeKind::kMatrix: |
409 | 73.3k | return this->columns() * this->rows(); |
410 | | |
411 | 0 | case Type::TypeKind::kStruct: { |
412 | 0 | size_t slots = 0; |
413 | 0 | for (const Field& field : this->fields()) { |
414 | 0 | slots += field.fType->slotCount(); |
415 | 0 | } |
416 | 0 | return slots; |
417 | 429k | } |
418 | 1.30k | case Type::TypeKind::kArray: |
419 | 1.30k | SkASSERT(this->columns() > 0); |
420 | 1.30k | return this->columns() * this->componentType().slotCount(); |
421 | 0 | } |
422 | 0 | SkUNREACHABLE; |
423 | 0 | } SkSL::Type::slotCount() const Line | Count | Source | 388 | 4.91M | size_t slotCount() const { | 389 | 4.91M | switch (this->typeKind()) { | 390 | 0 | case Type::TypeKind::kBlender: | 391 | 0 | case Type::TypeKind::kColorFilter: | 392 | 0 | case Type::TypeKind::kGeneric: | 393 | 0 | case Type::TypeKind::kOther: | 394 | 0 | case Type::TypeKind::kSampler: | 395 | 0 | case Type::TypeKind::kSeparateSampler: | 396 | 0 | case Type::TypeKind::kShader: | 397 | 0 | case Type::TypeKind::kTexture: | 398 | 0 | case Type::TypeKind::kVoid: | 399 | 0 | return 0; | 400 | |
| 401 | 48 | case Type::TypeKind::kLiteral: | 402 | 2.26M | case Type::TypeKind::kScalar: | 403 | 2.26M | return 1; | 404 | | | 405 | 2.64M | case Type::TypeKind::kVector: | 406 | 2.64M | return this->columns(); | 407 | | | 408 | 3 | case Type::TypeKind::kMatrix: | 409 | 3 | return this->columns() * this->rows(); | 410 | | | 411 | 0 | case Type::TypeKind::kStruct: { | 412 | 0 | size_t slots = 0; | 413 | 0 | for (const Field& field : this->fields()) { | 414 | 0 | slots += field.fType->slotCount(); | 415 | 0 | } | 416 | 0 | return slots; | 417 | 48 | } | 418 | 0 | case Type::TypeKind::kArray: | 419 | 0 | SkASSERT(this->columns() > 0); | 420 | 0 | return this->columns() * this->componentType().slotCount(); | 421 | 0 | } | 422 | 0 | SkUNREACHABLE; | 423 | 0 | } |
SkSL::Type::slotCount() const Line | Count | Source | 388 | 32.5M | size_t slotCount() const { | 389 | 32.5M | switch (this->typeKind()) { | 390 | 0 | case Type::TypeKind::kBlender: | 391 | 0 | case Type::TypeKind::kColorFilter: | 392 | 0 | case Type::TypeKind::kGeneric: | 393 | 0 | case Type::TypeKind::kOther: | 394 | 0 | case Type::TypeKind::kSampler: | 395 | 0 | case Type::TypeKind::kSeparateSampler: | 396 | 0 | case Type::TypeKind::kShader: | 397 | 0 | case Type::TypeKind::kTexture: | 398 | 0 | case Type::TypeKind::kVoid: | 399 | 0 | return 0; | 400 | |
| 401 | 429k | case Type::TypeKind::kLiteral: | 402 | 24.2M | case Type::TypeKind::kScalar: | 403 | 24.2M | return 1; | 404 | | | 405 | 8.26M | case Type::TypeKind::kVector: | 406 | 8.26M | return this->columns(); | 407 | | | 408 | 73.3k | case Type::TypeKind::kMatrix: | 409 | 73.3k | return this->columns() * this->rows(); | 410 | | | 411 | 0 | case Type::TypeKind::kStruct: { | 412 | 0 | size_t slots = 0; | 413 | 0 | for (const Field& field : this->fields()) { | 414 | 0 | slots += field.fType->slotCount(); | 415 | 0 | } | 416 | 0 | return slots; | 417 | 429k | } | 418 | 1.30k | case Type::TypeKind::kArray: | 419 | 1.30k | SkASSERT(this->columns() > 0); | 420 | 1.30k | return this->columns() * this->componentType().slotCount(); | 421 | 0 | } | 422 | 0 | SkUNREACHABLE; | 423 | 0 | } |
|
424 | | |
425 | 0 | virtual const std::vector<Field>& fields() const { |
426 | 0 | SK_ABORT("Internal error: not a struct"); |
427 | 0 | } |
428 | | |
429 | | /** |
430 | | * For generic types, returns the types that this generic type can substitute for. |
431 | | */ |
432 | 0 | virtual const std::vector<const Type*>& coercibleTypes() const { |
433 | 0 | SK_ABORT("Internal error: not a generic type"); |
434 | 0 | } |
435 | | |
436 | 0 | virtual SpvDim_ dimensions() const { |
437 | 0 | SkASSERT(false); |
438 | 0 | return SpvDim1D; |
439 | 0 | } Unexecuted instantiation: SkSL::Type::dimensions() const Unexecuted instantiation: SkSL::Type::dimensions() const |
440 | | |
441 | 0 | virtual bool isDepth() const { |
442 | 0 | SkASSERT(false); |
443 | 0 | return false; |
444 | 0 | } Unexecuted instantiation: SkSL::Type::isDepth() const Unexecuted instantiation: SkSL::Type::isDepth() const |
445 | | |
446 | 0 | virtual bool isArrayedTexture() const { |
447 | 0 | SkASSERT(false); |
448 | 0 | return false; |
449 | 0 | } Unexecuted instantiation: SkSL::Type::isArrayedTexture() const Unexecuted instantiation: SkSL::Type::isArrayedTexture() const |
450 | | |
451 | 654k | bool isVoid() const { |
452 | 654k | return fTypeKind == TypeKind::kVoid; |
453 | 654k | } |
454 | | |
455 | 22.1M | virtual bool isScalar() const { |
456 | 22.1M | return false; |
457 | 22.1M | } |
458 | | |
459 | 338k | virtual bool isLiteral() const { |
460 | 338k | return false; |
461 | 338k | } |
462 | | |
463 | 5.24M | virtual const Type& scalarTypeForLiteral() const { |
464 | 5.24M | return *this; |
465 | 5.24M | } |
466 | | |
467 | 25.8M | virtual bool isVector() const { |
468 | 25.8M | return false; |
469 | 25.8M | } |
470 | | |
471 | 31.0M | virtual bool isMatrix() const { |
472 | 31.0M | return false; |
473 | 31.0M | } |
474 | | |
475 | 4.55M | virtual bool isArray() const { |
476 | 4.55M | return false; |
477 | 4.55M | } |
478 | | |
479 | 2.61M | virtual bool isStruct() const { |
480 | 2.61M | return false; |
481 | 2.61M | } |
482 | | |
483 | | // Is this type something that can be bound & sampled from an SkRuntimeEffect? |
484 | | // Includes types that represent stages of the Skia pipeline (colorFilter, shader, blender). |
485 | 304k | bool isEffectChild() const { |
486 | 304k | return fTypeKind == TypeKind::kColorFilter || |
487 | 303k | fTypeKind == TypeKind::kShader || |
488 | 302k | fTypeKind == TypeKind::kBlender; |
489 | 304k | } |
490 | | |
491 | 0 | virtual bool isMultisampled() const { |
492 | 0 | SkASSERT(false); |
493 | 0 | return false; |
494 | 0 | } Unexecuted instantiation: SkSL::Type::isMultisampled() const Unexecuted instantiation: SkSL::Type::isMultisampled() const |
495 | | |
496 | 0 | virtual bool isSampled() const { |
497 | 0 | SkASSERT(false); |
498 | 0 | return false; |
499 | 0 | } Unexecuted instantiation: SkSL::Type::isSampled() const Unexecuted instantiation: SkSL::Type::isSampled() const |
500 | | |
501 | 198k | bool hasPrecision() const { |
502 | 198k | return this->componentType().isNumber() || fTypeKind == TypeKind::kSampler; |
503 | 198k | } |
504 | | |
505 | 10.4M | bool highPrecision() const { |
506 | 10.4M | return this->bitWidth() >= 32; |
507 | 10.4M | } |
508 | | |
509 | 11.2k | virtual int bitWidth() const { |
510 | 11.2k | return 0; |
511 | 11.2k | } |
512 | | |
513 | | bool isOrContainsArray() const; |
514 | | |
515 | | /** |
516 | | * Returns the corresponding vector or matrix type with the specified number of columns and |
517 | | * rows. |
518 | | */ |
519 | | const Type& toCompound(const Context& context, int columns, int rows) const; |
520 | | |
521 | | /** |
522 | | * Returns a type which honors the precision qualifiers set in Modifiers. e.g., kMediump_Flag |
523 | | * when applied to `float2` will return `half2`. Generates an error if the precision qualifiers |
524 | | * don't make sense, e.g. `highp bool` or `mediump MyStruct`. |
525 | | */ |
526 | | const Type* applyPrecisionQualifiers(const Context& context, |
527 | | const Modifiers& modifiers, |
528 | | SymbolTable* symbols, |
529 | | int offset) const; |
530 | | |
531 | | /** |
532 | | * Coerces the passed-in expression to this type. If the types are incompatible, reports an |
533 | | * error and returns null. |
534 | | */ |
535 | | std::unique_ptr<Expression> coerceExpression(std::unique_ptr<Expression> expr, |
536 | | const Context& context) const; |
537 | | |
538 | | /** Detects any IntLiterals in the expression which can't fit in this type. */ |
539 | | bool checkForOutOfRangeLiteral(const Context& context, const Expression& expr) const; |
540 | | |
541 | | protected: |
542 | | Type(skstd::string_view name, const char* abbrev, TypeKind kind, int offset = -1) |
543 | | : INHERITED(offset, kSymbolKind, name) |
544 | 4.07M | , fTypeKind(kind) { |
545 | 4.07M | SkASSERT(strlen(abbrev) <= kMaxAbbrevLength); |
546 | 4.07M | strcpy(fAbbreviatedName, abbrev); |
547 | 4.07M | } SkSL::Type::Type(skstd::string_view, char const*, SkSL::Type::TypeKind, int) Line | Count | Source | 544 | 116k | , fTypeKind(kind) { | 545 | 116k | SkASSERT(strlen(abbrev) <= kMaxAbbrevLength); | 546 | 116k | strcpy(fAbbreviatedName, abbrev); | 547 | 116k | } |
SkSL::Type::Type(skstd::string_view, char const*, SkSL::Type::TypeKind, int) Line | Count | Source | 544 | 3.95M | , fTypeKind(kind) { | 545 | 3.95M | SkASSERT(strlen(abbrev) <= kMaxAbbrevLength); | 546 | 3.95M | strcpy(fAbbreviatedName, abbrev); | 547 | 3.95M | } |
|
548 | | |
549 | | private: |
550 | | friend class BuiltinTypes; |
551 | | |
552 | | using INHERITED = Symbol; |
553 | | |
554 | | char fAbbreviatedName[kMaxAbbrevLength + 1] = {}; |
555 | | TypeKind fTypeKind; |
556 | | }; |
557 | | |
558 | | } // namespace SkSL |
559 | | |
560 | | #endif |