-
Notifications
You must be signed in to change notification settings - Fork 1.3k
[core] sort symbols using symbol-sort-key before placement #16023
Conversation
src/mbgl/renderer/render_layer.hpp
Outdated
@@ -29,7 +30,7 @@ class LayerRenderData { | |||
|
|||
class LayerPlacementData { | |||
public: | |||
std::reference_wrapper<Bucket> bucket; | |||
std::reference_wrapper<SymbolBucket> bucket; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's better to keep generic interface here, otherwise LTO will not be able to reduce SymbolLayer-related symbols from the binary if the symbol layer is disabled.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, thanks! I switched back to Bucket
src/mbgl/text/placement.hpp
Outdated
friend bool operator<(const BucketPlacementParameters& lhs, const BucketPlacementParameters& rhs) { | ||
return lhs.sortKey < rhs.sortKey; | ||
} | ||
SymbolBucket& bucket; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BucketPlacementParameters
shall not know about SymbolBucket
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be ok for BucketPlacementParameters
to have a reference to Bucket
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we instead just pre-sort LayerPlacementData
in RenderSymbolLayer::prepare() accordingly to the the symbol bucket sort key?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, changed to your suggestion. This means that there are now possibly multiple entries into LayerPlacementData per tile which we have to account for elsewhere
const RenderTile& tile; | ||
const mat4& projMatrix; | ||
std::string sourceId; | ||
std::shared_ptr<FeatureIndex> featureIndex; | ||
bool showCollisionBoxes; | ||
float sortKey; | ||
size_t symbolInstanceStart; | ||
size_t symbolInstanceEnd; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could the newly added fields be SymbolBucket
properties?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These properties come from SortKeyRange
. A bucket can have many SortKeyRange
s
2534f87
to
410a2b4
Compare
@pozdnyakov sorry about the delay getting back to this! I made changes based on your review so this is ready for another look. The |
|
||
bool firstInBucket = true; | ||
|
||
if (bucket->sortKeyRanges.size() == 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: bucket->sortKeyRanges.empty()
for (const SortKeyRange& sortKeyRange : bucket->sortKeyRanges) { | ||
LayerPlacementData layerData{*bucket, | ||
renderTile, | ||
static_cast<const GeometryTile*>(tile)->getFeatureIndex(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: might make sense to cache static_cast<const GeometryTile*>(tile)->getFeatureIndex()
in a local variable
@@ -656,18 +661,17 @@ void Placement::placeBucket(const SymbolBucket& bucket, | |||
} | |||
|
|||
} else { | |||
for (const SymbolInstance& symbol : bucket.symbolInstances) { | |||
placeSymbol(symbol); | |||
auto endIt = bucket.symbolInstances.begin() + params.symbolInstanceEnd; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we check that endIt <= bucket.symbolInstances.end()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope, would an assert be what you're looking for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
assert is fine (as long as there are no possible code paths that could violate it 😄 )
src/mbgl/layout/symbol_layout.cpp
Outdated
|
||
if (mode == MapMode::Tile || anchorInsideTile) { | ||
if (sortFeaturesByKey) { | ||
if (sortKeyRanges.size() && sortKeyRanges.back().sortKey == feature.sortKey) { | ||
sortKeyRanges.back().symbolInstanceEnd = symbolInstances.size() + 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sortKeyRanges.back().symbolInstanceEnd = symbolInstances.size();
shall be enough, no? begin()
+ size = end()
🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like I'm setting it before adding the new symbol instance. I guess moving it after and removing the + 1
would be cleaner
src/mbgl/text/placement.cpp
Outdated
for (const SymbolInstance& symbol : bucket.symbolInstances) { | ||
placeSymbol(symbol); | ||
auto endIt = bucket.symbolInstances.begin() + params.symbolInstanceEnd; | ||
for (auto it = bucket.symbolInstances.begin() + params.symbolInstanceStart; it != endIt; it++) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
styling nit: better have auto beginIt = bucket.symbolInstances.begin() + params.symbolInstanceStar
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: ++it
fix #15964
partially port mapbox/mapbox-gl-js#9054
Currently symbol-sort-key works:
This pr makes it work for collisions across tile boundaries as well.
This splits the bucket into ranges of symbolInstances with the same sort key. All the ranges from all the tiles in a layer are inserted into a sorted list. Placement is done in the order of the list.
@pozdnyakov feel free to assign reviewing to someone else if you want