feat(client): native Vulkan decode joins the automatic ladder, above FFmpeg-Vulkan

Closes M2. The 2026-08-05 ladder decision: WP-D shut with bit-exact
parity vs libavcodec (250/250 AUs on RADV, AMD-proprietary and NVIDIA)
and a 92-minute clean soak, and the program's goal is dropping FFmpeg
from the client — so on H.264 sessions where caps pass, auto now tries
pf-vkdecode FIRST, exactly where the ladder would reach FFmpeg-Vulkan.
No bake period.

native_vulkan_gate widens from by-name-only to the auto family
(auto/""/hardware); the vendor-first rungs are untouched (Linux
Intel/unknown still VAAPI-first, Windows Intel/unknown still
D3D11VA-first — NVIDIA and ALL AMD go native first). A native INIT
failure or caps refusal logs and falls through to FFmpeg-Vulkan, so
admission can't cost a session its decoder at start; runtime error
streaks ride the existing demotion machinery unchanged (past
FFmpeg-Vulkan to VAAPI/D3D11VA/software — a native→FFmpeg-Vulkan
runtime rung is deliberately absent, FFmpeg is on its way out).
PUNKTFUNK_DECODER=native-vulkan stays as the explicit pin; vulkan
keeps naming the FFmpeg backend specifically. A native_tried guard
keeps a failed pin init from re-attempting construction in auto.

Review round 8 (adversarial): no blocking code defect — no demote
bounce-back (Decoder::new is session-start-only; demotion mutates in
place), no double attempt, no cfg imbalance. 5 findings fixed: two doc
overclaims ("nothing regresses" now scoped to init; the ladder
enumerations no longer claim desktop-AMD Linux is VAAPI-first —
prefer_vulkan_first is vendor-wide), stale opt-in claims in Cargo.toml,
stale user-facing ladder text (console-ui row, trust.rs decoder field,
session README incl. the env-knob list), and the gate test now pins the
H264 codec-op bit to the literal 0x1 so a typo'd constant can't make
native silently never engage.

Gates: fmt clean; container clippy -D warnings zero for pf-client-core +
pf-presenter + pf-vkdecode; container tests green (pf-client-core lib +
pf-vkdecode + pf-bitstream); pf-console-ui check clean; mac
pf-vkdecode/pf-bitstream/cros-codecs 167 tests green.

