Skip to content

Instantly share code, notes, and snippets.

@peppergrayxyz
Last active March 16, 2026 17:03
Show Gist options
  • Select an option

  • Save peppergrayxyz/fdc9042760273d137dddd3e97034385f to your computer and use it in GitHub Desktop.

Select an option

Save peppergrayxyz/fdc9042760273d137dddd3e97034385f to your computer and use it in GitHub Desktop.
QEMU with VirtIO GPU Vulkan Support

QEMU with VirtIO GPU Vulkan Support

With its latest reales qemu added the Venus patches so that virtio-gpu now support venus encapsulation for vulkan. This is one more piece to the puzzle towards full Vulkan support.

An outdated blog post on clollabora described in 2021 how to enable 3D acceleration of Vulkan applications in QEMU through the Venus experimental Vulkan driver for VirtIO-GPU with a local development environment. Following up on the outdated write up, this is how its done today.

Definitions

Let's start with the brief description of the projects mentioned in the post & extend them:

  • QEMU is a machine emulator
  • VirGL is an OpenGL driver for VirtIO-GPU, available in Mesa.
  • Venus is an experimental Vulkan driver for VirtIO-GPU, also available in Mesa.
  • Virglrenderer is a library that enables hardware acceleration to VM guests, effectively translating commands from the two drivers just mentioned to either OpenGL or Vulkan.
  • libvirt is an API for managing platform virtualization
  • virt-manager is a desktop user interface for managing virtual machines through libvirt

Merged Patches:

Work in progress:

Prerequisites

Make sure you have the proper version installed on the host:

  • linux kernel >= 6.13 built with CONFIG_UDMABUF
  • working Vulkan and kvm setup
  • qemu >= 9.2.0
  • virglrenderer with enabled venus support
  • mesa >= 24.2.0

You can verify this like so:

$ uname -r
6.13.0
$ ls /dev/udmabuf
/dev/udmabuf
$ ls /dev/kvm
/dev/kvm
$ qemu-system-x86_64 --version
QEMU emulator version 9.2.0
Copyright (c) 2003-2024 Fabrice Bellard and the QEMU Project developers

Check your distros package sources how they build virglrenderer.

For Vulkan to work you need the proper drivers to be installed for your graphics card.

To verfiy your setup, install vulkan-tools. Make sure mesa >= 24.2.0 and test vkcube:

$ vulkaninfo --summary | grep driverInfo
	driverInfo         = Mesa 24.2.3-1ubuntu1
	driverInfo         = Mesa 24.2.3-1ubuntu1 (LLVM 19.1.0)
...
$ vkcube
Selected GPU x: ..., type: ...

Building qemu

If your distro doesn't (yet) ship and updated version of qemu, you can build it yourself from source:

wget https://download.qemu.org/qemu-9.2.0.tar.xz
tar xvJf qemu-9.2.0.tar.xz
cd qemu-9.2.0
mkdir build && cd build
../configure --target-list=x86_64-softmmu  \
  --enable-kvm                 \
  --enable-opengl              \
  --enable-virglrenderer       \
  --enable-gtk                 \
  --enable-sdl
make -j4

The configuration step will throgh errors if packages are missing. Check the qemu wiki for further info what to install: https://wiki.qemu.org/Hosts/Linux

Create and run an image for QEMU

Create an image & fetch the distro of your choice:

Host

ISO=ubuntu-24.10-desktop-amd64.iso  
wget https://releases.ubuntu.com/oracular/ubuntu-24.10-desktop-amd64.iso  

IMG=ubuntu-24-10.qcow2
qemu-img create -f qcow2 $IMG 16G

Run a live version or install the distro

qemu-system-x86_64                                               \
    -enable-kvm                                                  \
    -M q35                                                       \
    -smp 4                                                       \
    -m 4G                                                        \
    -cpu host                                                    \
    -net nic,model=virtio                                        \
    -net user,hostfwd=tcp::2222-:22                              \
    -device virtio-vga-gl,hostmem=4G,blob=true,venus=true        \
    -vga none                                                    \
    -display gtk,gl=on,show-cursor=on                            \
    -usb -device usb-tablet                                      \
    -object memory-backend-memfd,id=mem1,size=4G                 \
    -machine memory-backend=mem1                                 \
    -hda $IMG                                                    \
    -cdrom $ISO                                                  

