diff --git a/include/mbgl/gfx/uniform_block.hpp b/include/mbgl/gfx/uniform_block.hpp index 38c0a56a5..4e5740726 100644 --- a/include/mbgl/gfx/uniform_block.hpp +++ b/include/mbgl/gfx/uniform_block.hpp @@ -100,7 +100,8 @@ public: UniformBlockArray& operator=(const UniformBlockArray&); /// Do something with each block - void visit(const std::function& f) { + template + void visit(Func f) { std::for_each(uniformBlockMap.begin(), uniformBlockMap.end(), [&](const auto& kv) { if (kv.second) { f(kv.first, *kv.second); diff --git a/include/mbgl/gfx/vertex_attribute.hpp b/include/mbgl/gfx/vertex_attribute.hpp index 0c622bfd6..ecc5805e1 100644 --- a/include/mbgl/gfx/vertex_attribute.hpp +++ b/include/mbgl/gfx/vertex_attribute.hpp @@ -340,7 +340,8 @@ public: void clear(); /// Do something with each attribute - void visitAttributes(const std::function& f) { + template + void visitAttributes(Func f) { std::for_each(attrs.begin(), attrs.end(), [&](const auto& kv) { if (kv.second) { f(kv.first, *kv.second); @@ -348,19 +349,22 @@ public: }); } - /// Do something with each attribute - void visitAttributes(const std::function& f) const { - std::for_each(attrs.begin(), attrs.end(), [&](const auto& kv) { - if (kv.second) { - f(kv.first, *kv.second); - } - }); - } - - using ResolveDelegate = - std::function&)>; /// Call the provided delegate with each value, providing the override if one exists. - void resolve(const VertexAttributeArray& overrides, ResolveDelegate) const; + template &) */> + void resolve(const VertexAttributeArray& overrides, Func delegate) const { + for (auto& kv : attrs) { + delegate(kv.first, *kv.second, overrides.get(kv.first)); + } + // For OpenGL, the shader attributes are established with reflection, and we have extra + // entries when we share attributes between, e.g., fill and fill-outline drawables. +#if !defined(NDEBUG) && MLN_RENDERER_BACKEND_METAL + // Every override should match a defined attribute. + for (const auto& kv : overrides.attrs) { + const auto hit = attrs.find(kv.first); + assert(hit != attrs.end()); + } +#endif + } VertexAttributeArray& operator=(VertexAttributeArray&&); VertexAttributeArray& operator=(const VertexAttributeArray&); diff --git a/include/mbgl/renderer/layer_group.hpp b/include/mbgl/renderer/layer_group.hpp index 8a7726ea1..4acdfbef9 100644 --- a/include/mbgl/renderer/layer_group.hpp +++ b/include/mbgl/renderer/layer_group.hpp @@ -1,12 +1,15 @@ #pragma once +#include #include #include #include +#include #include #include #include +#include #include namespace mbgl { @@ -37,8 +40,16 @@ using LayerTweakerWeakPtr = std::weak_ptr; A layer-like group of drawables, not a group of layers. */ class LayerGroupBase : public util::SimpleIdentifiable { +public: + enum class Type : uint8_t { + LayerGroup = 0, + TileLayerGroup, + + Invalid = 255 + }; + protected: - LayerGroupBase(int32_t layerIndex, std::string name = std::string()); + LayerGroupBase(int32_t layerIndex, std::string name = std::string(), Type type = Type::Invalid); public: LayerGroupBase(const LayerGroupBase&) = delete; @@ -49,6 +60,9 @@ public: bool getEnabled() const { return enabled; } void setEnabled(bool value) { enabled = value; } + /// Get the type of layer group + Type getType() const noexcept { return type; } + /// Get the name of the layer group const std::string& getName() const { return name; } /// Set the name of the layer group @@ -81,15 +95,6 @@ public: /// Called at the end of each frame virtual void postRender(RenderOrchestrator&, PaintParameters&) {} - /// Call the provided function for each drawable in priority order - virtual std::size_t visitDrawables(const std::function&&) = 0; - virtual std::size_t visitDrawables(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 discard it and false to keep it - /// @return The number of items removed - virtual std::size_t removeDrawablesIf(const std::function&& f) = 0; - /// Attach a tweaker to be run on this layer group for each frame. /// Tweaker lifetime is controlled by the render layer and drawables, the layer group retains a weak reference. void addLayerTweaker(const LayerTweakerPtr& tweaker) { layerTweakers.emplace_back(tweaker); } @@ -97,6 +102,7 @@ public: void runTweakers(const RenderTree&, PaintParameters&); protected: + const Type type; bool enabled = true; int32_t layerIndex; std::vector layerTweakers; @@ -117,27 +123,70 @@ public: std::vector removeDrawables(mbgl::RenderPass, const OverscaledTileID&); void addDrawable(mbgl::RenderPass, const OverscaledTileID&, gfx::UniqueDrawable&&); - std::size_t visitDrawables(const std::function&&) override; - std::size_t visitDrawables(const std::function&&) const override; - std::size_t removeDrawablesIf(const std::function&&) override; + template + std::size_t visitDrawables(Func f) { + assert(drawablesByTile.size() == sortedDrawables.size()); + for (auto* drawable : sortedDrawables) { + f(*drawable); + } + return sortedDrawables.size(); + } + + template + std::size_t removeDrawablesIf(Func f) { + const auto oldSize = drawablesByTile.size(); + for (auto i = drawablesByTile.begin(); i != drawablesByTile.end();) { + auto& drawable = i->second; + if (!f(*drawable)) { + // Not removed, keep going + ++i; + } else { + // Removed, take it out of the collections + sortedDrawables.erase(drawable.get()); + i = drawablesByTile.erase(i); + } + assert(drawablesByTile.size() == sortedDrawables.size()); + } + return (oldSize - drawablesByTile.size()); + } /// Call the provided function for each drawable for the given tile - std::size_t visitDrawables(mbgl::RenderPass, const OverscaledTileID&, const std::function&&); - std::size_t visitDrawables(mbgl::RenderPass, - const OverscaledTileID&, - const std::function&&) const; + template + std::size_t visitDrawables(mbgl::RenderPass pass, const OverscaledTileID& tileID, Func f) { + assert(drawablesByTile.size() == sortedDrawables.size()); + const auto range = 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 clearDrawables() override; void setStencilTiles(RenderTiles); protected: - struct Impl; - std::unique_ptr impl; - // When stencil clipping is enabled for the layer, this is the set // of tile IDs that need to be rendered to the stencil buffer. RenderTiles stencilTiles; + + struct TileLayerGroupTileKey { + mbgl::RenderPass renderPass; + OverscaledTileID tileID; + bool operator==(const TileLayerGroupTileKey& other) const { + return renderPass == other.renderPass && tileID == other.tileID; + } + struct hash { + size_t operator()(const TileLayerGroupTileKey& k) const { + return (std::hash()(k.renderPass) ^ std::hash()(k.tileID) << 1); + } + }; + }; + +private: + using TileMap = std::unordered_multimap; + TileMap drawablesByTile; + + using DrawableMap = std::set; + DrawableMap sortedDrawables; }; /** @@ -154,15 +203,78 @@ public: std::vector removeDrawables(mbgl::RenderPass); void addDrawable(gfx::UniqueDrawable&&); - std::size_t visitDrawables(const std::function&&) override; - std::size_t visitDrawables(const std::function&&) const override; - std::size_t removeDrawablesIf(const std::function&&) override; + template + std::size_t visitDrawables(Func f) { + for (const auto& item : drawables) { + if (item) { + f(*item); + } + } + return drawables.size(); + } + + template + std::size_t removeDrawablesIf(Func f) { + decltype(drawables) newSet; + const auto oldSize = drawables.size(); + while (!drawables.empty()) { + // set members are immutable, since changes could affect its position, so extract each item + gfx::UniqueDrawable drawable = std::move(drawables.extract(drawables.begin()).value()); + if (!f(*drawable)) { + // Not removed, keep it, but in a new set so that if the key value + // has increased, we don't see it again during this iteration. + newSet.emplace_hint(newSet.end(), std::move(drawable)); + } + } + std::swap(drawables, newSet); + return (oldSize - drawables.size()); + } std::size_t clearDrawables() override; protected: - struct Impl; - std::unique_ptr impl; + using DrawableCollection = std::set; + DrawableCollection drawables; }; +template +void visitLayerGroupDrawables(mbgl::LayerGroupBase& layerGroup, Func dg) { + switch (layerGroup.getType()) { + case LayerGroupBase::Type::LayerGroup: { + static_cast(layerGroup).visitDrawables(dg); + break; + } + case LayerGroupBase::Type::TileLayerGroup: { + static_cast(layerGroup).visitDrawables(dg); + break; + } + default: { +#ifndef NDEBUG + mbgl::Log::Error(mbgl::Event::Render, + "Unknown layer group type: " + std::to_string(static_cast(layerGroup.getType()))); +#endif + break; + } + } +} + +template +std::size_t removeLayerGroupDrawablesIf(mbgl::LayerGroupBase& layerGroup, Func dg) { + switch (layerGroup.getType()) { + case LayerGroupBase::Type::LayerGroup: { + return static_cast(layerGroup).removeDrawablesIf(dg); + } + case LayerGroupBase::Type::TileLayerGroup: { + return static_cast(layerGroup).removeDrawablesIf(dg); + } + default: { +#ifndef NDEBUG + mbgl::Log::Error(mbgl::Event::Render, + "Unknown layer group type: " + std::to_string(static_cast(layerGroup.getType()))); +#endif + return 0; + } + } +} + } // namespace mbgl diff --git a/include/mbgl/renderer/render_target.hpp b/include/mbgl/renderer/render_target.hpp index 5375dfef3..e368034af 100644 --- a/include/mbgl/renderer/render_target.hpp +++ b/include/mbgl/renderer/render_target.hpp @@ -53,8 +53,14 @@ public: const LayerGroupBasePtr& getLayerGroup(const int32_t layerIndex) const; /// Execute the given function for each contained layer group - void visitLayerGroups(std::function); - void visitLayerGroups(std::function) const; + template + void visitLayerGroups(Func f) { + for (auto& pair : layerGroupsByLayerIndex) { + if (pair.second) { + f(*pair.second); + } + } + } /// Upload the layer groups void upload(gfx::UploadPass& uploadPass); diff --git a/src/mbgl/gfx/vertex_attribute.cpp b/src/mbgl/gfx/vertex_attribute.cpp index fcde4fa6b..25e8c5fce 100644 --- a/src/mbgl/gfx/vertex_attribute.cpp +++ b/src/mbgl/gfx/vertex_attribute.cpp @@ -151,21 +151,6 @@ void VertexAttributeArray::clear() { attrs.clear(); } -void VertexAttributeArray::resolve(const VertexAttributeArray& overrides, ResolveDelegate delegate) const { - for (auto& kv : attrs) { - delegate(kv.first, *kv.second, overrides.get(kv.first)); - } - // For OpenGL, the shader attributes are established with reflection, and we have extra - // entries when we share attributes between, e.g., fill and fill-outline drawables. -#if !defined(NDEBUG) && MLN_RENDERER_BACKEND_METAL - // Every override should match a defined attribute. - for (const auto& kv : overrides.attrs) { - const auto hit = attrs.find(kv.first); - assert(hit != attrs.end()); - } -#endif -} - const UniqueVertexAttribute& VertexAttributeArray::add(const StringIdentity id, std::unique_ptr&& attr) { const auto result = attrs.insert(std::make_pair(id, std::unique_ptr())); diff --git a/src/mbgl/gl/vertex_attribute_gl.cpp b/src/mbgl/gl/vertex_attribute_gl.cpp index dc8a5eb1e..2f859fea3 100644 --- a/src/mbgl/gl/vertex_attribute_gl.cpp +++ b/src/mbgl/gl/vertex_attribute_gl.cpp @@ -73,10 +73,10 @@ int VertexAttributeGL::getStride(GLenum glType) { } // Copy the transformed type into the buffer, returning true if it works. -template -static bool get(const gfx::VertexAttribute::ElementType& element, uint8_t* buffer, std::function f) { +template +static bool get(const gfx::VertexAttribute::ElementType& element, uint8_t* buffer, Func func) { if (auto* p = std::get_if(&element)) { - *reinterpret_cast(buffer) = f(*p); + *reinterpret_cast(buffer) = func(*p); return true; } return false; diff --git a/src/mbgl/renderer/layer_group.cpp b/src/mbgl/renderer/layer_group.cpp index 8ef50ea9e..caf0cfc2f 100644 --- a/src/mbgl/renderer/layer_group.cpp +++ b/src/mbgl/renderer/layer_group.cpp @@ -7,8 +7,6 @@ #include #include -#include - namespace mbgl { void LayerGroupBase::addDrawable(gfx::UniqueDrawable& drawable) { @@ -29,63 +27,23 @@ void LayerGroupBase::runTweakers(const RenderTree&, PaintParameters& parameters) } } -struct LayerGroup::Impl { - using DrawableCollection = std::set; - DrawableCollection drawables; -}; - LayerGroup::LayerGroup(int32_t layerIndex_, std::size_t /*initialCapacity*/, std::string name_) - : LayerGroupBase(layerIndex_, std::move(name_)), - impl(std::make_unique()) {} + : LayerGroupBase(layerIndex_, std::move(name_), LayerGroupBase::Type::LayerGroup) {} LayerGroup::~LayerGroup() = default; std::size_t LayerGroup::getDrawableCount() const { - return impl->drawables.size(); + return drawables.size(); } void LayerGroup::addDrawable(gfx::UniqueDrawable&& drawable) { LayerGroupBase::addDrawable(drawable); - impl->drawables.emplace(std::move(drawable)); -} - -std::size_t LayerGroup::visitDrawables(const std::function&& f) { - for (const auto& item : impl->drawables) { - if (item) { - f(*item); - } - } - return impl->drawables.size(); -} - -std::size_t LayerGroup::visitDrawables(const std::function&& f) const { - for (const auto& item : impl->drawables) { - if (item) { - f(*item); - } - } - return impl->drawables.size(); -} - -std::size_t LayerGroup::removeDrawablesIf(const std::function&& f) { - decltype(impl->drawables) newSet; - const auto oldSize = impl->drawables.size(); - while (!impl->drawables.empty()) { - // set members are immutable, since changes could affect its position, so extract each item - gfx::UniqueDrawable drawable = std::move(impl->drawables.extract(impl->drawables.begin()).value()); - if (!f(*drawable)) { - // Not removed, keep it, but in a new set so that if the key value - // has increased, we don't see it again during this iteration. - newSet.emplace_hint(newSet.end(), std::move(drawable)); - } - } - std::swap(impl->drawables, newSet); - return (oldSize - impl->drawables.size()); + drawables.emplace(std::move(drawable)); } std::size_t LayerGroup::clearDrawables() { - const auto count = impl->drawables.size(); - impl->drawables.clear(); + const auto count = drawables.size(); + drawables.clear(); return count; } diff --git a/src/mbgl/renderer/layers/background_layer_tweaker.cpp b/src/mbgl/renderer/layers/background_layer_tweaker.cpp index 74c577e58..384cfc742 100644 --- a/src/mbgl/renderer/layers/background_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/background_layer_tweaker.cpp @@ -52,7 +52,7 @@ void BackgroundLayerTweaker::execute(LayerGroupBase& layerGroup, const PaintPara layerGroup.setEnabled(true); std::optional samplerLocation{}; - layerGroup.visitDrawables([&](gfx::Drawable& drawable) { + visitLayerGroupDrawables(layerGroup, [&](gfx::Drawable& drawable) { assert(drawable.getTileID()); if (!drawable.getTileID() || !checkTweakDrawable(drawable)) { return; diff --git a/src/mbgl/renderer/layers/circle_layer_tweaker.cpp b/src/mbgl/renderer/layers/circle_layer_tweaker.cpp index 321040a70..ebeab47ec 100644 --- a/src/mbgl/renderer/layers/circle_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/circle_layer_tweaker.cpp @@ -106,7 +106,7 @@ void CircleLayerTweaker::execute(LayerGroupBase& layerGroup, const PaintParamete evaluatedPropsUniformBuffer = context.createUniformBuffer(&evaluatedPropsUBO, sizeof(evaluatedPropsUBO)); } - layerGroup.visitDrawables([&](gfx::Drawable& drawable) { + visitLayerGroupDrawables(layerGroup, [&](gfx::Drawable& drawable) { assert(drawable.getTileID() || !"Circles only render with tiles"); if (!drawable.getTileID() || !checkTweakDrawable(drawable)) { return; diff --git a/src/mbgl/renderer/layers/collision_layer_tweaker.cpp b/src/mbgl/renderer/layers/collision_layer_tweaker.cpp index c9622a0aa..a5b9f9a51 100644 --- a/src/mbgl/renderer/layers/collision_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/collision_layer_tweaker.cpp @@ -36,7 +36,7 @@ void CollisionLayerTweaker::execute(LayerGroupBase& layerGroup, const PaintParam const auto debugGroup = parameters.encoder->createDebugGroup(label.c_str()); #endif - layerGroup.visitDrawables([&](gfx::Drawable& drawable) { + visitLayerGroupDrawables(layerGroup, [&](gfx::Drawable& drawable) { if (!drawable.getTileID() || !drawable.getData() || !checkTweakDrawable(drawable)) { return; } diff --git a/src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.cpp b/src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.cpp index 55161b7a3..e9c4e51e2 100644 --- a/src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.cpp @@ -108,7 +108,7 @@ void FillExtrusionLayerTweaker::execute(LayerGroupBase& layerGroup, const PaintP } #endif - layerGroup.visitDrawables([&](gfx::Drawable& drawable) { + visitLayerGroupDrawables(layerGroup, [&](gfx::Drawable& drawable) { if (!drawable.getTileID() || !checkTweakDrawable(drawable)) { return; } diff --git a/src/mbgl/renderer/layers/fill_layer_tweaker.cpp b/src/mbgl/renderer/layers/fill_layer_tweaker.cpp index 52e7e8b1f..64ff197ba 100644 --- a/src/mbgl/renderer/layers/fill_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/fill_layer_tweaker.cpp @@ -231,7 +231,7 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup, const PaintParameters const auto intZoom = parameters.state.getIntegerZoom(); const auto pixelRatio = parameters.pixelRatio; - layerGroup.visitDrawables([&](gfx::Drawable& drawable) { + visitLayerGroupDrawables(layerGroup, [&](gfx::Drawable& drawable) { if (!drawable.getTileID() || !checkTweakDrawable(drawable)) { return; } diff --git a/src/mbgl/renderer/layers/heatmap_layer_tweaker.cpp b/src/mbgl/renderer/layers/heatmap_layer_tweaker.cpp index 70b7bc2e6..7fd4e6b22 100644 --- a/src/mbgl/renderer/layers/heatmap_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/heatmap_layer_tweaker.cpp @@ -77,7 +77,7 @@ void HeatmapLayerTweaker::execute(LayerGroupBase& layerGroup, const PaintParamet sizeof(evaluatedPropsUBO)); } - layerGroup.visitDrawables([&](gfx::Drawable& drawable) { + visitLayerGroupDrawables(layerGroup, [&](gfx::Drawable& drawable) { if (!drawable.getTileID() || !checkTweakDrawable(drawable)) { return; } diff --git a/src/mbgl/renderer/layers/heatmap_texture_layer_tweaker.cpp b/src/mbgl/renderer/layers/heatmap_texture_layer_tweaker.cpp index 99fb62e04..98752c45d 100644 --- a/src/mbgl/renderer/layers/heatmap_texture_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/heatmap_texture_layer_tweaker.cpp @@ -30,7 +30,7 @@ void HeatmapTextureLayerTweaker::execute(LayerGroupBase& layerGroup, const Paint const auto debugGroup = parameters.encoder->createDebugGroup(label.c_str()); #endif - layerGroup.visitDrawables([&](gfx::Drawable& drawable) { + visitLayerGroupDrawables(layerGroup, [&](gfx::Drawable& drawable) { if (!checkTweakDrawable(drawable)) { return; } diff --git a/src/mbgl/renderer/layers/hillshade_layer_tweaker.cpp b/src/mbgl/renderer/layers/hillshade_layer_tweaker.cpp index 0886ab272..e4e817c28 100644 --- a/src/mbgl/renderer/layers/hillshade_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/hillshade_layer_tweaker.cpp @@ -52,7 +52,7 @@ void HillshadeLayerTweaker::execute(LayerGroupBase& layerGroup, const PaintParam sizeof(evaluatedPropsUBO)); } - layerGroup.visitDrawables([&](gfx::Drawable& drawable) { + visitLayerGroupDrawables(layerGroup, [&](gfx::Drawable& drawable) { if (!drawable.getTileID() || !checkTweakDrawable(drawable)) { return; } diff --git a/src/mbgl/renderer/layers/hillshade_prepare_layer_tweaker.cpp b/src/mbgl/renderer/layers/hillshade_prepare_layer_tweaker.cpp index 446ffbc25..d09ae4d47 100644 --- a/src/mbgl/renderer/layers/hillshade_prepare_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/hillshade_prepare_layer_tweaker.cpp @@ -39,7 +39,7 @@ void HillshadePrepareLayerTweaker::execute(LayerGroupBase& layerGroup, const Pai const auto debugGroup = parameters.encoder->createDebugGroup(label.c_str()); #endif - layerGroup.visitDrawables([&](gfx::Drawable& drawable) { + visitLayerGroupDrawables(layerGroup, [&](gfx::Drawable& drawable) { if (!drawable.getTileID() || !drawable.getData() || !checkTweakDrawable(drawable)) { return; } diff --git a/src/mbgl/renderer/layers/line_layer_tweaker.cpp b/src/mbgl/renderer/layers/line_layer_tweaker.cpp index 9c1f72693..6b8608cad 100644 --- a/src/mbgl/renderer/layers/line_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/line_layer_tweaker.cpp @@ -117,7 +117,7 @@ void LineLayerTweaker::execute(LayerGroupBase& layerGroup, const PaintParameters } #endif - layerGroup.visitDrawables([&](gfx::Drawable& drawable) { + visitLayerGroupDrawables(layerGroup, [&](gfx::Drawable& drawable) { const auto shader = drawable.getShader(); if (!drawable.getTileID() || !shader || !checkTweakDrawable(drawable)) { return; diff --git a/src/mbgl/renderer/layers/raster_layer_tweaker.cpp b/src/mbgl/renderer/layers/raster_layer_tweaker.cpp index 501b119a3..922d40047 100644 --- a/src/mbgl/renderer/layers/raster_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/raster_layer_tweaker.cpp @@ -23,7 +23,7 @@ void RasterLayerTweaker::execute([[maybe_unused]] LayerGroupBase& layerGroup, [[maybe_unused]] const PaintParameters& parameters) { const auto& evaluated = static_cast(*evaluatedProperties).evaluated; - layerGroup.visitDrawables([&](gfx::Drawable& drawable) { + visitLayerGroupDrawables(layerGroup, [&](gfx::Drawable& drawable) { if (!checkTweakDrawable(drawable)) { return; } diff --git a/src/mbgl/renderer/layers/render_raster_layer.cpp b/src/mbgl/renderer/layers/render_raster_layer.cpp index 76d065715..c47f8f945 100644 --- a/src/mbgl/renderer/layers/render_raster_layer.cpp +++ b/src/mbgl/renderer/layers/render_raster_layer.cpp @@ -425,8 +425,9 @@ void RenderRasterLayer::update(gfx::ShaderRegistry& shaders, } else if (renderTiles) { // Remove existing drawables that are no longer in the cover set if (layerGroup) { - stats.drawablesRemoved += layerGroup->removeDrawablesIf( - [&](gfx::Drawable& drawable) { return drawable.getTileID() && !hasRenderTile(*drawable.getTileID()); }); + stats.drawablesRemoved += removeLayerGroupDrawablesIf(*layerGroup, [&](gfx::Drawable& drawable) { + return drawable.getTileID() && !hasRenderTile(*drawable.getTileID()); + }); } else { // Set up a tile layer group if (auto layerGroup_ = context.createTileLayerGroup(layerIndex, /*initialCapacity=*/64, getID())) { diff --git a/src/mbgl/renderer/layers/symbol_layer_tweaker.cpp b/src/mbgl/renderer/layers/symbol_layer_tweaker.cpp index 6505859f9..2ef06ead3 100644 --- a/src/mbgl/renderer/layers/symbol_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/symbol_layer_tweaker.cpp @@ -105,7 +105,7 @@ void SymbolLayerTweaker::execute(LayerGroupBase& layerGroup, const PaintParamete /*.pad1=*/0, /*.pad2=*/{0, 0}}; - layerGroup.visitDrawables([&](gfx::Drawable& drawable) { + visitLayerGroupDrawables(layerGroup, [&](gfx::Drawable& drawable) { if (!drawable.getTileID() || !drawable.getData()) { return; } diff --git a/src/mbgl/renderer/render_layer.cpp b/src/mbgl/renderer/render_layer.cpp index fcbdf4a9a..4e1f3e208 100644 --- a/src/mbgl/renderer/render_layer.cpp +++ b/src/mbgl/renderer/render_layer.cpp @@ -84,7 +84,7 @@ void RenderLayer::replaceTweaker(LayerTweakerPtr& curTweaker, if (group) { group->addLayerTweaker(newTweaker); - group->visitDrawables([&](gfx::Drawable& drawable) { + visitLayerGroupDrawables(*group, [&](gfx::Drawable& drawable) { if (drawable.getLayerTweaker() == prevTweaker) { drawable.setLayerTweaker(newTweaker); } @@ -166,30 +166,6 @@ const LayerRenderData* RenderLayer::getRenderDataForPass(const RenderTile& tile, } #if MLN_DRAWABLE_RENDERER -bool RenderLayer::updateTile(RenderPass renderPass, - const OverscaledTileID& tileID, - std::function update) { - bool anyUpdated = false; - if (const auto tileGroup = static_cast(layerGroup.get())) { - bool unUpdatedDrawables = false; - tileGroup->visitDrawables(renderPass, tileID, [&](gfx::Drawable& drawable) { - if (update(drawable)) { - anyUpdated = true; - } else { - unUpdatedDrawables = true; - } - }); - - // If any are updated, the caller shouldn't add new ones. - // If none are updated and some were skipped, remove those. - // This is to handle the case that the style layer changes but the bucket is not re-created. - if (!anyUpdated && unUpdatedDrawables) { - removeTile(renderPass, tileID); - } - } - return anyUpdated; -} - std::size_t RenderLayer::removeTile(RenderPass renderPass, const OverscaledTileID& tileID) { if (const auto tileGroup = static_cast(layerGroup.get())) { const auto n = tileGroup->removeDrawables(renderPass, tileID).size(); diff --git a/src/mbgl/renderer/render_layer.hpp b/src/mbgl/renderer/render_layer.hpp index 7e37afce9..8d2ae82fa 100644 --- a/src/mbgl/renderer/render_layer.hpp +++ b/src/mbgl/renderer/render_layer.hpp @@ -8,6 +8,7 @@ #if MLN_DRAWABLE_RENDERER #include +#include #include #include #endif // MLN_DRAWABLE_RENDERER @@ -19,7 +20,6 @@ namespace mbgl { class Bucket; class DynamicFeatureIndex; -class LayerGroupBase; class LineAtlas; class PropertyEvaluationParameters; class PaintParameters; @@ -218,9 +218,28 @@ protected: /// @param updateFunction A function that updates a single drawable. Should return true if the drawable /// was updated or false if it was skipped because it's for a previous style. /// @return true if drawables were updated - bool updateTile(RenderPass renderPass, - const OverscaledTileID& tileID, - std::function updateFunction); + template + bool updateTile(RenderPass renderPass, const OverscaledTileID& tileID, Func update) { + bool anyUpdated = false; + if (const auto tileGroup = static_cast(layerGroup.get())) { + bool unUpdatedDrawables = false; + tileGroup->visitDrawables(renderPass, tileID, [&](gfx::Drawable& drawable) { + if (update(drawable)) { + anyUpdated = true; + } else { + unUpdatedDrawables = true; + } + }); + + // If any are updated, the caller shouldn't add new ones. + // If none are updated and some were skipped, remove those. + // This is to handle the case that the style layer changes but the bucket is not re-created. + if (!anyUpdated && unUpdatedDrawables) { + removeTile(renderPass, tileID); + } + } + return anyUpdated; + } /// Remove all drawables for the tile from the layer group /// @return The number of drawables actually removed. diff --git a/src/mbgl/renderer/render_orchestrator.cpp b/src/mbgl/renderer/render_orchestrator.cpp index a67a46dff..ecf41d8ec 100644 --- a/src/mbgl/renderer/render_orchestrator.cpp +++ b/src/mbgl/renderer/render_orchestrator.cpp @@ -878,22 +878,6 @@ int32_t RenderOrchestrator::maxLayerIndex() const { return -1; } -void RenderOrchestrator::visitLayerGroups(std::function f) { - for (auto& pair : layerGroupsByLayerIndex) { - if (pair.second) { - f(*pair.second); - } - } -} - -void RenderOrchestrator::visitLayerGroups(std::function f) const { - for (const auto& pair : layerGroupsByLayerIndex) { - if (pair.second) { - f(*pair.second); - } - } -} - void RenderOrchestrator::updateLayers(gfx::ShaderRegistry& shaders, gfx::Context& context, const TransformState& state, @@ -944,40 +928,12 @@ bool RenderOrchestrator::removeRenderTarget(const RenderTargetPtr& renderTarget) } } -void RenderOrchestrator::visitRenderTargets(std::function f) { - for (auto& renderTarget : renderTargets) { - f(*renderTarget); - } -} - -void RenderOrchestrator::visitRenderTargets(std::function f) const { - for (const auto& renderTarget : renderTargets) { - f(*renderTarget); - } -} - void RenderOrchestrator::updateDebugLayerGroups(const RenderTree& renderTree, PaintParameters& parameters) { for (const RenderItem& item : renderTree.getSourceRenderItems()) { item.updateDebugDrawables(debugLayerGroups, parameters); } } -void RenderOrchestrator::visitDebugLayerGroups(std::function f) { - for (auto& pair : debugLayerGroups) { - if (pair.second) { - f(*pair.second); - } - } -} - -void RenderOrchestrator::visitDebugLayerGroups(std::function f) const { - for (const auto& pair : debugLayerGroups) { - if (pair.second) { - f(*pair.second); - } - } -} - #endif // MLN_DRAWABLE_RENDERER void RenderOrchestrator::onGlyphsError(const FontStack& fontStack, diff --git a/src/mbgl/renderer/render_orchestrator.hpp b/src/mbgl/renderer/render_orchestrator.hpp index eab0728ab..8df4d0b39 100644 --- a/src/mbgl/renderer/render_orchestrator.hpp +++ b/src/mbgl/renderer/render_orchestrator.hpp @@ -102,10 +102,17 @@ public: bool removeLayerGroup(const LayerGroupBasePtr&); size_t numLayerGroups() const noexcept; int32_t maxLayerIndex() const; - void visitLayerGroups(std::function); - void visitLayerGroups(std::function) const; void updateLayerIndex(LayerGroupBasePtr, int32_t newIndex); + template + void visitLayerGroups(Func f) { + for (auto& pair : layerGroupsByLayerIndex) { + if (pair.second) { + f(*pair.second); + } + } + } + void updateLayers(gfx::ShaderRegistry&, gfx::Context&, const TransformState&, @@ -116,12 +123,24 @@ public: bool addRenderTarget(RenderTargetPtr); bool removeRenderTarget(const RenderTargetPtr&); - void visitRenderTargets(std::function f); - void visitRenderTargets(std::function f) const; + + template + void visitRenderTargets(Func f) { + for (auto& renderTarget : renderTargets) { + f(*renderTarget); + } + } void updateDebugLayerGroups(const RenderTree& renderTree, PaintParameters& parameters); - void visitDebugLayerGroups(std::function); - void visitDebugLayerGroups(std::function) const; + + template + void visitDebugLayerGroups(Func f) { + for (auto& pair : debugLayerGroups) { + if (pair.second) { + f(*pair.second); + } + } + } #endif const ZoomHistory& getZoomHistory() const { return zoomHistory; } diff --git a/src/mbgl/renderer/render_target.cpp b/src/mbgl/renderer/render_target.cpp index 4d707d13e..5ceb64a21 100644 --- a/src/mbgl/renderer/render_target.cpp +++ b/src/mbgl/renderer/render_target.cpp @@ -60,22 +60,6 @@ const LayerGroupBasePtr& RenderTarget::getLayerGroup(const int32_t layerIndex) c return (hit == layerGroupsByLayerIndex.end()) ? no_group : hit->second; } -void RenderTarget::visitLayerGroups(std::function f) { - for (auto& pair : layerGroupsByLayerIndex) { - if (pair.second) { - f(*pair.second); - } - } -} - -void RenderTarget::visitLayerGroups(std::function f) const { - for (const auto& pair : layerGroupsByLayerIndex) { - if (pair.second) { - f(*pair.second); - } - } -} - void RenderTarget::upload(gfx::UploadPass& uploadPass) { visitLayerGroups(([&](LayerGroupBase& layerGroup) { layerGroup.upload(uploadPass); })); } diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp index 87498ff47..1c339f335 100644 --- a/src/mbgl/renderer/renderer_impl.cpp +++ b/src/mbgl/renderer/renderer_impl.cpp @@ -324,7 +324,7 @@ void Renderer::Impl::render(const RenderTree& renderTree, { const auto debugGroup(parameters.renderPass->createDebugGroup("debug")); orchestrator.visitDebugLayerGroups([&](LayerGroupBase& layerGroup) { - layerGroup.visitDrawables([&](gfx::Drawable& drawable) { drawable.draw(parameters); }); + visitLayerGroupDrawables(layerGroup, [&](gfx::Drawable& drawable) { drawable.draw(parameters); }); }); } }; diff --git a/src/mbgl/renderer/tile_layer_group.cpp b/src/mbgl/renderer/tile_layer_group.cpp index e79263605..ea0a607e8 100644 --- a/src/mbgl/renderer/tile_layer_group.cpp +++ b/src/mbgl/renderer/tile_layer_group.cpp @@ -9,136 +9,64 @@ namespace mbgl { -struct TileLayerGroupTileKey { - mbgl::RenderPass renderPass; - OverscaledTileID tileID; - bool operator==(const TileLayerGroupTileKey& other) const { - return renderPass == other.renderPass && tileID == other.tileID; - } - struct hash { - size_t operator()(const mbgl::TileLayerGroupTileKey& k) const { - return (std::hash()(k.renderPass) ^ std::hash()(k.tileID) << 1); - } - }; -}; - -struct TileLayerGroup::Impl { - Impl(std::size_t initialCapacity) { drawablesByTile.reserve(initialCapacity); } - - using TileMap = std::unordered_multimap; - TileMap drawablesByTile; - - using DrawableMap = std::set; - DrawableMap sortedDrawables; -}; - -LayerGroupBase::LayerGroupBase(int32_t layerIndex_, std::string name_) - : layerIndex(layerIndex_), +LayerGroupBase::LayerGroupBase(int32_t layerIndex_, std::string name_, Type type_) + : type(type_), + layerIndex(layerIndex_), name(std::move(name_)) {} TileLayerGroup::TileLayerGroup(int32_t layerIndex_, std::size_t initialCapacity, std::string name_) - : LayerGroupBase(layerIndex_, std::move(name_)), - impl(std::make_unique(initialCapacity)) {} + : LayerGroupBase(layerIndex_, std::move(name_), LayerGroupBase::Type::TileLayerGroup) { + drawablesByTile.reserve(initialCapacity); +} TileLayerGroup::~TileLayerGroup() = default; std::size_t TileLayerGroup::getDrawableCount() const { - return impl->drawablesByTile.size(); + return drawablesByTile.size(); } static const gfx::UniqueDrawable no_tile; std::size_t TileLayerGroup::getDrawableCount(mbgl::RenderPass pass, const OverscaledTileID& id) const { - assert(impl->drawablesByTile.size() == impl->sortedDrawables.size()); - const auto range = impl->drawablesByTile.equal_range({pass, id}); + assert(drawablesByTile.size() == sortedDrawables.size()); + const auto range = drawablesByTile.equal_range({pass, id}); return std::distance(range.first, range.second); } std::vector TileLayerGroup::removeDrawables(mbgl::RenderPass pass, const OverscaledTileID& id) { - assert(impl->drawablesByTile.size() == impl->sortedDrawables.size()); - const auto range = impl->drawablesByTile.equal_range({pass, id}); + assert(drawablesByTile.size() == sortedDrawables.size()); + const auto range = drawablesByTile.equal_range({pass, id}); std::vector result(std::distance(range.first, range.second)); std::transform( std::make_move_iterator(range.first), std::make_move_iterator(range.second), result.begin(), [](auto&& pair) { return std::move(pair.second); }); - impl->drawablesByTile.erase(range.first, range.second); + drawablesByTile.erase(range.first, range.second); std::for_each(result.begin(), result.end(), [&](const auto& item) { - const auto hit = impl->sortedDrawables.find(item.get()); - assert(hit != impl->sortedDrawables.end()); - if (hit != impl->sortedDrawables.end()) { - impl->sortedDrawables.erase(hit); + const auto hit = sortedDrawables.find(item.get()); + assert(hit != sortedDrawables.end()); + if (hit != sortedDrawables.end()) { + sortedDrawables.erase(hit); } }); return result; } void TileLayerGroup::addDrawable(mbgl::RenderPass pass, const OverscaledTileID& id, gfx::UniqueDrawable&& drawable) { - assert(impl->drawablesByTile.size() == impl->sortedDrawables.size()); + assert(drawablesByTile.size() == sortedDrawables.size()); if (drawable) { LayerGroupBase::addDrawable(drawable); - [[maybe_unused]] const auto result = impl->sortedDrawables.insert(drawable.get()); + [[maybe_unused]] const auto result = sortedDrawables.insert(drawable.get()); assert(result.second); - impl->drawablesByTile.insert(std::make_pair(TileLayerGroupTileKey{pass, id}, std::move(drawable))); + drawablesByTile.insert(std::make_pair(TileLayerGroupTileKey{pass, id}, std::move(drawable))); } } -std::size_t TileLayerGroup::visitDrawables(const std::function&& f) { - assert(impl->drawablesByTile.size() == impl->sortedDrawables.size()); - for (auto* drawable : impl->sortedDrawables) { - f(*drawable); - } - return impl->sortedDrawables.size(); -} - -std::size_t TileLayerGroup::visitDrawables(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::removeDrawablesIf(const std::function&& f) { - const auto oldSize = impl->drawablesByTile.size(); - for (auto i = impl->drawablesByTile.begin(); i != impl->drawablesByTile.end();) { - auto& drawable = i->second; - if (!f(*drawable)) { - // Not removed, keep going - ++i; - } else { - // Removed, take it out of the collections - impl->sortedDrawables.erase(drawable.get()); - i = impl->drawablesByTile.erase(i); - } - assert(impl->drawablesByTile.size() == impl->sortedDrawables.size()); - } - return (oldSize - impl->drawablesByTile.size()); -} - -std::size_t TileLayerGroup::visitDrawables(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); -} - -std::size_t TileLayerGroup::visitDrawables(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() { - const auto count = impl->drawablesByTile.size(); - assert(count == impl->sortedDrawables.size()); - impl->sortedDrawables.clear(); - impl->drawablesByTile.clear(); + const auto count = drawablesByTile.size(); + assert(count == sortedDrawables.size()); + sortedDrawables.clear(); + drawablesByTile.clear(); return count; }