feat(nvenc): default-on the Linux direct-SDK NVENC path
ci / web (push) Successful in 45s
ci / docs-site (push) Successful in 1m5s
decky / build-publish (push) Successful in 20s
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 7s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 7s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 8s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 8s
apple / swift (push) Successful in 4m49s
ci / bench (push) Successful in 6m13s
docker / deploy-docs (push) Successful in 20s
windows-host / package (push) Successful in 14m19s
arch / build-publish (push) Successful in 20m25s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 18m28s
android / android (push) Successful in 21m8s
deb / build-publish (push) Successful in 20m53s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 20m25s
ci / rust (push) Successful in 24m14s
apple / screenshots (push) Successful in 21m0s
ci / web (push) Successful in 45s
ci / docs-site (push) Successful in 1m5s
decky / build-publish (push) Successful in 20s
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 7s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 7s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 8s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 8s
apple / swift (push) Successful in 4m49s
ci / bench (push) Successful in 6m13s
docker / deploy-docs (push) Successful in 20s
windows-host / package (push) Successful in 14m19s
arch / build-publish (push) Successful in 20m25s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 18m28s
android / android (push) Successful in 21m8s
deb / build-publish (push) Successful in 20m53s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 20m25s
ci / rust (push) Successful in 24m14s
apple / screenshots (push) Successful in 21m0s
On-glass validated 2026-07-12 on an RTX 5070 Ti host with a real Steam Deck client (NV12 4:2:0, 1280x800@90): real nvEncInvalidateRefFrames landed 73/73 as clean P-frame recovery anchors (never IDR), losses consistently ~2 frames deep — well inside the 5-frame DPB. That is the loss recovery the libav hevc_nvenc path cannot express, so make the direct path the default on NVIDIA. PUNKTFUNK_NVENC_DIRECT=0 (also false/no/off) is now the libav escape hatch. Still gated on a CUDA capture payload — the `cuda` check in open_nvenc_probed keeps AMD/Intel on VAAPI regardless, and the NVENC/CUDA entry points stay dlopen'd at runtime (no new DT_NEEDED), so non-NVIDIA hosts are unaffected. Packaging comments updated to match. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -757,15 +757,16 @@ fn open_nvenc_probed(
|
||||
bit_depth: u8,
|
||||
chroma: ChromaFormat,
|
||||
) -> Result<Box<dyn Encoder>> {
|
||||
// Direct-SDK NVENC (design/linux-direct-nvenc.md): opt-in via PUNKTFUNK_NVENC_DIRECT, and only
|
||||
// for a CUDA capture payload (it registers CUDADEVICEPTR inputs — a CPU/dmabuf frame can't feed
|
||||
// it, so those keep the libav path). It self-clamps the bitrate internally (its own level-ceiling
|
||||
// binary search at session open), so it skips the probe-loop stepping below.
|
||||
// Direct-SDK NVENC (design/linux-direct-nvenc.md): the DEFAULT on NVIDIA, and only for a CUDA
|
||||
// capture payload (it registers CUDADEVICEPTR inputs — a CPU/dmabuf frame can't feed it, so those
|
||||
// keep the libav path; and `cuda` is false on AMD/Intel, so they stay on VAAPI). Set
|
||||
// PUNKTFUNK_NVENC_DIRECT=0 to fall back to libav. It self-clamps the bitrate internally (its own
|
||||
// level-ceiling binary search at session open), so it skips the probe-loop stepping below.
|
||||
#[cfg(feature = "nvenc")]
|
||||
if cuda && nvenc_direct_enabled() {
|
||||
tracing::info!(
|
||||
codec = codec.nvenc_name(),
|
||||
"Linux direct-SDK NVENC enabled (PUNKTFUNK_NVENC_DIRECT) — real RFI + recovery anchor"
|
||||
"Linux direct-SDK NVENC (real RFI + recovery anchor) — set PUNKTFUNK_NVENC_DIRECT=0 for libav"
|
||||
);
|
||||
return Ok(Box::new(nvenc_cuda::NvencCudaEncoder::open(
|
||||
codec,
|
||||
@@ -816,15 +817,17 @@ fn open_nvenc_probed(
|
||||
Err(last.unwrap_or_else(|| anyhow::anyhow!("encoder open failed at every probed bitrate")))
|
||||
}
|
||||
|
||||
/// Whether the operator opted into the direct-SDK NVENC path (`PUNKTFUNK_NVENC_DIRECT` truthy).
|
||||
/// OFF by default until the on-glass matrix (design/linux-direct-nvenc.md §9) is green; then the
|
||||
/// default flips and this becomes the libav escape hatch (`=0`). Only meaningful with `--features
|
||||
/// nvenc`.
|
||||
/// Whether the direct-SDK NVENC path is active. **Default ON** — on-glass validated 2026-07-12:
|
||||
/// real RFI landed 73/73 as clean P-frame recovery anchors (never IDR) on an RTX host with a real
|
||||
/// Steam Deck client (design/linux-direct-nvenc.md §9). `PUNKTFUNK_NVENC_DIRECT=0` (also `false`/
|
||||
/// `no`/`off`) is the libav escape hatch. Only consulted for a CUDA capture payload on an NVIDIA
|
||||
/// host — the `cuda` gate in `open_nvenc_probed` keeps AMD/Intel on VAAPI regardless — and only
|
||||
/// with `--features nvenc`.
|
||||
#[cfg(all(target_os = "linux", feature = "nvenc"))]
|
||||
fn nvenc_direct_enabled() -> bool {
|
||||
std::env::var("PUNKTFUNK_NVENC_DIRECT")
|
||||
.map(|v| matches!(v.trim(), "1" | "true" | "yes" | "on"))
|
||||
.unwrap_or(false)
|
||||
.map(|v| !matches!(v.trim(), "0" | "false" | "no" | "off"))
|
||||
.unwrap_or(true)
|
||||
}
|
||||
|
||||
/// Cheap, side-effect-free NVIDIA-presence probe for the `auto` backend selector: the NVIDIA
|
||||
|
||||
@@ -71,7 +71,8 @@ build() {
|
||||
# anchor on Linux NVIDIA; design/linux-direct-nvenc.md). AMD/Intel-SAFE: the NVENC/CUDA entry
|
||||
# points are dlopen'd at RUNTIME (libloading), never link-imported — `objdump -p` shows the same
|
||||
# DT_NEEDED as a plain build (no libcuda/libnvidia-encode), so the binary starts fine driver-less
|
||||
# and only touches NVIDIA when a CUDA capture frame + PUNKTFUNK_NVENC_DIRECT actually select it.
|
||||
# and only touches NVIDIA on a CUDA capture frame (default on NVIDIA; PUNKTFUNK_NVENC_DIRECT=0
|
||||
# opts back to libav). AMD/Intel never reach it — the `cuda` gate leaves them on VAAPI.
|
||||
cargo build --release --locked --features punktfunk-host/nvenc \
|
||||
-p punktfunk-host -p punktfunk-client-linux -p punktfunk-client-session -p punktfunk-tray
|
||||
# Management web console (opt-in): the Nitro `bun`-preset .output bundle (Bun.serve TLS),
|
||||
|
||||
@@ -178,7 +178,8 @@ export PUNKTFUNK_BUILD_VERSION="%{version}-%{release}"
|
||||
# --features punktfunk-host/nvenc: the direct-SDK NVENC path (real RFI + recovery anchor on Linux
|
||||
# NVIDIA; design/linux-direct-nvenc.md). AMD/Intel-safe — the NVENC/CUDA entry points are dlopen'd
|
||||
# at runtime (no link-time dep; __requires_exclude already drops libcuda), so the binary starts
|
||||
# driver-less; the encoder is only built for a CUDA frame + PUNKTFUNK_NVENC_DIRECT, never on VAAPI.
|
||||
# driver-less; the encoder engages only on a CUDA frame (default on NVIDIA; PUNKTFUNK_NVENC_DIRECT=0
|
||||
# opts back to libav) — the `cuda` gate keeps AMD/Intel on VAAPI regardless.
|
||||
cargo build --release --locked --features punktfunk-host/nvenc \
|
||||
-p punktfunk-host -p punktfunk-client-linux -p punktfunk-client-session -p punktfunk-tray
|
||||
|
||||
|
||||
Reference in New Issue
Block a user