fangorn/sunshine-qemu
public
SteamOS-style guest as a second app (Game Mode, gamepad target) #14
Links
A console-style Linux guest (Steam Game Mode) as a second app, so mode A (#13) has two VMs to switch between and gamepad work (#7) has a real target.
Why
Every guest so far is either the pattern boot sector or an XFCE desktop. A SteamOS-style guest is what this backend is for: a client streams a console-like session, with a gamepad, from a VM.
On this host
No /dev/dri, only /dev/dxg (WSL2), so the guest renders in software (llvmpipe, Vulkan through lavapipe). Game Mode should boot, but games will not be playable. That is fine for what this guest is for here:
- a second app for mode A, to prove switching VMs between streams;
- audio and input through a real session compositor (gamescope) rather than X11;
- later, gamepad input (#7, REQ-INP-004 has no tests).
On a native Linux host with a render node it also becomes a real performance test, together with the DMABUF path (#3).
Tasks
- Pick the image (Bazzite deck is the candidate; ChimeraOS as fallback) and pin the exact URL and checksum.
-
tests/e2e/qemu/steamos/build_steamos.sh: download, verify, install to a qcow2 with OVMF, unattended if the installer allows it. Cache like the desktop guest. -
run_steamos.sh: UEFI, virtio-vga, D-Bus display and audio, virtio-tablet/keyboard, and a gamepad device when #7 lands. - Add it as a second app once mode A can select a VM per app.
- Record what works: Game Mode boots, video, audio, keyboard and mouse; what doesn’t, with numbers.
Done when
A client picks the SteamOS app in Moonlight, streams its Game Mode session, and can switch back to the desktop app in a later stream.
GPU acceleration for this guest, settled with a rebuild rather than a guess (2026-09-16).
QEMU 11.1.1 was built without VirGL (libvirglrenderer-dev missing at configure time; meson disables it silently). Rebuilt with --enable-virglrenderer: VirGL support: YES 1.0.0, and -device help lists virtio-gpu-gl-pci and virtio-vga-gl.
It doesn’t help on the WSL2 host, and QEMU says why:
qemu-system-x86_64: egl: no drm render node available
qemu-system-x86_64: egl: render node init failed
Same with GALLIUM_DRIVER=d3d12 MESA_D3D12_DEFAULT_ADAPTER_NAME=NVIDIA and with EGL_PLATFORM=surfaceless. QEMU enumerates DRM render nodes instead of asking Mesa, so the host’s working D3D12 path is invisible to it — and that path is real: the same environment gives D3D12 (NVIDIA GeForce RTX 4090), Accelerated: yes, against llvmpipe by default. Host Vulkan is software only (lavapipe, no dzn ICD), which is what Proton needs.
What that means for this issue:
- On this host the guest renders in software. Game Mode should boot on lavapipe; expect UI navigation, not gameplay. Still worth building, for mode A app switching (#13), audio, input, and later gamepad (#7).
- On a host with
/dev/drithe same QEMU binary can do VirGL with no further rebuild, and this guest becomes a real performance target alongside the DMABUF work (#3). - Build it from the bootc image rather than the ISO:
ghcr.io/ublue-os/bazzite-deck:stablethroughquay.io/centos-bootc/bootc-image-builder --type qcow2, which needs no installer clicks. The live ISO (bazzite-deck-stable-live-amd64.iso, 8.98 GiB, checksum published) drives Anaconda from aninteractive-defaults.ks, which isn’t an unattended path. ChimeraOS is the fallback if bootc gives trouble: 873 MiB, cloud-init on the live ISO,frzr-bootstrap/frzr-deployare scriptable, installer needs no GPU, but the media is ~19 months old. - Not candidates: HoloISO is archived (its org renamed itself “eol”), and Valve’s recovery image detects virtualization and boots to Desktop Mode instead of Game Mode.