fix(client): the probe printed a device index the env var does not take
--probe-decode printed its DISPLAY position and called it the PUNKTFUNK_VK_DEVICE value. It is not. pick_device resolves that variable against the RAW vkEnumeratePhysicalDevices order (setup.rs, `devices.get(i)`) BEFORE any ranking runs, while the probe sorts discrete-first for readability. Those two orders disagree precisely on the hardware this flag exists to diagnose. pick_device's own comment records why the ranking is there: "enumeration order puts the iGPU FIRST on some hybrids (observed: Ryzen iGPU ahead of an RTX dGPU)". So on a hybrid laptop the number the probe printed for the iGPU could well be the number for the dGPU — a diagnostic handing out an actionable value that selects the other GPU, which is worse than printing none. Measured on the Arc + RTX 3500 Ada laptop, which is also where the first output went out with the wrong claim in it: three adapters, and the same Arc iGPU enumerated TWICE. So AdapterDecode now carries the raw enumeration index, captured before the sort, and the printer uses it; the "default presenter" marker stays on the first LISTED entry, because sorted-first is what pick_device lands on when nothing overrides. The duplicate is why the trailing hint names PUNKTFUNK_VK_ADAPTER as the safer knob and admits its limit: two adapters sharing a marketing name cannot be told apart by it, and a name match resolves to whichever enumerates first. The hint also states the thing this whole output invites a reader to get wrong — that a capable GPU in the list does not mean the decoder will use it, because Vulkan Video decodes on the presenter's device and PUNKTFUNK_DECODER does not move the presenter. Gates: fmt clean; clippy -D warnings on punktfunk-client-session and pf-presenter.
This commit is contained in:
@@ -548,12 +548,21 @@ mod session_main {
|
||||
println!("no Vulkan physical devices");
|
||||
}
|
||||
for (i, a) in adapters.iter().enumerate() {
|
||||
// The index IS the PUNKTFUNK_VK_DEVICE value, and entry 0 is what
|
||||
// The bracketed number is the PUNKTFUNK_VK_DEVICE value, and the
|
||||
// FIRST listed entry is what
|
||||
// a default run presents on — the decoder shares that device, so
|
||||
// on a hybrid box this line is usually the answer.
|
||||
let kind = if a.discrete { "discrete" } else { "integrated" };
|
||||
// `a.index`, NOT the loop position. This list is sorted
|
||||
// discrete-first for reading, but PUNKTFUNK_VK_DEVICE indexes the
|
||||
// raw enumeration, which puts the iGPU first on some hybrids —
|
||||
// printing the loop position would name the other GPU on exactly
|
||||
// the machines this flag is for. The `i == 0` marker is still the
|
||||
// loop position, because sorted-first IS what pick_device lands on
|
||||
// when nothing overrides it.
|
||||
println!(
|
||||
"[{i}] {} ({kind}){}",
|
||||
"[{}] {} ({kind}){}",
|
||||
a.index,
|
||||
a.name,
|
||||
if i == 0 { " <- default presenter" } else { "" }
|
||||
);
|
||||
@@ -620,6 +629,26 @@ mod session_main {
|
||||
println!(" extensions: {}", a.codec_exts.join(", "));
|
||||
}
|
||||
}
|
||||
if adapters.len() > 1 {
|
||||
// The single most common misreading of this output: seeing a
|
||||
// capable GPU listed and concluding the decoder will use it.
|
||||
// Vulkan Video decodes on the PRESENTER's device, and the decoder
|
||||
// preference does not move the presenter.
|
||||
println!();
|
||||
println!(
|
||||
"Vulkan Video decodes on the presenter's device. PUNKTFUNK_DECODER \
|
||||
picks the rung,"
|
||||
);
|
||||
println!(
|
||||
"not the GPU — move the presenter with PUNKTFUNK_VK_DEVICE=<index \
|
||||
above> or"
|
||||
);
|
||||
println!(
|
||||
"PUNKTFUNK_VK_ADAPTER=<name substring>, which is the safer knob \
|
||||
where two"
|
||||
);
|
||||
println!("adapters share a name.");
|
||||
}
|
||||
0
|
||||
}
|
||||
Err(e) => {
|
||||
|
||||
@@ -55,7 +55,19 @@ pub(crate) fn video_decode_gate(
|
||||
/// hardware decode starts here: WHICH adapter, and does it advertise the codec.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct AdapterDecode {
|
||||
/// Marketing name — also the `PUNKTFUNK_VK_ADAPTER` match key.
|
||||
/// The device's position in the RAW `vkEnumeratePhysicalDevices` order — and
|
||||
/// therefore the value `PUNKTFUNK_VK_DEVICE` takes, because `pick_device` indexes the
|
||||
/// unsorted list (`devices.get(i)`) before any ranking runs.
|
||||
///
|
||||
/// ⚠ NOT the display position. This list is sorted discrete-first for readability,
|
||||
/// while enumeration order puts the iGPU first on some hybrids — so the two disagree
|
||||
/// on exactly the machines this probe exists to diagnose. Printing the display
|
||||
/// position as if it were the env value would hand a hybrid-laptop reporter the
|
||||
/// number for the other GPU.
|
||||
pub index: usize,
|
||||
/// Marketing name — also the `PUNKTFUNK_VK_ADAPTER` match key. Not necessarily
|
||||
/// unique: a hybrid can expose the same iGPU twice, and a name match then resolves to
|
||||
/// whichever enumerates first.
|
||||
pub name: String,
|
||||
/// Discrete GPUs sort first, exactly as `pick_device` ranks them, so index 0 here is
|
||||
/// the device a default run will pick.
|
||||
@@ -743,7 +755,9 @@ pub fn probe_decode() -> Result<Vec<AdapterDecode>> {
|
||||
// filling locals returned by value.
|
||||
let devices = unsafe { instance.enumerate_physical_devices() }?;
|
||||
let mut out: Vec<(u8, AdapterDecode)> = Vec::with_capacity(devices.len());
|
||||
for pdev in devices {
|
||||
// `enumerate()` BEFORE any filtering or sorting: this index is what
|
||||
// `PUNKTFUNK_VK_DEVICE` selects, so it has to survive both.
|
||||
for (raw_index, pdev) in devices.into_iter().enumerate() {
|
||||
// SAFETY: per the Vulkan contract above - a read-only query on the live
|
||||
// instance/device, filling locals returned by value.
|
||||
let props = unsafe { instance.get_physical_device_properties(pdev) };
|
||||
@@ -834,6 +848,7 @@ pub fn probe_decode() -> Result<Vec<AdapterDecode>> {
|
||||
out.push((
|
||||
rank,
|
||||
AdapterDecode {
|
||||
index: raw_index,
|
||||
name,
|
||||
discrete: rank == 0,
|
||||
api_1_3,
|
||||
|
||||
Reference in New Issue
Block a user