diff --git a/include/mbgl/gfx/uniform_buffer.hpp b/include/mbgl/gfx/uniform_buffer.hpp index e0f690198..acb2a5261 100644 --- a/include/mbgl/gfx/uniform_buffer.hpp +++ b/include/mbgl/gfx/uniform_buffer.hpp @@ -62,7 +62,9 @@ public: void createOrUpdate(std::string_view name, const std::vector& data, gfx::Context&); void createOrUpdate(std::string_view name, const void* data, std::size_t size, gfx::Context&); template - void createOrUpdate(std::string_view name, const T* data, gfx::Context& context) { + std::enable_if_t> createOrUpdate(std::string_view name, + const T* data, + gfx::Context& context) { createOrUpdate(name, data, sizeof(T), context); } diff --git a/include/mbgl/renderer/layer_group.hpp b/include/mbgl/renderer/layer_group.hpp index b8f8de9de..1721ca733 100644 --- a/include/mbgl/renderer/layer_group.hpp +++ b/include/mbgl/renderer/layer_group.hpp @@ -67,8 +67,8 @@ public: virtual void postRender(RenderOrchestrator&, PaintParameters&) {} /// Call the provided function for each drawable in priority order - virtual void observeDrawables(const std::function&&) = 0; - virtual void observeDrawables(const std::function&&) const = 0; + virtual std::size_t observeDrawables(const std::function&&) = 0; + virtual std::size_t observeDrawables(const std::function&&) const = 0; /// Call the provided function for each drawable in undefined order, allowing for removal. /// @param f A function called with each drawable, returning true to keep and false to discard it. @@ -102,15 +102,17 @@ public: std::vector removeDrawables(mbgl::RenderPass, const OverscaledTileID&); void addDrawable(mbgl::RenderPass, const OverscaledTileID&, gfx::UniqueDrawable&&); - void observeDrawables(const std::function&&) override; - void observeDrawables(const std::function&&) const override; + std::size_t observeDrawables(const std::function&&) override; + std::size_t observeDrawables(const std::function&&) const override; std::size_t observeDrawablesRemove(const std::function&&) override; /// Call the provided function for each drawable for the given tile - void observeDrawables(mbgl::RenderPass, const OverscaledTileID&, const std::function&&); - void observeDrawables(mbgl::RenderPass, - const OverscaledTileID&, - const std::function&&) const; + std::size_t observeDrawables(mbgl::RenderPass, + const OverscaledTileID&, + const std::function&&); + std::size_t observeDrawables(mbgl::RenderPass, + const OverscaledTileID&, + const std::function&&) const; std::size_t clearDrawables() override; @@ -133,8 +135,8 @@ public: std::vector removeDrawables(mbgl::RenderPass); void addDrawable(gfx::UniqueDrawable&&); - void observeDrawables(const std::function&&) override; - void observeDrawables(const std::function&&) const override; + std::size_t observeDrawables(const std::function&&) override; + std::size_t observeDrawables(const std::function&&) const override; std::size_t observeDrawablesRemove(const std::function&&) override; std::size_t clearDrawables() override; diff --git a/src/mbgl/renderer/layer_group.cpp b/src/mbgl/renderer/layer_group.cpp index fbf15a6f2..39f001455 100644 --- a/src/mbgl/renderer/layer_group.cpp +++ b/src/mbgl/renderer/layer_group.cpp @@ -27,20 +27,22 @@ void LayerGroup::addDrawable(gfx::UniqueDrawable&& drawable) { impl->drawables.emplace(std::move(drawable)); } -void LayerGroup::observeDrawables(const std::function&& f) { +std::size_t LayerGroup::observeDrawables(const std::function&& f) { for (const auto& item : impl->drawables) { if (item) { f(*item); } } + return impl->drawables.size(); } -void LayerGroup::observeDrawables(const std::function&& f) const { +std::size_t LayerGroup::observeDrawables(const std::function&& f) const { for (const auto& item : impl->drawables) { if (item) { f(*item); } } + return impl->drawables.size(); } std::size_t LayerGroup::observeDrawablesRemove(const std::function&& f) { diff --git a/src/mbgl/renderer/layers/background_layer_tweaker.cpp b/src/mbgl/renderer/layers/background_layer_tweaker.cpp index 9604ab57d..b513116b8 100644 --- a/src/mbgl/renderer/layers/background_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/background_layer_tweaker.cpp @@ -138,12 +138,16 @@ void BackgroundLayerTweaker::execute(LayerGroupBase& layerGroup, const RenderTre }; uniforms.createOrUpdate(BackgroundLayerUBOName, &layerUBO, context); } else { - const BackgroundLayerUBO layerUBO = {/* .color = */ evaluated.get(), - /* .opacity = */ evaluated.get(), - /* .pad = */ 0, - 0, - 0}; - uniforms.createOrUpdate(BackgroundLayerUBOName, &layerUBO, context); + // UBOs can be shared + if (!backgroundLayerBuffer) { + const BackgroundLayerUBO layerUBO = {/* .color = */ evaluated.get(), + /* .opacity = */ evaluated.get(), + /* .pad = */ 0, + 0, + 0}; + backgroundLayerBuffer = context.createUniformBuffer(&layerUBO, sizeof(layerUBO)); + } + uniforms.addOrReplace(BackgroundLayerUBOName, backgroundLayerBuffer); } }); } diff --git a/src/mbgl/renderer/layers/background_layer_tweaker.hpp b/src/mbgl/renderer/layers/background_layer_tweaker.hpp index 19d974306..27ba75474 100644 --- a/src/mbgl/renderer/layers/background_layer_tweaker.hpp +++ b/src/mbgl/renderer/layers/background_layer_tweaker.hpp @@ -28,6 +28,7 @@ public: void execute(LayerGroupBase&, const RenderTree&, const PaintParameters&) override; protected: + gfx::UniformBufferPtr backgroundLayerBuffer; }; } // namespace mbgl diff --git a/src/mbgl/renderer/layers/circle_layer_tweaker.cpp b/src/mbgl/renderer/layers/circle_layer_tweaker.cpp index 4271b0f9c..cafc17385 100644 --- a/src/mbgl/renderer/layers/circle_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/circle_layer_tweaker.cpp @@ -47,6 +47,7 @@ static constexpr std::string_view CircleEvaluatedPropsUBOName = "CircleEvaluated void CircleLayerTweaker::execute(LayerGroupBase& layerGroup, const RenderTree& renderTree, const PaintParameters& parameters) { + auto& context = parameters.context; const auto& evaluated = static_cast(*evaluatedProperties).evaluated; if (layerGroup.empty()) { @@ -58,19 +59,21 @@ void CircleLayerTweaker::execute(LayerGroupBase& layerGroup, const auto debugGroup = parameters.encoder->createDebugGroup(label.c_str()); #endif + // Updated every frame, but shared across drawables const CirclePaintParamsUBO paintParamsUBO = { /* .camera_to_center_distance = */ parameters.state.getCameraToCenterDistance(), /* .device_pixel_ratio = */ parameters.pixelRatio, /* .padding = */ {0}}; if (!paintParamsUniformBuffer) { - paintParamsUniformBuffer = parameters.context.createUniformBuffer(&paintParamsUBO, sizeof(paintParamsUBO)); + paintParamsUniformBuffer = context.createUniformBuffer(&paintParamsUBO, sizeof(paintParamsUBO)); } else { paintParamsUniformBuffer->update(&paintParamsUBO, sizeof(CirclePaintParamsUBO)); } const bool pitchWithMap = evaluated.get() == AlignmentType::Map; + // Updated only with evaluated properties if (!evaluatedPropsUniformBuffer) { const CircleEvaluatedPropsUBO evaluatedPropsUBO = { /* .color = */ evaluated.get().constantOr(CircleColor::defaultValue()), @@ -84,13 +87,13 @@ void CircleLayerTweaker::execute(LayerGroupBase& layerGroup, /* .scale_with_map = */ evaluated.get() == CirclePitchScaleType::Map, /* .pitch_with_map = */ pitchWithMap, /* .padding = */ 0}; - evaluatedPropsUniformBuffer = parameters.context.createUniformBuffer(&evaluatedPropsUBO, - sizeof(evaluatedPropsUBO)); + evaluatedPropsUniformBuffer = context.createUniformBuffer(&evaluatedPropsUBO, sizeof(evaluatedPropsUBO)); } layerGroup.observeDrawables([&](gfx::Drawable& drawable) { - drawable.mutableUniformBuffers().addOrReplace(CirclePaintParamsUBOName, paintParamsUniformBuffer); - drawable.mutableUniformBuffers().addOrReplace(CircleEvaluatedPropsUBOName, evaluatedPropsUniformBuffer); + auto& uniforms = drawable.mutableUniformBuffers(); + uniforms.addOrReplace(CirclePaintParamsUBOName, paintParamsUniformBuffer); + uniforms.addOrReplace(CircleEvaluatedPropsUBOName, evaluatedPropsUniformBuffer); if (!drawable.getTileID()) { return; @@ -106,13 +109,14 @@ void CircleLayerTweaker::execute(LayerGroupBase& layerGroup, const auto pixelsToTileUnits = tileID.pixelsToTileUnits(1.0f, static_cast(parameters.state.getZoom())); - CircleDrawableUBO drawableUBO = { + // Updated for each drawable on each frame + const CircleDrawableUBO drawableUBO = { /* .matrix = */ util::cast(matrix), /* .extrude_scale = */ pitchWithMap ? std::array{{pixelsToTileUnits}} : parameters.pixelsToGLUnits, /* .padding = */ {0}}; - drawable.mutableUniformBuffers().createOrUpdate(CircleDrawableUBOName, &drawableUBO, parameters.context); + uniforms.createOrUpdate(CircleDrawableUBOName, &drawableUBO, context); }); } diff --git a/src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.cpp b/src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.cpp index 416d72938..15ec8b15c 100644 --- a/src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.cpp @@ -64,6 +64,7 @@ auto constOrDefault(const IndexedTuple, TypeList>& evalua void FillExtrusionLayerTweaker::execute(LayerGroupBase& layerGroup, const RenderTree& renderTree, const PaintParameters& parameters) { + auto& context = parameters.context; const auto& props = static_cast(*evaluatedProperties); const auto& evaluated = props.evaluated; const auto& crossfade = props.crossfade; @@ -78,7 +79,8 @@ void FillExtrusionLayerTweaker::execute(LayerGroupBase& layerGroup, const auto debugGroup = parameters.encoder->createDebugGroup(label.c_str()); #endif - // UBO depends on more than just evaluated properties, so we need to update every time. + // UBO depends on more than just evaluated properties, so we need to update every time, + // but the resulting buffer can be shared across all the drawables from the layer. const FillExtrusionDrawablePropsUBO paramsUBO = { /* .color = */ gfx::VertexAttribute::colorAttrRGBA(constOrDefault(evaluated)), /* .light_color = */ FillExtrusionProgram::lightColor(parameters.evaluatedLight), @@ -94,7 +96,7 @@ void FillExtrusionLayerTweaker::execute(LayerGroupBase& layerGroup, 0, 0}; if (!propsBuffer) { - propsBuffer = parameters.context.createUniformBuffer(¶msUBO, sizeof(paramsUBO)); + propsBuffer = context.createUniformBuffer(¶msUBO, sizeof(paramsUBO)); } else { propsBuffer->update(¶msUBO, sizeof(paramsUBO)); } @@ -145,7 +147,7 @@ void FillExtrusionLayerTweaker::execute(LayerGroupBase& layerGroup, /* .height_factor = */ heightFactor, /* .pad = */ 0}; - uniforms.createOrUpdate(FillExtrusionDrawableUBOName, &drawableUBO, parameters.context); + uniforms.createOrUpdate(FillExtrusionDrawableUBOName, &drawableUBO, context); }); } diff --git a/src/mbgl/renderer/layers/fill_layer_tweaker.cpp b/src/mbgl/renderer/layers/fill_layer_tweaker.cpp index 7c3ae62d4..48e6337db 100644 --- a/src/mbgl/renderer/layers/fill_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/fill_layer_tweaker.cpp @@ -44,6 +44,7 @@ static constexpr std::string_view FillDrawablePropsUBOName = "FillDrawablePropsU void FillLayerTweaker::execute(LayerGroupBase& layerGroup, const RenderTree& renderTree, const PaintParameters& parameters) { + auto& context = parameters.context; const auto& props = static_cast(*evaluatedProperties); const auto& evaluated = props.evaluated; const auto& crossfade = props.crossfade; @@ -65,11 +66,12 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup, /* .padding = */ 0, 0, 0}; - propsBuffer = parameters.context.createUniformBuffer(¶msUBO, sizeof(paramsUBO)); + propsBuffer = context.createUniformBuffer(¶msUBO, sizeof(paramsUBO)); } layerGroup.observeDrawables([&](gfx::Drawable& drawable) { - drawable.mutableUniformBuffers().addOrReplace(FillDrawablePropsUBOName, propsBuffer); + auto& uniforms = drawable.mutableUniformBuffers(); + uniforms.addOrReplace(FillDrawablePropsUBOName, propsBuffer); if (!drawable.getTileID()) { return; @@ -114,7 +116,7 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup, /*.texsize=*/{static_cast(textureSize.width), static_cast(textureSize.height)}, }; - drawable.mutableUniformBuffers().createOrUpdate(FillDrawableUBOName, &drawableUBO, parameters.context); + uniforms.createOrUpdate(FillDrawableUBOName, &drawableUBO, context); }); } diff --git a/src/mbgl/renderer/layers/heatmap_layer_tweaker.cpp b/src/mbgl/renderer/layers/heatmap_layer_tweaker.cpp index 51bd84763..1bce27a72 100644 --- a/src/mbgl/renderer/layers/heatmap_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/heatmap_layer_tweaker.cpp @@ -34,6 +34,7 @@ static constexpr std::string_view HeatmapEvaluatedPropsUBOName = "HeatmapEvaluat void HeatmapLayerTweaker::execute(LayerGroupBase& layerGroup, const RenderTree& renderTree, const PaintParameters& parameters) { + auto& context = parameters.context; const auto& evaluated = static_cast(*evaluatedProperties).evaluated; if (layerGroup.empty()) { @@ -46,7 +47,7 @@ void HeatmapLayerTweaker::execute(LayerGroupBase& layerGroup, #endif if (!evaluatedPropsUniformBuffer) { - HeatmapEvaluatedPropsUBO evaluatedPropsUBO = { + const HeatmapEvaluatedPropsUBO evaluatedPropsUBO = { /* .weight = */ evaluated.get().constantOr(HeatmapWeight::defaultValue()), /* .radius = */ evaluated.get().constantOr(HeatmapRadius::defaultValue()), /* .intensity = */ evaluated.get(), @@ -56,7 +57,8 @@ void HeatmapLayerTweaker::execute(LayerGroupBase& layerGroup, } layerGroup.observeDrawables([&](gfx::Drawable& drawable) { - drawable.mutableUniformBuffers().addOrReplace(HeatmapEvaluatedPropsUBOName, evaluatedPropsUniformBuffer); + auto& uniforms = drawable.mutableUniformBuffers(); + uniforms.addOrReplace(HeatmapEvaluatedPropsUBOName, evaluatedPropsUniformBuffer); if (!drawable.getTileID()) { return; @@ -71,12 +73,12 @@ void HeatmapLayerTweaker::execute(LayerGroupBase& layerGroup, TranslateAnchorType::Viewport, nearClipped, inViewportPixelUnits); - HeatmapDrawableUBO drawableUBO = { + const HeatmapDrawableUBO drawableUBO = { /* .matrix = */ util::cast(matrix), /* .extrude_scale = */ tileID.pixelsToTileUnits(1.0f, static_cast(parameters.state.getZoom())), /* .padding = */ {0}}; - drawable.mutableUniformBuffers().createOrUpdate(HeatmapDrawableUBOName, &drawableUBO, parameters.context); + uniforms.createOrUpdate(HeatmapDrawableUBOName, &drawableUBO, context); }); } diff --git a/src/mbgl/renderer/layers/heatmap_texture_layer_tweaker.cpp b/src/mbgl/renderer/layers/heatmap_texture_layer_tweaker.cpp index 4a7941dca..99708bc0c 100644 --- a/src/mbgl/renderer/layers/heatmap_texture_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/heatmap_texture_layer_tweaker.cpp @@ -41,7 +41,7 @@ void HeatmapTextureLayerTweaker::execute(LayerGroupBase& layerGroup, const auto& size = parameters.staticData.backendSize; mat4 viewportMat; matrix::ortho(viewportMat, 0, size.width, size.height, 0, 0, 1); - HeatmapTextureDrawableUBO drawableUBO = { + const HeatmapTextureDrawableUBO drawableUBO = { /* .matrix = */ util::cast(viewportMat), /* .world = */ {static_cast(size.width), static_cast(size.height)}, /* .opacity = */ evaluated.get(), diff --git a/src/mbgl/renderer/layers/line_layer_tweaker.cpp b/src/mbgl/renderer/layers/line_layer_tweaker.cpp index fecc8a8a5..f100f8792 100644 --- a/src/mbgl/renderer/layers/line_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/line_layer_tweaker.cpp @@ -120,35 +120,55 @@ static constexpr std::string_view LineSDFPropertiesUBOName = "LineSDFPropertiesU void LineLayerTweaker::execute(LayerGroupBase& layerGroup, const RenderTree& renderTree, const PaintParameters& parameters) { + auto& context = parameters.context; const auto& evaluated = static_cast(*evaluatedProperties).evaluated; const auto& crossfade = static_cast(*evaluatedProperties).crossfade; - const LinePropertiesUBO linePropertiesUBO{ - /*color =*/evaluated.get().constantOr(LineColor::defaultValue()), - /*blur =*/evaluated.get().constantOr(LineBlur::defaultValue()), - /*opacity =*/evaluated.get().constantOr(LineOpacity::defaultValue()), - /*gapwidth =*/evaluated.get().constantOr(LineGapWidth::defaultValue()), - /*offset =*/evaluated.get().constantOr(LineOffset::defaultValue()), - /*width =*/evaluated.get().constantOr(LineWidth::defaultValue()), - 0, - {0, 0}}; - const LineGradientPropertiesUBO lineGradientPropertiesUBO{ - /*blur =*/evaluated.get().constantOr(LineBlur::defaultValue()), - /*opacity =*/evaluated.get().constantOr(LineOpacity::defaultValue()), - /*gapwidth =*/evaluated.get().constantOr(LineGapWidth::defaultValue()), - /*offset =*/evaluated.get().constantOr(LineOffset::defaultValue()), - /*width =*/evaluated.get().constantOr(LineWidth::defaultValue()), - 0, - {0, 0}}; - const LineSDFPropertiesUBO lineSDFPropertiesUBO{ - /*color =*/evaluated.get().constantOr(LineColor::defaultValue()), - /*blur =*/evaluated.get().constantOr(LineBlur::defaultValue()), - /*opacity =*/evaluated.get().constantOr(LineOpacity::defaultValue()), - /*gapwidth =*/evaluated.get().constantOr(LineGapWidth::defaultValue()), - /*offset =*/evaluated.get().constantOr(LineOffset::defaultValue()), - /*width =*/evaluated.get().constantOr(LineWidth::defaultValue()), - /*floorwidth =*/evaluated.get().constantOr(LineFloorWidth::defaultValue()), - {0, 0}}; + const auto getLinePropsBuffer = [&]() { + if (!linePropertiesBuffer) { + const LinePropertiesUBO linePropertiesUBO{ + /*color =*/evaluated.get().constantOr(LineColor::defaultValue()), + /*blur =*/evaluated.get().constantOr(LineBlur::defaultValue()), + /*opacity =*/evaluated.get().constantOr(LineOpacity::defaultValue()), + /*gapwidth =*/evaluated.get().constantOr(LineGapWidth::defaultValue()), + /*offset =*/evaluated.get().constantOr(LineOffset::defaultValue()), + /*width =*/evaluated.get().constantOr(LineWidth::defaultValue()), + 0, + {0, 0}}; + linePropertiesBuffer = context.createUniformBuffer(&linePropertiesUBO, sizeof(linePropertiesUBO)); + } + return linePropertiesBuffer; + }; + const auto getLineGradientPropsBuffer = [&]() { + if (!lineGradientPropertiesBuffer) { + const LineGradientPropertiesUBO lineGradientPropertiesUBO{ + /*blur =*/evaluated.get().constantOr(LineBlur::defaultValue()), + /*opacity =*/evaluated.get().constantOr(LineOpacity::defaultValue()), + /*gapwidth =*/evaluated.get().constantOr(LineGapWidth::defaultValue()), + /*offset =*/evaluated.get().constantOr(LineOffset::defaultValue()), + /*width =*/evaluated.get().constantOr(LineWidth::defaultValue()), + 0, + {0, 0}}; + lineGradientPropertiesBuffer = context.createUniformBuffer(&lineGradientPropertiesUBO, + sizeof(lineGradientPropertiesUBO)); + } + return lineGradientPropertiesBuffer; + }; + const auto getLineSDFPropsBuffer = [&]() { + if (!lineSDFPropertiesBuffer) { + const LineSDFPropertiesUBO lineSDFPropertiesUBO{ + /*color =*/evaluated.get().constantOr(LineColor::defaultValue()), + /*blur =*/evaluated.get().constantOr(LineBlur::defaultValue()), + /*opacity =*/evaluated.get().constantOr(LineOpacity::defaultValue()), + /*gapwidth =*/evaluated.get().constantOr(LineGapWidth::defaultValue()), + /*offset =*/evaluated.get().constantOr(LineOffset::defaultValue()), + /*width =*/evaluated.get().constantOr(LineWidth::defaultValue()), + /*floorwidth =*/evaluated.get().constantOr(LineFloorWidth::defaultValue()), + {0, 0}}; + lineSDFPropertiesBuffer = context.createUniformBuffer(&lineSDFPropertiesUBO, sizeof(lineSDFPropertiesUBO)); + } + return lineSDFPropertiesBuffer; + }; layerGroup.observeDrawables([&](gfx::Drawable& drawable) { const auto shader = drawable.getShader(); @@ -175,11 +195,10 @@ void LineLayerTweaker::execute(LayerGroupBase& layerGroup, /*units_to_pixels = */ {1.0f / parameters.pixelsToGLUnits[0], 1.0f / parameters.pixelsToGLUnits[1]}, /*ratio = */ 1.0f / tileID.pixelsToTileUnits(1.0f, static_cast(parameters.state.getZoom())), /*device_pixel_ratio = */ parameters.pixelRatio}; - uniforms.createOrUpdate(LineUBOName, &lineUBO, sizeof(lineUBO), parameters.context); + uniforms.createOrUpdate(LineUBOName, &lineUBO, context); // properties UBO - uniforms.createOrUpdate( - LinePropertiesUBOName, &linePropertiesUBO, sizeof(linePropertiesUBO), parameters.context); + uniforms.addOrReplace(LinePropertiesUBOName, getLinePropsBuffer()); } // gradient line else if (shaderUniforms.get(std::string(LineGradientUBOName))) { @@ -189,13 +208,10 @@ void LineLayerTweaker::execute(LayerGroupBase& layerGroup, /*units_to_pixels = */ {1.0f / parameters.pixelsToGLUnits[0], 1.0f / parameters.pixelsToGLUnits[1]}, /*ratio = */ 1.0f / tileID.pixelsToTileUnits(1.0f, static_cast(parameters.state.getZoom())), /*device_pixel_ratio = */ parameters.pixelRatio}; - uniforms.createOrUpdate(LineGradientUBOName, &lineGradientUBO, sizeof(lineGradientUBO), parameters.context); + uniforms.createOrUpdate(LineGradientUBOName, &lineGradientUBO, context); // properties UBO - uniforms.createOrUpdate(LineGradientPropertiesUBOName, - &lineGradientPropertiesUBO, - sizeof(lineGradientPropertiesUBO), - parameters.context); + uniforms.addOrReplace(LineGradientPropertiesUBOName, getLineGradientPropsBuffer()); } // pattern line else if (shaderUniforms.get(std::string(LinePatternUBOName))) { @@ -219,7 +235,7 @@ void LineLayerTweaker::execute(LayerGroupBase& layerGroup, /*device_pixel_ratio =*/parameters.pixelRatio, /*fade =*/crossfade.t, 0}; - uniforms.createOrUpdate(LinePatternUBOName, &linePatternUBO, sizeof(linePatternUBO), parameters.context); + uniforms.createOrUpdate(LinePatternUBOName, &linePatternUBO, context); // properties UBO const LinePatternPropertiesUBO linePatternPropertiesUBO{ @@ -230,10 +246,7 @@ void LineLayerTweaker::execute(LayerGroupBase& layerGroup, /*width =*/evaluated.get().constantOr(LineWidth::defaultValue()), 0, {0, 0}}; - uniforms.createOrUpdate(LinePatternPropertiesUBOName, - &linePatternPropertiesUBO, - sizeof(linePatternPropertiesUBO), - parameters.context); + uniforms.createOrUpdate(LinePatternPropertiesUBOName, &linePatternPropertiesUBO, context); } // SDF line else if (shaderUniforms.get(std::string(LineSDFUBOName))) { @@ -273,11 +286,10 @@ void LineLayerTweaker::execute(LayerGroupBase& layerGroup, /* sdfgamma = */ static_cast(dashPatternTexture.getSize().width) / (std::min(widthA, widthB) * 256.0f * parameters.pixelRatio) / 2.0f, /* mix = */ crossfade.t}; - uniforms.createOrUpdate(LineSDFUBOName, &lineSDFUBO, sizeof(lineSDFUBO), parameters.context); + uniforms.createOrUpdate(LineSDFUBOName, &lineSDFUBO, context); // properties UBO - uniforms.createOrUpdate( - LineSDFPropertiesUBOName, &lineSDFPropertiesUBO, sizeof(lineSDFPropertiesUBO), parameters.context); + uniforms.addOrReplace(LineSDFPropertiesUBOName, getLineSDFPropsBuffer()); } } }); diff --git a/src/mbgl/renderer/layers/line_layer_tweaker.hpp b/src/mbgl/renderer/layers/line_layer_tweaker.hpp index de45922f7..73e446114 100644 --- a/src/mbgl/renderer/layers/line_layer_tweaker.hpp +++ b/src/mbgl/renderer/layers/line_layer_tweaker.hpp @@ -19,10 +19,14 @@ public: LineLayerTweaker(Immutable properties) : LayerTweaker(properties){}; -public: ~LineLayerTweaker() override = default; void execute(LayerGroupBase&, const RenderTree&, const PaintParameters&) override; + +protected: + gfx::UniformBufferPtr linePropertiesBuffer; + gfx::UniformBufferPtr lineGradientPropertiesBuffer; + gfx::UniformBufferPtr lineSDFPropertiesBuffer; }; } // namespace mbgl diff --git a/src/mbgl/renderer/layers/raster_layer_tweaker.cpp b/src/mbgl/renderer/layers/raster_layer_tweaker.cpp index 1df4f3aca..9f31384d6 100644 --- a/src/mbgl/renderer/layers/raster_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/raster_layer_tweaker.cpp @@ -38,7 +38,7 @@ void RasterLayerTweaker::execute([[maybe_unused]] LayerGroupBase& layerGroup, const auto& evaluated = static_cast(*evaluatedProperties).evaluated; layerGroup.observeDrawables([&](gfx::Drawable& drawable) { - auto spinWeights = [](float spin) -> std::array { + const auto spinWeights = [](float spin) -> std::array { spin = util::deg2radf(spin); const float s = std::sin(spin); const float c = std::cos(spin); @@ -46,14 +46,14 @@ void RasterLayerTweaker::execute([[maybe_unused]] LayerGroupBase& layerGroup, {(2 * c + 1) / 3, (-std::sqrt(3.0f) * s - c + 1) / 3, (std::sqrt(3.0f) * s - c + 1) / 3, 0}}; return spin_weights; }; - auto saturationFactor = [](float saturation) -> float { + const auto saturationFactor = [](float saturation) -> float { if (saturation > 0) { return 1.f - 1.f / (1.001f - saturation); } else { return -saturation; } }; - auto contrastFactor = [](float contrast) -> float { + const auto contrastFactor = [](float contrast) -> float { if (contrast > 0) { return 1 / (1 - contrast); } else { @@ -93,7 +93,7 @@ void RasterLayerTweaker::execute([[maybe_unused]] LayerGroupBase& layerGroup, 0, 0}; auto& uniforms = drawable.mutableUniformBuffers(); - uniforms.createOrUpdate("RasterDrawableUBO", &drawableUBO, sizeof(drawableUBO), parameters.context); + uniforms.createOrUpdate("RasterDrawableUBO", &drawableUBO, parameters.context); }); } diff --git a/src/mbgl/renderer/layers/render_circle_layer.cpp b/src/mbgl/renderer/layers/render_circle_layer.cpp index 8fe55293f..a2431df5c 100644 --- a/src/mbgl/renderer/layers/render_circle_layer.cpp +++ b/src/mbgl/renderer/layers/render_circle_layer.cpp @@ -352,14 +352,17 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders, std::get<0>(paintPropertyBinders.get()->interpolationFactor(zoom)), /* .padding = */ 0}; - tileLayerGroup->observeDrawables(renderPass, tileID, [&](gfx::Drawable& drawable) { - drawable.mutableUniformBuffers().createOrUpdate(CircleInterpolateUBOName, &interpolateUBO, context); - }); - - if (tileLayerGroup->getDrawableCount(renderPass, tileID) > 0) { + // If there are already drawables for this tile, update their UBOs and move on to the next tile. + auto updateExisting = [&](gfx::Drawable& drawable) { + auto& uniforms = drawable.mutableUniformBuffers(); + uniforms.createOrUpdate(CircleInterpolateUBOName, &interpolateUBO, context); + }; + if (0 < tileLayerGroup->observeDrawables(renderPass, tileID, std::move(updateExisting))) { continue; } + const auto interpBuffer = context.createUniformBuffer(&interpolateUBO, sizeof(interpolateUBO)); + gfx::VertexAttributeArray circleVertexAttrs; const auto propertiesAsUniforms = circleVertexAttrs.readDataDrivenPaintPropertiesclearDrawables()) { drawable->setTileID(tileID); - drawable->mutableUniformBuffers().createOrUpdate(CircleInterpolateUBOName, &interpolateUBO, context); + + auto& uniforms = drawable->mutableUniformBuffers(); + uniforms.addOrReplace(CircleInterpolateUBOName, interpBuffer); tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable)); ++stats.drawablesAdded; diff --git a/src/mbgl/renderer/layers/render_fill_layer.cpp b/src/mbgl/renderer/layers/render_fill_layer.cpp index 2eb0bfba8..102fabc6e 100644 --- a/src/mbgl/renderer/layers/render_fill_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_layer.cpp @@ -399,25 +399,25 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders, /* .padding = */ 0, 0}; - // TODO: only update if properties re-evaluated? const FillDrawableTilePropsUBO tileProps = { /* pattern_from = */ patternPosA ? util::cast(patternPosA->tlbr()) : std::array{0}, /* pattern_to = */ patternPosB ? util::cast(patternPosB->tlbr()) : std::array{0}, }; // If we already have drawables for this tile, update them. - if (tileLayerGroup->getDrawableCount(renderPass, tileID) > 0) { - // TODO: Share buffers - tileLayerGroup->observeDrawables(renderPass, tileID, [&](gfx::Drawable& drawable) { - drawable.mutableUniformBuffers().createOrUpdate( - FillLayerTweaker::FillInterpolateUBOName, &interpolateUBO, context); - drawable.mutableUniformBuffers().createOrUpdate( - FillLayerTweaker::FillTilePropsUBOName, &tileProps, context); - }); - + auto updateExisting = [&](gfx::Drawable& drawable) { + auto& uniforms = drawable.mutableUniformBuffers(); + uniforms.createOrUpdate(FillLayerTweaker::FillInterpolateUBOName, &interpolateUBO, context); + uniforms.createOrUpdate(FillLayerTweaker::FillTilePropsUBOName, &tileProps, context); + }; + if (0 < tileLayerGroup->observeDrawables(renderPass, tileID, std::move(updateExisting))) { continue; } + // Share UBO buffers among any drawables created for this tile + const auto interpBuffer = context.createUniformBuffer(&interpolateUBO, sizeof(interpolateUBO)); + const auto tilePropsBuffer = context.createUniformBuffer(&tileProps, sizeof(tileProps)); + // `Fill*Program` all use `style::FillPaintProperties` gfx::VertexAttributeArray vertexAttrs; const auto uniformProps = diff --git a/src/mbgl/renderer/layers/symbol_layer_tweaker.cpp b/src/mbgl/renderer/layers/symbol_layer_tweaker.cpp index 7b332b96b..0dde5c103 100644 --- a/src/mbgl/renderer/layers/symbol_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/symbol_layer_tweaker.cpp @@ -121,11 +121,11 @@ void SymbolLayerTweaker::execute(LayerGroupBase& layerGroup, const auto isText = (symbolData.symbolType == SymbolType::Text); if (isText && !textPaintBuffer) { - auto props = buildPaintUBO(true, evaluated); + const auto props = buildPaintUBO(true, evaluated); textPaintBuffer = parameters.context.createUniformBuffer(&props, sizeof(props)); } if (!isText && !iconPaintBuffer) { - auto props = buildPaintUBO(false, evaluated); + const auto props = buildPaintUBO(false, evaluated); iconPaintBuffer = parameters.context.createUniformBuffer(&props, sizeof(props)); } diff --git a/src/mbgl/renderer/tile_layer_group.cpp b/src/mbgl/renderer/tile_layer_group.cpp index f463ea84c..b835603bd 100644 --- a/src/mbgl/renderer/tile_layer_group.cpp +++ b/src/mbgl/renderer/tile_layer_group.cpp @@ -83,18 +83,20 @@ void TileLayerGroup::addDrawable(mbgl::RenderPass pass, const OverscaledTileID& } } -void TileLayerGroup::observeDrawables(const std::function&& f) { +std::size_t TileLayerGroup::observeDrawables(const std::function&& f) { assert(impl->drawablesByTile.size() == impl->sortedDrawables.size()); for (auto* drawable : impl->sortedDrawables) { f(*drawable); } + return impl->sortedDrawables.size(); } -void TileLayerGroup::observeDrawables(const std::function&& f) const { +std::size_t TileLayerGroup::observeDrawables(const std::function&& f) const { assert(impl->drawablesByTile.size() == impl->sortedDrawables.size()); for (const auto* drawable : impl->sortedDrawables) { f(*drawable); } + return impl->sortedDrawables.size(); } std::size_t TileLayerGroup::observeDrawablesRemove(const std::function&& f) { @@ -114,20 +116,22 @@ std::size_t TileLayerGroup::observeDrawablesRemove(const std::functiondrawablesByTile.size()); } -void TileLayerGroup::observeDrawables(mbgl::RenderPass pass, - const OverscaledTileID& tileID, - const std::function&& f) { +std::size_t TileLayerGroup::observeDrawables(mbgl::RenderPass pass, + const OverscaledTileID& tileID, + const std::function&& f) { assert(impl->drawablesByTile.size() == impl->sortedDrawables.size()); const auto range = impl->drawablesByTile.equal_range({pass, tileID}); std::for_each(range.first, range.second, [&f](const auto& pair) { f(*pair.second); }); + return std::distance(range.first, range.second); } -void TileLayerGroup::observeDrawables(mbgl::RenderPass pass, - const OverscaledTileID& tileID, - const std::function&& f) const { +std::size_t TileLayerGroup::observeDrawables(mbgl::RenderPass pass, + const OverscaledTileID& tileID, + const std::function&& f) const { assert(impl->drawablesByTile.size() == impl->sortedDrawables.size()); const auto range = impl->drawablesByTile.equal_range({pass, tileID}); std::for_each(range.first, range.second, [&f](const auto& pair) { f(*pair.second); }); + return std::distance(range.first, range.second); } std::size_t TileLayerGroup::clearDrawables() { diff --git a/src/mbgl/tile/geometry_tile_worker.cpp b/src/mbgl/tile/geometry_tile_worker.cpp index 8ab89f6a2..65f906875 100644 --- a/src/mbgl/tile/geometry_tile_worker.cpp +++ b/src/mbgl/tile/geometry_tile_worker.cpp @@ -378,7 +378,8 @@ void GeometryTileWorker::parse() { continue; } - std::vector layerIDs(group.size()); + std::vector layerIDs; + layerIDs.reserve(group.size()); for (const auto& layer : group) { layerIDs.push_back(layer->baseImpl->id); }