workaround: Force shm on Meteor/Arrow/Lunar Lake

This commit is contained in:
Ian Douglas Scott 2025-09-19 13:39:47 -07:00 committed by Ian Douglas Scott
parent b8780b9911
commit 9968b0e61f
5 changed files with 94 additions and 0 deletions

2
Cargo.lock generated
View file

@ -1242,6 +1242,8 @@ version = "0.1.0"
dependencies = [ dependencies = [
"aliasable", "aliasable",
"anyhow", "anyhow",
"ash",
"bytemuck",
"calloop 0.14.3", "calloop 0.14.3",
"calloop-wayland-source 0.4.1", "calloop-wayland-source 0.4.1",
"clap", "clap",

View file

@ -37,6 +37,8 @@ aliasable = "0.1.3"
futures-executor = { version = "0.3.31", features = ["thread-pool"] } futures-executor = { version = "0.3.31", features = ["thread-pool"] }
zbus = "5.9.0" zbus = "5.9.0"
tokio-stream = { version = "0.1.17", features = ["sync"] } tokio-stream = { version = "0.1.17", features = ["sync"] }
ash = { version = "0.38.0", features = ["loaded"] }
bytemuck = "1.23.2"
[dependencies.i18n-embed] [dependencies.i18n-embed]
version = "0.16" version = "0.16"

View file

@ -93,6 +93,14 @@ impl AppData {
return Ok(None); return Ok(None);
}; };
let drm_dev = drm_dev.unwrap_or(feedback.main_device() as u64); let drm_dev = drm_dev.unwrap_or(feedback.main_device() as u64);
if let Some(vulkan) = &mut self.vulkan {
if let Ok(Some(name)) = vulkan.device_name(drm_dev) {
// TODO Workaround: force shm on Meteor/Arrow/Lunar Lake
if name.contains("MTL") || name.contains("ARL") || name.contains("LNL") {
return Ok(None);
}
}
}
let Some((_dev_path, gbm)) = self.gbm_devices.gbm_device(drm_dev)? else { let Some((_dev_path, gbm)) = self.gbm_devices.gbm_device(drm_dev)? else {
return Ok(None); return Ok(None);
}; };

View file

@ -39,6 +39,7 @@ use gbm_devices::GbmDevices;
mod screencopy; mod screencopy;
use screencopy::{ScreencopySession, SessionData}; use screencopy::{ScreencopySession, SessionData};
mod toplevel; mod toplevel;
mod vulkan;
mod workspace; mod workspace;
use super::{CaptureFilter, CaptureImage, Cmd, Event}; use super::{CaptureFilter, CaptureImage, Cmd, Event};
@ -63,6 +64,7 @@ pub struct AppData {
dmabuf_feedback: Option<DmabufFeedback>, dmabuf_feedback: Option<DmabufFeedback>,
gbm_devices: GbmDevices, gbm_devices: GbmDevices,
thread_pool: futures_executor::ThreadPool, thread_pool: futures_executor::ThreadPool,
vulkan: Option<vulkan::Vulkan>,
} }
impl AppData { impl AppData {
@ -308,6 +310,7 @@ fn start(conn: Connection) -> mpsc::Receiver<Event> {
dmabuf_feedback: None, dmabuf_feedback: None,
gbm_devices: GbmDevices::default(), gbm_devices: GbmDevices::default(),
thread_pool, thread_pool,
vulkan: vulkan::Vulkan::new(),
}; };
let (cmd_sender, cmd_channel) = calloop::channel::channel(); let (cmd_sender, cmd_channel) = calloop::channel::channel();

View file

@ -0,0 +1,79 @@
use ash::{prelude::VkResult, vk};
use std::{collections::HashMap, ffi::CStr};
pub struct Vulkan {
instance: ash::Instance,
// TODO purge cache at some point
device_name_cache: HashMap<u64, VkResult<Option<String>>>,
}
impl Vulkan {
pub fn new() -> Option<Self> {
let entry = unsafe { ash::Entry::load().ok()? };
let app_info = vk::ApplicationInfo {
api_version: vk::make_api_version(0, 1, 1, 0),
..Default::default()
};
let create_info = vk::InstanceCreateInfo {
p_application_info: &app_info,
..Default::default()
};
let instance = unsafe { entry.create_instance(&create_info, None).ok()? };
Some(Self {
instance,
device_name_cache: HashMap::new(),
})
}
pub fn device_name(&mut self, dev: u64) -> VkResult<Option<&str>> {
if !self.device_name_cache.contains_key(&dev) {
let value = self.device_name_uncached(dev);
self.device_name_cache.insert(dev, value);
}
self.device_name_cache
.get(&dev)
.unwrap()
.as_ref()
.map(|x| x.as_deref())
.map_err(|err| err.clone())
}
fn device_name_uncached(&mut self, dev: u64) -> VkResult<Option<String>> {
let devices = unsafe { self.instance.enumerate_physical_devices()? };
for device in devices {
// Check extension is supported
let supported = unsafe {
self.instance
.enumerate_device_extension_properties(device)?
};
if !supported.iter().any(|ext| {
CStr::from_bytes_until_nul(bytemuck::cast_slice(&ext.extension_name))
== Ok(ash::ext::physical_device_drm::NAME)
}) {
continue;
}
let mut drm_props = vk::PhysicalDeviceDrmPropertiesEXT::default();
let mut props = vk::PhysicalDeviceProperties2::default().push_next(&mut drm_props);
unsafe {
self.instance
.get_physical_device_properties2(device, &mut props)
};
let device_name =
CStr::from_bytes_until_nul(bytemuck::cast_slice(&props.properties.device_name));
let major = rustix::fs::major(dev) as _;
let minor = rustix::fs::minor(dev) as _;
if (drm_props.primary_major, drm_props.primary_minor) == (major, minor)
|| (drm_props.render_major, drm_props.render_minor) == (major, minor)
{
return Ok(device_name
.ok()
.and_then(|x| Some(x.to_str().ok()?.to_owned())));
}
}
Ok(None)
}
}