Adjust the parameters accordingly:

  • smp: number of cpu cores
  • m: RAM
  • hostmem,size: VRAM

Guest

Install mesa-utilites and vulkan-tools to test the setup:

$ glxinfo -B
$ vkcube
Selected GPU x: ..., type: ...

If the deive is llvmpipe somehting is wrong. The device should be virgl (...).

Troubleshooting

  • (host) add -d guest_errors to show error messages from the guest
  • (guest) try installing vulkan virtio drivers and mesa
  • check the original blog post

Ubuntu 24.10

This is how you do it on Ubuntu

kernel

Install mainline: https://github.com/bkw777/mainline

sudo add-apt-repository ppa:cappelikan/ppa
sudo apt update
sudo apt install mainline

find the latest kernel (>= 6.13), at the time of writing 6.13 is a release candidate, so include those:

$ mainline check --include-rc

Install kernel:

$ sudo mainline install 6.13-rc1

Verfify installed kernels:

$ mainline list-installed
mainline 1.4.10
Installed Kernels:
linux-image-6.11.0-13-generic
linux-image-generic-hwe-24.04
linux-image-unsigned-6.13.0-061300rc1-generic
mainline: done

reboot into new kernel

verify running kernel

$ uname -r
6.13.0-061300rc1-generic

virglrenderer

the ubuntu package is not compiled with the proper flags.

If installed remove it: $ sudo apt-get remove libvirglrenderer-dev

download, build & install from source with venus enabled

wget    https://gitlab.freedesktop.org/virgl/virglrenderer/-/archive/1.1.0/virglrenderer-1.1.0.tar.gz
sudo apt-get install python3-full ninja-build libvulkan-dev libva-dev
python3 -m venv venv
venv/bin/pip install meson
venv/bin/meson build -Dvideo=true -Dvenus=true
ninja -C build
ninja install

qemu

install qemu >= 9.2.0, at the time of writing ubuntu has not yet packaged it

Install build depdencies: https://wiki.qemu.org/Hosts/Linux

sudo apt-get install build-essential pip libslirp-dev slirp
sudo apt-get install git libglib2.0-dev libfdt-dev libpixman-1-dev zlib1g-dev ninja-build
sudo apt-get install git-email
sudo apt-get install libaio-dev libbluetooth-dev libcapstone-dev libbrlapi-dev libbz2-dev
sudo apt-get install libcap-ng-dev libcurl4-gnutls-dev libgtk-3-dev
sudo apt-get install libibverbs-dev libjpeg8-dev libncurses5-dev libnuma-dev
sudo apt-get install librbd-dev librdmacm-dev
sudo apt-get install libsasl2-dev libsdl2-dev libseccomp-dev libsnappy-dev libssh-dev
sudo apt-get install libvde-dev libvdeplug-dev libvte-2.91-dev libxen-dev liblzo2-dev
sudo apt-get install valgrind xfslibs-dev 
sudo apt-get install libnfs-dev libiscsi-dev

build and run as described

virt-manager

-- work in progress --

Currently this is work in progress, so there is no option to add vulkan support in virt-manager. There are no fields to configure this. Also xml doesnt work, because libvirt doesn't know about these options either, so xml validation fails. There is however an option for QEMU command-line passthrough which bypasses the validation.

If you setup a default machine with 4G of memory, you can do this:

  <qemu:commandline>
    <qemu:arg value="-device"/>
    <qemu:arg value="virtio-vga-gl,hostmem=4G,blob=true,venus=true"/>
    <qemu:arg value="-object"/>
    <qemu:arg value="memory-backend-memfd,id=mem1,size=4G"/>
    <qemu:arg value="-machine"/>
    <qemu:arg value="memory-backend=mem1"/>
    <qemu:arg value="-vga"/>
    <qemu:arg value="none"/>
  </qemu:commandline>

Which gives this error:

qemu-system-x86_64: virgl could not be initialized: -1

Changing the number from 4G to 4194304k (same as memory) leds to this error:

