Improving Plasma’s Rendering (Part 1/2)

Background:

Many parts of Plasma are powered by QtQuick, an easy to use API to render shapes/text/buttons etc.
QtQuick contains a rendering engine powered by OpenGL making full use of the graphics card keeping our drawing super fast, super lightweight and in general amazing...when things work.

Handling Nvidia context loss events

When the proprietary nvidia driver comes out of suspend, or from a different terminal the pictures that it had stored get corrupted. This leads to returning to an image like this. Worst as we show stray video memory it even leak data on the lock screen.

When this occurs it might look something like this:
Like something from the Tate Modern...a horrible mess.

With various text or icons getting distorted seemingly at random.

Fortunately NVidia do have an API to emit a signal when this happens, allowing us to at least do something about it.

This handling to be done inside every single OpenGL powered application, which with the increasing popularity of QtQuick is a lot of places.

The new state

After over a year of gradual changes all of Plasma now handles this event and recovers gracefully. Some of these changes are in Qt5.13, but some more have only just landed in Qt 5.14 literally this evening.

Some notes for other devs

A QtQuick application

Due to some complications, handling this feature has to be opt-in. Triggering the notification leads to some behavioural changes. These behavioural changes if you're not prepared for will freeze or crash your application.

To opt-in one must explicitly set the surfaceFormat used for the backing store to have:
QSurfaceFormat::setOption(QSurfaceFormat::ResetNotification)

Within KDE code this can be done automagically with the helper function
KQuickAddons::QtQuickSettings::init() early in your main method.
This sets up the default surface format as well as several other QtQuick configurable settings.

Everything else is now all handled within Qt, if we detect an event the scene graph is invalidated cleaned and recreated.

However, if you create custom QQuickItem's using the QSG classes, you must be really really sure to handle resources correctly.

As a general rule all GL calls should be tied to the lifespan of QSGNodes and not of the QQuickItem itself. Otherwise items should connect to the window's sceneGraphInvalidated signals.

Using QtOpenGL outside QtQuick

To detect a context loss, check for myQOpenGLContext->isValid() if a makeCurrent fails.

In the event of a context loss one must discard all known textures, shaders, programs, vertex buffers, everything known to GL and recreate the context.

One especially quirky aspect of this flag is that in the event of a context loss glGetError will not clear itself, but continue to report a context loss error. Code trying to reset all gl errors will get stuck in a loop. This was the biggest battle in the seemingly never-ending series of patches upstream and why it has to be opt-in.

In the case of a shared context a reset notification is sent to all contexts who should recreate independently.

You can read more about the underlying GL spec.

Leave a Reply

Your email address will not be published. Required fields are marked *