From 0cae9dc1d9a706614ecdf2fdda4f23bb18fb8af4 Mon Sep 17 00:00:00 2001 From: iris <2+iris@noreply.localhost> Date: Fri, 4 Sep 2026 18:38:47 -0400 Subject: [PATCH] Add EMU_GPU=software, for work where the GPU is not what is measured `-gpu host` runs the guest's GLES on this machine's real GPU, which here is the host's, reached through virtio-gpu. That is right for the Compose scroll benchmarks and was measured -- 25% janky frames against 3%, and 3.9 GB resident against 2.9 GB -- so it stays the default and nothing any other session runs changes. EMU_GPU=software takes the software branch that already existed for the no-compositor case, for work where the emulator's own frame rate is not under test. Two things it buys: no GPU use at all, and a guest Vulkan device (SwiftShader, verified by `cmd gpu vkjson`), which is otherwise unavailable here because gfxstream's opaque-fd external memory cannot pair with Venus. Measured while it booted: qemu at about 490% CPU and a load average of 5, with io pressure at zero. The condition is on the existing branches rather than a fourth one, so there is still one place that says how software rendering is spelled. Co-Authored-By: Claude Opus 5 --- bin/emu | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/bin/emu b/bin/emu index 231e4d3..88ea209 100755 --- a/bin/emu +++ b/bin/emu @@ -49,9 +49,10 @@ usage: emu check refuse if a command that reaches every attached device would reach another checkout's emulator from here -Environment: AVD_NAME overrides the name, EMU_FORCE=1 overrides the memory -refusal, EMU_ANY_DEVICE=1 overrides `check`, DEVICE_PROFILE and SYSTEM_IMAGE -decide what `up` creates. +Environment: EMU_GPU=software renders on the CPU instead of the host's GPU, +AVD_NAME overrides the name, EMU_FORCE=1 overrides the memory refusal, +EMU_ANY_DEVICE=1 overrides `check`, DEVICE_PROFILE and SYSTEM_IMAGE decide +what `up` creates. USAGE exit 2 } @@ -225,15 +226,29 @@ cmd_up() { log="/tmp/$avd-emulator.log" rm -f "$log" - if [ -n "${DISPLAY:-}" ] || [ -n "${WAYLAND_DISPLAY:-}" ]; then + # `-gpu host` runs the guest's GLES on this machine's real GPU, which here + # means the *host's* GPU reached through virtio-gpu -- so a headless + # emulator nobody is watching still renders onto the desktop somebody is + # sitting at. It stays the default because it was measured (25% janky + # frames against 3%, and 3.9 GB resident against 2.9 GB) and the Compose + # scroll benchmarks depend on it. EMU_GPU=software opts out, for work + # where the emulator's own frame rate is not what is under test: it + # renders on the CPU and touches no GPU at all, which also means the + # guest gets a software Vulkan device (SwiftShader) instead of the host + # Vulkan that gfxstream cannot pair with Venus here. + if [ "${EMU_GPU:-}" != software ] && { [ -n "${DISPLAY:-}" ] || [ -n "${WAYLAND_DISPLAY:-}" ]; }; then echo "emu: starting '$avd' with GPU acceleration" >&2 "$sdk/emulator/emulator" -avd "$avd" -gpu host -no-audio >"$log" 2>&1 & - elif display=$(headless_display); then + elif [ "${EMU_GPU:-}" != software ] && display=$(headless_display); then echo "emu: no display -- starting '$avd' headless on the GPU ($display)" >&2 DISPLAY="$display" "$sdk/emulator/emulator" -avd "$avd" \ -gpu host $GPU_HOST_FEATURES -no-audio -no-window >"$log" 2>&1 & else - echo "emu: no display and no compositor -- starting '$avd' on software rendering" >&2 + if [ "${EMU_GPU:-}" = software ]; then + echo "emu: EMU_GPU=software -- starting '$avd' on the CPU, off the host GPU" >&2 + else + echo "emu: no display and no compositor -- starting '$avd' on software rendering" >&2 + fi "$sdk/emulator/emulator" -avd "$avd" -gpu swiftshader_indirect -no-audio -no-window \ >"$log" 2>&1 & fi