Merge perf/first-frame-latency: driver proto v4 + first-frame/resize latency (P0-P2)

Brings the first-frame-latency branch (P0.1 transition tracing, P1.1/P1.2
Welcome-time display prep, P2 in-place resize; pf-driver-proto v3 -> v4 with
IOCTL_UPDATE_MODES) onto current main. The branch predates the W6.2/W7 splits,
so git's rename detection carried most of it into the moved crates
(pf-capture idd_push, pf-vdisplay manager/pf_vdisplay, pf-win-display,
pf-driver-proto, the driver workspace) and the punktfunk1.rs remainder was
re-homed by hand:

- native/handshake.rs: welcome/start trace marks + the Welcome-time display
  prep spawn (the prep thread BECOMES the stream thread; hand-off via a
  SyncSender<SessionContext>). negotiate() gains bringup/quit/stop and returns
  the PrepHandle.
- native.rs: bringup/resize_ms creation + the stop/quit flags hoisted BEFORE
  the handshake (the close watcher splits: flags pre-handshake, lifecycle
  events post-handshake where `hello` exists); punch_done stamp; the data
  plane adopts the prep thread's result or builds inline.
- native/stream.rs: SessionContext/SendStats carry the trace; send_loop
  finishes it on the first video packet; the resize path gains the in-place
  fast path (try_inplace_resize) with the full rebuild as fallback, restructured
  so both share the post-rebuild bookkeeping; prepare_display/PreparedDisplay/
  PrepHandle; build_pipeline(+retry) thread the stage marks.
- session_status/mgmt: ttff_ms + last_resize_ms per session (union with the
  lifecycle-events fields main added to the same spots).
- pf-capture: Capturer gains capture_target_id() + resize_output() defaults.
- pf-vdisplay manager: perf's faster activation poll (60x50ms) + the settle
  floor before the PnP sweep, on main's knobs/no-trait shape.