qemu-system-x86_64: Spice: ../spice-0.15.2/server/red-qxl.cpp:435:spice_qxl_gl_scanout: condition `qxl_state->gl_draw_cookie == GL_DRAW_COOKIE_INVALID' failed

to be further investigated.

@the-burrito-triangle
Copy link

Have you tried using Mesa environment variables to force a specific GPU?

Use MESA_VK_DEVICE_SELECT=list vulkaninfo to get the PCI vendor and device IDs

$ MESA_VK_DEVICE_SELECT=list vulkaninfo
  GPU 0: 1002:7480 "AMD Radeon RX 7600 (RADV NAVI33)" discrete GPU 0000:03:00.0
  GPU 1: 8086:4c8a "Intel(R) Graphics (RKL GT1)" integrated GPU 0000:00:02.0
  GPU 2: 10005:0 "llvmpipe (LLVM 21.1.8, 256 bits)" CPU 0000:00:00.0

Then launch sunshine with either DRI_PRIME=1! (works for OpenGL and Vulkan don't forget the !), DRI_PRIME=<vendor_id>:<device_id> or MESA_VK_DEVICE_SELECT=<vendor_id>:<device_id>. Sometimes you might need to use MESA_VK_DEVICE_SELECT_FORCE_DEFAULT_DEVICE=1 if you wanted to force the iGPU when a Vulkan app requests a dGPU.

@gddgddg
Copy link

gddgddg commented Mar 13, 2026

Isn't it possible to make sunshine use a specific card? i remember starting it and it picking up the hardware encoder right away for h264,h265 and AV1. I think something weird is going on with KDE potentially, would you mind testing something else?

I might install and try niri, that's what I use mainly.

Have you tried using Mesa environment variables to force a specific GPU?

Use MESA_VK_DEVICE_SELECT=list vulkaninfo to get the PCI vendor and device IDs

$ MESA_VK_DEVICE_SELECT=list vulkaninfo
  GPU 0: 1002:7480 "AMD Radeon RX 7600 (RADV NAVI33)" discrete GPU 0000:03:00.0
  GPU 1: 8086:4c8a "Intel(R) Graphics (RKL GT1)" integrated GPU 0000:00:02.0
  GPU 2: 10005:0 "llvmpipe (LLVM 21.1.8, 256 bits)" CPU 0000:00:00.0

Then launch sunshine with either DRI_PRIME=1! (works for OpenGL and Vulkan don't forget the !), DRI_PRIME=<vendor_id>:<device_id> or MESA_VK_DEVICE_SELECT=<vendor_id>:<device_id>. Sometimes you might need to use MESA_VK_DEVICE_SELECT_FORCE_DEFAULT_DEVICE=1 if you wanted to force the iGPU when a Vulkan app requests a dGPU.

I tried all three options and Sunshine still starts with software encoding while using DRM native context. It does see my 9060 XT according to the log, but it's defaulting to software encoding on card0 no matter what I do. From what I read, Sunshine only uses the encoding of the card that the screen is connected to, which in this case seems to be the virtio GPU and not my dGPU. If I can somehow make the virtual screen run on my dGPU then I think that would fix the Sunshine issue, but like I said before, I don't know if that's even possible.

By the way, I want to thank everyone for the help and support so far. I'm going to try co-op streaming with the software encoding anyway, but I would like to get hardware encoding working too.

@the-burrito-triangle
Copy link

You could try compiling mesa for the guest OS without VirGL, Venus and llvmpipe support, that should force RadeonSI or RADV driver to be used via vDRM (I could be wrong here, fproverbio would likely know since he got vDRM working). If your 9060 XT is being ran headless, there are dongles that make the GPU think there is a display connected to it. Something to consider at least. I know people using Looking Glass have had good luck with that method when passing an AMD GPU to a Windows guest.

@gddgddg
Copy link

gddgddg commented Mar 13, 2026

What I wanted to do originally was have an isolated environment to use as a kind of shared PC that I and some other people could connect to to play games or watch videos together casually. Fully disconnecting and passing through my GPU to the VM would be a bit too much of a pain and not worth it if that's what it takes. Software rendering is just a little hard on the CPU, but I'll do some testing this weekend to see how it goes for me personally with one or two others connected.

Also, I set the environment variable KWIN_DRM_DEVICES=/dev/dri/renderD128 and rebooted and got a black screen in the SDL viewer. Moonlight showed the Sunshine server was available, but the connection was refused and I received this error from the VM in QEMU's output:

drm: amdgpu_get_object_from_res_id:203: [2|sunshine]: Couldn't find res_id: 2 [amdgpu_ccmd_bo_query_info]
drm: amdgpu_ccmd_bo_query_info:701: [2|sunshine]: Cannot find object

I'm not sure what res_id is. I wasn't able to do anything on my VM at all at this point, and I thought I had ruined it (should learn to take snapshots) but I realized I could boot into the install media and change the environment variable by mounting the partition and editing /etc/environment from there.

@the-burrito-triangle
Copy link

You can always just mount the VM image file and edit things from the host OS. One can also pass a whole drive (NVMe, SATA controller, etc.) or give write access to a block device (sdx, vs. sdxy which is a partition). These options let you work with physical storage rather than image files stored on a host partition.

@the-burrito-triangle
Copy link

Thinking about this some more. Its possible that you can just use another "seat" for the sunshine stuff or run it as a background service. This would have massively lower overhead than a VM. I think you use [ctrl]+[alt]+[Fn] to switch to a separate tty and run it from there? I haven't played too much with this sort of thing, but there are options that do not involve a VM that should do this in a satisfactory way.

@gddgddg
Copy link

gddgddg commented Mar 13, 2026

My reason is I wanted it to be separate from my running system with no access to the main filesystem. But yes, there's probably a different way that I'm not thinking of, I just didn't necessarily want to go there because it's so off topic. The problem with Sunshine is that it's not headless, so it specifically wants to stream a display that is turned on.

Despite all that, I wanted to learn about QEMU and this newer tech, so I'm pretty happy with all that too.

@wildxxxx
Copy link

@the-burrito-triangle QEMU freezes when running Venus
When trying to enable venus in qemu, the qemu process completely freezes when trying to boot into the guest OS.

I did everything according to this guide

system information:

GPU: Nvidia GeForce RTX 3050
Driver: 580.126.09

$ uname -r
6.18.12+deb13-amd64
$ ls /dev/udmabuf
/dev/udmabuf
$ ls /dev/kvm
/dev/kvm
$ qemu-system-x86_64 --version
QEMU emulator version 10.0.7 (Debian 1:10.0.7+ds-0+deb13u1+b1)
Copyright (c) 2003-2025 Fabrice Bellard and the QEMU Project developers

I installed qemu through the package manager.
apt install qemu-kvm

launch arguments

qemu-system-x86_64                                               \
    -enable-kvm                                                  \
    -M q35                                                       \
    -smp 4                                                       \
    -m 4G                                                        \
    -cpu host                                                    \
    -net nic,model=virtio                                        \
    -net user,hostfwd=tcp::2222-:22                              \
    -device virtio-vga-gl,hostmem=4G,blob=true,venus=true        \
    -vga none                                                    \
    -display sdl,gl=on,show-cursor=on                            \
    -usb -device usb-tablet                                      \
    -object memory-backend-memfd,id=mem1,size=4G                 \
    -machine memory-backend=mem1                                 \
    -hda $IMG                                                    \
    -cdrom $ISO

During freeze, I get this error output from qemu:

XIO:  fatal IO error 11 (Resource temporarily unavailable) on X server ":1"
     after 2023 requests (2023 known processed) with 0 events remaining.
[xcb] Unknown sequence number while processing queue
[xcb] You called XInitThreads, this is not your fault
[xcb] Aborting, sorry about that.
qemu-system-x86_64: ../../src/xcb_io.c:278: poll_for_event: Assertion `!xcb_xlib_threads_sequence_lost' failed.

