Skip to content

Instantly share code, notes, and snippets.

@peppergrayxyz
Last active March 14, 2026 12:14
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.

@stf-ftw
Copy link

stf-ftw commented Mar 9, 2026

Hi, could anyone with a Nvidia GPU help check if vkcube works with guest mesa 26.0 + host Nvidia driver 590.48.1 (or 595.x)? thanks in advance!

Try updating Mesa to 26.0.1. That fixed it for me and now my VMs are no longer crashing (the moment I tried running any vk tool or game the VMs would segfault). Performance however is bad, getting only 80 FPS in Dusk and 5 FPS in Nightmare Reaper.

Host: 5070 Ti, 5950x, 32GB RAM
VM: virtio-gpu-gl-pci blob=true venus=true, 12GB RAM, 8GB VRAM, 16 threads

Mesa bug fixes: "venus crashes in vn_CreateDevice() with latest mesa/main [bisected]"

https://docs.mesa3d.org/relnotes/26.0.1.html

@gddgddg
Copy link

gddgddg commented Mar 9, 2026

I have venus working in the VM to my satisfaction and vkmark is showing roughly 270 fps, but the output as I see it is stuttery and doesn't look quite smooth enough. It's a bit subtle, but it just doesn't look right. Is there something I missed? I'm trying to get Sunshine to use this as a shared VM for light games, but the stuttery output shows up no matter what I do, whether through streaming or in sdl/gtk display. I tested SuperTuxKart and it runs okay, but the stuttering is still present in every application. Here's my config:

#!/bin/sh
qemu-system-x86_64                                                                   \
    -enable-kvm                                                                      \
    -smbios type=0,uefi=on                                                           \
    -M q35,accel=kvm                                                                 \
    -smp 8                                                                           \
    -m 12G                                                                           \
    -cpu host                                                                        \
    -net nic,model=virtio                                                            \
    -net bridge,br=virbr0                                                            \
    -device virtio-gpu-gl,hostmem=16G,blob=true,venus=true                           \
    -vga none                                                                        \
    -display sdl,gl=on,show-cursor=on                                                \
    -object memory-backend-memfd,id=mem1,size=12G                                    \
    -machine memory-backend=mem1                                                     \
    -d guest_errors                                                                  \
    -drive if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/x64/OVMF_CODE.4m.fd \
    -drive if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/x64/OVMF_VARS.4m.fd \
    -hda /home/me/Misc/qemu-images/fedora-games/fedora-games.img              

Edit: I just retried SuperTuxKart and the video is frozen, but the game is running. Using Plasma, when I open the launcher by hitting Super, the game refreshes but stays on a single frame. I managed to run the performance test and it shows around 32 FPS, so something is actually wrong.

I changed SuperTuxKart back to OpenGL and it runs more properly now, but of course it's still stuttery. Framerate according to the performance test is a little worse, around 24-31. vkcube shows my GPU as it should and confirms Virtio-GPU Venus. I believe the desktop is entirely running at around 30 FPS for some reason, but I'm not sure why. I have a 9060 XT.

To clarify, I think the reason for the stuttery output is because it's actually showing around 30 fps for some reason, despite my somewhat nicer GPU and a 24-thread CPU. That's why I'm saying it's kind of subtle, because it's actually running at an unsteady 30 fps. At least I think that's what's happening, but I'm not sure how to check what framerate the VM is displaying.

I should also mention that I'm on an Arch host and Fedora guest, both fully updated.

Another edit: I made some progress on this. I changed -display sdl,gl=on,show-cursor=on to -display egl-headless,gl=on, and I only log in using Moonlight (client for Sunshine streaming server). It displays at the proper FPS now, though there's still significant stuttering. I believe this is due to the software encoding, so my next step will be to build QEMU with native context and try again.

However, there's an issue with artifacting in Vulkan applications running in full screen. I'm not sure if this is a problem with virgl/venus or if it's the streaming. I've attached an example below:

2026-03-09.19-34-50.mp4

