UI Toolkit runtime UI performance

I would like to know how many times performance improvement of current runtime UI performance at Unity 2022.2 compares to uGUI and is there any plan to even further improve the performance?

Currently is that able to draw a lot of different separate UI panels in 1 batches only?

Is that possible to still draw in 1 batches if the UI panel has image and text mesh pro text together that uGUI needs to have 1 more batches to render text mesh pro text?

And also is that able auto combine different images into single sprite atlas at runtime for all the UI panels that has been opened to make it render in 1 batches? For this the use case is the panel is consist of static sprite atlas created by currently available SpriteAtlas feature and then at runtime dynamically load other few of separate images that is not in sprite atlas into panel then at the end it will auto combine into single sprite atlas at runtime and make it draw 1 batches.

And lastly is that UI runtime able to dynamically update only the part that need update like a complex UI panel I only update 1 text and ui runtime will just update 1 text instead of update the entire panel that slow down the performance massively?

Yes in general performance is a still a big area of focus for UI Toolkit.

As a general note, each PanelSettings instances are not batched together, but multiple Visual Elements and multiple UI Documents can as long as they belong to the same PanelSettings.

Yes trying to minimize the number of batches to draw UI was the main focus of the UI Rendering strategy for UI Toolkit.
Compared to UGUI which offers the flexibility of customizing the UI shader, UI Toolkit has a single uber-shader for the whole UI.
By integrating the core bits of Text Mesh Pro in core Unity (TextCore), the same shader can also draw text so this doesn’t qualify as a batch breaking reason right now (text vs. non-text element).

UI Toolkit supports both static Sprite Atlases and has Dynamic Atlas feature (one large texture per PanelSettings). The Dynamic Atlas is populated as elements are added.
Some of its behaviour can be configured in the Dynamic Atlas Settings of the Panel.

As an aside, the UI Toolkit shader has 8 texture slots which can be bound dynamically (for example 1 dynamic atlas, 1 SpriteAtlas, multiple single textures). In 2022.1, font atlas textures can also be part of this dynamic slots, whereas there is only a single font texture slot in 2021 LTS.

It depends what you mean by “update”. But one thing that UI Toolkit does is that it doesn’t need to combine geometries together to enable batching. Instead, pages of vertices/indices are pre-allocated and ranges of these pages are allocated as needed for each element. This allows the geometry to be contiguous on the GPU to allow drawing multiple elements as once.
When an element changes, we just “update” the range for the VisualElement so we don’t need to re-combine the geometry.

Additionally one can use the UsageHints on specific elements to enable some transformations be done on the GPU directly (like moving vertices).

We know all of this information isn’t properly documented, I expect our documentation be updated before end of year about this.

In pratice though, any non-trivial UI will actually incur more than 1 draw calls, because:

  • the geometry extends the maximum size for a specific page
  • using UsageHints presents a tradeoff between CPU cost and batch breaks
  • usage of masks changes the stencil buffer which leads to batch breaks

But in practice what we observe is that keeping the same material and just drawing a different range with a few different settings is less expensive that reconfiguring the whole GPU state.

3 Likes

Basically I don’t really want to have uGUI authoring experience that uGUI will need to redraw the entire UI Panel even u just want to update 1 text only which slow down performance a lot and u need to move dynamically update UI element into another Canvas to solve this issue but u need to cost 1 more batches. Just want to know whether UI toolkit can fix and improve this for runtime ui to make it auto and dun need to cost 1 more batches?

There is a lot of nuance to UI rendering performance as my first post hopefully explains.

But yes I think with UI Toolkit we have a strategy in place that allow better scalability when a single thing is changed, mostly because we avoid any sort of mesh combination work.

1 Like

If I understand correctly does it means that I can a lot of different fonts and same font with different outline value all still can render in 1 batches?

I don’t know for sure what the outline effect incurs, but I’d think it doesn’t cause a batch break. I’ll ask for someone to confirm.

With 2021 LTS every font leads to a different draw call.
With 2022+ there 8 texture slots so in theory up to 8 fonts, but it will compete with other textures at some point so it really depends on the UI content you’re drawing.

1 Like

Basically at TextMeshPro using the same font to create multiple font assets that each have little different setup like different outline value. From wat I observe it will increase batches at uGUI for each different font asset added.

Awesome. Looks like I can achieve multiple panels to render in just 1 batches if I plan out the UI design nicely.

I tried using the texture atlas with UI builder. If the atlas gets updated all the references break. I use TexturePacker to pack the sprites.

Hi, so did I get you correctly, all sprites assigned to various UI elements like buttons backgrounds are automatically added to Dynamic Atlas?

Is there a way to preview it? What happens if sprites do not fit max atlas size? it generates 2 atlases or they are just not batched to atlas?

Also about static Sprite Atlases, I didnt find a way to assign some sprites from Sprite Atlas to for example Button background. Would you suggest related documentation please?

We have documentation about the Dynamic Atlas here (see “Control textures of the dynamic atlas”): https://docs.unity3d.com/Manual/UIE-performance-consideration-runtime.html

We are about to land an update to this page, which goes like this:

To use Unity’s Sprite Atlas system, you will need to switch to the “Sprite” type next to the background property in the UI Builder. Please check the following page (and its child pages) for additional details: https://docs.unity3d.com/Manual/UIB-styling-ui-backgrounds.html

1 Like

Thanks for the explanation. Please consider a bug in documentation:

NOT VisualElement.backgroundImage BUT VisualElement.style.backgroundImage

1 Like