I would be glad to help!

@fproverbio
Copy link

You could try compiling mesa for the guest OS without VirGL, Venus and llvmpipe support, that should force RadeonSI or RADV driver to be used via vDRM (I could be wrong here, fproverbio would likely know since he got vDRM working). If your 9060 XT is being ran headless, there are dongles that make the GPU think there is a display connected to it. Something to consider at least. I know people using Looking Glass have had good luck with that method when passing an AMD GPU to a Windows guest.

i actually had both the gpu running amdgpu and llvmpipe, but everything defaulted to the gpu (unigine heaver, supertuxkar, xonotic). I couldn't test sunshine properly due to networking differences, but checking the logs revealed that it found the encoders fine.

@fproverbio
Copy link

My reason is I wanted it to be separate from my running system with no access to the main filesystem. But yes, there's probably a different way that I'm not thinking of, I just didn't necessarily want to go there because it's so off topic. The problem with Sunshine is that it's not headless, so it specifically wants to stream a display that is turned on.

Despite all that, I wanted to learn about QEMU and this newer tech, so I'm pretty happy with all that too.

There is apollo, which is a sunshine fork specifically built to have a virtual display output the game and stream that, but unfortunately at the moment is windows-only. The headless setup is actually the biggest difference between our setups, as i'm running the host window manager on the 7800xt and the guest programs on the same 7800xt, The vm output is just an SDL window on the host. If it's a completely headless system, you could try a headless adapter or hdmi/displayport dummy plug to trick the gpu into thinking that it's displaying to a proper monitor. If you have no password login in the guest you could start the sunshine sessione remotely and enjoy the headless setup (the vm "display" would be outputted to the dummy plug as it's outputted on my display in mine).

