From 01485e2020acf9036a4a1355da77e0fd71786c97 Mon Sep 17 00:00:00 2001 From: Nova Date: Mon, 19 Aug 2024 10:18:44 -0400 Subject: [PATCH 1/5] fix: stereokit rust to make it compile at all --- Cargo.lock | 45 +++++++++++++++++++++++++++++++++++++++++++-- Cargo.toml | 6 +++--- 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fd7771f..7643fc5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,6 +26,33 @@ dependencies = [ "memchr", ] +[[package]] +name = "android-activity" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef6978589202a00cd7e118380c448a08b6ed394c3a8df3a430d0898e3a42d046" +dependencies = [ + "android-properties", + "bitflags 2.6.0", + "cc", + "cesu8", + "jni", + "jni-sys", + "libc", + "log", + "ndk", + "ndk-context", + "ndk-sys", + "num_enum 0.7.2", + "thiserror", +] + +[[package]] +name = "android-properties" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" + [[package]] name = "android_log-sys" version = "0.3.1" @@ -479,6 +506,10 @@ name = "cc" version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2aba8f4e9906c7ce3c73463f62a7f0c65183ada1a2d47e397cc8810827f9694f" +dependencies = [ + "jobserver", + "libc", +] [[package]] name = "cesu8" @@ -1361,6 +1392,15 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + [[package]] name = "kdl" version = "4.6.0" @@ -2488,13 +2528,14 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "stereokit-macros" version = "0.1.0" -source = "git+https://github.com/technobaboo/StereoKit-rust.git#7dc90dc23537f7b71605612a8ce3a5e6f0a54eae" +source = "git+https://github.com/mvvvv/StereoKit-rust.git#2bfa9a812422a2b5b98db9979b5a4cc28cea151e" [[package]] name = "stereokit-rust" version = "0.1.0" -source = "git+https://github.com/technobaboo/StereoKit-rust.git#7dc90dc23537f7b71605612a8ce3a5e6f0a54eae" +source = "git+https://github.com/mvvvv/StereoKit-rust.git#2bfa9a812422a2b5b98db9979b5a4cc28cea151e" dependencies = [ + "android-activity", "android_logger", "bitflags 2.6.0", "cmake", diff --git a/Cargo.toml b/Cargo.toml index bc29a23..f8992a1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -107,9 +107,9 @@ optional = true [dependencies.stereokit-rust] # path = "../StereoKit-rust" -# git = "https://github.com/mvvvv/StereoKit-rust.git" -git = "https://github.com/technobaboo/StereoKit-rust.git" -features = ["force-local-deps"] +git = "https://github.com/mvvvv/StereoKit-rust.git" +# git = "https://github.com/technobaboo/StereoKit-rust.git" +features = ["no-event-loop"] default-features = false [dependencies.stardust-xr] From 6146a5b63a10d0e8c9b990e28ae6125437a47fe8 Mon Sep 17 00:00:00 2001 From: Nova Date: Tue, 20 Aug 2024 16:59:15 -0400 Subject: [PATCH 2/5] fix(model): rebatch identical materials to save on draw calls --- src/nodes/drawable/model.rs | 78 ++++++++++++++++++++++++++++++------- 1 file changed, 65 insertions(+), 13 deletions(-) diff --git a/src/nodes/drawable/model.rs b/src/nodes/drawable/model.rs index 87a932f..756c3d0 100644 --- a/src/nodes/drawable/model.rs +++ b/src/nodes/drawable/model.rs @@ -1,3 +1,4 @@ +use super::{MaterialParameter, ModelAspect, ModelPartAspect, MODEL_PART_ASPECT_ALIAS_INFO}; use crate::core::client::Client; use crate::core::registry::Registry; use crate::core::resource::get_resource_file; @@ -6,25 +7,71 @@ use crate::nodes::spatial::Spatial; use crate::nodes::{Aspect, Node}; use color_eyre::eyre::{bail, eyre, Result}; use glam::{Mat4, Vec2, Vec3}; -use once_cell::sync::OnceCell; +use once_cell::sync::{Lazy, OnceCell}; use parking_lot::Mutex; -use rustc_hash::FxHashMap; - +use rustc_hash::{FxHashMap, FxHashSet}; use stardust_xr::values::ResourceID; +use std::ffi::OsStr; +use std::hash::{Hash, Hasher}; +use std::sync::{Arc, Weak}; use stereokit_rust::material::Transparency; use stereokit_rust::maths::Bounds; use stereokit_rust::sk::MainThreadToken; use stereokit_rust::{material::Material, model::Model as SKModel, tex::Tex, util::Color128}; -use std::ffi::OsStr; -use std::sync::{Arc, Weak}; - -use super::{MaterialParameter, ModelAspect, ModelPartAspect, MODEL_PART_ASPECT_ALIAS_INFO}; - pub struct MaterialWrapper(pub Material); +impl Hash for MaterialWrapper { + fn hash(&self, state: &mut H) { + self.0.get_shader().0.as_ptr().hash(state); + for param in self.0.get_all_param_info() { + param.to_string().hash(state) + } + self.0.get_chain().map(MaterialWrapper).hash(state) + } +} +impl PartialEq for MaterialWrapper { + fn eq(&self, other: &Self) -> bool { + if self.0.get_shader().0.as_ptr() != other.0.get_shader().0.as_ptr() { + return false; + } + if self.0.get_all_param_info().count() != other.0.get_all_param_info().count() { + return false; + } + for self_param in self.0.get_all_param_info() { + let Some(other_param) = other + .0 + .get_all_param_info() + .get_data(self_param.get_name(), self_param.get_type()) + else { + return false; + }; + if self_param.to_string() != other_param.to_string() { + return false; + } + } + self.0.get_chain().map(MaterialWrapper) == other.0.get_chain().map(MaterialWrapper) + } +} +impl Eq for MaterialWrapper {} unsafe impl Send for MaterialWrapper {} unsafe impl Sync for MaterialWrapper {} +#[derive(Default)] +struct MaterialRegistry(Mutex>>); +impl MaterialRegistry { + fn add_or_get(&self, material: Arc) -> Arc { + let mut lock = self.0.lock(); + + if let Some(existing) = lock.get(&material) { + existing.clone() + } else { + lock.insert(material.clone()); + material + } + } +} + +static MATERIAL_REGISTRY: Lazy = Lazy::new(MaterialRegistry::default); static MODEL_REGISTRY: Registry = Registry::new(); static HOLDOUT_MATERIAL: OnceCell> = OnceCell::new(); @@ -156,9 +203,10 @@ impl ModelPart { } pub fn replace_material(&self, replacement: Arc) { + let shared_material = MATERIAL_REGISTRY.add_or_get(replacement); self.pending_material_replacement .lock() - .replace(replacement); + .replace(shared_material); } /// only to be run on the main thread pub fn replace_material_now(&self, replacement: &Material) { @@ -172,7 +220,9 @@ impl ModelPart { let Some(mut part) = nodes.get_index(self.id) else { return; }; - part.material(replacement); + let shared_material = + MATERIAL_REGISTRY.add_or_get(Arc::new(MaterialWrapper(replacement.copy()))); + part.material(&shared_material.0); } fn update(&self) { @@ -202,18 +252,20 @@ impl ModelPart { part.material(&material_replacement.0); } - // todo: find all materials with identical parameters and batch them into 1 material again 'mat_params: { let mut material_parameters = self.pending_material_parameters.lock(); if !material_parameters.is_empty() { let Some(material) = part.get_material() else { break 'mat_params; }; - let new_material = Material::copy(&material); - part.material(&new_material); + let new_material = material.copy(); for (parameter_name, parameter_value) in material_parameters.drain() { parameter_value.apply_to_material(&client, &new_material, ¶meter_name); } + + let shared_material = + MATERIAL_REGISTRY.add_or_get(Arc::new(MaterialWrapper(new_material))); + part.material(&shared_material.0); } } } From 21d10a15ee4ef567af10feefba917a351a22a9b7 Mon Sep 17 00:00:00 2001 From: Nova Date: Tue, 20 Aug 2024 16:59:37 -0400 Subject: [PATCH 3/5] clippy: cleanup --- src/nodes/input/hand.rs | 3 +++ src/objects/input/mouse_pointer.rs | 2 +- src/wayland/utils.rs | 12 ++---------- src/wayland/xdg_shell.rs | 12 ++++-------- 4 files changed, 10 insertions(+), 19 deletions(-) diff --git a/src/nodes/input/hand.rs b/src/nodes/input/hand.rs index 789d2e1..8512583 100644 --- a/src/nodes/input/hand.rs +++ b/src/nodes/input/hand.rs @@ -14,6 +14,7 @@ impl Default for Joint { } } } +#[allow(clippy::derivable_impls)] impl Default for Finger { fn default() -> Self { Finger { @@ -25,6 +26,7 @@ impl Default for Finger { } } } +#[allow(clippy::derivable_impls)] impl Default for Thumb { fn default() -> Self { Thumb { @@ -35,6 +37,7 @@ impl Default for Thumb { } } } +#[allow(clippy::derivable_impls)] impl Default for Hand { fn default() -> Self { Hand { diff --git a/src/objects/input/mouse_pointer.rs b/src/objects/input/mouse_pointer.rs index 1a2fe39..2e97a50 100644 --- a/src/objects/input/mouse_pointer.rs +++ b/src/objects/input/mouse_pointer.rs @@ -140,7 +140,7 @@ impl MousePointer { }); let valid = result.deepest_point_distance > 0.0 && result.min_distance.is_sign_negative(); - valid.then(|| result.deepest_point_distance) + valid.then_some(result.deepest_point_distance) }; self.capture_manager.update_capture(&self.pointer); diff --git a/src/wayland/utils.rs b/src/wayland/utils.rs index b6dc842..3625085 100644 --- a/src/wayland/utils.rs +++ b/src/wayland/utils.rs @@ -35,20 +35,12 @@ impl WlSurfaceExt for WlSurface { } fn get_current_surface_state(&self) -> SurfaceCachedState { compositor::with_states(self, |states| { - states - .cached_state - .get::() - .current() - .clone() + *states.cached_state.get::().current() }) } fn get_pending_surface_state(&self) -> SurfaceCachedState { compositor::with_states(self, |states| { - states - .cached_state - .get::() - .pending() - .clone() + *states.cached_state.get::().pending() }) } fn get_size(&self) -> Option> { diff --git a/src/wayland/xdg_shell.rs b/src/wayland/xdg_shell.rs index 50db4a0..8d2b83b 100644 --- a/src/wayland/xdg_shell.rs +++ b/src/wayland/xdg_shell.rs @@ -107,14 +107,10 @@ impl XdgShellHandler for WaylandState { .wl_surface() .max_size() .map(|s| Vector2::from([s.x as f32, s.y as f32])), - logical_rectangle: toplevel - .wl_surface() - .get_geometry() - .map(|r| r.into()) - .unwrap_or(Geometry { - origin: [0; 2].into(), - size: initial_size, - }), + logical_rectangle: toplevel.wl_surface().get_geometry().unwrap_or(Geometry { + origin: [0; 2].into(), + size: initial_size, + }), }; toplevel .wl_surface() From 853f779930776256ac3a6f2f30d0b155ed1455d8 Mon Sep 17 00:00:00 2001 From: Nova Date: Tue, 20 Aug 2024 17:18:48 -0400 Subject: [PATCH 4/5] fix(model): don't keep material references --- src/nodes/drawable/model.rs | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/nodes/drawable/model.rs b/src/nodes/drawable/model.rs index 756c3d0..01c396f 100644 --- a/src/nodes/drawable/model.rs +++ b/src/nodes/drawable/model.rs @@ -9,7 +9,7 @@ use color_eyre::eyre::{bail, eyre, Result}; use glam::{Mat4, Vec2, Vec3}; use once_cell::sync::{Lazy, OnceCell}; use parking_lot::Mutex; -use rustc_hash::{FxHashMap, FxHashSet}; +use rustc_hash::FxHashMap; use stardust_xr::values::ResourceID; use std::ffi::OsStr; use std::hash::{Hash, Hasher}; @@ -57,17 +57,25 @@ unsafe impl Send for MaterialWrapper {} unsafe impl Sync for MaterialWrapper {} #[derive(Default)] -struct MaterialRegistry(Mutex>>); +struct MaterialRegistry(Mutex>); impl MaterialRegistry { fn add_or_get(&self, material: Arc) -> Arc { let mut lock = self.0.lock(); + let hash = { + use std::hash::{Hash, Hasher}; + let mut hasher = std::collections::hash_map::DefaultHasher::new(); + material.hash(&mut hasher); + hasher.finish() + }; - if let Some(existing) = lock.get(&material) { - existing.clone() - } else { - lock.insert(material.clone()); - material + if let Some(id) = lock.get(&hash) { + if let Ok(existing) = Material::find(id) { + return Arc::new(MaterialWrapper(existing)); + } } + + lock.insert(hash, material.0.get_id().to_string()); + material } } From 62802367eb22f5aac15b62dc04db1a0ce68fd9c1 Mon Sep 17 00:00:00 2001 From: Nova Date: Tue, 20 Aug 2024 17:24:57 -0400 Subject: [PATCH 5/5] fix: clippy --- src/nodes/input/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/nodes/input/mod.rs b/src/nodes/input/mod.rs index 716918d..45e2955 100644 --- a/src/nodes/input/mod.rs +++ b/src/nodes/input/mod.rs @@ -1,3 +1,5 @@ +#![allow(clippy::needless_question_mark)] + mod hand; mod handler; mod method;