#pragma once #include #include #include #include #include #include #define MBGL_DEFINE_ATTRIBUTE(type_, n_, name_) \ struct name_ { \ using Type = ::mbgl::gfx::AttributeType; \ static auto name() { \ return #name_; \ } \ } #define MBGL_VERTEX_ALIGN __attribute__((aligned(4))) namespace mbgl { namespace gfx { namespace { template struct AttributeDataTypeOf; template <> struct AttributeDataTypeOf : std::integral_constant {}; template <> struct AttributeDataTypeOf : std::integral_constant {}; template <> struct AttributeDataTypeOf : std::integral_constant {}; template <> struct AttributeDataTypeOf : std::integral_constant {}; template <> struct AttributeDataTypeOf : std::integral_constant {}; template <> struct AttributeDataTypeOf : std::integral_constant {}; template <> struct AttributeDataTypeOf : std::integral_constant {}; template <> struct AttributeDataTypeOf : std::integral_constant {}; template <> struct AttributeDataTypeOf : std::integral_constant {}; template <> struct AttributeDataTypeOf : std::integral_constant {}; template <> struct AttributeDataTypeOf : std::integral_constant {}; template <> struct AttributeDataTypeOf : std::integral_constant {}; template <> struct AttributeDataTypeOf : std::integral_constant {}; template <> struct AttributeDataTypeOf : std::integral_constant {}; template <> struct AttributeDataTypeOf : std::integral_constant {}; template <> struct AttributeDataTypeOf : std::integral_constant {}; template <> struct AttributeDataTypeOf : std::integral_constant {}; template <> struct AttributeDataTypeOf : std::integral_constant {}; template <> struct AttributeDataTypeOf : std::integral_constant {}; template <> struct AttributeDataTypeOf : std::integral_constant {}; template <> struct AttributeDataTypeOf : std::integral_constant {}; template <> struct AttributeDataTypeOf : std::integral_constant {}; template <> struct AttributeDataTypeOf : std::integral_constant {}; template <> struct AttributeDataTypeOf : std::integral_constant {}; template <> struct AttributeDataTypeOf : std::integral_constant {}; template <> struct AttributeDataTypeOf : std::integral_constant {}; template <> struct AttributeDataTypeOf : std::integral_constant {}; template <> struct AttributeDataTypeOf : std::integral_constant {}; } // namespace template class AttributeType { public: using ElementType = T; static constexpr AttributeDataType DataType = AttributeDataTypeOf::value; static constexpr size_t Dimensions = N; using Value = std::array; }; struct AttributeDescriptor { AttributeDataType dataType; uint8_t offset; }; inline bool operator==(const AttributeDescriptor& lhs, const AttributeDescriptor& rhs) { return lhs.dataType == rhs.dataType && lhs.offset == rhs.offset; } struct VertexDescriptor { uint8_t stride; uint8_t count; AttributeDescriptor attributes[5]; }; // Attribute binding requires member offsets. The only standard way to // obtain an offset is the offsetof macro. The offsetof macro has defined // behavior only for standard layout types. That rules out std::tuple and // any other solution that relies on chained inheritance. Manually implemented // variadic specialization looks like the only solution. Fortunately, we // only use a maximum of five attributes. namespace detail { template struct Vertex; template struct Vertex { using Type = Vertex; typename A1::Value a1; } MBGL_VERTEX_ALIGN; template struct Vertex { using Type = Vertex; typename A1::Value a1; typename A2::Value a2; } MBGL_VERTEX_ALIGN; template struct Vertex { using Type = Vertex; typename A1::Value a1; typename A2::Value a2; typename A3::Value a3; } MBGL_VERTEX_ALIGN; template struct Vertex { using Type = Vertex; typename A1::Value a1; typename A2::Value a2; typename A3::Value a3; typename A4::Value a4; } MBGL_VERTEX_ALIGN; template struct Vertex { using Type = Vertex; typename A1::Value a1; typename A2::Value a2; typename A3::Value a3; typename A4::Value a4; typename A5::Value a5; } MBGL_VERTEX_ALIGN; template struct Descriptor; template struct Descriptor> { using Type = Vertex; static_assert(sizeof(Type) < 256, "vertex type must be smaller than 256 bytes"); static_assert(std::is_standard_layout::value, "vertex type must use standard layout"); static constexpr const VertexDescriptor data = { sizeof(Type), 1, { { A1::DataType, offsetof(Type, a1) }, }}; }; template constexpr const VertexDescriptor Descriptor>::data; template struct Descriptor> { using Type = Vertex; static_assert(sizeof(Type) < 256, "vertex type must be smaller than 256 bytes"); static_assert(std::is_standard_layout::value, "vertex type must use standard layout"); static constexpr const VertexDescriptor data = { sizeof(Type), 2, { { A1::DataType, offsetof(Type, a1) }, { A2::DataType, offsetof(Type, a2) }, }}; }; template constexpr const VertexDescriptor Descriptor>::data; template struct Descriptor> { using Type = Vertex; static_assert(sizeof(Type) < 256, "vertex type must be smaller than 256 bytes"); static_assert(std::is_standard_layout::value, "vertex type must use standard layout"); static constexpr const VertexDescriptor data = { sizeof(Type), 3, { { A1::DataType, offsetof(Type, a1) }, { A2::DataType, offsetof(Type, a2) }, { A3::DataType, offsetof(Type, a3) }, }}; }; template constexpr const VertexDescriptor Descriptor>::data; template struct Descriptor> { using Type = Vertex; static_assert(sizeof(Type) < 256, "vertex type must be smaller than 256 bytes"); static_assert(std::is_standard_layout::value, "vertex type must use standard layout"); static constexpr const VertexDescriptor data = { sizeof(Type), 4, { { A1::DataType, offsetof(Type, a1) }, { A2::DataType, offsetof(Type, a2) }, { A3::DataType, offsetof(Type, a3) }, { A4::DataType, offsetof(Type, a4) }, }}; }; template constexpr const VertexDescriptor Descriptor>::data; template struct Descriptor> { using Type = Vertex; static_assert(sizeof(Type) < 256, "vertex type must be smaller than 256 bytes"); static_assert(std::is_standard_layout::value, "vertex type must use standard layout"); static constexpr const VertexDescriptor data = { sizeof(Type), 5, { { A1::DataType, offsetof(Type, a1) }, { A2::DataType, offsetof(Type, a2) }, { A3::DataType, offsetof(Type, a3) }, { A4::DataType, offsetof(Type, a4) }, { A5::DataType, offsetof(Type, a5) }, }}; }; template constexpr const VertexDescriptor Descriptor>::data; template struct Vertex> { using Type = Vertex; }; } // namespace detail template using Vertex = typename detail::Vertex::Type; template using VertexDescriptorOf = detail::Descriptor; } // namespace gfx } // namespace mbgl