HDR (display-driven, matching the WGC path): - CTA-861.3 HDR EDID (BT.2020 primaries + HDR Static Metadata block) so Windows offers "Use HDR" on the virtual display. The host FOLLOWS the display's live advanced-color state, recreating the shared ring at the matching format (FP16 in HDR / BGRA in SDR) on a toggle — no freeze. - Always emit Main10/BT.2020-PQ Rgb10a2 while the display is HDR; the client auto-detects PQ from the HEVC VUI (clients under-report VIDEO_CAP_10BIT). Generic HDR10 mastering SEI on every IDR. - Generation-tagged `latest` (gen<<40|seq<<8|slot) + driver `is_stale` re-attach kill the toggle-time garbage frame and any stale-ring read. Perf: - Pipeline the encode loop (Capturer::pipeline_depth; IDD-push = 2): submit N+1 before polling N so the convert/copy on the 3D engine overlaps the NVENC encode of N on the ASIC. PUNKTFUNK_IDD_DEPTH overrides (1 = synchronous). - Rotating host output ring (OUT_RING) so the in-flight encode and the next convert never touch the same texture. - HDR converts directly from the keyed-mutex slot's SRV into the output ring (drops the redundant slot->fp16 scratch copy); SDR copies the BGRA slot in. The slot mutex is held only across the convert/copy, not the encode. RING_LEN 3->6 for publish headroom. - Capture-health diagnostic: new_fps vs repeat_fps under PUNKTFUNK_PERF (a low new_fps at a high send rate means the source isn't compositing, not an encode stall). Validated live on the RTX box: 5120x1440@240 HDR streams; driver composes ~180 new fps, encode 240 fps @ ~4.3 ms p50. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
pf-vdisplay — punktfunk Windows virtual display (Rust IddCx)
P1 of replacing the vendored SudoVDA C++ driver with one we own — a pure-Rust UMDF2 IddCx
(Indirect Display Driver) virtual display, drop-in compatible with the host's existing
vdisplay/sudovda.rs IOCTL control plane. Full rationale + roadmap:
docs/windows-virtual-display-rust-port.md.
Layout
vdisplay-driver/
wdf-umdf-sys/ VENDORED bindgen FFI to WDF + IddCx (links WdfDriverStubUm + IddCxStub)
wdf-umdf/ VENDORED safe wrappers (IddCx*/Wdf*)
pf-vdisplay/ OUR driver crate (cdylib) + pf_vdisplay.inx
wdf-umdf-sys / wdf-umdf are vendored from MolotovCherry/virtual-display-rs
(MIT — see LICENSE.virtual-display-rs). They're a self-contained bindgen over the WDK, not
windows-drivers-rs (which the gamepad drivers use): IddCx functions are direct IddCxStub exports the
WDF function-table macro can't reach, so a unified bindgen is the cleaner base. Local fix carried in
wdf-umdf-sys/build.rs: resolve the IddCxStub lib path by the SDK version that actually contains
um\x64\iddcx\<ver> (a newer base SDK alongside the WDK has um\x64 but no iddcx).
Status
- Scaffold builds ✅ — workspace + vendored bindings +
pf-vdisplaycompile in-tree topf_vdisplay.dll. The reference (virtual-display-rs) was separately built + installed + loaded (Status OK) on the RTX box, proving the IddCx-in-Rust chain end to end. - Next (P1 driver logic): port the IddCx driver —
DriverEntry→IDD_CX_CLIENT_CONFIG(adapter-init / parse-monitor-description / query-target-modes / assign-swapchain) → device + monitor context, generic EDID, no-op swap-chain drain (DDA still captures for P1). Logging viaOutputDebugString(nolog/driver-logger/tokio). - Then (control plane): the SudoVDA-compatible IOCTL surface on the control device
(
ADD/REMOVE/PING/GET_WATCHDOG/GET_VERSION/SET_RENDER_ADAPTER, byte-identical structs + the{e5bcc234-…}interface GUID) sovdisplay/sudovda.rsdrives it unchanged; a default mode table + the per-ADDclient mode injected as preferred; the watchdog. - Later (P2): push swap-chain frames straight to the host (skip DDA); HDR via the IddCx 1.11 D3D12 acquire path.
Build
Needs the WDK (UMDF 2.31 + IddCx stubs), LLVM/clang (LIBCLANG_PATH), and the pinned
nightly-2024-07-26 (auto-selected via rust-toolchain.toml). From pf-vdisplay/, inside an MSVC dev
shell:
set LIBCLANG_PATH=C:\Program Files\LLVM\bin
cargo build # -> ../target/x86_64-pc-windows-msvc/debug/pf_vdisplay.dll
Sign + install (same recipe as the gamepad drivers)
- (no FORCE_INTEGRITY bit to clear — this crate doesn't set
/INTEGRITYCHECK) signtool sign /fd SHA256 /sha1 <punktfunk-ds-test thumbprint>the renamedpf_vdisplay.dllstampinf -f pf_vdisplay.inf -d * -a amd64 -u 2.15.0 -v <ver>;Inf2Cat /driver:<dir> /os:10_X64; sign the.catpnputil /add-driver pf_vdisplay.inf; create the root devnode (nefconc --create-device-node --hardware-id root\pf_vdisplay --class-name Display --class-guid {4d36e968-…}, mirroringinstall-sudovda.ps1)
Bundles into the Inno Setup installer the same way as gamepad-drivers/ once the driver is functional.