Skip to content

Commit b7773a5

Browse files
add an openxr backend
1 parent 9bd8e41 commit b7773a5

File tree

6 files changed

+708
-4
lines changed

6 files changed

+708
-4
lines changed

Cargo.lock

Lines changed: 89 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ name = "app_core"
1111

1212
[dependencies]
1313
bytemuck = { version = "1.24.0", features = ["derive"] }
14+
clap = { version = "4.5", features = ["derive"] }
1415
egui = "0.33.0"
1516
egui-wgpu = { version = "0.33.0", features = ["winit"] }
1617
futures = "0.3.31"
@@ -19,14 +20,18 @@ nalgebra-glm = { version = "0.20.0", features = [
1920
"convert-bytemuck",
2021
"serde-serialize",
2122
] }
23+
openxr = { version = "0.19", features = ["static", "loaded"], optional = true }
2224
web-time = "1.1.0"
2325
wgpu = { version = "27.0.1", default-features = false }
2426
winit = "0.30.12"
2527

2628
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
29+
ash = { version = "0.38", optional = true }
2730
env_logger = "0.11.8"
2831
egui-winit = "0.33.0"
32+
gpu-allocator = { version = "0.27", optional = true }
2933
pollster = "0.4.0"
34+
wgpu-hal = { version = "27.0.4", optional = true }
3035

3136
[target.'cfg(target_arch = "wasm32")'.dependencies]
3237
console_error_panic_hook = "0.1.7"
@@ -37,5 +42,6 @@ wasm-bindgen-futures = "0.4.55"
3742

3843
[features]
3944
default = ["wgpu/default"]
45+
openxr = ["dep:openxr", "dep:ash", "dep:wgpu-hal", "dep:gpu-allocator"]
4046
webgl = ["wgpu/webgl"]
4147
webgpu = ["wgpu/webgpu"]

justfile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ lint:
4141
run:
4242
cargo run -r
4343

44+
# Run the desktop app in OpenXR mode
45+
run-openxr:
46+
cargo run -r --features openxr -- --openxr
47+
4448
# Build the app with wgpu + WebGL
4549
build-webgl:
4650
trunk build --features webgl

src/lib.rs

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22
use wasm_bindgen::prelude::*;
33
use wgpu::InstanceDescriptor;
44

5+
#[cfg(all(not(target_arch = "wasm32"), feature = "openxr"))]
6+
pub mod xr;
7+
8+
#[cfg(all(not(target_arch = "wasm32"), feature = "openxr"))]
9+
pub use xr::run_xr;
10+
511
use std::sync::Arc;
612
use web_time::{Duration, Instant};
713
use winit::{
@@ -563,9 +569,67 @@ impl Gpu {
563569
surface_format,
564570
}
565571
}
572+
573+
#[cfg(not(target_arch = "wasm32"))]
574+
pub async fn new_async_headless() -> Self {
575+
let instance = wgpu::Instance::new(&InstanceDescriptor::default());
576+
577+
let adapter = instance
578+
.request_adapter(&wgpu::RequestAdapterOptions {
579+
power_preference: wgpu::PowerPreference::default(),
580+
compatible_surface: None,
581+
force_fallback_adapter: false,
582+
})
583+
.await
584+
.expect("Failed to request adapter!");
585+
586+
let (device, queue) = {
587+
log::info!("WGPU Adapter Features: {:#?}", adapter.features());
588+
adapter
589+
.request_device(&wgpu::DeviceDescriptor {
590+
label: Some("WGPU Device"),
591+
memory_hints: wgpu::MemoryHints::default(),
592+
required_features: wgpu::Features::default(),
593+
required_limits: wgpu::Limits::default().using_resolution(adapter.limits()),
594+
experimental_features: wgpu::ExperimentalFeatures::disabled(),
595+
trace: wgpu::Trace::Off,
596+
})
597+
.await
598+
.expect("Failed to request a device!")
599+
};
600+
601+
let surface_format = wgpu::TextureFormat::Rgba8UnormSrgb;
602+
let surface_config = wgpu::SurfaceConfiguration {
603+
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
604+
format: surface_format,
605+
width: 1,
606+
height: 1,
607+
present_mode: wgpu::PresentMode::Fifo,
608+
alpha_mode: wgpu::CompositeAlphaMode::Opaque,
609+
view_formats: vec![],
610+
desired_maximum_frame_latency: 2,
611+
};
612+
613+
let dummy_surface = unsafe {
614+
let handle = wgpu::rwh::RawDisplayHandle::Windows(wgpu::rwh::WindowsDisplayHandle::new());
615+
let window_handle = wgpu::rwh::RawWindowHandle::Win32(wgpu::rwh::Win32WindowHandle::new(std::num::NonZeroIsize::new(1).unwrap()));
616+
instance.create_surface_unsafe(wgpu::SurfaceTargetUnsafe::RawHandle {
617+
raw_display_handle: handle,
618+
raw_window_handle: window_handle,
619+
}).unwrap()
620+
};
621+
622+
Self {
623+
surface: dummy_surface,
624+
device,
625+
queue,
626+
surface_config,
627+
surface_format,
628+
}
629+
}
566630
}
567631

568-
struct Scene {
632+
pub struct Scene {
569633
pub model: nalgebra_glm::Mat4,
570634
pub vertex_buffer: wgpu::Buffer,
571635
pub index_buffer: wgpu::Buffer,
@@ -723,7 +787,7 @@ struct UniformBuffer {
723787
mvp: nalgebra_glm::Mat4,
724788
}
725789

726-
struct UniformBinding {
790+
pub struct UniformBinding {
727791
pub buffer: wgpu::Buffer,
728792
pub bind_group: wgpu::BindGroup,
729793
pub bind_group_layout: wgpu::BindGroupLayout,

src/main.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,22 @@
1-
// #![windows_subsystem = "windows"] // uncomment this to suppress terminal on windows
1+
use clap::Parser;
2+
3+
#[derive(Parser)]
4+
#[command(author, version, about, long_about = None)]
5+
struct Args {
6+
#[cfg(feature = "openxr")]
7+
#[arg(long)]
8+
openxr: bool,
9+
}
10+
11+
fn main() -> Result<(), Box<dyn std::error::Error>> {
12+
let args = Args::parse();
13+
14+
#[cfg(feature = "openxr")]
15+
if args.openxr {
16+
app_core::run_xr()?;
17+
return Ok(());
18+
}
219

3-
fn main() -> Result<(), winit::error::EventLoopError> {
420
let event_loop = winit::event_loop::EventLoop::builder().build()?;
521
event_loop.set_control_flow(winit::event_loop::ControlFlow::Poll);
622
let mut app = app_core::App::default();

0 commit comments

Comments
 (0)