fps: Add per-process GPU usage to the HUD (#2751)
## Summary The HUD reported CPU and memory but nothing about the GPU, which for a renderer is the half that usually explains a slow frame. This adds a `GPU` reading for **this process' own share**, and colors the `FRAME` value against the frame budget. ``` ┌──────────────────────────┐ │ ﹋﹏ 118 FPS ﹋︿﹏﹋ │ │ FRAME 8.4 ms │ ← now colored against the budget │ DROP 0.0% │ │ GPU 31.0% │ ← new │ CPU 12.4% MEM 84 MB │ └──────────────────────────┘ ``` ### Why per-process, not device-wide A device-wide number moves for the compositor and every other window, none of which the application can act on. It also would not sit sensibly next to the per-process CPU beside it. Each platform is read where it already attributes GPU time per process. No vendor SDK, no elevated privilege: | Platform | Source | Same counter as | |---|---|---| | macOS | `accumulatedGPUTime` on this process' accelerator clients in the IO registry | Activity Monitor's GPU column | | Windows | `\GPU Engine(*)\Utilization Percentage`, filtered to `pid_<self>_` instances | Task Manager's GPU column | | Linux | `drm-engine-*` in `/proc/self/fdinfo` | `nvtop`, `intel_gpu_top` | Two dead ends are recorded in `gpu/macos.rs` so they are not retried: the accelerator's own `PerformanceStatistics` is easier to read but device wide, and `task_info`'s `task_gpu_utilisation` is per process but sits at zero on Apple silicon. Where several engines run at once (Windows, Linux) the reading is the busiest engine *type* rather than their sum, which would pass 100% while the GPU still had headroom. **The row is left out entirely where no per-process counter is reachable**, rather than reading a flat zero — the web, an Intel Mac (accelerator clients publish no `AppUsage`), and a Linux driver such as nvidia's, which keeps its accounting in NVML. ### `FRAME` color The headline is graded on the frame *rate*, so an idle window drawing a handful of frames a second turns it red even though every one of those frames landed well inside the budget. `FRAME` is graded on the frame *time* with the same scale as the trace, so it staying green is what tells you the application is fine and simply has nothing to redraw. ## Test plan - Verified on macOS against a real load: the reading tracked the window from 0% in the background, to 13% in the foreground, to 33% with the example's curve count dialed up, cross-checked against `ioreg`'s accumulated total for the same pid. - `cargo clippy -p gpui-fps --all-targets -- -D warnings` clean; 12 tests pass; `rustfmt`, `typos` and `cargo machete` clean. - The Windows and Linux backends cannot link the full `gpui` from macOS, so both were extracted into an isolated crate and run through `cargo clippy -D warnings` for `x86_64-pc-windows-msvc` and `x86_64-unknown-linux-gnu`. The Linux `fdinfo` parser's tests (including that `drm-engine-capacity-*` counts engines, not nanoseconds) pass on the host. **Runtime behavior on those two platforms still needs confirmation from CI or a reviewer on that hardware.** - `wasm32-unknown-unknown` and the whole workspace compile. No public API change: the new reading rides on the existing `show_resources` and `resource_interval` builders. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-authored-by: Codex <codex@openai.com>
J
Jason Lee committed
7a9ac172e804ce89aebac644a02f09813dc9e793
Parent: 5b3e18d
Committed by GitHub <noreply@github.com>
on 8/18/2026, 7:32:50 AM