Chromium Code Reviews| 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 * Rounds up to the nearest multiple of 16 if in std140, otherwise returns t he parameter | |
| 31 * unchanged (std140 requires various things to be rounded up to the nearest multiple of 16, | |
| 32 * std430 does not). | |
| 33 */ | |
| 34 size_t roundUpIfNeeded(size_t raw) const { | |
| 35 switch (fStd) { | |
| 36 case k140_Standard: return (raw + 15) & ~15; | |
| 37 case k430_Standard: return raw; | |
| 38 } | |
| 39 ABORT("unreachable"); | |
| 40 } | |
| 41 | |
| 42 /** | |
| 43 * Returns a type's required alignment when used as a standalone variable. | |
| 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->roundUpIfNeeded(vector_alignment(this->size(type.co mponentType()), | |
| 54 type.rows())); | |
| 55 case Type::kArray_Kind: | |
| 56 return this->roundUpIfNeeded(this->alignment(type.componentType( ))); | |
| 57 case Type::kStruct_Kind: { | |
| 58 size_t result = 0; | |
| 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 return this->roundUpIfNeeded(result); | |
| 66 } | |
| 67 default: | |
| 68 ABORT(("cannot determine size of type " + type.name()).c_str()); | |
| 69 } | |
| 70 } | |
| 71 | |
| 72 /** | |
| 73 * For matrices and arrays, returns the number of bytes from the start of on e entry (row, in | |
| 74 * the case of matrices) to the start of the next. | |
| 75 */ | |
| 76 size_t stride(const Type& type) const { | |
| 77 switch (type.kind()) { | |
| 78 case Type::kMatrix_Kind: // fall through | |
| 79 case Type::kArray_Kind: | |
| 80 return this->alignment(type); | |
| 81 default: | |
| 82 ABORT("type does not have a stride"); | |
| 83 } | |
| 84 } | |
| 85 | |
| 86 /** | |
| 87 * Returns the size of a type in bytes. | |
| 88 */ | |
| 89 size_t size(const Type& type) const { | |
| 90 switch (type.kind()) { | |
| 91 case Type::kScalar_Kind: | |
| 92 if (type.name() == "bool") { | |
| 93 return 1; | |
| 94 } | |
| 95 // FIXME need to take precision into account, once we figure out how we want to | |
| 96 // handle it... | |
| 97 return 4; | |
| 98 case Type::kVector_Kind: | |
| 99 return type.columns() * this->size(type.componentType()); | |
| 100 case Type::kMatrix_Kind: | |
| 101 return vector_alignment(this->size(type.componentType()), type.r ows()) * | |
| 102 type.columns(); | |
| 103 case Type::kArray_Kind: | |
| 104 return type.columns() * this->stride(type); | |
| 105 case Type::kStruct_Kind: { | |
| 106 size_t total = 0; | |
| 107 for (const auto& f : type.fields()) { | |
| 108 size_t alignment = this->alignment(*f.fType); | |
| 109 if (total % alignment != 0) { | |
| 110 total += alignment - total % alignment; | |
| 111 } | |
| 112 ASSERT(total % alignment == 0); | |
| 113 total += this->size(*f.fType); | |
| 114 } | |
| 115 size_t alignment = this->alignment(type); | |
| 116 ASSERT(0 == alignment % this->alignment(*type.fields()[0].fType) ); | |
|
egdaniel
2016/11/15 16:59:28
Hmm this does risk referencing field 0 if there a
| |
| 117 return (total + alignment - 1) & ~(alignment - 1); | |
| 118 } | |
| 119 default: | |
| 120 ABORT(("cannot determine size of type " + type.name()).c_str()); | |
| 121 } | |
| 122 } | |
| 123 | |
| 124 const Standard fStd; | |
| 125 }; | |
| 126 | |
| 127 } // namespace | |
| 128 | |
| 129 #endif | |
| OLD | NEW |