From 1573a9876b66a92d98dfc9d7c7b6c511b183f967 Mon Sep 17 00:00:00 2001 From: enricobuehler Date: Thu, 6 Aug 2026 12:34:31 +0200 Subject: [PATCH] fix(client): a d3d11va soak could not tell which rung it soaked MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `stats:` line's decode-path tag is derived from the DecodedImage variant, and both D3D11VA rungs deliver DecodedImage::D3d11 — they share the hand-off ring on purpose. So a native-d3d11va session and an FFmpeg-d3d11va session emitted a byte-identical tag, and nothing downstream could tell them apart. The native Vulkan rung never had this: it carries its own variant, hence its own `native-vulkan` tag. That is not cosmetic, and it was found the only way it could be — by running the rung on glass and having to grep the log to prove which one had answered. A native pin that fails to initialise falls through to the FFmpeg rung by design; the line it then emits is exactly the line the native rung would have emitted. M5's owed soak and M9's vendor-matrix bake both rest on attributing a session to a rung, and until now the machine-readable half of that evidence could not do it. This project has already shipped one measurement that could not tell "clean" from "unmeasured"; this is the same shape. D3d11Frame now records which rung wrote the surface, keyed off the pin constant itself rather than a second field the two rungs could set inconsistently — the native rung passes DECODER_PIN into the hand-off and nothing else does. The stats line stays additive for every shipping session: the only value that changes belongs to a rung that is pin-only and deliberately absent from the automatic ladder, and the Windows shell passes the line through opaquely rather than matching on the tag. Verified on glass on .173, both directions: pinned native-d3d11va gives 85 windows tagged `native-d3d11va` and 0 plain, pinned d3d11va gives 64 plain and 0 native, zero errors either way. Gates: clippy -D warnings on Windows, the Linux container's clippy/tests/workspace check, rustfmt. --- crates/pf-client-core/src/session.rs | 13 ++++++++++++- crates/pf-client-core/src/video_d3d11.rs | 20 ++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/crates/pf-client-core/src/session.rs b/crates/pf-client-core/src/session.rs index e8be2f8a..cc5708d9 100644 --- a/crates/pf-client-core/src/session.rs +++ b/crates/pf-client-core/src/session.rs @@ -893,8 +893,19 @@ fn pump( #[cfg(target_os = "linux")] DecodedImage::Dmabuf(_) => "vaapi", DecodedImage::VkFrame(_) => "vulkan", + // Both D3D11VA rungs deliver this variant — they share the + // hand-off ring on purpose — so the frame carries which one + // wrote it. Without that, a native session and an FFmpeg + // session emit the same tag and no soak log can tell them + // apart (`D3d11Frame::native`). #[cfg(windows)] - DecodedImage::D3d11(_) => "d3d11va", + DecodedImage::D3d11(f) => { + if f.native { + "native-d3d11va" + } else { + "d3d11va" + } + } #[cfg(all(any(target_os = "linux", windows), feature = "pyrowave"))] DecodedImage::PyroWave(_) => "pyrowave", DecodedImage::NativeVk(_) => "native-vulkan", diff --git a/crates/pf-client-core/src/video_d3d11.rs b/crates/pf-client-core/src/video_d3d11.rs index 354477e3..f874aceb 100644 --- a/crates/pf-client-core/src/video_d3d11.rs +++ b/crates/pf-client-core/src/video_d3d11.rs @@ -127,6 +127,22 @@ pub struct D3d11Frame { /// presenter-side import cache could never alias a stale handle. Informational today /// (the presenter imports per frame). pub generation: u32, + /// Which D3D11VA rung wrote the surface this ring slot was converted from: + /// [`crate::video_d3d11_native`] (`true`) or this module's libavcodec one (`false`). + /// + /// Both rungs deliver `DecodedImage::D3d11`, because they deliberately share this + /// hand-off ring — so without this flag the `stats:` line's decode-path tag reads + /// `d3d11va` for both and nothing downstream can tell them apart. The native Vulkan + /// rung never had that problem: it has its own `DecodedImage` variant, hence its own + /// `native-vulkan` tag. + /// + /// That gap is not cosmetic. A native pin that fails to initialise falls through to + /// the FFmpeg rung by design, and the line it then emits is byte-identical to the one + /// the native rung would have emitted — so a soak or a vendor-matrix bake could + /// attribute an entire session to a rung that never ran. This program has already + /// shipped one measurement that could not tell "clean" from "unmeasured"; this is the + /// same shape and it is closed here rather than in the analysis of a soak log. + pub native: bool, } // --- FFmpeg hwcontext_d3d11va ABI (repr(C) mirrors, same as the legacy decoder) -------------- @@ -794,6 +810,10 @@ impl HandoffRing { keyframe, handle, generation, + // Identity by the pin constant itself, not by a second field the two rungs + // could set inconsistently: the native rung passes `DECODER_PIN` here and + // nothing else does. + native: decoder == crate::video_d3d11_native::DECODER_PIN, }) } }