This also seems to be related to SuperTuxKart's video being frozen while Vulkan is enabled. It seems Vulkan is unstable, but I'm not sure what to do about it.

Edit: I attempted to use native context, but I ran into some problems. Although I built it and it appears to be running, the result of vainfo shows that no hardware encoding is present. What I did:

  • Built qemu-git from AUR with modified pkgbuild as above
  • Tried to run the VM with -device virtio-gpu-gl,hostmem=16G,blob=on,drm_native_context=on, but received error DRM native context support was not enabled in virglrenderer
  • Built virglrenderer-git from AUR, changing the build line to include -Ddrm-renderers=amdgpu-experimental.

When I started the VM, I got the following error:

context 30 failed to dispatch CREATE_VIDEO_BUFFER: 22
vrend_decode_ctx_submit_cmd: context error reported 30 "sunshine" Illegal command buffer 393271

How do I build virglrenderer to support hardware encoding on the GPU? Or what have I missed? Something with mesa on the guest?

@zzyiwei
Copy link

zzyiwei commented Mar 9, 2026

Thanks for verifying it working! Do you mind sharing your guest os env? the desktop env and the compositor used

For performance on QEMU, I can't tell for sure before seeing a perfetto system trace, but this big effort finally lands: https://lore.kernel.org/all/20260306195048.2869788-1-alex.bennee@linaro.org/

The thing has a great impact on perf is the last commit there support mapping hostmem blobs with map_fixed. If you are interested in the background, here it is:

Local build ToT QEMU + virglrenderer 1.3 should get that enabled automatically.

@stf-ftw
Copy link

stf-ftw commented Mar 10, 2026

Thanks for verifying it working! Do you mind sharing your guest os env? the desktop env and the compositor used

For performance on QEMU, I can't tell for sure before seeing a perfetto system trace, but this big effort finally lands: https://lore.kernel.org/all/20260306195048.2869788-1-alex.bennee@linaro.org/

The thing has a great impact on perf is the last commit there support mapping hostmem blobs with map_fixed. If you are interested in the background, here it is:

Local build ToT QEMU + virglrenderer 1.3 should get that enabled automatically.

Guest:
Bazzite (I rebased it with Mesa 26.0.1)
GNOME (Wayland)

Host:
Fedora 43
GNOME (Wayland)

@fproverbio
Copy link

fproverbio commented Mar 10, 2026

I have venus working in the VM to my satisfaction and vkmark is showing roughly 270 fps, but the output as I see it is stuttery and doesn't look quite smooth enough. It's a bit subtle, but it just doesn't look right. Is there something I missed? I'm trying to get Sunshine to use this as a shared VM for light games, but the stuttery output shows up no matter what I do, whether through streaming or in sdl/gtk display. I tested SuperTuxKart and it runs okay, but the stuttering is still present in every application. Here's my config:

#!/bin/sh
qemu-system-x86_64                                                                   \
    -enable-kvm                                                                      \
    -smbios type=0,uefi=on                                                           \
    -M q35,accel=kvm                                                                 \
    -smp 8                                                                           \
    -m 12G                                                                           \
    -cpu host                                                                        \
    -net nic,model=virtio                                                            \
    -net bridge,br=virbr0                                                            \
    -device virtio-gpu-gl,hostmem=16G,blob=true,venus=true                           \
    -vga none                                                                        \
    -display sdl,gl=on,show-cursor=on                                                \
    -object memory-backend-memfd,id=mem1,size=12G                                    \
    -machine memory-backend=mem1                                                     \
    -d guest_errors                                                                  \
    -drive if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/x64/OVMF_CODE.4m.fd \
    -drive if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/x64/OVMF_VARS.4m.fd \
    -hda /home/me/Misc/qemu-images/fedora-games/fedora-games.img              

Edit: I just retried SuperTuxKart and the video is frozen, but the game is running. Using Plasma, when I open the launcher by hitting Super, the game refreshes but stays on a single frame. I managed to run the performance test and it shows around 32 FPS, so something is actually wrong.

