fix(client): a d3d11va soak could not tell which rung it soaked

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.
This commit is contained in:
2026-08-06 12:34:31 +02:00
parent 3041d9bb43
commit 1573a9876b
2 changed files with 32 additions and 1 deletions
+12 -1
View File
@@ -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",
+20
View File
@@ -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,
})
}
}