Skip to content

obs-gpu-status: Windows GPU: x% from PDH GPU Engine counters - #1264

Merged
zackees merged 3 commits into
obs-rust:masterfrom
vpacher:feat/1025-windows-pdh-usage
Oct 17, 2026
Merged

zackees merged 3 commits into
obs-rust:masterfrom
vpacher:feat/1025-windows-pdh-usage

Conversation

@vpacher

@vpacher vpacher commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

Refs #1025
Refs #1022

What and why

On Windows the GPU: x% label (#1025, #1236) shows GPU: 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:

  1. Adds PdhSource to platform::usage_sources() on Windows, after NVML. It reads the render adapter's LUID (obs-gpu-status: Pick the Windows render GPU by LUID #1198) through pdh::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.
  2. Adds Source::Pdh (JSON usage.source: pdh).
  3. Updates docs/gpu-status.md, and the GPU: x% line in docs/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.rs or platform/windows.rs (#1022 stays with its claim; see the comment there).

RED → GREEN

Checklist

  • Base is master (or the description starts with a Stacked: note)
  • I claimed the issue, or no one else has an open PR for it (frontend: GPU: x% readout replaces the GPU status light #1025 is mine; obs-gpu-status: Windows GPU utilization through PDH GPU Engine counters #1022 is zackees', coordinated there)
  • Characterization test (if the unit had none), then RED, then GREEN commits
  • (Optional) Local gate passed and the pushed head is stamped; otherwise PR CI runs the full suite
  • Warning or flag changes (-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)
  • Intentional differences from C listed in the parity test header and rust/README.md (ports) (not applicable: new code, no C original)

🤖 Generated with Claude Code

@zackees zackees left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@zackees
zackees added this pull request to the merge queue Oct 17, 2026
@zackees

zackees commented Oct 17, 2026

Copy link
Copy Markdown
Member

@vpacher On the PDH polling-cost follow-up from my review (keep one query open between samples instead of reopening it in gpu_engine_samples() each tick): if you already have a fix for it, you're welcome to do it, here or as a follow-up PR. Just say so and I'll leave it to you. Otherwise I'll pick it up once this merges.

@zackees
zackees removed this pull request from the merge queue due to a manual request Oct 17, 2026
@zackees

zackees commented Oct 17, 2026

Copy link
Copy Markdown
Member

@vpacher #1262 is ahead of this in the queue, and the two conflict in platform/mod.rs, usage.rs, tests/gpu_status/usage.rs and docs/gpu-status.md (both add a usage source). I've taken this out of the queue. Once #1262 merges, could you rebase onto master? You know how the macOS and Windows sources should sit together better than I do. I'll queue it again when CI is green.

@vpacher
vpacher force-pushed the feat/1025-windows-pdh-usage branch from b544c43 to 0eed5e3 Compare October 17, 2026 16:59
@vpacher

vpacher commented Oct 17, 2026

Copy link
Copy Markdown
Contributor Author

@zackees Rebased onto master after #1262 (head 0eed5e3). Conflict resolution: the macOS IOKit and Windows PDH sources sit side by side after NVML (usage_sources(), Source, the names test, docs/gpu-status.md). The probe commit dropped out, because #1262 merged the same lines. RED still fails on source_names and GREEN passes 129/129; clippy is clean for macOS and x86_64-pc-windows-msvc. Per the ledger rule from #1267, the GPU: x% line in docs/features.md now covers all three platforms (#1262 merged before the ledger existed).

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 PdhQuery owned by PdhSource that opens the query and adds the counter once; each tick does one PdhCollectQueryData and uses the previous tick as the baseline (no 100 ms sleep; the first tick primes and gives Unavailable). gpu_engine_samples() stays as the one-shot API for the probe. I'll measure before and after on the same Windows VM with the RTX 3060.

@zackees

zackees commented Oct 17, 2026

Copy link
Copy Markdown
Member

@vpacher Thanks. I checked the rebase: IOKit and PDH each sit after NVML behind their own cfg!, Source::Pdh/"pdh" sits next to iokit, and windows_asks_nvml_then_pdh still pins the Windows order. Looks right. Re-queuing with auto-merge.

The PDH polling cost is yours, as a separate PR. The plan sounds good. A first tick that only primes and reports Unavailable is fine: the label shows GPU: n/a for one second at startup, which is better than blocking. I'll stay out of platform/windows.rs and pdh.rs so we don't collide. Before/after numbers from the same VM would be great in that PR.

vpacher and others added 3 commits October 17, 2026 19:07
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>
auto-merge was automatically disabled October 17, 2026 17:07

Head branch was pushed to by a user without write access

@vpacher
vpacher force-pushed the feat/1025-windows-pdh-usage branch from 0eed5e3 to ebfa77c Compare October 17, 2026 17:07
@vpacher

vpacher commented Oct 17, 2026

Copy link
Copy Markdown
Contributor Author

@zackees #1268 (the ledger backfill) merged first and conflicted with this PR's ledger line, so I rebased again (head ebfa77c). Only docs/features.md changed: the macOS/Windows update now sits on the backfilled GPU: x% line, which keeps its existing links and adds #1022, #1026, #1262 and this PR. The code commits applied unchanged. The push turned auto-merge off; could you queue it again?

@zackees
zackees added this pull request to the merge queue Oct 17, 2026
Merged via the queue into obs-rust:master with commit d145635 Oct 17, 2026
25 of 26 checks passed
@vpacher
vpacher deleted the feat/1025-windows-pdh-usage branch October 17, 2026 18:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

frontend: GPU: x% readout replaces the GPU status light

2 participants