I changed SuperTuxKart back to OpenGL and it runs more properly now, but of course it's still stuttery. Framerate according to the performance test is a little worse, around 24-31. vkcube shows my GPU as it should and confirms Virtio-GPU Venus. I believe the desktop is entirely running at around 30 FPS for some reason, but I'm not sure why. I have a 9060 XT.

To clarify, I think the reason for the stuttery output is because it's actually showing around 30 fps for some reason, despite my somewhat nicer GPU and a 24-thread CPU. That's why I'm saying it's kind of subtle, because it's actually running at an unsteady 30 fps. At least I think that's what's happening, but I'm not sure how to check what framerate the VM is displaying.

I should also mention that I'm on an Arch host and Fedora guest, both fully updated.

Another edit: I made some progress on this. I changed -display sdl,gl=on,show-cursor=on to -display egl-headless,gl=on, and I only log in using Moonlight (client for Sunshine streaming server). It displays at the proper FPS now, though there's still significant stuttering. I believe this is due to the software encoding, so my next step will be to build QEMU with native context and try again.

However, there's an issue with artifacting in Vulkan applications running in full screen. I'm not sure if this is a problem with virgl/venus or if it's the streaming. I've attached an example below:
2026-03-09.19-34-50.mp4

This also seems to be related to SuperTuxKart's video being frozen while Vulkan is enabled. It seems Vulkan is unstable, but I'm not sure what to do about it.

Edit: I attempted to use native context, but I ran into some problems. Although I built it and it appears to be running, the result of vainfo shows that no hardware encoding is present. What I did:

* Built `qemu-git` from AUR with modified pkgbuild as above

* Tried to run the VM with `-device virtio-gpu-gl,hostmem=16G,blob=on,drm_native_context=on`, but received error `DRM native context support was not enabled in virglrenderer`

* Built `virglrenderer-git` from AUR, changing the build line to include `-Ddrm-renderers=amdgpu-experimental`.

When I started the VM, I got the following error:

context 30 failed to dispatch CREATE_VIDEO_BUFFER: 22
vrend_decode_ctx_submit_cmd: context error reported 30 "sunshine" Illegal command buffer 393271

How do I build virglrenderer to support hardware encoding on the GPU? Or what have I missed? Something with mesa on the guest?

does it change anything if you specify a lower hostmem value, like 4G for example, 16G might be over the limit (i seem to recall being 8G)

also -object memory-backend-memfd,id=mem1,size=12G should be the same value as hostmem or higher IIRC.

this is the command i used:

/run/media/user/SN770/tmp/packages/qemu-git/pkg/qemu-git/usr/bin/qemu-system-x86_64 \
      -enable-kvm \
      -smp 12 \
      -m 8G \
      -M q35 \
      -cpu host \
      -net nic,model=virtio \
      -net user,hostfwd=tcp::2222-:22 \
      -device virtio-sound-pci,audiodev=my_audiodev -audiodev pipewire,id=my_audiodev            \
      -device virtio-gpu-gl-pci,hostmem=4G,blob=true,drm_native_context=on                                      \
      -vga none \
      -display sdl,gl=on,show-cursor=on \
      -usb -device usb-tablet \
      -object memory-backend-memfd,id=mem1,size=8G                                              \
      -machine memory-backend=mem1 \
      -drive if=pflash,format=raw,readonly=on,file=/run/media/user/SN770/tmp/OVMF_CODE.4m.fd   \
      -drive if=pflash,format=raw,file=/run/media/user/SN770/tmp/OVMF_VARS.4m.fd              \
      -drive file=/run/media/user/SN770/tmp/cachyos.qcow2

i'm on a 7800xt so it should be similar

@gddgddg
Copy link

gddgddg commented Mar 10, 2026

