1 Commits

Author SHA1 Message Date
Nova
0ae20b23c5 feat: initial openxr stuff
feat: openxr system


refactor: rename oxr_runtime to openxr_runtime


refactor: make openxr methods/signals snake case


feat(openxr): session

feat(openxr): action, action set

feat(openxr/action): suggested bindings
2023-07-31 23:44:48 -04:00
10 changed files with 346 additions and 0 deletions

View File

@@ -14,6 +14,7 @@ path = "src/main.rs"
[features] [features]
default = ["wayland", "xwayland"] default = ["wayland", "xwayland"]
openxr_runtime = []
wayland = ["dep:smithay", "dep:xkbcommon"] wayland = ["dep:smithay", "dep:xkbcommon"]
xwayland = ["smithay/xwayland"] xwayland = ["smithay/xwayland"]
profile_tokio = ["dep:console-subscriber", "tokio/tracing"] profile_tokio = ["dep:console-subscriber", "tokio/tracing"]

View File

@@ -1,4 +1,6 @@
use super::scenegraph::Scenegraph; use super::scenegraph::Scenegraph;
#[cfg(feature = "oxr_runtime")]
use crate::openxr;
use crate::{ use crate::{
core::{registry::OwnedRegistry, task}, core::{registry::OwnedRegistry, task},
nodes::{ nodes::{
@@ -108,6 +110,8 @@ impl Client {
items::create_interface(&client)?; items::create_interface(&client)?;
input::create_interface(&client)?; input::create_interface(&client)?;
startup::create_interface(&client)?; startup::create_interface(&client)?;
#[cfg(feature = "openxr_runtime")]
openxr::create_interface(&client);
let pid_printable = pid let pid_printable = pid
.map(|pid| pid.to_string()) .map(|pid| pid.to_string())

View File

@@ -1,6 +1,8 @@
mod core; mod core;
mod nodes; mod nodes;
mod objects; mod objects;
#[cfg(feature = "openxr_runtime")]
mod openxr;
#[cfg(feature = "wayland")] #[cfg(feature = "wayland")]
mod wayland; mod wayland;
@@ -31,6 +33,8 @@ use tracing::metadata::LevelFilter;
use tracing::{debug_span, error, info}; use tracing::{debug_span, error, info};
use tracing_subscriber::{fmt, prelude::*, EnvFilter}; use tracing_subscriber::{fmt, prelude::*, EnvFilter};
pub static SK_INFO: OnceCell<SystemInfo> = OnceCell::new();
#[derive(Parser)] #[derive(Parser)]
#[clap(author, version, about, long_about = None)] #[clap(author, version, about, long_about = None)]
struct CliArgs { struct CliArgs {
@@ -114,6 +118,8 @@ fn main() {
let _ = SK_MULTITHREAD.set(sk.multithreaded()); let _ = SK_MULTITHREAD.set(sk.multithreaded());
info!("Init StereoKit"); info!("Init StereoKit");
SK_INFO.set(stereokit.system_info()).unwrap();
sk.material_set_shader( sk.material_set_shader(
sk.material_find("default/material_pbr").unwrap(), sk.material_find("default/material_pbr").unwrap(),
sk.shader_find("default/shader_pbr_clip").unwrap(), sk.shader_find("default/shader_pbr_clip").unwrap(),

View File

@@ -29,6 +29,8 @@ use tracing::{debug_span, instrument};
use crate::core::client::Client; use crate::core::client::Client;
use crate::core::registry::Registry; use crate::core::registry::Registry;
#[cfg(feature = "openxr_runtime")]
use crate::openxr;
use self::alias::Alias; use self::alias::Alias;
use self::audio::Sound; use self::audio::Sound;
@@ -101,6 +103,10 @@ pub struct Node {
// Startup // Startup
pub startup_settings: OnceCell<Mutex<StartupSettings>>, pub startup_settings: OnceCell<Mutex<StartupSettings>>,
// OpenXR
#[cfg(feature = "openxr_runtime")]
pub openxr_object: OnceCell<openxr::Object>,
} }
impl Node { impl Node {
@@ -144,6 +150,8 @@ impl Node {
item_acceptor: OnceCell::new(), item_acceptor: OnceCell::new(),
item_ui: OnceCell::new(), item_ui: OnceCell::new(),
sound: OnceCell::new(), sound: OnceCell::new(),
#[cfg(feature = "openxr_runtime")]
openxr_object: OnceCell::new(),
startup_settings: OnceCell::new(), startup_settings: OnceCell::new(),
}; };
node.add_local_signal("set_enabled", Node::set_enabled_flex); node.add_local_signal("set_enabled", Node::set_enabled_flex);

76
src/openxr/action.rs Normal file
View File

@@ -0,0 +1,76 @@
use super::Object;
use crate::{core::client::Client, nodes::Node};
use color_eyre::eyre::{bail, Result};
use parking_lot::Mutex;
use rustc_hash::FxHashMap;
use serde::Deserialize;
use stardust_xr::schemas::flex::deserialize;
use std::sync::Arc;
#[derive(Debug)]
pub struct Action {
// _info: InstanceInfo,
_localized_name: String,
suggested_bindings: Mutex<FxHashMap<String, String>>,
}
impl Action {
pub fn create_action_flex(
node: &Node,
_calling_client: Arc<Client>,
data: &[u8],
) -> Result<()> {
let Object::ActionSet(action_set) = node.get_aspect("OpenXR interface", "Instance", |n| &n.openxr_object)? else {
bail!("Object not an instance")
};
#[derive(Debug, Deserialize)]
struct CreateActionInfo {
name: String,
localized_name: String,
}
let info: CreateActionInfo = dbg!(deserialize(data)?);
let node = Node::create(
&node.get_client().unwrap(),
node.get_path(),
&info.name,
true,
)
.add_to_scenegraph();
node.add_local_signal("suggest_binding", Self::suggest_binding_flex);
let action = Arc::new(Action {
_localized_name: info.localized_name,
suggested_bindings: Mutex::new(FxHashMap::default()),
});
action_set
.actions
.lock()
.insert(info.name, Arc::downgrade(&action));
node.openxr_object.set(Object::Action(action)).unwrap();
Ok(())
}
pub fn suggest_binding_flex(
node: &Node,
_calling_client: Arc<Client>,
data: &[u8],
) -> Result<()> {
let Object::Action(action) = node.get_aspect("OpenXR interface", "Action", |n| &n.openxr_object)? else {
bail!("Object not an action")
};
#[derive(Debug, Deserialize)]
struct SuggestBindingArgs {
interaction_profile: String,
binding: String,
}
let args: SuggestBindingArgs = dbg!(deserialize(data)?);
action
.suggested_bindings
.lock()
.insert(args.interaction_profile, args.binding);
Ok(())
}
}

60
src/openxr/action_set.rs Normal file
View File

@@ -0,0 +1,60 @@
use super::{action::Action, Object};
use crate::{core::client::Client, nodes::Node};
use color_eyre::eyre::{bail, Result};
use parking_lot::Mutex;
use rustc_hash::FxHashMap;
use serde::Deserialize;
use stardust_xr::schemas::flex::deserialize;
use std::sync::{Arc, Weak};
#[derive(Debug)]
pub struct ActionSet {
// _info: InstanceInfo,
_localized_name: String,
_priority: u32,
pub actions: Mutex<FxHashMap<String, Weak<Action>>>,
}
impl ActionSet {
pub fn create_action_set_flex(
node: &Node,
_calling_client: Arc<Client>,
data: &[u8],
) -> Result<()> {
let Object::Instance(instance) = node.get_aspect("OpenXR interface", "Instance", |n| &n.openxr_object)? else {
bail!("Object not an instance")
};
let Some(instance) = instance.get() else { bail!("Instance not initialized") };
#[derive(Deserialize)]
struct CreateActionSetInfo {
name: String,
localized_name: String,
priority: u32,
}
let info: CreateActionSetInfo = deserialize(data)?;
let node = Node::create(
&node.get_client().unwrap(),
"/openxr/action_set",
&info.name,
true,
)
.add_to_scenegraph();
node.add_local_signal("create_action", Action::create_action_flex);
let action_set = Arc::new(ActionSet {
_localized_name: info.localized_name,
_priority: info.priority,
actions: Mutex::new(FxHashMap::default()),
});
instance
.action_sets
.lock()
.insert(info.name, Arc::downgrade(&action_set));
node.openxr_object
.set(Object::ActionSet(action_set))
.unwrap();
Ok(())
}
}

47
src/openxr/instance.rs Normal file
View File

@@ -0,0 +1,47 @@
use super::{action_set::ActionSet, Object};
use crate::{core::client::Client, nodes::Node};
use color_eyre::eyre::{bail, eyre, Result};
use parking_lot::Mutex;
use rustc_hash::FxHashMap;
use serde::Deserialize;
use stardust_xr::schemas::flex::deserialize;
use std::sync::{Arc, Weak};
#[derive(Debug, Deserialize)]
struct InstanceInfo {
_app_info: ApplicationInfo,
_extension_names: Vec<String>,
}
#[derive(Debug, Deserialize)]
struct ApplicationInfo {
_app_name: String,
_app_version: u32,
_engine_name: String,
_engine_version: u32,
_api_version: u64,
}
#[derive(Debug)]
pub struct Instance {
_info: InstanceInfo,
pub action_sets: Mutex<FxHashMap<String, Weak<ActionSet>>>,
}
impl Instance {
pub fn setup_instance_flex(
node: &Node,
_calling_client: Arc<Client>,
data: &[u8],
) -> Result<()> {
let Object::Instance(instance) = node.get_aspect("OpenXR interface", "Instance", |n| &n.openxr_object)? else {
bail!("Object not an instance")
};
let instance_info = Instance {
_info: deserialize(data)?,
action_sets: Mutex::new(FxHashMap::default()),
};
dbg!(&instance_info);
instance
.set(Arc::new(instance_info))
.map_err(|_| eyre!("Instance already set up"))
}
}

34
src/openxr/mod.rs Normal file
View File

@@ -0,0 +1,34 @@
mod action;
mod action_set;
mod instance;
mod session;
mod system;
use self::{
action::Action, action_set::ActionSet, instance::Instance, session::Session, system::System,
};
use crate::{core::client::Client, nodes::Node};
use once_cell::sync::OnceCell;
use std::sync::Arc;
#[derive(Debug)]
pub enum Object {
Instance(OnceCell<Arc<Instance>>),
System(System),
Session(Session),
ActionSet(Arc<ActionSet>),
Action(Arc<Action>),
}
pub fn create_interface(client: &Arc<Client>) {
let node = Node::create(client, "", "openxr", false);
node.add_local_signal("setup_instance", Instance::setup_instance_flex);
node.add_local_method("get_system", System::get_system_flex);
node.add_local_signal("create_action_set", ActionSet::create_action_set_flex);
node.openxr_object
.set(Object::Instance(OnceCell::new()))
.unwrap();
node.add_to_scenegraph();
}

34
src/openxr/session.rs Normal file
View File

@@ -0,0 +1,34 @@
use std::sync::Arc;
use color_eyre::eyre::{bail, Result};
use stardust_xr::schemas::flex::deserialize;
use super::Object;
use crate::{core::client::Client, nodes::Node};
#[derive(Debug)]
pub struct Session {
// _info: InstanceInfo,
}
impl Session {
pub fn create_session_flex(
node: &Node,
_calling_client: Arc<Client>,
data: &[u8],
) -> Result<()> {
let Object::System(_system) = node.get_aspect("OpenXR interface", "Instance", |n| &n.openxr_object)? else {
bail!("Object not a system")
};
let node = Node::create(
&node.get_client().unwrap(),
node.get_path(),
deserialize(data)?,
true,
)
.add_to_scenegraph();
let session = Session {};
node.openxr_object.set(Object::Session(session)).unwrap();
Ok(())
}
}

76
src/openxr/system.rs Normal file
View File

@@ -0,0 +1,76 @@
use super::{session::Session, Object};
use crate::{core::client::Client, nodes::Node, SK_INFO};
use color_eyre::eyre::{bail, eyre, Result};
use serde::Serialize;
use stardust_xr::schemas::flex::{deserialize, serialize};
use std::sync::Arc;
#[derive(Debug)]
pub enum System {
Handheld,
HeadMounted,
}
impl System {
pub fn from_raw(raw: u32) -> Option<Self> {
match raw {
1 => Some(System::Handheld),
2 => Some(System::HeadMounted),
_ => None,
}
}
pub fn get_system_flex(
node: &Node,
_calling_client: Arc<Client>,
data: &[u8],
) -> Result<Vec<u8>> {
// let Object::Instance(instance) = node.get_aspect("OpenXR interface", "Instance", |n| &n.openxr_object)? else {
// bail!("Object not an instance")
// };
let system_type: u32 = deserialize(data)?;
let system = System::from_raw(system_type).ok_or_else(|| eyre!("No system exists!"))?;
let node = Node::create(
&node.get_client().unwrap(),
node.get_path(),
&format!("system{}", system_type),
true,
)
.add_to_scenegraph();
node.add_local_method("views", System::views_flex);
node.add_local_signal("create_session", Session::create_session_flex);
node.openxr_object.set(Object::System(system)).unwrap();
Ok(serialize(system_type)?)
}
fn views_flex(_node: &Node, _calling_client: Arc<Client>, data: &[u8]) -> Result<Vec<u8>> {
let view_configuration_type: u64 = deserialize(data)?;
let view_count: u32 = match view_configuration_type {
1 => 1,
2 => 2,
1000037000 => 4,
1000054000 => 1,
_ => bail!("Invalid view config type"),
};
#[derive(Debug, Serialize)]
struct View {
recommended_image_rect_width: u32,
max_image_rect_width: u32,
recommended_image_rect_height: u32,
max_image_rect_height: u32,
}
let sk_info = SK_INFO.get().unwrap();
Ok(serialize(
(0..view_count)
.map(|_| View {
recommended_image_rect_width: sk_info.display_width,
max_image_rect_width: sk_info.display_width,
recommended_image_rect_height: sk_info.display_height,
max_image_rect_height: sk_info.display_height,
})
.collect::<Vec<_>>(),
)?)
}
}