Files
MapLibreParticleLab/src/mbgl/gl/attribute.hpp
2016-11-08 08:09:29 -08:00

169 lines
4.5 KiB
C++

#pragma once
#include <mbgl/gl/types.hpp>
#include <mbgl/util/ignore.hpp>
#include <mbgl/util/indexed_tuple.hpp>
#include <cstddef>
#include <functional>
namespace mbgl {
namespace gl {
template <class Tag, class T, std::size_t N>
class Attribute {
public:
using Type = T[N];
class State {
public:
AttributeLocation location;
static constexpr std::size_t count = N;
static constexpr DataType type = DataTypeOf<T>::value;
};
};
#define MBGL_DEFINE_ATTRIBUTE(type_, n_, name_) \
struct name_ : ::mbgl::gl::Attribute<name_, type_, n_> { static constexpr auto name = #name_; }
namespace detail {
// 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.
template <class... As>
class Vertex;
template <class A1>
class Vertex<A1> {
public:
typename A1::Type a1;
using VertexType = Vertex<A1>;
static const std::size_t attributeOffsets[1];
};
template <class A1, class A2>
class Vertex<A1, A2> {
public:
typename A1::Type a1;
typename A2::Type a2;
using VertexType = Vertex<A1, A2>;
static const std::size_t attributeOffsets[2];
};
template <class A1, class A2, class A3>
class Vertex<A1, A2, A3> {
public:
typename A1::Type a1;
typename A2::Type a2;
typename A3::Type a3;
using VertexType = Vertex<A1, A2, A3>;
static const std::size_t attributeOffsets[3];
};
template <class A1, class A2, class A3, class A4>
class Vertex<A1, A2, A3, A4> {
public:
typename A1::Type a1;
typename A2::Type a2;
typename A3::Type a3;
typename A4::Type a4;
using VertexType = Vertex<A1, A2, A3, A4>;
static const std::size_t attributeOffsets[4];
};
template <class A1, class A2, class A3, class A4, class A5>
class Vertex<A1, A2, A3, A4, A5> {
public:
typename A1::Type a1;
typename A2::Type a2;
typename A3::Type a3;
typename A4::Type a4;
typename A5::Type a5;
using VertexType = Vertex<A1, A2, A3, A4, A5>;
static const std::size_t attributeOffsets[5];
};
template <class A1>
const std::size_t Vertex<A1>::attributeOffsets[1] = {
offsetof(VertexType, a1)
};
template <class A1, class A2>
const std::size_t Vertex<A1, A2>::attributeOffsets[2] = {
offsetof(VertexType, a1),
offsetof(VertexType, a2)
};
template <class A1, class A2, class A3>
const std::size_t Vertex<A1, A2, A3>::attributeOffsets[3] = {
offsetof(VertexType, a1),
offsetof(VertexType, a2),
offsetof(VertexType, a3)
};
template <class A1, class A2, class A3, class A4>
const std::size_t Vertex<A1, A2, A3, A4>::attributeOffsets[4] = {
offsetof(VertexType, a1),
offsetof(VertexType, a2),
offsetof(VertexType, a3),
offsetof(VertexType, a4)
};
template <class A1, class A2, class A3, class A4, class A5>
const std::size_t Vertex<A1, A2, A3, A4, A5>::attributeOffsets[5] = {
offsetof(VertexType, a1),
offsetof(VertexType, a2),
offsetof(VertexType, a3),
offsetof(VertexType, a4),
offsetof(VertexType, a5)
};
} // namespace detail
AttributeLocation attributeLocation(ProgramID, const char * name);
void bindAttribute(AttributeLocation location,
std::size_t count,
DataType type,
std::size_t vertexSize,
std::size_t vertexOffset,
std::size_t attributeOffset);
template <class... As>
class Attributes {
public:
using State = IndexedTuple<TypeList<As...>, TypeList<typename As::State...>>;
using Vertex = detail::Vertex<As...>;
template <class A>
static constexpr std::size_t Index = TypeIndex<A, As...>::value;
static State state(const ProgramID& id) {
return State { { attributeLocation(id, As::name) }... };
}
static std::function<void (std::size_t)> binder(const State& state) {
return [&state] (std::size_t vertexOffset) {
ignore({ (bindAttribute(state.template get<As>().location,
state.template get<As>().count,
state.template get<As>().type,
sizeof(Vertex),
vertexOffset,
Vertex::attributeOffsets[Index<As>]), 0)... });
};
}
};
} // namespace gl
} // namespace mbgl