Set hostmem and -object size= at 4G and at least in Retroarch the strange flashing visual artifacts on the bottom half of the screen are gone with Vulkan enabled. The video stutters just as much, but I'm still thinking that's the h.264 encoding In the stream and not the VM. Interestingly, my dGPU is no longer shown in use, but I can see my iGPU is being used when I have the VM on, and my CPU core use goes higher when I use vkmark, with the fps now shooting up in the 800-900 range, score coming out out as 2026. This is with drm_native_context=on. Is there a way I can specify my dGPU to be used on it? Either way, it should still have encoding, but it doesn't according to vainfo.

Framerate in SuperTuxKart is another story. Complete slide show with Vulkan on at 4 to 7 fps, though I can say at least that it's actually moving instead of technically running but being frozen. My CPU use also jumps up to around 30% or so. It seems to be running Vulkan partly on the CPU itself and only a little on the iGPU. iGPU is showing spikes, but not steady use.

I should also say that vkcube shows that it's running on the CPU. With Venus on, it showed my dGPU.

Also, I think this might have to do with the guest running Mesa 25, but I admit that I'm not sure how to compile and install Mesa 26.0.1 with the proper flags on Fedora. I'm mostly familiar with Arch. Would the xxmitsu copr repo with mesa-git work? Would I have to modify something?

@fproverbio
Copy link

fproverbio commented Mar 11, 2026

Set hostmem and -object size= at 4G and at least in Retroarch the strange flashing visual artifacts on the bottom half of the screen are gone with Vulkan enabled. The video stutters just as much, but I'm still thinking that's the h.264 encoding In the stream and not the VM. Interestingly, my dGPU is no longer shown in use, but I can see my iGPU is being used when I have the VM on, and my CPU core use goes higher when I use vkmark, with the fps now shooting up in the 800-900 range, score coming out out as 2026. This is with drm_native_context=on. Is there a way I can specify my dGPU to be used on it? Either way, it should still have encoding, but it doesn't according to vainfo.

Framerate in SuperTuxKart is another story. Complete slide show with Vulkan on at 4 to 7 fps, though I can say at least that it's actually moving instead of technically running but being frozen. My CPU use also jumps up to around 30% or so. It seems to be running Vulkan partly on the CPU itself and only a little on the iGPU. iGPU is showing spikes, but not steady use.

I should also say that vkcube shows that it's running on the CPU. With Venus on, it showed my dGPU.

Also, I think this might have to do with the guest running Mesa 25, but I admit that I'm not sure how to compile and install Mesa 26.0.1 with the proper flags on Fedora. I'm mostly familiar with Arch. Would the xxmitsu copr repo with mesa-git work? Would I have to modify something?

unfortunately i only have the rx7800xt on my system, but vainfo does show hardware encoding/decodig capabilities so something is definitely wrong. Maybe check if the patchset has documentation on how to select the device passed.

on amdgpu guests should have at least mesa 25 and linux 6.14, so your mesa version should be ok. Can you try with a different guest distro? maybe arch or cachy? also if you are using native context remove venus=true

@gddgddg
Copy link

gddgddg commented Mar 11, 2026

That's strange, Fedora 43 is on Linux 6.18 and Mesa 25. I did remove venus=true. I'm going to try the copr repo first with mesa-git to see if maybe it has the right build flag enabled, because I'm starting to think that's the problem. If it doesn't work I'll try Cachy.

I will note that 3D games in Retroarch are working without any problems, so I don't know why SuperTuxKart was so slow. I ran both with Vulkan enabled.

Here's my current script to run the VM in case I missed something obvious:

#!/bin/sh

