ref:main

Phase 1 follow-ups: full-motion latency, remaining review findings, manual checks #12

open Opened by cole.christensen@gmail.com

Follow-ups found while testing phase-1 (PR #2) against a real desktop guest, real libvirt and systemd, and in a code review. Details and numbers are in JOURNAL.md (2026-09-13).

Performance (REQ-NFR-001)

  • Full-motion video misses the latency target. A 1080p guest playing full-screen video measures p95 22 ms (target ≤ 12 ms; the pattern guest does 4-5 ms). Every frame is fully damaged:

    • the frame store copies the shared map into its buffer (listener thread)
    • capture copies that buffer into the image (capture thread)
    • the image is uploaded to CUDA

    Remove one copy by copying from the map straight into the pipeline image at capture time, and keep the frame-store lock out of the full-frame memcpy so QEMU’s listener calls don’t wait.

  • 4K full-motion is ~22 fps, limited before the encoder. It’s the same at a 1080p stream and with software encoding. The guest’s vCPUs are busy in virtio-gpu 2D transfers, while Sunshine’s threads use ≤ 35% of a core. The GL/DMABUF path (#3) is the real fix; add a 4K desktop run to its verification.

  • Latency for an idle or typing desktop isn’t measured. The idle runs produced 1-2 samples. Add a workload to tests/e2e/qemu/desktop/desktop_stream.sh that makes small, frequent damage (typing into a terminal, cursor moves) and record p50/p95.

Robustness (review findings, minor)

  • Console input proxies are created with blocking *_proxy_new_sync on the input thread (session.cpp, console_input_impl_t::start). Events for the previous console queue behind them; use the async variants.
  • The input call queue is unbounded when QEMU stops reading but keeps its socket open (SIGSTOP or a debugger). Cap it and merge motion; never drop key or button releases.
  • A guest volume change made while no client is streaming is never seen (QEMU doesn’t replay SetVolume), so the next session uses the cached value.
  • libvirt_open_display (virConnectOpen) has no timeout of its own, though it no longer holds the shared_session lock.

Manual checks still needed (need a person or other hardware)

  • A real Moonlight client (#4, #5): tests/e2e/qemu/desktop/serve_desktop.sh serves the desktop VM with persistent pairing.
    • On WSL2 other devices can’t reach it without networkingMode=mirrored or port forwards; the script prints both.
  • The virt-manager click-through (#6). The hook, units and p2p display are verified on real libvirt 10.0 and systemd 255 without the GUI.
  • DMABUF, VAAPI and the GPU unit tests on native Linux with /dev/dri (#3).
colechristensen cole.christensen@gmail.com commented 2026-09-16 06:11

The rig for the real Moonlight client test is up on DESKTOP-12GQBKK (2026-09-16), so the check only needs a person with a Moonlight client now.

  • tests/e2e/qemu/desktop/serve_desktop.sh runs detached with the release NVENC build of phase-1 (ee6140d2) and QEMU 11.1: host 192.168.1.102, port 47989, web UI on 47990.
  • WSL2 is in mirrored networking, so the address is on the LAN. mDNS discovery won’t work here (no Avahi daemon on the host, and adb holds 5353), so the host has to be added by IP.
  • The VM has virtio-tablet-pci and virtio-keyboard-pci but no multi-touch device, so a touch client should exercise the new mouse fallback.
  • The guest desktop has a test kit in ~/Desktop: video + 440 Hz tone, stop, an input event viewer (evtest on every device), and a terminal for typing.
  • Verified through the headless client before handing over: 302 frames with motion on every frame, audio 439.999 Hz on both channels, 923 packets, none lost; p50 13 ms, p95 20.9 ms (the known full-motion gap). Pairing persists across restarts of the server.