From 89672a82d600cc49e353c27d1b89e4c399187fd7 Mon Sep 17 00:00:00 2001 From: Nova Date: Fri, 14 Mar 2025 16:22:57 -0700 Subject: [PATCH 1/4] feat(wayland): logging --- src/wayland/surface.rs | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/src/wayland/surface.rs b/src/wayland/surface.rs index 936871b..e4877ae 100644 --- a/src/wayland/surface.rs +++ b/src/wayland/surface.rs @@ -95,7 +95,8 @@ impl CoreSurface { }); // Import all surface buffers into textures - if import_surface_tree(renderer, &wl_surface).is_err() { + if let Err(err) = import_surface_tree(renderer, &wl_surface) { + tracing::error!("Failed to import surface tree for surface {}: {}", wl_surface.id(), err); return; } @@ -107,25 +108,11 @@ impl CoreSurface { let Some(wl_surface) = self.wl_surface() else { return; }; - let mapped = wl_surface - .get_data_raw::(|surface_states| { - surface_states.lock().unwrap().buffer().is_some() - }) - .unwrap_or(false); - - if !mapped { - return; - } - - let mut mapped_data = self.mapped_data.lock(); let Some(smithay_tex) = wl_surface .get_data_raw::(|surface_states| { - surface_states - .lock() - .unwrap() - .texture::(renderer.id()) - .cloned() + let locked = surface_states.lock().unwrap(); + locked.texture::(renderer.id()).cloned() }) .flatten() else { @@ -133,9 +120,11 @@ impl CoreSurface { }; let Some(sk_tex) = self.sk_tex.get() else { + tracing::error!("No sk_tex found for surface"); return; }; let Some(sk_mat) = self.sk_mat.get() else { + tracing::error!("No sk_mat found for surface"); return; }; sk_tex @@ -160,7 +149,7 @@ impl CoreSurface { let new_mapped_data = CoreSurfaceData { wl_tex: Some(SendWrapper::new(smithay_tex)), }; - *mapped_data = Some(new_mapped_data); + *self.mapped_data.lock() = Some(new_mapped_data); } pub fn frame(&self, output: Output) { -- 2.49.1 From 6930d5cecc5cc84ca6271e502df97b27f51f91ec Mon Sep 17 00:00:00 2001 From: Schmarni Date: Wed, 19 Mar 2025 16:51:20 +0100 Subject: [PATCH 2/4] feat: add --nvidia flag Signed-off-by: Schmarni --- src/main.rs | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index 87281e0..34032c5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -67,12 +67,16 @@ struct CliArgs { /// Restore the session with the given ID (or `latest`), ignoring the startup script. Sessions are stored in directories at `~/.local/state/stardust/`. #[clap(id = "SESSION_ID", long = "restore", action)] restore: Option, + /// this should fix nvidia issues, it'll only help on driver 565+ + /// and only if running under wayland, probably + #[clap(long)] + nvidia: bool, } static STARDUST_INSTANCE: OnceLock = OnceLock::new(); -// #[tokio::main] -#[tokio::main(flavor = "current_thread")] +// #[tokio::main(flavor = "current_thread")] +#[tokio::main] async fn main() { color_eyre::install().unwrap(); @@ -98,6 +102,20 @@ async fn main() { let cli_args = CliArgs::parse(); + if cli_args.nvidia && !cli_args.flatscreen { + // Only call this while singlethreaded since it can/will cause raceconditions with other + // functions reading or writing from the env + unsafe { + std::env::set_var("__GLX_VENDOR_LIBRARY_NAME", "mesa"); + std::env::set_var( + "__EGL_VENDOR_LIBRARY_FILENAMES", + "/usr/share/glvnd/egl_vendor.d/50_mesa.json", + ); + std::env::set_var("MESA_LOADER_DRIVER_OVERRIDE", "zink"); + std::env::set_var("GALLIUM_DRIVER", "zink"); + } + } + let socket_path = server::get_free_socket_path().expect("Unable to find a free stardust socket path"); STARDUST_INSTANCE.set(socket_path.file_name().unwrap().to_string_lossy().into_owned()).expect("Someone hasn't done their job, yell at Nova because how is this set multiple times what the hell"); -- 2.49.1 From 826809bb505c60fab70e2270e93c7ce88aef09f8 Mon Sep 17 00:00:00 2001 From: Schmarni Date: Wed, 19 Mar 2025 16:51:59 +0100 Subject: [PATCH 3/4] refactor: switch to dashmap for Aspects and Registries Signed-off-by: Schmarni --- Cargo.lock | 15 ++++++++ Cargo.toml | 1 + src/core/registry.rs | 90 ++++++++++++++++++++++++++------------------ src/nodes/mod.rs | 17 ++++----- 4 files changed, 78 insertions(+), 45 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d30cf1d..131e907 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -755,6 +755,20 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991" +[[package]] +name = "dashmap" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core 0.9.10", +] + [[package]] name = "directories" version = "5.0.1" @@ -2653,6 +2667,7 @@ dependencies = [ "clap", "color-eyre", "console-subscriber", + "dashmap", "directories", "glam", "global_counter", diff --git a/Cargo.toml b/Cargo.toml index 15b55cc..e494c63 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -92,6 +92,7 @@ xkbcommon-rs = "0.1.0" # wayland wayland-backend = { version = "0.3.7", optional = true, default-features = false } wayland-scanner = { version = "0.31.4", optional = true } +dashmap = "6.1.0" [dependencies.smithay] git = "https://github.com/smithay/smithay.git" diff --git a/src/core/registry.rs b/src/core/registry.rs index 5d9d85b..d1e5431 100644 --- a/src/core/registry.rs +++ b/src/core/registry.rs @@ -1,19 +1,18 @@ #![allow(dead_code)] +use dashmap::DashMap; use parking_lot::{MappedMutexGuard, Mutex, MutexGuard, const_mutex}; use rustc_hash::FxHashMap; +use std::ops::Deref; use std::ptr; -use std::sync::{Arc, Weak}; +use std::sync::{Arc, LazyLock, Weak}; #[derive(Debug)] -pub struct Registry(Mutex>>>); +pub struct Registry(MaybeLazy>>); impl Registry { pub const fn new() -> Self { - Registry(const_mutex(None)) - } - fn lock(&self) -> MappedMutexGuard>> { - MutexGuard::map(self.0.lock(), |r| r.get_or_insert_with(FxHashMap::default)) + Registry(MaybeLazy::Lazy(LazyLock::new(DashMap::default))) } pub fn add(&self, t: T) -> Arc where @@ -24,30 +23,29 @@ impl Registry { t_arc } pub fn add_raw(&self, t: &Arc) { - self.lock() + self.0 .insert(Arc::as_ptr(t) as *const () as usize, Arc::downgrade(t)); } pub fn contains(&self, t: &T) -> bool { - self.lock() + self.0 .contains_key(&(ptr::addr_of!(*t) as *const () as usize)) } pub fn get_changes(old: &Registry, new: &Registry) -> (Vec>, Vec>) { - let old = old.lock(); - let new = new.lock(); - let mut added = Vec::new(); let mut removed = Vec::new(); - for (id, entry) in new.iter() { + for pair in new.0.iter() { + let (id, entry) = pair.pair(); if let Some(entry) = entry.upgrade() { - if !old.contains_key(id) { + if !old.0.contains_key(id) { added.push(entry); } } } - for (id, entry) in old.iter() { + for pair in old.0.iter() { + let (id, entry) = pair.pair(); if let Some(entry) = entry.upgrade() { - if !new.contains_key(id) { + if !new.0.contains_key(id) { removed.push(entry); } } @@ -55,52 +53,48 @@ impl Registry { (added, removed) } pub fn get_valid_contents(&self) -> Vec> { - self.lock() + self.0 .iter() - .filter_map(|pair| pair.1.upgrade()) + .filter_map(|pair| pair.value().upgrade()) .collect() } pub fn set(&self, other: &Registry) { - self.lock().clone_from(&other.lock()); + self.clear(); + for (key, value) in other.0.deref().clone().into_iter() { + self.0.insert(key, value); + } } pub fn take_valid_contents(&self) -> Vec> { - self.0 - .lock() - .take() - .unwrap_or_default() - .into_iter() - .filter_map(|pair| pair.1.upgrade()) - .collect() + let contents = self.get_valid_contents(); + self.0.clear(); + contents } pub fn retain) -> bool>(&self, f: F) { - self.lock().retain(|_, v| { + self.0.retain(|_, v| { let Some(v) = v.upgrade() else { + // why would we want to retain things we can't upgrade? return true; }; (f)(&v) }) } pub fn remove(&self, t: &T) { - self.lock() - .remove(&(ptr::addr_of!(*t) as *const () as usize)); + self.0.remove(&(ptr::addr_of!(*t) as *const () as usize)); } pub fn clear(&self) { - self.lock().clear(); + self.0.clear(); } pub fn is_empty(&self) -> bool { - let registry = self.0.lock(); - let Some(registry) = &*registry else { - return true; - }; - if registry.is_empty() { + if self.0.is_empty() { return true; } - registry.values().all(|v| v.strong_count() == 0) + self.0.iter().all(|v| v.value().strong_count() == 0) } } + impl Clone for Registry { fn clone(&self) -> Self { - Self(Mutex::new(self.0.lock().clone())) + Self(self.0.clone()) } } impl Default for Registry { @@ -109,6 +103,30 @@ impl Default for Registry { } } +#[derive(Debug)] +enum MaybeLazy { + Lazy(LazyLock), + NonLazy(T), +} +impl Clone for MaybeLazy { + fn clone(&self) -> Self { + match self { + MaybeLazy::Lazy(lazy_lock) => Self::NonLazy(lazy_lock.deref().clone()), + MaybeLazy::NonLazy(v) => Self::NonLazy(v.clone()), + } + } +} +impl Deref for MaybeLazy { + type Target = T; + + fn deref(&self) -> &Self::Target { + match self { + MaybeLazy::Lazy(lazy_lock) => lazy_lock, + MaybeLazy::NonLazy(v) => v, + } + } +} + pub struct OwnedRegistry(Mutex>>>); impl OwnedRegistry { diff --git a/src/nodes/mod.rs b/src/nodes/mod.rs index fe1359e..3296613 100644 --- a/src/nodes/mod.rs +++ b/src/nodes/mod.rs @@ -12,8 +12,7 @@ use crate::core::client::Client; use crate::core::error::{Result, ServerError}; use crate::core::registry::Registry; use crate::core::scenegraph::MethodResponseSender; -use parking_lot::Mutex; -use rustc_hash::FxHashMap; +use dashmap::DashMap; use serde::{Serialize, de::DeserializeOwned}; use spatial::Spatial; use stardust_xr::messenger::MessageSenderHandle; @@ -190,7 +189,6 @@ impl Node { let aspect = self .aspects .0 - .lock() .get(&aspect_id) .ok_or(ScenegraphError::AspectNotFound)? .clone(); @@ -229,7 +227,7 @@ impl Node { response, ) } else { - let Some(aspect) = self.aspects.0.lock().get(&aspect_id).cloned() else { + let Some(aspect) = self.aspects.0.get(&aspect_id).map(|v| v.clone()) else { response.send(Err(ScenegraphError::AspectNotFound)); return; }; @@ -324,7 +322,7 @@ pub trait Aspect: Any + Send + Sync + 'static { } #[derive(Default)] -struct Aspects(Mutex>>); +struct Aspects(DashMap>); impl Aspects { fn add(&self, t: A) -> Arc { let aspect = Arc::new(t); @@ -332,13 +330,13 @@ impl Aspects { aspect } fn add_raw(&self, aspect: Arc) { - self.0.lock().insert(A::ID, aspect); + self.0.insert(A::ID, aspect); } fn get(&self) -> Result> { self.0 - .lock() .get(&A::ID) - .cloned() + // .cloned doesn't work for some reason + .map(|v| v.clone()) .map(|a| a.as_any()) .and_then(|a| Arc::downcast(a).ok()) .ok_or(ServerError::NoAspect(TypeId::of::())) @@ -346,6 +344,7 @@ impl Aspects { } impl Drop for Aspects { fn drop(&mut self) { - self.0.lock().clear() + // why would this be needed? do drop impls not run otherwise? + self.0.clear() } } -- 2.49.1 From 1be3e226707afb3f44085334a3ff54c541dd8984 Mon Sep 17 00:00:00 2001 From: Schmarni Date: Wed, 19 Mar 2025 17:57:28 +0100 Subject: [PATCH 4/4] feat: make stage tracking space always available Signed-off-by: Schmarni --- src/objects/mod.rs | 7 ++----- src/objects/play_space.rs | 21 ++++++++++++++------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/objects/mod.rs b/src/objects/mod.rs index d7495e9..b848b8e 100644 --- a/src/objects/mod.rs +++ b/src/objects/mod.rs @@ -17,7 +17,7 @@ use play_space::PlaySpaceBounds; use stardust_xr::schemas::dbus::object_registry::ObjectRegistry; use std::{ marker::PhantomData, - sync::{atomic::Ordering, Arc}, + sync::{Arc, atomic::Ordering}, }; use stereokit_rust::{ material::Material, @@ -65,10 +65,7 @@ impl ServerObjects { ) -> ServerObjects { let hmd = SpatialRef::create(&connection, "/org/stardustxr/HMD"); - let play_space = (World::has_bounds() - && World::get_bounds_size().x != 0.0 - && World::get_bounds_size().y != 0.0) - .then(|| SpatialRef::create(&connection, "/org/stardustxr/PlaySpace")); + let play_space = Some(SpatialRef::create(&connection, "/org/stardustxr/PlaySpace")); if play_space.is_some() { let dbus_connection = connection.clone(); tokio::task::spawn(async move { diff --git a/src/objects/play_space.rs b/src/objects/play_space.rs index 5061311..c392c9b 100644 --- a/src/objects/play_space.rs +++ b/src/objects/play_space.rs @@ -15,12 +15,19 @@ impl PlaySpaceBounds { impl PlaySpaceBounds { #[zbus(property)] fn bounds(&self) -> Vec<(f64, f64)> { - let bounds = World::get_bounds_size(); - vec![ - ((bounds.x).into(), (bounds.y).into()), - ((bounds.x).into(), (-bounds.y).into()), - ((-bounds.x).into(), (-bounds.y).into()), - ((-bounds.x).into(), (bounds.y).into()), - ] + if (World::has_bounds() + && World::get_bounds_size().x != 0.0 + && World::get_bounds_size().y != 0.0) + { + let bounds = World::get_bounds_size(); + vec![ + ((bounds.x).into(), (bounds.y).into()), + ((bounds.x).into(), (-bounds.y).into()), + ((-bounds.x).into(), (-bounds.y).into()), + ((-bounds.x).into(), (bounds.y).into()), + ] + } else { + vec![] + } } } -- 2.49.1