Also: packaging/windows/build-gamepad-drivers.ps1 is ASCII again (an em-dash
from the pf-mouse work tripped windows-host.yml's locale-safety gate on main).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-17 16:08:16 +02:00
19 changed files with 1544 additions and 172 deletions
+163
View File
@@ -232,6 +232,169 @@ pub unsafe fn active_resolution(target_id: u32) -> Option<(u32, u32)> {
Some((dm.dmPelsWidth, dm.dmPelsHeight))
}
/// Verified-state topology-settle wait (latency plan P0.2): poll the CCD state until the target is
/// actually COMMITTED — an active path exists (the GDI name resolves) and the active resolution
/// equals the requested one — instead of sleeping a fixed interval. The conditions are exactly what
/// `resolve_gdi_name`/`set_active_mode` already established once; this waits until the OS reports
/// them stable. `ceiling` (the old fixed sleep) is the worst-case bound: a mode the driver rejected
/// (`set_active_mode` left the OS default) or a slow third-party CCD-lock holder (SteelSeries
/// class) burns the ceiling and proceeds — behavior identical to the fixed sleep it replaces.
/// Returns `true` when the state verified (typical: one or two 25 ms polls), `false` on ceiling.
///
/// # Safety
/// Runs the CCD/GDI query FFI; call under the manager `state` lock like the callers it serves.
pub(crate) unsafe fn wait_mode_settled(
target_id: u32,
mode: Mode,
ceiling: std::time::Duration,
) -> bool {
let deadline = std::time::Instant::now() + ceiling;
loop {
// SAFETY (both calls): CCD/GDI FFI over a `Copy` target id, owned returns — the callers'
// own safety contract (under the `state` lock) covers them.
if resolve_gdi_name(target_id).is_some()
&& active_resolution(target_id) == Some((mode.width, mode.height))
{
return true;
}
if std::time::Instant::now() >= deadline {
return false;
}
std::thread::sleep(std::time::Duration::from_millis(25));
}
}
/// Re-commit the CURRENT active config with `SDC_FORCE_MODE_ENUMERATION` — the nudge that makes
/// the OS re-query an indirect display's target modes. Observed on-glass (P2): after
/// `IddCxMonitorUpdateModes2` the OS did NOT re-enumerate on its own within 2 s, so a freshly
/// advertised mode never became settable; the isolate/layout paths already re-commit with this
/// flag for the same "the OS won't re-evaluate unless told" class. Best-effort.
///
/// # Safety
/// Runs the CCD query/apply FFI; call under the manager `state` lock (sole topology mutator).
pub(crate) unsafe fn force_mode_reenumeration() -> bool {
let Some((paths, modes)) = query_active_config() else {
return false;
};
let rc = SetDisplayConfig(
Some(paths.as_slice()),
Some(modes.as_slice()),
SDC_APPLY
| SDC_USE_SUPPLIED_DISPLAY_CONFIG
| SDC_ALLOW_CHANGES
| SDC_FORCE_MODE_ENUMERATION,
);
if rc != 0 {
tracing::debug!("force mode re-enumeration: SetDisplayConfig rc={rc:#x}");
}
rc == 0
}
/// The distinct resolutions `gdi_name` currently advertises (diagnostics for the in-place-resize
/// path: what the OS actually offers when a requested mode never shows up).
pub(crate) fn advertised_resolutions(gdi_name: &str) -> Vec<(u32, u32)> {
let wname: Vec<u16> = gdi_name.encode_utf16().chain(std::iter::once(0)).collect();
let mut set = std::collections::BTreeSet::new();
let mut i = 0u32;
loop {
let mut dm = DEVMODEW {
dmSize: size_of::<DEVMODEW>() as u16,
..Default::default()
};
// SAFETY: `wname` is a live NUL-terminated UTF-16 device name; `&mut dm` is a live,
// size-stamped DEVMODEW the API fills for mode index `i`. Both outlive the call.
let ok = unsafe {
EnumDisplaySettingsW(
PCWSTR(wname.as_ptr()),
ENUM_DISPLAY_SETTINGS_MODE(i),
&mut dm,
)
}
.as_bool();
if !ok {
break;
}
set.insert((dm.dmPelsWidth, dm.dmPelsHeight));
i += 1;
}
set.into_iter().collect()
}
/// Wait (bounded) until `gdi_name` ADVERTISES `mode`'s resolution in its display-mode list — the
/// gate between a driver-side mode-list refresh (`IOCTL_UPDATE_MODES`, latency plan P2) and the
/// CCD/GDI force-set: the OS re-evaluates an indirect display's settable modes asynchronously after
/// `IddCxMonitorUpdateModes2`, so an immediate `set_active_mode` could race the re-enumeration and
/// silently leave the old mode. Returns `true` once any refresh at the requested WxH is enumerable.
pub(crate) fn wait_mode_advertised(
gdi_name: &str,
mode: Mode,
ceiling: std::time::Duration,
) -> bool {
let wname: Vec<u16> = gdi_name.encode_utf16().chain(std::iter::once(0)).collect();
let deadline = std::time::Instant::now() + ceiling;
loop {
let mut i = 0u32;
loop {
let mut dm = DEVMODEW {
dmSize: size_of::<DEVMODEW>() as u16,
..Default::default()
};
// SAFETY: `wname` is a live NUL-terminated UTF-16 device name whose pointer stays valid
// for the call; `&mut dm` is a live, size-stamped DEVMODEW the API fills for mode index
// `i`. Both outlive this synchronous call.
let ok = unsafe {
EnumDisplaySettingsW(
PCWSTR(wname.as_ptr()),
ENUM_DISPLAY_SETTINGS_MODE(i),
&mut dm,
)
}
.as_bool();
if !ok {
break;
}
if dm.dmPelsWidth == mode.width && dm.dmPelsHeight == mode.height {
return true;
}
i += 1;
}
if std::time::Instant::now() >= deadline {
return false;
}
std::thread::sleep(std::time::Duration::from_millis(25));
}
}
/// Monitor-departure wait (latency plan P0.3): after a REMOVE, poll until the target has left the
/// ACTIVE CCD set — two consecutive absent samples, so one transient query failure mid-teardown
/// can't read as "gone" — instead of sleeping the fixed departure settle. `ceiling` (the old fixed
/// sleep) bounds the worst case. The OS-side departure may still be finishing driver-side when the
/// CCD stops listing the target; the ADD path's ghost-reap retry (pf_vdisplay) remains the backstop
/// for that rare race, exactly as it was for a settle that expired. Returns `true` when departure
/// was observed, `false` on ceiling.
///
/// # Safety
/// Runs the CCD query FFI; call under the manager `state` lock like the callers it serves.
pub(crate) unsafe fn wait_target_departed(target_id: u32, ceiling: std::time::Duration) -> bool {
let deadline = std::time::Instant::now() + ceiling;
let mut absent_streak = 0u32;
loop {
// SAFETY: CCD FFI over a `Copy` target id, owned return, under the caller's `state` lock.
if resolve_gdi_name(target_id).is_none() {
absent_streak += 1;
if absent_streak >= 2 {
return true;
}
} else {
absent_streak = 0;
}
if std::time::Instant::now() >= deadline {
return false;
}
std::thread::sleep(std::time::Duration::from_millis(25));
}
}
/// Toggle the virtual-display target's advanced-color (HDR) state via the CCD API. Disabling HDR while on the
/// secure (Winlogon) desktop makes it render SDR/composed so DXGI Desktop Duplication can capture it
/// (the HDR fullscreen independent-flip otherwise storms `ACCESS_LOST` → black); re-enable on return so