qemu-system-x86_64                                                                    \
    -enable-kvm                                                                       \
    -smbios type=0,uefi=on                                                            \
    -M q35,accel=kvm                                                                  \
    -smp 8                                                                            \
    -m 12G                                                                            \
    -cpu host                                                                         \
    -net nic,model=virtio                                                             \
    -net bridge,br=virbr0                                                             \
    -device virtio-gpu-gl,hostmem=8G,blob=on,drm_native_context=on                    \
    -vga none                                                                         \
    -display egl-headless,gl=on                                                       \
    -object memory-backend-memfd,id=mem1,size=12G                                     \
    -machine memory-backend=mem1                                                      \
    -d guest_errors                                                                   \
    -drive if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/x64/OVMF_CODE.4m.fd  \
    -drive if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/x64/OVMF_VARS.4m.fd  \
    -virtfs local,path=/mnt/games,mount_tag=host0,security_model=passthrough,id=host0 \
    -hda ./fedora-games.img              

I tested hostmem at 4 and 8 and they both seem to work about the same way. I thought 8G was a typical number, but not a limit.

Edit: xxmitsu mesa-git copr repo didn't work. I'm installing a Cachy VM now

Edit 2: Cachy seems to be worse. I installed mesa-git and lib32-mesa-git on the guest and vkcube and vkgears run, but even with venus=on it doesn't detect my GPU anymore and just runs on the CPU. In Fedora Venus will allow it to see my GPU. I feel like I've forgotten to install something in the guest and I should have written some notes down from before. Anything I might have missed?

Some further testing: Cachy actually seems to have nearly eliminated video stuttering, so I guess this is what I'll stick with, especially if I can get drm_native_context to see my GPU and allow me to hardware encode video.

@fproverbio
Copy link

fproverbio commented Mar 11, 2026

That's strange, Fedora 43 is on Linux 6.18 and Mesa 25. I did remove venus=true. I'm going to try the copr repo first with mesa-git to see if maybe it has the right build flag enabled, because I'm starting to think that's the problem. If it doesn't work I'll try Cachy.

I will note that 3D games in Retroarch are working without any problems, so I don't know why SuperTuxKart was so slow. I ran both with Vulkan enabled.

Here's my current script to run the VM in case I missed something obvious:

#!/bin/sh

qemu-system-x86_64                                                                    \
    -enable-kvm                                                                       \
    -smbios type=0,uefi=on                                                            \
    -M q35,accel=kvm                                                                  \
    -smp 8                                                                            \
    -m 12G                                                                            \
    -cpu host                                                                         \
    -net nic,model=virtio                                                             \
    -net bridge,br=virbr0                                                             \
    -device virtio-gpu-gl,hostmem=8G,blob=on,drm_native_context=on                    \
    -vga none                                                                         \
    -display egl-headless,gl=on                                                       \
    -object memory-backend-memfd,id=mem1,size=12G                                     \
    -machine memory-backend=mem1                                                      \
    -d guest_errors                                                                   \
    -drive if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/x64/OVMF_CODE.4m.fd  \
    -drive if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/x64/OVMF_VARS.4m.fd  \
    -virtfs local,path=/mnt/games,mount_tag=host0,security_model=passthrough,id=host0 \
    -hda ./fedora-games.img              

I tested hostmem at 4 and 8 and they both seem to work about the same way. I thought 8G was a typical number, but not a limit.

Edit: xxmitsu mesa-git copr repo didn't work. I'm installing a Cachy VM now

Edit 2: Cachy seems to be worse. I installed mesa-git and lib32-mesa-git on the guest and vkcube and vkgears run, but even with venus=on it doesn't detect my GPU anymore and just runs on the CPU. In Fedora Venus will allow it to see my GPU. I feel like I've forgotten to install something in the guest and I should have written some notes down from before. Anything I might have missed?

Some further testing: Cachy actually seems to have nearly eliminated video stuttering, so I guess this is what I'll stick with, especially if I can get drm_native_context to see my GPU and allow me to hardware encode video.

the only difference that i see is blob=true and -display sdl,gl=on on mine, the rest is pretty much identical. To summarize:

on the host you have:

  • qemu built with the patches applied
  • virglrenderer-git
  • mesa 26?

that part should be fine, in the guest i only had to install mesa-git to get it to work, let me check in the vm if i did anything else.

