diff --git a/src/main.rs b/src/main.rs index 6afc4a3..0539760 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,11 +20,11 @@ use std::path::PathBuf; use std::process::Command; use std::sync::Arc; use std::time::Duration; -use stereokit::DisplayBlend; use stereokit::{ named_colors::BLACK, DepthMode, DisplayMode, Handed, LogLevel, StereoKitMultiThread, TextureFormat, TextureType, }; +use stereokit::{DisplayBlend, Sk}; use tokio::{runtime::Handle, sync::oneshot}; use tracing::{debug_span, error, info}; use tracing_subscriber::{fmt, prelude::*, EnvFilter}; @@ -50,6 +50,7 @@ struct CliArgs { } static STARDUST_INSTANCE: OnceCell = OnceCell::new(); +static SK_MULTITHREAD: OnceCell = OnceCell::new(); struct EventLoopInfo { tokio_handle: Handle, @@ -100,6 +101,7 @@ fn main() -> Result<()> { } .init() .expect("StereoKit failed to initialize"); + let _ = SK_MULTITHREAD.set(sk.multithreaded()); info!("Init StereoKit"); sk.material_set_shader( diff --git a/src/nodes/drawable/model.rs b/src/nodes/drawable/model.rs index 85ec8f7..3bd150b 100644 --- a/src/nodes/drawable/model.rs +++ b/src/nodes/drawable/model.rs @@ -1,11 +1,11 @@ use super::Node; use crate::core::client::Client; -use crate::core::destroy_queue; use crate::core::node_collections::LifeLinkedNodeMap; use crate::core::registry::Registry; use crate::core::resource::ResourceID; use crate::nodes::drawable::Drawable; use crate::nodes::spatial::{find_spatial_parent, parse_transform, Spatial}; +use crate::SK_MULTITHREAD; use color_eyre::eyre::{bail, ensure, eyre, Result}; use glam::Mat4; use mint::{ColumnMatrix4, Vector2, Vector3, Vector4}; @@ -18,7 +18,6 @@ use serde::Deserialize; use stardust_xr::schemas::flex::deserialize; use stardust_xr::values::Transform; use std::ffi::OsStr; -use std::fmt::Error; use std::path::PathBuf; use std::sync::{Arc, Weak}; use stereokit::named_colors::WHITE; @@ -124,7 +123,7 @@ pub struct ModelPart { pending_material_replacement: Mutex>>>, } impl ModelPart { - fn create_for_model(sk: &impl StereoKitDraw, model: &Arc, sk_model: &SKModel) { + fn create_for_model(sk: &impl StereoKitMultiThread, model: &Arc, sk_model: &SKModel) { let first_root_part = sk.model_node_get_root(sk_model); let mut current_option_part = Some(first_root_part); @@ -148,7 +147,7 @@ impl ModelPart { } fn create( - sk: &impl StereoKitDraw, + sk: &impl StereoKitMultiThread, model: &Arc, sk_model: &SKModel, id: i32, @@ -225,27 +224,23 @@ impl ModelPart { fn update(&self, sk: &impl StereoKitDraw) { let Some(model) = self.model.upgrade() else {return}; + let Some(sk_model) = model.sk_model.get() else {return}; let Some(node) = model.space.node() else {return}; let Some(client) = node.get_client() else {return}; - let Some(sk_model) = model.sk_model.get() else {return}; if let Some(material_replacement) = self.pending_material_replacement.lock().take() { - sk.model_node_set_material( - sk_model.as_ref(), - self.id, - material_replacement.as_ref().as_ref(), - ); + sk.model_node_set_material(sk_model, self.id, material_replacement.as_ref().as_ref()); } let mut material_parameters = self.pending_material_parameters.lock(); for (parameter_name, parameter_value) in material_parameters.drain() { - let Some(material) = sk.model_node_get_material(sk_model.as_ref(), self.id) else {continue}; + let Some(material) = sk.model_node_get_material(sk_model, self.id) else {continue}; let new_material = sk.material_copy(material); parameter_value.apply_to_material(&client, sk, &new_material, parameter_name.as_str()); - sk.model_node_set_material(sk_model.as_ref(), self.id, &new_material); + sk.model_node_set_material(sk_model, self.id, &new_material); } sk.model_node_set_transform_model( - sk_model.as_ref(), + sk_model, self.id, Spatial::space_to_space_matrix(Some(&self.space), Some(&model.space)), ); @@ -256,11 +251,12 @@ pub struct Model { self_ref: Weak, enabled: Arc, space: Arc, - resource_id: ResourceID, - pending_model_path: OnceCell, - sk_model: OnceCell>, + _resource_id: ResourceID, + sk_model: OnceCell, parts: LifeLinkedNodeMap, } +unsafe impl Send for Model {} +unsafe impl Sync for Model {} impl Model { pub fn add_to(node: &Arc, resource_id: ResourceID) -> Result> { @@ -272,54 +268,47 @@ impl Model { node.drawable.get().is_none(), "Internal: Node already has a drawable attached!" ); + + let pending_model_path = resource_id + .get_file( + &node + .get_client() + .ok_or_else(|| eyre!("Client not found"))? + .base_resource_prefixes + .lock() + .clone(), + &[OsStr::new("glb"), OsStr::new("gltf")], + ) + .ok_or_else(|| eyre!("Resource not found"))?; + let model = Arc::new_cyclic(|self_ref| Model { self_ref: self_ref.clone(), enabled: node.enabled.clone(), space: node.spatial.get().unwrap().clone(), - resource_id, - pending_model_path: OnceCell::new(), + _resource_id: resource_id, sk_model: OnceCell::new(), parts: LifeLinkedNodeMap::default(), }); MODEL_REGISTRY.add_raw(&model); - let _ = model.pending_model_path.set( - model - .resource_id - .get_file( - &node - .get_client() - .ok_or_else(|| eyre!("Client not found"))? - .base_resource_prefixes - .lock() - .clone(), - &[OsStr::new("glb"), OsStr::new("gltf")], - ) - .ok_or_else(|| eyre!("Resource not found"))?, - ); + + let sk = SK_MULTITHREAD.get().unwrap(); + let sk_model = + sk.model_create_file(pending_model_path.to_str().unwrap(), None::)?; + ModelPart::create_for_model(sk, &model.self_ref.upgrade().unwrap(), &sk_model); + let _ = model.sk_model.set(sk_model); let _ = node.drawable.set(Drawable::Model(model.clone())); Ok(model) } fn draw(&self, sk: &impl StereoKitDraw) { - let Ok(sk_model) = self - .sk_model - .get_or_try_init(|| -> color_eyre::eyre::Result> { - let pending_model_path = self.pending_model_path.get().ok_or(Error)?; - let model = - sk.model_create_file(pending_model_path.to_str().unwrap(), None::)?; - - ModelPart::create_for_model(sk, &self.self_ref.upgrade().unwrap(), &model); - - Ok(SendWrapper::new(sk.model_copy(model))) - }) else {return}; - + let Some(sk_model) = self.sk_model.get() else {return}; for model_node_node in self.parts.nodes() { let Some(Drawable::ModelPart(model_node)) = model_node_node.drawable.get() else {continue}; model_node.update(sk); } sk.model_draw( - sk_model.as_ref(), + sk_model, self.space.global_transform(), WHITE, RenderLayer::LAYER0, @@ -329,9 +318,6 @@ impl Model { impl Drop for Model { fn drop(&mut self) { - if let Some(model) = self.sk_model.take() { - destroy_queue::add(model); - } MODEL_REGISTRY.remove(self); } }