From 3cbc10d91e355c990e8cdf670a81585368eadd9f Mon Sep 17 00:00:00 2001 From: Nova Date: Thu, 6 Jun 2024 09:02:32 -0400 Subject: [PATCH] fix(model): no panic on material change --- src/nodes/audio.rs | 9 ++++----- src/nodes/drawable/model.rs | 16 ++++++++++------ src/nodes/input/method.rs | 4 ++-- src/nodes/items/camera.rs | 25 ++++++++++++++++--------- src/wayland/surface.rs | 24 ++++++++++++++++-------- 5 files changed, 48 insertions(+), 30 deletions(-) diff --git a/src/nodes/audio.rs b/src/nodes/audio.rs index 76ea51f..3ab3303 100644 --- a/src/nodes/audio.rs +++ b/src/nodes/audio.rs @@ -9,7 +9,6 @@ use color_eyre::eyre::{eyre, Result}; use glam::{vec3, Vec4Swizzles}; use once_cell::sync::OnceCell; use parking_lot::Mutex; -use send_wrapper::SendWrapper; use stardust_xr::values::ResourceID; use std::ops::DerefMut; @@ -25,7 +24,7 @@ pub struct Sound { volume: f32, pending_audio_path: PathBuf, - sk_sound: OnceCell>, + sk_sound: OnceCell, instance: Mutex>, stop: Mutex>, play: Mutex>, @@ -54,9 +53,9 @@ impl Sound { } fn update(&self) { - let sound = self.sk_sound.get_or_init(|| { - SendWrapper::new(SkSound::from_file(self.pending_audio_path.clone()).unwrap()) - }); + let sound = self + .sk_sound + .get_or_init(|| SkSound::from_file(self.pending_audio_path.clone()).unwrap()); if self.stop.lock().take().is_some() { if let Some(instance) = self.instance.lock().take() { instance.stop(); diff --git a/src/nodes/drawable/model.rs b/src/nodes/drawable/model.rs index 6c56942..337ae68 100644 --- a/src/nodes/drawable/model.rs +++ b/src/nodes/drawable/model.rs @@ -9,7 +9,7 @@ use glam::{Mat4, Vec2, Vec3}; use once_cell::sync::OnceCell; use parking_lot::Mutex; use rustc_hash::FxHashMap; -use send_wrapper::SendWrapper; + use stardust_xr::values::ResourceID; use stereokit_rust::material::Transparency; use stereokit_rust::maths::Bounds; @@ -21,8 +21,12 @@ use std::sync::{Arc, Weak}; use super::{MaterialParameter, ModelAspect, ModelPartAspect, MODEL_PART_ASPECT_ALIAS_INFO}; +pub struct MaterialWrapper(pub Material); +unsafe impl Send for MaterialWrapper {} +unsafe impl Sync for MaterialWrapper {} + static MODEL_REGISTRY: Registry = Registry::new(); -static HOLDOUT_MATERIAL: OnceCell>> = OnceCell::new(); +static HOLDOUT_MATERIAL: OnceCell> = OnceCell::new(); impl MaterialParameter { fn apply_to_material(&self, client: &Client, material: &Material, parameter_name: &str) { @@ -72,7 +76,7 @@ pub struct ModelPart { space: Arc, model: Weak, pending_material_parameters: Mutex>, - pending_material_replacement: Mutex>>>, + pending_material_replacement: Mutex>>, aliases: AliasList, } impl ModelPart { @@ -81,7 +85,7 @@ impl ModelPart { let mut mat = Material::copy(Material::unlit()); mat.transparency(Transparency::None); mat.color_tint(Color128::BLACK_TRANSPARENT); - Arc::new(SendWrapper::new(mat)) + Arc::new(MaterialWrapper(mat)) }); let nodes = sk_model.get_nodes(); @@ -151,7 +155,7 @@ impl ModelPart { Some(model_part) } - pub fn replace_material(&self, replacement: Arc>) { + pub fn replace_material(&self, replacement: Arc) { self.pending_material_replacement .lock() .replace(replacement); @@ -195,7 +199,7 @@ impl ModelPart { }; if let Some(material_replacement) = self.pending_material_replacement.lock().take() { - part.material(&**material_replacement); + part.material(&material_replacement.0); } // todo: find all materials with identical parameters and batch them into 1 material again diff --git a/src/nodes/input/method.rs b/src/nodes/input/method.rs index 227bcf2..26cd46a 100644 --- a/src/nodes/input/method.rs +++ b/src/nodes/input/method.rs @@ -45,12 +45,12 @@ impl InputMethod { handler_field_aliases: AliasList::default(), handler_order: Mutex::new(Vec::new()), }; + ::add_node_members(node); + ::add_node_members(node); for handler in INPUT_HANDLER_REGISTRY.get_valid_contents() { method.handle_new_handler(&handler); } let method = INPUT_METHOD_REGISTRY.add(method); - ::add_node_members(node); - ::add_node_members(node); node.add_aspect_raw(method.clone()); Ok(method) } diff --git a/src/nodes/items/camera.rs b/src/nodes/items/camera.rs index cf39188..094e870 100644 --- a/src/nodes/items/camera.rs +++ b/src/nodes/items/camera.rs @@ -5,7 +5,10 @@ use crate::{ core::{client::Client, registry::Registry, scenegraph::MethodResponseSender}, create_interface, nodes::{ - drawable::{model::ModelPart, shaders::UNLIT_SHADER_BYTES}, + drawable::{ + model::{MaterialWrapper, ModelPart}, + shaders::UNLIT_SHADER_BYTES, + }, items::TypeInfo, spatial::{Spatial, Transform}, Message, Node, @@ -17,7 +20,7 @@ use lazy_static::lazy_static; use mint::{ColumnMatrix4, Vector2}; use once_cell::sync::OnceCell; use parking_lot::Mutex; -use send_wrapper::SendWrapper; + use stardust_xr::schemas::flex::{deserialize, serialize}; use std::sync::Arc; use stereokit_rust::{ @@ -30,6 +33,10 @@ use stereokit_rust::{ }; use tracing::error; +pub struct TexWrapper(pub Tex); +unsafe impl Send for TexWrapper {} +unsafe impl Sync for TexWrapper {} + stardust_xr_server_codegen::codegen_item_camera_protocol!(); lazy_static! { pub(super) static ref ITEM_TYPE_INFO_CAMERA: TypeInfo = TypeInfo { @@ -53,8 +60,8 @@ struct FrameInfo { pub struct CameraItem { space: Arc, frame_info: Mutex, - sk_tex: OnceCell>, - sk_mat: OnceCell>>, + sk_tex: OnceCell, + sk_mat: OnceCell>, applied_to: Registry, apply_to: Registry, } @@ -120,7 +127,7 @@ impl CameraItem { pub fn update(&self, token: &MainThreadToken) { let frame_info = self.frame_info.lock(); let sk_tex = self.sk_tex.get_or_init(|| { - SendWrapper::new(Tex::gen_color( + TexWrapper(Tex::gen_color( Color128::default(), frame_info.px_size.x as i32, frame_info.px_size.y as i32, @@ -130,12 +137,12 @@ impl CameraItem { }); let sk_mat = self .sk_mat - .get_or_try_init(|| -> Result>> { + .get_or_try_init(|| -> Result> { let shader = Shader::from_memory(&UNLIT_SHADER_BYTES)?; let mut mat = Material::new(&shader, None); - mat.get_all_param_info().set_texture("diffuse", &**sk_tex); + mat.get_all_param_info().set_texture("diffuse", &sk_tex.0); mat.transparency(Transparency::Blend); - Ok(Arc::new(SendWrapper::new(mat))) + Ok(Arc::new(MaterialWrapper(mat))) }); let Ok(sk_mat) = sk_mat else { error!("unable to make camera item stereokit texture"); @@ -148,7 +155,7 @@ impl CameraItem { if !self.applied_to.is_empty() { Renderer::render_to( token, - &**sk_tex, + &sk_tex.0, self.space.global_transform(), frame_info.proj_matrix, None, diff --git a/src/wayland/surface.rs b/src/wayland/surface.rs index 5552068..b887757 100644 --- a/src/wayland/surface.rs +++ b/src/wayland/surface.rs @@ -1,11 +1,18 @@ use super::{state::WaylandState, utils::get_data}; use crate::{ core::{delta::Delta, destroy_queue, registry::Registry}, - nodes::drawable::{model::ModelPart, shaders::PANEL_SHADER_BYTES}, + nodes::{ + drawable::{ + model::{MaterialWrapper, ModelPart}, + shaders::PANEL_SHADER_BYTES, + }, + items::camera::TexWrapper, + }, }; use mint::Vector2; use once_cell::sync::OnceCell; use parking_lot::Mutex; + use send_wrapper::SendWrapper; use smithay::{ backend::renderer::{ @@ -42,8 +49,8 @@ pub struct CoreSurface { pub dh: DisplayHandle, pub weak_surface: wayland_server::Weak, mapped_data: Mutex>, - sk_tex: OnceCell>>, - sk_mat: OnceCell>>, + sk_tex: OnceCell>, + sk_mat: OnceCell>, material_offset: Mutex>, on_mapped: Mutex>, on_commit: Mutex>, @@ -93,7 +100,7 @@ impl CoreSurface { }; let sk_tex = self.sk_tex.get_or_init(|| { - SendWrapper::new(Mutex::new(Tex::new( + Mutex::new(TexWrapper(Tex::new( TexType::ImageNomips, TexFormat::RGBA32Linear, nanoid::nanoid!(), @@ -106,9 +113,9 @@ impl CoreSurface { // }); let mut mat = Material::new(shader, None); - mat.diffuse_tex(sk_tex.lock().as_ref()); + mat.diffuse_tex(&sk_tex.lock().0); mat.transparency(Transparency::Blend); - SendWrapper::new(Mutex::new(mat)) + Mutex::new(MaterialWrapper(mat)) }); // Let smithay handle buffer management (has to be done here as RendererSurfaceStates is not thread safe) @@ -154,6 +161,7 @@ impl CoreSurface { }; sk_tex .lock() + .0 .set_native_surface( smithay_tex.tex_id() as usize as *mut c_void, TexType::ImageNomips, @@ -167,7 +175,7 @@ impl CoreSurface { .address_mode(TexAddress::Clamp); if let Some(material_offset) = self.material_offset.lock().delta() { - sk_mat.lock().queue_offset(*material_offset as i32); + sk_mat.lock().0.queue_offset(*material_offset as i32); } let Some(surface_size) = renderer_surface_state.surface_size() else { @@ -212,7 +220,7 @@ impl CoreSurface { if let Some(sk_mat) = self.sk_mat.get() { let sk_mat = sk_mat.lock(); for model_node in self.pending_material_applications.get_valid_contents() { - model_node.replace_material_now(sk_mat.as_ref()); + model_node.replace_material_now(&sk_mat.0); } self.pending_material_applications.clear(); }