Don't use std::function in the renderer hot paths (#1883)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
mwilsnd
2023-11-27 10:36:03 -05:00
committed by GitHub
parent bf472b0703
commit 71d4ceabcd
27 changed files with 260 additions and 311 deletions

View File

@@ -100,7 +100,8 @@ public:
UniformBlockArray& operator=(const UniformBlockArray&);
/// Do something with each block
void visit(const std::function<void(const StringIdentity, const UniformBlock&)>& f) {
template <typename Func /* void(const StringIdentity, const UniformBlock&) */>
void visit(Func f) {
std::for_each(uniformBlockMap.begin(), uniformBlockMap.end(), [&](const auto& kv) {
if (kv.second) {
f(kv.first, *kv.second);

View File

@@ -340,7 +340,8 @@ public:
void clear();
/// Do something with each attribute
void visitAttributes(const std::function<void(const StringIdentity, VertexAttribute&)>& f) {
template <typename Func /* void(StringIdentity, VertexAttribute&) */>
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<void(const StringIdentity, const VertexAttribute&)>& f) const {
std::for_each(attrs.begin(), attrs.end(), [&](const auto& kv) {
if (kv.second) {
f(kv.first, *kv.second);
}
});
}
using ResolveDelegate =
std::function<void(const StringIdentity, VertexAttribute&, const std::unique_ptr<VertexAttribute>&)>;
/// Call the provided delegate with each value, providing the override if one exists.
void resolve(const VertexAttributeArray& overrides, ResolveDelegate) const;
template <typename Func /* void(const StringIdentity, VertexAttribute&, const std::unique_ptr<VertexAttribute>&) */>
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&);

View File

@@ -1,12 +1,15 @@
#pragma once
#include <mbgl/gfx/drawable.hpp>
#include <mbgl/renderer/render_pass.hpp>
#include <mbgl/tile/tile_id.hpp>
#include <mbgl/util/identity.hpp>
#include <mbgl/util/logging.hpp>
#include <functional>
#include <memory>
#include <string>
#include <set>
#include <vector>
namespace mbgl {
@@ -37,8 +40,16 @@ using LayerTweakerWeakPtr = std::weak_ptr<LayerTweaker>;
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<void(gfx::Drawable&)>&&) = 0;
virtual std::size_t visitDrawables(const std::function<void(const gfx::Drawable&)>&&) 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<bool(gfx::Drawable&)>&& 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<LayerTweakerWeakPtr> layerTweakers;
@@ -117,27 +123,70 @@ public:
std::vector<gfx::UniqueDrawable> removeDrawables(mbgl::RenderPass, const OverscaledTileID&);
void addDrawable(mbgl::RenderPass, const OverscaledTileID&, gfx::UniqueDrawable&&);
std::size_t visitDrawables(const std::function<void(gfx::Drawable&)>&&) override;
std::size_t visitDrawables(const std::function<void(const gfx::Drawable&)>&&) const override;
std::size_t removeDrawablesIf(const std::function<bool(gfx::Drawable&)>&&) override;
template <typename Func /* void(gfx::Drawable&) */>
std::size_t visitDrawables(Func f) {
assert(drawablesByTile.size() == sortedDrawables.size());
for (auto* drawable : sortedDrawables) {
f(*drawable);
}
return sortedDrawables.size();
}
template <typename Func /* bool(gfx::Drawable&) */>
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<void(gfx::Drawable&)>&&);
std::size_t visitDrawables(mbgl::RenderPass,
const OverscaledTileID&,
const std::function<void(const gfx::Drawable&)>&&) const;
template <typename Func /* void(gfx::Drawable&) */>
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> 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<mbgl::RenderPass>()(k.renderPass) ^ std::hash<OverscaledTileID>()(k.tileID) << 1);
}
};
};
private:
using TileMap = std::unordered_multimap<TileLayerGroupTileKey, gfx::UniqueDrawable, TileLayerGroupTileKey::hash>;
TileMap drawablesByTile;
using DrawableMap = std::set<gfx::Drawable*, gfx::DrawableLessByPriority>;
DrawableMap sortedDrawables;
};
/**
@@ -154,15 +203,78 @@ public:
std::vector<gfx::UniqueDrawable> removeDrawables(mbgl::RenderPass);
void addDrawable(gfx::UniqueDrawable&&);
std::size_t visitDrawables(const std::function<void(gfx::Drawable&)>&&) override;
std::size_t visitDrawables(const std::function<void(const gfx::Drawable&)>&&) const override;
std::size_t removeDrawablesIf(const std::function<bool(gfx::Drawable&)>&&) override;
template <typename Func /* void(gfx::Drawable&) */>
std::size_t visitDrawables(Func f) {
for (const auto& item : drawables) {
if (item) {
f(*item);
}
}
return drawables.size();
}
template <typename Func /* bool(gfx::Drawable&) */>
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> impl;
using DrawableCollection = std::set<gfx::UniqueDrawable, gfx::DrawableLessByPriority>;
DrawableCollection drawables;
};
template <typename Func /* void(gfx::Drawable&) */>
void visitLayerGroupDrawables(mbgl::LayerGroupBase& layerGroup, Func dg) {
switch (layerGroup.getType()) {
case LayerGroupBase::Type::LayerGroup: {
static_cast<LayerGroup&>(layerGroup).visitDrawables(dg);
break;
}
case LayerGroupBase::Type::TileLayerGroup: {
static_cast<TileLayerGroup&>(layerGroup).visitDrawables(dg);
break;
}
default: {
#ifndef NDEBUG
mbgl::Log::Error(mbgl::Event::Render,
"Unknown layer group type: " + std::to_string(static_cast<uint8_t>(layerGroup.getType())));
#endif
break;
}
}
}
template <typename Func /* bool(gfx::Drawable&) */>
std::size_t removeLayerGroupDrawablesIf(mbgl::LayerGroupBase& layerGroup, Func dg) {
switch (layerGroup.getType()) {
case LayerGroupBase::Type::LayerGroup: {
return static_cast<LayerGroup&>(layerGroup).removeDrawablesIf(dg);
}
case LayerGroupBase::Type::TileLayerGroup: {
return static_cast<TileLayerGroup&>(layerGroup).removeDrawablesIf(dg);
}
default: {
#ifndef NDEBUG
mbgl::Log::Error(mbgl::Event::Render,
"Unknown layer group type: " + std::to_string(static_cast<uint8_t>(layerGroup.getType())));
#endif
return 0;
}
}
}
} // namespace mbgl

