Chromium Code Reviews| Index: src/sksl/SkSLMemoryLayout.h |
| diff --git a/src/sksl/SkSLMemoryLayout.h b/src/sksl/SkSLMemoryLayout.h |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..76d122e41a6d53c15ec4a58eba5c9f531a710a33 |
| --- /dev/null |
| +++ b/src/sksl/SkSLMemoryLayout.h |
| @@ -0,0 +1,123 @@ |
| +/* |
| + * Copyright 2016 Google Inc. |
| + * |
| + * Use of this source code is governed by a BSD-style license that can be |
| + * found in the LICENSE file. |
| + */ |
| + |
| +#ifndef SKIASL_MEMORYLAYOUT |
| +#define SKIASL_MEMORYLAYOUT |
| + |
| +#include "ir/SkSLType.h" |
| + |
| +namespace SkSL { |
| + |
| +class MemoryLayout { |
| +public: |
| + enum Standard { |
| + k140_Standard, |
| + k430_Standard |
| + }; |
| + |
| + MemoryLayout(Standard std) |
| + : fStd(std) {} |
| + |
| + static size_t vector_alignment(size_t componentSize, int columns) { |
| + return componentSize * (columns + columns % 2); |
| + } |
| + |
| + /** |
| + * Perform required rounding on array (and matrix) component sizes. std140 requires array and |
| + * matrix strides to be rounded up to the nearest multiple of 16, std430 does not. |
| + */ |
| + size_t roundArraySize(size_t raw) const { |
| + switch (fStd) { |
| + case k140_Standard: return (raw + 15) & ~15; |
| + case k430_Standard: return raw; |
| + } |
| + ABORT("unreachable"); |
| + } |
| + |
| + /** |
| + * Returns a type's required alignment (when putting this type into a struct, the offset must be |
| + * a multiple of the alignment). |
| + */ |
| + size_t alignment(const Type& type) const { |
| + // See OpenGL Spec 7.6.2.2 Standard Uniform Block Layout |
| + switch (type.kind()) { |
| + case Type::kScalar_Kind: |
| + return this->size(type); |
| + case Type::kVector_Kind: |
| + return vector_alignment(this->size(type.componentType()), type.columns()); |
| + case Type::kMatrix_Kind: |
| + return this->roundArraySize(vector_alignment(this->size(type.componentType()), |
| + type.rows())); |
| + case Type::kArray_Kind: |
| + return this->roundArraySize(this->alignment(type.componentType())); |
| + case Type::kStruct_Kind: { |
|
egdaniel
2016/11/14 18:48:34
Add return here for struct. Also struct must be ro
|
| + size_t result = 16; |
| + for (const auto& f : type.fields()) { |
| + size_t alignment = this->alignment(*f.fType); |
| + if (alignment > result) { |
| + result = alignment; |
| + } |
| + } |
| + } |
| + default: |
| + ABORT(("cannot determine size of type " + type.name()).c_str()); |
| + } |
| + } |
| + |
| + /** |
| + * For matrices and arrays, returns the number of bytes from the start of one entry (row, in |
| + * the case of matrices) to the start of the next. |
| + */ |
| + size_t stride(const Type& type) const { |
| + switch (type.kind()) { |
| + case Type::kMatrix_Kind: // fall through |
| + case Type::kArray_Kind: |
| + return this->alignment(type); |
| + default: |
| + ABORT("type does not have a stride"); |
| + } |
| + } |
| + |
| + /** |
| + * Returns the size of a type in bytes. |
| + */ |
| + size_t size(const Type& type) const { |
| + switch (type.kind()) { |
| + case Type::kScalar_Kind: |
| + // FIXME need to take precision into account, once we figure out how we want to |
| + // handle it... |
| + return 4; |
| + case Type::kVector_Kind: |
| + return type.columns() * this->size(type.componentType()); |
| + case Type::kMatrix_Kind: |
| + return vector_alignment(this->size(type.componentType()), type.rows()) * |
| + type.columns(); |
| + case Type::kArray_Kind: |
| + return type.columns() * this->stride(type); |
| + case Type::kStruct_Kind: { |
| + size_t total = 0; |
| + for (const auto& f : type.fields()) { |
| + size_t alignment = this->alignment(*f.fType); |
| + if (total % alignment != 0) { |
| + total += alignment - total % alignment; |
| + } |
| + ASSERT(total % alignment == 0); |
| + total += this->size(*f.fType); |
| + } |
| + return total; |
| + } |
| + default: |
| + ABORT(("cannot determine size of type " + type.name()).c_str()); |
| + } |
| + } |
| + |
| + const Standard fStd; |
| +}; |
| + |
| +} // namespace |
| + |
| +#endif |