EDIT: i did modify mesa-git from cachyos adding the -Damdgpu-virtio=true.
To replicate in the guest if cachy, git clone https://github.com/CachyOS/CachyOS-PKGBUILDS then cd CachyOS-PKGBUILDS/mesa/mesa-git and edit the PKGBUILD like so:
(should start at line 530)

arch-meson $_mesa_srcdir _build64 \
       --wrap-mode=nofallback \
       --force-fallback-for=syn,paste,rustc-hash \
       -D b_ndebug=true \
       -D platforms=${_platforms} \
       -D amdgpu-virtio=true \
       -D gallium-drivers=${_gallium_drivers} \
       -D vulkan-drivers=${_vulkan_drivers} \
       -D egl=${_enabled_} \
       -D gallium-extra-hud=true \
       -D gallium-rusticl=${_rusticl} \
       -D gallium-va=${_gallium_va} \
       -D gbm=${_enabled_} \
       -D gles1=${_disabled_} \
       -D gles2=${_enabled_} \
       -D glvnd=${_enabled_} \
       -D glx=dri \
       -D libunwind=${_enabled_} \
       -D llvm=${_enabled_} \
       -D lmsensors=${_enabled_} \
       -D opengl=true \
       -D zstd=auto \
       -D valgrind=${_enabled_} $_legacy_switches $_dri3 $_omx $_dri_inc $_microsoft_clc $_osmesa $_xvmc $_layers $_optional_codecs $_android_libbacktrace $_intel_rt $_galliumnine $_galliumxa $_sharedglapi $_galliumopencl $_gallium_vdpau $_mediafoundation $_rusticladditions $_lto $_additional_meson_flags $_additional_meson_flags_64

    meson configure _build64 --no-pager

then build with makepkg -scCLi --skipinteg and let me know.

@fproverbio
Copy link

also check with render devices you have in the vm after that and verify if video accel is working (maybe it's defaulting to lavapipe for vulkan-video):

vainfo --display drm --device /dev/dri/YOUR-DGPU

@gddgddg
Copy link

gddgddg commented Mar 11, 2026

That mostly did it, but there's a new problem now. vainfo shows my GPU and all the encoding options, but Sunshine segfaults and the entire VM crashes when I try to connect. I changed to -display sdl and I can see that programs are running at 60 fps now. SuperTuxKart runs at 60 fps most of the time with Vulkan enabled.

This is a huge change, but the problem now is that programs are very slow to start and Sunshine crashes when attempting to connect. That being said, once a program running on Vulkan does start, it's perfectly smooth, at least in the SDL viewer. But my goal was to share this using Sunshine/Moonlight. It might be out of scope for this discussion, but it seems like Sunshine isn't seeing my GPU while everything else is. Additionally, programs starting very slowly and then running somewhat normally once they do get running is strange, but I don't know how to begin to address that.

vulkaninfo --summary detects two GPUs, GPU0 being my 9060 XT and GPU1 being llvmpipe. I wonder now if this is causing a conflict and if there's a way to force only the 9060 XT to be used. btop and nvtop don't detect any GPUs, but that might be a quirk of the way the GPU is being used by the VM.

After doing some quick observation, I believe the reason why some programs are so slow to start is because they're engaging the GPU, and Plasma has some effects applied that are using it as well. I don't know if there's any fix for that I can try at this point, and it seems to speed up a bit as I use the VM more.

@fproverbio
Copy link

fproverbio commented Mar 11, 2026

That mostly did it, but there's a new problem now. vainfo shows my GPU and all the encoding options, but Sunshine segfaults and the entire VM crashes when I try to connect. I changed to -display sdl and I can see that programs are running at 60 fps now. SuperTuxKart runs at 60 fps most of the time with Vulkan enabled.

This is a huge change, but the problem now is that programs are very slow to start and Sunshine crashes when attempting to connect. That being said, once a program running on Vulkan does start, it's perfectly smooth, at least in the SDL viewer. But my goal was to share this using Sunshine/Moonlight. It might be out of scope for this discussion, but it seems like Sunshine isn't seeing my GPU while everything else is. Additionally, programs starting very slowly and then running somewhat normally once they do get running is strange, but I don't know how to begin to address that.

vulkaninfo --summary detects two GPUs, GPU0 being my 9060 XT and GPU1 being llvmpipe. I wonder now if this is causing a conflict and if there's a way to force only the 9060 XT to be used. btop and nvtop don't detect any GPUs, but that might be a quirk of the way the GPU is being used by the VM.

good progress! may i ask which DE/window manager are you using? i only tested wayland (niri) and sddm as login manager, it may have problems with X11 or other DEs. High cpu usage and slow to load programs may be due to it using llvmpipe (which i also have as secondary gpu).

unfortunately i never got to test sunshine as i'm using usermode networking instead of a bridge, i could pass the ports via qemu and test, maybe it segfaults for me as well.

Does playing a youtube video with mpv and vaapi enabled work? what if you use RADV_PERFTEST=video_decode mpv ...?

@gddgddg
Copy link

gddgddg commented Mar 11, 2026

Sorry, I edited my post above. I'm using Plasma with Wayland. Sunshine is using card0 even when I set the adapter in its settings to /dev/dri/renderD128. The mpv test worked, but it stutters a bit during the video playback.

I should also note that it's not using the CPU very much at all now, even when programs are loading.

Edit: I just had a thought, which might also have to do with the reason why programs are loading slowly. I don't know if this is correct, but I think when Sunshine starts, it uses the GPU that the display is on. The virtual display in this case is on the virtio GPU (I don't know how to confirm this at the moment, just guessing). So when a program is starting slowly, it might be because it's starting on the virtio GPU and then offloading to the dGPU. If I could start a virtual display on the dGPU in the VM, Sunshine might use that instead of virtio and it might help with slow startup. I just don't know if it's even possible.

