-
Notifications
You must be signed in to change notification settings - Fork 2.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
port CollisionIndex and Placement changes from -native #5890
Conversation
Awesome! I'm just starting to work through the PR, should get more comments in tomorrow. It appears to me that this fixes part of #5887 (in that tiles never "lose" their collision index because they don't hold references to the collision index any more), but maybe makes more of a problem in the case when a |
Yes... I think so. Would adding a |
aac1687
to
0570b39
Compare
src/style/placement.js
Outdated
@@ -1,25 +1,26 @@ | |||
// @flow |
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.
Can we rename this file to pauseable_placement.js
so the name doesn't collide with src/symbol/placement.js
?
Haven't figured out the problem yet, but just panning around I see sometimes placement doesn't seem to finish (?) until some later map interaction: Also on zooming out I'll see symbols disappear: (This is running against 7bb3d45) |
src/symbol/placement.js
Outdated
|
||
let placeText = false; | ||
let placeIcon = false; | ||
//let offscreen = true; |
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 the plan to hook this back up later?
|
||
import type {OverscaledTileID} from '../source/tile_id'; | ||
import type {SymbolInstance} from '../data/bucket/symbol_bucket'; | ||
import type SymbolBucket from '../data/bucket/symbol_bucket'; | ||
import type StyleLayer from '../style/style_layer'; | ||
import type Tile from '../source/tile'; | ||
|
||
/* | ||
The CrossTileSymbolIndex generally works on the assumption that |
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 comment needs updating.
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.
updated in 8e20dd3
70eb215 should fix the missing labels |
} | ||
|
||
const tileIndex = new TileLayerIndex(tileID, symbolInstances); | ||
|
||
// make all higher-res child tiles block duplicate labels in this tile |
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 two loops (child index and parent index) still have structure and comments from when child and parent indexes had different blocking logic. Now that the logic is really just "run findMatches
across all zoom levels", maybe we could express this more clearly with one loop that just has a branch for looking up child vs. parent indices?
src/style/style.js
Outdated
.sort((a, b) => (b.tileID.overscaledZ - a.tileID.overscaledZ) || (a.tileID.isLessThan(b.tileID) ? -1 : 1)); | ||
} | ||
|
||
if (this.crossTileSymbolIndex.addLayer(styleLayer, layerTiles[styleLayer.source])) symbolBucketsChanged = true; |
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.
How about symbolBucketsChanged |= addLayer(...
instead?
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.
I think a regular if
is clearer than cleverly using a bitwise or
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.
and flow expects numbers not booleans 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.
OK, how about just bringing the symbolBucketsChanged = true
down to its own line? My reasoning is that when someone is scanning the logic looking for where assignments happen, they're easiest (most common) to see when they start the line they're on.
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.
good point, would this alternative be better than a separate line?
const layerBucketsChanged = this.crossTileSymbolIndex.addLayer(styleLayer, layerTiles[styleLayer.source]);
symbolBucketsChanged = symbolBucketsChanged || layerBucketsChanged;
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.
Yeah that's good.
👍 Looking good now. |
It would work to prevent errors, but wouldn't that still exhibit the behavior from #5716 (comment)? Ideally, I think the results of |
It looks like getting rid of full placement on tile loading is working to make the ten-second pitched rotation animation case significantly smoother (looks like 2 instances of stutter after vs. about 15 before): 🎉 ! |
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.
b0aa49b
to
98dbc7f
Compare
@ChrisLoer can you review c47acaa, d44241b, ba0dc8a, 98dbc7f which are meant to fix flickering bugs related to data and style updates? |
src/style/style.js
Outdated
this.collisionIndex = this.placement.collisionIndex; | ||
this.placement.setRecent(browser.now()); | ||
} else { | ||
this.placement.setRecent(browser.now()); |
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 was tricky for me to read -- it looks like setRecent
is just being duplicated, it's easy to miss that setRecent
is going to set stale
to false, and confusing that we want to undo it right away (because we want to update _recentUntil
for throttling, right?).
Could we just save something like inProgressPlacementStale
at the top and set it at the bottom? It might be clearer.
Or would it make sense to simplify this just by always committing the pausable placement? Do we expect there's some performance win from keeping the original placement object unmodified in the case nothing changes?
src/symbol/placement.js
Outdated
class JointPlacement { | ||
text: boolean; | ||
icon: boolean; | ||
// offscreen = outside viewport, but within CollisionIndex::viewportPadding px of the edge |
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.
By the time it gets here "offscreen" now means something like "skip fade animation" since it's the combination of "offscreen" and "justReloaded". We should come up with a new name to account for that once the two concepts are combined.
The index relied on a source layer and index to identify a feature. If a data layer gets updated a new bucket is formed where these identifiers probably don't match the previous bucket. Since there is a gap between a bucket being loaded and the index being updated (during the next placement) it was possible for a query to return wrong results. This prevents it from returning incorrect features but it does not return the correct features. This might cause it to return empty results.
6f8caa4
to
6dd9f66
Compare
This ports changes to
CrossTileSymbolIndex
andPlacement
from -native (mapbox/mapbox-gl-native#10436) back to -js.Previously symbol opacities were stored directly on
SymbolInstance
s. Whenever a tile was added or removedCrossTileSymbolIndex
would do a bunch of calculations and copy these opacities directly betweenSymbolInstance
s, which it would hold references to. The approach was really stateful. The new approach untangles things into four more distinct steps:crossTileIDs
to matching symbols (CrossTileIndex
)crossTileID
in the current set of tiles (Placement.placeLayer
)Placement.commit
)crossTileID
(Placement.updateLayerOpacities
)A stale
Placement
can be used to update newly loaded buckets. This lets us avoid doing a full, expensive placement on every frame where a tile gets loaded. It uses the old values and updates them after a new Placement (split over several frames) has been produced.Launch Checklist
The most critical benchmark for these changes is
Paint
and the results look good.setData
symbol exampleI still need to finish writing new tests but the pr is at the point where it could be reviewed.