Skip to content

Commit

Permalink
OpenXR: Separate graphics handling from main OpenXR code (#243)
Browse files Browse the repository at this point in the history
* Genericize session type in input params

Signed-off-by: Daniel Adams <[email protected]>

* Create generic graphics methods, extract D3D11 code

Signed-off-by: Daniel Adams <[email protected]>

* GraphicsProviderType -> Backend

Signed-off-by: Daniel Adams <[email protected]>

---------

Signed-off-by: Daniel Adams <[email protected]>
  • Loading branch information
msub2 authored Aug 27, 2024
1 parent 06cf810 commit 7656508
Show file tree
Hide file tree
Showing 4 changed files with 202 additions and 139 deletions.
25 changes: 25 additions & 0 deletions webxr/openxr/graphics.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use euclid::{Size2D, UnknownUnit};
use openxr::{ExtensionSet, FrameStream, FrameWaiter, Graphics, Instance, Session, SystemId};
use surfman::Context as SurfmanContext;
use surfman::Device as SurfmanDevice;
use surfman::Error as SurfmanError;
use surfman::SurfaceTexture;
use webxr_api::Error;

pub enum GraphicsProvider {}

pub trait GraphicsProviderMethods<G: Graphics> {
fn enable_graphics_extensions(exts: &mut ExtensionSet);
fn pick_format(formats: &[u32]) -> u32;
fn create_session(
device: &SurfmanDevice,
instance: &Instance,
system: SystemId,
) -> Result<(Session<G>, FrameWaiter, FrameStream<G>), Error>;
fn surface_texture_from_swapchain_texture(
image: <G as Graphics>::SwapchainImage,
device: &mut SurfmanDevice,
context: &mut SurfmanContext,
size: &Size2D<i32, UnknownUnit>,
) -> Result<SurfaceTexture, SurfmanError>;
}
138 changes: 138 additions & 0 deletions webxr/openxr/graphics_d3d11.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
use std::{mem, ptr};

use euclid::{Size2D, UnknownUnit};
use log::warn;
use openxr::d3d::{Requirements, SessionCreateInfoD3D11, D3D11};
use openxr::{
ExtensionSet, FormFactor, FrameStream, FrameWaiter, Graphics, Instance, Session, SystemId,
};
use surfman::Adapter as SurfmanAdapter;
use surfman::Context as SurfmanContext;
use surfman::Device as SurfmanDevice;
use surfman::Error as SurfmanError;
use surfman::SurfaceTexture;
use webxr_api::Error;
use winapi::shared::winerror::{DXGI_ERROR_NOT_FOUND, S_OK};
use winapi::shared::{dxgi, dxgiformat};
use winapi::um::d3d11::ID3D11Texture2D;
use winapi::Interface;
use wio::com::ComPtr;

use crate::openxr::graphics::{GraphicsProvider, GraphicsProviderMethods};
use crate::openxr::{create_instance, AppInfo};

pub type Backend = D3D11;

impl GraphicsProviderMethods<D3D11> for GraphicsProvider {
fn enable_graphics_extensions(exts: &mut ExtensionSet) {
exts.khr_d3d11_enable = true;
}

fn pick_format(formats: &[u32]) -> u32 {
// TODO: extract the format from surfman's device and pick a matching
// valid format based on that. For now, assume that eglChooseConfig will
// gravitate to B8G8R8A8.
warn!("Available formats: {:?}", formats);
for format in formats {
match *format {
dxgiformat::DXGI_FORMAT_B8G8R8A8_UNORM => return *format,
//dxgiformat::DXGI_FORMAT_R8G8B8A8_UNORM => return *format,
f => {
warn!("Backend requested unsupported format {:?}", f);
}
}
}

panic!("No formats supported amongst {:?}", formats);
}

fn create_session(
device: &SurfmanDevice,
instance: &Instance,
system: SystemId,
) -> Result<(Session<D3D11>, FrameWaiter, FrameStream<D3D11>), Error> {
// Get the current surfman device and extract its D3D device. This will ensure
// that the OpenXR runtime's texture will be shareable with surfman's surfaces.
let native_device = device.native_device();
let d3d_device = native_device.d3d11_device;

// FIXME: we should be using these graphics requirements to drive the actual
// d3d device creation, rather than assuming the device that surfman
// already created is appropriate. OpenXR returns a validation error
// unless we call this method, so we call it and ignore the results
// in the short term.
let _requirements = D3D11::requirements(&instance, system)
.map_err(|e| Error::BackendSpecific(format!("D3D11::requirements {:?}", e)))?;

unsafe {
instance
.create_session::<D3D11>(
system,
&SessionCreateInfoD3D11 {
device: d3d_device as *mut _,
},
)
.map_err(|e| Error::BackendSpecific(format!("Instance::create_session {:?}", e)))
}
}

fn surface_texture_from_swapchain_texture(
image: <D3D11 as Graphics>::SwapchainImage,
device: &mut SurfmanDevice,
context: &mut SurfmanContext,
size: &Size2D<i32, UnknownUnit>,
) -> Result<SurfaceTexture, SurfmanError> {
unsafe {
let image = ComPtr::from_raw(image as *mut ID3D11Texture2D);
image.AddRef();
device.create_surface_texture_from_texture(context, size, image)
}
}
}

fn get_matching_adapter(
requirements: &Requirements,
) -> Result<ComPtr<dxgi::IDXGIAdapter1>, String> {
unsafe {
let mut factory_ptr: *mut dxgi::IDXGIFactory1 = ptr::null_mut();
let result = dxgi::CreateDXGIFactory1(
&dxgi::IDXGIFactory1::uuidof(),
&mut factory_ptr as *mut _ as *mut _,
);
assert_eq!(result, S_OK);
let factory = ComPtr::from_raw(factory_ptr);

let index = 0;
loop {
let mut adapter_ptr = ptr::null_mut();
let result = factory.EnumAdapters1(index, &mut adapter_ptr);
if result == DXGI_ERROR_NOT_FOUND {
return Err("No matching adapter".to_owned());
}
assert_eq!(result, S_OK);
let adapter = ComPtr::from_raw(adapter_ptr);
let mut adapter_desc = mem::zeroed();
let result = adapter.GetDesc1(&mut adapter_desc);
assert_eq!(result, S_OK);
let adapter_luid = &adapter_desc.AdapterLuid;
if adapter_luid.LowPart == requirements.adapter_luid.LowPart
&& adapter_luid.HighPart == requirements.adapter_luid.HighPart
{
return Ok(adapter);
}
}
}
}

#[allow(unused)]
pub fn create_surfman_adapter() -> Option<SurfmanAdapter> {
let instance = create_instance(false, false, false, &AppInfo::default()).ok()?;
let system = instance
.instance
.system(FormFactor::HEAD_MOUNTED_DISPLAY)
.ok()?;

let requirements = D3D11::requirements(&instance.instance, system).ok()?;
let adapter = get_matching_adapter(&requirements).ok()?;
Some(SurfmanAdapter::from_dxgi_adapter(adapter.up()))
}
27 changes: 13 additions & 14 deletions webxr/openxr/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@ use std::mem::MaybeUninit;

use euclid::RigidTransform3D;
use log::debug;
use openxr::d3d::D3D11;
use openxr::sys::{
HandJointLocationsEXT, HandJointsLocateInfoEXT, HandTrackingAimStateFB,
FB_HAND_TRACKING_AIM_EXTENSION_NAME,
};
use openxr::{
self, Action, ActionSet, Binding, FrameState, Hand as HandEnum, HandJoint, HandJointLocation,
HandTracker, HandTrackingAimFlagsFB, Instance, Path, Posef, Session, Space, SpaceLocationFlags,
HAND_JOINT_COUNT,
self, Action, ActionSet, Binding, FrameState, Graphics, Hand as HandEnum, HandJoint,
HandJointLocation, HandTracker, HandTrackingAimFlagsFB, Instance, Path, Posef, Session, Space,
SpaceLocationFlags, HAND_JOINT_COUNT,
};
use webxr_api::Finger;
use webxr_api::Hand;
Expand Down Expand Up @@ -70,10 +69,10 @@ pub struct Frame {
}

impl ClickState {
fn update_from_action(
fn update_from_action<G: Graphics>(
&mut self,
action: &Action<bool>,
session: &Session<D3D11>,
session: &Session<G>,
menu_selected: bool,
) -> (/* is_active */ bool, Option<SelectEvent>) {
let click = action.state(session, Path::NULL).unwrap();
Expand Down Expand Up @@ -147,11 +146,11 @@ fn hand_str(h: Handedness) -> &'static str {
}

impl OpenXRInput {
pub fn new(
pub fn new<G: Graphics>(
id: InputId,
handedness: Handedness,
action_set: &ActionSet,
session: &Session<D3D11>,
session: &Session<G>,
needs_hands: bool,
supported_interaction_profiles: Vec<&'static str>,
) -> Self {
Expand Down Expand Up @@ -306,9 +305,9 @@ impl OpenXRInput {
}
}

pub fn setup_inputs(
pub fn setup_inputs<G: Graphics>(
instance: &Instance,
session: &Session<D3D11>,
session: &Session<G>,
needs_hands: bool,
supported_interaction_profiles: Vec<&'static str>,
) -> (ActionSet, Self, Self) {
Expand Down Expand Up @@ -447,9 +446,9 @@ impl OpenXRInput {
ret
}

pub fn frame(
pub fn frame<G: Graphics>(
&mut self,
session: &Session<D3D11>,
session: &Session<G>,
frame_state: &FrameState,
base_space: &Space,
viewer: &RigidTransform3D<f32, Viewer, Native>,
Expand Down Expand Up @@ -637,12 +636,12 @@ fn pose_for(
}
}

fn locate_hand(
fn locate_hand<G: Graphics>(
base_space: &Space,
tracker: &HandTracker,
frame_state: &FrameState,
use_alternate_input_source: bool,
session: &Session<D3D11>,
session: &Session<G>,
aim_state: &mut Option<HandTrackingAimStateFB>,
) -> Option<Box<Hand<JointFrame>>> {
let mut state = HandTrackingAimStateFB::out(std::ptr::null_mut());
Expand Down
Loading

0 comments on commit 7656508

Please sign in to comment.