@fproverbio
Copy link

That mostly did it, but there's a new problem now. vainfo shows my GPU and all the encoding options, but Sunshine segfaults and the entire VM crashes when I try to connect. I changed to -display sdl and I can see that programs are running at 60 fps now. SuperTuxKart runs at 60 fps most of the time with Vulkan enabled.
This is a huge change, but the problem now is that programs are very slow to start and Sunshine crashes when attempting to connect. That being said, once a program running on Vulkan does start, it's perfectly smooth, at least in the SDL viewer. But my goal was to share this using Sunshine/Moonlight. It might be out of scope for this discussion, but it seems like Sunshine isn't seeing my GPU while everything else is. Additionally, programs starting very slowly and then running somewhat normally once they do get running is strange, but I don't know how to begin to address that.
vulkaninfo --summary detects two GPUs, GPU0 being my 9060 XT and GPU1 being llvmpipe. I wonder now if this is causing a conflict and if there's a way to force only the 9060 XT to be used. btop and nvtop don't detect any GPUs, but that might be a quirk of the way the GPU is being used by the VM.

good progress! may i ask which DE/window manager are you using? i only tested wayland (niri) and sddm as login manager, it may have problems with X11 or other DEs. High cpu usage and slow to load programs may be due to it using llvmpipe (which i also have as secondary gpu).

Sorry, I edited my post above. I'm using Plasma with Wayland. Sunshine is using card0 even when I set the adapter in its settings to /dev/dri/renderD128. The mpv test worked, but it stutters a bit during the video playback.

I should also note that it's not using the CPU very much at all now, even when programs are loading.

Edit: I just had a thought, which might also have to do with the reason why programs are loading slowly. I don't know if this is correct, but I think when Sunshine starts, it uses the GPU that the display is on. The virtual display in this case is on the virtio GPU (I don't know how to confirm this at the moment, just guessing). So when a program is starting slowly, it might be because it's starting on the virtio GPU and then offloading to the dGPU. If I could start a virtual display on the dGPU in the VM, Sunshine might use that instead of virtio and it might help with slow startup. I just don't know if it's even possible.

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?

@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.

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