When working with graphical applications, there are multiple constraints and techniques applied in order to reduce the number of pixels that are being uploaded to the GPU, swapped on screen, or being manipulated. Even with highly optimized GPUs, the massive number of pixels we have to deal with (a 1080p monitor, for example, has 2 million pixels!) forces everyone to have some level of scrutiny.
When it comes to Linux compositors and clients, a widely adopted technique is regional rendering. GTK tracks which parts of the window actually changed and only redraws that part; then sends this information to the compositor so that the compositor itself can redraw only the new contents of the window.
Fortunately, the entire graphics stack is well optimized for doing that! When using EGL, we can use eglSwapBuffersWithDamageEXT(), which receives a list of rectangles representing the parts of the window that changed. Mutter also uses a similar API after compositing the desktop.
With GTK4, we have not only GL-based renderers, but Vulkan renderers as well! A few years back, GTK4 received support for Vulkan on Wayland. While developing GNOME To Do (which already uses GTK4), I recently tried the Vulkan renderer, but the result was disappointing:
After a lot of research, asking around various places, and trying to understand Vulkan again, finally it was fixed! I must say, it was extremely hard to figure it out. Vulkan is very interesting, but the number of details is absolutely overwhelming. However, having it rendering correctly wasn’t enough.
The Vulkan renderer in GTK4 always submits the entire window to the compositor. Sure, we’re still rendering everything in the GPU, so pixels are not being uploaded, but it’s still suboptimal. Fortunately for us, we have VK_KHR_incremental_present, which allows us to tell Vulkan which parts of the window actually changed — like eglSwapBuffersWithDamageEXT() — and optimize the rendering.
This was already merged and will be part of GTK 4.
Leave a Reply