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:
@@ -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);
|
||||
|
||||
@@ -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&);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>()));
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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())) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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); }));
|
||||
}
|
||||
|
||||
@@ -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); });
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user