-
Notifications
You must be signed in to change notification settings - Fork 1.3k
[core] Attempt placement if at least one image is ready #9816
Conversation
Additionally, there is a race condition that sometimes prevents the images from being emplaced after |
|
This looks good to me, but I'm just looking at the new per-tile atlas logic for the first time.
How would placement have already happened? Are there cases where Your changes make it look like we're going in the direction of supporting progressive loading/placement of images (so, we could get all glyphs and one of two images, do placement and render the tile, then get the second image, and redo placement (including text shaping) and render the tile again). I didn't think that was something we actually support (i.e. Is there a possible simplification where we make the "images get loaded all at once" expectation more explicit? In that case instead of trying to manage the state of |
Yeah -- can we revisit #9739? What exactly about the prior logic was a problem? |
Started to do some analysis... Tracing into the
This particular ordering is not guaranteed; the relative order between main and worker could vary. Also, I've seen this test pass even after reverting the |
I don't think so: I've added a new branch https://github.com/mapbox/mapbox-gl-native/tree/9739-revert-test that reverts cd8eb13, and |
This is exactly how the previous implementation works (and causes the test from #9739 to fail). |
I believe progressive loading/placement of images is exactly the intent - as per @jfirebaugh comments in #9739 (comment):
|
I'll try to reply both questions in a single answer:
In Do not attempt symbol placement if there is no data, layers, placement configuration or if there is any pending symbol dependencies left. The problem here lies in the pending symbol dependencies. Before #9739, whenever Given the analysis in #9816 (comment), the first call for This should be fine as long as the second The changes in #9739 changes this behavior by making the first call for However, this raises a new issue (as pointed out by @jfirebaugh in #9792) in which it causes symbol placement to never happen because In some cases, we've already done layout and attempted placement before new images have arrived (which is the case for API.ReaddImage and when |
@jfirebaugh, @brunoabinader can we solve the race condition by using the same As far as what happens when there's an error loading an image: I think we should treat resource loading errors as a fatal error for still image rendering, but mark the image as "completed" in continuous rendering mode so that we can run attemptPlacement, and potentially wait for a refreshed request or for network connectivity coming back. It seems like the underlying issue is that we don't have a strategy for how to explicitly handle resource loading failure. Tiles can be in a "loaded" state, which means that we've made an attempt to load it and received a reply (either positive or negative). We should look at adopting a similar concept for resources so that we know whether we're still waiting for a resource to load or can start attempting placement, even if some resources are missing. |
I think that would be a problem e.g. in continuous mode like you mentioned, in a sense that we want to start rendering tiles even though not all images are yet loaded. Also, from my tests the correlation does not solve the case where a placement attempt did not re-prepare the symbol layouts because a previous layout+placement sequence caused |
My very first attempt to make @@ -58,14 +59,22 @@ void ImageManager::getImages(ImageRequestor& requestor, ImageDependencies depend
// Otherwise, delay notification until the sprite is loaded. At that point, if any of the
// dependencies are still unavailable, we'll just assume they are permanently missing.
bool hasAllDependencies = true;
- if (!isLoaded()) {
- for (const auto& dependency : dependencies) {
- if (images.find(dependency) == images.end()) {
- hasAllDependencies = false;
- }
+ for (const auto& dependency : dependencies) {
+ if (images.find(dependency) == images.end()) {
+ hasAllDependencies = false;
}
} This causes |
After discussing with @ChrisLoer I came to conclusion these patches were in fact working around the fact that |
This patch fixes an edge case when two or more images are referred on a style, but only one of them gets actually fetched.
There are times (like in the test case from #9792) where two or more images are needed, but only one (or more up to n - 1) gets successfully fetched. In those cases, we still want to attempt placement, so
hasPendingSymbolDependencies
should return false. We force this behavior by checking whetherimageMap
is empty before actually checking for any pending image dependencies.This works as long as
imageMap
state is always up-to-date. This isn't true in cases e.g. when we had at least one placement attempt already. To fix that, we clear upimageMap
after using it, as it gets updated inGeometryTileWorker::onImagesAvailable
anyway.Fixes #9792.