-
Notifications
You must be signed in to change notification settings - Fork 1.3k
[core] Don't use a separate SpriteAtlas for annotation images #9003
Conversation
d990b2c
to
75fecf2
Compare
@jfirebaugh The size/capacity of Style::spriteAtlas should also be changed to 2048x2048 since it now needs to have capacity for style sprite as well as user added annotations. |
src/mbgl/sprite/sprite_atlas.cpp
Outdated
@@ -42,13 +42,8 @@ SpriteAtlas::SpriteAtlas(Size size_, float pixelRatio_) | |||
|
|||
SpriteAtlas::~SpriteAtlas() = default; | |||
|
|||
void SpriteAtlas::onSpriteLoaded(Images&& result) { | |||
void SpriteAtlas::onSpriteLoaded() { | |||
markAsLoaded(); |
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 can now remove this public method and set loaded = true
directly.
if (style.getImage(image)) { | ||
style.removeImage(image); | ||
} | ||
} |
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'm worried about how this will interact with image names from the sprite sheet: Removing annotation images that have the same name as images in the sprite sheet means that they will be dangling.
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 went back and forth about this. We could prefix the ids when adding to the style. But using the same namespace would actually fix #4750.
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 use some sort of reference counting system?
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.
What do you have in mind?
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.
For glyphs, we store the GlyphRequestor
in each Entry
/GlyphValue
, and only remove it from the atlas once all requestors are gone. We could use a similar model for requesting sprite images that were implicitly added to the sprite atlas.
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 elected to use a prefix, as that solves both the removal issue and other issues with ID collisions.
@@ -167,13 +159,26 @@ void AnnotationManager::updateStyle(Style& style) { | |||
shape.second->updateStyle(style); | |||
} | |||
|
|||
for (const auto& image : images) { | |||
if (!style.getImage(image.first)) { | |||
style.addImage(image.first, std::make_unique<style::Image>(image.second)); |
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 move images instead of copying them? This will leave the Image object in the unordered_map
empty, but we'll never access it again (there's no getImage
method on the AnnotationManager
). We can treat the mere presence of the key as the availability of this image, and only call style.addImage
when we still own the image.
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.
For clarity, I'd rather copy; it's cheap, because all that's being copied is an Immutable
, which is a shared pointer. (Edit: we actually have to copy because annotation images must persist across style replacement.)
addSpriteImage(spriteImages, id, std::move(image), [&](style::Image& added) { | ||
spriteAtlas.addImage(id, added.impl); | ||
}); | ||
images.emplace(id, *image); |
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.
Why are we making a copy here? We already own the style::Image
object.
417d118
to
6c6cb2e
Compare
In order for this to not reduce the total combined capacity for spite and annotation images, while simultaneously not increasing the base memory consumption and failing the related test, we'll need to implement auto-growing atlas textures. |
6c6cb2e
to
7b61b8a
Compare
7b61b8a
to
957e6e0
Compare
src/mbgl/sprite/sprite_atlas.cpp
Outdated
if (entry.iconRect) { | ||
bin.release(*entry.iconRect); | ||
if (entry.iconBin) { | ||
// shelfPack.release(*iconBin); |
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.
Does shelfpack currently support removing bins?
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.
Not currently, we're waiting on v2 / mapbox/shelf-pack-cpp#5 which @bhousel is working on.
957e6e0
to
f3dbb82
Compare
67d5254
to
f7cd879
Compare
25018c1
to
5dc6a13
Compare
This is ready for re-review. |
e9cd79d
to
4faedf6
Compare
@@ -155,7 +148,7 @@ void AnnotationManager::updateStyle(Style& style) { | |||
std::unique_ptr<SymbolLayer> layer = std::make_unique<SymbolLayer>(PointLayerID, SourceID); | |||
|
|||
layer->setSourceLayer(PointLayerID); | |||
layer->setIconImage({"{sprite}"}); | |||
layer->setIconImage({SourceID + ".{sprite}"}); |
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.
👍
@@ -166,13 +159,26 @@ void AnnotationManager::updateStyle(Style& style) { | |||
shape.second->updateStyle(style); | |||
} | |||
|
|||
for (const auto& image : images) { | |||
if (!style.getImage(image.first)) { | |||
style.addImage(std::make_unique<style::Image>(image.second)); |
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 move them instead of copying them? What is the benefit of retaining the image?
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.
See previous discussion.
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.
Sorry
// create a new image with the input ID prefixed by "com.mapbox.annotations". | ||
std::string id = SourceID + "." + image->getID(); | ||
images.emplace(id, | ||
style::Image(id, image->getImage().clone(), image->getPixelRatio(), image->isSdf())); |
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 is a no-op when there is already an image with the same ID. Adding a different image with the same name will thus not have any affect. Is that the intended API behavior?
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.
Maybe we could have a list of IDs we currently have, a list of IDs to remove, and a map of new sprite images to add, then replace existing entries in the map when calling addImage
.
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; I think the existing behavior is to replace the image (if it's the same size). I'll confirm and preserve that if so.
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.
Keeping a map of new sprite images to add isn't sufficient, because we also need to add all images in the case where there's a fresh style.
Eventually I think we should refactor AnnotationManager
so that it updates the style immediately in each operation, and is notified when there's a fresh style, but that's a separate refactor. For now I made it add all images every updateStyle
.
We gained a lot of overhead by reducing the initial SpriteAtlas size.
4faedf6
to
ac2f1f3
Compare
Instead, just add them to the Style as needed. Includes changes from #8905 and takes care to avoid regressing #3817.
In order for this to not reduce the total combined capacity for spite and annotation images, while simultaneously not increasing the base memory consumption and failing the related test, it includes a switch to auto-growing the SpriteAtlas texture using shelf-pack-cpp. This also fixes #8247 ("Measured vectorFootprint = 31104204 Bytes").