View File

@@ -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(LayerGroupBase&)>);
void visitLayerGroups(std::function<void(const LayerGroupBase&)>) const;
template <typename Func /* void(LayerGroupBase&) */>
void visitLayerGroups(Func f) {
for (auto& pair : layerGroupsByLayerIndex) {
if (pair.second) {
f(*pair.second);
}
}
}
/// Upload the layer groups
void upload(gfx::UploadPass& uploadPass);

View File

@@ -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<VertexAttribute>&& attr) {
const auto result = attrs.insert(std::make_pair(id, std::unique_ptr<VertexAttribute>()));

View File

@@ -73,10 +73,10 @@ int VertexAttributeGL::getStride(GLenum glType) {
}
// Copy the transformed type into the buffer, returning true if it works.
template <typename T, typename R>
static bool get(const gfx::VertexAttribute::ElementType& element, uint8_t* buffer, std::function<R(T)> f) {
template <typename T, typename R, typename Func /* R(T) */>
static bool get(const gfx::VertexAttribute::ElementType& element, uint8_t* buffer, Func func) {
if (auto* p = std::get_if<T>(&element)) {
*reinterpret_cast<R*>(buffer) = f(*p);
*reinterpret_cast<R*>(buffer) = func(*p);
return true;
}
return false;

View File

@@ -7,8 +7,6 @@
#include <mbgl/renderer/render_orchestrator.hpp>
#include <mbgl/renderer/render_tree.hpp>
#include <set>
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<gfx::UniqueDrawable, gfx::DrawableLessByPriority>;
DrawableCollection drawables;
};
LayerGroup::LayerGroup(int32_t layerIndex_, std::size_t /*initialCapacity*/, std::string name_)
: LayerGroupBase(layerIndex_, std::move(name_)),
impl(std::make_unique<Impl>()) {}
: 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<void(gfx::Drawable&)>&& f) {
for (const auto& item : impl->drawables) {
if (item) {
f(*item);
}
}
return impl->drawables.size();
}
std::size_t LayerGroup::visitDrawables(const std::function<void(const gfx::Drawable&)>&& f) const {
for (const auto& item : impl->drawables) {
if (item) {
f(*item);
}
}
return impl->drawables.size();
}
std::size_t LayerGroup::removeDrawablesIf(const std::function<bool(gfx::Drawable&)>&& 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;
}

View File

@@ -52,7 +52,7 @@ void BackgroundLayerTweaker::execute(LayerGroupBase& layerGroup, const PaintPara
layerGroup.setEnabled(true);
std::optional<uint32_t> samplerLocation{};
layerGroup.visitDrawables([&](gfx::Drawable& drawable) {
visitLayerGroupDrawables(layerGroup, [&](gfx::Drawable& drawable) {
assert(drawable.getTileID());
if (!drawable.getTileID() || !checkTweakDrawable(drawable)) {
return;

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -23,7 +23,7 @@ void RasterLayerTweaker::execute([[maybe_unused]] LayerGroupBase& layerGroup,
[[maybe_unused]] const PaintParameters& parameters) {
const auto& evaluated = static_cast<const RasterLayerProperties&>(*evaluatedProperties).evaluated;
layerGroup.visitDrawables([&](gfx::Drawable& drawable) {
visitLayerGroupDrawables(layerGroup, [&](gfx::Drawable& drawable) {
if (!checkTweakDrawable(drawable)) {
return;
}

View File

@@ -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())) {

View File

@@ -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;
}

View File

@@ -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<bool(gfx::Drawable&)> update) {
bool anyUpdated = false;
if (const auto tileGroup = static_cast<TileLayerGroup*>(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<TileLayerGroup*>(layerGroup.get())) {
const auto n = tileGroup->removeDrawables(renderPass, tileID).size();

View File

@@ -8,6 +8,7 @@
#if MLN_DRAWABLE_RENDERER
#include <mbgl/gfx/drawable.hpp>
#include <mbgl/renderer/layer_group.hpp>
#include <mbgl/renderer/change_request.hpp>
#include <mbgl/util/tiny_unordered_map.hpp>
#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<bool(gfx::Drawable&)> updateFunction);
template <typename Func /* bool(gfx::Drawable&) */>
bool updateTile(RenderPass renderPass, const OverscaledTileID& tileID, Func update) {
bool anyUpdated = false;
if (const auto tileGroup = static_cast<TileLayerGroup*>(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.

View File

@@ -878,22 +878,6 @@ int32_t RenderOrchestrator::maxLayerIndex() const {
return -1;
}
void RenderOrchestrator::visitLayerGroups(std::function<void(LayerGroupBase&)> f) {
for (auto& pair : layerGroupsByLayerIndex) {
if (pair.second) {
f(*pair.second);
}
}
}
void RenderOrchestrator::visitLayerGroups(std::function<void(const LayerGroupBase&)> 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<void(RenderTarget&)> f) {
for (auto& renderTarget : renderTargets) {
f(*renderTarget);
}
}
void RenderOrchestrator::visitRenderTargets(std::function<void(const RenderTarget&)> 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<void(LayerGroupBase&)> f) {
for (auto& pair : debugLayerGroups) {
if (pair.second) {
f(*pair.second);
}
}
}
void RenderOrchestrator::visitDebugLayerGroups(std::function<void(const LayerGroupBase&)> f) const {
for (const auto& pair : debugLayerGroups) {
if (pair.second) {
f(*pair.second);
}
}
}
#endif // MLN_DRAWABLE_RENDERER
void RenderOrchestrator::onGlyphsError(const FontStack& fontStack,

View File

@@ -102,10 +102,17 @@ public:
bool removeLayerGroup(const LayerGroupBasePtr&);
size_t numLayerGroups() const noexcept;
int32_t maxLayerIndex() const;
void visitLayerGroups(std::function<void(LayerGroupBase&)>);
void visitLayerGroups(std::function<void(const LayerGroupBase&)>) const;
void updateLayerIndex(LayerGroupBasePtr, int32_t newIndex);
template <typename Func /* void(LayerGroupBase&) */>
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<void(RenderTarget&)> f);
void visitRenderTargets(std::function<void(const RenderTarget&)> f) const;
template <typename Func /* void(RenderTarget&) */>
void visitRenderTargets(Func f) {
for (auto& renderTarget : renderTargets) {
f(*renderTarget);
}
}
void updateDebugLayerGroups(const RenderTree& renderTree, PaintParameters& parameters);
void visitDebugLayerGroups(std::function<void(LayerGroupBase&)>);
void visitDebugLayerGroups(std::function<void(const LayerGroupBase&)>) const;
template <typename Func /* void(LayerGroupBase&) */>
void visitDebugLayerGroups(Func f) {
for (auto& pair : debugLayerGroups) {
if (pair.second) {
f(*pair.second);
}
}
}
#endif
const ZoomHistory& getZoomHistory() const { return zoomHistory; }

View File

@@ -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<void(LayerGroupBase&)> f) {
for (auto& pair : layerGroupsByLayerIndex) {
if (pair.second) {
f(*pair.second);
}
}
}
void RenderTarget::visitLayerGroups(std::function<void(const LayerGroupBase&)> 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); }));
}

View File

@@ -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); });
});
}
};

View File

@@ -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<mbgl::RenderPass>()(k.renderPass) ^ std::hash<OverscaledTileID>()(k.tileID) << 1);
}
};
};
struct TileLayerGroup::Impl {
Impl(std::size_t initialCapacity) { drawablesByTile.reserve(initialCapacity); }
using TileMap = std::unordered_multimap<TileLayerGroupTileKey, gfx::UniqueDrawable, TileLayerGroupTileKey::hash>;
TileMap drawablesByTile;
using DrawableMap = std::set<gfx::Drawable*, gfx::DrawableLessByPriority>;
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<Impl>(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<gfx::UniqueDrawable> 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<gfx::UniqueDrawable> 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<void(gfx::Drawable&)>&& 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<void(const gfx::Drawable&)>&& 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<bool(gfx::Drawable&)>&& 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<void(gfx::Drawable&)>&& 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<void(const gfx::Drawable&)>&& 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;
}