[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.
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. |
| 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.
Could we change this to std::shared_ptr<SymbolBucket>?
There was a problem hiding this comment.
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 |
|
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.
| : 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.
Is it guaranteed that layerIDs always has at least one element?
There was a problem hiding this comment.
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