ember-latency
Input latency in MangoHud on Linux. Shows how long it takes from a key press or mouse click until
the frame it caused is on screen, as an INPUT 18.5 ms row under your FPS. It's like PresentMon's
"click to photon" or NVIDIA's PC Latency, but for any Vulkan game on any GPU, and with no cost to
performance.
It's two parts:
VK_LAYER_EMBER_latency, a small Vulkan layer (one C file, no dependencies) that measures and writes the result to/dev/shm/ember-latency/<pid>.- A MangoHud patch that adds a native
input_latencyrow, drawn like the AVG/1% rows. If you don't want to rebuild MangoHud, there's also a no-patch option usingcustom_text(below).
How it measures
key press / click evdev kernel timestamp (CLOCK_MONOTONIC)
-> next frame the first frame the game starts after the press
-> first pixel out VK_EXT_present_timing: the compositor's real flip time
- Presses only. The layer reads
/dev/inputwithEVIOCSMASK, so the kernel never wakes it for mouse motion, only for key and button presses. - The frame you saw. If the compositor drops the frame after a press, it follows the press to the next frame that was actually shown.
- Native Wayland and gamescope report the real flip time (
FIRST_PIXEL_OUT). gamescope reports its scheduled vblank, which can be a few ms in the future, so that's allowed for. - XWayland only reports when the image was handed over. With vsync that's real. Without vsync it's
a stale vblank, so after a press the layer adds one empty
vkQueueSubmitthat waits on the game's semaphores and reports when the GPU finished the frame (xwayland-gpuin the details line). With tearing allowed, that's about when it reaches the screen. Xlib/XCB surfaces are identified at creation, so this also works when DXGI owns its own presentation timing queue (including GTA V Enhanced through Proton). - Without present timing (other drivers), it falls back to when
vkWaitForPresentKHRreturns, and only in FIFO (vsync), where that means something. - The readout is the average of your last 16 presses. It's an estimate: it assumes the game reads input at the start of a frame, and it can't see the panel's own pixel response. Expect it to be within about one frame.
Cost. It adds no GPU work, except that one empty submit on XWayland, and the game's threads never wait on anything. While you aren't pressing anything, a present costs one atomic load. Only the frame after a press asks the driver for timing, and the file is written by a worker thread, never on the present path. Benchmarks at 30,000 fps (vkcube) and in CS2 (about 400 fps) were within noise.
Requirements
- Linux with a Vulkan driver that has
VK_EXT_present_timingfor the real flip time (Mesa 26.2+ RADV tested). Anything else uses the vsync fallback. - Your user in the
inputgroup, so the layer can read key-press timestamps from/dev/input/event*. Be aware that this group lets any program you run read your keyboard. The layer itself only looks at when keys and buttons go down, never at what you type. - Build tools: a C compiler, make, Vulkan headers (Arch:
vulkan-headers; Debian/Ubuntu:libvulkan-dev).
Install
git clone https://github.com/Tjabooo/ember-latency.git
cd ember-latency
make install # ~/.local/lib/ember-latency + a user layer manifest; no root
sudo usermod -aG input "$USER" # once, then log out and in
The layer turns itself on whenever MangoHud does (MANGOHUD=1, or mangohud %command% in Steam).
Turn it off for one game with DISABLE_EMBER_LATENCY=1. Remove it with make uninstall.
Option A: native INPUT row (patched MangoHud)
sh mangohud/build-mangohud.sh # builds the version of MangoHud you have installed
This downloads that MangoHud release, applies input-latency.patch,
builds it in ~/.cache, and installs it as a user Vulkan layer. Your system package
isn't touched. Then add one line to ~/.config/MangoHud/MangoHud.conf, for example right after
fps_metrics:
input_latency
Rerun the script after your distro updates MangoHud. The patch was written against MangoHud 0.8.4. For Proton/Lutris, explicitly select the patched copy: a runtime can collect both the user and system manifests and choose the system library despite the user override. The build script also installs a uniquely named, opt-in manifest. Add these two environment variables to the game's Lutris configuration, or prefix its Steam launch command with them:
EMBER_MANGOHUD=1 VK_LOADER_LAYERS_DISABLE=VK_LAYER_MANGOHUD_overlay_x86_64 mangohud %command%
Keep MangoHud enabled in Lutris. If VK_LOADER_LAYERS_DISABLE already contains other filters,
append ,VK_LAYER_MANGOHUD_overlay_x86_64 to its value. This disables the duplicate stock 64-bit
layer while enabling the uniquely named patched one; 32-bit and OpenGL MangoHud are unaffected.
Relaunch the game and its launcher after changing these variables.
Undo: remove those environment variables and both user manifests,
MangoHud.x86_64.json and ember_mangohud.x86_64.json, from
~/.local/share/vulkan/implicit_layer.d/.
The patched build covers 64-bit Vulkan games. OpenGL and 32-bit games keep the stock MangoHud,
which ignores the input_latency line, so there the row is simply missing.
Option B: stock MangoHud, no rebuild
MangoHud runs exec commands as children of the game, so $PPID is the game's PID:
custom_text=INPUT
exec=f=/dev/shm/ember-latency/$PPID; if [ -r "$f" ]; then read -r l < "$f"; echo "$l ms"; else echo -; fi
custom_text=
Stock MangoHud draws these in its smaller secondary font and in a single colour.
Reading it
INPUT 18.5 ms: the average of your last 16 presses.-: no data yet (nothing pressed, an OpenGL game, or the layer can't read/dev/input)./dev/shm/ember-latency/<pid>: line 1 is the average, line 2 has the details (method, samples, last value).
Debugging:
| Variable | Effect |
|---|---|
EMBER_LATENCY_DEBUG=1 |
Log to stderr (2 = every timing report) |
EMBER_LATENCY_NO_TIMING=1 |
Force the vkWaitForPresent fallback |
EMBER_LATENCY_TEST=<n> |
Simulate n presses per second (no human needed) |
DISABLE_EMBER_LATENCY=1 |
Turn the layer off |
Tested with vkcube (Wayland, XWayland and nested gamescope, all present modes), inside Steam's
Linux runtime (Proton games: the runtime shares /dev/input and /dev/shm), and with CS2. Sober
(a Flatpak) and OpenGL games show -.
License
MIT