Skip to main content

Performance

YAUI is fast by default. This page explains what costs time, and how to keep it low. For measurements against uGUI and UI Toolkit, see Benchmarks.

Draw calls​

A panel is drawn in one draw call, except where:

  • the material changes between elements in the draw order (custom materials),
  • a mask starts or ends (YauiMask),
  • more than 8 textures are used by consecutive elements. Font atlases, sprite textures, dynamic atlas pages and raw image textures all count,
  • a backdrop blur is drawn (see below),
  • YAUI draws elements without heavy features apart, so that they use a lighter shader (see below).

Elements with the same material are drawn together even when other elements come between them in the draw order, as long as those do not overlap them: YAUI reorders the draws where the result stays the same, like uGUI's batching.

To keep draw calls low:

  • Use the uber shader (box style, text effects, image types) instead of custom materials. Packages that shade primitives in their own way can do it inside the uber shader with shader modules.
  • Use ClipChildren instead of YauiMask when a rectangle or a single rounded rectangle is enough.
  • Keep small sprites in the dynamic atlas, and put larger sprites that are shown together in the same sprite atlas.
  • Use few fonts in one panel.

CPU​

WorkTips
Text generation is the most expensive operation.Set texts only when they change. Keep the number of texts that change in the same frame low.
Layout runs for the boundaries that contain changes.Give fixed Width and Height to containers whose size does not depend on their content, to make them layout boundaries. Animate with the render transform, not with layout properties.
Hierarchy changes rebuild the draw order of the panel.Reuse elements instead of creating and destroying them each frame. Enabling and disabling a GameObject is also a hierarchy change.
YauiPanel.ForceUpdate() completes all the work at once on the main thread.Call it only when you need the result in the same frame.

Colors, render transforms and opacity are nearly free to change, and a frame without changes costs almost nothing. Hidden panels (opacity 0, or nothing visible) are not drawn.

Cameras​

In camera mode, each URP camera has a fixed CPU cost that is much larger than drawing a panel. Instead of a camera for each layer of UI, draw the panels in a camera that already renders, at different injection points. If a camera exists only to show some panels over the image of another camera, enable it only while YauiPanel.IsDrawn is true for one of them.

GPU​

The uber shader has a cost for its many features, which shader variants keep to the features in use: the GPU time of YAUI is about the same as uGUI's to 1.5 times, and lower than UI Toolkit's (see Benchmarks). To keep it low:

  • Avoid large overlapping transparent areas (overdraw), as with any UI.
  • Large shadow blurs enlarge the quads that are drawn.
  • YAUI_PIXEL_CLIP in custom shaders costs GPU time on mobile. Enable it only when needed.

Shader variants​

Each draw call uses a variant of the uber shader with only the features its elements use: text, images, borders (with radial fills) and shadows. Features that no element uses cost nothing, even though the uber shader has them.

One element with a shadow would make its whole draw call pay for shadows. When it pays off, YAUI draws the elements with shadows (or borders) in draw calls of their own, so that the others use a lighter variant. It weighs the fixed cost of the extra draw calls, on the GPU and the CPU, against the GPU time saved on pixels. YauiBatching sets the balance:

PropertyDefaultDescription
SplitByShaderFeaturestrueWhether draws split by heavy features.
GpuWeight, CpuWeight1The weights of GPU and CPU time. The default minimizes the total work, which saves power and heat at a capped frame rate. Raise GpuWeight in a project bound by the GPU, or CpuWeight in one bound by the CPU, for instance per quality level.
SplitMargin2How many times its cost a split has to save.

The estimates of these costs come from a mid-range Android device. While a panel moves, YAUI chooses its draws again every frame on a worker thread; when that costs more than a split saves, it keeps one draw until the panel stops.

The first draw with a variant can stall while the GPU creates its pipeline state. YAUI does not warm them up, since the states a project needs depend on the project: warm them up in your project if needed (for instance with GraphicsStateCollection). The variants are the keywords YAUI_TEXT, YAUI_IMAGE, YAUI_BORDER, YAUI_SHADOW and YAUI_PIXEL_CLIP of Hidden/Yaui/Uber.

Backdrop blur​

A backdrop blur ends the panel's pass, copies the target, and blurs it at a reduced size before the element is drawn. Its cost grows with the size of the target and of the blur. Elements next to each other with the same material share one copy, so put them next to each other in the hierarchy.

Scroll views​

YauiScrollView moves its content with the render transform, so scrolling never runs the layout. It does not virtualize its items: all items are drawn and laid out. For very long lists, reuse a small set of items in a higher layer.