Render drawables in order (#1321)

This commit is contained in:
Tim Sylvester
2023-07-07 14:52:03 -07:00
committed by Bart Louwers
parent eac6c84508
commit d094b9928e
14 changed files with 131 additions and 166 deletions

View File

@@ -181,7 +181,7 @@ protected:
bool is3D = false;
bool isCustom = false;
std::string name;
util::SimpleIdentity uniqueID;
const util::SimpleIdentity uniqueID;
gfx::ShaderProgramBasePtr shader;
mbgl::RenderPass renderPass;
std::optional<OverscaledTileID> tileID;
@@ -203,7 +203,7 @@ using UniqueDrawable = std::unique_ptr<Drawable>;
/// Comparator for sorting drawable pointers primarily by draw priority
struct DrawableLessByPriority {
DrawableLessByPriority(bool descending)
DrawableLessByPriority(bool descending = false)
: desc(descending) {}
bool operator()(const Drawable& left, const Drawable& right) const {
const auto& a = desc ? right : left;
@@ -213,6 +213,8 @@ struct DrawableLessByPriority {
}
return a.getId() < b.getId();
}
bool operator()(const Drawable* left, const Drawable* right) const { return operator()(*left, *right); }
bool operator()(const UniqueDrawable& left, const UniqueDrawable& right) const { return operator()(*left, *right); }
bool operator()(const DrawablePtr& left, const DrawablePtr& right) const {
const auto& a = desc ? right : left;
const auto& b = desc ? left : right;

View File

@@ -66,12 +66,14 @@ public:
/// Called at the end of each frame
virtual void postRender(RenderOrchestrator&, PaintParameters&) {}
/// Call the provided function for each drawable in undefined order
virtual void observeDrawables(std::function<void(gfx::Drawable&)>) = 0;
virtual void observeDrawables(std::function<void(const gfx::Drawable&)>) const = 0;
/// Call the provided function for each drawable in priority order
virtual void observeDrawables(const std::function<void(gfx::Drawable&)>&&) = 0;
virtual void observeDrawables(const std::function<void(const gfx::Drawable&)>&&) const = 0;
/// Call the provided function for each drawable in undefined order, allowing ownership to be taken.
virtual void observeDrawables(std::function<void(gfx::UniqueDrawable&)>) = 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.
/// @return The number of items removed
virtual std::size_t observeDrawablesRemove(const std::function<bool(gfx::Drawable&)>&& f) = 0;
/// Attach a tweaker to be run on this layer group for each frame
void setLayerTweaker(LayerTweakerPtr tweaker) { layerTweaker = std::move(tweaker); }
@@ -100,13 +102,15 @@ public:
std::vector<gfx::UniqueDrawable> removeDrawables(mbgl::RenderPass, const OverscaledTileID&);
void addDrawable(mbgl::RenderPass, const OverscaledTileID&, gfx::UniqueDrawable&&);
void observeDrawables(std::function<void(gfx::Drawable&)>) override;
void observeDrawables(std::function<void(const gfx::Drawable&)>) const override;
void observeDrawables(std::function<void(gfx::UniqueDrawable&)>) override;
void observeDrawables(const std::function<void(gfx::Drawable&)>&&) override;
void observeDrawables(const std::function<void(const gfx::Drawable&)>&&) const override;
std::size_t observeDrawablesRemove(const std::function<bool(gfx::Drawable&)>&&) override;
/// Call the provided function for each drawable for the given tile
void observeDrawables(mbgl::RenderPass, const OverscaledTileID&, std::function<void(gfx::Drawable&)>&&);
void observeDrawables(mbgl::RenderPass, const OverscaledTileID&, std::function<void(const gfx::Drawable&)>&&) const;
void observeDrawables(mbgl::RenderPass, const OverscaledTileID&, const std::function<void(gfx::Drawable&)>&&);
void observeDrawables(mbgl::RenderPass,
const OverscaledTileID&,
const std::function<void(const gfx::Drawable&)>&&) const;
std::size_t clearDrawables() override;
@@ -129,9 +133,9 @@ public:
std::vector<gfx::UniqueDrawable> removeDrawables(mbgl::RenderPass);
void addDrawable(gfx::UniqueDrawable&&);
void observeDrawables(std::function<void(gfx::Drawable&)>) override;
void observeDrawables(std::function<void(const gfx::Drawable&)>) const override;
void observeDrawables(std::function<void(gfx::UniqueDrawable&)>) override;
void observeDrawables(const std::function<void(gfx::Drawable&)>&&) override;
void observeDrawables(const std::function<void(const gfx::Drawable&)>&&) const override;
std::size_t observeDrawablesRemove(const std::function<bool(gfx::Drawable&)>&&) override;
std::size_t clearDrawables() override;

View File

@@ -4,20 +4,18 @@
#include <mbgl/renderer/paint_parameters.hpp>
#include <mbgl/renderer/render_orchestrator.hpp>
#include <unordered_map>
#include <set>
namespace mbgl {
struct LayerGroup::Impl {
Impl(std::size_t capacity) { drawables.reserve(capacity); }
using DrawableCollection = std::vector<gfx::UniqueDrawable>;
using DrawableCollection = std::set<gfx::UniqueDrawable, gfx::DrawableLessByPriority>;
DrawableCollection drawables;
};
LayerGroup::LayerGroup(int32_t layerIndex_, std::size_t initialCapacity, std::string name_)
LayerGroup::LayerGroup(int32_t layerIndex_, std::size_t /*initialCapacity*/, std::string name_)
: LayerGroupBase(layerIndex_, std::move(name_)),
impl(std::make_unique<Impl>(initialCapacity)) {}
impl(std::make_unique<Impl>()) {}
LayerGroup::~LayerGroup() = default;
@@ -26,10 +24,10 @@ std::size_t LayerGroup::getDrawableCount() const {
}
void LayerGroup::addDrawable(gfx::UniqueDrawable&& drawable) {
impl->drawables.emplace_back(std::move(drawable));
impl->drawables.emplace(std::move(drawable));
}
void LayerGroup::observeDrawables(std::function<void(gfx::Drawable&)> f) {
void LayerGroup::observeDrawables(const std::function<void(gfx::Drawable&)>&& f) {
for (const auto& item : impl->drawables) {
if (item) {
f(*item);
@@ -37,7 +35,7 @@ void LayerGroup::observeDrawables(std::function<void(gfx::Drawable&)> f) {
}
}
void LayerGroup::observeDrawables(std::function<void(const gfx::Drawable&)> f) const {
void LayerGroup::observeDrawables(const std::function<void(const gfx::Drawable&)>&& f) const {
for (const auto& item : impl->drawables) {
if (item) {
f(*item);
@@ -45,20 +43,20 @@ void LayerGroup::observeDrawables(std::function<void(const gfx::Drawable&)> f) c
}
}
void LayerGroup::observeDrawables(std::function<void(gfx::UniqueDrawable&)> f) {
for (auto i = impl->drawables.begin(); i != impl->drawables.end();) {
auto& drawable = *i;
if (drawable) {
f(drawable);
}
if (drawable) {
// Not removed, keep going
++i;
} else {
// Removed, take it out of the map
i = impl->drawables.erase(i);
std::size_t LayerGroup::observeDrawablesRemove(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());
}
std::size_t LayerGroup::clearDrawables() {

View File

@@ -203,6 +203,10 @@ void RenderBackgroundLayer::prepare(const LayerPrepareParameters& params) {
addPatternIfNeeded(evaluated.get<BackgroundPattern>().from.id(), params);
addPatternIfNeeded(evaluated.get<BackgroundPattern>().to.id(), params);
}
#if MLN_DRAWABLE_RENDERER
updateRenderTileIDs();
#endif // MLN_DRAWABLE_RENDERER
}
#if MLN_DRAWABLE_RENDERER
@@ -275,21 +279,11 @@ void RenderBackgroundLayer::update(gfx::ShaderRegistry& shaders,
const auto indexes = RenderStaticData::quadTriangleIndices();
const auto segs = RenderStaticData::tileTriangleSegments();
// Put the tile cover into a searchable form.
// TODO: Likely better to sort and `std::binary_search` the vector.
// If it's returned in a well-defined order, we might not even need to sort.
const std::unordered_set<OverscaledTileID> newTileIDs(tileCover.begin(), tileCover.end());
std::unique_ptr<gfx::DrawableBuilder> builder;
tileLayerGroup->observeDrawables([&](gfx::UniqueDrawable& drawable) {
tileLayerGroup->observeDrawables([&](gfx::Drawable& drawable) -> bool {
// Has this tile dropped out of the cover set?
const auto tileID = drawable->getTileID();
if (tileID && newTileIDs.find(*tileID) == newTileIDs.end()) {
drawable.reset();
++stats.drawablesRemoved;
return;
}
return (!drawable.getTileID() || renderTileIDs.find(*drawable.getTileID()) != renderTileIDs.end());
});
// For each tile in the cover set, add a tile drawable if one doesn't already exist.

View File

@@ -300,28 +300,17 @@ void RenderCircleLayer::update(gfx::ShaderRegistry& shaders,
return;
}
std::unordered_set<OverscaledTileID> newTileIDs(renderTiles->size());
std::transform(renderTiles->begin(),
renderTiles->end(),
std::inserter(newTileIDs, newTileIDs.begin()),
[](const auto& renderTile) -> OverscaledTileID { return renderTile.get().getOverscaledTileID(); });
std::unique_ptr<gfx::DrawableBuilder> circleBuilder;
std::vector<gfx::DrawablePtr> newTiles;
gfx::VertexAttributeArray circleVertexAttrs;
auto renderPass = RenderPass::Translucent;
constexpr auto renderPass = RenderPass::Translucent;
if (!(mbgl::underlying_type(renderPass) & evaluatedProperties->renderPasses)) {
return;
}
tileLayerGroup->observeDrawables([&](gfx::UniqueDrawable& drawable) {
const auto tileID = drawable->getTileID();
if (tileID && newTileIDs.find(*tileID) == newTileIDs.end()) {
// remove it
drawable.reset();
++stats.drawablesRemoved;
}
stats.drawablesRemoved += tileLayerGroup->observeDrawablesRemove([&](gfx::Drawable& drawable) {
return (!drawable.getTileID() || renderTileIDs.find(*drawable.getTileID()) != renderTileIDs.end());
});
const auto& evaluated = static_cast<const CircleLayerProperties&>(*evaluatedProperties).evaluated;

View File

@@ -92,14 +92,6 @@ bool RenderFillExtrusionLayer::is3D() const {
return true;
}
void RenderFillExtrusionLayer::prepare(const LayerPrepareParameters& params) {
RenderLayer::prepare(params);
#if MLN_DRAWABLE_RENDERER
updateRenderTileIDs();
#endif // MLN_DRAWABLE_RENDERER
}
#if MLN_LEGACY_RENDERER
void RenderFillExtrusionLayer::render(PaintParameters& parameters) {
assert(renderTiles);
@@ -315,13 +307,10 @@ void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders,
// in the "3D pass".
constexpr auto drawPass = RenderPass::Translucent;
tileLayerGroup->observeDrawables([&](gfx::UniqueDrawable& drawable) {
stats.drawablesRemoved += tileLayerGroup->observeDrawablesRemove([&](gfx::Drawable& drawable) {
// If the render pass has changed or the tile has dropped out of the cover set, remove it.
const auto tileID = drawable->getTileID();
if (drawable->getRenderPass() != drawPass || (tileID && renderTileIDs.find(*tileID) == renderTileIDs.end())) {
drawable.reset();
++stats.drawablesRemoved;
}
return (drawable.getRenderPass() == drawPass &&
(!drawable.getTileID() || renderTileIDs.find(*drawable.getTileID()) != renderTileIDs.end()));
});
const auto zoom = static_cast<float>(state.getZoom());

View File

@@ -23,7 +23,6 @@ private:
bool hasTransition() const override;
bool hasCrossfade() const override;
bool is3D() const override;
void prepare(const LayerPrepareParameters&) override;
#if MLN_LEGACY_RENDERER
void render(PaintParameters&) override;

View File

@@ -325,12 +325,6 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders,
return;
}
std::unordered_set<OverscaledTileID> newTileIDs(renderTiles->size());
std::transform(renderTiles->begin(),
renderTiles->end(),
std::inserter(newTileIDs, newTileIDs.begin()),
[](const auto& renderTile) -> OverscaledTileID { return renderTile.get().getOverscaledTileID(); });
std::unique_ptr<gfx::DrawableBuilder> fillBuilder;
std::unique_ptr<gfx::DrawableBuilder> outlineBuilder;
std::unique_ptr<gfx::DrawableBuilder> patternBuilder;
@@ -364,13 +358,10 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders,
builder.setEnableStencil(true);
};
tileLayerGroup->observeDrawables([&](gfx::UniqueDrawable& drawable) {
stats.drawablesRemoved += tileLayerGroup->observeDrawablesRemove([&](gfx::Drawable& drawable) {
// If the render pass has changed or the tile has dropped out of the cover set, remove it.
const auto tileID = drawable->getTileID();
if (drawable->getRenderPass() != renderPass || (tileID && newTileIDs.find(*tileID) == newTileIDs.end())) {
drawable.reset();
++stats.drawablesRemoved;
}
return (drawable.getRenderPass() == renderPass &&
(!drawable.getTileID() || renderTileIDs.find(*drawable.getTileID()) != renderTileIDs.end()));
});
for (const RenderTile& tile : *renderTiles) {

View File

@@ -317,12 +317,6 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders,
return;
}
std::unordered_set<OverscaledTileID> newTileIDs(renderTiles->size());
std::transform(renderTiles->begin(),
renderTiles->end(),
std::inserter(newTileIDs, newTileIDs.begin()),
[](const auto& renderTile) -> OverscaledTileID { return renderTile.get().getOverscaledTileID(); });
std::unique_ptr<gfx::DrawableBuilder> heatmapBuilder;
std::vector<gfx::DrawablePtr> newTiles;
gfx::VertexAttributeArray heatmapVertexAttrs;
@@ -332,13 +326,8 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders,
return;
}
tileLayerGroup->observeDrawables([&](gfx::UniqueDrawable& drawable) {
const auto tileID = drawable->getTileID();
if (tileID && newTileIDs.find(*tileID) == newTileIDs.end()) {
// remove it
drawable.reset();
++stats.drawablesRemoved;
}
stats.drawablesRemoved += tileLayerGroup->observeDrawablesRemove([&](gfx::Drawable& drawable) {
return (!drawable.getTileID() || renderTileIDs.find(*drawable.getTileID()) != renderTileIDs.end());
});
const auto& evaluated = static_cast<const HeatmapLayerProperties&>(*evaluatedProperties).evaluated;

View File

@@ -90,7 +90,7 @@ void RenderLineLayer::prepare(const LayerPrepareParameters& params) {
const auto& evaluated = getEvaluated<LineLayerProperties>(renderData->layerProperties);
if (evaluated.get<LineDasharray>().from.empty()) continue;
auto& bucket = static_cast<LineBucket&>(*renderData->bucket);
const auto& bucket = static_cast<const LineBucket&>(*renderData->bucket);
const LinePatternCap cap = bucket.layout.get<LineCap>() == LineCapType::Round ? LinePatternCap::Round
: LinePatternCap::Square;
// Ensures that the dash data gets added to the atlas.
@@ -441,22 +441,13 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders,
lineSDFShaderGroup = shaders.getShaderGroup("LineSDFShader");
}
std::unordered_set<OverscaledTileID> newTileIDs(renderTiles->size());
std::transform(renderTiles->begin(),
renderTiles->end(),
std::inserter(newTileIDs, newTileIDs.begin()),
[](const auto& renderTile) -> OverscaledTileID { return renderTile.get().getOverscaledTileID(); });
const RenderPass renderPass = static_cast<RenderPass>(evaluatedProperties->renderPasses &
~mbgl::underlying_type(RenderPass::Opaque));
tileLayerGroup->observeDrawables([&](gfx::UniqueDrawable& drawable) {
stats.drawablesRemoved += tileLayerGroup->observeDrawablesRemove([&](gfx::Drawable& drawable) {
// If the render pass has changed or the tile has dropped out of the cover set, remove it.
const auto tileID = drawable->getTileID();
if (drawable->getRenderPass() != renderPass || (tileID && newTileIDs.find(*tileID) == newTileIDs.end())) {
drawable.reset();
++stats.drawablesRemoved;
}
return (drawable.getRenderPass() == renderPass &&
(!drawable.getTileID() || renderTileIDs.find(*drawable.getTileID()) != renderTileIDs.end()));
});
auto createLineBuilder = [&](const std::string& name,

View File

@@ -97,6 +97,10 @@ void RenderRasterLayer::prepare(const LayerPrepareParameters& params) {
imageData = params.source->getImageRenderData();
// It is possible image data is not available until the source loads it.
assert(renderTiles || imageData || !params.source->isEnabled());
#if MLN_DRAWABLE_RENDERER
updateRenderTileIDs();
#endif // MLN_DRAWABLE_RENDERER
}
#if MLN_LEGACY_RENDERER
@@ -416,19 +420,9 @@ void RenderRasterLayer::update(gfx::ShaderRegistry& shaders,
}
} else if (renderTiles) {
if (layerGroup) {
layerGroup->observeDrawables([&](gfx::UniqueDrawable& drawable) {
stats.drawablesRemoved += layerGroup->observeDrawablesRemove([&](gfx::Drawable& drawable) {
// Has this tile dropped out of the cover set?
if (const auto it = std::find_if(renderTiles->begin(),
renderTiles->end(),
[&drawable](const auto& renderTile) {
return drawable->getTileID() ==
renderTile.get().getOverscaledTileID();
});
it == renderTiles->end()) {
// remove it
drawable.reset();
++stats.drawablesRemoved;
}
return (!drawable.getTileID() || renderTileIDs.find(*drawable.getTileID()) != renderTileIDs.end());
});
} else {
// Set up a tile layer group

View File

@@ -831,14 +831,14 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders,
}
auto* tileLayerGroup = static_cast<TileLayerGroup*>(layerGroup.get());
tileLayerGroup->observeDrawables([&](gfx::UniqueDrawable& drawable) {
stats.drawablesRemoved += tileLayerGroup->observeDrawablesRemove([&](gfx::Drawable& drawable) {
// If the render pass has changed or the tile has dropped out of the cover set, remove it.
const auto tileID = drawable->getTileID();
if (drawable->getRenderPass() != passes || (tileID && renderTileIDs.find(*tileID) == renderTileIDs.end())) {
drawable.reset();
const auto& tileID = drawable.getTileID();
if (drawable.getRenderPass() != passes || (tileID && renderTileIDs.find(*tileID) == renderTileIDs.end())) {
tileBucketInstances.erase(*tileID);
++stats.drawablesRemoved;
return false;
}
return true;
});
const bool sortFeaturesByKey = !impl_cast(baseImpl).layout.get<SymbolSortKey>().isUndefined();

View File

@@ -58,6 +58,10 @@ void RenderLayer::prepare(const LayerPrepareParameters& params) {
assert(params.source->isEnabled());
renderTiles = params.source->getRenderTiles();
addRenderPassesFromTiles();
#if MLN_DRAWABLE_RENDERER
updateRenderTileIDs();
#endif // MLN_DRAWABLE_RENDERER
}
std::optional<Color> RenderLayer::getSolidBackground() const {

View File

@@ -5,6 +5,7 @@
#include <mbgl/renderer/render_orchestrator.hpp>
#include <unordered_map>
#include <set>
namespace mbgl {
@@ -22,11 +23,14 @@ struct TileLayerGroupTileKey {
};
struct TileLayerGroup::Impl {
Impl(std::size_t capacity)
: tileDrawables(capacity) {}
Impl(std::size_t initialCapacity)
: drawablesByTile(initialCapacity) {}
using TileMap = std::unordered_multimap<TileLayerGroupTileKey, gfx::UniqueDrawable, TileLayerGroupTileKey::hash>;
TileMap tileDrawables;
TileMap drawablesByTile;
using DrawableMap = std::set<gfx::Drawable*, gfx::DrawableLessByPriority>;
DrawableMap sortedDrawables;
};
LayerGroupBase::LayerGroupBase(int32_t layerIndex_, std::string name_)
@@ -40,80 +44,97 @@ TileLayerGroup::TileLayerGroup(int32_t layerIndex_, std::size_t initialCapacity,
TileLayerGroup::~TileLayerGroup() = default;
std::size_t TileLayerGroup::getDrawableCount() const {
return impl->tileDrawables.size();
return impl->drawablesByTile.size();
}
static const gfx::UniqueDrawable no_tile;
std::size_t TileLayerGroup::getDrawableCount(mbgl::RenderPass pass, const OverscaledTileID& id) const {
const auto range = impl->tileDrawables.equal_range({pass, id});
assert(impl->drawablesByTile.size() == impl->sortedDrawables.size());
const auto range = impl->drawablesByTile.equal_range({pass, id});
return std::distance(range.first, range.second);
}
std::vector<gfx::UniqueDrawable> TileLayerGroup::removeDrawables(mbgl::RenderPass pass, const OverscaledTileID& id) {
const auto range = impl->tileDrawables.equal_range({pass, id});
assert(impl->drawablesByTile.size() == impl->sortedDrawables.size());
const auto range = impl->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->tileDrawables.erase(range.first, range.second);
impl->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);
}
});
return result;
}
void TileLayerGroup::addDrawable(mbgl::RenderPass pass, const OverscaledTileID& id, gfx::UniqueDrawable&& drawable) {
impl->tileDrawables.insert(std::make_pair(TileLayerGroupTileKey{pass, id}, std::move(drawable)));
}
void TileLayerGroup::observeDrawables(std::function<void(gfx::Drawable&)> f) {
for (auto& pair : impl->tileDrawables) {
if (pair.second) {
f(*pair.second);
}
assert(impl->drawablesByTile.size() == impl->sortedDrawables.size());
if (drawable) {
[[maybe_unused]] const auto result = impl->sortedDrawables.insert(drawable.get());
assert(result.second);
impl->drawablesByTile.insert(std::make_pair(TileLayerGroupTileKey{pass, id}, std::move(drawable)));
}
}
void TileLayerGroup::observeDrawables(std::function<void(const gfx::Drawable&)> f) const {
for (const auto& pair : impl->tileDrawables) {
if (pair.second) {
f(*pair.second);
}
void TileLayerGroup::observeDrawables(const std::function<void(gfx::Drawable&)>&& f) {
assert(impl->drawablesByTile.size() == impl->sortedDrawables.size());
for (auto* drawable : impl->sortedDrawables) {
f(*drawable);
}
}
void TileLayerGroup::observeDrawables(std::function<void(gfx::UniqueDrawable&)> f) {
for (auto i = impl->tileDrawables.begin(); i != impl->tileDrawables.end();) {
void TileLayerGroup::observeDrawables(const std::function<void(const gfx::Drawable&)>&& f) const {
assert(impl->drawablesByTile.size() == impl->sortedDrawables.size());
for (const auto* drawable : impl->sortedDrawables) {
f(*drawable);
}
}
std::size_t TileLayerGroup::observeDrawablesRemove(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 (drawable) {
f(drawable);
}
if (drawable) {
if (f(*drawable)) {
// Not removed, keep going
++i;
} else {
// Removed, take it out of the map
i = impl->tileDrawables.erase(i);
// 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());
}
void TileLayerGroup::observeDrawables(mbgl::RenderPass pass,
const OverscaledTileID& tileID,
std::function<void(gfx::Drawable&)>&& f) {
const auto range = impl->tileDrawables.equal_range({pass, 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); });
}
void TileLayerGroup::observeDrawables(mbgl::RenderPass pass,
const OverscaledTileID& tileID,
std::function<void(const gfx::Drawable&)>&& f) const {
const auto range = impl->tileDrawables.equal_range({pass, 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); });
}
std::size_t TileLayerGroup::clearDrawables() {
const auto count = impl->tileDrawables.size();
impl->tileDrawables.clear();
const auto count = impl->drawablesByTile.size();
assert(count == impl->sortedDrawables.size());
impl->sortedDrawables.clear();
impl->drawablesByTile.clear();
return count;
}