fix(encode): key the PyroWave plane-import cache on the capturer's ring generation

Completes the partial fix from the previous commit. The Windows PyroWave backend
caches its imported plane images keyed on the D3D11 texture's COM address, and
holds no reference on that texture — so once the capturer recreates its ring,
those addresses can be handed straight back out by the allocator and a
pointer-keyed cache hit returns an image bound to a texture that no longer
exists. Adding the extent to the key ruled out same-address-different-size
aliasing, but a recycle at identical dimensions still aliased.

The capturer already tracks exactly the value needed: `generation`, bumped on
every ring recreate. Plumbed it onto `PyroFrameShare` and the encoder now
flushes every cached import when it changes, which makes cache identity
independent of allocator behaviour rather than a bet against pointer reuse.

Validated on the RTX box: `pyrowave_win_smoke` (forced with `--ignored`, the
only test that actually exercises this path on real hardware) passes all ten
configurations — 1024²/720p/1080p/1440p across SDR/HDR and 4:2:0/4:4:4 — with
correct decoded chroma means, so the steady-state cache-hit path still works.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-19 21:45:14 +02:00
parent 6f52397342
commit b0fbb80fd5
3 changed files with 35 additions and 0 deletions
+6
View File
@@ -52,6 +52,12 @@ pub struct PyroFrameShare {
/// The fence value the capturer signalled after THIS frame's convert. The encoder's Vulkan
/// acquire waits on it, so the wavelet read is ordered after the D3D11 CSC.
pub fence_value: u64,
/// The capturer's ring generation, bumped every time it recreates its texture ring. The
/// PyroWave encoder caches its plane imports keyed on the texture's COM address, which carries
/// no reference — after a recreate those addresses can be recycled by the allocator, so a
/// cached import may describe a texture that no longer exists. The encoder flushes its import
/// cache whenever this changes, making cache identity independent of allocator behaviour.
pub ring_gen: u32,
}
/// A GPU-resident captured texture (the Windows zero-copy path: NVENC/AMF/QSV encode it in place;