fix(model): no panic on material change
This commit is contained in:
@@ -9,7 +9,6 @@ use color_eyre::eyre::{eyre, Result};
|
|||||||
use glam::{vec3, Vec4Swizzles};
|
use glam::{vec3, Vec4Swizzles};
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use send_wrapper::SendWrapper;
|
|
||||||
use stardust_xr::values::ResourceID;
|
use stardust_xr::values::ResourceID;
|
||||||
|
|
||||||
use std::ops::DerefMut;
|
use std::ops::DerefMut;
|
||||||
@@ -25,7 +24,7 @@ pub struct Sound {
|
|||||||
|
|
||||||
volume: f32,
|
volume: f32,
|
||||||
pending_audio_path: PathBuf,
|
pending_audio_path: PathBuf,
|
||||||
sk_sound: OnceCell<SendWrapper<SkSound>>,
|
sk_sound: OnceCell<SkSound>,
|
||||||
instance: Mutex<Option<SoundInst>>,
|
instance: Mutex<Option<SoundInst>>,
|
||||||
stop: Mutex<Option<()>>,
|
stop: Mutex<Option<()>>,
|
||||||
play: Mutex<Option<()>>,
|
play: Mutex<Option<()>>,
|
||||||
@@ -54,9 +53,9 @@ impl Sound {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn update(&self) {
|
fn update(&self) {
|
||||||
let sound = self.sk_sound.get_or_init(|| {
|
let sound = self
|
||||||
SendWrapper::new(SkSound::from_file(self.pending_audio_path.clone()).unwrap())
|
.sk_sound
|
||||||
});
|
.get_or_init(|| SkSound::from_file(self.pending_audio_path.clone()).unwrap());
|
||||||
if self.stop.lock().take().is_some() {
|
if self.stop.lock().take().is_some() {
|
||||||
if let Some(instance) = self.instance.lock().take() {
|
if let Some(instance) = self.instance.lock().take() {
|
||||||
instance.stop();
|
instance.stop();
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use glam::{Mat4, Vec2, Vec3};
|
|||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use send_wrapper::SendWrapper;
|
|
||||||
use stardust_xr::values::ResourceID;
|
use stardust_xr::values::ResourceID;
|
||||||
use stereokit_rust::material::Transparency;
|
use stereokit_rust::material::Transparency;
|
||||||
use stereokit_rust::maths::Bounds;
|
use stereokit_rust::maths::Bounds;
|
||||||
@@ -21,8 +21,12 @@ use std::sync::{Arc, Weak};
|
|||||||
|
|
||||||
use super::{MaterialParameter, ModelAspect, ModelPartAspect, MODEL_PART_ASPECT_ALIAS_INFO};
|
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<Model> = Registry::new();
|
static MODEL_REGISTRY: Registry<Model> = Registry::new();
|
||||||
static HOLDOUT_MATERIAL: OnceCell<Arc<SendWrapper<Material>>> = OnceCell::new();
|
static HOLDOUT_MATERIAL: OnceCell<Arc<MaterialWrapper>> = OnceCell::new();
|
||||||
|
|
||||||
impl MaterialParameter {
|
impl MaterialParameter {
|
||||||
fn apply_to_material(&self, client: &Client, material: &Material, parameter_name: &str) {
|
fn apply_to_material(&self, client: &Client, material: &Material, parameter_name: &str) {
|
||||||
@@ -72,7 +76,7 @@ pub struct ModelPart {
|
|||||||
space: Arc<Spatial>,
|
space: Arc<Spatial>,
|
||||||
model: Weak<Model>,
|
model: Weak<Model>,
|
||||||
pending_material_parameters: Mutex<FxHashMap<String, MaterialParameter>>,
|
pending_material_parameters: Mutex<FxHashMap<String, MaterialParameter>>,
|
||||||
pending_material_replacement: Mutex<Option<Arc<SendWrapper<Material>>>>,
|
pending_material_replacement: Mutex<Option<Arc<MaterialWrapper>>>,
|
||||||
aliases: AliasList,
|
aliases: AliasList,
|
||||||
}
|
}
|
||||||
impl ModelPart {
|
impl ModelPart {
|
||||||
@@ -81,7 +85,7 @@ impl ModelPart {
|
|||||||
let mut mat = Material::copy(Material::unlit());
|
let mut mat = Material::copy(Material::unlit());
|
||||||
mat.transparency(Transparency::None);
|
mat.transparency(Transparency::None);
|
||||||
mat.color_tint(Color128::BLACK_TRANSPARENT);
|
mat.color_tint(Color128::BLACK_TRANSPARENT);
|
||||||
Arc::new(SendWrapper::new(mat))
|
Arc::new(MaterialWrapper(mat))
|
||||||
});
|
});
|
||||||
|
|
||||||
let nodes = sk_model.get_nodes();
|
let nodes = sk_model.get_nodes();
|
||||||
@@ -151,7 +155,7 @@ impl ModelPart {
|
|||||||
Some(model_part)
|
Some(model_part)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn replace_material(&self, replacement: Arc<SendWrapper<Material>>) {
|
pub fn replace_material(&self, replacement: Arc<MaterialWrapper>) {
|
||||||
self.pending_material_replacement
|
self.pending_material_replacement
|
||||||
.lock()
|
.lock()
|
||||||
.replace(replacement);
|
.replace(replacement);
|
||||||
@@ -195,7 +199,7 @@ impl ModelPart {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if let Some(material_replacement) = self.pending_material_replacement.lock().take() {
|
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
|
// todo: find all materials with identical parameters and batch them into 1 material again
|
||||||
|
|||||||
@@ -45,12 +45,12 @@ impl InputMethod {
|
|||||||
handler_field_aliases: AliasList::default(),
|
handler_field_aliases: AliasList::default(),
|
||||||
handler_order: Mutex::new(Vec::new()),
|
handler_order: Mutex::new(Vec::new()),
|
||||||
};
|
};
|
||||||
|
<InputMethod as InputMethodRefAspect>::add_node_members(node);
|
||||||
|
<InputMethod as InputMethodAspect>::add_node_members(node);
|
||||||
for handler in INPUT_HANDLER_REGISTRY.get_valid_contents() {
|
for handler in INPUT_HANDLER_REGISTRY.get_valid_contents() {
|
||||||
method.handle_new_handler(&handler);
|
method.handle_new_handler(&handler);
|
||||||
}
|
}
|
||||||
let method = INPUT_METHOD_REGISTRY.add(method);
|
let method = INPUT_METHOD_REGISTRY.add(method);
|
||||||
<InputMethod as InputMethodRefAspect>::add_node_members(node);
|
|
||||||
<InputMethod as InputMethodAspect>::add_node_members(node);
|
|
||||||
node.add_aspect_raw(method.clone());
|
node.add_aspect_raw(method.clone());
|
||||||
Ok(method)
|
Ok(method)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,10 @@ use crate::{
|
|||||||
core::{client::Client, registry::Registry, scenegraph::MethodResponseSender},
|
core::{client::Client, registry::Registry, scenegraph::MethodResponseSender},
|
||||||
create_interface,
|
create_interface,
|
||||||
nodes::{
|
nodes::{
|
||||||
drawable::{model::ModelPart, shaders::UNLIT_SHADER_BYTES},
|
drawable::{
|
||||||
|
model::{MaterialWrapper, ModelPart},
|
||||||
|
shaders::UNLIT_SHADER_BYTES,
|
||||||
|
},
|
||||||
items::TypeInfo,
|
items::TypeInfo,
|
||||||
spatial::{Spatial, Transform},
|
spatial::{Spatial, Transform},
|
||||||
Message, Node,
|
Message, Node,
|
||||||
@@ -17,7 +20,7 @@ use lazy_static::lazy_static;
|
|||||||
use mint::{ColumnMatrix4, Vector2};
|
use mint::{ColumnMatrix4, Vector2};
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use send_wrapper::SendWrapper;
|
|
||||||
use stardust_xr::schemas::flex::{deserialize, serialize};
|
use stardust_xr::schemas::flex::{deserialize, serialize};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use stereokit_rust::{
|
use stereokit_rust::{
|
||||||
@@ -30,6 +33,10 @@ use stereokit_rust::{
|
|||||||
};
|
};
|
||||||
use tracing::error;
|
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!();
|
stardust_xr_server_codegen::codegen_item_camera_protocol!();
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub(super) static ref ITEM_TYPE_INFO_CAMERA: TypeInfo = TypeInfo {
|
pub(super) static ref ITEM_TYPE_INFO_CAMERA: TypeInfo = TypeInfo {
|
||||||
@@ -53,8 +60,8 @@ struct FrameInfo {
|
|||||||
pub struct CameraItem {
|
pub struct CameraItem {
|
||||||
space: Arc<Spatial>,
|
space: Arc<Spatial>,
|
||||||
frame_info: Mutex<FrameInfo>,
|
frame_info: Mutex<FrameInfo>,
|
||||||
sk_tex: OnceCell<SendWrapper<Tex>>,
|
sk_tex: OnceCell<TexWrapper>,
|
||||||
sk_mat: OnceCell<Arc<SendWrapper<Material>>>,
|
sk_mat: OnceCell<Arc<MaterialWrapper>>,
|
||||||
applied_to: Registry<ModelPart>,
|
applied_to: Registry<ModelPart>,
|
||||||
apply_to: Registry<ModelPart>,
|
apply_to: Registry<ModelPart>,
|
||||||
}
|
}
|
||||||
@@ -120,7 +127,7 @@ impl CameraItem {
|
|||||||
pub fn update(&self, token: &MainThreadToken) {
|
pub fn update(&self, token: &MainThreadToken) {
|
||||||
let frame_info = self.frame_info.lock();
|
let frame_info = self.frame_info.lock();
|
||||||
let sk_tex = self.sk_tex.get_or_init(|| {
|
let sk_tex = self.sk_tex.get_or_init(|| {
|
||||||
SendWrapper::new(Tex::gen_color(
|
TexWrapper(Tex::gen_color(
|
||||||
Color128::default(),
|
Color128::default(),
|
||||||
frame_info.px_size.x as i32,
|
frame_info.px_size.x as i32,
|
||||||
frame_info.px_size.y as i32,
|
frame_info.px_size.y as i32,
|
||||||
@@ -130,12 +137,12 @@ impl CameraItem {
|
|||||||
});
|
});
|
||||||
let sk_mat = self
|
let sk_mat = self
|
||||||
.sk_mat
|
.sk_mat
|
||||||
.get_or_try_init(|| -> Result<Arc<SendWrapper<Material>>> {
|
.get_or_try_init(|| -> Result<Arc<MaterialWrapper>> {
|
||||||
let shader = Shader::from_memory(&UNLIT_SHADER_BYTES)?;
|
let shader = Shader::from_memory(&UNLIT_SHADER_BYTES)?;
|
||||||
let mut mat = Material::new(&shader, None);
|
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);
|
mat.transparency(Transparency::Blend);
|
||||||
Ok(Arc::new(SendWrapper::new(mat)))
|
Ok(Arc::new(MaterialWrapper(mat)))
|
||||||
});
|
});
|
||||||
let Ok(sk_mat) = sk_mat else {
|
let Ok(sk_mat) = sk_mat else {
|
||||||
error!("unable to make camera item stereokit texture");
|
error!("unable to make camera item stereokit texture");
|
||||||
@@ -148,7 +155,7 @@ impl CameraItem {
|
|||||||
if !self.applied_to.is_empty() {
|
if !self.applied_to.is_empty() {
|
||||||
Renderer::render_to(
|
Renderer::render_to(
|
||||||
token,
|
token,
|
||||||
&**sk_tex,
|
&sk_tex.0,
|
||||||
self.space.global_transform(),
|
self.space.global_transform(),
|
||||||
frame_info.proj_matrix,
|
frame_info.proj_matrix,
|
||||||
None,
|
None,
|
||||||
|
|||||||
@@ -1,11 +1,18 @@
|
|||||||
use super::{state::WaylandState, utils::get_data};
|
use super::{state::WaylandState, utils::get_data};
|
||||||
use crate::{
|
use crate::{
|
||||||
core::{delta::Delta, destroy_queue, registry::Registry},
|
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 mint::Vector2;
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
|
||||||
use send_wrapper::SendWrapper;
|
use send_wrapper::SendWrapper;
|
||||||
use smithay::{
|
use smithay::{
|
||||||
backend::renderer::{
|
backend::renderer::{
|
||||||
@@ -42,8 +49,8 @@ pub struct CoreSurface {
|
|||||||
pub dh: DisplayHandle,
|
pub dh: DisplayHandle,
|
||||||
pub weak_surface: wayland_server::Weak<WlSurface>,
|
pub weak_surface: wayland_server::Weak<WlSurface>,
|
||||||
mapped_data: Mutex<Option<CoreSurfaceData>>,
|
mapped_data: Mutex<Option<CoreSurfaceData>>,
|
||||||
sk_tex: OnceCell<SendWrapper<Mutex<Tex>>>,
|
sk_tex: OnceCell<Mutex<TexWrapper>>,
|
||||||
sk_mat: OnceCell<SendWrapper<Mutex<Material>>>,
|
sk_mat: OnceCell<Mutex<MaterialWrapper>>,
|
||||||
material_offset: Mutex<Delta<u32>>,
|
material_offset: Mutex<Delta<u32>>,
|
||||||
on_mapped: Mutex<Box<dyn Fn() + Send + Sync>>,
|
on_mapped: Mutex<Box<dyn Fn() + Send + Sync>>,
|
||||||
on_commit: Mutex<Box<dyn Fn(u32) + Send + Sync>>,
|
on_commit: Mutex<Box<dyn Fn(u32) + Send + Sync>>,
|
||||||
@@ -93,7 +100,7 @@ impl CoreSurface {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let sk_tex = self.sk_tex.get_or_init(|| {
|
let sk_tex = self.sk_tex.get_or_init(|| {
|
||||||
SendWrapper::new(Mutex::new(Tex::new(
|
Mutex::new(TexWrapper(Tex::new(
|
||||||
TexType::ImageNomips,
|
TexType::ImageNomips,
|
||||||
TexFormat::RGBA32Linear,
|
TexFormat::RGBA32Linear,
|
||||||
nanoid::nanoid!(),
|
nanoid::nanoid!(),
|
||||||
@@ -106,9 +113,9 @@ impl CoreSurface {
|
|||||||
// });
|
// });
|
||||||
|
|
||||||
let mut mat = Material::new(shader, None);
|
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);
|
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)
|
// Let smithay handle buffer management (has to be done here as RendererSurfaceStates is not thread safe)
|
||||||
@@ -154,6 +161,7 @@ impl CoreSurface {
|
|||||||
};
|
};
|
||||||
sk_tex
|
sk_tex
|
||||||
.lock()
|
.lock()
|
||||||
|
.0
|
||||||
.set_native_surface(
|
.set_native_surface(
|
||||||
smithay_tex.tex_id() as usize as *mut c_void,
|
smithay_tex.tex_id() as usize as *mut c_void,
|
||||||
TexType::ImageNomips,
|
TexType::ImageNomips,
|
||||||
@@ -167,7 +175,7 @@ impl CoreSurface {
|
|||||||
.address_mode(TexAddress::Clamp);
|
.address_mode(TexAddress::Clamp);
|
||||||
|
|
||||||
if let Some(material_offset) = self.material_offset.lock().delta() {
|
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 {
|
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() {
|
if let Some(sk_mat) = self.sk_mat.get() {
|
||||||
let sk_mat = sk_mat.lock();
|
let sk_mat = sk_mat.lock();
|
||||||
for model_node in self.pending_material_applications.get_valid_contents() {
|
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();
|
self.pending_material_applications.clear();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user