diff --git a/include/mbgl/gfx/uniform_buffer.hpp b/include/mbgl/gfx/uniform_buffer.hpp index 8e749912c..60b7b08b1 100644 --- a/include/mbgl/gfx/uniform_buffer.hpp +++ b/include/mbgl/gfx/uniform_buffer.hpp @@ -18,6 +18,7 @@ protected: public: virtual ~UniformBuffer() = default; + virtual void update(const void* data, std::size_t size_) = 0; std::size_t getSize() const { return size; } diff --git a/include/mbgl/gl/uniform_buffer_gl.hpp b/include/mbgl/gl/uniform_buffer_gl.hpp index 1fda40db5..7a1a4511f 100644 --- a/include/mbgl/gl/uniform_buffer_gl.hpp +++ b/include/mbgl/gl/uniform_buffer_gl.hpp @@ -16,6 +16,7 @@ public: ~UniformBufferGL() override; BufferID getID() const { return id; } + void update(const void* data, std::size_t size_) override; protected: BufferID id = 0; diff --git a/src/mbgl/gl/uniform_buffer_gl.cpp b/src/mbgl/gl/uniform_buffer_gl.cpp index 6bf4f51ca..9f21b21f8 100644 --- a/src/mbgl/gl/uniform_buffer_gl.cpp +++ b/src/mbgl/gl/uniform_buffer_gl.cpp @@ -1,7 +1,9 @@ - #include #include #include +#include + +#include namespace mbgl { namespace gl { @@ -12,7 +14,7 @@ UniformBufferGL::UniformBufferGL(const void* data, std::size_t size_) : UniformBuffer(size_) { MBGL_CHECK_ERROR(glGenBuffers(1, &id)); MBGL_CHECK_ERROR(glBindBuffer(GL_UNIFORM_BUFFER, id)); - MBGL_CHECK_ERROR(glBufferData(GL_UNIFORM_BUFFER, size, data, GL_STATIC_DRAW)); + MBGL_CHECK_ERROR(glBufferData(GL_UNIFORM_BUFFER, size, data, GL_DYNAMIC_DRAW)); MBGL_CHECK_ERROR(glBindBuffer(GL_UNIFORM_BUFFER, 0)); } @@ -23,5 +25,19 @@ UniformBufferGL::~UniformBufferGL() { } } +void UniformBufferGL::update(const void* data, std::size_t size_) { + assert(size == size_); + if (size != size_) { + Log::Error( + Event::General, + "Mismatched size given to UBO update, expected " + std::to_string(size) + ", got " + std::to_string(size_)); + return; + } + + MBGL_CHECK_ERROR(glBindBuffer(GL_UNIFORM_BUFFER, id)); + MBGL_CHECK_ERROR(glBufferSubData(GL_UNIFORM_BUFFER, 0, size_, data)); + MBGL_CHECK_ERROR(glBindBuffer(GL_UNIFORM_BUFFER, 0)); +} + } // namespace gl } // namespace mbgl diff --git a/src/mbgl/renderer/layers/background_layer_tweaker.cpp b/src/mbgl/renderer/layers/background_layer_tweaker.cpp index 24ef602c1..707f73581 100644 --- a/src/mbgl/renderer/layers/background_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/background_layer_tweaker.cpp @@ -82,10 +82,14 @@ void BackgroundLayerTweaker::execute(LayerGroup& layerGroup, const RenderTree&, BackgroundDrawableUBO drawableUBO; drawableUBO.matrix = util::cast(matrix); - auto drawableUniformBuffer = parameters.context.createUniformBuffer(&drawableUBO, sizeof(drawableUBO)); - drawable.mutableUniformBuffers().addOrReplace("BackgroundDrawableUBO", std::move(drawableUniformBuffer)); - gfx::UniformBufferPtr layerUniformBuffer; + if (auto& ubo = drawable.mutableUniformBuffers().get("BackgroundDrawableUBO")) { + ubo->update(&drawableUBO, sizeof(drawableUBO)); + } else { + drawable.mutableUniformBuffers().addOrReplace( + "BackgroundDrawableUBO", parameters.context.createUniformBuffer(&drawableUBO, sizeof(drawableUBO))); + } + if (hasPattern) { // TODO: add when raster is merged // curShader->getSamplerLocation("u_image"); @@ -117,17 +121,29 @@ void BackgroundLayerTweaker::execute(LayerGroup& layerGroup, const RenderTree&, /* .opacity = */ evaluated.get(), /* .pad = */ {0}, }; - // TODO: Update UBOs in-place - layerUniformBuffer = parameters.context.createUniformBuffer(&layerUBO, sizeof(layerUBO)); + + if (auto& ubo = drawable.mutableUniformBuffers().get("BackgroundLayerUBO"); + ubo->getSize() == sizeof(layerUBO)) { + ubo->update(&drawableUBO, sizeof(drawableUBO)); + } else { + drawable.mutableUniformBuffers().addOrReplace( + "BackgroundLayerUBO", parameters.context.createUniformBuffer(&layerUBO, sizeof(layerUBO))); + } } else { const BackgroundLayerUBO layerUBO = { /* .color = */ evaluated.get(), /* .opacity = */ evaluated.get(), /* .pad = */ {0, 0, 0}, }; - layerUniformBuffer = parameters.context.createUniformBuffer(&layerUBO, sizeof(layerUBO)); + + if (auto& ubo = drawable.mutableUniformBuffers().get("BackgroundLayerUBO"); + ubo->getSize() == sizeof(layerUBO)) { + ubo->update(&drawableUBO, sizeof(drawableUBO)); + } else { + drawable.mutableUniformBuffers().addOrReplace( + "BackgroundLayerUBO", parameters.context.createUniformBuffer(&layerUBO, sizeof(layerUBO))); + } } - drawable.mutableUniformBuffers().addOrReplace("BackgroundLayerUBO", std::move(layerUniformBuffer)); }); } diff --git a/src/mbgl/renderer/layers/circle_layer_tweaker.cpp b/src/mbgl/renderer/layers/circle_layer_tweaker.cpp index fb12b7b79..477638e3a 100644 --- a/src/mbgl/renderer/layers/circle_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/circle_layer_tweaker.cpp @@ -60,7 +60,12 @@ void CircleLayerTweaker::execute(LayerGroup& layerGroup, CirclePaintParamsUBO paintParamsUBO; paintParamsUBO.camera_to_center_distance = parameters.state.getCameraToCenterDistance(); paintParamsUBO.device_pixel_ratio = parameters.pixelRatio; - auto paintParamsUniformBuffer = parameters.context.createUniformBuffer(&paintParamsUBO, sizeof(paintParamsUBO)); + + if (!paintParamsUniformBuffer) { + paintParamsUniformBuffer = parameters.context.createUniformBuffer(&paintParamsUBO, sizeof(paintParamsUBO)); + } else { + paintParamsUniformBuffer->update(&paintParamsUBO, sizeof(CirclePaintParamsUBO)); + } const bool pitchWithMap = evaluated.get() == AlignmentType::Map; @@ -87,7 +92,12 @@ void CircleLayerTweaker::execute(LayerGroup& layerGroup, interpolateUBO.stroke_color_t = 0; interpolateUBO.stroke_width_t = 0; interpolateUBO.stroke_opacity_t = 0; - auto interpolateUniformBuffer = parameters.context.createUniformBuffer(&interpolateUBO, sizeof(interpolateUBO)); + + if (!interpolateUniformBuffer) { + interpolateUniformBuffer = parameters.context.createUniformBuffer(&interpolateUBO, sizeof(interpolateUBO)); + } else { + interpolateUniformBuffer->update(&interpolateUBO, sizeof(CircleInterpolateUBO)); + } layerGroup.observeDrawables([&](gfx::Drawable& drawable) { drawable.mutableUniformBuffers().addOrReplace("CirclePaintParamsUBO", paintParamsUniformBuffer); @@ -112,8 +122,13 @@ void CircleLayerTweaker::execute(LayerGroup& layerGroup, ? std::array{{tileID.pixelsToTileUnits(1.0f, static_cast(parameters.state.getZoom())), tileID.pixelsToTileUnits(1.0f, static_cast(parameters.state.getZoom()))}} : parameters.pixelsToGLUnits; - auto drawableUniformBuffer = parameters.context.createUniformBuffer(&drawableUBO, sizeof(drawableUBO)); - drawable.mutableUniformBuffers().addOrReplace("CircleDrawableUBO", drawableUniformBuffer); + + if (auto& ubo = drawable.mutableUniformBuffers().get("CircleDrawableUBO")) { + ubo->update(&drawableUBO, sizeof(drawableUBO)); + } else { + auto drawableUniformBuffer = parameters.context.createUniformBuffer(&drawableUBO, sizeof(drawableUBO)); + drawable.mutableUniformBuffers().addOrReplace("CircleDrawableUBO", drawableUniformBuffer); + } }); } diff --git a/src/mbgl/renderer/layers/circle_layer_tweaker.hpp b/src/mbgl/renderer/layers/circle_layer_tweaker.hpp index 9915a897d..adf716ef8 100644 --- a/src/mbgl/renderer/layers/circle_layer_tweaker.hpp +++ b/src/mbgl/renderer/layers/circle_layer_tweaker.hpp @@ -23,7 +23,9 @@ public: void execute(LayerGroup&, const RenderTree&, const PaintParameters&) override; protected: + gfx::UniformBufferPtr paintParamsUniformBuffer = nullptr; gfx::UniformBufferPtr evaluatedPropsUniformBuffer = nullptr; + gfx::UniformBufferPtr interpolateUniformBuffer = nullptr; }; } // namespace mbgl diff --git a/src/mbgl/renderer/layers/fill_layer_tweaker.cpp b/src/mbgl/renderer/layers/fill_layer_tweaker.cpp index 822a0968a..f5d56de02 100644 --- a/src/mbgl/renderer/layers/fill_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/fill_layer_tweaker.cpp @@ -115,9 +115,12 @@ void FillLayerTweaker::execute(LayerGroup& layerGroup, /*.image=*/ // TextureAttachment(tile.getIconAtlasTexture().getResource(), Linear) }; - auto drawableUniformBuffer = parameters.context.createUniformBuffer(&drawableUBO, sizeof(drawableUBO)); - drawable.mutableUniformBuffers().addOrReplace("FillDrawableUBO", drawableUniformBuffer); + if (auto& ubo = drawable.mutableUniformBuffers().get("FillDrawableUBO")) { + ubo->update(&drawableUBO, sizeof(drawableUBO)); + } else { + drawable.mutableUniformBuffers().addOrReplace( + "FillDrawableUBO", parameters.context.createUniformBuffer(&drawableUBO, sizeof(drawableUBO))); + } }); } - } // namespace mbgl