virtio-gpu and qemu graphics in 2021
Time for an update, a few things did happen since the previous update in November 2019.
virtio-gpu features
Progress is rather slow in qemu due to shifted priorities. That doesn't mean virglrenderer development is completely stalled though. crosvm (aka Chrome OS Virtual Machine Monitor) has virtio-gpu support too and is pushing forward virglrenderer development these days. There is good progress in virglrenderer library (although I don't follow that closely any more these days), crosvm and linux kernel driver.
Lets go through the feature list from 2019 for a quick update first:
- shared mappings
- Not a separate feature, it's part of blob resources now.
- blob resources
- Specification is final. Linux kernel got support. crosvm too as far I know. qemu lags behind.
- metadata query
- Is implemented using execbuffer commands. Which is the communication path between guest driver and virglrenderer, so virtio-gpu doesn't need any changes for this.
- host memory
- Also part of blob resources.
- vulkan support
- Not fully sure where we stand here. Blob resources are designed with vulkan memory management needs in mind, so there shouldn't be any blockers left in the virtio-gpu guest/host interface. It should "only" be a matter of coding things up in guest driver and virglrenderer. And add blob resource support to qemu of course.
Another feature which was added to virtio-gpu which is not on the 2019 list is UUID support. This allows to attach a UUID to a virtio-gpu resource, which is specifically useful for dma-buf sharing between virtio drivers inside the guest. A guest driver importing a virtio-gpu resource can send the UUID to the host device for lookup, so the host devices can easily share the resource too.
virtio-gpu state in qemu
Not much progress here up to qemu 6.0. There are a few changes merged or in the pipeline for the next release (6.1) though.
First, the virtio-gpu device is splitted. It will loose the
virgl=on|off
property. There will be two devices
instead: virtio-vga
and virtio-vga-gl
(same for the other device variants).
This will de-clutter the source code and it will also remove hard
virglrenderer dependency from virtio-gpu. With modular qemu builds
you'll now have two modules: One for the
simple virtio-vga
device, without any external
dependencies, and one for the virtio-vga-gl
device,
which supports virgl and thus depends on the virglrenderer library.
Second, blob resource support for the simple virtio-vga
device is in progress, and it will bring support shared resource
mappings to qemu. This will accelerate the display path due to less
or no copying of pixel data.
You may wonder why this is useful for the non-virgl device. The use case is 3D-rendering using a pci-assigned GPU (or vgpu). In that model the GPU handles only the rendering, virtio-gpu handles the display scanout, and framebuffers are shared between drivers using dma-bufs. If you worked with arm socs before this may sound familiar because they often handle rendering and scanout with separate hardware blocks too. So virt graphics will use the same approach, and userspace (xorg + wayland) luckily is already prepared for it.
modular graphics in qemu
When building qemu with configure --enable-modules
you'll get a modular qemu build, which means some functionality is
build as separate module (aka shared object) which is loaded on
demand. This allows distributions to move some functionality to
separate, optional sub-packages, which is especially useful for
modules which depend on shared libraries. That way you can have a
rather lightweight qemu install by simply not installing the
sub-packages not needed.
Block backend drivers where modularized first, audio backend drivers next. The easy UI code was modularized early on too: curses, gtk and sdl.
Last year we took a big step forward in modularizing qemu graphics. Two features got added to qemu: First support for building devices as modules, and second support for modules depending on other modules. This allowed building pretty much all qemu graphics code with external shared library dependencies modular:
- opengl, egl-headless
- depend on mesa libraries and drivers
- spice-core, spice-app
- depend on libspice-server (plus more indirect deps)
depend on qemu opengl module - qxl device
- depends on libspice-server too
depends on qemu spice-core module - virtio-vga-gl device
- depends on virglrenderer
You can see the results on Fedora 34.
Installing qemu-system-x86-core
on a fresh system
installs 29 packages, summing up to an 18M download and 74M
installed size. Installing qemu-system-x86
(which
pulls in all module sub-packages) on top adds 125 more packages with
45M download size and 145M installed size.
linux kernel drm driver updates
As already mentioned above the virtio drm driver got support for blob resources. Also a collection of bugfixes all over the place.
The ttm (drm memory manager) got a bunch of cleanups over the last few upstream kernel releases. A bunch of sanity checks have been added along the way, and they flagged a number of issues in the qxl drm driver (which uses ttm to manage video memory). That in turn caused a bunch of bugfixes and some other improvements in the qxl drm driver. Merged upstream for linux 5.13, most important fixes have been backported to 5.10+ stable branches.