feat(windows-host): rotate out-ring on repeat + size HDR ring at open (audit §5.3/§5.4)
§5.3 (C3): repeat_last() now copies the last frame into a FRESH rotated out-ring slot instead of re-handing last_present's slot, so a repeat (static desktop) never re-hands a slot still encoding under pipeline_depth>1. OUT_RING(3) > max depth(2) keeps the rotated slot free — the out-ring rotation contract now holds for repeats too, not just the synchronous-loop assumption. §5.4 (C4): when enabling advanced color for a 10-bit client, trust set_advanced_color success and size the ring FP16 directly, instead of racing the advanced_color_enabled poll (which could size SDR while the driver composes FP16 -> format mismatch -> an immediate ring recreate + dropped first frames). Verified: host clippy (nvenc) clean on the RTX box. On-glass to confirm: HDR-client first-frame + static-desktop pipelining. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -371,12 +371,18 @@ impl IddPushCapturer {
|
|||||||
// SDR-only client leaves the display alone (and still gets a tone-mapped picture, never a freeze,
|
// SDR-only client leaves the display alone (and still gets a tone-mapped picture, never a freeze,
|
||||||
// if the user does enable HDR).
|
// if the user does enable HDR).
|
||||||
unsafe {
|
unsafe {
|
||||||
if client_10bit && crate::vdisplay::sudovda::set_advanced_color(target.target_id, true)
|
// If we ENABLE advanced color for a 10-bit client, trust it (the driver will compose FP16) and
|
||||||
{
|
// size the ring FP16 directly — don't race the advanced_color_enabled poll, which may not have
|
||||||
|
// settled within 250 ms and would size the ring SDR while the driver composes FP16 → a format
|
||||||
|
// mismatch → an immediate ring recreate + dropped first frames (audit §5.4).
|
||||||
|
let enabled_hdr =
|
||||||
|
client_10bit && crate::vdisplay::sudovda::set_advanced_color(target.target_id, true);
|
||||||
|
if enabled_hdr {
|
||||||
// Let the colorspace change settle before the driver composes + we size the ring.
|
// Let the colorspace change settle before the driver composes + we size the ring.
|
||||||
std::thread::sleep(Duration::from_millis(250));
|
std::thread::sleep(Duration::from_millis(250));
|
||||||
}
|
}
|
||||||
let display_hdr = crate::vdisplay::sudovda::advanced_color_enabled(target.target_id);
|
let display_hdr =
|
||||||
|
enabled_hdr || crate::vdisplay::sudovda::advanced_color_enabled(target.target_id);
|
||||||
let ring_fmt = if display_hdr {
|
let ring_fmt = if display_hdr {
|
||||||
DXGI_FORMAT_R16G16B16A16_FLOAT
|
DXGI_FORMAT_R16G16B16A16_FLOAT
|
||||||
} else {
|
} else {
|
||||||
@@ -810,14 +816,28 @@ impl IddPushCapturer {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn repeat_last(&self) -> Option<CapturedFrame> {
|
fn repeat_last(&mut self) -> Option<CapturedFrame> {
|
||||||
self.last_present.as_ref().map(|(tex, pf)| CapturedFrame {
|
// Copy the last presented frame into a FRESH rotated out-ring slot so a repeat (static desktop, no
|
||||||
|
// new driver frame) never re-hands a slot that may still be encoding under pipeline_depth>1 — the
|
||||||
|
// out-ring rotation IS the texture-ownership contract, and repeats must honor it too (audit §5.3).
|
||||||
|
// OUT_RING(3) > the max pipeline_depth(2) guarantees the rotated slot is not in flight.
|
||||||
|
let (src, pf) = self.last_present.clone()?;
|
||||||
|
let i = self.out_idx;
|
||||||
|
let dst = self.out_ring.get(i)?.0.clone();
|
||||||
|
// SAFETY: GPU copy on the owning thread's immediate context; src/dst are our out-ring textures of
|
||||||
|
// identical format/size (src is a previous out-ring slot; dst the next).
|
||||||
|
unsafe {
|
||||||
|
self.context.CopyResource(&dst, &src);
|
||||||
|
}
|
||||||
|
self.out_idx = (i + 1) % self.out_ring.len();
|
||||||
|
self.last_present = Some((dst.clone(), pf));
|
||||||
|
Some(CapturedFrame {
|
||||||
width: self.width,
|
width: self.width,
|
||||||
height: self.height,
|
height: self.height,
|
||||||
pts_ns: now_ns(),
|
pts_ns: now_ns(),
|
||||||
format: *pf,
|
format: pf,
|
||||||
payload: FramePayload::D3d11(D3d11Frame {
|
payload: FramePayload::D3d11(D3d11Frame {
|
||||||
texture: tex.clone(),
|
texture: dst,
|
||||||
device: self.device.clone(),
|
device: self.device.clone(),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user