Commit 796c963a4b55
tarball3 files changed+64-11
@@ -21,6 +21,7 @@ monolith-motion.workspace = true
2121
monolith-planner.workspace = true2222
monolith-protocols.workspace = true2323
monolith-render-vk.workspace = true24
+libc = "0.2"2425
pound = "0.5"2526
profiling = "1"2627
serde_json.workspace = true@@ -131,6 +131,23 @@ fn main() -> ExitCode {
131131
}132132
}133133
134
+/// Puts the compositor thread on SCHED_RR so a busy desktop cannot delay a135
+/// frame. Reset-on-fork keeps threads and programs it starts off realtime.136
+fn realtime() {137
+ let param = libc::sched_param { sched_priority: 2 };138
+ // SAFETY: plain syscall on the calling thread with a valid param.139
+ let rc =140
+ unsafe { libc::sched_setscheduler(0, libc::SCHED_RR | libc::SCHED_RESET_ON_FORK, ¶m) };141
+ if rc == 0 {142
+ tracing::info!("compositor thread runs SCHED_RR");143
+ } else {144
+ tracing::info!(145
+ "no realtime scheduling, it needs CAP_SYS_NICE or an rtprio limit: {}",146
+ std::io::Error::last_os_error()147
+ );148
+ }149
+}150
+134151
/// Hands the session's variables to D-Bus and systemd activated services,135152
/// which portals need to find the compositor and pick monolith-portals.conf.136153
fn export_session(state: &State) {@@ -169,6 +186,9 @@ fn run(
169186
Backend::Drm => Some(drm::primary()?),170187
_ => None,171188
};189
+ if gpu.is_some() {190
+ realtime();191
+ }172192
let node = gpu173193
.as_deref()174194
.map(smithay::backend::drm::DrmNode::from_path)@@ -82,9 +82,6 @@ impl Shared {
8282
return Err(Error::NoSuitableDevice);8383
};8484
let priorities = [1.0];85
- let queues = [vk::DeviceQueueCreateInfo::default()86
- .queue_family_index(queue_family)87
- .queue_priorities(&priorities)];8885
let available: Vec<_> = unsafe { instance.enumerate_device_extension_properties(physical) }8986
.unwrap_or_default()9087
.iter()@@ -97,14 +94,49 @@ impl Shared {
9794
if has_dmabuf {9895
extensions.extend(DMABUF_EXTENSIONS.iter().map(|n| n.as_ptr()));9996
}100
- let mut features13 = vk::PhysicalDeviceVulkan13Features::default()101
- .dynamic_rendering(true)102
- .synchronization2(true);103
- let info = vk::DeviceCreateInfo::default()104
- .queue_create_infos(&queues)105
- .enabled_extension_names(&extensions)106
- .push_next(&mut features13);107
- let device = match unsafe { instance.create_device(physical, &info, None) } {97
+ let global_priority = [98
+ ash::khr::global_priority::NAME,99
+ ash::ext::global_priority::NAME,100
+ ]101
+ .into_iter()102
+ .find(|n| available.iter().any(|a| a.as_c_str() == *n));103
+ let mut priorities_to_try = vec![None];104
+ if let Some(name) = global_priority {105
+ extensions.push(name.as_ptr());106
+ priorities_to_try = vec![107
+ Some(vk::QueueGlobalPriorityKHR::REALTIME),108
+ Some(vk::QueueGlobalPriorityKHR::HIGH),109
+ None,110
+ ];111
+ }112
+ let mut created = Err(vk::Result::ERROR_INITIALIZATION_FAILED);113
+ for priority in priorities_to_try {114
+ let mut features13 = vk::PhysicalDeviceVulkan13Features::default()115
+ .dynamic_rendering(true)116
+ .synchronization2(true);117
+ let mut global = vk::DeviceQueueGlobalPriorityCreateInfoKHR::default()118
+ .global_priority(priority.unwrap_or(vk::QueueGlobalPriorityKHR::MEDIUM));119
+ let mut queue = vk::DeviceQueueCreateInfo::default()120
+ .queue_family_index(queue_family)121
+ .queue_priorities(&priorities);122
+ if priority.is_some() {123
+ queue = queue.push_next(&mut global);124
+ }125
+ let queues = [queue];126
+ let info = vk::DeviceCreateInfo::default()127
+ .queue_create_infos(&queues)128
+ .enabled_extension_names(&extensions)129
+ .push_next(&mut features13);130
+ created = unsafe { instance.create_device(physical, &info, None) };131
+ match &created {132
+ Ok(_) => {133
+ tracing::info!(?priority, "queue global priority");134
+ break;135
+ }136
+ Err(e) => tracing::debug!(?priority, "queue global priority refused: {e}"),137
+ }138
+ }139
+ let device = match created {108140
Ok(d) => d,109141
Err(e) => {110142
unsafe { instance.destroy_instance(None) };