summaryrefslogtreecommitdiff
path: root/src/mbgl/gfx/attribute.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mbgl/gfx/attribute.hpp')
-rw-r--r--src/mbgl/gfx/attribute.hpp123
1 files changed, 94 insertions, 29 deletions
diff --git a/src/mbgl/gfx/attribute.hpp b/src/mbgl/gfx/attribute.hpp
index 0dce6b2a06..4f44d68d7b 100644
--- a/src/mbgl/gfx/attribute.hpp
+++ b/src/mbgl/gfx/attribute.hpp
@@ -1,8 +1,11 @@
#pragma once
#include <mbgl/gfx/types.hpp>
+#include <mbgl/gfx/vertex_buffer.hpp>
#include <mbgl/util/type_list.hpp>
#include <mbgl/util/indexed_tuple.hpp>
+#include <mbgl/util/ignore.hpp>
+#include <mbgl/util/optional.hpp>
#include <array>
#include <type_traits>
@@ -79,6 +82,21 @@ struct VertexDescriptor {
AttributeDescriptor attributes[5];
};
+class AttributeBinding {
+public:
+ AttributeDescriptor attribute;
+ uint8_t vertexStride;
+ const VertexBufferResource* vertexBufferResource;
+ uint32_t vertexOffset;
+
+ friend bool operator==(const AttributeBinding& lhs, const AttributeBinding& rhs) {
+ return lhs.attribute == rhs.attribute &&
+ lhs.vertexStride == rhs.vertexStride &&
+ lhs.vertexBufferResource == rhs.vertexBufferResource &&
+ lhs.vertexOffset == rhs.vertexOffset;
+ }
+};
+
// 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
@@ -89,32 +107,32 @@ struct VertexDescriptor {
namespace detail {
template <class...>
-struct Vertex;
+struct VertexType;
template <class A1>
-struct Vertex<A1> {
- using Type = Vertex<A1>;
+struct VertexType<A1> {
+ using Type = VertexType<A1>;
typename A1::Value a1;
} MBGL_VERTEX_ALIGN;
template <class A1, class A2>
-struct Vertex<A1, A2> {
- using Type = Vertex<A1, A2>;
+struct VertexType<A1, A2> {
+ using Type = VertexType<A1, A2>;
typename A1::Value a1;
typename A2::Value a2;
} MBGL_VERTEX_ALIGN;
template <class A1, class A2, class A3>
-struct Vertex<A1, A2, A3> {
- using Type = Vertex<A1, A2, A3>;
+struct VertexType<A1, A2, A3> {
+ using Type = VertexType<A1, A2, A3>;
typename A1::Value a1;
typename A2::Value a2;
typename A3::Value a3;
} MBGL_VERTEX_ALIGN;
template <class A1, class A2, class A3, class A4>
-struct Vertex<A1, A2, A3, A4> {
- using Type = Vertex<A1, A2, A3, A4>;
+struct VertexType<A1, A2, A3, A4> {
+ using Type = VertexType<A1, A2, A3, A4>;
typename A1::Value a1;
typename A2::Value a2;
typename A3::Value a3;
@@ -122,8 +140,8 @@ struct Vertex<A1, A2, A3, A4> {
} MBGL_VERTEX_ALIGN;
template <class A1, class A2, class A3, class A4, class A5>
-struct Vertex<A1, A2, A3, A4, A5> {
- using Type = Vertex<A1, A2, A3, A4, A5>;
+struct VertexType<A1, A2, A3, A4, A5> {
+ using Type = VertexType<A1, A2, A3, A4, A5>;
typename A1::Value a1;
typename A2::Value a2;
typename A3::Value a3;
@@ -135,8 +153,8 @@ template <class>
struct Descriptor;
template <class A1>
-struct Descriptor<Vertex<A1>> {
- using Type = Vertex<A1>;
+struct Descriptor<VertexType<A1>> {
+ using Type = VertexType<A1>;
static_assert(sizeof(Type) < 256, "vertex type must be smaller than 256 bytes");
static_assert(std::is_standard_layout<Type>::value, "vertex type must use standard layout");
static constexpr const VertexDescriptor data = { sizeof(Type), 1, {
@@ -145,11 +163,11 @@ struct Descriptor<Vertex<A1>> {
};
template <class A1>
-constexpr const VertexDescriptor Descriptor<Vertex<A1>>::data;
+constexpr const VertexDescriptor Descriptor<VertexType<A1>>::data;
template <class A1, class A2>
-struct Descriptor<Vertex<A1, A2>> {
- using Type = Vertex<A1, A2>;
+struct Descriptor<VertexType<A1, A2>> {
+ using Type = VertexType<A1, A2>;
static_assert(sizeof(Type) < 256, "vertex type must be smaller than 256 bytes");
static_assert(std::is_standard_layout<Type>::value, "vertex type must use standard layout");
static constexpr const VertexDescriptor data = { sizeof(Type), 2, {
@@ -159,11 +177,11 @@ struct Descriptor<Vertex<A1, A2>> {
};
template <class A1, class A2>
-constexpr const VertexDescriptor Descriptor<Vertex<A1, A2>>::data;
+constexpr const VertexDescriptor Descriptor<VertexType<A1, A2>>::data;
template <class A1, class A2, class A3>
-struct Descriptor<Vertex<A1, A2, A3>> {
- using Type = Vertex<A1, A2, A3>;
+struct Descriptor<VertexType<A1, A2, A3>> {
+ using Type = VertexType<A1, A2, A3>;
static_assert(sizeof(Type) < 256, "vertex type must be smaller than 256 bytes");
static_assert(std::is_standard_layout<Type>::value, "vertex type must use standard layout");
static constexpr const VertexDescriptor data = { sizeof(Type), 3, {
@@ -174,11 +192,11 @@ struct Descriptor<Vertex<A1, A2, A3>> {
};
template <class A1, class A2, class A3>
-constexpr const VertexDescriptor Descriptor<Vertex<A1, A2, A3>>::data;
+constexpr const VertexDescriptor Descriptor<VertexType<A1, A2, A3>>::data;
template <class A1, class A2, class A3, class A4>
-struct Descriptor<Vertex<A1, A2, A3, A4>> {
- using Type = Vertex<A1, A2, A3, A4>;
+struct Descriptor<VertexType<A1, A2, A3, A4>> {
+ using Type = VertexType<A1, A2, A3, A4>;
static_assert(sizeof(Type) < 256, "vertex type must be smaller than 256 bytes");
static_assert(std::is_standard_layout<Type>::value, "vertex type must use standard layout");
static constexpr const VertexDescriptor data = { sizeof(Type), 4, {
@@ -190,11 +208,11 @@ struct Descriptor<Vertex<A1, A2, A3, A4>> {
};
template <class A1, class A2, class A3, class A4>
-constexpr const VertexDescriptor Descriptor<Vertex<A1, A2, A3, A4>>::data;
+constexpr const VertexDescriptor Descriptor<VertexType<A1, A2, A3, A4>>::data;
template <class A1, class A2, class A3, class A4, class A5>
-struct Descriptor<Vertex<A1, A2, A3, A4, A5>> {
- using Type = Vertex<A1, A2, A3, A4, A5>;
+struct Descriptor<VertexType<A1, A2, A3, A4, A5>> {
+ using Type = VertexType<A1, A2, A3, A4, A5>;
static_assert(sizeof(Type) < 256, "vertex type must be smaller than 256 bytes");
static_assert(std::is_standard_layout<Type>::value, "vertex type must use standard layout");
static constexpr const VertexDescriptor data = { sizeof(Type), 5, {
@@ -207,11 +225,14 @@ struct Descriptor<Vertex<A1, A2, A3, A4, A5>> {
};
template <class A1, class A2, class A3, class A4, class A5>
-constexpr const VertexDescriptor Descriptor<Vertex<A1, A2, A3, A4, A5>>::data;
+constexpr const VertexDescriptor Descriptor<VertexType<A1, A2, A3, A4, A5>>::data;
+
+template <class>
+struct Vertex;
template <class... As>
struct Vertex<TypeList<As...>> {
- using Type = Vertex<typename As::Type...>;
+ using Type = VertexType<typename As::Type...>;
};
} // namespace detail
@@ -219,8 +240,52 @@ struct Vertex<TypeList<As...>> {
template <class A>
using Vertex = typename detail::Vertex<A>::Type;
-template <class V>
-using VertexDescriptorOf = detail::Descriptor<V>;
+template <class T>
+using VertexType = typename detail::VertexType<T>;
+
+template <size_t I = 0, class... As>
+AttributeBinding attributeBinding(const VertexBuffer<detail::VertexType<As...>>& buffer) {
+ using Descriptor = detail::Descriptor<detail::VertexType<As...>>;
+ static_assert(I < Descriptor::data.count, "attribute index must be in range");
+ return {
+ Descriptor::data.attributes[I],
+ Descriptor::data.stride,
+ buffer.resource.get(),
+ 0,
+ };
+}
+
+optional<gfx::AttributeBinding> offsetAttributeBinding(const optional<gfx::AttributeBinding>& binding, std::size_t vertexOffset);
+
+template <class>
+class AttributeBindings;
+
+template <class... As>
+class AttributeBindings<TypeList<As...>> final
+ : public IndexedTuple<TypeList<As...>,
+ TypeList<ExpandToType<As, optional<AttributeBinding>>...>> {
+ using Base = IndexedTuple<TypeList<As...>,
+ TypeList<ExpandToType<As, optional<AttributeBinding>>...>>;
+
+public:
+ AttributeBindings(const VertexBuffer<Vertex<TypeList<As...>>>& buffer)
+ : Base{ attributeBinding<TypeIndex<As, As...>::value>(buffer)... } {
+ }
+
+ template <class... Args>
+ AttributeBindings(Args&&... args) : Base(std::forward<Args>(args)...) {
+ }
+
+ AttributeBindings offset(const std::size_t vertexOffset) const {
+ return { offsetAttributeBinding(Base::template get<As>(), vertexOffset)... };
+ }
+
+ uint32_t activeCount() const {
+ uint32_t result = 0;
+ util::ignore({ ((result += bool(Base::template get<As>())), 0)... });
+ return result;
+ }
+};
} // namespace gfx
} // namespace mbgl