-
-
Notifications
You must be signed in to change notification settings - Fork 3.5k
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
Store font texture atlas handles in a separate list in TextLayoutInfo #9471
base: main
Are you sure you want to change the base?
Conversation
PositionedGlyphs in the same text section all share the same texture atlas, so only perform a texture atlas lookup when the section index changes.
`PositionedGlyph` * Added back size field. * Changed index fields to u32 instead of usize. `GlyphBrush` * `process_glyphs` returns the texture atlas handles in a separate vector. `extract_text2d_sprite` & `extract_text_uinodes` * Added an outer loop to text extraction that iterates through `TextLayoutInfo`'s atlas handle list.
Would it be possible/make sense to do something similar, but based on |
Example |
Would it be possible to do something similar, but based on section_index
rather than glyph_index?
not sure
The code would be simpler if it just stored an atlas handle per section index but we'd end up storing a lot of duplicate handles for stuff like multi-colored text.
|
Are glyphs already stored/processed in increasing order of Either way, maybe Sorry for the somewhat lazy reviews. Not enough contiguous free time to actually understand what's going on in these pipelines. |
You've given me a really good idea actually, I can clean this up and fix #9278 at the same time. |
…hBatch` vector. Each `PositionedGlyphBatch` consists of a texture atlas handle and a range. The ranges partition the `PositionedGlyph` list by texture atlas. Before leaving `GlyphBrush::process_glyphs` we sort the `PositionedGlyphBatch`es by their texture atlas handle, so that glyphs from the same texture are batched together during rendering.
Example |
Alright, getting up to speed here. I hadn't noticed that This is interesting. So this is doing "local batching" of for each entity. Text across multiple entities with the same font is not batched. It also looks like a scenario similar to your new example like:
would result in at least 3 batches, right? More if the particular glyphs in a section lie in a different atlas of the It seems like a fairly niche optimization. Have we attempted to / is there a plan to eventually do "global batching" of glyphs? |
Text from different entities can get batched together. It depends on how elaborate the UI is and how the node tree is organised. #8793 added in 0.11 improved things a lot. The Also, if you are conscious of how things work you can rearrange a UI layout to reduce the number of batches significantly. Assume the labels are all from the same font, and the images are all from the same texture atlas. A natural way to construct this UI is to have a row of nodes, where each node in the row contains an item button and its label arranged in a column (the red lines denote the boundaries of the column nodes): With this design, the items will be rendered in seven batches:
A different approach would be to place all the labels first and then arrange the items in a row inside a node placed above the inventory panel: Just two batches would be generated for this design:
Yep that would result in three batches in main, and two with this PR (assuming we're not over the texture atlas limit for fonts). If someone is displaying large pages of text that use many different fonts these changes will have a large impact but otherwise, it's not going to help that much.
I've got a second PR #9212 that uses a similar "local batching" strategy to greatly improve overall UI extraction performance. I don't know that much about rendering, so I've been concentrating on improvements like this which reduce the amount of data and arrange and manage it more efficiently etc. Text rendering is quite difficult to optimise I think as the glyphs have transparency and we can't just sort everything by depth. The UI layout tree z-order rules are very complicated as well. Unfortunately we can't just walk the UI layout tree and assume that every element deeper in the tree will be drawn above every element before it. |
Ah, right. The UI stack stuff is a bit of an obstacle.
I was actually confused there, but I see now that the existing UI batching gets that down to two. I appreciate the thorough explanation. |
Yep, another change I'd like to make is to remove |
Objective
Most displayed text only uses one
TextureAtlas
asset but:TextLayoutInfo
stores a texture atlas handle per individual glyph.fixes #9278
Solution
Remove the texture atlas asset handle from
PositionedGlyph
.Add a new field
batches: Vec<PostionedGlyphBatch>
toTextureLayoutInfo
.Each
PositionedGlyphBatch
consists of a texture atlas handle and a range. These ranges partition thePositionedGlyph
list into contiguous sections sharing the same texture atlas.Before leaving
GlyphBrush::process_glyphs
we sort thePositionedGlyphBatch
vector by texture atlas handle ensuring that glyphs sharing the same texture are batched together during rendering.The Bevy stress test examples don't capture the batching change improvements. This example reports 25% better fps on the textlayout-refactor branch compared to main on my computer:
Changelog
TextLayoutInfo
atlases: Vec<(Handle<TextureAtlas>, usize)>
to hold the atlas handles for the fonts instead of individualPositionedGlyphs
.PositionedGlyph
:atlas_info
field.glyph_index: usize
field.extract_text2d_sprite
&extract_text_uinodes
:TextLayoutInfo
's atlas handle list.GlyphBrush::process_glyphs
:Migration Guide
TextLayoutInfo
no longer stores texture atlas handles per glyph but instead in a separate vectoratlases
.