feat(vdisplay/driver): frame witness + commit-mode flag logging #446

Merged
enricobuehler merged 1 commits from worktree-vdisplay-ddi-sweep into main 2026-08-29 17:42:17 +00:00
Owner

Why

This is the deliverable of the pf-vdisplay IddCx correctness sweep (the follow-up to #445: the standby-sink fix removed the catastrophic holes only half the time, and the working hypothesis was that the driver mishandles part of the IddCx contract).

Sweep verdict: the hypothesis is not confirmed. All seven scope items were checked against the real 10.0.26100.0\um\iddcx\1.10\IddCx.h (read on .173) and the MS sample:

  • Callback table (26 slots): only the eight OPM callbacks (optional; a DRM output-protection feature gap, not a display-path lever) and GetPhysicalSize (only called for EDID-less remote monitors — ours ships an EDID with size bytes) are unset.
  • Zeroed fields: all match the sample. MaxDisplayPipelineRate=0, RequiredBandwidth=0 and StaticDesktopReencodeFrameCount=0 are canonical.
  • One documented divergence, deliberately not fixed: IDARG_OUT_QUERYTARGET_INFO.TargetCaps sets HIGH_COLOR_SPACE without WIDE_COLOR_SPACE, which the header asks for. Adding WIDE advertises SDR-WCG, so Windows may offer ACM and hand the driver FP16 SDR surfaces the host ring/tonemap path never planned for. If we ever want it, it needs its own program.
  • Frame lifecycle, mode timing, E_PENDING wait, surface-ref adopt/release, MMCSS Distribution, delete-swapchain-on-exit: IddSampleDriver-exact; every path is bounded far under the 10 s FinishedProcessingFrame bugcheck watchdog.

Since no divergence can explain the residual FRAME-GENERATION holes, the driver now testifies instead of guessing.

What

  • swap_chain_processor.rs: a frame witness. Every acquire that ends ≥ 1 s of silence (or lands ≥ 250 ms after its display time, throttled to one line per 2 s) logs the OS's own stamps from IDDCX_METADATA2: frame-witness t=<unix_ms> silence=..ms pfn=N (+step) late=..ms dirty=... Reading: a pfn jump = DWM composed frames this swap-chain never received (a true drop); +1 with a large late = composed on time, delivered late; +1 and fresh = DWM composed nothing for this head. Rides dbglog!, so release builds without PFVD_DEBUG_LOG emit nothing.
  • callbacks.rs: commit_modes/commit_modes2 log each path's ACTIVE/CHANGED flags, so an OS-side head deactivation without an unassign would be visible next to a hole.

Measurements (.173, loopback rig, debug driver 9.9.829.1810)

The witness paid for itself in its first leg. Three legs, 90–150 s each, punktfunk-session loopback with Epic present:

  • Idle legs (cursor-wiggle "damage"): the head received ~5 composed frames per 150 s — every witness line read pfn +1, late≈−15ms, dirty=1, with silences of 24–60 s and an exact 60.000 s beat (the taskbar clock repaint as the only real damage). A 58.8 s host stall labelled FRAME-GENERATION matched a witness line saying "DWM composed nothing".
  • Root cause of the blindness: ssh shells run in session 0; DWM composes only console session 1. The wiggle cursor, the loopback client's own window, and any ssh-spawned animator are invisible to composition — the rig's damage source never existed.
  • Leg with real damage (a 60 Hz invalidating borderless window scheduled into session 1 via schtasks /it): from the moment it fired, witness lines stopped for the rest of the leg — continuous compose, zero holes, zero host stalls.

Consequences for earlier numbers: the #445 16-pair comparison stands (both arms equally blind, treatment asserted per leg), but its hole-time magnitudes measured an idle desktop and want a re-run with session-1 damage. A FRAME-GENERATION conviction on this rig can also be fed by presents from invisible session-0 windows (the loopback client itself); field convictions with a game on glass are unaffected.

Gates

  • .173 (real WDK): cargo build, cargo clippy, cargo fmt --check for pf-vdisplay all exit 0.
  • Deployed and streamed live: two verified legs, frame statistics still report rc=0x0.
  • The macOS check for this crate is vacuous by design; the Windows runs above are the real gates.
## Why This is the deliverable of the pf-vdisplay IddCx correctness sweep (the follow-up to #445: the standby-sink fix removed the catastrophic holes only half the time, and the working hypothesis was that the driver mishandles part of the IddCx contract). **Sweep verdict: the hypothesis is not confirmed.** All seven scope items were checked against the real `10.0.26100.0\um\iddcx\1.10\IddCx.h` (read on .173) and the MS sample: - **Callback table (26 slots):** only the eight OPM callbacks (optional; a DRM output-protection feature gap, not a display-path lever) and `GetPhysicalSize` (only called for EDID-less remote monitors — ours ships an EDID with size bytes) are unset. - **Zeroed fields:** all match the sample. `MaxDisplayPipelineRate=0`, `RequiredBandwidth=0` and `StaticDesktopReencodeFrameCount=0` are canonical. - **One documented divergence, deliberately not fixed:** `IDARG_OUT_QUERYTARGET_INFO.TargetCaps` sets `HIGH_COLOR_SPACE` without `WIDE_COLOR_SPACE`, which the header asks for. Adding WIDE advertises SDR-WCG, so Windows may offer ACM and hand the driver FP16 SDR surfaces the host ring/tonemap path never planned for. If we ever want it, it needs its own program. - **Frame lifecycle, mode timing, E_PENDING wait, surface-ref adopt/release, MMCSS `Distribution`, delete-swapchain-on-exit:** IddSampleDriver-exact; every path is bounded far under the 10 s `FinishedProcessingFrame` bugcheck watchdog. Since no divergence can explain the residual FRAME-GENERATION holes, the driver now testifies instead of guessing. ## What - `swap_chain_processor.rs`: a **frame witness**. Every acquire that ends ≥ 1 s of silence (or lands ≥ 250 ms after its display time, throttled to one line per 2 s) logs the OS's own stamps from `IDDCX_METADATA2`: `frame-witness t=<unix_ms> silence=..ms pfn=N (+step) late=..ms dirty=..`. Reading: a `pfn` **jump** = DWM composed frames this swap-chain never received (a true drop); **+1 with a large `late`** = composed on time, delivered late; **+1 and fresh** = DWM composed nothing for this head. Rides `dbglog!`, so release builds without `PFVD_DEBUG_LOG` emit nothing. - `callbacks.rs`: `commit_modes`/`commit_modes2` log each path's ACTIVE/CHANGED flags, so an OS-side head deactivation without an unassign would be visible next to a hole. ## Measurements (.173, loopback rig, debug driver 9.9.829.1810) The witness paid for itself in its first leg. Three legs, 90–150 s each, `punktfunk-session` loopback with Epic present: - **Idle legs (cursor-wiggle "damage"):** the head received ~5 composed frames per 150 s — every witness line read `pfn +1`, `late≈−15ms`, `dirty=1`, with silences of 24–60 s and an exact 60.000 s beat (the taskbar clock repaint as the only real damage). A 58.8 s host stall labelled FRAME-GENERATION matched a witness line saying "DWM composed nothing". - **Root cause of the blindness:** ssh shells run in **session 0**; DWM composes only console **session 1**. The wiggle cursor, the loopback client's own window, and any ssh-spawned animator are invisible to composition — the rig's damage source never existed. - **Leg with real damage** (a 60 Hz invalidating borderless window scheduled into session 1 via `schtasks /it`): from the moment it fired, witness lines stopped for the rest of the leg — continuous compose, zero holes, zero host stalls. Consequences for earlier numbers: the #445 16-pair comparison stands (both arms equally blind, treatment asserted per leg), but its hole-time magnitudes measured an idle desktop and want a re-run with session-1 damage. A FRAME-GENERATION conviction on this rig can also be fed by presents from invisible session-0 windows (the loopback client itself); field convictions with a game on glass are unaffected. ## Gates - .173 (real WDK): `cargo build`, `cargo clippy`, `cargo fmt --check` for `pf-vdisplay` all exit 0. - Deployed and streamed live: two verified legs, frame statistics still report `rc=0x0`. - The macOS `check` for this crate is vacuous by design; the Windows runs above are the real gates.
enricobuehler added 1 commit 2026-08-29 16:42:22 +00:00
feat(vdisplay/driver): frame witness + commit-mode flag logging
ci / bun-nix (pull_request) Successful in 33s
windows-drivers / probe-and-proto (pull_request) Successful in 1m16s
ci / rust-arm64 (pull_request) Successful in 1m27s
ci / docs-drift (pull_request) Failing after 1m30s
ci / web (pull_request) Successful in 1m53s
ci / docs-site (pull_request) Successful in 2m3s
windows-drivers / driver-build (pull_request) Successful in 2m1s
ci / rust (pull_request) Failing after 8m20s
5d2f6f0e32
The correctness sweep found no IddCx 1.10 divergence that could starve
frame generation, so the driver now testifies instead: every acquire
that ends >=1 s of silence (or lands >=250 ms after its display time)
logs the OS's PresentationFrameNumber step and PresentDisplayQPCTime
lag, splitting a FRAME-GENERATION hole into dropped / delayed /
never-composed from inside the swap-chain. The commit-modes callbacks
log each path's ACTIVE/CHANGED flags so an OS-side head deactivation
is visible next to a hole.

On .173 the witness immediately showed the loopback rig's cursor
wiggle generates no damage (ssh runs in session 0; only the console
session is composed): an idle-desktop hole reads pfn +1/fresh, and
with real session-1 damage the head composes hole-free.
enricobuehler merged commit 2fe713dc77 into main 2026-08-29 17:42:17 +00:00
enricobuehler deleted branch worktree-vdisplay-ddi-sweep 2026-08-29 17:42:30 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: unom/punktfunk#446