On-glass sanity CLOSED 2026-08-05 ~22:10 UTC on .173 (4090, coincide
mode), decoder=auto and NO env var: the ladder picked native on its
own ("pf-vkdecode auto rung" log line), 525/526 stats windows on
native-vulkan over ~8m46s / 31550 frames, fps 0/59.4/61 with 6
windows <55 incl. startup zeros, bad-signature grep over the whole
log EMPTY, zero TDR events, host service Running after teardown.
This commit is contained in:
2026-08-06 00:12:35 +02:00
parent cf5db2d485
commit 370b0ab494
7 changed files with 160 additions and 73 deletions
+7 -6
View File
@@ -49,18 +49,19 @@ path + per-stage latency equation); any tier but Off also emits the stdout mirro
`--no-default-features` is the ~5 MB power-user build — same streaming, stats on stdout
only, no Skia anywhere in the dependency tree.
Decode follows the Settings preference (auto: Vulkan Video → VAAPI → software on Linux,
Vulkan Video → D3D11VA → software on Windows): FFmpeg's Vulkan Video decoder runs on the
presenter's own device where the stack supports it (every vendor, zero copy); VAAPI
dmabufs import per-plane elsewhere (D3D11VA textures on Windows); software is the
universal fallback. 10-bit Main10 and HDR10 are advertised
Decode follows the Settings preference (auto is vendor-ordered: hardware Vulkan Video →
VAAPI → software on Linux, hardware Vulkan Video → D3D11VA → software on Windows, with
VAAPI/D3D11VA first on Intel; on H.264 the native pf-vkdecode Vulkan decoder is tried
immediately before FFmpeg-Vulkan): the Vulkan decoders run on the presenter's own
device where the stack supports it (every vendor, zero copy); VAAPI dmabufs import
per-plane elsewhere (D3D11VA textures on Windows); software is the universal fallback. 10-bit Main10 and HDR10 are advertised
(`VIDEO_CAP_10BIT|HDR`): P010 decodes through all three paths, and PQ streams present
on an HDR10/ST.2084 swapchain when the desktop offers one (KDE HDR, gamescope) or
tone-map in-shader to SDR when it doesn't (`PUNKTFUNK_TONEMAP_PEAK` tunes the rolloff,
default ≈1000 nits). The host still gates the upgrade behind its `PUNKTFUNK_10BIT`
policy.
Debug/bisect knobs: `PUNKTFUNK_DECODER=vulkan|vaapi|d3d11va|software`, `PUNKTFUNK_PRESENT_MODE=
Debug/bisect knobs: `PUNKTFUNK_DECODER=native-vulkan|vulkan|vaapi|d3d11va|software`, `PUNKTFUNK_PRESENT_MODE=
mailbox|fifo|immediate|fifo_relaxed` (default MAILBOX, FIFO where the surface offers no
MAILBOX — AMD on Windows), `PUNKTFUNK_VK_DEVICE=<index>` (multi-GPU), and
`PUNKTFUNK_HW_FAULT=import` (fault every VAAPI dmabuf import — proves the three-strike
+3 -2
View File
@@ -17,8 +17,9 @@ repository.workspace = true
punktfunk-core = { path = "../punktfunk-core", features = ["quic"] }
# FFmpeg's Vulkan hwcontext surface (Vulkan Video decode on the presenter's device).
pf-ffvk = { path = "../pf-ffvk" }
# Native Vulkan Video H.264 decode (WP-C of the native-decode program): the opt-in
# `PUNKTFUNK_DECODER=native-vulkan` backend in video_vk_native.rs, running pf-vkdecode's
# Native Vulkan Video H.264 decode (WP-C of the native-decode program): auto's rung
# immediately above FFmpeg-Vulkan (2026-08-05 ladder decision), also pinnable via
# `PUNKTFUNK_DECODER=native-vulkan` — video_vk_native.rs, running pf-vkdecode's
# VkH264Decoder on the presenter's shared device.
pf-vkdecode = { path = "../pf-vkdecode" }
async-channel = "2"
+3 -2
View File
@@ -78,8 +78,9 @@ mod video_libav;
#[cfg(target_os = "linux")]
mod video_vaapi;
// Native Vulkan Video H.264 decode (WP-C of the native-decode program): pf-vkdecode's
// decoder on the presenter's shared device, behind the `PUNKTFUNK_DECODER=native-vulkan`
// runtime opt-in only.
// decoder on the presenter's shared device — auto's rung immediately above
// FFmpeg-Vulkan (2026-08-05 ladder decision; the program is dropping FFmpeg from the
// client), also pinnable via `PUNKTFUNK_DECODER=native-vulkan`.
#[cfg(any(target_os = "linux", windows))]
mod video_vk_native;
#[cfg(any(target_os = "linux", windows))]
+4 -2
View File
@@ -937,8 +937,10 @@ pub struct Settings {
/// preference — the host honors it when it can emit it, else falls back to the best shared codec.
#[serde(default = "default_codec")]
pub codec: String,
/// Video decoder preference: `"auto"` (Vulkan Video → VAAPI → software),
/// `"vulkan"`, `"vaapi"`, `"software"`.
/// Video decoder preference: `"auto"` (vendor-ordered hardware ladder — on H.264
/// the native pf-vkdecode rung sits immediately above FFmpeg-Vulkan; then
/// VAAPI/D3D11VA, then software — see `video::Decoder::new` for the per-vendor
/// order), `"vulkan"`, `"vaapi"`, `"d3d11va"`, `"native-vulkan"`, `"software"`.
/// The `PUNKTFUNK_DECODER` env var overrides this (see `video::Decoder::new`).
pub decoder: String,
/// Decode/present GPU (multi-GPU boxes): the adapter's marketing name, as the WinUI
+137 -57
View File
@@ -1,13 +1,18 @@
//! Video decode: reassembled HEVC access units → frames for the presenter.
//!
//! Three backends, picked at session start (auto is vendor-ordered on BOTH desktop OSes —
//! see [`VulkanDecodeDevice::prefer_vulkan_first`]. Linux: vaapi → vulkan → software on
//! desktop Mesa, vulkan first on NVIDIA/VanGogh. Windows: d3d11va → vulkan → software on
//! Intel/unknown, vulkan first on NVIDIA/AMD.
//! Override: `PUNKTFUNK_DECODER=vulkan|vaapi|d3d11va|software`; additionally
//! `native-vulkan` — the pf-vkdecode H.264 decoder on the presenter's device
//! (`video_vk_native`), runtime-opt-in ONLY until WP-D's A/B verdict admits it to the
//! ladder — see [`native_vulkan_gate`]):
//! Backends, picked at session start (auto is vendor-ordered on BOTH desktop OSes —
//! see [`VulkanDecodeDevice::prefer_vulkan_first`]; on H.264 sessions the native
//! pf-vkdecode decoder (`video_vk_native`, gated by [`native_vulkan_gate`]) slots in
//! immediately ABOVE the FFmpeg-Vulkan rung wherever the ladder reaches it — the
//! program's goal is dropping FFmpeg from the client, and a native INIT failure
//! falls through to FFmpeg-Vulkan; a runtime error streak instead demotes past it,
//! same as FFmpeg-Vulkan's own streaks do — see `decode_frame`). Linux: native →
//! vulkan → vaapi → software on NVIDIA and ALL AMD (VanGogh included), vaapi →
//! native → vulkan → software on Intel/unknown. Windows: native → vulkan → d3d11va →
//! software on NVIDIA/AMD, d3d11va → native → vulkan → software on Intel/unknown.
//! Override: `PUNKTFUNK_DECODER=vulkan|vaapi|d3d11va|software|native-vulkan` —
//! `vulkan` names the FFmpeg-Vulkan backend specifically; `native-vulkan` pins the
//! pf-vkdecode decoder by name, skipping the vendor-ordered rungs ahead of it):
//!
//! * **Vulkan Video**: FFmpeg's Vulkan decoder running on the PRESENTER's own VkDevice
//! (its handles arrive via [`VulkanDecodeDevice`]) — the decoded VkImage feeds the
@@ -83,7 +88,8 @@ pub enum DecodedImage {
/// samples them directly (BT.709 limited, the codec's fixed colour contract).
#[cfg(all(any(target_os = "linux", windows), feature = "pyrowave"))]
PyroWave(crate::video_pyrowave::PyroWavePlanarFrame),
/// Native Vulkan Video output (pf-vkdecode, `PUNKTFUNK_DECODER=native-vulkan`):
/// Native Vulkan Video output (pf-vkdecode — auto's H.264 rung immediately above
/// FFmpeg-Vulkan, also pinnable via `PUNKTFUNK_DECODER=native-vulkan`):
/// an NV12 image + per-plane views already on the PRESENTER's device — same
/// zero-copy contract as [`DecodedImage::VkFrame`], no FFmpeg involved. The
/// presenter waits the frame's timeline pair, transitions the layer for sampling
@@ -389,10 +395,12 @@ impl Drop for DrmFrameGuard {
enum Backend {
Vulkan(VulkanDecoder),
/// Native Vulkan Video H.264 (pf-vkdecode) on the presenter's device — runtime
/// opt-in only (`PUNKTFUNK_DECODER=native-vulkan`, see [`native_vulkan_gate`]);
/// not in the automatic ladder until WP-D's A/B verdict. Errors ride the SAME
/// streak/demotion machinery as the FFmpeg-Vulkan rung.
/// Native Vulkan Video H.264 (pf-vkdecode) on the presenter's device — auto's
/// rung immediately above FFmpeg-Vulkan since the 2026-08-05 ladder decision
/// (WP-D closed bit-exact; the program's goal is dropping FFmpeg from the
/// client), also pinnable by name (`PUNKTFUNK_DECODER=native-vulkan`) — see
/// [`native_vulkan_gate`]. Errors ride the SAME streak/demotion machinery as
/// the FFmpeg-Vulkan rung.
/// Boxed: the decoder (planner + shipped-frame ledger) dwarfs the other variants,
/// same as PyroWave below.
NativeVulkan(Box<NativeVulkanDecoder>),
@@ -454,24 +462,34 @@ const VAAPI_DEMOTE_AFTER: u32 = 3;
/// software before the first requested IDR could even arrive.
const HW_DEMOTE_MIN_STREAK: std::time::Duration = std::time::Duration::from_millis(1000);
/// The native Vulkan Video opt-in gate (WP-C of the native-decode program): the
/// pf-vkdecode backend engages ONLY when the operator asked for it by name
/// (`PUNKTFUNK_DECODER=native-vulkan` — `choice` is env-first, so that's what carries
/// it), the negotiated wire codec is H.264 (the one codec pf-vkdecode speaks), and the
/// presenter's device actually advertises Vulkan Video decode. Deliberately NOT an
/// `auto` rung: entering the automatic ladder is WP-D's A/B verdict. Pure so the
/// decision is CPU-testable.
/// `VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR` — the raw flag bit within
/// [`VulkanDecodeDevice::decode_video_caps`] (this crate stays ash-free).
const VIDEO_CODEC_OP_DECODE_H264: u32 = 0x0000_0001;
/// The native Vulkan Video admission gate (WP-C of the native-decode program, widened
/// by the 2026-08-05 ladder decision): the pf-vkdecode backend engages when `choice`
/// asks for it — by name (`PUNKTFUNK_DECODER=native-vulkan` — `choice` is env-first,
/// so that's what carries it) or as the auto family (`auto`/``/`hardware`), where
/// native is the rung immediately ABOVE FFmpeg-Vulkan: WP-D closed with bit-exact
/// parity against libavcodec (250/250 AUs on three drivers, clean 92-minute soak),
/// and the program's goal is dropping FFmpeg from the client, so native goes first
/// wherever the ladder would reach FFmpeg-Vulkan — a native INIT failure falls
/// through to that rung, so admission can't cost a session its decoder at start
/// (a runtime error streak demotes past FFmpeg-Vulkan to VAAPI/D3D11VA/software,
/// like every hardware rung's streaks do — a native→FFmpeg-Vulkan runtime rung is
/// deliberately absent; FFmpeg is on its way out). The explicit
/// `vulkan` pin still names the FFmpeg-Vulkan backend specifically; it — and every
/// other explicit backend pin — refuses. Beyond the choice: the negotiated wire codec
/// must be H.264 (the one codec pf-vkdecode speaks) and the presenter's device must
/// actually advertise Vulkan Video H.264 decode. Pure so the decision is
/// CPU-testable.
fn native_vulkan_gate(
choice: &str,
codec_id: ffmpeg::codec::Id,
video_decode: bool,
decode_video_caps: u32,
) -> bool {
choice == "native-vulkan"
matches!(choice, "native-vulkan" | "auto" | "" | "hardware")
&& codec_id == ffmpeg::codec::Id::H264
&& video_decode
// The decode family must advertise the H264 op specifically —
@@ -631,11 +649,17 @@ impl Decoder {
/// Precedence: the `PUNKTFUNK_DECODER` env override wins (support/debug escape
/// hatch, and the documented knob), then the setting; both default to auto.
/// Auto's hardware order depends on the device on BOTH desktop OSes
/// ([`VulkanDecodeDevice::prefer_vulkan_first`]). Linux: VAAPI → Vulkan → software on
/// desktop Mesa (AMD/Intel), Vulkan → VAAPI → software on NVIDIA and the Deck's
/// VanGogh. Windows (no VAAPI there): Vulkan → D3D11VA → software on NVIDIA/AMD,
/// D3D11VA → Vulkan → software on Intel/unknown (Intel's driver advertises Vulkan
/// Video, but FFmpeg-Vulkan on it strobes/overruns the budget — B580 field report).
/// ([`VulkanDecodeDevice::prefer_vulkan_first`]); on H.264 sessions the native
/// pf-vkdecode rung sits immediately above FFmpeg-Vulkan wherever the ladder
/// reaches it ([`native_vulkan_gate`] — the program is dropping FFmpeg, and a
/// native INIT failure falls through to FFmpeg-Vulkan). Linux: native → Vulkan
/// VAAPI → software on NVIDIA and ALL AMD (`prefer_vulkan_first` is vendor-wide —
/// desktop RADV included, on-glass verdict — not just the Deck's VanGogh);
/// VAAPI → native → Vulkan → software on Intel/unknown. Windows (no VAAPI
/// there): native → Vulkan → D3D11VA → software on NVIDIA/AMD, D3D11VA →
/// native → Vulkan → software on Intel/unknown (Intel's driver advertises Vulkan
/// Video, but FFmpeg-Vulkan on it strobes/overruns the budget — B580 field
/// report).
pub fn new(
codec_id: ffmpeg::codec::Id,
pref: &str,
@@ -668,13 +692,16 @@ impl Decoder {
d3d11_hdr10,
})
};
// Native Vulkan Video (pf-vkdecode) — strictly the runtime opt-in
// (`PUNKTFUNK_DECODER=native-vulkan`); [`native_vulkan_gate`] is the whole
// decision. Any refusal or init failure logs and DEMOTES to the standard
// ladder below exactly as if the native rung errored (choice reads as `auto`
// from here on) — a native failure must never be quieter, or land somewhere
// Native Vulkan Video (pf-vkdecode), pinned by name (`PUNKTFUNK_DECODER=
// native-vulkan`). Since the 2026-08-05 ladder decision native is ALSO an
// auto rung (below, immediately above FFmpeg-Vulkan); the pin stays as the
// support/debug escape hatch that skips the vendor-ordered rungs ahead of
// it. Any refusal or init failure logs and DEMOTES to the standard ladder
// below exactly as if the native rung errored (choice reads as `auto` from
// here on) — a native failure must never be quieter, or land somewhere
// other, than the FFmpeg rungs' failures do.
let mut choice = choice;
let mut native_tried = false;
if choice == "native-vulkan" {
if native_vulkan_gate(
&choice,
@@ -682,6 +709,7 @@ impl Decoder {
vk.is_some_and(|v| v.video_decode),
vk.map_or(0, |v| v.decode_video_caps),
) {
native_tried = true;
let vk = vk.expect("gate demands video_decode, so vk is Some");
match NativeVulkanDecoder::new(vk) {
Ok(n) => {
@@ -773,6 +801,39 @@ impl Decoder {
}
}
}
// Native Vulkan Video (pf-vkdecode) — auto's rung immediately ABOVE
// FFmpeg-Vulkan (2026-08-05 ladder decision: WP-D closed with bit-exact parity
// against libavcodec on three drivers and a clean soak, and the program's goal
// is dropping FFmpeg from the client entirely — so wherever auto would reach
// FFmpeg-Vulkan, native goes first). [`native_vulkan_gate`] carries the whole
// decision, including the choice: the explicit `vulkan` pin is NOT this rung —
// it names the FFmpeg-Vulkan backend specifically and keeps meaning exactly
// that. An init failure logs and falls through to FFmpeg-Vulkan below, so
// admission can never cost a session hardware decode it had before.
// (`native_tried` skips the repeat when the pin above already attempted — and
// failed — the same construction.)
if !native_tried
&& native_vulkan_gate(
&choice,
codec_id,
vk.is_some_and(|v| v.video_decode),
vk.map_or(0, |v| v.decode_video_caps),
)
{
let vk = vk.expect("gate demands video_decode, so vk is Some");
match NativeVulkanDecoder::new(vk) {
Ok(n) => {
tracing::info!(
?codec_id,
"native Vulkan Video hardware decode active \
(pf-vkdecode auto rung, presenter-shared device)"
);
return done(Backend::NativeVulkan(Box::new(n)));
}
Err(e) => tracing::info!(reason = %format!("{e:#}"),
"native Vulkan decode unavailable — trying FFmpeg Vulkan Video"),
}
}
if matches!(choice.as_str(), "auto" | "" | "vulkan" | "hardware") {
// `video_decode` gates the Vulkan Video attempt: the presenter now exports its
// handle bundle even when the device has no decode queue (Windows D3D11 interop
@@ -1350,40 +1411,59 @@ mod tests {
assert!(!decode_device(0x8086, "Intel(R) Arc(TM) Pro Graphics").prefer_vulkan_first());
}
/// The native-Vulkan opt-in gate (WP-C): by name only, H.264 only, and only on a
/// device that really decodes — every other combination takes the standard ladder.
/// Pinned so "native enters auto" can only ever be a deliberate WP-D change.
/// The native-Vulkan admission gate (WP-C, widened by the 2026-08-05 ladder
/// decision): the pin AND the auto family admit on a capable H.264 session —
/// native sits immediately above FFmpeg-Vulkan because the program is dropping
/// FFmpeg — while every explicit backend pin refuses (`vulkan` names the
/// FFmpeg-Vulkan backend specifically and must keep meaning exactly that), and
/// the codec/device legs still refuse for every choice.
#[test]
fn native_vulkan_gate_is_by_name_h264_and_capable_device_only() {
fn native_vulkan_gate_admits_pin_and_auto_family_on_capable_h264_only() {
use ffmpeg::codec::Id;
// Pin the raw spec value, not the implementation constant — a typo'd bit
// would refuse every real driver's caps and native would silently never
// engage (the program's own nb_queries=0 lesson: silent non-engagement is
// the failure mode nothing flags).
assert_eq!(
VIDEO_CODEC_OP_DECODE_H264, 0x1,
"VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR"
);
const H264_OP: u32 = VIDEO_CODEC_OP_DECODE_H264;
assert!(native_vulkan_gate("native-vulkan", Id::H264, true, H264_OP));
// Never by any other preference — it is not an auto rung yet.
for choice in ["auto", "", "hardware", "vulkan", "software"] {
for choice in ["native-vulkan", "auto", "", "hardware"] {
// The pin and the whole auto family admit…
assert!(
native_vulkan_gate(choice, Id::H264, true, H264_OP),
"{choice:?}"
);
// …but only for the one codec pf-vkdecode speaks.
assert!(
!native_vulkan_gate(choice, Id::HEVC, true, H264_OP),
"{choice:?}"
);
assert!(
!native_vulkan_gate(choice, Id::AV1, true, H264_OP),
"{choice:?}"
);
// No Vulkan-Video-capable presenter device.
assert!(
!native_vulkan_gate(choice, Id::H264, false, H264_OP),
"{choice:?}"
);
// A decode family WITHOUT the H264 op (e.g. AV1-only) refuses even with
// the extension stack present — the caps BIT is the codec gate.
assert!(!native_vulkan_gate(choice, Id::H264, true, 0), "{choice:?}");
assert!(
!native_vulkan_gate(choice, Id::H264, true, 0x4),
"{choice:?}"
);
}
// Never for an explicit OTHER-backend pin, capable device or not.
for choice in ["vulkan", "vaapi", "d3d11va", "software"] {
assert!(
!native_vulkan_gate(choice, Id::H264, true, H264_OP),
"{choice:?}"
);
}
// The one codec pf-vkdecode speaks.
assert!(!native_vulkan_gate(
"native-vulkan",
Id::HEVC,
true,
H264_OP
));
assert!(!native_vulkan_gate("native-vulkan", Id::AV1, true, H264_OP));
// No Vulkan-Video-capable presenter device.
assert!(!native_vulkan_gate(
"native-vulkan",
Id::H264,
false,
H264_OP
));
// A decode family WITHOUT the H264 op (e.g. AV1-only) refuses even with
// the extension stack present — the caps BIT is the codec gate.
assert!(!native_vulkan_gate("native-vulkan", Id::H264, true, 0));
assert!(!native_vulkan_gate("native-vulkan", Id::H264, true, 0x4));
}
/// Lock the DRM FourCC magic numbers against typos — these are the exact values
+5 -3
View File
@@ -1,8 +1,10 @@
//! Native Vulkan Video H.264 decode backend (WP-C of the native-decode program):
//! pf-vkdecode's [`VkH264Decoder`] running on the PRESENTER's own VkDevice — the same
//! zero-copy shape as the FFmpeg-Vulkan backend, with no FFmpeg in the path. Strictly
//! the `PUNKTFUNK_DECODER=native-vulkan` runtime opt-in (`video::native_vulkan_gate`);
//! the automatic ladder stays FFmpeg's until WP-D's A/B verdict.
//! zero-copy shape as the FFmpeg-Vulkan backend, with no FFmpeg in the path. Auto's
//! rung immediately ABOVE FFmpeg-Vulkan since the 2026-08-05 ladder decision (WP-D
//! closed bit-exact — the program is dropping FFmpeg from the client), also pinnable
//! via `PUNKTFUNK_DECODER=native-vulkan`; `video::native_vulkan_gate` is the
//! admission either way, and a failure falls through to the FFmpeg-Vulkan rung.
//!
//! **Queue lock:** pf-vkdecode submits on queue 0 of the decode family
//! ([`DECODE_QUEUE_INDEX`] — the presenter creates exactly one queue per family). When
+1 -1
View File
@@ -536,7 +536,7 @@ fn detail(id: RowId) -> &'static str {
"Which compositor drives the virtual output — honored only if available on the host."
}
RowId::Codec => "A preference — the host falls back if it can't encode this one.",
RowId::Decoder => "Automatic prefers Vulkan Video, then VAAPI, then software.",
RowId::Decoder => "Automatic picks the best hardware decoder for this GPU, then software.",
RowId::Hdr => {
"HDR10 — engages when the host sends HDR content and this display supports it."
}