perf(zerocopy/vulkan): LN4 — global-priority VkBridge queue for the LINEAR/gamescope CSC
apple / swift (push) Successful in 1m22s
apple / screenshots (push) Successful in 6m27s
ci / web (push) Successful in 1m0s
ci / docs-site (push) Successful in 1m6s
decky / build-publish (push) Successful in 21s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 12s
ci / bench (push) Successful in 7m51s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 9s
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 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 9s
deb / build-publish (push) Successful in 8m47s
arch / build-publish (push) Successful in 15m47s
android / android (push) Successful in 16m2s
deb / build-publish-host (push) Successful in 12m13s
ci / rust (push) Successful in 26m31s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 15m54s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 16m3s
docker / deploy-docs (push) Successful in 16s
apple / swift (push) Successful in 1m22s
apple / screenshots (push) Successful in 6m27s
ci / web (push) Successful in 1m0s
ci / docs-site (push) Successful in 1m6s
decky / build-publish (push) Successful in 21s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 12s
ci / bench (push) Successful in 7m51s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 9s
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 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 9s
deb / build-publish (push) Successful in 8m47s
arch / build-publish (push) Successful in 15m47s
android / android (push) Successful in 16m2s
deb / build-publish-host (push) Successful in 12m13s
ci / rust (push) Successful in 26m31s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 15m54s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 16m3s
docker / deploy-docs (push) Successful in 16s
The RGB→NV12 compute CSC shares the SMs with the game; request an
elevated global-priority queue (VK_KHR/EXT_global_priority) so the
driver can schedule it ahead. PUNKTFUNK_VK_QUEUE_PRIORITY =
off|high|realtime (default realtime), downgrading REALTIME→HIGH→none
on NOT_PERMITTED/INITIALIZATION_FAILED — a refused class never fails
the bridge. Mirrors PyroWave's ac0e7332 (same honest caveat: WDDM
didn't move; the Linux driver may — contended-tail lever, correct and
harmless either way).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -86,9 +86,11 @@ impl VkBridge {
|
|||||||
// SAFETY: standard ash bring-up — every call is `unsafe` only because ash cannot statically
|
// SAFETY: standard ash bring-up — every call is `unsafe` only because ash cannot statically
|
||||||
// verify Vulkan handle/CreateInfo validity. `ash::Entry::load` dlopens a real system
|
// verify Vulkan handle/CreateInfo validity. `ash::Entry::load` dlopens a real system
|
||||||
// libvulkan. Each `*CreateInfo`/`AllocateInfo` is built by ash's builders from locals (`app`,
|
// libvulkan. Each `*CreateInfo`/`AllocateInfo` is built by ash's builders from locals (`app`,
|
||||||
// `exts`, `prio`, `qci`, and the inline infos) that all live for the duration of the
|
// `exts`, `prio`, `qci`, `gp_info`, and the inline infos) that all live for the duration of
|
||||||
// synchronous `create_*`/`enumerate_*` call that reads them — in particular the
|
// the synchronous `create_*`/`enumerate_*` call that reads them — the ladder loop rebuilds
|
||||||
// `enabled_extension_names(&exts)` and `queue_priorities(&prio)` borrows outlive their calls.
|
// `prio`/`gp_info`/`qci`/`exts` fresh per attempt, so every `enabled_extension_names(&exts)`
|
||||||
|
// / `queue_priorities(&prio)` / `push_next(&mut gp_info)` borrow outlives its own
|
||||||
|
// `create_device` call.
|
||||||
// Every handle passed (`instance`, `phys`, `device`, `qf`, `cmd_pool`) was just created and
|
// Every handle passed (`instance`, `phys`, `device`, `qf`, `cmd_pool`) was just created and
|
||||||
// checked via `?`/`ok_or_else` in this same function, so no invalid handle is ever used. This
|
// checked via `?`/`ok_or_else` in this same function, so no invalid handle is ever used. This
|
||||||
// constructor shares nothing across threads.
|
// constructor shares nothing across threads.
|
||||||
@@ -122,23 +124,93 @@ impl VkBridge {
|
|||||||
.ok_or_else(|| anyhow!("no compute-capable queue family"))?
|
.ok_or_else(|| anyhow!("no compute-capable queue family"))?
|
||||||
as u32;
|
as u32;
|
||||||
|
|
||||||
let exts = [
|
// Global-priority queue (latency plan §7 LN4, PyroWave's `ac0e7332` lever for the
|
||||||
|
// VkBridge): the LINEAR/gamescope CSC dispatch shares the SM/compute cores with the
|
||||||
|
// game, so ask for an elevated global priority to get scheduled ahead of it.
|
||||||
|
// `PUNKTFUNK_VK_QUEUE_PRIORITY` = off | high | realtime (default realtime); the
|
||||||
|
// create loop downgrades REALTIME→HIGH→none on NOT_PERMITTED (and retries a plain
|
||||||
|
// create on INITIALIZATION_FAILED) so a refused class never fails the bridge.
|
||||||
|
let gp_ext = std::env::var("PUNKTFUNK_VK_QUEUE_PRIORITY")
|
||||||
|
.ok()
|
||||||
|
.as_deref()
|
||||||
|
.map_or(Some(vk::QueueGlobalPriorityKHR::REALTIME), |v| match v {
|
||||||
|
"off" | "0" => None,
|
||||||
|
"high" => Some(vk::QueueGlobalPriorityKHR::HIGH),
|
||||||
|
_ => Some(vk::QueueGlobalPriorityKHR::REALTIME),
|
||||||
|
})
|
||||||
|
.and_then(|want| {
|
||||||
|
// Enable whichever alias the driver advertises (KHR = the promoted name).
|
||||||
|
let props = instance.enumerate_device_extension_properties(phys).ok()?;
|
||||||
|
let has = |name: &std::ffi::CStr| {
|
||||||
|
props
|
||||||
|
.iter()
|
||||||
|
.any(|p| p.extension_name_as_c_str() == Ok(name))
|
||||||
|
};
|
||||||
|
if has(vk::KHR_GLOBAL_PRIORITY_NAME) {
|
||||||
|
Some((vk::KHR_GLOBAL_PRIORITY_NAME, want))
|
||||||
|
} else if has(vk::EXT_GLOBAL_PRIORITY_NAME) {
|
||||||
|
Some((vk::EXT_GLOBAL_PRIORITY_NAME, want))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let base_exts = [
|
||||||
ash::khr::external_memory_fd::NAME.as_ptr(),
|
ash::khr::external_memory_fd::NAME.as_ptr(),
|
||||||
ash::ext::external_memory_dma_buf::NAME.as_ptr(),
|
ash::ext::external_memory_dma_buf::NAME.as_ptr(),
|
||||||
];
|
];
|
||||||
let prio = [1.0f32];
|
let mut try_priority = gp_ext.map(|(_, want)| want);
|
||||||
let qci = [vk::DeviceQueueCreateInfo::default()
|
let device = loop {
|
||||||
.queue_family_index(qf)
|
let prio = [1.0f32];
|
||||||
.queue_priorities(&prio)];
|
let mut gp_info = vk::DeviceQueueGlobalPriorityCreateInfoKHR::default()
|
||||||
let device = instance
|
.global_priority(try_priority.unwrap_or(vk::QueueGlobalPriorityKHR::MEDIUM));
|
||||||
.create_device(
|
let mut qci0 = vk::DeviceQueueCreateInfo::default()
|
||||||
|
.queue_family_index(qf)
|
||||||
|
.queue_priorities(&prio);
|
||||||
|
let mut exts: Vec<*const std::ffi::c_char> = base_exts.to_vec();
|
||||||
|
if try_priority.is_some() {
|
||||||
|
qci0 = qci0.push_next(&mut gp_info);
|
||||||
|
exts.push(gp_ext.expect("try_priority implies gp_ext").0.as_ptr());
|
||||||
|
}
|
||||||
|
let qci = [qci0];
|
||||||
|
match instance.create_device(
|
||||||
phys,
|
phys,
|
||||||
&vk::DeviceCreateInfo::default()
|
&vk::DeviceCreateInfo::default()
|
||||||
.queue_create_infos(&qci)
|
.queue_create_infos(&qci)
|
||||||
.enabled_extension_names(&exts),
|
.enabled_extension_names(&exts),
|
||||||
None,
|
None,
|
||||||
)
|
) {
|
||||||
.context("vkCreateDevice (external-memory extensions supported?)")?;
|
Ok(d) => {
|
||||||
|
if let Some(p) = try_priority {
|
||||||
|
tracing::info!(
|
||||||
|
priority = ?p,
|
||||||
|
"VkBridge queue at elevated global priority (CSC schedules \
|
||||||
|
ahead of a GPU-bound game where the driver honors it)"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break d;
|
||||||
|
}
|
||||||
|
// A refused class must never fail the bridge — walk the ladder down.
|
||||||
|
Err(
|
||||||
|
vk::Result::ERROR_NOT_PERMITTED_KHR
|
||||||
|
| vk::Result::ERROR_INITIALIZATION_FAILED,
|
||||||
|
) if try_priority == Some(vk::QueueGlobalPriorityKHR::REALTIME) => {
|
||||||
|
try_priority = Some(vk::QueueGlobalPriorityKHR::HIGH);
|
||||||
|
}
|
||||||
|
Err(
|
||||||
|
vk::Result::ERROR_NOT_PERMITTED_KHR
|
||||||
|
| vk::Result::ERROR_INITIALIZATION_FAILED,
|
||||||
|
) if try_priority.is_some() => {
|
||||||
|
tracing::debug!(
|
||||||
|
"global-priority queue not permitted — VkBridge at default priority"
|
||||||
|
);
|
||||||
|
try_priority = None;
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
return Err(e)
|
||||||
|
.context("vkCreateDevice (external-memory extensions supported?)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
let ext_fd = ash::khr::external_memory_fd::Device::new(&instance, &device);
|
let ext_fd = ash::khr::external_memory_fd::Device::new(&instance, &device);
|
||||||
let queue = device.get_device_queue(qf, 0);
|
let queue = device.get_device_queue(qf, 0);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user