Why to optimize skins
While the PC the skin is written on might be fast enough to render the GUI at 4k/60fps, it might be too expensive to run on lower end hardware. This page will give examples how to optimize skins, focusing on GPU performance.
In general, the two most important resources on the GPU are memory bandwidth and computing power. Different systems might show different bottlenecks to render the GUI, but the following topics should help both.
Analysis via Renderdoc
It is highly advised to use a tool like Renderdoc, a debugging program for computer graphics. While it offers a lot of features for graphics developers, it is also suitable for skinners to check for issues in the GUI layer compositing. With Renderdoc, the amount of overdraw can easily be judged.
A tutorial how it can aid in skin development can be found here.
An important metric for performance evaluation is the amount of overdraw. Overdraw defines how many times a pixel gets rendered to, averaging across the whole screen. Using lots of layers increases the rendering costs. In order to have a performance target, a value should be picked when designing the skin.
|Raspberry Pi 3, 1080p60
|Raspberry Pi 4, 1080p60
|Odroid C2, 1080p60
|Intel HD 610, 1080p60
|Intel HD 630, 2160p60
Please take all of the values with a great pinch of salt. The actual value might vary when the system is busy, like when playing a video or rendering a visualization. Overdraw should be seen as a guide to keep the whole GUI experience consistent.
Also, the performance target can be set lower when doing animations transitioning between menus. This will result in stutter on low-end systems during the transition, but the user experience is fine otherwise. On systems where the video is rendered via the GPU (Intel and similar "desktop" systems), this might be more noticable.
As an example, a target of 3.5 permits the usage of one background layer (fanart) with one texture filter on top, while still leaving 1.5 pixel draws for UI elements.
For comparison, the overdraw for the Estuary movie home screen is about 4.2, while the amount for Confluence is about 1.8.
Reducing layer counts
While Kodi can render dozens of layers on top of each other, each layer consumes quite a bit of rendering resources. The overall goal should be to use as few layers as possible.
Typically, the most performance gains can be made by reducing the full-screen layers, but this is not exclusive to them.
Diffuse texture usage
The skinning engine has the ability to apply diffuse textures. While it might be tempting to get the same effect via a separate texture, it is faster.
Coloring via diffusecolors
In a lot of skins, coloring/shading is done by applying a white, featureless texture with a diffuse color to do color filtering. Most often, the same/similar effect can be obtained by applying the diffuse color to the underlying layer, so a whole layer can be saved.
With Kodi 20 (Nexus), it will even be possible to animate the diffuse color (see https://github.com/xbmc/xbmc/pull/21400).
Squashing filter layers
In a lot of skins, various shadow effects get applied to the fanart in the background. Most often, such effects can be combined together into one texture to achieve a very similar effect.
Combined into a diffuse texture, such savings could halve the rendering cost for some skins.
Disabling invisible layers
Always disable occluded layers. Even though they have no impact on the final result, they still have to be processed and rendered. This wastes a lot of resources.
Avoid presenting assets multiple times
Another pitfall is to present an asset (posters, fanart, ...) multiple times in the exact same location. While this has no or just a small impact on the output, it eats up resources.
Usage of background color
If the skin uses a plain background color, set it via the
<backgroundcolor> tag instead of using an image spanning the whole screen. This saves a good amount of resources.
Other optimization considerations.
Proper asset sizes
One easy to solve issue is the use of too large assets. Check the resolution of the displayed icons. They should be suitably sized to the targeted rendering resolution (most often 1920x1080). When too large, it will result in increased usage of memory resources and in decreased image quality.
For a lot of background effects, a smaller resolution texture might be used. Often enough, just 1/4th of the target resolution might do the trick (e.g. 960x540), especially when there are multiple layers.
Avoid infill by border textures
bordertexture with a transparent center is used, the GUI can be informed via
infill="false" that it does not have to be rendered.
Avoid almost opaque elements
Consider using opaque elements instead of barely transparent ones. Especially on modern GPU's, this avoids rendering everything below such an element.
Don't include unnecessary alpha layers in textures
Including an alpha layer in a texture implies that it is used, even if the texture is fully opaque. The GUI has to treat such an element as transparent, with all the associated costs.
Use single channel textures if possible
A lot of GUI assets included in skins are delivered in a RGB format, even when they are greyscale. A single channel format saves disk space and might even reduce memory bandwidth in the future. Such textures can be colored by a
Don't use different uniformly colored textures
Skins might use different textures to color in elements (for example "white.png", "red.png", "black.png"). Instead of using textures for each color, use a white texture in combination with a diffuse color. This saves resources.
Avoid dead-zones around icons
Icons are often used as decals, featuring transparent portions. Keep those transparent to a minimum to save resources, as the transparent pixels have to be rendered as well.