-
Notifications
You must be signed in to change notification settings - Fork 1.3k
[core] Fix symbol flickering during tile reload #7616
Conversation
@jfirebaugh, thanks for your PR! By analyzing this pull request, we identified @ansis, @incanus and @tmpsantos to be potential reviewers. |
fe4c382
to
fa2a465
Compare
for (auto& bucket : result.buckets) { | ||
buckets[bucket.first] = std::move(bucket.second); | ||
} | ||
symbolBuckets = std::move(result.symbolBuckets); |
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.
This also fixes a potential issue that could occur when after a relayout, a layer doesn't have any data anymore. In this case, it wouldn't produce a new bucket, so the old bucket would not be overwritten.
Could you please use branch names that are unambiguous? Using a digit-only branch name makes it harder to check out the branch locally. |
@@ -59,7 +59,7 @@ class GeometryTile : public Tile { | |||
|
|||
class PlacementResult { | |||
public: | |||
std::unordered_map<std::string, std::shared_ptr<Bucket>> buckets; | |||
std::unordered_map<std::string, std::shared_ptr<Bucket>> symbolBuckets; |
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 change this to std::shared_ptr<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.
We could, however it would make GeometryTile::getBucket
longer because it couldn't use layer.is<SymbolLayer>() ? symbolBuckets : nonSymbolBuckets
. Not sure if it's worth it.
I tested this with a database that has prior cache data in my testing area (Berlin), and ran the following SQL command to simulate expired + non-304 responses from the server: Here's a frame sequence I recorded with this patch: http://bl.ocks.org/kkaefer/raw/a422cc89a78917aaf718fe022c61bfe8/ |
This pull request fixes a part of the issue; the other part of the issue was introduced just a few days ago in 99c1a0e#diff-7c17b75ae445adc15c24e3f167193e4eR217: When a tile in the cache is expired, we start a refresh request. In many cases, we're getting a 304 response (not modified) back, in which case we don't do anything. However, when the tile changed, we're calling std::vector<std::vector<std::unique_ptr<Layer>>> groups = groupByLayout(std::move(*layers)); This means that it moved the layer information objects out of itself, and through some hoops into the I implemented a fix in 7615...7615-reset-layers-after-redolayout, which works by disengaging the |
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.
Incomplete fix
Thanks for tracking down #7586 as a cause of flickering. Indeed, |
Discard prior symbol buckets only when new symbol buckets became available, in order to eliminate flickering when tiles are refreshed.
This reduces state and simplifies the test added in the prior commit.
It should be safe to invoke GeometryTileWorker::setData multiple times without invoking GeometryTileWorker::setLayers. Therefore GeometryTileWorker::redoLayout() must not consume the layers.
@@ -254,7 +254,7 @@ void SymbolLayout::addFeature(const SymbolFeature& feature, | |||
? SymbolPlacementType::Point | |||
: layout.get<SymbolPlacement>(); | |||
const float textRepeatDistance = symbolSpacing / 2; | |||
IndexedSubfeature indexedFeature = {feature.index, sourceLayerName, layers.at(0)->getID(), symbolInstances.size()}; | |||
IndexedSubfeature indexedFeature = {feature.index, sourceLayerName, layerIDs.at(0), symbolInstances.size()}; |
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.
Is it guaranteed that layerIDs
always has at least one element?
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.
That invariant should hold: the layer IDs are constructed from the layer group, and if there's no group, no SymbolLayout
will be created. However, just in case it doesn't, I used at(0)
here rather than [0]
to get an exception rather than invalid memory access.
Yeah, agreed. There's a call to |
Discard prior symbol buckets only when new symbol buckets became available, in order to eliminate flickering when tiles are refreshed. Plus followup refactor.
Fixes #7615