VirGL is a driver that allows creating a virtual GPU within Virtual Machines that leverages host’s GPU without the need for passing it through (VFIO). Currently it’s mature enough to support window managers and maybe some really, really simple quake clones (I tried running Half Life 2… It did not work well). Currently it only supports Linux guests, although there was an experiment to get Windows guests working as well.
Hardware wise you need a GPU with DRM support. Intel iGPUs should work, so should most AMD cards. With nvidia cards you’re probably stuck on using the nouveau driver which is not ideal. Obviously, you also need a system capable of virtualisation.
Sadly the version of QEMU that comes with Ubuntu does not have VirGL support. Because of this, we’ll need to compile it with the necessary support.
sudo apt install build-essential libepoxy-dev libdrm-dev libgbm-dev libx11-dev libvirglrenderer-dev libpulse-dev libsdl2-dev python python-dev libpixman-1-dev build-essential.
wget http://download.qemu-project.org/qemu-2.12.0.tar.xz -O qemu.tar.xz (or whatever the latest version is at the time of reading).
mkdir qemu && tar -xf qemu.tar.xz -C qemu --strip-components=1 && cd qemu.
./configure --enable-sdl --with-sdlabi=2.0 --enable-opengl --enable-virglrenderer --enable-system --enable-modules --audio-drv-list=pa --target-list=x86_64-softmmu --enable-kvm.
After configure finishes it should output all of the features the new QEMU version will support. The ones that interest us are - SDL Support, virgl support, KVM support, OpenGL support, OpenGL dmabufs - all of them should be set to yes.
This will install our newly compiled version to /usr/local. You CAN install it over the distribution’s packages by setting the prefix for configure, but personally I would refrain from doing so if only because you can accidentally mess up your existing virtual machines.
To install Libvirt you have two options - compile it manually or install it from distribution’s repositories. The first option has the added ‘benefit’ of being able to disable Apparmor which will block you from using Libvirt with a custom version of QEMU.
sudo apt-get install git build-essential xsltproc libxml-xpath-perl libyajl-dev libdevmapper-dev libpciaccess-dev libnl-3-dev libnl-route-3-dev systemtap-sdt-dev uuid-dev libtool autoconf pkg-config libxml2 libxml2-utils autopoint python-dev libnuma-dev gettext gnutls-dev libxml2-dev numad librbd-dev build-essential.
wget https://libvirt.org/sources/libvirt-4.5.0.tar.xz -O libvirt.tar.xz (or find the latest version here).
mkdir libvirt && tar xf libvirt.tar.xz -C libvirt --strip-components=1 && cd libvirt.
./configure --with-qemu=yes --with-dtrace --with-numad --with-storage-rbd --disable-nls. If you want to compile without Apparmor support, append --disable-apparmor to the command.
make -j$(nproc) && sudo make install.
This will install Libvirt to /usr/local.
If you compiled Libvirt without Apparmor support you can skip this section. Otherwise, you’ll need to manually add the executables to Apparmor access lists.
You will also need to symlink the required libraries using sudo ln -s /usr/lib/x86_64-linux-gnu/dri /usr/lib/dri because Libvirt (even the one from Ubuntu repositories) will not look into x86_64-linux-gnu by default.
Now the fun part. First create a VM the way you usually would (i.e. using virt-install, using a web GUI like Kimchi etc.) and set it up. What you definitely want to set up is some sort of remote desktop software, like x2go, nomachine, one of the VNC server options (1, 2…), or even something like teamviewer. The reason for this is that enabling virgl will effectively kill QEMU’s SPICE socket - there’s no support for tcp sockets (it simply won’t let you start the VM), and I could not get file sockets to work with virgl enabled (the spice client connects, even shows you the name of the VM you’ve connected to, but there’s no video output).
Under <devices>, change (or add?) the <emulator> used to your new qemu installation, i.e. - <emulator>/usr/local/bin/qemu-system-x86_64</emulator>.
Once done, save, let Libvirt validate it, and if it works, you can just start it. To test whether it works, connect to the VM and check if VirGL was enabled by running dmesg | grep "virgl 3d acceleration enabled". If your dmesg contains this line, you’re good to go.