diff --git a/include/mbgl/util/traits.hpp b/include/mbgl/util/traits.hpp index 9d6f947cd28..6cbac457c3c 100644 --- a/include/mbgl/util/traits.hpp +++ b/include/mbgl/util/traits.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include namespace mbgl { @@ -9,4 +10,38 @@ constexpr auto underlying_type(T t) -> typename std::underlying_type_t { return typename std::underlying_type_t(t); } +template +std::enable_if_t>::value, void> apply(T&&, Fn&&) { +} + +template +std::enable_if_t>::value, void> apply(T&& t, Fn&& fn) { + fn(std::get(std::forward(t))); + apply(std::forward(t), std::forward(fn)); +} + +// Checks whether the template parameter pack contains T +template +struct tuple_contains; + +template +struct tuple_contains> : std::false_type {}; + +template +struct tuple_contains> : tuple_contains> {}; + +template +struct tuple_contains> : std::true_type {}; + +// Obtains the type T from the Tuple, or the first (default) parameter otherwise. +template +constexpr std::enable_if_t::value, T&&> get_tuple_type(T&&, Tuple&& tuple) { + return std::forward(std::get(std::forward(tuple))); +} + +template +constexpr std::enable_if_t::value, T&&> get_tuple_type(T&& t, Tuple&&) { + return std::forward(t); +} + } // namespace mbgl diff --git a/src/mbgl/renderer/painter_background.cpp b/src/mbgl/renderer/painter_background.cpp index 48c03fe3f91..91b08eef57a 100644 --- a/src/mbgl/renderer/painter_background.cpp +++ b/src/mbgl/renderer/painter_background.cpp @@ -49,9 +49,6 @@ void Painter::renderBackground(PaintParameters& parameters, const BackgroundLaye } else { config.program = plainShader.getID(); - plainShader.u_color = properties.backgroundColor; - plainShader.u_opacity = properties.backgroundOpacity; - arrayBackground.bind(plainShader, tileStencilBuffer, BUFFER_OFFSET(0), store); } @@ -80,7 +77,10 @@ void Painter::renderBackground(PaintParameters& parameters, const BackgroundLaye patternShader.u_pixel_coord_upper = {{ float(pixelX >> 16), float(pixelY >> 16) }}; patternShader.u_pixel_coord_lower = {{ float(pixelX & 0xFFFF), float(pixelY & 0xFFFF) }}; } else { - plainShader.u_matrix = vertexMatrix; + plainShader.setUniforms( + UniformValue{ properties.backgroundColor }, + UniformValue{ properties.backgroundOpacity }, + UniformValue{ vertexMatrix }); } MBGL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, (GLsizei)tileStencilBuffer.index())); diff --git a/src/mbgl/renderer/painter_clipping.cpp b/src/mbgl/renderer/painter_clipping.cpp index 7cb8e01c573..3efaaa4d454 100644 --- a/src/mbgl/renderer/painter_clipping.cpp +++ b/src/mbgl/renderer/painter_clipping.cpp @@ -35,7 +35,7 @@ void Painter::drawClippingMasks(PaintParameters& parameters, const std::map{ matrix }); const GLint ref = (GLint)(clip.reference.to_ulong()); config.stencilFunc = { GL_ALWAYS, ref, mask }; diff --git a/src/mbgl/renderer/painter_debug.cpp b/src/mbgl/renderer/painter_debug.cpp index 7c24f67fb41..0817676aec4 100644 --- a/src/mbgl/renderer/painter_debug.cpp +++ b/src/mbgl/renderer/painter_debug.cpp @@ -42,11 +42,11 @@ void Painter::renderDebugText(Tile& tile, const mat4 &matrix) { auto& plainShader = shaders->plain; config.program = plainShader.getID(); - plainShader.u_matrix = matrix; - plainShader.u_opacity = 1.0f; // Draw white outline - plainShader.u_color = Color::white(); + plainShader.setUniforms(UniformValue{ matrix }, + UniformValue{ 1.0f }, + UniformValue{ Color::white() }); config.lineWidth = 4.0f * frame.pixelRatio; tile.debugBucket->drawLines(plainShader, store); @@ -57,7 +57,9 @@ void Painter::renderDebugText(Tile& tile, const mat4 &matrix) { #endif // Draw black text. - plainShader.u_color = Color::black(); + plainShader.setUniforms(UniformValue{ matrix }, + UniformValue{ 1.0f }, + UniformValue{ Color::black() }); config.lineWidth = 2.0f * frame.pixelRatio; tile.debugBucket->drawLines(plainShader, store); @@ -77,12 +79,12 @@ void Painter::renderDebugFrame(const mat4 &matrix) { auto& plainShader = shaders->plain; config.program = plainShader.getID(); - plainShader.u_matrix = matrix; - plainShader.u_opacity = 1.0f; // draw tile outline tileBorderArray.bind(plainShader, tileBorderBuffer, BUFFER_OFFSET_0, store); - plainShader.u_color = { 1.0f, 0.0f, 0.0f, 1.0f }; + plainShader.setUniforms(UniformValue{ matrix }, + UniformValue{ 1.0f }, + UniformValue{ { 1.0f, 0.0f, 0.0f, 1.0f } }); config.lineWidth = 4.0f * frame.pixelRatio; MBGL_CHECK_ERROR(glDrawArrays(GL_LINE_STRIP, 0, (GLsizei)tileBorderBuffer.index())); } diff --git a/src/mbgl/renderer/painter_fill.cpp b/src/mbgl/renderer/painter_fill.cpp index 7d952caa123..bc6c2f9e3cd 100644 --- a/src/mbgl/renderer/painter_fill.cpp +++ b/src/mbgl/renderer/painter_fill.cpp @@ -143,9 +143,11 @@ void Painter::renderFill(PaintParameters& parameters, // fragments // Draw filling rectangle. config.program = plainShader.getID(); - plainShader.u_matrix = vertexMatrix; - plainShader.u_color = fillColor; - plainShader.u_opacity = opacity; + plainShader.setUniforms( + UniformValue{ vertexMatrix }, + UniformValue{ fillColor }, + UniformValue{ opacity } + ); // Draw the actual triangles into the color & stencil buffer. setDepthSublayer(1); diff --git a/src/mbgl/shader/plain_shader.cpp b/src/mbgl/shader/plain_shader.cpp index 1309c4f14a1..f10ef11e272 100644 --- a/src/mbgl/shader/plain_shader.cpp +++ b/src/mbgl/shader/plain_shader.cpp @@ -3,6 +3,8 @@ #include #include +#include + namespace mbgl { PlainShader::PlainShader(gl::ObjectStore& store, Defines defines) @@ -10,6 +12,9 @@ PlainShader::PlainShader(gl::ObjectStore& store, Defines defines) shaders::fill::vertex, shaders::fill::fragment, store, defines) { + apply(uniforms, [this](auto& uniform) { + uniform.location = MBGL_CHECK_ERROR(glGetUniformLocation(getID(), uniform.name)); + }); } void PlainShader::bind(GLbyte* offset) { diff --git a/src/mbgl/shader/plain_shader.hpp b/src/mbgl/shader/plain_shader.hpp index a126fa30a99..2356b1994d7 100644 --- a/src/mbgl/shader/plain_shader.hpp +++ b/src/mbgl/shader/plain_shader.hpp @@ -3,18 +3,42 @@ #include #include #include +#include namespace mbgl { +template +struct UniformValue { + const typename U::ArgType& value; +}; + class PlainShader : public Shader { public: PlainShader(gl::ObjectStore&, Defines defines = None); void bind(GLbyte *offset) final; - UniformMatrix<4> u_matrix = {"u_matrix", *this}; - Uniform u_color = {"u_color", *this}; - Uniform u_opacity = {"u_opacity", *this}; + struct matrix : public UniformMatrix<4> { + matrix() : UniformMatrix{ "u_matrix" } {}; + }; + struct color : public Uniform { + color() : Uniform{ "u_color" } {}; + }; + struct opacity : public Uniform { + opacity() : Uniform{ "u_opacity" } {}; + }; + + template + void setUniforms(Args&&... args) { + auto x = std::make_tuple(std::forward(args)...); + apply(uniforms, [this, &x](auto& uniform) { + using U = std::remove_cv_t>; + uniform.set(get_tuple_type>({ {} }, std::forward(x)).value); + }); + } + +private: + std::tuple uniforms; }; } // namespace mbgl diff --git a/src/mbgl/shader/uniform.cpp b/src/mbgl/shader/uniform.cpp index 4c7646119ad..218c3460e00 100644 --- a/src/mbgl/shader/uniform.cpp +++ b/src/mbgl/shader/uniform.cpp @@ -4,49 +4,48 @@ namespace mbgl { template <> -void Uniform::bind(const GLfloat& t) { - MBGL_CHECK_ERROR(glUniform1f(location, t)); +void Uniform::bind() { + MBGL_CHECK_ERROR(glUniform1f(location, current)); } template <> -void Uniform::bind(const GLint& t) { - MBGL_CHECK_ERROR(glUniform1i(location, t)); +void Uniform::bind() { + MBGL_CHECK_ERROR(glUniform1i(location, current)); } template <> -void Uniform>::bind(const std::array& t) { - MBGL_CHECK_ERROR(glUniform2fv(location, 1, t.data())); +void Uniform>::bind() { + MBGL_CHECK_ERROR(glUniform2fv(location, 1, current.data())); } template <> -void Uniform>::bind(const std::array& t) { - MBGL_CHECK_ERROR(glUniform3fv(location, 1, t.data())); +void Uniform>::bind() { + MBGL_CHECK_ERROR(glUniform3fv(location, 1, current.data())); } template <> -void Uniform>::bind(const std::array& t) { - MBGL_CHECK_ERROR(glUniform4fv(location, 1, t.data())); +void Uniform>::bind() { + MBGL_CHECK_ERROR(glUniform4fv(location, 1, current.data())); } template <> -void Uniform::bind(const Color& t) { - std::array a = {{ t.r, t.g, t.b, t.a }}; - MBGL_CHECK_ERROR(glUniform4fv(location, 1, a.data())); +void Uniform::bind() { + MBGL_CHECK_ERROR(glUniform4f(location, current.r, current.g, current.b, current.a)); } template <> -void UniformMatrix<2>::bind(const std::array& t) { - MBGL_CHECK_ERROR(glUniformMatrix2fv(location, 1, GL_FALSE, t.data())); +void UniformMatrix<2>::bind() { + MBGL_CHECK_ERROR(glUniformMatrix2fv(location, 1, GL_FALSE, current.data())); } template <> -void UniformMatrix<3>::bind(const std::array& t) { - MBGL_CHECK_ERROR(glUniformMatrix3fv(location, 1, GL_FALSE, t.data())); +void UniformMatrix<3>::bind() { + MBGL_CHECK_ERROR(glUniformMatrix3fv(location, 1, GL_FALSE, current.data())); } template <> -void UniformMatrix<4>::bind(const std::array& t) { - MBGL_CHECK_ERROR(glUniformMatrix4fv(location, 1, GL_FALSE, t.data())); +void UniformMatrix<4>::bind() { + MBGL_CHECK_ERROR(glUniformMatrix4fv(location, 1, GL_FALSE, current.data())); } // Add more as needed. diff --git a/src/mbgl/shader/uniform.hpp b/src/mbgl/shader/uniform.hpp index fd7e8797be0..eb63f1f4585 100644 --- a/src/mbgl/shader/uniform.hpp +++ b/src/mbgl/shader/uniform.hpp @@ -10,34 +10,48 @@ namespace mbgl { template class Uniform { public: - Uniform(const GLchar* name, const Shader& shader) : current() { - location = MBGL_CHECK_ERROR(glGetUniformLocation(shader.getID(), name)); + using Type = T; + using ArgType = T; + + Uniform(const GLchar* name_, const Shader& shader) : name(name_), current() { + location = MBGL_CHECK_ERROR(glGetUniformLocation(shader.getID(), name)); } - void operator=(const T& t) { + Uniform(const GLchar* name_) : name(name_), current() { + } + + void operator=(const ArgType& t) { if (current != t) { current = t; - bind(t); + bind(); } } -private: - void bind(const T&); + void set(const ArgType& t) { + operator=(t); + } + + void bind(); - T current; - GLint location; + const char* const name; + Type current; + GLint location = -1; }; template class UniformMatrix { public: - typedef std::array T; + using Type = std::array; + using ArgType = std::array; - UniformMatrix(const GLchar* name, const Shader& shader) : current() { + UniformMatrix(const GLchar* name_, const Shader& shader) : name(name_), current() { location = MBGL_CHECK_ERROR(glGetUniformLocation(shader.getID(), name)); } - void operator=(const std::array& t) { + UniformMatrix(const GLchar* name_) : name(name_), current() { + } + + void operator=(const ArgType& t) { bool dirty = false; for (unsigned int i = 0; i < C*R; i++) { if (current[i] != t[i]) { @@ -46,15 +60,19 @@ class UniformMatrix { } } if (dirty) { - bind(current); + bind(); } } -private: - void bind(const T&); + void set(const ArgType& t) { + operator=(t); + } + + void bind(); - T current; - GLint location; + const char* const name; + Type current; + GLint location = -1; }; } // namespace mbgl