perf(host): replace the Windows bring-up/resize fixed sleeps with verified-state waits

Latency plan P0.2/P0.3/P0.5 (design/first-frame-and-resize-latency.md):
- topology settle: the unconditional 1500 ms sleeps after create_monitor's
  group-topology apply and re_add's reisolate become a 25 ms poll for the
  committed state (active path + active mode == requested), ceiling 1500 ms —
  worst case identical, typical case saves ~1.2-1.4 s on every fresh create
  AND every mid-stream resize. The experimental pnp_disable_monitors sweep
  keeps the full settle as its floor (it reads OTHER displays' active flags,
  which the target-scoped wait doesn't verify).
- monitor departure: the fixed 400 ms REMOVE settles (re_add + both preempt
  paths) become a 25 ms poll until the target leaves the active CCD set
  (2 consecutive absent samples), ceiling 400 ms; the driver-side ghost-reap
  ADD retry stays the backstop.
- activation ladder: 200 ms -> 50 ms sampling, same 3 s per-stage ceilings
  and the same 3-stage structure.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-16 16:44:57 +02:00
parent 4ffa2665ac
commit 4ed5b88407
2 changed files with 141 additions and 22 deletions
@@ -35,7 +35,8 @@ use windows::Win32::System::Threading::{
use super::{DisplayOwnership, Mode, VirtualOutput};
use crate::win_display::{
count_other_active, force_extend_topology, isolate_displays_ccd, resolve_gdi_name,
restore_displays_ccd, set_active_mode, set_virtual_primary_ccd, SavedConfig,
restore_displays_ccd, set_active_mode, set_virtual_primary_ccd, wait_mode_settled,
wait_target_departed, SavedConfig,
};
/// The per-backend REMOVE key the driver stamps on ADD and consumes on REMOVE. SudoVDA keys monitors by
@@ -511,9 +512,10 @@ impl VirtualDisplayManager {
if let Some(SlotState::Lingering { mon, .. } | SlotState::Pinned { mon }) =
inner.slots.remove(&slot)
{
let old_target = mon.target_id;
tracing::info!(
slot,
old_target = mon.target_id,
old_target,
"IDD-push reconnect — preempting the kept (lingering/pinned) monitor, recreating a fresh one"
);
// SAFETY: `teardown_removed` requires `dev` to be a valid control handle; `dev` is the
@@ -523,7 +525,16 @@ impl VirtualDisplayManager {
unsafe { self.teardown_removed(dev, &mut inner, mon) };
// Let the OS finish the ASYNC monitor departure before the next ADD; a back-to-back
// REMOVE→ADD races the teardown and the ADD IOCTL is rejected under reconnect churn.
thread::sleep(Duration::from_millis(400));
// Verified-state wait, ceiling = the old fixed 400 ms settle (latency plan P0.3).
// SAFETY: CCD query FFI over a `Copy` target id, under the held `state` lock.
let departed =
unsafe { wait_target_departed(old_target, Duration::from_millis(400)) };
if !departed {
tracing::debug!(
old_target,
"preempted monitor still in the active CCD set after the departure ceiling"
);
}
}
}
@@ -539,9 +550,10 @@ impl VirtualDisplayManager {
if matches!(inner.slots.get(&slot), Some(SlotState::Active { mon, .. }) if !wudf_alive(mon.wudf_pid))
{
if let Some(SlotState::Active { mon, .. }) = inner.slots.remove(&slot) {
let old_target = mon.target_id;
tracing::warn!(
slot,
old_target = mon.target_id,
old_target,
wudf_pid = mon.wudf_pid,
"virtual monitor's WUDFHost is gone — preempting the dead monitor, recreating"
);
@@ -550,8 +562,9 @@ impl VirtualDisplayManager {
// retired, kept alive; see `DeviceSlot`). `mon` was just removed from the map, so it
// is exclusively owned here — no aliasing.
unsafe { self.teardown_removed(dev, &mut inner, mon) };
// Same async-departure settle as the reconnect preempt above.
thread::sleep(Duration::from_millis(400));
// Same async-departure settle as the reconnect preempt above (verified wait, P0.3).
// SAFETY: CCD query FFI over a `Copy` target id, under the held `state` lock.
let _ = unsafe { wait_target_departed(old_target, Duration::from_millis(400)) };
}
}
@@ -832,8 +845,12 @@ impl VirtualDisplayManager {
/// # Safety
/// Runs the CCD (QueryDisplayConfig / SetDisplayConfig) FFI; call under the `state` lock.
unsafe fn resolve_target_gdi(&self, target_id: u32) -> Option<String> {
for _ in 0..15 {
thread::sleep(Duration::from_millis(200));
// 50 ms sampling (latency plan P0.5): the SAME 3 s per-stage ceilings — the 3-stage ladder
// structure encodes real failure modes (headless auto-activate, integrated-panel clone,
// lid-closed path activation) and is untouched — but a typical activation resolves on an
// early poll, so finer sampling shaves ~150 ms off every stage crossing.
for _ in 0..60 {
thread::sleep(Duration::from_millis(50));
// SAFETY: `resolve_gdi_name` is `unsafe` for its CCD FFI; it takes a plain `Copy` `u32`
// target id by value and returns an owned `String`, so no caller memory is borrowed.
if let Some(n) = unsafe { resolve_gdi_name(target_id) } {
@@ -842,8 +859,8 @@ impl VirtualDisplayManager {
}
// SAFETY: `force_extend_topology` only calls `SetDisplayConfig` (CCD) with no borrowed memory.
unsafe { force_extend_topology() };
for _ in 0..15 {
thread::sleep(Duration::from_millis(200));
for _ in 0..60 {
thread::sleep(Duration::from_millis(50));
// SAFETY: as the resolve loop above.
if let Some(n) = unsafe { resolve_gdi_name(target_id) } {
return Some(n);
@@ -852,8 +869,8 @@ impl VirtualDisplayManager {
// SAFETY: `activate_target_path` runs the CCD query/apply FFI with owned local buffers; the
// `Copy` target id is passed by value, under the `state` lock — the sole topology mutator.
if unsafe { crate::win_display::activate_target_path(target_id) } {
for _ in 0..15 {
thread::sleep(Duration::from_millis(200));
for _ in 0..60 {
thread::sleep(Duration::from_millis(50));
// SAFETY: as the resolve loops above.
if let Some(n) = unsafe { resolve_gdi_name(target_id) } {
return Some(n);
@@ -1015,19 +1032,40 @@ impl VirtualDisplayManager {
);
}
}
thread::sleep(Duration::from_millis(1500)); // let the topology settle before capture opens
// Topology settle before capture opens: verified-state wait (latency plan P0.2) —
// poll until the target's path + active mode are committed, ceiling = the old fixed
// 1500 ms sleep (a rejected mode / slow third-party CCD-lock holder burns the
// ceiling and proceeds, exactly like the sleep it replaces).
let settle_start = std::time::Instant::now();
// SAFETY: CCD/GDI query FFI over a `Copy` target id, under the held `state` lock.
let settled = unsafe {
wait_mode_settled(added.target_id, mode, Duration::from_millis(1500))
};
tracing::info!(
settle_ms = settle_start.elapsed().as_millis() as u64,
verified = settled,
"topology settle (verified-state wait)"
);
// EXPERIMENTAL `pnp_disable_monitors`, second selector (ANY topology): monitors
// that are connected but NOT part of the desktop — the standby TV/monitor the
// deactivated-set selector above structurally misses (it never had an active path
// to deactivate), yet whose periodic standby wake events drive the same Windows
// reaction cascade (rationale in `windows/monitor_devnode.rs`). Runs AFTER the
// settle sleep so the active flags it reads are the committed ones (a display
// still mid-activation from the primary topology's force-EXTEND must not read as
// inactive and get disabled); in Extend the active physical panels are untouched
// by construction. First member only — the sweep is group-scoped like the
// isolate; later members join an already-swept desktop.
// settle so the active flags it reads are the committed ones (a display still
// mid-activation from the primary topology's force-EXTEND must not read as
// inactive and get disabled) — and since the verified wait above only confirms
// OUR target (not a physical still lighting up from force-EXTEND), this opt-in
// sweep keeps the old FULL settle as its floor before reading those flags.
// In Extend the active physical panels are untouched by construction. First
// member only — the sweep is group-scoped like the isolate; later members join
// an already-swept desktop.
if first_member && crate::vdisplay::policy::prefs().pnp_disable_monitors() {
if let Some(rest) =
Duration::from_millis(1500).checked_sub(settle_start.elapsed())
{
thread::sleep(rest);
}
let mut keep = inner.target_ids();
keep.push(added.target_id);
for id in crate::monitor_devnode::disable_connected_inactive(&keep) {
@@ -1109,9 +1147,17 @@ impl VirtualDisplayManager {
);
}
// Let the OS finish the ASYNC monitor departure before the ADD — a back-to-back REMOVE→ADD
// races the teardown and the ADD is rejected under churn (same 400 ms settle as the reconnect
// preempt path).
thread::sleep(Duration::from_millis(400));
// races the teardown and the ADD is rejected under churn. Verified departure wait, ceiling =
// the old fixed 400 ms settle (latency plan P0.3); the driver's ghost-reap ADD retry remains
// the backstop for a departure the CCD reports early.
let depart_start = std::time::Instant::now();
// SAFETY: CCD query FFI over a `Copy` target id, under the held `state` lock.
let departed = unsafe { wait_target_departed(old.target_id, Duration::from_millis(400)) };
tracing::info!(
depart_ms = depart_start.elapsed().as_millis() as u64,
verified = departed,
"re-arrival: old monitor departure settle"
);
// 2. ADD a fresh monitor at the NEW mode, reusing the slot as the preferred (stable) id.
let render_pin = resolve_render_pin();
// SAFETY: `dev` is the live control handle; `render_pin`/`client_hdr` are owned `Copy`/`Option`
@@ -1138,7 +1184,18 @@ impl VirtualDisplayManager {
// the group's first-member restore snapshot.
// SAFETY: CCD FFI over borrowed Copy target ids, under the `state` lock.
unsafe { self.reisolate_after_swap(inner, added.target_id) };
thread::sleep(Duration::from_millis(1500)); // let the topology settle before capture reopens
// Topology settle before capture reopens: verified-state wait, ceiling = the old
// fixed 1500 ms sleep (latency plan P0.2 — the re-arrival twin).
let settle_start = std::time::Instant::now();
// SAFETY: CCD/GDI query FFI over a `Copy` target id, under the held `state` lock.
let settled = unsafe {
wait_mode_settled(added.target_id, mode, Duration::from_millis(1500))
};
tracing::info!(
settle_ms = settle_start.elapsed().as_millis() as u64,
verified = settled,
"re-arrival topology settle (verified-state wait)"
);
}
None => tracing::warn!(
"re-arrival target {} not yet an active display path (auto-activate, EXTEND preset \
@@ -226,6 +226,68 @@ pub(crate) 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));
}
}
/// 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