Repository navigation
obs-gpu-status: Windows GPU: x% from PDH GPU Engine counters - #1264
Conversation
zackees
left a comment
There was a problem hiding this comment.
Reviewed. Wiring is right: PDH runs after NVML on Windows only, keyed by the render adapter's LUID (#1198), and any other adapter (or an empty/failed PDH read, which pdh_utilization turns into Unavailable) falls through cleanly. cfg!(windows) sits in src/platform/, inside the boundary. The test gives a source-order RED on Windows, and the hardware table against nvidia-smi is good evidence that the busiest-engine headline matches.
One follow-up, not blocking (it's in my #1022 code, and I'll take it): gpu_engine_samples() opens the query and adds the counter on every call, which accounts for most of the ~225 ms per sample (894 ms for the first). Keeping one query open in a struct owned by PdhSource and collecting once per tick would cut it to about one PdhCollectQueryData, and would also drop the 100 ms sleep, since the previous tick serves as the baseline.
|
@vpacher On the PDH polling-cost follow-up from my review (keep one query open between samples instead of reopening it in |
|
@vpacher #1262 is ahead of this in the queue, and the two conflict in |
b544c43 to
0eed5e3
Compare
|
@zackees Rebased onto master after #1262 (head 0eed5e3). Conflict resolution: the macOS IOKit and Windows PDH sources sit side by side after NVML ( The PDH polling cost: I'll take it, as a separate PR after this one, so this PR stays as you reviewed it. Plan: a |
|
@vpacher Thanks. I checked the rebase: IOKit and PDH each sit after NVML behind their own The PDH polling cost is yours, as a separate PR. The plan sounds good. A first tick that only primes and reports |
Source::Pdh names the Windows PDH GPU Engine counters (obs-rust#1022) in the JSON; the stub name is empty, so source_names fails. A Windows-only test requires usage_sources() to ask NVML, then PDH; it fails on Windows, where PDH is not wired in yet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
platform::usage_sources() asks the PDH GPU Engine counters (obs-rust#1022, LUID (obs-rust#1198) through pdh_utilization, the busiest engine as Task Manager shows it, for every vendor. NVML cannot map the LUID to a PCI address yet, so PDH also reads NVIDIA GPUs on Windows. One sample blocks for 100 ms on the obs-gpu-usage thread, never the UI thread. The JSON source name is "pdh". 125/125 crate tests pass on macOS; clippy -D warnings is clean for macOS and x86_64-pc-windows-msvc. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The features ledger line for the GPU: x% label names all three platforms and their sources: NVML and gpu_busy_percent on Linux, IOKit on macOS (obs-rust#1262, merged before the ledger existed) and PDH on Windows. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Head branch was pushed to by a user without write access
0eed5e3 to
ebfa77c
Compare
|
@zackees #1268 (the ledger backfill) merged first and conflicted with this PR's ledger line, so I rebased again (head ebfa77c). Only |
Refs #1025
Refs #1022
What and why
On Windows the
GPU: x%label (#1025, #1236) showsGPU: n/a. NVML cannot find the render GPU there yet (it needs the DXGI LUID as a PCI address), and the PDH sampler from #1228 is not wired into the label. This PR wires it in.This PR:
PdhSourcetoplatform::usage_sources()on Windows, after NVML. It reads the render adapter's LUID (obs-gpu-status: Pick the Windows render GPU by LUID #1198) throughpdh::pdh_utilization, the busiest engine as Task Manager shows it, for every vendor. NVIDIA GPUs also read through PDH on Windows until NVML can map the LUID.Source::Pdh(JSONusage.source:pdh).docs/gpu-status.md, and theGPU: x%line indocs/features.md(docs: A features ledger linked from the README #1267): all three platforms, with obs-gpu-status: macOS GPU utilization from IOKit PerformanceStatistics #1262 and this PR.It changes nothing in
pdh.rsorplatform/windows.rs(#1022 stays with its claim; see the comment there).RED → GREEN
Rebased onto master after obs-gpu-status: macOS GPU utilization from IOKit PerformanceStatistics #1262 (both sources sit side by side: macOS IOKit, then Windows PDH, after NVML). The probe commit is gone, because obs-gpu-status: macOS GPU utilization from IOKit PerformanceStatistics #1262 merged the same lines.
RED a063567:
Source::Pdhwith an empty name, sosource_namesfails (left: "",right: "pdh"). A Windows-only test,windows_asks_nvml_then_pdh, requires the source order NVML, PDH. It fails on Windows, where PDH is not wired in yet (PR CI runs it inRust Tests 🦀 (windows-2025-vs2026)).GREEN 7bf5f0e: 129/129 crate tests pass on macOS. clippy: PR CI's
Rust Cross Lint 🦀 (Windows, macOS)passes (my local clippy check had a broken output filter, so the CI run is the evidence).Real hardware (probe from this branch before the rebase, cross-built for
x86_64-pc-windows-gnuon Linux): Windows 11 LTSC 2024 VM with an RTX 3060 passed through, driver 617.42. DXGI adapter 0 (OBS's defaultadapter0) is the RTX 3060,Luid(0x239bee), and the label sample isUsageSample { source: Pdh }. Adapters 1 and 2 giveUnknown. Under a GPU-bound WebGL load, PDH andnvidia-smiagree:nvidia-smiPolling cost (research: GPU utilization readout in the status bar, merged with the acceleration light #1004, obs-gpu-status: Windows GPU utilization through PDH GPU Engine counters #1022): the first sample takes 894 ms, then 222 to 247 ms each. That is the 100 ms interval plus about 125 ms to open the query and add the counter, which
gpu_engine_samples()does on every call. It runs on theobs-gpu-usagethread, never the UI thread. A query that stays open between samples would remove most of it; that is a change inplatform/windows.rs(obs-gpu-status: Windows GPU utilization through PDH GPU Engine counters #1022).Real app: not done. PR CI skips the Windows app build for this Rust-only change, and the latest beta (2026-10-14) is older than frontend: GPU: x% label replaces the GPU status light text #1236. For this reason this PR uses Refs, not Fixes. I will run the first beta that contains it on the same machine and close frontend: GPU: x% readout replaces the GPU status light #1025 with the result.
Checklist
master(or the description starts with a Stacked: note)-W..., ratchets): built with scripting ON (a flag change under cmake/ or build-aux/ runs the full builds) and cross-checked with clang and MSVC (not applicable: no flag changes)🤖 Generated with Claude Code