ci / web (push) Successful in 1m4s
ci / docs-site (push) Successful in 1m8s
apple / swift (push) Successful in 1m22s
decky / build-publish (push) Successful in 19s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 9s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 8s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 7s
docker / build-push (ci, ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 9s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 9s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 45s
ci / bench (push) Successful in 6m59s
windows-host / package (push) Failing after 10m45s
deb / build-publish (push) Successful in 11m9s
android / android (push) Successful in 12m59s
deb / build-publish-host (push) Successful in 11m59s
arch / build-publish (push) Successful in 13m21s
apple / screenshots (push) Successful in 16m48s
ci / rust (push) Successful in 22m37s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 20m17s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 20m39s
docker / deploy-docs (push) Successful in 28s
`linux_native_nv12_ok` is the verdict the host threads into capture negotiation
(session_plan -> OutputFormat::nv12_native -> ZeroCopyPolicy::native_nv12_session
-> pf-capture's prefer_native_nv12). Its doc claimed "the backend must be eligible
to open", but it asked only three static questions — codec is H265/AV1, an env
default, and a pref denylist — and never whether this GPU has an encode queue at
all. It could not: vulkan_video.rs exposed no probe.
That verdict is uniquely load-bearing. Once the producer has been asked for
two-plane NV12 there is NO fallback: open_video deliberately makes a failed Vulkan
open FATAL for an NV12 capture rather than degrading to libav VAAPI, because VAAPI
would import that buffer as packed RGB and stream silent garbage. So on a gamescope
host whose Mesa lacks Vulkan HEVC encode the session died at its first frame, while
the same host with PUNKTFUNK_PIPEWIRE_NV12=0 streamed fine — and the comment
promising such a device "degrades gracefully to the old backend rather than
breaking the stream" was stale on every gamescope host.
Two changes:
1. The gate. The third conjunct was a denylist of the EXPLICIT prefs that skip
Vulkan Video ("nvenc"|"nvidia"|"cuda"|"pyrowave"), which silently missed the one
that matters: the DEFAULT encoder_pref is "", and "" resolves to auto, which on
an NVIDIA box opens NVENC. A stock NVIDIA host passed this gate. It now consults
`linux_zero_copy_is_vaapi`, which layers the pref on top of the same auto
decision open_video makes — what the note on `linux_auto_is_vaapi` says a
capability probe must use, and what the downstream consumer of this very verdict
already uses. This alone was worth fixing; a probe added behind the old gate
would have opened a Vulkan instance on every NVIDIA handshake.
2. The probe. `vulkan_video::probe_encode_support` runs the FIRST check open_inner
performs and hard-fails on — the physical-device + encode-queue-family scan for
this codec's op — and nothing more, so it is provably no stricter than the open
and can never talk a working host out of the fast path. The scan is now a shared
`find_encode_device` used by BOTH, because a probe that mirrors a dispatch goes
stale the first time the dispatch grows a case (the failure open_video's
backend-label note already records). Cost: one instance plus physical-device
queries — no logical device, no video session, no VRAM — cached per (selected
GPU, codec) in the can_encode_10bit idiom, with the probe run outside the lock.
Per codec, not once: codec_op_for selects a different queue-family bit for AV1,
and HEVC-encode-without-AV1-encode is the common VCN/ANV configuration.
Later stages (create_device, create_video_session, the capability query) can still
fail for reasons the probe does not model. Those are harmless: the capture format
is only committed once the probe says yes, and everything after keeps the ordinary
packed-RGB negotiation.
Verified `-D warnings --all-targets` + tests on Linux (default; shipped
nvenc+vulkan-encode+pyrowave). The behaviour needs an on-glass check on the bazzite
RADV box — including the negative case, which `RADV_DEBUG=novideo` reproduces.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>