Browse Source

Trade: reorganize MeshAttributeData internals for better serializability.

Put the pointer that differs in size on 32 and 64bit platforms last so
we have at least the prefix always stable. This also makes it possible
to extend the class to store 8/16 bytes of arbitrary data in there
(bounds etc.). Not doing that yet, just preparing for possible
extension.
catastrophic-cross
Vladimír Vondruš 6 years ago
parent
commit
95c93c928a
  1. 71
      src/Magnum/Trade/MeshData.h

71
src/Magnum/Trade/MeshData.h

@ -338,7 +338,7 @@ class MAGNUM_TRADE_EXPORT MeshAttributeData {
* initialization of the attribute array for @ref MeshData, expected to * initialization of the attribute array for @ref MeshData, expected to
* be replaced with concrete values later. * be replaced with concrete values later.
*/ */
constexpr explicit MeshAttributeData() noexcept: _data{}, _vertexCount{}, _format{}, _stride{}, _name{}, _arraySize{}, _isOffsetOnly{false} {} constexpr explicit MeshAttributeData() noexcept: _format{}, _name{}, _isOffsetOnly{false}, _vertexCount{}, _stride{}, _arraySize{}, _data{} {}
/** /**
* @brief Type-erased constructor * @brief Type-erased constructor
@ -485,10 +485,10 @@ class MAGNUM_TRADE_EXPORT MeshAttributeData {
* passed to @ref MeshData. * passed to @ref MeshData.
* @see @ref stride() * @see @ref stride()
*/ */
constexpr explicit MeshAttributeData(Int padding): _data{nullptr}, _vertexCount{0}, _format{}, _stride{ constexpr explicit MeshAttributeData(Int padding): _format{}, _name{}, _isOffsetOnly{false}, _vertexCount{0}, _stride{
(CORRADE_CONSTEXPR_ASSERT(padding >= -32768 && padding <= 32767, (CORRADE_CONSTEXPR_ASSERT(padding >= -32768 && padding <= 32767,
"Trade::MeshAttributeData: at most 32k padding supported, got" << padding), Short(padding)) "Trade::MeshAttributeData: at most 32k padding supported, got" << padding), Short(padding))
}, _name{}, _arraySize{}, _isOffsetOnly{false} {} }, _arraySize{}, _data{nullptr} {}
/** /**
* @brief If the attribute is offset-only * @brief If the attribute is offset-only
@ -559,29 +559,34 @@ class MAGNUM_TRADE_EXPORT MeshAttributeData {
} }
private: private:
friend MeshData;
constexpr explicit MeshAttributeData(MeshAttribute name, VertexFormat format, UnsignedShort arraySize, const Containers::StridedArrayView1D<const void>& data, std::nullptr_t) noexcept; constexpr explicit MeshAttributeData(MeshAttribute name, VertexFormat format, UnsignedShort arraySize, const Containers::StridedArrayView1D<const void>& data, std::nullptr_t) noexcept;
friend MeshData; VertexFormat _format;
union Data { MeshAttribute _name;
/* FFS C++ why this doesn't JUST WORK goddamit?! */ bool _isOffsetOnly;
constexpr Data(const void* pointer = nullptr): pointer{pointer} {} /* 1 byte free for more stuff on 64b (23, aligned to 24) and on 32b
constexpr Data(std::size_t offset): offset{offset} {} (19, aligned to 20) */
const void* pointer;
std::size_t offset;
} _data;
/* Vertex count in MeshData is currently 32-bit, so this doesn't need /* Vertex count in MeshData is currently 32-bit, so this doesn't need
to be 64-bit either */ to be 64-bit either */
UnsignedInt _vertexCount; UnsignedInt _vertexCount;
VertexFormat _format;
/* According to https://opengl.gpuinfo.org/displaycapability.php?name=GL_MAX_VERTEX_ATTRIB_STRIDE, /* According to https://opengl.gpuinfo.org/displaycapability.php?name=GL_MAX_VERTEX_ATTRIB_STRIDE,
current largest reported stride is 4k so 32k should be enough */ current largest reported stride is 4k so 32k should be enough */
Short _stride; Short _stride;
MeshAttribute _name;
UnsignedShort _arraySize; UnsignedShort _arraySize;
bool _isOffsetOnly;
/* 1 byte free for more stuff on 64b (23, aligned to 24) and on 32b /* Data pointer last. Its size varies between 32 and 64 bit and having
(19, aligned to 20) */ it last reduces the amount of pain when serializing. */
union Data {
/* FFS C++ why this doesn't JUST WORK goddamit?! */
constexpr Data(const void* pointer = nullptr): pointer{pointer} {}
constexpr Data(std::size_t offset): offset{offset} {}
const void* pointer;
std::size_t offset;
} _data;
}; };
/** @relatesalso MeshAttributeData /** @relatesalso MeshAttributeData
@ -2069,30 +2074,32 @@ namespace Implementation {
#endif #endif
constexpr MeshAttributeData::MeshAttributeData(const MeshAttribute name, const VertexFormat format, const UnsignedShort arraySize, const Containers::StridedArrayView1D<const void>& data, std::nullptr_t) noexcept: constexpr MeshAttributeData::MeshAttributeData(const MeshAttribute name, const VertexFormat format, const UnsignedShort arraySize, const Containers::StridedArrayView1D<const void>& data, std::nullptr_t) noexcept:
_data{data.data()}, _vertexCount{UnsignedInt(data.size())}, _format{format}, _format{(CORRADE_CONSTEXPR_ASSERT(!arraySize || !isVertexFormatImplementationSpecific(format),
"Trade::MeshAttributeData: array attributes can't have an implementation-specific format"), format)},
_name{(CORRADE_CONSTEXPR_ASSERT(Implementation::isVertexFormatCompatibleWithAttribute(name, format),
"Trade::MeshAttributeData:" << format << "is not a valid format for" << name), name)},
_isOffsetOnly{false}, _vertexCount{UnsignedInt(data.size())},
/** @todo support zero / negative stride? would be hard to transfer to GL */ /** @todo support zero / negative stride? would be hard to transfer to GL */
_stride{(CORRADE_CONSTEXPR_ASSERT(!(UnsignedInt(data.stride()) & 0xffff8000), _stride{(CORRADE_CONSTEXPR_ASSERT(!(UnsignedInt(data.stride()) & 0xffff8000),
"Trade::MeshAttributeData: expected stride to be positive and at most 32k, got" << data.stride()), "Trade::MeshAttributeData: expected stride to be positive and at most 32k, got" << data.stride()),
Short(data.stride())) Short(data.stride()))},
}, _name{(CORRADE_CONSTEXPR_ASSERT(Implementation::isVertexFormatCompatibleWithAttribute(name, format), _arraySize{(CORRADE_CONSTEXPR_ASSERT(!arraySize || Implementation::isAttributeArrayAllowed(name),
"Trade::MeshAttributeData:" << format << "is not a valid format for" << name), name) "Trade::MeshAttributeData:" << name << "can't be an array attribute"), arraySize)},
}, _arraySize{(CORRADE_CONSTEXPR_ASSERT(!arraySize || Implementation::isAttributeArrayAllowed(name), _data{data.data()} {}
"Trade::MeshAttributeData:" << name << "can't be an array attribute"), arraySize)
}, _isOffsetOnly{(CORRADE_CONSTEXPR_ASSERT(!arraySize || !isVertexFormatImplementationSpecific(format),
"Trade::MeshAttributeData: array attributes can't have an implementation-specific format"), false)} {}
constexpr MeshAttributeData::MeshAttributeData(const MeshAttribute name, const VertexFormat format, const std::size_t offset, const UnsignedInt vertexCount, const std::ptrdiff_t stride, UnsignedShort arraySize) noexcept: constexpr MeshAttributeData::MeshAttributeData(const MeshAttribute name, const VertexFormat format, const std::size_t offset, const UnsignedInt vertexCount, const std::ptrdiff_t stride, UnsignedShort arraySize) noexcept:
_data{offset}, _vertexCount{vertexCount}, _format{format}, _format{(CORRADE_CONSTEXPR_ASSERT(!arraySize || !isVertexFormatImplementationSpecific(format),
"Trade::MeshAttributeData: array attributes can't have an implementation-specific format"), format)},
_name{(CORRADE_CONSTEXPR_ASSERT(Implementation::isVertexFormatCompatibleWithAttribute(name, format),
"Trade::MeshAttributeData:" << format << "is not a valid format for" << name), name)},
_isOffsetOnly{true}, _vertexCount{vertexCount},
/** @todo support zero / negative stride? would be hard to transfer to GL */ /** @todo support zero / negative stride? would be hard to transfer to GL */
_stride{(CORRADE_CONSTEXPR_ASSERT(!(UnsignedInt(stride) & 0xffff8000), _stride{(CORRADE_CONSTEXPR_ASSERT(!(UnsignedInt(stride) & 0xffff8000),
"Trade::MeshAttributeData: expected stride to be positive and at most 32k, got" << stride), "Trade::MeshAttributeData: expected stride to be positive and at most 32k, got" << stride),
Short(stride)) Short(stride))},
}, _name{(CORRADE_CONSTEXPR_ASSERT(Implementation::isVertexFormatCompatibleWithAttribute(name, format), _arraySize{(CORRADE_CONSTEXPR_ASSERT(!arraySize || Implementation::isAttributeArrayAllowed(name),
"Trade::MeshAttributeData:" << format << "is not a valid format for" << name), name) "Trade::MeshAttributeData:" << name << "can't be an array attribute"), arraySize)},
}, _arraySize{(CORRADE_CONSTEXPR_ASSERT(!arraySize || Implementation::isAttributeArrayAllowed(name), _data{offset} {}
"Trade::MeshAttributeData:" << name << "can't be an array attribute"), arraySize)
}, _isOffsetOnly{(CORRADE_CONSTEXPR_ASSERT(!arraySize || !isVertexFormatImplementationSpecific(format),
"Trade::MeshAttributeData: array attributes can't have an implementation-specific format"), true)} {}
template<class T> constexpr MeshAttributeData::MeshAttributeData(MeshAttribute name, const Containers::StridedArrayView1D<T>& data) noexcept: MeshAttributeData{name, Implementation::vertexFormatFor<typename std::remove_const<T>::type>(), 0, data, nullptr} {} template<class T> constexpr MeshAttributeData::MeshAttributeData(MeshAttribute name, const Containers::StridedArrayView1D<T>& data) noexcept: MeshAttributeData{name, Implementation::vertexFormatFor<typename std::remove_const<T>::type>(), 0, data, nullptr} {}

Loading…
Cancel
Save