@wildxxxx
Copy link

@fproverbio Hi. Can you help me with the freezing caused by venus in qemu?

@fproverbio
Copy link

@fproverbio Hi. Can you help me with the freezing caused by venus in qemu?

I'm not on NVIDIA so i can't reproduce, i assume you are using X11 as the error seems to be related to xcb. What DE/WM are you using? could you test gtk instead of sdl? I know wayland with nvidia can be problematic, but maybe try wayland as well.

@ifaigios
Copy link

@fproverbio Hi. Can you help me with the freezing caused by venus in qemu?

Try building latest qemu from git.

@wildxxxx
Copy link

@fproverbio Hi. Can you help me with the freezing caused by venus in qemu?

Try building latest qemu from git.

A couple of hours ago I was building the latest version (10.2.1) from source. Unfortunately, the problem persists.

@wildxxxx
Copy link

@fproverbio Hi. Can you help me with the freezing caused by venus in qemu?

I'm not on NVIDIA so i can't reproduce, i assume you are using X11 as the error seems to be related to xcb. What DE/WM are you using? could you test gtk instead of sdl? I know wayland with nvidia can be problematic, but maybe try wayland as well.

I've already tried this, but in the case of gtk qemu it also freezes

@ifaigios
Copy link

@fproverbio Hi. Can you help me with the freezing caused by venus in qemu?

Try building latest qemu from git.

A couple of hours ago I was building the latest version (10.2.1) from source. Unfortunately, the problem persists.

I also had some crashes with 10.2.1. Try the git master branch: https://gitlab.com/qemu-project/qemu . Also I suppose you have virglrenderer installed on the host.

@fproverbio
Copy link

@fproverbio Hi. Can you help me with the freezing caused by venus in qemu?

I'm not on NVIDIA so i can't reproduce, i assume you are using X11 as the error seems to be related to xcb. What DE/WM are you using? could you test gtk instead of sdl? I know wayland with nvidia can be problematic, but maybe try wayland as well.

I've already tried this, but in the case of gtk qemu it also freezes

i'm out of ideas to be honest, beside testing it with a different brand gpu (an igpu if your cpu has it). NVIDIA has always be finnicky, especially with bleeding edge features. Hopefully as open source drivers mature it will get better (i'm not counting on it though)

@zzyiwei
Copy link

zzyiwei commented Mar 16, 2026

FYI: a new NV workaround for KWin and wlroots based compositor implementations have landed and will be ported to mesa 26.0.3 release

  • see MR description for details: https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/40339
  • without being impacted by above (e.g. GNOME with Mutter), guest mesa 26.0+ has already switched back to zero-copy hw WSI path
  • if impacted, MESA_VK_WSI_DEBUG=sw should bring it back to 25.x working state. Then 26.0.3 fixes the zero-copy hw WSI path against the impacted compositors.

At this point, all NV specific GPU faults/hangs in various combos should have been mitigated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment