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_MEMORYLAYOUT | |
9 #define SKIASL_MEMORYLAYOUT | |
10 | |
11 #include "ir/SkSLType.h" | |
12 | |
13 namespace SkSL { | |
14 | |
15 class MemoryLayout { | |
16 public: | |
17 enum Standard { | |
18 k140_Standard, | |
19 k430_Standard | |
20 }; | |
21 | |
22 MemoryLayout(Standard std) | |
23 : fStd(std) {} | |
24 | |
25 static size_t vector_alignment(size_t componentSize, int columns) { | |
26 return componentSize * (columns + columns % 2); | |
27 } | |
28 | |
29 /** | |
30 * Perform required rounding on array (and matrix) component sizes. std140 r equires array and | |
31 * matrix strides to be rounded up to the nearest multiple of 16, std430 doe s not. | |
32 */ | |
33 size_t roundArraySize(size_t raw) const { | |
34 switch (fStd) { | |
35 case k140_Standard: return (raw + 15) & ~15; | |
36 case k430_Standard: return raw; | |
37 } | |
38 ABORT("unreachable"); | |
39 } | |
40 | |
41 /** | |
42 * Returns a type's required alignment (when putting this type into a struct , the offset must be | |
43 * a multiple of the alignment). | |
44 */ | |
45 size_t alignment(const Type& type) const { | |
46 // See OpenGL Spec 7.6.2.2 Standard Uniform Block Layout | |
47 switch (type.kind()) { | |
48 case Type::kScalar_Kind: | |
49 return this->size(type); | |
50 case Type::kVector_Kind: | |
51 return vector_alignment(this->size(type.componentType()), type.c olumns()); | |
52 case Type::kMatrix_Kind: | |
53 return this->roundArraySize(vector_alignment(this->size(type.com ponentType()), | |
54 type.rows())); | |
55 case Type::kArray_Kind: | |
56 return this->roundArraySize(this->alignment(type.componentType() )); | |
57 case Type::kStruct_Kind: { | |
egdaniel
2016/11/14 18:48:34
Add return here for struct. Also struct must be ro
| |
58 size_t result = 16; | |
59 for (const auto& f : type.fields()) { | |
60 size_t alignment = this->alignment(*f.fType); | |
61 if (alignment > result) { | |
62 result = alignment; | |
63 } | |
64 } | |
65 } | |
66 default: | |
67 ABORT(("cannot determine size of type " + type.name()).c_str()); | |
68 } | |
69 } | |
70 | |
71 /** | |
72 * For matrices and arrays, returns the number of bytes from the start of on e entry (row, in | |
73 * the case of matrices) to the start of the next. | |
74 */ | |
75 size_t stride(const Type& type) const { | |
76 switch (type.kind()) { | |
77 case Type::kMatrix_Kind: // fall through | |
78 case Type::kArray_Kind: | |
79 return this->alignment(type); | |
80 default: | |
81 ABORT("type does not have a stride"); | |
82 } | |
83 } | |
84 | |
85 /** | |
86 * Returns the size of a type in bytes. | |
87 */ | |
88 size_t size(const Type& type) const { | |
89 switch (type.kind()) { | |
90 case Type::kScalar_Kind: | |
91 // FIXME need to take precision into account, once we figure out how we want to | |
92 // handle it... | |
93 return 4; | |
94 case Type::kVector_Kind: | |
95 return type.columns() * this->size(type.componentType()); | |
96 case Type::kMatrix_Kind: | |
97 return vector_alignment(this->size(type.componentType()), type.r ows()) * | |
98 type.columns(); | |
99 case Type::kArray_Kind: | |
100 return type.columns() * this->stride(type); | |
101 case Type::kStruct_Kind: { | |
102 size_t total = 0; | |
103 for (const auto& f : type.fields()) { | |
104 size_t alignment = this->alignment(*f.fType); | |
105 if (total % alignment != 0) { | |
106 total += alignment - total % alignment; | |
107 } | |
108 ASSERT(total % alignment == 0); | |
109 total += this->size(*f.fType); | |
110 } | |
111 return total; | |
112 } | |
113 default: | |
114 ABORT(("cannot determine size of type " + type.name()).c_str()); | |
115 } | |
116 } | |
117 | |
118 const Standard fStd; | |
119 }; | |
120 | |
121 } // namespace | |
122 | |
123 #endif | |
OLD | NEW |