test(pf-encode): re-point the cpu_img size-change smoke at the CSC guard's contract
arch / build-publish (push) Failing after 58s
ci / web (push) Successful in 51s
ci / docs-site (push) Successful in 53s
android / android (push) Failing after 7m59s
ci / bench (push) Failing after 4m9s
ci / rust-arm64 (push) Failing after 6m44s
ci / rust (push) Failing after 6m45s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 12s
decky / build-publish (push) Successful in 24s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 12s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 9s
docker / build-push (ci, ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 8s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 7s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 47s
apple / swift (push) Successful in 5m28s
deb / build-publish (push) Successful in 9m25s
windows-host / package (push) Successful in 10m44s
docker / deploy-docs (push) Successful in 31s
docker / build-push-arm64cross (push) Successful in 5m33s
deb / build-publish-client-arm64 (push) Successful in 8m20s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Failing after 7m41s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Failing after 7m4s
deb / build-publish-host (push) Successful in 12m7s
apple / screenshots (push) Successful in 25m11s
arch / build-publish (push) Failing after 58s
ci / web (push) Successful in 51s
ci / docs-site (push) Successful in 53s
android / android (push) Failing after 7m59s
ci / bench (push) Failing after 4m9s
ci / rust-arm64 (push) Failing after 6m44s
ci / rust (push) Failing after 6m45s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 12s
decky / build-publish (push) Successful in 24s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 12s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 9s
docker / build-push (ci, ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 8s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 7s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 47s
apple / swift (push) Successful in 5m28s
deb / build-publish (push) Successful in 9m25s
windows-host / package (push) Successful in 10m44s
docker / deploy-docs (push) Successful in 31s
docker / build-push-arm64cross (push) Successful in 5m33s
deb / build-publish-client-arm64 (push) Successful in 8m20s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Failing after 7m41s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Failing after 7m4s
deb / build-publish-host (push) Successful in 12m7s
apple / screenshots (push) Successful in 25m11s
vulkan_cpu_img_survives_a_source_size_change drove MISMATCHED source sizes through the then-lenient CSC arm as its vehicle for the staging cache hazard (format-only-keyed cpu_img → OOB copy while submit said Ok). e3354b6d's guard — correctly the equality check every sibling arm always had, against the MODE, not the coded extent, so the padded render-vs-coded tolerance in the direct arms is untouched — makes that scenario unrepresentable through submit and broke the test on main (.25 layers baseline read 13/13 instead of 14/12). Replaced by vulkan_csc_refuses_a_mismatched_source: refusal pinned in BOTH directions, plus the property that actually needs proving — a refused submit does not WEDGE the session (the bail lands after step 1's frame-type bookkeeping; the next well-sized frame must still encode, and an AU must come out). Verified on the 780M under validation layers: 8/8 vulkan tests, full-suite baseline restored to 14/12. The WP4.2 size-keyed staging stays as belt-and-braces; the hazard it fixed is now structurally unreachable through submit. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -4486,44 +4486,50 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
/// A CPU-capture source that CHANGES SIZE mid-session must not copy past the cached staging
|
||||
/// image. `ensure_cpu_rgb` keys that image on (format, width, height); when it was keyed on
|
||||
/// format alone the image kept the FIRST frame's size while `cmd_copy_buffer_to_image` used the
|
||||
/// current frame's extent, so a same-format size increase wrote out of bounds — and `submit`
|
||||
/// still returned `Ok`, so nothing upstream noticed.
|
||||
///
|
||||
/// The out-of-bounds copy is only *observable* through the Vulkan validation layers, so run this
|
||||
/// as: `VK_LOADER_LAYERS_ENABLE='*validation*' cargo test ... -- --ignored`. Confirmed on RADV
|
||||
/// PHOENIX 2026-07-25: 8 x VUID-vkCmdCopyBufferToImage-imageSubresource-07971 before the fix
|
||||
/// ("extent.width (512) exceeds imageSubresource width extent (128)"), zero after.
|
||||
/// The CSC arm REFUSES a source that doesn't match the session mode (the e3354b6d guard —
|
||||
/// the check every sibling arm always had; a clamped-texelFetch mismatch used to stream a
|
||||
/// silently cropped/edge-padded picture). This test previously DROVE mismatched sizes through
|
||||
/// the lenient arm to exercise the per-slot `cpu_img` staging across a size change (the
|
||||
/// format-only-keyed cache wrote out of bounds while `submit` returned `Ok`); the guard makes
|
||||
/// that scenario unrepresentable through `submit`, structurally retiring the hazard — the
|
||||
/// size-keyed staging from that fix stays as belt-and-braces. What's left to pin:
|
||||
/// refusal in BOTH directions, and that a refused submit does not WEDGE the session — the
|
||||
/// bail happens after step 1's frame-type bookkeeping, so "the next well-sized frame still
|
||||
/// encodes" is a real property, not a formality (the host routes the error to its
|
||||
/// encoder-rebuild path and the session must be able to continue if that path retries).
|
||||
#[test]
|
||||
#[ignore = "needs a real VK_KHR_video_encode_h265 device; meaningful only under validation layers"]
|
||||
fn vulkan_cpu_img_survives_a_source_size_change() {
|
||||
// CSC mode (rgb=false) — that is the arm where the image is sized to the SOURCE frame.
|
||||
fn vulkan_csc_refuses_a_mismatched_source() {
|
||||
// CSC mode (rgb=false) — the arm the guard covers.
|
||||
let mut enc = VulkanVideoEncoder::open_opts(Codec::H265, 512, 512, 60, 10_000_000, false)
|
||||
.expect("open");
|
||||
// `cpu_img` is cached PER RING SLOT, so the small frames must first populate every slot;
|
||||
// only when the ring wraps does a slot holding a 128x128 image get a 512x512 copy.
|
||||
eprintln!("phase 1: 8x 128x128 — populates every ring slot with a 128x128 cpu_img");
|
||||
for i in 0..8u64 {
|
||||
enc.submit_indexed(&cpu_frame(512, 512, 0, [40, 40, 200, 255]), 0)
|
||||
.expect("well-sized baseline");
|
||||
while enc.poll().expect("poll").is_some() {}
|
||||
// Smaller AND larger both refuse — the guard is equality on the MODE (render size), not
|
||||
// a ceiling; the render-vs-CODED padding tolerance lives in the direct arms, untouched.
|
||||
let e = enc
|
||||
.submit_indexed(&cpu_frame(128, 128, 16_666_667, [200, 40, 40, 255]), 1)
|
||||
.expect_err("smaller source must refuse");
|
||||
assert!(e.to_string().contains("mismatched"), "{e:#}");
|
||||
let e = enc
|
||||
.submit_indexed(&cpu_frame(640, 640, 33_333_334, [200, 40, 40, 255]), 2)
|
||||
.expect_err("larger source must refuse");
|
||||
assert!(e.to_string().contains("mismatched"), "{e:#}");
|
||||
// The refusals must not wedge the session: a well-sized frame still encodes and an AU
|
||||
// still comes out the other end.
|
||||
let mut got_au = false;
|
||||
for i in 3..11u64 {
|
||||
enc.submit_indexed(
|
||||
&cpu_frame(128, 128, i * 16_666_667, [40, 40, 200, 255]),
|
||||
&cpu_frame(512, 512, i * 16_666_667, [40, 200, 40, 255]),
|
||||
i as u32,
|
||||
)
|
||||
.expect("submit small");
|
||||
while enc.poll().expect("poll").is_some() {}
|
||||
.expect("well-sized after refusal");
|
||||
while let Ok(Some(_)) = enc.poll() {
|
||||
got_au = true;
|
||||
}
|
||||
eprintln!("phase 2: 8x 512x512 — SAME format, so each slot REUSES its 128x128 image");
|
||||
for i in 8..16u64 {
|
||||
let r = enc.submit_indexed(
|
||||
&cpu_frame(512, 512, i * 16_666_667, [200, 40, 40, 255]),
|
||||
i as u32,
|
||||
);
|
||||
r.expect("submit after the source grew");
|
||||
while matches!(enc.poll(), Ok(Some(_))) {}
|
||||
}
|
||||
let _ = enc.flush();
|
||||
while matches!(enc.poll(), Ok(Some(_))) {}
|
||||
assert!(got_au, "no AU after the refused submits — session wedged");
|
||||
eprintln!("done — under validation layers this run must report ZERO VUID errors");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user