From 0a7f692a3549d6b6d3e601330308933e07589f19 Mon Sep 17 00:00:00 2001 From: Schmarni Date: Mon, 24 Jun 2024 23:09:58 +0200 Subject: [PATCH] add session creation next chain infrastructure Signed-off-by: Schmarni --- crates/bevy_openxr/src/openxr/graphics.rs | 9 +++- .../bevy_openxr/src/openxr/graphics/d3d12.rs | 46 +++++++++++++++++ .../bevy_openxr/src/openxr/graphics/vulkan.rs | 51 ++++++++++++++++++- crates/bevy_openxr/src/openxr/init.rs | 6 ++- crates/bevy_openxr/src/openxr/resources.rs | 5 +- crates/bevy_openxr/src/openxr/session.rs | 22 ++++++++ 6 files changed, 134 insertions(+), 5 deletions(-) diff --git a/crates/bevy_openxr/src/openxr/graphics.rs b/crates/bevy_openxr/src/openxr/graphics.rs index aa93290..caa22a9 100644 --- a/crates/bevy_openxr/src/openxr/graphics.rs +++ b/crates/bevy_openxr/src/openxr/graphics.rs @@ -6,8 +6,9 @@ pub mod vulkan; use std::any::TypeId; use bevy::math::UVec2; +use openxr::{FrameStream, FrameWaiter, Session}; -use crate::types::{AppInfo, OxrExtensions, Result, WgpuGraphics}; +use crate::{session::OxrSessionCreateNextChain, types::{AppInfo, OxrExtensions, Result, WgpuGraphics}}; /// This is an extension trait to the [`Graphics`](openxr::Graphics) trait and is how the graphics API should be interacted with. pub unsafe trait GraphicsExt: openxr::Graphics { @@ -36,6 +37,12 @@ pub unsafe trait GraphicsExt: openxr::Graphics { instance: &openxr::Instance, system_id: openxr::SystemId, ) -> Result<(WgpuGraphics, Self::SessionCreateInfo)>; + unsafe fn create_session( + instance: &openxr::Instance, + system_id: openxr::SystemId, + info: &Self::SessionCreateInfo, + session_create_info_chain: &mut OxrSessionCreateNextChain, + ) -> openxr::Result<(Session, FrameWaiter, FrameStream)>; } /// A type that can be used in [`GraphicsWrap`]. diff --git a/crates/bevy_openxr/src/openxr/graphics/d3d12.rs b/crates/bevy_openxr/src/openxr/graphics/d3d12.rs index 82dca9a..b633a66 100644 --- a/crates/bevy_openxr/src/openxr/graphics/d3d12.rs +++ b/crates/bevy_openxr/src/openxr/graphics/d3d12.rs @@ -1,10 +1,12 @@ use bevy::log::error; +use openxr::sys; use wgpu_hal::{Adapter, Instance}; use winapi::shared::dxgiformat::DXGI_FORMAT; use winapi::um::d3d12 as winapi_d3d12; use super::{GraphicsExt, GraphicsType, GraphicsWrap}; use crate::error::OxrError; +use crate::session::OxrSessionCreateNextChain; use crate::types::{AppInfo, OxrExtensions, Result, WgpuGraphics}; unsafe impl GraphicsExt for openxr::D3D12 { @@ -155,6 +157,49 @@ unsafe impl GraphicsExt for openxr::D3D12 { }, )) } + + unsafe fn create_session( + instance: &openxr::Instance, + system_id: openxr::SystemId, + info: &Self::SessionCreateInfo, + session_create_info_chain: &mut OxrSessionCreateNextChain, + ) -> openxr::Result<( + openxr::Session, + openxr::FrameWaiter, + openxr::FrameStream, + )> { + let binding = sys::GraphicsBindingD3D12KHR { + ty: sys::GraphicsBindingD3D12KHR::TYPE, + next: session_create_info_chain.chain_pointer(), + device: info.device, + queue: info.queue, + }; + let info = sys::SessionCreateInfo { + ty: sys::SessionCreateInfo::TYPE, + next: &binding as *const _ as *const _, + create_flags: Default::default(), + system_id: system_id, + }; + let mut out = sys::Session::NULL; + cvt((instance.fp().create_session)( + instance.as_raw(), + &info, + &mut out, + ))?; + Ok(openxr::Session::from_raw( + instance.clone(), + out, + Box::new(()), + )) + } +} + +fn cvt(x: sys::Result) -> openxr::Result { + if x.into_raw() >= 0 { + Ok(x) + } else { + Err(x) + } } // Extracted from https://github.com/gfx-rs/wgpu/blob/1161a22f4fbb4fc204eb06f2ac4243f83e0e980d/wgpu-hal/src/dx12/adapter.rs#L73-L94 @@ -345,3 +390,4 @@ fn wgpu_to_d3d12(format: wgpu::TextureFormat) -> Option { } => return None, }) } + diff --git a/crates/bevy_openxr/src/openxr/graphics/vulkan.rs b/crates/bevy_openxr/src/openxr/graphics/vulkan.rs index 7a52a38..da1d733 100644 --- a/crates/bevy_openxr/src/openxr/graphics/vulkan.rs +++ b/crates/bevy_openxr/src/openxr/graphics/vulkan.rs @@ -3,12 +3,13 @@ use std::ffi::{c_void, CString}; use ash::vk::Handle; use bevy::log::error; use bevy::math::UVec2; -use openxr::Version; +use openxr::{sys, Version}; use wgpu_hal::api::Vulkan; use wgpu_hal::Api; use super::{GraphicsExt, GraphicsType, GraphicsWrap}; use crate::error::OxrError; +use crate::session::OxrSessionCreateNextChain; use crate::types::{AppInfo, OxrExtensions, Result, WgpuGraphics}; #[cfg(not(target_os = "android"))] @@ -294,6 +295,53 @@ unsafe impl GraphicsExt for openxr::Vulkan { }, )) } + + unsafe fn create_session( + instance: &openxr::Instance, + system_id: openxr::SystemId, + info: &Self::SessionCreateInfo, + session_create_info_chain: &mut OxrSessionCreateNextChain, + ) -> openxr::Result<( + openxr::Session, + openxr::FrameWaiter, + openxr::FrameStream, + )> { + let next_ptr = session_create_info_chain.chain_pointer(); + let binding = sys::GraphicsBindingVulkanKHR { + ty: sys::GraphicsBindingVulkanKHR::TYPE, + next: next_ptr, + instance: info.instance, + physical_device: info.physical_device, + device: info.device, + queue_family_index: info.queue_family_index, + queue_index: info.queue_index, + }; + let info = sys::SessionCreateInfo { + ty: sys::SessionCreateInfo::TYPE, + next: &binding as *const _ as *const _, + create_flags: Default::default(), + system_id: system_id, + }; + let mut out = sys::Session::NULL; + cvt((instance.fp().create_session)( + instance.as_raw(), + &info, + &mut out, + ))?; + Ok(openxr::Session::from_raw( + instance.clone(), + out, + Box::new(()), + )) + } +} + +fn cvt(x: sys::Result) -> openxr::Result { + if x.into_raw() >= 0 { + Ok(x) + } else { + Err(x) + } } fn vulkan_to_wgpu(format: ash::vk::Format) -> Option { @@ -676,3 +724,4 @@ fn wgpu_to_vulkan(format: wgpu::TextureFormat) -> Option { }, }) } + diff --git a/crates/bevy_openxr/src/openxr/init.rs b/crates/bevy_openxr/src/openxr/init.rs index 8fada5f..e216249 100644 --- a/crates/bevy_openxr/src/openxr/init.rs +++ b/crates/bevy_openxr/src/openxr/init.rs @@ -31,6 +31,7 @@ use crate::error::OxrError; use crate::graphics::*; use crate::resources::*; use crate::session::OxrSession; +use crate::session::OxrSessionCreateNextChain; use crate::session::OxrSessionStatusEvent; use crate::types::*; @@ -281,6 +282,7 @@ fn init_xr_session( device: &wgpu::Device, instance: &OxrInstance, system_id: openxr::SystemId, + chain: &mut OxrSessionCreateNextChain, SessionConfigInfo { blend_modes, formats, @@ -296,7 +298,7 @@ fn init_xr_session( OxrGraphicsInfo, )> { let (session, frame_waiter, frame_stream) = - unsafe { instance.create_session(system_id, graphics_info)? }; + unsafe { instance.create_session(system_id, graphics_info, chain)? }; // TODO!() support other view configurations let available_view_configurations = instance.enumerate_view_configurations(system_id)?; @@ -440,12 +442,14 @@ pub fn create_xr_session( instance: Res, create_info: NonSend, system_id: Res, + mut chain: NonSendMut, mut commands: Commands, ) { match init_xr_session( device.wgpu_device(), &instance, **system_id, + &mut chain, create_info.clone(), ) { Ok((session, frame_waiter, frame_stream, swapchain, images, graphics_info)) => { diff --git a/crates/bevy_openxr/src/openxr/resources.rs b/crates/bevy_openxr/src/openxr/resources.rs index 76de551..15124b3 100644 --- a/crates/bevy_openxr/src/openxr/resources.rs +++ b/crates/bevy_openxr/src/openxr/resources.rs @@ -6,7 +6,7 @@ use bevy::render::extract_resource::ExtractResource; use crate::error::OxrError; use crate::graphics::*; use crate::layer_builder::{CompositionLayer, LayerProvider}; -use crate::session::OxrSession; +use crate::session::{OxrSession, OxrSessionCreateNextChain}; use crate::types::*; /// Wrapper around an [`Entry`](openxr::Entry) with some methods overridden to use bevy types. @@ -128,6 +128,7 @@ impl OxrInstance { &self, system_id: openxr::SystemId, info: SessionCreateInfo, + chain: &mut OxrSessionCreateNextChain, ) -> Result<(OxrSession, OxrFrameWaiter, OxrFrameStream)> { if !info.0.using_graphics_of_val(&self.1) { return Err(OxrError::GraphicsBackendMismatch { @@ -139,7 +140,7 @@ impl OxrInstance { graphics_match!( info.0; info => { - let (session, frame_waiter, frame_stream) = self.0.create_session::(system_id, &info)?; + let (session, frame_waiter, frame_stream) = Api::create_session(self,system_id, &info,chain)?; Ok((session.into(), OxrFrameWaiter(frame_waiter), OxrFrameStream(Api::wrap(frame_stream)))) } ) diff --git a/crates/bevy_openxr/src/openxr/session.rs b/crates/bevy_openxr/src/openxr/session.rs index 522e552..1ce507a 100644 --- a/crates/bevy_openxr/src/openxr/session.rs +++ b/crates/bevy_openxr/src/openxr/session.rs @@ -1,4 +1,7 @@ +use std::ffi::c_void; + use crate::init::{OxrHandleEvents, OxrLast}; +use crate::next_chain::{OxrNextChain, OxrNextChainStructBase, OxrNextChainStructProvider}; use crate::resources::{ OxrCleanupSession, OxrPassthrough, OxrPassthroughLayer, OxrSessionStarted, OxrSwapchain, }; @@ -22,6 +25,7 @@ pub struct OxrSessionPlugin; impl Plugin for OxrSessionPlugin { fn build(&self, app: &mut App) { + app.init_non_send_resource::(); app.add_event::(); app.add_systems(OxrLast, run_session_status_schedules.after(OxrHandleEvents)); app.add_systems(XrSessionExiting, clean_session); @@ -169,3 +173,21 @@ impl OxrSession { })) } } + +pub trait OxrSessionCreateNextProvider: OxrNextChainStructProvider {} + +/// NonSend Resource +#[derive(Default)] +pub struct OxrSessionCreateNextChain(OxrNextChain); + +impl OxrSessionCreateNextChain { + pub fn push(&mut self, info_struct: T) { + self.0.push(info_struct) + } + pub fn chain(&self) -> Option<&OxrNextChainStructBase> { + self.0.chain() + } + pub fn chain_pointer(&self) -> *const c_void { + self.0.chain_pointer() + } +}