fix(encode/windows): a stale PUNKTFUNK_ENCODER pin no longer wedges a conflicting GPU selection

On a hybrid box, picking a GPU in the web console whose vendor contradicts a
host.env PUNKTFUNK_ENCODER pin produced an unrecoverable session: the pin won
backend selection while the adapter followed the console, the wrong-vendor
encoder failed deterministically at submit, the reset ladder burned its 5
in-place rebuilds on it, and the client reconnected into the identical wall
forever (~10 s per cycle, no visible reason).

Three legs:
- windows_resolved_backend() now reconciles: a hardware pin whose vendor
  contradicts the selected GPU is overridden by the adapter-derived backend
  (capture + encode share one adapter, so honoring the pin can only fail);
  open_video warns loudly when a pin loses. The reconciliation is a pure,
  unit-tested table (resolve_windows_backend).
- the QSV wrong-adapter bind is typed TerminalEncoderError, and the stream
  loop's reset ladder ends the session immediately on it instead of feeding a
  deterministic config error 5 futile rebuilds.
- the un-pinned path was already correct (verified on-glass: NVIDIA preference
  + no pin = stable AV1 10-bit HDR on NVENC), so the override simply takes the
  conflict case onto that path.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-26 16:53:19 +02:00
co-authored by Claude Fable 5
parent 36e566052f
commit 751d1de506
3 changed files with 181 additions and 39 deletions
+8 -4
View File
@@ -313,11 +313,15 @@ fn create_session(target_luid: Option<[u8; 8]>) -> Result<(Loader, Session, (u16
.unwrap_or(&impls[0]);
if let Some(want) = target_luid {
if !(chosen.luid_valid && chosen.luid == want) {
bail!(
// Static configuration mismatch — the capture adapter has no Intel VPL
// implementation, so every rebuild re-hits this same wall. The terminal marker
// makes the stream loop end the session at once instead of spending its reset
// budget (5 futile rebuilds, then an opaque loop as the client reconnects).
return Err(anyhow::Error::new(super::TerminalEncoderError).context(
"capture device's adapter is not an Intel VPL implementation (hybrid box? \
point PUNKTFUNK_RENDER_ADAPTER / the web-console GPU preference at the Intel \
adapter for a QSV session)"
);
point PUNKTFUNK_RENDER_ADAPTER / the web-console GPU preference at the \
Intel adapter for a QSV session)",
));
}
}
// SAFETY: `loader.0` is live; `MFXCreateSession` fills `session` only on success and the