summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Firebaugh <john.firebaugh@gmail.com>2016-11-07 12:26:05 -0800
committerJohn Firebaugh <john.firebaugh@gmail.com>2016-11-08 08:09:29 -0800
commit1db2ffbc1b69069eca39f786cacc45dbb02c3052 (patch)
tree9d6ed2a7302492f41c52ea3fdeadabf6466b0d8d
parent66bdbc3b969083b9d647abdf72784be64a125949 (diff)
downloadqtlocation-mapboxgl-1db2ffbc1b69069eca39f786cacc45dbb02c3052.tar.gz
[core] Use gl::Program to resolve some rough edges in the GL binding types
* Extract `ignore` util to separate header. * `Segment` now tracks offset and length of indices, rather than primitives. This is more natural. * Introduce `VertexVector` and `IndexVector` types. These types carry information about the intended draw mode (`Triangles`, `LineStrip`, etc.), and ensure that elements are always appended in a group size appropriate for that draw mode, for both indexed and unindexed rendering. * `Program`, rather than `Drawable`, is now the unifying object for draw calls. `Program` is the best place to type check the draw call, because it is typed to carry information about the intended primitive, vertex type, attributes, and uniforms. * Use the debug shaders for debug tile rendering, like gl-js. * Fix the draw mode for background. It was drawing triangle strips with a triangles array. Surprised this didn’t cause issues. Now it’s type checked.
-rw-r--r--cmake/core-files.cmake3
-rw-r--r--src/mbgl/gl/attribute.hpp16
-rw-r--r--src/mbgl/gl/context.cpp4
-rw-r--r--src/mbgl/gl/context.hpp40
-rw-r--r--src/mbgl/gl/draw_mode.hpp34
-rw-r--r--src/mbgl/gl/drawable.hpp124
-rw-r--r--src/mbgl/gl/index_buffer.hpp38
-rw-r--r--src/mbgl/gl/primitives.hpp22
-rw-r--r--src/mbgl/gl/program.hpp64
-rw-r--r--src/mbgl/gl/segment.hpp12
-rw-r--r--src/mbgl/gl/uniform.hpp7
-rw-r--r--src/mbgl/gl/vertex_buffer.hpp31
-rw-r--r--src/mbgl/layout/symbol_layout.cpp20
-rw-r--r--src/mbgl/programs/circle_program.hpp1
-rw-r--r--src/mbgl/programs/collision_box_program.hpp1
-rw-r--r--src/mbgl/programs/debug_program.hpp23
-rw-r--r--src/mbgl/programs/fill_program.hpp4
-rw-r--r--src/mbgl/programs/line_program.hpp3
-rw-r--r--src/mbgl/programs/program.hpp8
-rw-r--r--src/mbgl/programs/programs.hpp3
-rw-r--r--src/mbgl/programs/raster_program.hpp1
-rw-r--r--src/mbgl/programs/symbol_program.hpp2
-rw-r--r--src/mbgl/renderer/circle_bucket.cpp4
-rw-r--r--src/mbgl/renderer/circle_bucket.hpp6
-rw-r--r--src/mbgl/renderer/debug_bucket.cpp21
-rw-r--r--src/mbgl/renderer/debug_bucket.hpp2
-rw-r--r--src/mbgl/renderer/fill_bucket.cpp10
-rw-r--r--src/mbgl/renderer/fill_bucket.hpp10
-rw-r--r--src/mbgl/renderer/line_bucket.cpp14
-rw-r--r--src/mbgl/renderer/line_bucket.hpp6
-rw-r--r--src/mbgl/renderer/painter.cpp54
-rw-r--r--src/mbgl/renderer/painter.hpp6
-rw-r--r--src/mbgl/renderer/painter_background.cpp18
-rw-r--r--src/mbgl/renderer/painter_circle.cpp15
-rw-r--r--src/mbgl/renderer/painter_clipping.cpp9
-rw-r--r--src/mbgl/renderer/painter_debug.cpp27
-rw-r--r--src/mbgl/renderer/painter_fill.cpp80
-rw-r--r--src/mbgl/renderer/painter_line.cpp15
-rw-r--r--src/mbgl/renderer/painter_raster.cpp9
-rw-r--r--src/mbgl/renderer/painter_symbol.cpp27
-rw-r--r--src/mbgl/renderer/symbol_bucket.hpp16
-rw-r--r--src/mbgl/util/ignore.hpp21
42 files changed, 472 insertions, 359 deletions
diff --git a/cmake/core-files.cmake b/cmake/core-files.cmake
index 7a2ed33281..45305fdd65 100644
--- a/cmake/core-files.cmake
+++ b/cmake/core-files.cmake
@@ -65,7 +65,6 @@ set(MBGL_CORE_FILES
src/mbgl/gl/depth_mode.cpp
src/mbgl/gl/depth_mode.hpp
src/mbgl/gl/draw_mode.hpp
- src/mbgl/gl/drawable.hpp
src/mbgl/gl/extension.cpp
src/mbgl/gl/extension.hpp
src/mbgl/gl/framebuffer.hpp
@@ -73,6 +72,7 @@ set(MBGL_CORE_FILES
src/mbgl/gl/index_buffer.hpp
src/mbgl/gl/object.cpp
src/mbgl/gl/object.hpp
+ src/mbgl/gl/primitives.hpp
src/mbgl/gl/program.hpp
src/mbgl/gl/renderbuffer.hpp
src/mbgl/gl/segment.hpp
@@ -154,6 +154,7 @@ set(MBGL_CORE_FILES
src/mbgl/programs/circle_program.hpp
src/mbgl/programs/collision_box_program.cpp
src/mbgl/programs/collision_box_program.hpp
+ src/mbgl/programs/debug_program.hpp
src/mbgl/programs/fill_program.cpp
src/mbgl/programs/fill_program.hpp
src/mbgl/programs/line_program.cpp
diff --git a/src/mbgl/gl/attribute.hpp b/src/mbgl/gl/attribute.hpp
index 126da38de5..a2b165fa21 100644
--- a/src/mbgl/gl/attribute.hpp
+++ b/src/mbgl/gl/attribute.hpp
@@ -1,6 +1,7 @@
#pragma once
#include <mbgl/gl/types.hpp>
+#include <mbgl/util/ignore.hpp>
#include <cstddef>
#include <functional>
@@ -157,17 +158,14 @@ private:
template <std::size_t... Is>
static std::function<void (std::size_t)> binder(const State& state, std::index_sequence<Is...>) {
return [&state] (std::size_t vertexOffset) {
- noop((bindAttribute(std::get<Is>(state).location,
- std::get<Is>(state).count,
- std::get<Is>(state).type,
- sizeof(Vertex),
- vertexOffset,
- Vertex::attributeOffsets[Is]), 0)...);
+ ignore((bindAttribute(std::get<Is>(state).location,
+ std::get<Is>(state).count,
+ std::get<Is>(state).type,
+ sizeof(Vertex),
+ vertexOffset,
+ Vertex::attributeOffsets[Is]), 0)...);
};
}
-
- // This exists only to provide a varags context for unpacking the assignments in `binder`.
- template <int...> static void noop(int...) {}
};
} // namespace gl
diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp
index b12c77c1a1..c4485ad0fd 100644
--- a/src/mbgl/gl/context.cpp
+++ b/src/mbgl/gl/context.cpp
@@ -533,9 +533,9 @@ void Context::draw(const Drawable& drawable) {
if (drawable.indexBuffer) {
MBGL_CHECK_ERROR(glDrawElements(
static_cast<GLenum>(primitiveType),
- static_cast<GLsizei>(drawable.primitiveSize / sizeof(uint16_t) * segment.primitiveLength),
+ static_cast<GLsizei>(segment.indexLength),
GL_UNSIGNED_SHORT,
- reinterpret_cast<GLvoid*>(drawable.primitiveSize * segment.primitiveOffset)));
+ reinterpret_cast<GLvoid*>(sizeof(uint16_t) * segment.indexOffset)));
} else {
MBGL_CHECK_ERROR(glDrawArrays(
static_cast<GLenum>(primitiveType),
diff --git a/src/mbgl/gl/context.hpp b/src/mbgl/gl/context.hpp
index 2a3fbea33d..154921a1b9 100644
--- a/src/mbgl/gl/context.hpp
+++ b/src/mbgl/gl/context.hpp
@@ -8,9 +8,16 @@
#include <mbgl/gl/framebuffer.hpp>
#include <mbgl/gl/vertex_buffer.hpp>
#include <mbgl/gl/index_buffer.hpp>
-#include <mbgl/gl/drawable.hpp>
+#include <mbgl/gl/types.hpp>
+#include <mbgl/gl/draw_mode.hpp>
+#include <mbgl/gl/depth_mode.hpp>
+#include <mbgl/gl/stencil_mode.hpp>
+#include <mbgl/gl/color_mode.hpp>
+#include <mbgl/gl/segment.hpp>
#include <mbgl/util/noncopyable.hpp>
+
+#include <functional>
#include <memory>
#include <vector>
#include <array>
@@ -33,18 +40,18 @@ public:
UniqueProgram createProgram(ShaderID vertexShader, ShaderID fragmentShader);
UniqueTexture createTexture();
- template <class V>
- VertexBuffer<V> createVertexBuffer(std::vector<V>&& v) {
- return VertexBuffer<V> {
- v.size(),
- createVertexBuffer(v.data(), v.size() * sizeof(V))
+ template <class Vertex, class DrawMode>
+ VertexBuffer<Vertex, DrawMode> createVertexBuffer(VertexVector<Vertex, DrawMode>&& v) {
+ return VertexBuffer<Vertex, DrawMode> {
+ v.vertexSize(),
+ createVertexBuffer(v.data(), v.byteSize())
};
}
- template <class P>
- IndexBuffer<P> createIndexBuffer(std::vector<P>&& v) {
- return IndexBuffer<P> {
- createIndexBuffer(v.data(), v.size() * sizeof(P))
+ template <class DrawMode>
+ IndexBuffer<DrawMode> createIndexBuffer(IndexVector<DrawMode>&& v) {
+ return IndexBuffer<DrawMode> {
+ createIndexBuffer(v.data(), v.byteSize())
};
}
@@ -111,6 +118,19 @@ public:
optional<float> depth,
optional<int32_t> stencil);
+ struct Drawable {
+ DrawMode drawMode;
+ DepthMode depthMode;
+ StencilMode stencilMode;
+ ColorMode colorMode;
+ gl::ProgramID program;
+ gl::BufferID vertexBuffer;
+ gl::BufferID indexBuffer;
+ const std::vector<Segment>& segments;
+ std::function<void ()> bindUniforms;
+ std::function<void (std::size_t)> bindAttributes;
+ };
+
void draw(const Drawable&);
void setDepthMode(const DepthMode&);
diff --git a/src/mbgl/gl/draw_mode.hpp b/src/mbgl/gl/draw_mode.hpp
index a379162210..8f7db0a3fa 100644
--- a/src/mbgl/gl/draw_mode.hpp
+++ b/src/mbgl/gl/draw_mode.hpp
@@ -1,5 +1,6 @@
#pragma once
+#include <mbgl/gl/primitives.hpp>
#include <mbgl/util/variant.hpp>
namespace mbgl {
@@ -7,21 +8,50 @@ namespace gl {
class Points {
public:
+ using Primitive = Point;
+ static constexpr std::size_t bufferGroupSize = 1;
+
float pointSize;
};
class Lines {
public:
+ using Primitive = Line;
+ static constexpr std::size_t bufferGroupSize = 2;
+
float lineWidth;
};
class LineStrip {
public:
+ // LineStrip is a form of "Line" rendering, but the element buffer
+ // cannot be grouped into logical elements beyond a single Point.
+ using Primitive = Line;
+ static constexpr std::size_t bufferGroupSize = 1;
+
float lineWidth;
};
-class Triangles {};
-class TriangleStrip {};
+class Triangles {
+public:
+ using Primitive = Triangle;
+ static constexpr std::size_t bufferGroupSize = 3;
+};
+
+class TriangleStrip {
+public:
+ // TriangleStrip is a form of "Triangle" rendering, but the element buffer
+ // cannot be grouped into logical elements beyond a single Point.
+ using Primitive = Triangle;
+ static constexpr std::size_t bufferGroupSize = 1;
+};
+
+// Special draw mode for use with VertexVector<Indexed, Vertex>, in which
+// case the true draw mode is denoted by the IndexVector type.
+class Indexed {
+public:
+ static constexpr std::size_t bufferGroupSize = 1;
+};
using DrawMode = variant<
Points,
diff --git a/src/mbgl/gl/drawable.hpp b/src/mbgl/gl/drawable.hpp
deleted file mode 100644
index 747d8facf0..0000000000
--- a/src/mbgl/gl/drawable.hpp
+++ /dev/null
@@ -1,124 +0,0 @@
-#pragma once
-
-#include <mbgl/gl/types.hpp>
-#include <mbgl/gl/draw_mode.hpp>
-#include <mbgl/gl/depth_mode.hpp>
-#include <mbgl/gl/stencil_mode.hpp>
-#include <mbgl/gl/color_mode.hpp>
-#include <mbgl/gl/vertex_buffer.hpp>
-#include <mbgl/gl/index_buffer.hpp>
-#include <mbgl/gl/attribute.hpp>
-#include <mbgl/gl/uniform.hpp>
-#include <mbgl/gl/segment.hpp>
-
-#include <cstddef>
-#include <functional>
-#include <limits>
-#include <vector>
-
-namespace mbgl {
-namespace gl {
-
-template <class Vertex>
-class UnindexedVertices {
-public:
- using VertexType = Vertex;
-
- UnindexedVertices(DrawMode drawMode_, const VertexBuffer<Vertex>& vertexBuffer_)
- : drawMode(std::move(drawMode_)),
- vertexBuffer(vertexBuffer_.buffer),
- segments({{ 0, 0, vertexBuffer_.vertexCount, 0 }}) {}
-
- DrawMode drawMode;
- gl::BufferID vertexBuffer;
- static constexpr std::size_t vertexSize = sizeof(Vertex);
- static constexpr gl::BufferID indexBuffer = 0;
- static constexpr std::size_t primitiveSize = 0;
- std::vector<Segment> segments;
-};
-
-template <class DrawMode, class Vertex, class...Args>
-auto Unindexed(const VertexBuffer<Vertex>& vertexBuffer,
- Args&&... drawModeArguments) {
- return UnindexedVertices<Vertex>(
- DrawMode { std::forward<Args>(drawModeArguments)... },
- vertexBuffer);
-}
-
-template <class Vertex, class Primitive>
-class SegmentedVertices {
-public:
- using VertexType = Vertex;
-
- SegmentedVertices(DrawMode drawMode_,
- const VertexBuffer<Vertex>& vertexBuffer_,
- const IndexBuffer<Primitive>& indexBuffer_,
- const std::vector<Segment>& segments_)
- : drawMode(std::move(drawMode_)),
- vertexBuffer(vertexBuffer_.buffer),
- indexBuffer(indexBuffer_.buffer),
- segments(segments_) {}
-
- DrawMode drawMode;
- gl::BufferID vertexBuffer;
- static constexpr std::size_t vertexSize = sizeof(Vertex);
- gl::BufferID indexBuffer;
- static constexpr std::size_t primitiveSize = sizeof(Primitive);
- const std::vector<Segment>& segments;
-};
-
-template <class DrawMode, class Vertex, class Primitive, class...Args>
-auto Segmented(const VertexBuffer<Vertex>& vertexBuffer,
- const IndexBuffer<Primitive>& indexBuffer,
- const std::vector<Segment>& segments,
- Args&&... drawModeArguments) {
- static_assert(std::is_same<typename Primitive::DrawMode, DrawMode>::value, "primitive mode mismatch");
- return SegmentedVertices<Vertex, Primitive>(
- DrawMode { std::forward<Args>(drawModeArguments)... },
- vertexBuffer,
- indexBuffer,
- segments);
-}
-
-class Drawable {
-public:
- template <class Program, class Subject>
- Drawable(DepthMode depthMode_,
- StencilMode stencilMode_,
- ColorMode colorMode_,
- Program& program_,
- typename Program::UniformValues&& uniformValues,
- const Subject& subject)
- : drawMode(subject.drawMode),
- depthMode(std::move(depthMode_)),
- stencilMode(std::move(stencilMode_)),
- colorMode(std::move(colorMode_)),
- program(program_.program),
- vertexBuffer(subject.vertexBuffer),
- vertexSize(subject.vertexSize),
- indexBuffer(subject.indexBuffer),
- primitiveSize(subject.primitiveSize),
- segments(subject.segments),
- bindUniforms(Program::Uniforms::binder(program_.uniformsState, std::move(uniformValues))),
- bindAttributes(Program::Attributes::binder(program_.attributesState))
- {
- static_assert(std::is_standard_layout<typename Program::Vertex>::value, "vertex type must use standard layout");
- static_assert(std::is_same<typename Program::Vertex, typename Subject::VertexType>::value, "vertex type mismatch");
- }
-
- DrawMode drawMode;
- DepthMode depthMode;
- StencilMode stencilMode;
- ColorMode colorMode;
- gl::ProgramID program;
- gl::BufferID vertexBuffer;
- std::size_t vertexSize;
- gl::BufferID indexBuffer;
- std::size_t primitiveSize;
- const std::vector<Segment>& segments;
- std::function<void ()> bindUniforms;
- std::function<void (std::size_t)> bindAttributes;
-};
-
-} // namespace gl
-} // namespace mbgl
diff --git a/src/mbgl/gl/index_buffer.hpp b/src/mbgl/gl/index_buffer.hpp
index 5d8630b902..8b40bf68c3 100644
--- a/src/mbgl/gl/index_buffer.hpp
+++ b/src/mbgl/gl/index_buffer.hpp
@@ -2,39 +2,37 @@
#include <mbgl/gl/object.hpp>
#include <mbgl/gl/draw_mode.hpp>
+#include <mbgl/util/ignore.hpp>
+
+#include <vector>
namespace mbgl {
namespace gl {
-class Line {
+template <class DrawMode>
+class IndexVector {
public:
- using DrawMode = Lines;
-
- Line(uint16_t a_, uint16_t b_)
- : a(a_), b(b_) {}
+ static constexpr std::size_t groupSize = DrawMode::bufferGroupSize;
- uint16_t a;
- uint16_t b;
-};
+ template <class... Args>
+ void emplace_back(Args&&... args) {
+ static_assert(sizeof...(args) == groupSize, "wrong buffer element count");
+ ignore({(v.emplace_back(std::forward<Args>(args)), 0)...});
+ }
-class Triangle {
-public:
- using DrawMode = Triangles;
+ std::size_t indexSize() const { return v.size(); }
+ std::size_t byteSize() const { return v.size() * sizeof(uint16_t); }
- Triangle(uint16_t a_, uint16_t b_, uint16_t c_)
- : a(a_), b(b_), c(c_) {}
+ bool empty() const { return v.empty(); }
+ const uint16_t* data() const { return v.data(); }
- uint16_t a;
- uint16_t b;
- uint16_t c;
+private:
+ std::vector<uint16_t> v;
};
-template <class Primitive>
+template <class DrawMode>
class IndexBuffer {
public:
- static_assert(std::is_same<Primitive, Line>::value || std::is_same<Primitive, Triangle>::value,
- "primitive must be Line or Triangle");
- static constexpr std::size_t primitiveSize = sizeof(Primitive);
UniqueBuffer buffer;
};
diff --git a/src/mbgl/gl/primitives.hpp b/src/mbgl/gl/primitives.hpp
new file mode 100644
index 0000000000..fe6b1b2e5b
--- /dev/null
+++ b/src/mbgl/gl/primitives.hpp
@@ -0,0 +1,22 @@
+#pragma once
+
+namespace mbgl {
+namespace gl {
+
+class Point {
+public:
+ static constexpr std::size_t vertexCount = 1;
+};
+
+class Line {
+public:
+ static constexpr std::size_t vertexCount = 2;
+};
+
+class Triangle {
+public:
+ static constexpr std::size_t vertexCount = 3;
+};
+
+} // namespace gl
+} // namespace mbgl
diff --git a/src/mbgl/gl/program.hpp b/src/mbgl/gl/program.hpp
index ea4dbcc1df..929237037b 100644
--- a/src/mbgl/gl/program.hpp
+++ b/src/mbgl/gl/program.hpp
@@ -3,21 +3,28 @@
#include <mbgl/gl/types.hpp>
#include <mbgl/gl/object.hpp>
#include <mbgl/gl/context.hpp>
+#include <mbgl/gl/vertex_buffer.hpp>
+#include <mbgl/gl/index_buffer.hpp>
+#include <mbgl/gl/attribute.hpp>
+#include <mbgl/gl/uniform.hpp>
#include <string>
namespace mbgl {
namespace gl {
-template <class As, class Us>
+template <class P, class As, class Us>
class Program {
public:
+ using Primitive = P;
using Attributes = As;
- using Vertex = typename Attributes::Vertex;
-
using Uniforms = Us;
+
+ using Vertex = typename Attributes::Vertex;
using UniformValues = typename Uniforms::Values;
+ static_assert(std::is_standard_layout<Vertex>::value, "vertex type must use standard layout");
+
Program(Context& context, const std::string& vertexSource, const std::string& fragmentSource)
: vertexShader(context.createShader(ShaderType::Vertex, vertexSource)),
fragmentShader(context.createShader(ShaderType::Fragment, fragmentSource)),
@@ -25,6 +32,57 @@ public:
attributesState(Attributes::state(program)),
uniformsState(Uniforms::state(program)) {}
+ // Indexed drawing.
+ template <class DrawMode>
+ void draw(Context& context,
+ DrawMode drawMode,
+ DepthMode depthMode,
+ StencilMode stencilMode,
+ ColorMode colorMode,
+ UniformValues&& uniformValues,
+ const VertexBuffer<Vertex>& vertexBuffer,
+ const IndexBuffer<DrawMode>& indexBuffer,
+ const std::vector<Segment>& segments) {
+ static_assert(std::is_same<Primitive, typename DrawMode::Primitive>::value, "incompatible draw mode");
+ context.draw({
+ std::move(drawMode),
+ std::move(depthMode),
+ std::move(stencilMode),
+ std::move(colorMode),
+ program,
+ vertexBuffer.buffer,
+ indexBuffer.buffer,
+ segments,
+ Uniforms::binder(uniformsState, std::move(uniformValues)),
+ Attributes::binder(attributesState)
+ });
+ }
+
+ // Unindexed drawing.
+ template <class DrawMode>
+ void draw(Context& context,
+ DrawMode drawMode,
+ DepthMode depthMode,
+ StencilMode stencilMode,
+ ColorMode colorMode,
+ UniformValues&& uniformValues,
+ const VertexBuffer<Vertex, DrawMode>& vertexBuffer) {
+ static_assert(std::is_same<Primitive, typename DrawMode::Primitive>::value, "incompatible draw mode");
+ context.draw({
+ std::move(drawMode),
+ std::move(depthMode),
+ std::move(stencilMode),
+ std::move(colorMode),
+ program,
+ vertexBuffer.buffer,
+ 0,
+ {{ 0, 0, vertexBuffer.vertexCount, 0 }},
+ Uniforms::binder(uniformsState, std::move(uniformValues)),
+ Attributes::binder(attributesState)
+ });
+ }
+
+private:
UniqueShader vertexShader;
UniqueShader fragmentShader;
UniqueProgram program;
diff --git a/src/mbgl/gl/segment.hpp b/src/mbgl/gl/segment.hpp
index 648d02e902..f65f2a5f7e 100644
--- a/src/mbgl/gl/segment.hpp
+++ b/src/mbgl/gl/segment.hpp
@@ -8,19 +8,19 @@ namespace gl {
class Segment {
public:
Segment(std::size_t vertexOffset_,
- std::size_t primitiveOffset_,
+ std::size_t indexOffset_,
std::size_t vertexLength_ = 0,
- std::size_t primitiveLength_ = 0)
+ std::size_t indexLength_ = 0)
: vertexOffset(vertexOffset_),
- primitiveOffset(primitiveOffset_),
+ indexOffset(indexOffset_),
vertexLength(vertexLength_),
- primitiveLength(primitiveLength_) {}
+ indexLength(indexLength_) {}
const std::size_t vertexOffset;
- const std::size_t primitiveOffset;
+ const std::size_t indexOffset;
std::size_t vertexLength;
- std::size_t primitiveLength;
+ std::size_t indexLength;
};
} // namespace gl
diff --git a/src/mbgl/gl/uniform.hpp b/src/mbgl/gl/uniform.hpp
index 90ca16e46f..df4de0c75a 100644
--- a/src/mbgl/gl/uniform.hpp
+++ b/src/mbgl/gl/uniform.hpp
@@ -2,6 +2,7 @@
#include <mbgl/gl/types.hpp>
#include <mbgl/util/optional.hpp>
+#include <mbgl/util/ignore.hpp>
#include <array>
#include <functional>
@@ -71,13 +72,9 @@ public:
static std::function<void ()> binder(State& state, Values&& values_) {
return [&state, values = std::move(values_)] () mutable {
- noop((std::get<typename Us::State>(state) = std::get<typename Us::Value>(values), 0)...);
+ ignore((std::get<typename Us::State>(state) = std::get<typename Us::Value>(values), 0)...);
};
}
-
-private:
- // This exists only to provide a varags context for unpacking the assignments in `binder`.
- template <int...> static void noop(int...) {}
};
} // namespace gl
diff --git a/src/mbgl/gl/vertex_buffer.hpp b/src/mbgl/gl/vertex_buffer.hpp
index c77a9a4213..9d5532beab 100644
--- a/src/mbgl/gl/vertex_buffer.hpp
+++ b/src/mbgl/gl/vertex_buffer.hpp
@@ -1,14 +1,43 @@
#pragma once
#include <mbgl/gl/object.hpp>
+#include <mbgl/gl/primitives.hpp>
+#include <mbgl/gl/draw_mode.hpp>
+#include <mbgl/util/ignore.hpp>
+
+#include <vector>
namespace mbgl {
namespace gl {
-template <class Vertex>
+template <class V, class DrawMode = Indexed>
+class VertexVector {
+public:
+ using Vertex = V;
+ static constexpr std::size_t groupSize = DrawMode::bufferGroupSize;
+
+ template <class... Args>
+ void emplace_back(Args&&... args) {
+ static_assert(sizeof...(args) == groupSize, "wrong buffer element count");
+ ignore({(v.emplace_back(std::forward<Args>(args)), 0)...});
+ }
+
+ std::size_t vertexSize() const { return v.size(); }
+ std::size_t byteSize() const { return v.size() * sizeof(Vertex); }
+
+ bool empty() const { return v.empty(); }
+ const Vertex* data() const { return v.data(); }
+
+private:
+ std::vector<Vertex> v;
+};
+
+template <class V, class DrawMode = Indexed>
class VertexBuffer {
public:
+ using Vertex = V;
static constexpr std::size_t vertexSize = sizeof(Vertex);
+
std::size_t vertexCount;
UniqueBuffer buffer;
};
diff --git a/src/mbgl/layout/symbol_layout.cpp b/src/mbgl/layout/symbol_layout.cpp
index c2f8426785..932745aa57 100644
--- a/src/mbgl/layout/symbol_layout.cpp
+++ b/src/mbgl/layout/symbol_layout.cpp
@@ -449,7 +449,7 @@ void SymbolLayout::addSymbols(Buffer &buffer, const SymbolQuads &symbols, float
}
if (buffer.segments.empty() || buffer.segments.back().vertexLength + vertexLength > std::numeric_limits<uint16_t>::max()) {
- buffer.segments.emplace_back(buffer.vertices.size(), buffer.triangles.size());
+ buffer.segments.emplace_back(buffer.vertices.vertexSize(), buffer.triangles.indexSize());
}
// We're generating triangle fans, so we always start with the first
@@ -476,7 +476,7 @@ void SymbolLayout::addSymbols(Buffer &buffer, const SymbolQuads &symbols, float
buffer.triangles.emplace_back(index + 1, index + 2, index + 3);
segment.vertexLength += vertexLength;
- segment.primitiveLength += 2;
+ segment.indexLength += 6;
}
}
@@ -507,14 +507,14 @@ void SymbolLayout::addToDebugBuffers(CollisionTile& collisionTile, SymbolBucket&
const float maxZoom = util::clamp(zoom + util::log2(box.maxScale), util::MIN_ZOOM_F, util::MAX_ZOOM_F);
const float placementZoom = util::clamp(zoom + util::log2(box.placementScale), util::MIN_ZOOM_F, util::MAX_ZOOM_F);
- collisionBox.vertices.emplace_back(CollisionBoxProgram::vertex(anchor, tl, maxZoom, placementZoom));
- collisionBox.vertices.emplace_back(CollisionBoxProgram::vertex(anchor, tr, maxZoom, placementZoom));
- collisionBox.vertices.emplace_back(CollisionBoxProgram::vertex(anchor, tr, maxZoom, placementZoom));
- collisionBox.vertices.emplace_back(CollisionBoxProgram::vertex(anchor, br, maxZoom, placementZoom));
- collisionBox.vertices.emplace_back(CollisionBoxProgram::vertex(anchor, br, maxZoom, placementZoom));
- collisionBox.vertices.emplace_back(CollisionBoxProgram::vertex(anchor, bl, maxZoom, placementZoom));
- collisionBox.vertices.emplace_back(CollisionBoxProgram::vertex(anchor, bl, maxZoom, placementZoom));
- collisionBox.vertices.emplace_back(CollisionBoxProgram::vertex(anchor, tl, maxZoom, placementZoom));
+ collisionBox.vertices.emplace_back(CollisionBoxProgram::vertex(anchor, tl, maxZoom, placementZoom),
+ CollisionBoxProgram::vertex(anchor, tr, maxZoom, placementZoom));
+ collisionBox.vertices.emplace_back(CollisionBoxProgram::vertex(anchor, tr, maxZoom, placementZoom),
+ CollisionBoxProgram::vertex(anchor, br, maxZoom, placementZoom));
+ collisionBox.vertices.emplace_back(CollisionBoxProgram::vertex(anchor, br, maxZoom, placementZoom),
+ CollisionBoxProgram::vertex(anchor, bl, maxZoom, placementZoom));
+ collisionBox.vertices.emplace_back(CollisionBoxProgram::vertex(anchor, bl, maxZoom, placementZoom),
+ CollisionBoxProgram::vertex(anchor, tl, maxZoom, placementZoom));
}
};
populateCollisionBox(symbolInstance.textCollisionFeature);
diff --git a/src/mbgl/programs/circle_program.hpp b/src/mbgl/programs/circle_program.hpp
index 690608a438..75c030b1c8 100644
--- a/src/mbgl/programs/circle_program.hpp
+++ b/src/mbgl/programs/circle_program.hpp
@@ -16,6 +16,7 @@ MBGL_DEFINE_UNIFORM_SCALAR(float, u_devicepixelratio);
class CircleProgram : public Program<
shaders::circle,
+ gl::Triangle,
gl::Attributes<
attributes::a_pos>,
gl::Uniforms<
diff --git a/src/mbgl/programs/collision_box_program.hpp b/src/mbgl/programs/collision_box_program.hpp
index 66b1284621..5eda3fefb0 100644
--- a/src/mbgl/programs/collision_box_program.hpp
+++ b/src/mbgl/programs/collision_box_program.hpp
@@ -17,6 +17,7 @@ MBGL_DEFINE_UNIFORM_SCALAR(float, u_maxzoom);
class CollisionBoxProgram : public Program<
shaders::collision_box,
+ gl::Line,
gl::Attributes<
attributes::a_pos,
attributes::a_extrude,
diff --git a/src/mbgl/programs/debug_program.hpp b/src/mbgl/programs/debug_program.hpp
new file mode 100644
index 0000000000..3596dc1f7e
--- /dev/null
+++ b/src/mbgl/programs/debug_program.hpp
@@ -0,0 +1,23 @@
+#pragma once
+
+#include <mbgl/programs/program.hpp>
+#include <mbgl/programs/attributes.hpp>
+#include <mbgl/programs/uniforms.hpp>
+#include <mbgl/shader/debug.hpp>
+
+namespace mbgl {
+
+class DebugProgram : public Program<
+ shaders::debug,
+ gl::Line,
+ gl::Attributes<
+ attributes::a_pos>,
+ gl::Uniforms<
+ uniforms::u_matrix,
+ uniforms::u_color>>
+{
+public:
+ using Program::Program;
+};
+
+} // namespace mbgl
diff --git a/src/mbgl/programs/fill_program.hpp b/src/mbgl/programs/fill_program.hpp
index 3f738527c8..d885215c59 100644
--- a/src/mbgl/programs/fill_program.hpp
+++ b/src/mbgl/programs/fill_program.hpp
@@ -86,6 +86,7 @@ struct FillPatternUniforms : gl::Uniforms<
class FillProgram : public Program<
shaders::fill,
+ gl::Triangle,
FillAttributes,
FillUniforms>
{
@@ -94,6 +95,7 @@ class FillProgram : public Program<
class FillPatternProgram : public Program<
shaders::fill_pattern,
+ gl::Triangle,
FillAttributes,
FillPatternUniforms>
{
@@ -102,6 +104,7 @@ class FillPatternProgram : public Program<
class FillOutlineProgram : public Program<
shaders::fill_outline,
+ gl::Line,
FillAttributes,
FillUniforms>
{
@@ -110,6 +113,7 @@ class FillOutlineProgram : public Program<
class FillOutlinePatternProgram : public Program<
shaders::fill_outline_pattern,
+ gl::Line,
FillAttributes,
FillPatternUniforms>
{
diff --git a/src/mbgl/programs/line_program.hpp b/src/mbgl/programs/line_program.hpp
index 960438f4cd..07ae35b8ed 100644
--- a/src/mbgl/programs/line_program.hpp
+++ b/src/mbgl/programs/line_program.hpp
@@ -88,6 +88,7 @@ using LineVertex = LineAttributes::Vertex;
class LineProgram : public Program<
shaders::line,
+ gl::Triangle,
LineAttributes,
gl::Uniforms<
uniforms::u_matrix,
@@ -113,6 +114,7 @@ public:
class LinePatternProgram : public Program<
shaders::line_pattern,
+ gl::Triangle,
LineAttributes,
gl::Uniforms<
uniforms::u_matrix,
@@ -147,6 +149,7 @@ public:
class LineSDFProgram : public Program<
shaders::line_sdf,
+ gl::Triangle,
LineAttributes,
gl::Uniforms<
uniforms::u_matrix,
diff --git a/src/mbgl/programs/program.hpp b/src/mbgl/programs/program.hpp
index 9f154b051a..fa41d43e5c 100644
--- a/src/mbgl/programs/program.hpp
+++ b/src/mbgl/programs/program.hpp
@@ -11,11 +11,13 @@ enum class ProgramDefines : bool {
Overdraw = true,
};
-template <class Shaders, class As, class Us>
-class Program : public gl::Program<As, Us> {
+template <class Shaders, class Primitive, class Attributes, class Uniforms>
+class Program : public gl::Program<Primitive, Attributes, Uniforms> {
public:
+ using ParentType = gl::Program<Primitive, Attributes, Uniforms>;
+
Program(gl::Context& context, ProgramDefines defines)
- : gl::Program<As, Us>(context, Shaders::vertexSource, fragmentSource(defines))
+ : ParentType(context, Shaders::vertexSource, fragmentSource(defines))
{}
static std::string fragmentSource(ProgramDefines defines) {
diff --git a/src/mbgl/programs/programs.hpp b/src/mbgl/programs/programs.hpp
index aebafaec62..53ed26e969 100644
--- a/src/mbgl/programs/programs.hpp
+++ b/src/mbgl/programs/programs.hpp
@@ -5,6 +5,7 @@
#include <mbgl/programs/line_program.hpp>
#include <mbgl/programs/raster_program.hpp>
#include <mbgl/programs/symbol_program.hpp>
+#include <mbgl/programs/debug_program.hpp>
#include <mbgl/programs/collision_box_program.hpp>
namespace mbgl {
@@ -24,6 +25,7 @@ public:
symbolIcon(context, defines),
symbolIconSDF(context, defines),
symbolGlyph(context, defines),
+ debug(context, ProgramDefines::None),
collisionBox(context, ProgramDefines::None) {
}
@@ -40,6 +42,7 @@ public:
SymbolSDFProgram symbolIconSDF;
SymbolSDFProgram symbolGlyph;
+ DebugProgram debug;
CollisionBoxProgram collisionBox;
};
diff --git a/src/mbgl/programs/raster_program.hpp b/src/mbgl/programs/raster_program.hpp
index 1e9a0cdb6a..1bab2d5765 100644
--- a/src/mbgl/programs/raster_program.hpp
+++ b/src/mbgl/programs/raster_program.hpp
@@ -25,6 +25,7 @@ MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_tl_parent);
class RasterProgram : public Program<
shaders::raster,
+ gl::Triangle,
gl::Attributes<
attributes::a_pos,
attributes::a_texture_pos>,
diff --git a/src/mbgl/programs/symbol_program.hpp b/src/mbgl/programs/symbol_program.hpp
index eb8c56b326..be987551c0 100644
--- a/src/mbgl/programs/symbol_program.hpp
+++ b/src/mbgl/programs/symbol_program.hpp
@@ -72,6 +72,7 @@ using SymbolVertex = SymbolAttributes::Vertex;
class SymbolIconProgram : public Program<
shaders::symbol_icon,
+ gl::Triangle,
SymbolAttributes,
gl::Uniforms<
uniforms::u_matrix,
@@ -95,6 +96,7 @@ public:
class SymbolSDFProgram : public Program<
shaders::symbol_sdf,
+ gl::Triangle,
SymbolAttributes,
gl::Uniforms<
uniforms::u_matrix,
diff --git a/src/mbgl/renderer/circle_bucket.cpp b/src/mbgl/renderer/circle_bucket.cpp
index 08f2a144a1..ba2285c4eb 100644
--- a/src/mbgl/renderer/circle_bucket.cpp
+++ b/src/mbgl/renderer/circle_bucket.cpp
@@ -46,7 +46,7 @@ void CircleBucket::addGeometry(const GeometryCollection& geometryCollection) {
if (segments.empty() || segments.back().vertexLength + vertexLength > std::numeric_limits<uint16_t>::max()) {
// Move to a new segments because the old one can't hold the geometry.
- segments.emplace_back(vertices.size(), triangles.size());
+ segments.emplace_back(vertices.vertexSize(), triangles.indexSize());
}
// this geometry will be of the Point type, and we'll derive
@@ -73,7 +73,7 @@ void CircleBucket::addGeometry(const GeometryCollection& geometryCollection) {
triangles.emplace_back(index, index + 3, index + 2);
segment.vertexLength += vertexLength;
- segment.primitiveLength += 2;
+ segment.indexLength += 6;
}
}
}
diff --git a/src/mbgl/renderer/circle_bucket.hpp b/src/mbgl/renderer/circle_bucket.hpp
index d5df06f110..a93b052d68 100644
--- a/src/mbgl/renderer/circle_bucket.hpp
+++ b/src/mbgl/renderer/circle_bucket.hpp
@@ -20,12 +20,12 @@ public:
bool hasData() const override;
void addGeometry(const GeometryCollection&);
- std::vector<CircleVertex> vertices;
- std::vector<gl::Triangle> triangles;
+ gl::VertexVector<CircleVertex> vertices;
+ gl::IndexVector<gl::Triangles> triangles;
std::vector<gl::Segment> segments;
optional<gl::VertexBuffer<CircleVertex>> vertexBuffer;
- optional<gl::IndexBuffer<gl::Triangle>> indexBuffer;
+ optional<gl::IndexBuffer<gl::Triangles>> indexBuffer;
const MapMode mode;
};
diff --git a/src/mbgl/renderer/debug_bucket.cpp b/src/mbgl/renderer/debug_bucket.cpp
index 931d1bf30d..4beb16a996 100644
--- a/src/mbgl/renderer/debug_bucket.cpp
+++ b/src/mbgl/renderer/debug_bucket.cpp
@@ -10,13 +10,14 @@
namespace mbgl {
-std::vector<FillVertex> buildTextVertices(const OverscaledTileID& id,
- const bool renderable,
- const bool complete,
- optional<Timestamp> modified,
- optional<Timestamp> expires,
- MapDebugOptions debugMode) {
- std::vector<FillVertex> textPoints;
+gl::VertexVector<FillVertex, gl::Lines>
+buildTextVertices(const OverscaledTileID& id,
+ const bool renderable,
+ const bool complete,
+ optional<Timestamp> modified,
+ optional<Timestamp> expires,
+ MapDebugOptions debugMode) {
+ gl::VertexVector<FillVertex, gl::Lines> textLines;
auto addText = [&] (const std::string& text, double left, double baseline, double scale) {
for (uint8_t c : text) {
@@ -36,8 +37,8 @@ std::vector<FillVertex> buildTextVertices(const OverscaledTileID& id,
};
if (prev) {
- textPoints.emplace_back(FillAttributes::vertex(*prev));
- textPoints.emplace_back(FillAttributes::vertex(p));
+ textLines.emplace_back(FillAttributes::vertex(*prev),
+ FillAttributes::vertex(p));
}
prev = p;
@@ -64,7 +65,7 @@ std::vector<FillVertex> buildTextVertices(const OverscaledTileID& id,
addText(expiresText, 50, baseline + 200, 5);
}
- return textPoints;
+ return textLines;
}
DebugBucket::DebugBucket(const OverscaledTileID& id,
diff --git a/src/mbgl/renderer/debug_bucket.hpp b/src/mbgl/renderer/debug_bucket.hpp
index 9b19e7f949..4c173786ae 100644
--- a/src/mbgl/renderer/debug_bucket.hpp
+++ b/src/mbgl/renderer/debug_bucket.hpp
@@ -32,7 +32,7 @@ public:
const optional<Timestamp> expires;
const MapDebugOptions debugMode;
- gl::VertexBuffer<FillVertex> vertexBuffer;
+ gl::VertexBuffer<FillVertex, gl::Lines> vertexBuffer;
};
} // namespace mbgl
diff --git a/src/mbgl/renderer/fill_bucket.cpp b/src/mbgl/renderer/fill_bucket.cpp
index 2eee8f2d6d..96e44d6903 100644
--- a/src/mbgl/renderer/fill_bucket.cpp
+++ b/src/mbgl/renderer/fill_bucket.cpp
@@ -39,7 +39,7 @@ void FillBucket::addGeometry(const GeometryCollection& geometry) {
throw GeometryTooLongException();
}
- std::size_t startVertices = vertices.size();
+ std::size_t startVertices = vertices.vertexSize();
for (const auto& ring : polygon) {
std::size_t nVertices = ring.size();
@@ -48,7 +48,7 @@ void FillBucket::addGeometry(const GeometryCollection& geometry) {
continue;
if (lineSegments.empty() || lineSegments.back().vertexLength + nVertices > std::numeric_limits<uint16_t>::max()) {
- lineSegments.emplace_back(vertices.size(), lines.size());
+ lineSegments.emplace_back(vertices.vertexSize(), lines.indexSize());
}
auto& lineSegment = lineSegments.back();
@@ -64,7 +64,7 @@ void FillBucket::addGeometry(const GeometryCollection& geometry) {
}
lineSegment.vertexLength += nVertices;
- lineSegment.primitiveLength += nVertices;
+ lineSegment.indexLength += nVertices * 2;
}
std::vector<uint32_t> indices = mapbox::earcut(polygon);
@@ -73,7 +73,7 @@ void FillBucket::addGeometry(const GeometryCollection& geometry) {
assert(nIndicies % 3 == 0);
if (triangleSegments.empty() || triangleSegments.back().vertexLength + totalVertices > std::numeric_limits<uint16_t>::max()) {
- triangleSegments.emplace_back(startVertices, triangles.size());
+ triangleSegments.emplace_back(startVertices, triangles.indexSize());
}
auto& triangleSegment = triangleSegments.back();
@@ -87,7 +87,7 @@ void FillBucket::addGeometry(const GeometryCollection& geometry) {
}
triangleSegment.vertexLength += totalVertices;
- triangleSegment.primitiveLength += nIndicies / 3;
+ triangleSegment.indexLength += nIndicies;
}
}
diff --git a/src/mbgl/renderer/fill_bucket.hpp b/src/mbgl/renderer/fill_bucket.hpp
index b2c549a758..4ea558b629 100644
--- a/src/mbgl/renderer/fill_bucket.hpp
+++ b/src/mbgl/renderer/fill_bucket.hpp
@@ -19,15 +19,15 @@ public:
void addGeometry(const GeometryCollection&);
- std::vector<FillVertex> vertices;
- std::vector<gl::Line> lines;
- std::vector<gl::Triangle> triangles;
+ gl::VertexVector<FillVertex> vertices;
+ gl::IndexVector<gl::Lines> lines;
+ gl::IndexVector<gl::Triangles> triangles;
std::vector<gl::Segment> lineSegments;
std::vector<gl::Segment> triangleSegments;
optional<gl::VertexBuffer<FillVertex>> vertexBuffer;
- optional<gl::IndexBuffer<gl::Line>> lineIndexBuffer;
- optional<gl::IndexBuffer<gl::Triangle>> triangleIndexBuffer;
+ optional<gl::IndexBuffer<gl::Lines>> lineIndexBuffer;
+ optional<gl::IndexBuffer<gl::Triangles>> triangleIndexBuffer;
};
} // namespace mbgl
diff --git a/src/mbgl/renderer/line_bucket.cpp b/src/mbgl/renderer/line_bucket.cpp
index 1db075652c..554fef5ca7 100644
--- a/src/mbgl/renderer/line_bucket.cpp
+++ b/src/mbgl/renderer/line_bucket.cpp
@@ -96,7 +96,7 @@ void LineBucket::addGeometry(const GeometryCoordinates& coordinates) {
nextNormal = util::perp(util::unit(convertPoint<double>(firstCoordinate - *currentCoordinate)));
}
- const std::size_t startVertex = vertices.size();
+ const std::size_t startVertex = vertices.vertexSize();
std::vector<TriangleElement> triangleStore;
for (std::size_t i = 0; i < len; ++i) {
@@ -345,11 +345,11 @@ void LineBucket::addGeometry(const GeometryCoordinates& coordinates) {
startOfLine = false;
}
- const std::size_t endVertex = vertices.size();
+ const std::size_t endVertex = vertices.vertexSize();
const std::size_t vertexCount = endVertex - startVertex;
if (segments.empty() || segments.back().vertexLength + vertexCount > std::numeric_limits<uint16_t>::max()) {
- segments.emplace_back(startVertex, triangles.size());
+ segments.emplace_back(startVertex, triangles.indexSize());
}
auto& segment = segments.back();
@@ -361,7 +361,7 @@ void LineBucket::addGeometry(const GeometryCoordinates& coordinates) {
}
segment.vertexLength += vertexCount;
- segment.primitiveLength += triangleStore.size();
+ segment.indexLength += triangleStore.size() * 3;
}
void LineBucket::addCurrentVertex(const GeometryCoordinate& currentCoordinate,
@@ -376,7 +376,7 @@ void LineBucket::addCurrentVertex(const GeometryCoordinate& currentCoordinate,
if (endLeft)
extrude = extrude - (util::perp(normal) * endLeft);
vertices.emplace_back(LineAttributes::vertex(currentCoordinate, extrude, { round, false }, endLeft, distance * LINE_DISTANCE_SCALE));
- e3 = vertices.size() - 1 - startVertex;
+ e3 = vertices.vertexSize() - 1 - startVertex;
if (e1 >= 0 && e2 >= 0) {
triangleStore.emplace_back(e1, e2, e3);
}
@@ -387,7 +387,7 @@ void LineBucket::addCurrentVertex(const GeometryCoordinate& currentCoordinate,
if (endRight)
extrude = extrude - (util::perp(normal) * endRight);
vertices.emplace_back(LineAttributes::vertex(currentCoordinate, extrude, { round, true }, -endRight, distance * LINE_DISTANCE_SCALE));
- e3 = vertices.size() - 1 - startVertex;
+ e3 = vertices.vertexSize() - 1 - startVertex;
if (e1 >= 0 && e2 >= 0) {
triangleStore.emplace_back(e1, e2, e3);
}
@@ -412,7 +412,7 @@ void LineBucket::addPieSliceVertex(const GeometryCoordinate& currentVertex,
std::vector<TriangleElement>& triangleStore) {
Point<double> flippedExtrude = extrude * (lineTurnsLeft ? -1.0 : 1.0);
vertices.emplace_back(LineAttributes::vertex(currentVertex, flippedExtrude, { false, lineTurnsLeft }, 0, distance * LINE_DISTANCE_SCALE));
- e3 = vertices.size() - 1 - startVertex;
+ e3 = vertices.vertexSize() - 1 - startVertex;
if (e1 >= 0 && e2 >= 0) {
triangleStore.emplace_back(e1, e2, e3);
}
diff --git a/src/mbgl/renderer/line_bucket.hpp b/src/mbgl/renderer/line_bucket.hpp
index 4d78a80123..9903ca1842 100644
--- a/src/mbgl/renderer/line_bucket.hpp
+++ b/src/mbgl/renderer/line_bucket.hpp
@@ -26,12 +26,12 @@ public:
style::LineLayoutProperties layout;
- std::vector<LineVertex> vertices;
- std::vector<gl::Triangle> triangles;
+ gl::VertexVector<LineVertex> vertices;
+ gl::IndexVector<gl::Triangles> triangles;
std::vector<gl::Segment> segments;
optional<gl::VertexBuffer<LineVertex>> vertexBuffer;
- optional<gl::IndexBuffer<gl::Triangle>> indexBuffer;
+ optional<gl::IndexBuffer<gl::Triangles>> indexBuffer;
private:
struct TriangleElement {
diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp
index d9e7f9fd35..a09e3b73fc 100644
--- a/src/mbgl/renderer/painter.cpp
+++ b/src/mbgl/renderer/painter.cpp
@@ -41,30 +41,44 @@ namespace mbgl {
using namespace style;
-Painter::Painter(gl::Context& context_, const TransformState& state_)
- : context(context_),
- state(state_),
- tileTriangleVertexBuffer(context.createVertexBuffer(std::vector<FillVertex> {{
+static gl::VertexVector<FillVertex, gl::Triangles> tileTriangles() {
+ gl::VertexVector<FillVertex, gl::Triangles> result;
+ result.emplace_back(
FillAttributes::vertex({ 0, 0 }),
FillAttributes::vertex({ util::EXTENT, 0 }),
- FillAttributes::vertex({ 0, util::EXTENT }),
- FillAttributes::vertex({ util::EXTENT, 0 }),
- FillAttributes::vertex({ 0, util::EXTENT }),
- FillAttributes::vertex({ util::EXTENT, util::EXTENT })
- }})),
- tileLineStripVertexBuffer(context.createVertexBuffer(std::vector<FillVertex> {{
- FillAttributes::vertex({ 0, 0 }),
+ FillAttributes::vertex({ 0, util::EXTENT }));
+ result.emplace_back(
FillAttributes::vertex({ util::EXTENT, 0 }),
- FillAttributes::vertex({ util::EXTENT, util::EXTENT }),
FillAttributes::vertex({ 0, util::EXTENT }),
- FillAttributes::vertex({ 0, 0 })
- }})),
- rasterVertexBuffer(context.createVertexBuffer(std::vector<RasterVertex> {{
- RasterProgram::vertex({ 0, 0 }, { 0, 0 }),
- RasterProgram::vertex({ util::EXTENT, 0 }, { 32767, 0 }),
- RasterProgram::vertex({ 0, util::EXTENT }, { 0, 32767 }),
- RasterProgram::vertex({ util::EXTENT, util::EXTENT }, { 32767, 32767 })
- }})) {
+ FillAttributes::vertex({ util::EXTENT, util::EXTENT }));
+ return result;
+}
+
+static gl::VertexVector<FillVertex, gl::LineStrip> tileLineStrip() {
+ gl::VertexVector<FillVertex, gl::LineStrip> result;
+ result.emplace_back(FillAttributes::vertex({ 0, 0 }));
+ result.emplace_back(FillAttributes::vertex({ util::EXTENT, 0 }));
+ result.emplace_back(FillAttributes::vertex({ util::EXTENT, util::EXTENT }));
+ result.emplace_back(FillAttributes::vertex({ 0, util::EXTENT }));
+ result.emplace_back(FillAttributes::vertex({ 0, 0 }));
+ return result;
+}
+
+static gl::VertexVector<RasterVertex, gl::TriangleStrip> rasterTriangleStrip() {
+ gl::VertexVector<RasterVertex, gl::TriangleStrip> result;
+ result.emplace_back(RasterProgram::vertex({ 0, 0 }, { 0, 0 }));
+ result.emplace_back(RasterProgram::vertex({ util::EXTENT, 0 }, { 32767, 0 }));
+ result.emplace_back(RasterProgram::vertex({ 0, util::EXTENT }, { 0, 32767 }));
+ result.emplace_back(RasterProgram::vertex({ util::EXTENT, util::EXTENT }, { 32767, 32767 }));
+ return result;
+}
+
+Painter::Painter(gl::Context& context_, const TransformState& state_)
+ : context(context_),
+ state(state_),
+ tileTriangleVertexBuffer(context.createVertexBuffer(tileTriangles())),
+ tileLineStripVertexBuffer(context.createVertexBuffer(tileLineStrip())),
+ rasterVertexBuffer(context.createVertexBuffer(rasterTriangleStrip())) {
#ifndef NDEBUG
gl::debugging::enable();
#endif
diff --git a/src/mbgl/renderer/painter.hpp b/src/mbgl/renderer/painter.hpp
index 53215c5033..3f5f28dad1 100644
--- a/src/mbgl/renderer/painter.hpp
+++ b/src/mbgl/renderer/painter.hpp
@@ -156,9 +156,9 @@ private:
std::unique_ptr<Programs> overdrawPrograms;
#endif
- gl::VertexBuffer<FillVertex> tileTriangleVertexBuffer;
- gl::VertexBuffer<FillVertex> tileLineStripVertexBuffer;
- gl::VertexBuffer<RasterVertex> rasterVertexBuffer;
+ gl::VertexBuffer<FillVertex, gl::Triangles> tileTriangleVertexBuffer;
+ gl::VertexBuffer<FillVertex, gl::LineStrip> tileLineStripVertexBuffer;
+ gl::VertexBuffer<RasterVertex, gl::TriangleStrip> rasterVertexBuffer;
};
} // namespace mbgl
diff --git a/src/mbgl/renderer/painter_background.cpp b/src/mbgl/renderer/painter_background.cpp
index 3e2597e47c..5e71cb7b20 100644
--- a/src/mbgl/renderer/painter_background.cpp
+++ b/src/mbgl/renderer/painter_background.cpp
@@ -28,11 +28,12 @@ void Painter::renderBackground(PaintParameters& parameters, const BackgroundLaye
spriteAtlas->bind(true, context, 0);
for (const auto& tileID : util::tileCover(state, state.getIntegerZoom())) {
- context.draw({
+ parameters.programs.fillPattern.draw(
+ context,
+ gl::Triangles(),
depthModeForSublayer(0, gl::DepthMode::ReadOnly),
gl::StencilMode::disabled(),
colorModeForRenderPass(),
- parameters.programs.fillPattern,
FillPatternUniforms::values(
matrixForTile(tileID),
properties.backgroundOpacity.value,
@@ -43,16 +44,17 @@ void Painter::renderBackground(PaintParameters& parameters, const BackgroundLaye
tileID,
state
),
- gl::Unindexed<gl::TriangleStrip>(tileTriangleVertexBuffer)
- });
+ tileTriangleVertexBuffer
+ );
}
} else {
for (const auto& tileID : util::tileCover(state, state.getIntegerZoom())) {
- context.draw({
+ parameters.programs.fill.draw(
+ context,
+ gl::Triangles(),
depthModeForSublayer(0, gl::DepthMode::ReadOnly),
gl::StencilMode::disabled(),
colorModeForRenderPass(),
- parameters.programs.fill,
FillProgram::UniformValues {
uniforms::u_matrix::Value{ matrixForTile(tileID) },
uniforms::u_opacity::Value{ properties.backgroundOpacity.value },
@@ -60,8 +62,8 @@ void Painter::renderBackground(PaintParameters& parameters, const BackgroundLaye
uniforms::u_outline_color::Value{ properties.backgroundColor.value },
uniforms::u_world::Value{ context.viewport.getCurrentValue().size },
},
- gl::Unindexed<gl::TriangleStrip>(tileTriangleVertexBuffer)
- });
+ tileTriangleVertexBuffer
+ );
}
}
}
diff --git a/src/mbgl/renderer/painter_circle.cpp b/src/mbgl/renderer/painter_circle.cpp
index e4977b8abb..e9c828bcd8 100644
--- a/src/mbgl/renderer/painter_circle.cpp
+++ b/src/mbgl/renderer/painter_circle.cpp
@@ -23,13 +23,14 @@ void Painter::renderCircle(PaintParameters& parameters,
const CirclePaintProperties& properties = layer.impl->paint;
const bool scaleWithMap = properties.circlePitchScale.value == CirclePitchScaleType::Map;
- context.draw({
+ parameters.programs.circle.draw(
+ context,
+ gl::Triangles(),
depthModeForSublayer(0, gl::DepthMode::ReadOnly),
frame.mapMode == MapMode::Still
? stencilModeForClipping(tile.clip)
: gl::StencilMode::disabled(),
colorModeForRenderPass(),
- parameters.programs.circle,
CircleProgram::UniformValues {
uniforms::u_matrix::Value{ tile.translatedMatrix(properties.circleTranslate.value,
properties.circleTranslateAnchor.value,
@@ -47,12 +48,10 @@ void Painter::renderCircle(PaintParameters& parameters,
: pixelsToGLUnits },
uniforms::u_devicepixelratio::Value{ frame.pixelRatio },
},
- gl::Segmented<gl::Triangles>(
- *bucket.vertexBuffer,
- *bucket.indexBuffer,
- bucket.segments
- )
- });
+ *bucket.vertexBuffer,
+ *bucket.indexBuffer,
+ bucket.segments
+ );
}
} // namespace mbgl
diff --git a/src/mbgl/renderer/painter_clipping.cpp b/src/mbgl/renderer/painter_clipping.cpp
index b64c5d5efc..2054424475 100644
--- a/src/mbgl/renderer/painter_clipping.cpp
+++ b/src/mbgl/renderer/painter_clipping.cpp
@@ -6,7 +6,9 @@
namespace mbgl {
void Painter::renderClippingMask(const UnwrappedTileID& tileID, const ClipID& clip) {
- context.draw({
+ programs->fill.draw(
+ context,
+ gl::Triangles(),
gl::DepthMode::disabled(),
gl::StencilMode {
gl::StencilMode::Always(),
@@ -17,7 +19,6 @@ void Painter::renderClippingMask(const UnwrappedTileID& tileID, const ClipID& cl
gl::StencilMode::Replace
},
gl::ColorMode::disabled(),
- programs->fill,
FillProgram::UniformValues {
uniforms::u_matrix::Value{ matrixForTile(tileID) },
uniforms::u_opacity::Value{ 0.0f },
@@ -25,8 +26,8 @@ void Painter::renderClippingMask(const UnwrappedTileID& tileID, const ClipID& cl
uniforms::u_outline_color::Value{ Color {} },
uniforms::u_world::Value{ context.viewport.getCurrentValue().size },
},
- gl::Unindexed<gl::Triangles>(tileTriangleVertexBuffer)
- });
+ tileTriangleVertexBuffer
+ );
}
} // namespace mbgl
diff --git a/src/mbgl/renderer/painter_debug.cpp b/src/mbgl/renderer/painter_debug.cpp
index a0fc98b8c1..8969354d23 100644
--- a/src/mbgl/renderer/painter_debug.cpp
+++ b/src/mbgl/renderer/painter_debug.cpp
@@ -18,21 +18,19 @@ void Painter::renderTileDebug(const RenderTile& renderTile) {
MBGL_DEBUG_GROUP(std::string { "debug " } + util::toString(renderTile.id));
- auto draw = [&] (Color color, auto subject) {
- context.draw({
+ auto draw = [&] (Color color, const auto& vertexBuffer, auto drawMode) {
+ programs->debug.draw(
+ context,
+ drawMode,
gl::DepthMode::disabled(),
stencilModeForClipping(renderTile.clip),
gl::ColorMode::unblended(),
- programs->fill,
- FillProgram::UniformValues {
+ DebugProgram::UniformValues {
uniforms::u_matrix::Value{ renderTile.matrix },
- uniforms::u_opacity::Value{ 1.0f },
- uniforms::u_color::Value{ color },
- uniforms::u_outline_color::Value{ color },
- uniforms::u_world::Value{ context.viewport.getCurrentValue().size },
+ uniforms::u_color::Value{ color }
},
- subject
- });
+ vertexBuffer
+ );
};
if (frame.debugOptions & (MapDebugOptions::Timestamps | MapDebugOptions::ParseStatus)) {
@@ -47,15 +45,12 @@ void Painter::renderTileDebug(const RenderTile& renderTile) {
tile.expires, frame.debugOptions, context);
}
- const auto& vertexBuffer = tile.debugBucket->vertexBuffer;
-
- draw(Color::white(), gl::Unindexed<gl::Lines>(vertexBuffer, 4.0f * frame.pixelRatio));
- draw(Color::black(), gl::Unindexed<gl::Points>(vertexBuffer, 2.0f));
- draw(Color::black(), gl::Unindexed<gl::Lines>(vertexBuffer, 2.0f * frame.pixelRatio));
+ draw(Color::white(), tile.debugBucket->vertexBuffer, gl::Lines { 4.0f * frame.pixelRatio });
+ draw(Color::black(), tile.debugBucket->vertexBuffer, gl::Lines { 2.0f * frame.pixelRatio });
}
if (frame.debugOptions & MapDebugOptions::TileBorders) {
- draw(Color::red(), gl::Unindexed<gl::LineStrip>(tileLineStripVertexBuffer, 4.0f * frame.pixelRatio));
+ draw(Color::red(), tileLineStripVertexBuffer, gl::LineStrip { 4.0f * frame.pixelRatio });
}
}
diff --git a/src/mbgl/renderer/painter_fill.cpp b/src/mbgl/renderer/painter_fill.cpp
index cdce181e1c..e5a536fde3 100644
--- a/src/mbgl/renderer/painter_fill.cpp
+++ b/src/mbgl/renderer/painter_fill.cpp
@@ -35,12 +35,18 @@ void Painter::renderFill(PaintParameters& parameters,
spriteAtlas->bind(true, context, 0);
- auto draw = [&] (uint8_t sublayer, auto& program, const auto& subject) {
- context.draw({
+ auto draw = [&] (uint8_t sublayer,
+ auto& program,
+ const auto& drawMode,
+ const auto& vertexBuffer,
+ const auto& indexBuffer,
+ const auto& segments) {
+ program.draw(
+ context,
+ drawMode,
depthModeForSublayer(sublayer, gl::DepthMode::ReadWrite),
stencilModeForClipping(tile.clip),
colorModeForRenderPass(),
- program,
FillPatternUniforms::values(
tile.translatedMatrix(properties.fillTranslate.value,
properties.fillTranslateAnchor.value,
@@ -53,16 +59,18 @@ void Painter::renderFill(PaintParameters& parameters,
tile.id,
state
),
- subject
- });
+ vertexBuffer,
+ indexBuffer,
+ segments
+ );
};
draw(0,
parameters.programs.fillPattern,
- gl::Segmented<gl::Triangles>(
- *bucket.vertexBuffer,
- *bucket.triangleIndexBuffer,
- bucket.triangleSegments));
+ gl::Triangles(),
+ *bucket.vertexBuffer,
+ *bucket.triangleIndexBuffer,
+ bucket.triangleSegments);
if (!properties.fillAntialias.value || !properties.fillOutlineColor.isUndefined()) {
return;
@@ -70,18 +78,24 @@ void Painter::renderFill(PaintParameters& parameters,
draw(2,
parameters.programs.fillOutlinePattern,
- gl::Segmented<gl::Lines>(
- *bucket.vertexBuffer,
- *bucket.lineIndexBuffer,
- bucket.lineSegments,
- 2.0f));
+ gl::Lines { 2.0f },
+ *bucket.vertexBuffer,
+ *bucket.lineIndexBuffer,
+ bucket.lineSegments);
} else {
- auto draw = [&] (uint8_t sublayer, auto& program, Color outlineColor, const auto& subject) {
- context.draw({
+ auto draw = [&] (uint8_t sublayer,
+ auto& program,
+ Color outlineColor,
+ const auto& drawMode,
+ const auto& vertexBuffer,
+ const auto& indexBuffer,
+ const auto& segments) {
+ program.draw(
+ context,
+ drawMode,
depthModeForSublayer(sublayer, gl::DepthMode::ReadWrite),
stencilModeForClipping(tile.clip),
colorModeForRenderPass(),
- program,
FillProgram::UniformValues {
uniforms::u_matrix::Value{ tile.translatedMatrix(properties.fillTranslate.value,
properties.fillTranslateAnchor.value,
@@ -91,19 +105,20 @@ void Painter::renderFill(PaintParameters& parameters,
uniforms::u_outline_color::Value{ outlineColor },
uniforms::u_world::Value{ context.viewport.getCurrentValue().size },
},
- subject
- });
+ vertexBuffer,
+ indexBuffer,
+ segments
+ );
};
if (properties.fillAntialias.value && !properties.fillOutlineColor.isUndefined() && pass == RenderPass::Translucent) {
draw(2,
parameters.programs.fillOutline,
properties.fillOutlineColor.value,
- gl::Segmented<gl::Lines>(
- *bucket.vertexBuffer,
- *bucket.lineIndexBuffer,
- bucket.lineSegments,
- 2.0f));
+ gl::Lines { 2.0f },
+ *bucket.vertexBuffer,
+ *bucket.lineIndexBuffer,
+ bucket.lineSegments);
}
// Only draw the fill when it's opaque and we're drawing opaque fragments,
@@ -112,21 +127,20 @@ void Painter::renderFill(PaintParameters& parameters,
draw(1,
parameters.programs.fill,
properties.fillOutlineColor.value,
- gl::Segmented<gl::Triangles>(
- *bucket.vertexBuffer,
- *bucket.triangleIndexBuffer,
- bucket.triangleSegments));
+ gl::Triangles(),
+ *bucket.vertexBuffer,
+ *bucket.triangleIndexBuffer,
+ bucket.triangleSegments);
}
if (properties.fillAntialias.value && properties.fillOutlineColor.isUndefined() && pass == RenderPass::Translucent) {
draw(2,
parameters.programs.fillOutline,
properties.fillColor.value,
- gl::Segmented<gl::Lines>(
- *bucket.vertexBuffer,
- *bucket.lineIndexBuffer,
- bucket.lineSegments,
- 2.0f));
+ gl::Lines { 2.0f },
+ *bucket.vertexBuffer,
+ *bucket.lineIndexBuffer,
+ bucket.lineSegments);
}
}
}
diff --git a/src/mbgl/renderer/painter_line.cpp b/src/mbgl/renderer/painter_line.cpp
index 7f9556fd3f..a495edc428 100644
--- a/src/mbgl/renderer/painter_line.cpp
+++ b/src/mbgl/renderer/painter_line.cpp
@@ -24,18 +24,17 @@ void Painter::renderLine(PaintParameters& parameters,
const auto& properties = layer.impl->paint;
auto draw = [&] (auto& program, auto&& uniformValues) {
- context.draw({
+ program.draw(
+ context,
+ gl::Triangles(),
depthModeForSublayer(0, gl::DepthMode::ReadOnly),
stencilModeForClipping(tile.clip),
colorModeForRenderPass(),
- program,
std::move(uniformValues),
- gl::Segmented<gl::Triangles>(
- *bucket.vertexBuffer,
- *bucket.indexBuffer,
- bucket.segments
- )
- });
+ *bucket.vertexBuffer,
+ *bucket.indexBuffer,
+ bucket.segments
+ );
};
if (!properties.lineDasharray.value.from.empty()) {
diff --git a/src/mbgl/renderer/painter_raster.cpp b/src/mbgl/renderer/painter_raster.cpp
index c619cad2aa..e19cde289a 100644
--- a/src/mbgl/renderer/painter_raster.cpp
+++ b/src/mbgl/renderer/painter_raster.cpp
@@ -54,11 +54,12 @@ void Painter::renderRaster(PaintParameters& parameters,
context.bindTexture(*bucket.texture, 0, gl::TextureFilter::Linear);
context.bindTexture(*bucket.texture, 1, gl::TextureFilter::Linear);
- context.draw({
+ parameters.programs.raster.draw(
+ context,
+ gl::TriangleStrip(),
depthModeForSublayer(0, gl::DepthMode::ReadOnly),
gl::StencilMode::disabled(),
colorModeForRenderPass(),
- parameters.programs.raster,
RasterProgram::UniformValues {
uniforms::u_matrix::Value{ tile.matrix },
uniforms::u_image0::Value{ 0 },
@@ -74,8 +75,8 @@ void Painter::renderRaster(PaintParameters& parameters,
uniforms::u_scale_parent::Value{ 1.0f },
uniforms::u_tl_parent::Value{ std::array<float, 2> {{ 0.0f, 0.0f }} },
},
- gl::Unindexed<gl::TriangleStrip>(rasterVertexBuffer)
- });
+ rasterVertexBuffer
+ );
}
} // namespace mbgl
diff --git a/src/mbgl/renderer/painter_symbol.cpp b/src/mbgl/renderer/painter_symbol.cpp
index 2f94544486..d2dee5d99d 100644
--- a/src/mbgl/renderer/painter_symbol.cpp
+++ b/src/mbgl/renderer/painter_symbol.cpp
@@ -46,7 +46,9 @@ void Painter::renderSymbol(PaintParameters& parameters,
const bool drawAcrossEdges = (frame.mapMode == MapMode::Continuous) && (true || !(layout.textAllowOverlap || layout.iconAllowOverlap ||
layout.textIgnorePlacement || layout.iconIgnorePlacement));
- context.draw({
+ program.draw(
+ context,
+ gl::Triangles(),
values_.pitchAlignment == AlignmentType::Map
? depthModeForSublayer(0, gl::DepthMode::ReadOnly)
: gl::DepthMode::disabled(),
@@ -54,14 +56,11 @@ void Painter::renderSymbol(PaintParameters& parameters,
? gl::StencilMode::disabled()
: stencilModeForClipping(tile.clip),
colorModeForRenderPass(),
- program,
std::move(uniformValues),
- gl::Segmented<gl::Triangles>(
- *buffers.vertexBuffer,
- *buffers.indexBuffer,
- buffers.segments
- )
- });
+ *buffers.vertexBuffer,
+ *buffers.indexBuffer,
+ buffers.segments
+ );
};
if (bucket.hasIconData()) {
@@ -119,22 +118,20 @@ void Painter::renderSymbol(PaintParameters& parameters,
}
if (bucket.hasCollisionBoxData()) {
- context.draw({
+ programs->collisionBox.draw(
+ context,
+ gl::Lines { 1.0f },
gl::DepthMode::disabled(),
gl::StencilMode::disabled(),
colorModeForRenderPass(),
- programs->collisionBox,
CollisionBoxProgram::UniformValues {
uniforms::u_matrix::Value{ tile.matrix },
uniforms::u_scale::Value{ std::pow(2.0f, float(state.getZoom() - tile.tile.id.overscaledZ)) },
uniforms::u_zoom::Value{ float(state.getZoom() * 10) },
uniforms::u_maxzoom::Value{ float((tile.id.canonical.z + 1) * 10) },
},
- gl::Unindexed<gl::Lines>(
- *bucket.collisionBox.vertexBuffer,
- 1.0f
- )
- });
+ *bucket.collisionBox.vertexBuffer
+ );
}
}
diff --git a/src/mbgl/renderer/symbol_bucket.hpp b/src/mbgl/renderer/symbol_bucket.hpp
index d33341008e..f1fc3d324e 100644
--- a/src/mbgl/renderer/symbol_bucket.hpp
+++ b/src/mbgl/renderer/symbol_bucket.hpp
@@ -34,26 +34,26 @@ public:
const bool iconsNeedLinear;
struct TextBuffer {
- std::vector<SymbolVertex> vertices;
- std::vector<gl::Triangle> triangles;
+ gl::VertexVector<SymbolVertex> vertices;
+ gl::IndexVector<gl::Triangles> triangles;
std::vector<gl::Segment> segments;
optional<gl::VertexBuffer<SymbolVertex>> vertexBuffer;
- optional<gl::IndexBuffer<gl::Triangle>> indexBuffer;
+ optional<gl::IndexBuffer<gl::Triangles>> indexBuffer;
} text;
struct IconBuffer {
- std::vector<SymbolVertex> vertices;
- std::vector<gl::Triangle> triangles;
+ gl::VertexVector<SymbolVertex> vertices;
+ gl::IndexVector<gl::Triangles> triangles;
std::vector<gl::Segment> segments;
optional<gl::VertexBuffer<SymbolVertex>> vertexBuffer;
- optional<gl::IndexBuffer<gl::Triangle>> indexBuffer;
+ optional<gl::IndexBuffer<gl::Triangles>> indexBuffer;
} icon;
struct CollisionBoxBuffer {
- std::vector<CollisionBoxVertex> vertices;
- optional<gl::VertexBuffer<CollisionBoxVertex>> vertexBuffer;
+ gl::VertexVector<CollisionBoxVertex, gl::Lines> vertices;
+ optional<gl::VertexBuffer<CollisionBoxVertex, gl::Lines>> vertexBuffer;
} collisionBox;
};
diff --git a/src/mbgl/util/ignore.hpp b/src/mbgl/util/ignore.hpp
new file mode 100644
index 0000000000..31cd092c0e
--- /dev/null
+++ b/src/mbgl/util/ignore.hpp
@@ -0,0 +1,21 @@
+#pragma once
+
+#include <initializer_list>
+
+namespace mbgl {
+
+// Accept any number of parameters of any types, and do nothing with them.
+// Useful for providing a context for parameter pack expansion where a legal
+// expansion context is not otherwise available.
+//
+// See https://github.com/mapbox/cpp/blob/master/C%2B%2B%20Structural%20Metaprogramming.md
+// for more details.
+//
+template <class... Ts> void ignore(Ts&&...) {}
+
+// std::initializer_list overload, for situations where you need sequenced
+// modifications.
+//
+template <class T> void ignore(const std::initializer_list<T>&) {}
+
+} // namespace mbgl