Skip to content
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

Glyph Atlas improvements #1923

Closed
wants to merge 3 commits into from
Closed

Glyph Atlas improvements #1923

wants to merge 3 commits into from

Conversation

bhousel
Copy link
Contributor

@bhousel bhousel commented Jan 12, 2016

Improves but does not completely eliminate issues with glyph atlas overflow (#141)

  • GlyphSource now manages multiple GlyphAtlases, 1 per fontstack.
  • GlyphAtlas GL textures start out 128x128 and grow by power of 2 up to 1024x1024
  • BinPack now uses shelf best height fit algorithm, more efficient packing for things with similar heights
  • Doesn't attempt to remove glyphs when removing tiles (performance boost)

@bhousel
Copy link
Contributor Author

bhousel commented Jan 12, 2016

cc @mourner @ansis @jfirebaugh

@ansis
Copy link
Contributor

ansis commented Jan 12, 2016

Doesn't attempt to remove glyphs when removing tiles (performance boost)

Do glyphs ever get removed? How big is the performance benefit?

@bhousel
Copy link
Contributor Author

bhousel commented Jan 12, 2016

Do glyphs ever get removed? How big is the performance benefit?

They do not get removed - for most languages with only a few dozen glyphs this is probably desired anyway as the overhead of constantly removing and then adding them back is not worth it. I would like to benchmark this rather than just trusting my own perceived performance.

For Asian character sets, I could see a potential rationale for refcounting the glyphs and removing the ones that aren't visible anymore.

I have been testing around this location in Southern China: # 10.01/22.9452/113.1932 - set tilt to maximum to load as many tiles as possible, and scroll around. It does take a LOT of scrolling to get to 2048x2048, and even textures larger than that are considered safe for WebGL.

To exceed the 1024x1024 limit, we would need to change how texture coordinates are packed in SymbolBucket shaderAttributes.

@mikemorris
Copy link
Contributor

For Asian character sets, I could see a potential rationale for refcounting the glyphs and removing the ones that aren't visible anymore.

Would it be possible to refcount all glyphs added to the atlas and only cull unreferenced glyphs if the atlas would be in danger of overflowing?

@mourner
Copy link
Member

mourner commented Jan 12, 2016

Yes, I think MRU-cache-like behavior would be optimal — remove the least used glyphs when atlas gets near overflowing. Might need some algorithmic effort though since you would have to use "holes" of different size in the atlas to place new glyphs.

@mourner
Copy link
Member

mourner commented Jan 12, 2016

As for the PR — the code changes look great. Rebase this into a few clean commits with passing builds and we can merge — even with the overflowing problem, it's better than the current approach.

@bhousel
Copy link
Contributor Author

bhousel commented Jan 13, 2016

As for the PR — the code changes look great. Rebase this into a few clean commits with passing builds and we can merge — even with the overflowing problem, it's better than the current approach.

Great! I squashed away the middle commits and rebased to master.. I'll open a separate issue to track follow on improvements to this.

@mourner
Copy link
Member

mourner commented Jan 13, 2016

Looks good to me, @ansis want to give a final look?
Also, do we need a similar native PR before we can merge?

@bhousel
Copy link
Contributor Author

bhousel commented Jan 13, 2016

I understand there is a need for resizing of sprite atlas also - want me to open a PR for that? It would be pretty easy to do (at least up to 1024x1024 dimensions).

@ansis
Copy link
Contributor

ansis commented Jan 13, 2016

@lucaswoj do you think have a separate glyphAtlas for each fonstack will cause problems with making text-font a data-driven property?

@lucaswoj
Copy link
Contributor

do you think have a separate glyphAtlas for each fonstack will cause problems with making text-font a data-driven property?

Yes, it probably would. But I don't want to delay landing this bug fix for that reason.

@mikemorris
Copy link
Contributor

@lucaswoj do you think have a separate glyphAtlas for each fonstack will cause problems with making text-font a data-driven property?

This will probably need to change to per-font glyph atlases with mapbox/DEPRECATED-mapbox-gl#4 if that makes a difference re data-driven styling.

@lucaswoj
Copy link
Contributor

Upon further thought, I don't think this will affect data-driven styling. We render each symbol in a separate draw call. There will be a performance cost to switching glyph atlases between each draw call but we can put off digging into that.

@mourner
Copy link
Member

mourner commented Jan 14, 2016

But this will change after we do #1898, right?

@lucaswoj
Copy link
Contributor

If/when we use ANGLE_instanced_arrays to render symbols, there'd still be one draw call per font

@ansis
Copy link
Contributor

ansis commented Jan 14, 2016

@bhousel looks good to me!

The only thing I'm wondering about is whether "not removing glyphs when tiles are removed" is worth it.(cc @kkaefer ) It would be useful to run a quick benchmark on master and see how much tile removeGlyphs takes up.

Other than that, this should be ready to merge!

@bhousel
Copy link
Contributor Author

bhousel commented Jan 15, 2016

The only thing I'm wondering about is whether "not removing glyphs when tiles are removed" is worth it.(cc @kkaefer ) It would be useful to run a quick benchmark on master and see how much tile removeGlyphs takes up.

I did a quick benchmark of this... It's admittedly not great, but I cycled through a 5 glyph-heavy spots and let the map "quiesce" each time.

tl;dr:

  • GlyphAtlas.removeGlyphs takes up 3.5% of the time spent. (I consider this significant).
  • On this branch GlyphAtlas.addGlyphs jumps up a bit (I think a lot of that is the console warnings, which would go away once we grow the texture as much as I'd like).
  • DrawSymbols is slower too, probably from redundant glyphAtlas.updateTexture(gl); calls - these can be minimized.
  • I do agree that a better solution involves refcounting and replacing unused glyphs in the texture, so I want to do that as a next priority.
  • merge if you like it - it's at least not worse than what we have now.

Master:

screenshot 2016-01-15 16 05 43

This Branch:

screenshot 2016-01-15 16 16 16

t.test('not enough room', function(t) {
var bp = new BinPack(10, 10);
t.deepEqual(bp.allocate(10, 10), {x: 0, y: 0, w: 10, h: 10 }, 'first 10x10 bin');
t.deepEqual(bp.allocate(10, 10), {x: -1, y: -1 }, 'not enough room');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be a followup task, but allocate should return null or undefined rather than (-1, -1) to indicate failure.

@jfirebaugh
Copy link
Contributor

merge if you like it

I like it, let's merge and ticket followups.

@ansis
Copy link
Contributor

ansis commented Jan 15, 2016

yeah, looks good! thanks for profiling

@bhousel
Copy link
Contributor Author

bhousel commented Jan 16, 2016

Thanks! I'll cleanup & merge tonight..

@bhousel
Copy link
Contributor Author

bhousel commented Jan 16, 2016

merged as
9d216c1 Limit glyph atlas texture growth to 1024x1024, remove comment
e55c8c5 Use Shelf Best Height Fit algorithm in BinPack, support texture resize
24b5eea Now GlyphSource will manage multiple GlyphAtlases (1 per fontstack)

@bhousel bhousel closed this Jan 16, 2016
@bhousel bhousel deleted the glyph_overflow branch January 16, 2016 01:28
@ansis
Copy link
Contributor

ansis commented Jan 16, 2016

\o/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants