OLD | NEW |
---|---|
(Empty) | |
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 /** | |
22 * Represents a type, such as int or vec4. | |
23 */ | |
24 class Type : public Symbol { | |
25 public: | |
26 struct Field { | |
27 Field(Modifiers modifiers, std::string name, std::shared_ptr<Type> type) | |
28 : fModifiers(modifiers) | |
29 , fName(std::move(name)) | |
30 , fType(std::move(type)) {} | |
31 | |
32 const std::string description() { | |
33 return fType->description() + " " + fName + ";"; | |
34 } | |
35 | |
36 const Modifiers fModifiers; | |
37 const std::string fName; | |
38 const std::shared_ptr<Type> fType; | |
39 }; | |
40 | |
41 enum Kind { | |
42 kScalar_Kind, | |
43 kVector_Kind, | |
44 kMatrix_Kind, | |
45 kArray_Kind, | |
46 kStruct_Kind, | |
47 kGeneric_Kind, | |
48 kSampler_Kind, | |
49 kOther_Kind | |
50 }; | |
51 | |
52 // Create an "other" (special) type with the given name. These types cannot be directly | |
53 // referenced from user code. | |
54 Type(std::string name) | |
55 : INHERITED(Position(), kType_Kind, std::move(name)) | |
56 , fTypeKind(kOther_Kind) | |
57 , fIsNumber(false) | |
dogben
2016/06/28 02:14:55
nit: Given that there are so many constructors and
ethannicholas
2016/06/30 15:19:28
Last time I did that the reviewer told me not to u
dogben
2016/06/30 18:19:44
It hasn't been fully supported until recently. I'm
| |
58 , fColumns(-1) | |
59 , fRows(-1) | |
60 , fDimensions(SpvDim1D) | |
61 , fIsDepth(false) | |
62 , fIsArrayed(false) | |
63 , fIsMultisampled(false) | |
64 , fIsSampled(false) {} | |
65 | |
66 // Create a generic type which maps to the listed types. | |
67 Type(std::string name, std::vector<std::shared_ptr<Type>> types) | |
68 : INHERITED(Position(), kType_Kind, std::move(name)) | |
69 , fTypeKind(kGeneric_Kind) | |
70 , fIsNumber(false) | |
71 , fCoercibleTypes(std::move(types)) | |
72 , fColumns(-1) | |
73 , fRows(-1) | |
74 , fDimensions(SpvDim1D) | |
75 , fIsDepth(false) | |
76 , fIsArrayed(false) | |
77 , fIsMultisampled(false) | |
78 , fIsSampled(false) { | |
79 ASSERT(fCoercibleTypes.size() == 4); | |
80 } | |
81 | |
82 // Create a struct type with the given fields. | |
83 Type(std::string name, std::vector<Field> fields) | |
84 : INHERITED(Position(), kType_Kind, std::move(name)) | |
85 , fTypeKind(kStruct_Kind) | |
86 , fIsNumber(false) | |
87 , fColumns(-1) | |
88 , fRows(-1) | |
89 , fFields(std::move(fields)) | |
90 , fDimensions(SpvDim1D) | |
91 , fIsDepth(false) | |
92 , fIsArrayed(false) | |
93 , fIsMultisampled(false) | |
94 , fIsSampled(false) {} | |
95 | |
96 // Create a scalar type. | |
97 Type(std::string name, bool isNumber) | |
98 : INHERITED(Position(), kType_Kind, std::move(name)) | |
99 , fTypeKind(kScalar_Kind) | |
100 , fIsNumber(isNumber) | |
101 , fColumns(1) | |
102 , fRows(1) | |
103 , fDimensions(SpvDim1D) | |
104 , fIsDepth(false) | |
105 , fIsArrayed(false) | |
106 , fIsMultisampled(false) | |
107 , fIsSampled(false) {} | |
108 | |
109 // Create a scalar type which can be coerced to the listed types. | |
110 Type(std::string name, bool isNumber, std::vector<std::shared_ptr<Type>> coe rcibleTypes) | |
111 : INHERITED(Position(), kType_Kind, std::move(name)) | |
112 , fTypeKind(kScalar_Kind) | |
113 , fIsNumber(isNumber) | |
114 , fCoercibleTypes(std::move(coercibleTypes)) | |
115 , fColumns(1) | |
116 , fRows(1) | |
117 , fDimensions(SpvDim1D) | |
118 , fIsDepth(false) | |
119 , fIsArrayed(false) | |
120 , fIsMultisampled(false) | |
121 , fIsSampled(false) {} | |
122 | |
123 // Create a vector type. | |
124 Type(std::string name, std::shared_ptr<Type> componentType, int columns) | |
125 : INHERITED(Position(), kType_Kind, std::move(name)) | |
dogben
2016/06/28 02:14:55
nit: maybe delegate to next constructor?
| |
126 , fTypeKind(kVector_Kind) | |
127 , fIsNumber(false) | |
128 , fComponentType(std::move(componentType)) | |
129 , fColumns(columns) | |
130 , fRows(1) | |
131 , fDimensions(SpvDim1D) | |
132 , fIsDepth(false) | |
133 , fIsArrayed(false) | |
134 , fIsMultisampled(false) | |
135 , fIsSampled(false) {} | |
136 | |
137 // Create a vector or array type. | |
138 Type(std::string name, Kind kind, std::shared_ptr<Type> componentType, int c olumns) | |
139 : INHERITED(Position(), kType_Kind, std::move(name)) | |
140 , fTypeKind(kind) | |
141 , fIsNumber(false) | |
142 , fComponentType(std::move(componentType)) | |
143 , fColumns(columns) | |
144 , fRows(1) | |
145 , fDimensions(SpvDim1D) | |
146 , fIsDepth(false) | |
147 , fIsArrayed(false) | |
148 , fIsMultisampled(false) | |
149 , fIsSampled(false) {} | |
150 | |
151 // Create a matrix type. | |
152 Type(std::string name, std::shared_ptr<Type> componentType, int columns, int rows) | |
153 : INHERITED(Position(), kType_Kind, std::move(name)) | |
154 , fTypeKind(kMatrix_Kind) | |
155 , fIsNumber(false) | |
156 , fComponentType(std::move(componentType)) | |
157 , fColumns(columns) | |
158 , fRows(rows) | |
159 , fDimensions(SpvDim1D) | |
160 , fIsDepth(false) | |
161 , fIsArrayed(false) | |
162 , fIsMultisampled(false) | |
163 , fIsSampled(false) {} | |
164 | |
165 // Create a sampler type. | |
166 Type(std::string name, SpvDim_ dimensions, bool isDepth, bool isArrayed, boo l isMultisampled, | |
167 bool isSampled) | |
168 : INHERITED(Position(), kType_Kind, std::move(name)) | |
169 , fTypeKind(kSampler_Kind) | |
170 , fIsNumber(false) | |
171 , fColumns(-1) | |
172 , fRows(-1) | |
173 , fDimensions(dimensions) | |
174 , fIsDepth(isDepth) | |
175 , fIsArrayed(isArrayed) | |
176 , fIsMultisampled(isMultisampled) | |
177 , fIsSampled(isSampled) {} | |
178 | |
179 std::string name() const { | |
180 return fName; | |
181 } | |
182 | |
183 std::string description() const override { | |
184 return fName; | |
185 } | |
186 | |
187 bool operator==(const Type& other) const { | |
188 return fName == other.fName; | |
189 } | |
190 | |
191 bool operator!=(const Type& other) const { | |
192 return fName != other.fName; | |
193 } | |
194 | |
195 /** | |
196 * Returns the category (scalar, vector, matrix, etc.) of this type. | |
197 */ | |
198 Kind kind() const { | |
199 return fTypeKind; | |
200 } | |
201 | |
202 /** | |
203 * Returns true if this is a numeric scalar type. | |
204 */ | |
205 bool isNumber() const { | |
206 return fIsNumber; | |
207 } | |
208 | |
209 /** | |
210 * Returns true if an instance of this type can be freely coerced (implicitl y converted) to | |
211 * another type. | |
212 */ | |
213 bool canCoerceTo(std::shared_ptr<Type> other) const { | |
214 int cost; | |
215 return determineCoercionCost(other, &cost); | |
216 } | |
217 | |
218 /** | |
219 * Determines the "cost" of coercing (implicitly converting) this type to an other type. The cost | |
220 * is a number with no particular meaning other than that lower costs are pr eferable to higher | |
221 * costs. Returns true if a conversion is possible, false otherwise. The val ue of the out | |
222 * parameter is undefined if false is returned. | |
223 */ | |
224 bool determineCoercionCost(std::shared_ptr<Type> other, int* outCost) const; | |
225 | |
226 /** | |
227 * For matrices and vectors, returns the type of individual cells (e.g. mat2 has a component | |
228 * type of kFloat_Type). For all other types, causes an assertion failure. | |
229 */ | |
230 std::shared_ptr<Type> componentType() const { | |
231 ASSERT(fComponentType); | |
232 return fComponentType; | |
233 } | |
234 | |
235 /** | |
236 * For matrices and vectors, returns the number of columns (e.g. both mat3 a nd vec3 return 3). | |
237 * For scalars, returns 1. For arrays, returns either the size of the array (if known) or -1. | |
238 * For all other types, causes an assertion failure. | |
239 */ | |
240 int columns() const { | |
241 ASSERT(fTypeKind == kScalar_Kind || fTypeKind == kVector_Kind || | |
242 fTypeKind == kMatrix_Kind || fTypeKind == kArray_Kind); | |
243 return fColumns; | |
244 } | |
245 | |
246 /** | |
247 * For matrices, returns the number of rows (e.g. mat2x4 returns 4). For vec tors and scalars, | |
248 * returns 1. For all other types, causes an assertion failure. | |
249 */ | |
250 int rows() const { | |
251 ASSERT(fRows > 0); | |
252 return fRows; | |
253 } | |
254 | |
255 std::vector<Field> fields() const { | |
256 ASSERT(fTypeKind == kStruct_Kind); | |
257 return fFields; | |
258 } | |
259 | |
260 /** | |
261 * For generic types, returns the types that this generic type can substitut e for. For other | |
262 * types, returns a list of other types that this type can be coerced into. | |
263 */ | |
264 std::vector<std::shared_ptr<Type>> coercibleTypes() const { | |
265 ASSERT(fCoercibleTypes.size() > 0); | |
266 return fCoercibleTypes; | |
267 } | |
268 | |
269 int dimensions() const { | |
270 ASSERT(fTypeKind == kSampler_Kind); | |
271 return fDimensions; | |
272 } | |
273 | |
274 bool isDepth() const { | |
275 ASSERT(fTypeKind == kSampler_Kind); | |
276 return fIsDepth; | |
277 } | |
278 | |
279 bool isArrayed() const { | |
280 ASSERT(fTypeKind == kSampler_Kind); | |
281 return fIsArrayed; | |
282 } | |
283 | |
284 bool isMultisampled() const { | |
285 ASSERT(fTypeKind == kSampler_Kind); | |
286 return fIsMultisampled; | |
287 } | |
288 | |
289 bool isSampled() const { | |
290 ASSERT(fTypeKind == kSampler_Kind); | |
291 return fIsSampled; | |
292 } | |
293 | |
294 /** | |
295 * Returns the type's required alignment (when putting this type into a stru ct, the offset must | |
296 * be a multiple of the alignment). | |
297 */ | |
298 size_t alignment() const { | |
299 // See OpenGL Spec 7.6.2.2 Standard Uniform Block Layout | |
300 switch (fTypeKind) { | |
301 case kScalar_Kind: | |
302 return this->size(); | |
303 case kVector_Kind: | |
304 return (fColumns + fColumns % 2) * fComponentType->size(); | |
305 case kMatrix_Kind: | |
306 return (fRows + fRows % 2) * fComponentType->size(); | |
egdaniel
2016/06/28 15:53:32
This seems wrong. A column matrix should be though
| |
307 case kArray_Kind: | |
308 switch (fComponentType->kind()) { | |
309 case kScalar_Kind: | |
310 return fComponentType->alignment() * 4; | |
egdaniel
2016/06/28 15:53:32
This should be the base alignment of the scalar ro
ethannicholas
2016/06/30 15:19:28
I based mine on the OpenGL spec, which says "round
| |
311 case kVector_Kind: | |
312 return fComponentType->componentType()->size() * 4; | |
egdaniel
2016/06/28 15:53:31
same need for asserts as above
| |
313 case kStruct_Kind: | |
314 return fComponentType->alignment(); | |
315 default: | |
316 ABORT("unsupported array type"); | |
317 } | |
318 case kStruct_Kind: { | |
319 size_t result = 16; | |
320 for (size_t i = 0; i < fFields.size(); i++) { | |
321 size_t alignment = fFields[i].fType->alignment(); | |
322 if (alignment > result) { | |
323 result = alignment; | |
324 } | |
325 } | |
326 } | |
327 default: | |
328 ABORT(("cannot determine size of type " + fName).c_str()); | |
329 } | |
330 } | |
331 | |
332 /** | |
333 * For matrices and arrays, returns the number of bytes from the start of on e entry (row, in | |
334 * the case of matrices) to the start of the next. | |
335 */ | |
336 size_t stride() const { | |
337 // the OpenGL spec specifies a minimum of vec4 stride for these types, w hich is consistent | |
338 // with what glslang produces. Since the Skia Vulkan engine sets up its structures to fit | |
339 // with what glslang expects, we have no choice but to be consistent wit h that, which leads | |
340 // to wasting 75% of the space in a float[]. However, it's possible that (for arrays, at | |
341 // least) there is no actual reason to require a stride of 16, provided that both the shader | |
egdaniel
2016/06/28 15:53:32
This is actually all required by the Vulkan spec e
| |
342 // and Skia agree on the stride. | |
343 // FIXME: see whether we can remove the restriction on array stride | |
344 switch (fTypeKind) { | |
345 case kMatrix_Kind: | |
346 // for the time being, we only handle 32 bit numbers | |
egdaniel
2016/06/28 15:53:32
is this asserted somewhere?
| |
347 return 16; | |
348 case kArray_Kind: | |
349 return std::max(this->componentType()->size(), (size_t) 16); | |
egdaniel
2016/06/28 15:53:32
If we are trying to match the vulkan spec here, th
| |
350 default: | |
351 ABORT("type does not have a stride"); | |
352 } | |
353 } | |
354 | |
355 /** | |
356 * Returns the size of this type in bytes. | |
357 */ | |
358 size_t size() const { | |
359 switch (fTypeKind) { | |
360 case kScalar_Kind: | |
361 // FIXME need to take precision into account, once we figure out how we want to | |
362 // handle it... | |
363 return 4; | |
364 case kVector_Kind: | |
365 return fColumns * fComponentType->size(); | |
egdaniel
2016/06/28 15:53:31
does a vec3 not have a size of a vec4?
ethannicholas
2016/06/30 15:19:28
No. It has the *alignment* of a vec4, but not the
| |
366 case kMatrix_Kind: | |
367 return (fRows + fRows % 2) * fColumns * fComponentType->size(); | |
368 case kArray_Kind: | |
369 return fColumns * this->alignment(); | |
370 case kStruct_Kind: { | |
371 size_t total = 0; | |
372 for (size_t i = 0; i < fFields.size(); i++) { | |
373 size_t alignment = fFields[i].fType->alignment(); | |
374 if (total % alignment != 0) { | |
375 total += alignment - total % alignment; | |
376 } | |
377 ASSERT(false); | |
378 ASSERT(total % alignment == 0); | |
379 total += fFields[i].fType->size(); | |
380 } | |
381 return total; | |
382 } | |
383 default: | |
384 ABORT(("cannot determine size of type " + fName).c_str()); | |
385 } | |
386 } | |
387 | |
388 /** | |
389 * Returns the corresponding vector or matrix type with the specified number of columns and | |
390 * rows. | |
391 */ | |
392 std::shared_ptr<Type> toCompound(int columns, int rows); | |
393 | |
394 private: | |
395 typedef Symbol INHERITED; | |
396 | |
397 const Kind fTypeKind; | |
398 const bool fIsNumber; | |
399 const std::shared_ptr<Type> fComponentType; | |
400 const std::vector<std::shared_ptr<Type>> fCoercibleTypes; | |
401 const int fColumns; | |
402 const int fRows; | |
403 const std::vector<Field> fFields; | |
404 const SpvDim_ fDimensions; | |
405 const bool fIsDepth; | |
406 const bool fIsArrayed; | |
407 const bool fIsMultisampled; | |
408 const bool fIsSampled; | |
409 }; | |
410 | |
411 extern const std::shared_ptr<Type> kVoid_Type; | |
412 | |
413 extern const std::shared_ptr<Type> kFloat_Type; | |
414 extern const std::shared_ptr<Type> kVec2_Type; | |
415 extern const std::shared_ptr<Type> kVec3_Type; | |
416 extern const std::shared_ptr<Type> kVec4_Type; | |
417 extern const std::shared_ptr<Type> kDouble_Type; | |
418 extern const std::shared_ptr<Type> kDVec2_Type; | |
419 extern const std::shared_ptr<Type> kDVec3_Type; | |
420 extern const std::shared_ptr<Type> kDVec4_Type; | |
421 extern const std::shared_ptr<Type> kInt_Type; | |
422 extern const std::shared_ptr<Type> kIVec2_Type; | |
423 extern const std::shared_ptr<Type> kIVec3_Type; | |
424 extern const std::shared_ptr<Type> kIVec4_Type; | |
425 extern const std::shared_ptr<Type> kUInt_Type; | |
426 extern const std::shared_ptr<Type> kUVec2_Type; | |
427 extern const std::shared_ptr<Type> kUVec3_Type; | |
428 extern const std::shared_ptr<Type> kUVec4_Type; | |
429 extern const std::shared_ptr<Type> kBool_Type; | |
430 extern const std::shared_ptr<Type> kBVec2_Type; | |
431 extern const std::shared_ptr<Type> kBVec3_Type; | |
432 extern const std::shared_ptr<Type> kBVec4_Type; | |
433 | |
434 extern const std::shared_ptr<Type> kMat2x2_Type; | |
435 extern const std::shared_ptr<Type> kMat2x3_Type; | |
436 extern const std::shared_ptr<Type> kMat2x4_Type; | |
437 extern const std::shared_ptr<Type> kMat3x2_Type; | |
438 extern const std::shared_ptr<Type> kMat3x3_Type; | |
439 extern const std::shared_ptr<Type> kMat3x4_Type; | |
440 extern const std::shared_ptr<Type> kMat4x2_Type; | |
441 extern const std::shared_ptr<Type> kMat4x3_Type; | |
442 extern const std::shared_ptr<Type> kMat4x4_Type; | |
443 | |
444 extern const std::shared_ptr<Type> kDMat2x2_Type; | |
445 extern const std::shared_ptr<Type> kDMat2x3_Type; | |
446 extern const std::shared_ptr<Type> kDMat2x4_Type; | |
447 extern const std::shared_ptr<Type> kDMat3x2_Type; | |
448 extern const std::shared_ptr<Type> kDMat3x3_Type; | |
449 extern const std::shared_ptr<Type> kDMat3x4_Type; | |
450 extern const std::shared_ptr<Type> kDMat4x2_Type; | |
451 extern const std::shared_ptr<Type> kDMat4x3_Type; | |
452 extern const std::shared_ptr<Type> kDMat4x4_Type; | |
453 | |
454 extern const std::shared_ptr<Type> kSampler1D_Type; | |
455 extern const std::shared_ptr<Type> kSampler2D_Type; | |
456 extern const std::shared_ptr<Type> kSampler3D_Type; | |
457 extern const std::shared_ptr<Type> kSamplerCube_Type; | |
458 extern const std::shared_ptr<Type> kSampler2DRect_Type; | |
459 extern const std::shared_ptr<Type> kSampler1DArray_Type; | |
460 extern const std::shared_ptr<Type> kSampler2DArray_Type; | |
461 extern const std::shared_ptr<Type> kSamplerCubeArray_Type; | |
462 extern const std::shared_ptr<Type> kSamplerBuffer_Type; | |
463 extern const std::shared_ptr<Type> kSampler2DMS_Type; | |
464 extern const std::shared_ptr<Type> kSampler2DMSArray_Type; | |
465 | |
466 extern const std::shared_ptr<Type> kGSampler1D_Type; | |
467 extern const std::shared_ptr<Type> kGSampler2D_Type; | |
468 extern const std::shared_ptr<Type> kGSampler3D_Type; | |
469 extern const std::shared_ptr<Type> kGSamplerCube_Type; | |
470 extern const std::shared_ptr<Type> kGSampler2DRect_Type; | |
471 extern const std::shared_ptr<Type> kGSampler1DArray_Type; | |
472 extern const std::shared_ptr<Type> kGSampler2DArray_Type; | |
473 extern const std::shared_ptr<Type> kGSamplerCubeArray_Type; | |
474 extern const std::shared_ptr<Type> kGSamplerBuffer_Type; | |
475 extern const std::shared_ptr<Type> kGSampler2DMS_Type; | |
476 extern const std::shared_ptr<Type> kGSampler2DMSArray_Type; | |
477 | |
478 extern const std::shared_ptr<Type> kSampler1DShadow_Type; | |
479 extern const std::shared_ptr<Type> kSampler2DShadow_Type; | |
480 extern const std::shared_ptr<Type> kSamplerCubeShadow_Type; | |
481 extern const std::shared_ptr<Type> kSampler2DRectShadow_Type; | |
482 extern const std::shared_ptr<Type> kSampler1DArrayShadow_Type; | |
483 extern const std::shared_ptr<Type> kSampler2DArrayShadow_Type; | |
484 extern const std::shared_ptr<Type> kSamplerCubeArrayShadow_Type; | |
485 extern const std::shared_ptr<Type> kGSampler2DArrayShadow_Type; | |
486 extern const std::shared_ptr<Type> kGSamplerCubeArrayShadow_Type; | |
487 | |
488 extern const std::shared_ptr<Type> kGenType_Type; | |
489 extern const std::shared_ptr<Type> kGenDType_Type; | |
490 extern const std::shared_ptr<Type> kGenIType_Type; | |
491 extern const std::shared_ptr<Type> kGenUType_Type; | |
492 extern const std::shared_ptr<Type> kGenBType_Type; | |
493 extern const std::shared_ptr<Type> kMat_Type; | |
494 extern const std::shared_ptr<Type> kVec_Type; | |
495 extern const std::shared_ptr<Type> kGVec_Type; | |
496 extern const std::shared_ptr<Type> kGVec2_Type; | |
497 extern const std::shared_ptr<Type> kGVec3_Type; | |
498 extern const std::shared_ptr<Type> kGVec4_Type; | |
499 extern const std::shared_ptr<Type> kDVec_Type; | |
500 extern const std::shared_ptr<Type> kIVec_Type; | |
501 extern const std::shared_ptr<Type> kUVec_Type; | |
502 extern const std::shared_ptr<Type> kBVec_Type; | |
503 | |
504 extern const std::shared_ptr<Type> kInvalid_Type; | |
505 | |
506 } // namespace | |
507 | |
508 #endif | |
OLD | NEW |