Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: OpenXR integration #1387

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions wgpu-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@ trace = ["ron", "serde", "wgt/trace", "naga/serialize"]
replay = ["serde", "wgt/replay", "naga/deserialize"]
# Enable serializable compute/render passes, and bundle encoders.
serial-pass = ["serde", "wgt/serde", "arrayvec/serde"]
use-openxr = [
"openxr",
"hal/use-openxr",
"wgt/use-openxr",
"gfx-backend-vulkan/use-openxr",
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Current PR supports only Vulkan-based OpenXR (are others possible?)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think they are, at least dx and gl are supported by OpenXR.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

from what I've seen from the docs its GL and VK

#"gfx-backend-gl/use-openxr",
#"gfx-backend-metal/use-openxr",
#"gfx-backend-dx11/use-openxr",
#"gfx-backend-dx12/use-openxr"
]

[dependencies]
arrayvec = "0.5"
Expand Down
108 changes: 83 additions & 25 deletions wgpu-core/src/device/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,7 @@ impl<B: GfxBackend> Device<B> {
self_id: id::DeviceId,
adapter: &crate::instance::Adapter<B>,
desc: &resource::TextureDescriptor,
raw_image: Option<u64>,
) -> Result<resource::Texture<B>, resource::CreateTextureError> {
debug_assert_eq!(self_id.backend(), B::VARIANT);

Expand Down Expand Up @@ -653,34 +654,81 @@ impl<B: GfxBackend> Device<B> {

// TODO: 2D arrays, cubemap arrays

let mut image = unsafe {
let mut image = self
.raw
.create_image(
kind,
desc.mip_level_count as hal::image::Level,
format,
hal::image::Tiling::Optimal,
usage,
view_caps,
)
.map_err(|err| match err {
hal::image::CreationError::OutOfMemory(_) => DeviceError::OutOfMemory,
_ => panic!("failed to create texture: {}", err),
})?;
if let Some(ref label) = desc.label {
self.raw.set_image_name(&mut image, label);
let mut image = match raw_image {
None => {
unsafe {
let mut image = self
.raw
.create_image(
kind,
desc.mip_level_count as hal::image::Level,
format,
hal::image::Tiling::Optimal,
usage,
view_caps,
)
.map_err(|err| match err {
hal::image::CreationError::OutOfMemory(_) => DeviceError::OutOfMemory,
_ => panic!("failed to create texture: {}", err),
})?;
if let Some(ref label) = desc.label {
self.raw.set_image_name(&mut image, label);
}
image
}
}
image
Some(raw_image) => {
#[cfg(feature="use-openxr")]
unsafe {
let mut image = self
.raw
.create_image_from_openxr_raw_image(
kind,
desc.mip_level_count as hal::image::Level,
format,
hal::image::Tiling::Optimal,
usage,
view_caps,
raw_image
)
.map_err(|err| match err {
hal::image::CreationError::OutOfMemory(_) => DeviceError::OutOfMemory,
_ => panic!("failed to create texture: {}", err),
})?;
if let Some(ref label) = desc.label {
self.raw.set_image_name(&mut image, label);
}
image
}

#[cfg(not(feature="use-openxr"))]
panic!("OpenXR feature not enabled");
},
};

let requirements = unsafe { self.raw.get_image_requirements(&image) };
let block = self.mem_allocator.lock().allocate(
&self.raw,
requirements,
gpu_alloc::UsageFlags::FAST_DEVICE_ACCESS,
)?;
block.bind_image(&self.raw, &mut image)?;

let block = match raw_image {
None => {
let block = self.mem_allocator.lock().allocate(
&self.raw,
requirements,
gpu_alloc::UsageFlags::FAST_DEVICE_ACCESS,
)?;
block.bind_image(&self.raw, &mut image)?;
block
}
Some(_) => {
// FIXME this allocation is not required, since its already done by openxr
// tried setting size to 0, didn't work
let block = self.mem_allocator.lock().allocate(
&self.raw,
requirements,
gpu_alloc::UsageFlags::FAST_DEVICE_ACCESS,
)?;
block
}
};

Ok(resource::Texture {
raw: Some((image, block)),
Expand Down Expand Up @@ -2839,6 +2887,16 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
device_id: id::DeviceId,
desc: &resource::TextureDescriptor,
id_in: Input<G, id::TextureId>,
) -> (id::TextureId, Option<resource::CreateTextureError>) {
self.device_create_texture_raw_image::<B>(device_id, desc, None, id_in)
}

pub fn device_create_texture_raw_image<B: GfxBackend>(
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic here is modeled from https://github.com/Ralith/openxrs/blob/5283daa09ddbe7170069ff3ea9e42e8a8a9ff4bc/openxr/examples/vulkan.rs#L537 - basically a raw image is required for the swapchain

&self,
device_id: id::DeviceId,
desc: &resource::TextureDescriptor,
raw_image: Option<u64>,
id_in: Input<G, id::TextureId>,
) -> (id::TextureId, Option<resource::CreateTextureError>) {
span!(_guard, INFO, "Device::create_texture");

Expand All @@ -2853,7 +2911,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
Err(_) => break DeviceError::Invalid.into(),
};
let adapter = &adapter_guard[device.adapter_id.value];
let texture = match device.create_texture(device_id, adapter, desc) {
let texture = match device.create_texture(device_id, adapter, desc, raw_image) {
Ok(texture) => texture,
Err(error) => break error,
};
Expand Down
2 changes: 2 additions & 0 deletions wgpu-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ pub mod device;
pub mod hub;
pub mod id;
pub mod instance;
#[cfg(feature = "use-openxr")]
pub mod openxr;
mod memory_init_tracker;
pub mod pipeline;
pub mod resource;
Expand Down
124 changes: 124 additions & 0 deletions wgpu-core/src/openxr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
use openxr as xr;
use wgt::{
openxr::{OpenXRHandles, OpenXROptions},
Backend, BackendBit,
};

#[derive(Debug)]
pub struct WGPUOpenXR {
#[cfg(vulkan)]
pub vulkan: Option<gfx_backend_vulkan::OpenXR>,
/*
#[cfg(metal)]
pub metal: Option<gfx_backend_metal::OpenXR>,
#[cfg(dx12)]
pub dx12: Option<gfx_backend_dx12::OpenXR>,
#[cfg(dx11)]
pub dx11: Option<gfx_backend_dx11::OpenXR>,
#[cfg(gl)]
pub gl: Option<gfx_backend_gl::OpenXR>,
*/
}

impl WGPUOpenXR {
pub fn configure(
backends: BackendBit,
instance: xr::Instance,
_options: OpenXROptions, // FIXME use these
) -> WGPUOpenXR {
backends_map! {
let map = |(backend, openxr_configure)| {
if backends.contains(backend.into()) {
openxr_configure(instance).ok() // FIXME options
} else {
None
}
};
Self {
#[cfg(vulkan)]
vulkan: map((Backend::Vulkan, gfx_backend_vulkan::OpenXR::configure)),
/*
#[cfg(metal)]
metal: map((Backend::Metal, gfx_backend_metal::OpenXR::configure)),
#[cfg(dx12)]
dx12: map((Backend::Dx12, gfx_backend_dx12::OpenXR::configure)),
#[cfg(dx11)]
dx11: map((Backend::Dx11, gfx_backend_dx11::OpenXR::configure)),
#[cfg(gl)]
gl: map((Backend::Gl, gfx_backend_gl::OpenXR::configure)),
*/
}
}
}

/*
// FIXME add correct error
pub fn texture_from_raw_image<B, C>(
&self,
device: Arc<C>,
raw_image: u64,
resolution: Extent3d
) -> Result<resource::Texture<B>, resource::CreateTextureError> where B: hal::Backend {
let texture = self.texture_from_raw_image_inner(raw_image, resolution);

Ok(resource::Texture {
raw: Option<(B::Image, MemoryBlock<B>)>,
device_id: Stored<DeviceId>,
usage: wgt::TextureUsage,
aspects: hal::format::Aspects,
dimension: wgt::TextureDimension,
kind: hal::image::Kind,
format: wgt::TextureFormat,
format_features: wgt::TextureFormatFeatures,
framebuffer_attachment: hal::image::FramebufferAttachment,
full_range: TextureSelector,
life_guard: LifeGuard,
})
}

fn texture_from_raw_image_inner<B>(
&self,
raw_image: u64,
resolution: Extent3d
) -> Result<B::Image, ()> where B: hal::Backend {
backends_map! {
let map = |(is_backend, texture_from_raw_image)| {
if is_backend {
texture_from_raw_image(
raw_image,
hal::image::Kind::D2(resolution.width, resolution.height, 1, 1),
hal::image::ViewCapabilities::KIND_2D_ARRAY
)
} else {
Err(())
}
};

#[cfg(vulkan)]
map((self.vulkan.is_some(), gfx_backend_vulkan::OpenXR::texture_from_raw_image)),
}
}
*/

pub fn get_session_handles(&self) -> Option<OpenXRHandles> {
backends_map! {
let map = |(is_backend, get_session_handles)| {
if is_backend {
let ret = get_session_handles();
Some(OpenXRHandles {
session: ret.0,
frame_waiter: ret.1,
frame_stream: ret.2,
space: ret.3,
system: ret.4,
})
} else {
None
}
};

#[cfg(vulkan)]
map((self.vulkan.is_some(), gfx_backend_vulkan::OpenXR::get_session_handles)),
}
}
}
2 changes: 2 additions & 0 deletions wgpu-types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ license = "MPL-2.0"
[features]
trace = ["serde"]
replay = ["serde"]
use-openxr = ["openxr"]

[dependencies]
bitflags = "1.0"
serde = { version = "1.0", features = ["serde_derive"], optional = true }
openxr = { version = "0.14", features = ["loaded"], default-features = false, optional = true }
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eventually, is it okay to have openxr as an optional dependency?

4 changes: 4 additions & 0 deletions wgpu-types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
use serde::{Deserialize, Serialize};
use std::{num::NonZeroU32, ops::Range};

#[cfg(feature = "use-openxr")]
/// OpenXR
pub mod openxr;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Naming clash with openxr crate, other names?


/// Integral type used for buffer offsets.
pub type BufferAddress = u64;
/// Integral type used for buffer slice sizes.
Expand Down
24 changes: 24 additions & 0 deletions wgpu-types/src/openxr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/// Config
pub struct OpenXROptions {

}

impl Default for OpenXROptions {
fn default() -> Self {
OpenXROptions {}
}
}

/// FIXME FIXME FIXME is this okay?
pub struct OpenXRHandles {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These OpenXR concepts are required at engine-space (bevy) in order to communicate with openxr. This is one take at transferring them between

/// TODO: Documentation
pub session: openxr::Session<openxr::Vulkan>,
/// TODO: Documentation
pub frame_waiter: openxr::FrameWaiter,
/// TODO: Documentation
pub frame_stream: openxr::FrameStream<openxr::Vulkan>,
/// TODO: Documentation
pub space: openxr::Space,
/// TODO: Documentation
pub system: openxr::SystemId,
}