Reduce memory use of FeatureIndex (#2364)

This commit is contained in:
Tim Sylvester
2024-05-16 07:17:24 -07:00
committed by GitHub
parent aff5693fb9
commit b812e97aaf
15 changed files with 211 additions and 64 deletions

View File

@@ -24,7 +24,7 @@ void FileSourceRequest::onCancel(std::function<void()>&& callback) {
void FileSourceRequest::setResponse(const Response& response) { void FileSourceRequest::setResponse(const Response& response) {
// Copy, because calling the callback will sometimes self // Copy, because calling the callback will sometimes self
// destroy this object. We cannot move because this method // destroy this object. We cannot move because this method
// can be called more than one. // can be called more than once.
auto callback = responseCallback; auto callback = responseCallback;
callback(response); callback(response);
} }

View File

@@ -33,6 +33,90 @@ mbgl::Point<double> project(const mbgl::LatLng& coordinate, const mbgl::Transfor
namespace mbgl { namespace mbgl {
constexpr auto expectedUniqueLayerIDs = 10;
constexpr auto expectedUniqueLeaderIDs = 30;
RefIndexedSubfeature::RefIndexedSubfeature(std::size_t index_,
const std::string& sourceLayerName_,
const std::string& bucketName_,
size_t sortIndex_,
uint32_t bucketInstanceId_,
uint16_t collisionGroupId_)
: index(index_),
sortIndex(sortIndex_),
sourceLayerName(sourceLayerName_),
bucketLeaderID(bucketName_),
bucketInstanceId(bucketInstanceId_),
collisionGroupId(collisionGroupId_) {}
IndexedSubfeature::IndexedSubfeature(const RefIndexedSubfeature& other)
: IndexedSubfeature(other, other.getBucketInstanceId(), other.getCollisionGroupId()) {}
IndexedSubfeature::IndexedSubfeature(const RefIndexedSubfeature& other,
uint32_t bucketInstanceId_,
uint16_t collisionGroupId_)
: IndexedSubfeature(other.getIndex(),
other.getSourceLayerName(),
other.getBucketLeaderID(),
other.getSortIndex(),
bucketInstanceId_,
collisionGroupId_) {}
IndexedSubfeature::IndexedSubfeature(const IndexedSubfeature& other)
: IndexedSubfeature(other.getIndex(),
other.sourceLayerName,
other.bucketLeaderID,
other.getSortIndex(),
other.getBucketInstanceId(),
other.getCollisionGroupId()) {}
IndexedSubfeature::IndexedSubfeature(IndexedSubfeature&& other)
: IndexedSubfeature(other.getIndex(),
std::move(other.sourceLayerName),
std::move(other.bucketLeaderID),
other.getSortIndex(),
other.getBucketInstanceId(),
other.getCollisionGroupId()) {}
IndexedSubfeature::IndexedSubfeature(std::size_t index_,
std::string sourceLayerName_,
std::string bucketName_,
size_t sortIndex_,
uint32_t bucketInstanceId_,
uint16_t collisionGroupId_)
: RefIndexedSubfeature(index_,
this->sourceLayerNameCopy,
this->bucketLeaderIDCopy,
sortIndex_,
bucketInstanceId_,
collisionGroupId_),
sourceLayerNameCopy(std::move(sourceLayerName_)),
bucketLeaderIDCopy(std::move(bucketName_)) {}
IndexedSubfeature& IndexedSubfeature::operator=(const IndexedSubfeature& other) {
index = other.index;
sourceLayerName = sourceLayerNameCopy;
bucketLeaderID = bucketLeaderIDCopy;
sortIndex = other.sortIndex;
bucketInstanceId = other.bucketInstanceId;
collisionGroupId = other.collisionGroupId;
sourceLayerNameCopy = other.sourceLayerNameCopy;
bucketLeaderIDCopy = other.bucketLeaderIDCopy;
return *this;
}
IndexedSubfeature& IndexedSubfeature::operator=(IndexedSubfeature&& other) {
index = other.index;
sourceLayerName = sourceLayerNameCopy;
bucketLeaderID = bucketLeaderIDCopy;
sortIndex = other.sortIndex;
bucketInstanceId = other.bucketInstanceId;
collisionGroupId = other.collisionGroupId;
sourceLayerNameCopy = std::move(other.sourceLayerNameCopy);
bucketLeaderIDCopy = std::move(other.bucketLeaderIDCopy);
return *this;
}
FeatureIndex::FeatureIndex(std::unique_ptr<const GeometryTileData> tileData_) FeatureIndex::FeatureIndex(std::unique_ptr<const GeometryTileData> tileData_)
: grid(util::EXTENT, util::EXTENT, util::EXTENT / 16), // 16x16 grid -> 32px cell : grid(util::EXTENT, util::EXTENT, util::EXTENT / 16), // 16x16 grid -> 32px cell
tileData(std::move(tileData_)) {} tileData(std::move(tileData_)) {}
@@ -41,12 +125,22 @@ void FeatureIndex::insert(const GeometryCollection& geometries,
std::size_t index, std::size_t index,
const std::string& sourceLayerName, const std::string& sourceLayerName,
const std::string& bucketLeaderID) { const std::string& bucketLeaderID) {
if (uniqueLayerIDs.empty()) {
uniqueLayerIDs.reserve(expectedUniqueLayerIDs);
}
const std::string& emplacedLayerName = *uniqueLayerIDs.insert(sourceLayerName).first;
if (bucketLayerIDs.empty()) {
bucketLayerIDs.reserve(expectedUniqueLeaderIDs);
}
const std::string& emplacedLeaderID =
bucketLayerIDs.insert(std::make_pair(bucketLeaderID, std::vector<std::string>{})).first->first;
auto featureSortIndex = sortIndex++; auto featureSortIndex = sortIndex++;
for (const auto& ring : geometries) { for (const auto& ring : geometries) {
auto envelope = mapbox::geometry::envelope(ring); const auto envelope = mapbox::geometry::envelope(ring);
if (envelope.min.x < util::EXTENT && envelope.min.y < util::EXTENT && envelope.max.x >= 0 && if (envelope.min.x < util::EXTENT && envelope.min.y < util::EXTENT && envelope.max.x >= 0 &&
envelope.max.y >= 0) { envelope.max.y >= 0) {
grid.insert(IndexedSubfeature(index, sourceLayerName, bucketLeaderID, featureSortIndex), grid.insert(RefIndexedSubfeature(index, emplacedLayerName, emplacedLeaderID, featureSortIndex),
{convertPoint<float>(envelope.min), convertPoint<float>(envelope.max)}); {convertPoint<float>(envelope.min), convertPoint<float>(envelope.max)});
} }
} }
@@ -74,17 +168,17 @@ void FeatureIndex::query(std::unordered_map<std::string, std::vector<Feature>>&
// Query the grid index // Query the grid index
mapbox::geometry::box<int16_t> box = mapbox::geometry::envelope(queryGeometry); mapbox::geometry::box<int16_t> box = mapbox::geometry::envelope(queryGeometry);
std::vector<IndexedSubfeature> features = grid.query( std::vector<RefIndexedSubfeature> features = grid.query(
{convertPoint<float>(box.min - additionalPadding), convertPoint<float>(box.max + additionalPadding)}); {convertPoint<float>(box.min - additionalPadding), convertPoint<float>(box.max + additionalPadding)});
std::sort(features.begin(), features.end(), [](const IndexedSubfeature& a, const IndexedSubfeature& b) { std::sort(features.begin(), features.end(), [](const RefIndexedSubfeature& a, const RefIndexedSubfeature& b) {
return a.sortIndex > b.sortIndex; return a.getSortIndex() > b.getSortIndex();
}); });
size_t previousSortIndex = std::numeric_limits<size_t>::max(); size_t previousSortIndex = std::numeric_limits<size_t>::max();
for (const auto& indexedFeature : features) { for (const auto& indexedFeature : features) {
// If this feature is the same as the previous feature, skip it. // If this feature is the same as the previous feature, skip it.
if (indexedFeature.sortIndex == previousSortIndex) continue; if (indexedFeature.getSortIndex() == previousSortIndex) continue;
previousSortIndex = indexedFeature.sortIndex; previousSortIndex = indexedFeature.getSortIndex();
addFeature(result, addFeature(result,
indexedFeature, indexedFeature,
@@ -109,11 +203,12 @@ std::unordered_map<std::string, std::vector<Feature>> FeatureIndex::lookupSymbol
if (!tileData) { if (!tileData) {
return result; return result;
} }
std::vector<IndexedSubfeature> sortedFeatures(symbolFeatures.begin(), symbolFeatures.end()); std::vector<std::reference_wrapper<const RefIndexedSubfeature>> sortedFeatures(symbolFeatures.begin(),
symbolFeatures.end());
std::sort(sortedFeatures.begin(), std::sort(sortedFeatures.begin(),
sortedFeatures.end(), sortedFeatures.end(),
[featureSortOrder](const IndexedSubfeature& a, const IndexedSubfeature& b) { [featureSortOrder](const RefIndexedSubfeature& a, const RefIndexedSubfeature& b) {
// Same idea as the non-symbol sort order, but symbol features may // Same idea as the non-symbol sort order, but symbol features may
// have changed their sort order since their corresponding // have changed their sort order since their corresponding
// IndexedSubfeature was added to the CollisionIndex The // IndexedSubfeature was added to the CollisionIndex The
@@ -124,15 +219,15 @@ std::unordered_map<std::string, std::vector<Feature>> FeatureIndex::lookupSymbol
// "top-to-bottom" rendering order (aka last-to-first). // "top-to-bottom" rendering order (aka last-to-first).
// Actually there can be multiple symbol instances per feature, so // Actually there can be multiple symbol instances per feature, so
// we sort each feature based on the first matching symbol instance. // we sort each feature based on the first matching symbol instance.
auto sortedA = std::find(featureSortOrder->begin(), featureSortOrder->end(), a.index); auto sortedA = std::find(featureSortOrder->begin(), featureSortOrder->end(), a.getIndex());
auto sortedB = std::find(featureSortOrder->begin(), featureSortOrder->end(), b.index); auto sortedB = std::find(featureSortOrder->begin(), featureSortOrder->end(), b.getIndex());
assert(sortedA != featureSortOrder->end()); assert(sortedA != featureSortOrder->end());
assert(sortedB != featureSortOrder->end()); assert(sortedB != featureSortOrder->end());
return sortedA > sortedB; return sortedA > sortedB;
} else { } else {
// Bucket hasn't been re-sorted based on angle, so use same // Bucket hasn't been re-sorted based on angle, so use same
// "reverse of appearance in source data" logic as non-symboles // "reverse of appearance in source data" logic as non-symboles
return a.sortIndex > b.sortIndex; return a.getSortIndex() > b.getSortIndex();
} }
}); });
@@ -153,7 +248,7 @@ std::unordered_map<std::string, std::vector<Feature>> FeatureIndex::lookupSymbol
} }
void FeatureIndex::addFeature(std::unordered_map<std::string, std::vector<Feature>>& result, void FeatureIndex::addFeature(std::unordered_map<std::string, std::vector<Feature>>& result,
const IndexedSubfeature& indexedFeature, const RefIndexedSubfeature& indexedFeature,
const RenderedQueryOptions& options, const RenderedQueryOptions& options,
const CanonicalTileID& tileID, const CanonicalTileID& tileID,
const std::unordered_map<std::string, const RenderLayer*>& layers, const std::unordered_map<std::string, const RenderLayer*>& layers,
@@ -166,7 +261,7 @@ void FeatureIndex::addFeature(std::unordered_map<std::string, std::vector<Featur
std::unique_ptr<GeometryTileLayer> sourceLayer; std::unique_ptr<GeometryTileLayer> sourceLayer;
std::unique_ptr<GeometryTileFeature> geometryTileFeature; std::unique_ptr<GeometryTileFeature> geometryTileFeature;
for (const std::string& layerID : bucketLayerIDs.at(indexedFeature.bucketLeaderID)) { for (const std::string& layerID : bucketLayerIDs.at(indexedFeature.getBucketLeaderID())) {
const auto it = layers.find(layerID); const auto it = layers.find(layerID);
if (it == layers.end()) { if (it == layers.end()) {
continue; continue;
@@ -175,10 +270,10 @@ void FeatureIndex::addFeature(std::unordered_map<std::string, std::vector<Featur
const RenderLayer* renderLayer = it->second; const RenderLayer* renderLayer = it->second;
if (!geometryTileFeature) { if (!geometryTileFeature) {
sourceLayer = tileData->getLayer(indexedFeature.sourceLayerName); sourceLayer = tileData->getLayer(indexedFeature.getSourceLayerName());
assert(sourceLayer); assert(sourceLayer);
geometryTileFeature = sourceLayer->getFeature(indexedFeature.index); geometryTileFeature = sourceLayer->getFeature(indexedFeature.getIndex());
assert(geometryTileFeature); assert(geometryTileFeature);
} }
FeatureState state; FeatureState state;
@@ -226,6 +321,8 @@ std::optional<GeometryCoordinates> FeatureIndex::translateQueryGeometry(const Ge
} }
GeometryCoordinates translated; GeometryCoordinates translated;
translated.reserve(queryGeometry.size());
for (const auto& p : queryGeometry) { for (const auto& p : queryGeometry) {
translated.push_back(p - translateVec); translated.push_back(p - translateVec);
} }
@@ -233,6 +330,9 @@ std::optional<GeometryCoordinates> FeatureIndex::translateQueryGeometry(const Ge
} }
void FeatureIndex::setBucketLayerIDs(const std::string& bucketLeaderID, const std::vector<std::string>& layerIDs) { void FeatureIndex::setBucketLayerIDs(const std::string& bucketLeaderID, const std::vector<std::string>& layerIDs) {
if (bucketLayerIDs.empty()) {
bucketLayerIDs.reserve(expectedUniqueLeaderIDs);
}
bucketLayerIDs[bucketLeaderID] = layerIDs; bucketLayerIDs[bucketLeaderID] = layerIDs;
} }
@@ -249,6 +349,7 @@ void DynamicFeatureIndex::query(std::unordered_map<std::string, std::vector<Feat
const Point<int64_t> coord = {int64_t(pm.x), int64_t(pm.y)}; const Point<int64_t> coord = {int64_t(pm.x), int64_t(pm.y)};
mbgl::updateBBox(queryBox, coord); mbgl::updateBBox(queryBox, coord);
} }
for (const auto& f : features) { for (const auto& f : features) {
// hit testing // hit testing
mbgl::GeometryBBox<int64_t> featureBox = DefaultWithinBBox; mbgl::GeometryBBox<int64_t> featureBox = DefaultWithinBBox;

View File

@@ -21,34 +21,69 @@ class SourceFeatureState;
class CollisionIndex; class CollisionIndex;
class IndexedSubfeature { /// An indexed element within a feature index.
/// This version holds a reference to the strings within the index itself to avoid making tens of thousands of
/// unnecessary copies of them. As a result, its lifetime cannot exceed that of the index.
class RefIndexedSubfeature {
public: public:
IndexedSubfeature() = delete; RefIndexedSubfeature() = delete;
IndexedSubfeature(std::size_t index_, std::string sourceLayerName_, std::string bucketName_, size_t sortIndex_) RefIndexedSubfeature(RefIndexedSubfeature&&) = default;
: index(index_), RefIndexedSubfeature(const RefIndexedSubfeature&) = default;
sourceLayerName(std::move(sourceLayerName_)), RefIndexedSubfeature(std::size_t index_,
bucketLeaderID(std::move(bucketName_)), const std::string& sourceLayerName_,
sortIndex(sortIndex_), const std::string& bucketName_,
bucketInstanceId(0), size_t sortIndex_,
collisionGroupId(0) {} uint32_t bucketInstanceId_ = 0,
uint16_t collisionGroupId_ = 0);
IndexedSubfeature(const IndexedSubfeature& other, uint32_t bucketInstanceId_, uint16_t collisionGroupId_) RefIndexedSubfeature& operator=(const RefIndexedSubfeature&) = default;
: index(other.index), RefIndexedSubfeature& operator=(RefIndexedSubfeature&&) = default;
sourceLayerName(other.sourceLayerName),
bucketLeaderID(other.bucketLeaderID), size_t getIndex() const { return index; }
sortIndex(other.sortIndex), size_t getSortIndex() const { return sortIndex; }
bucketInstanceId(bucketInstanceId_),
collisionGroupId(collisionGroupId_) {} const std::string& getSourceLayerName() const { return sourceLayerName.get(); }
const std::string& getBucketLeaderID() const { return bucketLeaderID.get(); }
uint32_t getBucketInstanceId() const { return bucketInstanceId; }
uint16_t getCollisionGroupId() const { return collisionGroupId; }
protected:
size_t index; size_t index;
std::string sourceLayerName;
std::string bucketLeaderID;
size_t sortIndex; size_t sortIndex;
std::reference_wrapper<const std::string> sourceLayerName;
std::reference_wrapper<const std::string> bucketLeaderID;
// Only used for symbol features // Only used for symbol features
uint32_t bucketInstanceId; uint32_t bucketInstanceId;
uint16_t collisionGroupId; uint16_t collisionGroupId;
}; };
/// This version of an indexed feature has copies of the necessary strings, so that it can be used outside the index.
class IndexedSubfeature : public RefIndexedSubfeature {
public:
IndexedSubfeature(const RefIndexedSubfeature&);
IndexedSubfeature(const RefIndexedSubfeature&, uint32_t bucketInstanceId_, uint16_t collisionGroupId_);
IndexedSubfeature(const IndexedSubfeature&);
IndexedSubfeature(IndexedSubfeature&&);
IndexedSubfeature(std::size_t index_,
std::string sourceLayerName_,
std::string bucketName_,
size_t sortIndex_,
uint32_t bucketInstanceId_ = 0,
uint16_t collisionGroupId_ = 0);
IndexedSubfeature& operator=(const IndexedSubfeature&);
IndexedSubfeature& operator=(IndexedSubfeature&&);
private:
std::string sourceLayerNameCopy;
std::string bucketLeaderIDCopy;
};
using FeatureSortOrder = std::shared_ptr<const std::vector<size_t>>; using FeatureSortOrder = std::shared_ptr<const std::vector<size_t>>;
class DynamicFeatureIndex { class DynamicFeatureIndex {
@@ -112,7 +147,7 @@ public:
private: private:
void addFeature(std::unordered_map<std::string, std::vector<Feature>>& result, void addFeature(std::unordered_map<std::string, std::vector<Feature>>& result,
const IndexedSubfeature&, const RefIndexedSubfeature&,
const RenderedQueryOptions& options, const RenderedQueryOptions& options,
const CanonicalTileID&, const CanonicalTileID&,
const std::unordered_map<std::string, const RenderLayer*>&, const std::unordered_map<std::string, const RenderLayer*>&,
@@ -122,10 +157,15 @@ private:
const mat4& posMatrix, const mat4& posMatrix,
const SourceFeatureState* sourceFeatureState) const; const SourceFeatureState* sourceFeatureState) const;
GridIndex<IndexedSubfeature> grid; GridIndex<RefIndexedSubfeature> grid;
unsigned int sortIndex = 0; unsigned int sortIndex = 0;
// mbgl::unordered_* cannot be used here, as we rely on holding references to elements:
// 22.2.7 Unordered associative containers [unord.req]
// The insert and emplace members shall not affect the validity of references to
// container elements, but may invalidate all iterators to the container.
std::unordered_map<std::string, std::vector<std::string>> bucketLayerIDs; std::unordered_map<std::string, std::vector<std::string>> bucketLayerIDs;
std::unordered_set<std::string> uniqueLayerIDs;
std::unique_ptr<const GeometryTileData> tileData; std::unique_ptr<const GeometryTileData> tileData;
}; };
} // namespace mbgl } // namespace mbgl

View File

@@ -87,7 +87,7 @@ SymbolInstance::SymbolInstance(Anchor& anchor_,
const float iconBoxScale, const float iconBoxScale,
const float iconPadding, const float iconPadding,
const std::array<float, 2>& iconOffset_, const std::array<float, 2>& iconOffset_,
const IndexedSubfeature& indexedFeature, const RefIndexedSubfeature& indexedFeature,
const std::size_t layoutFeatureIndex_, const std::size_t layoutFeatureIndex_,
const std::size_t dataFeatureIndex_, const std::size_t dataFeatureIndex_,
std::u16string key_, std::u16string key_,

View File

@@ -66,7 +66,7 @@ public:
float iconBoxScale, float iconBoxScale,
float iconPadding, float iconPadding,
const std::array<float, 2>& iconOffset, const std::array<float, 2>& iconOffset,
const IndexedSubfeature& indexedFeature, const RefIndexedSubfeature& indexedFeature,
std::size_t layoutFeatureIndex, std::size_t layoutFeatureIndex,
std::size_t dataFeatureIndex, std::size_t dataFeatureIndex,
std::u16string key, std::u16string key,

View File

@@ -1206,13 +1206,15 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders,
// We'll be processing renderables across tiles, potentially out-of-order, so keep // We'll be processing renderables across tiles, potentially out-of-order, so keep
// track of some things by tile ID so we don't have to re-build them multiple times. // track of some things by tile ID so we don't have to re-build them multiple times.
using RawVertexVec = std::vector<std::uint8_t>; // <int16_t, 4> using RawVertexVec = std::vector<std::uint8_t>; // raw buffer for vertexes of <int16_t, 4>
struct TileInfo { struct TileInfo {
RawVertexVec textVertices, iconVertices; RawVertexVec textVertices, iconVertices;
gfx::DrawableTweakerPtr textTweaker, iconTweaker; gfx::DrawableTweakerPtr textTweaker, iconTweaker;
gfx::UniformBufferPtr textInterp, iconInterp; gfx::UniformBufferPtr textInterp, iconInterp;
}; };
std::unordered_map<UnwrappedTileID, TileInfo> tileCache; std::unordered_map<UnwrappedTileID, TileInfo> tileCache;
tileCache.reserve(renderTiles->size());
for (auto& group : renderableSegments) { for (auto& group : renderableSegments) {
const auto& renderable = group.renderable; const auto& renderable = group.renderable;

View File

@@ -87,7 +87,7 @@ public:
const float boxScale, const float boxScale,
const float padding, const float padding,
const style::SymbolPlacementType placement, const style::SymbolPlacementType placement,
const IndexedSubfeature& indexedFeature_, const RefIndexedSubfeature& indexedFeature_,
const float overscaling, const float overscaling,
const float rotate) const float rotate)
: CollisionFeature(line, : CollisionFeature(line,
@@ -117,7 +117,7 @@ public:
std::optional<PositionedIcon> shapedIcon, std::optional<PositionedIcon> shapedIcon,
const float boxScale, const float boxScale,
const float padding, const float padding,
const IndexedSubfeature& indexedFeature_, const RefIndexedSubfeature& indexedFeature_,
const float rotate) const float rotate)
: CollisionFeature(line, : CollisionFeature(line,
anchor, anchor,

View File

@@ -159,7 +159,7 @@ std::pair<bool, bool> CollisionIndex::placeFeature(
const bool pitchWithMap, const bool pitchWithMap,
const bool collisionDebug, const bool collisionDebug,
const std::optional<CollisionBoundaries>& avoidEdges, const std::optional<CollisionBoundaries>& avoidEdges,
const std::optional<std::function<bool(const IndexedSubfeature&)>>& collisionGroupPredicate, const std::optional<std::function<bool(const RefIndexedSubfeature&)>>& collisionGroupPredicate,
std::vector<ProjectedCollisionBox>& projectedBoxes) { std::vector<ProjectedCollisionBox>& projectedBoxes) {
assert(projectedBoxes.empty()); assert(projectedBoxes.empty());
if (!feature.alongLine) { if (!feature.alongLine) {
@@ -202,7 +202,7 @@ std::pair<bool, bool> CollisionIndex::placeLineFeature(
const bool pitchWithMap, const bool pitchWithMap,
const bool collisionDebug, const bool collisionDebug,
const std::optional<CollisionBoundaries>& avoidEdges, const std::optional<CollisionBoundaries>& avoidEdges,
const std::optional<std::function<bool(const IndexedSubfeature&)>>& collisionGroupPredicate, const std::optional<std::function<bool(const RefIndexedSubfeature&)>>& collisionGroupPredicate,
std::vector<ProjectedCollisionBox>& projectedBoxes) { std::vector<ProjectedCollisionBox>& projectedBoxes) {
assert(feature.alongLine); assert(feature.alongLine);
assert(projectedBoxes.empty()); assert(projectedBoxes.empty());
@@ -340,10 +340,10 @@ void CollisionIndex::insertFeature(const CollisionFeature& feature,
} }
if (ignorePlacement) { if (ignorePlacement) {
ignoredGrid.insert(IndexedSubfeature(feature.indexedFeature, bucketInstanceId, collisionGroupId), ignoredGrid.insert(IndexedSubfeature{feature.indexedFeature, bucketInstanceId, collisionGroupId},
circle.circle()); circle.circle());
} else { } else {
collisionGrid.insert(IndexedSubfeature(feature.indexedFeature, bucketInstanceId, collisionGroupId), collisionGrid.insert(IndexedSubfeature{feature.indexedFeature, bucketInstanceId, collisionGroupId},
circle.circle()); circle.circle());
} }
} }
@@ -352,10 +352,10 @@ void CollisionIndex::insertFeature(const CollisionFeature& feature,
auto& box = projectedBoxes[0]; auto& box = projectedBoxes[0];
assert(box.isBox()); assert(box.isBox());
if (ignorePlacement) { if (ignorePlacement) {
ignoredGrid.insert(IndexedSubfeature(feature.indexedFeature, bucketInstanceId, collisionGroupId), ignoredGrid.insert(IndexedSubfeature{feature.indexedFeature, bucketInstanceId, collisionGroupId},
box.box()); box.box());
} else { } else {
collisionGrid.insert(IndexedSubfeature(feature.indexedFeature, bucketInstanceId, collisionGroupId), collisionGrid.insert(IndexedSubfeature{feature.indexedFeature, bucketInstanceId, collisionGroupId},
box.box()); box.box());
} }
} }
@@ -398,23 +398,25 @@ std::unordered_map<uint32_t, std::vector<IndexedSubfeature>> CollisionIndex::que
std::vector<QueryResult> features = collisionGrid.queryWithBoxes(envelope); std::vector<QueryResult> features = collisionGrid.queryWithBoxes(envelope);
std::vector<QueryResult> ignoredFeatures = ignoredGrid.queryWithBoxes(envelope); std::vector<QueryResult> ignoredFeatures = ignoredGrid.queryWithBoxes(envelope);
features.insert(features.end(), ignoredFeatures.begin(), ignoredFeatures.end()); features.insert(features.end(),
std::make_move_iterator(ignoredFeatures.begin()),
std::make_move_iterator(ignoredFeatures.end()));
std::unordered_map<uint32_t, std::unordered_set<size_t>> seenBuckets; mbgl::unordered_map<uint32_t, mbgl::unordered_set<size_t>> seenBuckets;
for (auto& queryResult : features) { for (auto& queryResult : features) {
auto& feature = queryResult.first; auto& feature = queryResult.first;
auto& bbox = queryResult.second; auto& bbox = queryResult.second;
// Skip already seen features. // Skip already seen features.
auto& seenFeatures = seenBuckets[feature.bucketInstanceId]; auto& seenFeatures = seenBuckets[feature.getBucketInstanceId()];
if (seenFeatures.find(feature.index) != seenFeatures.end()) continue; if (seenFeatures.find(feature.getIndex()) != seenFeatures.end()) continue;
if (!polygonIntersectsBox(gridQuery, bbox)) { if (!polygonIntersectsBox(gridQuery, bbox)) {
continue; continue;
} }
seenFeatures.insert(feature.index); seenFeatures.insert(feature.getIndex());
result[feature.bucketInstanceId].push_back(feature); result[feature.getBucketInstanceId()].push_back(feature);
} }
return result; return result;

View File

@@ -48,7 +48,7 @@ public:
bool pitchWithMap, bool pitchWithMap,
bool collisionDebug, bool collisionDebug,
const std::optional<CollisionBoundaries>& avoidEdges, const std::optional<CollisionBoundaries>& avoidEdges,
const std::optional<std::function<bool(const IndexedSubfeature&)>>& collisionGroupPredicate, const std::optional<std::function<bool(const RefIndexedSubfeature&)>>& collisionGroupPredicate,
std::vector<ProjectedCollisionBox>& /*out*/ std::vector<ProjectedCollisionBox>& /*out*/
); );
@@ -84,7 +84,7 @@ private:
bool pitchWithMap, bool pitchWithMap,
bool collisionDebug, bool collisionDebug,
const std::optional<CollisionBoundaries>& avoidEdges, const std::optional<CollisionBoundaries>& avoidEdges,
const std::optional<std::function<bool(const IndexedSubfeature&)>>& collisionGroupPredicate, const std::optional<std::function<bool(const RefIndexedSubfeature&)>>& collisionGroupPredicate,
std::vector<ProjectedCollisionBox>& /*out*/ std::vector<ProjectedCollisionBox>& /*out*/
); );

View File

@@ -49,8 +49,8 @@ const CollisionGroups::CollisionGroup& CollisionGroups::get(const std::string& s
collisionGroups.emplace( collisionGroups.emplace(
sourceID, sourceID,
CollisionGroup(nextGroupID, CollisionGroup(nextGroupID,
std::optional<Predicate>([nextGroupID](const IndexedSubfeature& feature) -> bool { std::optional<Predicate>([nextGroupID](const RefIndexedSubfeature& feature) -> bool {
return feature.collisionGroupId == nextGroupID; return feature.getCollisionGroupId() == nextGroupID;
}))); })));
} }
return collisionGroups[sourceID]; return collisionGroups[sourceID];

View File

@@ -77,7 +77,7 @@ struct RetainedQueryData {
class CollisionGroups { class CollisionGroups {
public: public:
using Predicate = std::function<bool(const IndexedSubfeature&)>; using Predicate = std::function<bool(const RefIndexedSubfeature&)>;
using CollisionGroup = std::pair<uint16_t, std::optional<Predicate>>; using CollisionGroup = std::pair<uint16_t, std::optional<Predicate>>;
CollisionGroups(const bool crossSourceCollisions_) CollisionGroups(const bool crossSourceCollisions_)

View File

@@ -363,7 +363,9 @@ void GeometryTileWorker::parse() {
ImageDependencies imageDependencies; ImageDependencies imageDependencies;
// Create render layers and group by layout // Create render layers and group by layout
std::unordered_map<std::string, std::vector<Immutable<style::LayerProperties>>> groupMap; mbgl::unordered_map<std::string, std::vector<Immutable<style::LayerProperties>>> groupMap;
groupMap.reserve(layers->size());
for (auto layer : *layers) { for (auto layer : *layers) {
groupMap[layoutKey(*layer->baseImpl)].push_back(std::move(layer)); groupMap[layoutKey(*layer->baseImpl)].push_back(std::move(layer));
} }

View File

@@ -3,6 +3,6 @@
namespace mbgl { namespace mbgl {
template class GridIndex<IndexedSubfeature>; template class GridIndex<RefIndexedSubfeature>;
} // namespace mbgl } // namespace mbgl

View File

@@ -141,7 +141,7 @@ void GridIndex<T>::insert(T&& t, const BBox& bbox) {
} }
} }
boxElements.emplace_back(t, bbox); boxElements.emplace_back(std::move(t), bbox);
} }
template <class T> template <class T>
@@ -164,7 +164,7 @@ void GridIndex<T>::insert(T&& t, const BCircle& bcircle) {
} }
} }
circleElements.emplace_back(t, bcircle); circleElements.emplace_back(std::move(t), bcircle);
} }
template <class T> template <class T>

View File

@@ -10,7 +10,7 @@ SymbolInstance makeSymbolInstance(float x, float y, std::u16string key) {
ImageMap imageMap; ImageMap imageMap;
const ShapedTextOrientations shaping{}; const ShapedTextOrientations shaping{};
style::SymbolLayoutProperties::Evaluated layout_; style::SymbolLayoutProperties::Evaluated layout_;
IndexedSubfeature subfeature(0, "", "", 0); IndexedSubfeature subfeature(0, {}, {}, 0);
Anchor anchor(x, y, 0, 0); Anchor anchor(x, y, 0, 0);
std::array<float, 2> textOffset{{0.0f, 0.0f}}; std::array<float, 2> textOffset{{0.0f, 0.0f}};
std::array<float, 2> iconOffset{{0.0f, 0.0f}}; std::array<float, 2> iconOffset{{0.0f, 0.0f}};