Merge pull request #50 from SafariMonkey/implement-d3d12
Initial D3D12 implementation + improvements
This commit is contained in:
@@ -8,8 +8,10 @@ license = "MIT/Apache-2.0"
|
|||||||
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = ["vulkan", "d3d12"]
|
||||||
force-link = ["openxr/linked"]
|
force-link = ["openxr/linked"]
|
||||||
|
vulkan = ["wgpu-core/vulkan"]
|
||||||
|
d3d12 = ["wgpu-core/dx12", "dep:winapi", "dep:d3d12"]
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
members = ["examples/android", "examples/demo"]
|
members = ["examples/android", "examples/demo"]
|
||||||
@@ -21,7 +23,7 @@ bevy = "0.13"
|
|||||||
futures-lite = "2.0.1"
|
futures-lite = "2.0.1"
|
||||||
mint = "0.5.9"
|
mint = "0.5.9"
|
||||||
wgpu = "0.19"
|
wgpu = "0.19"
|
||||||
wgpu-core = { version = "0.19", features = ["vulkan"] }
|
wgpu-core = { version = "0.19" }
|
||||||
wgpu-hal = "0.19"
|
wgpu-hal = "0.19"
|
||||||
eyre = "0.6.11"
|
eyre = "0.6.11"
|
||||||
|
|
||||||
@@ -31,6 +33,9 @@ openxr = { git = "https://github.com/Ralith/openxrs", rev = "0177d2d", features
|
|||||||
"static",
|
"static",
|
||||||
"mint",
|
"mint",
|
||||||
] }
|
] }
|
||||||
|
winapi = { version = "0.3.9", optional = true }
|
||||||
|
d3d12 = { version = "0.19", features = ["libloading"], optional = true }
|
||||||
|
|
||||||
[target.'cfg(all(target_family = "unix", not(target_arch = "wasm32")) )'.dependencies]
|
[target.'cfg(all(target_family = "unix", not(target_arch = "wasm32")) )'.dependencies]
|
||||||
openxr = { git = "https://github.com/Ralith/openxrs", rev = "0177d2d", features = [
|
openxr = { git = "https://github.com/Ralith/openxrs", rev = "0177d2d", features = [
|
||||||
"mint",
|
"mint",
|
||||||
|
|||||||
474
src/graphics/d3d12.rs
Normal file
474
src/graphics/d3d12.rs
Normal file
@@ -0,0 +1,474 @@
|
|||||||
|
use std::sync::atomic::AtomicBool;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
|
// use anyhow::Context;
|
||||||
|
use bevy::math::uvec2;
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use bevy::render::renderer::{RenderAdapter, RenderAdapterInfo, RenderDevice, RenderQueue};
|
||||||
|
use bevy::window::RawHandleWrapper;
|
||||||
|
use eyre::{Context, ContextCompat};
|
||||||
|
use openxr as xr;
|
||||||
|
use wgpu::Instance;
|
||||||
|
use wgpu_hal::{api::Dx12, Api};
|
||||||
|
use wgpu_hal::{Adapter as HalAdapter, Instance as HalInstance};
|
||||||
|
use winapi::shared::dxgiformat::{self, DXGI_FORMAT};
|
||||||
|
use winapi::um::{d3d12 as winapi_d3d12, d3dcommon};
|
||||||
|
use xr::EnvironmentBlendMode;
|
||||||
|
|
||||||
|
use crate::graphics::extensions::XrExtensions;
|
||||||
|
use crate::input::XrInput;
|
||||||
|
|
||||||
|
use crate::resources::{
|
||||||
|
OXrSessionSetupInfo, Swapchain, SwapchainInner, XrEnvironmentBlendMode, XrFormat, XrFrameState,
|
||||||
|
XrFrameWaiter, XrInstance, XrResolution, XrSession, XrSessionRunning, XrSwapchain, XrViews,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(all(feature = "d3d12", windows))]
|
||||||
|
use crate::resources::D3D12OXrSessionSetupInfo;
|
||||||
|
#[cfg(feature = "vulkan")]
|
||||||
|
use crate::resources::VulkanOXrSessionSetupInfo;
|
||||||
|
|
||||||
|
use super::{XrAppInfo, XrPreferdBlendMode};
|
||||||
|
use crate::VIEW_TYPE;
|
||||||
|
|
||||||
|
pub fn initialize_xr_instance(
|
||||||
|
window: Option<RawHandleWrapper>,
|
||||||
|
xr_entry: xr::Entry,
|
||||||
|
reqeusted_extensions: XrExtensions,
|
||||||
|
available_extensions: XrExtensions,
|
||||||
|
prefered_blend_mode: XrPreferdBlendMode,
|
||||||
|
app_info: XrAppInfo,
|
||||||
|
) -> eyre::Result<(
|
||||||
|
XrInstance,
|
||||||
|
OXrSessionSetupInfo,
|
||||||
|
XrEnvironmentBlendMode,
|
||||||
|
RenderDevice,
|
||||||
|
RenderQueue,
|
||||||
|
RenderAdapterInfo,
|
||||||
|
RenderAdapter,
|
||||||
|
Instance,
|
||||||
|
)> {
|
||||||
|
#[cfg(target_os = "android")]
|
||||||
|
xr_entry.initialize_android_loader()?;
|
||||||
|
|
||||||
|
assert!(available_extensions.raw().khr_d3d12_enable);
|
||||||
|
//info!("available xr exts: {:#?}", available_extensions);
|
||||||
|
|
||||||
|
let mut enabled_extensions: xr::ExtensionSet =
|
||||||
|
(available_extensions & reqeusted_extensions).into();
|
||||||
|
enabled_extensions.khr_d3d12_enable = true;
|
||||||
|
|
||||||
|
let available_layers = xr_entry.enumerate_layers()?;
|
||||||
|
//info!("available xr layers: {:#?}", available_layers);
|
||||||
|
|
||||||
|
let xr_instance = xr_entry.create_instance(
|
||||||
|
&xr::ApplicationInfo {
|
||||||
|
application_name: &app_info.name,
|
||||||
|
engine_name: "Bevy",
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
&enabled_extensions,
|
||||||
|
&[],
|
||||||
|
)?;
|
||||||
|
info!("created OpenXR instance");
|
||||||
|
let instance_props = xr_instance.properties()?;
|
||||||
|
let xr_system_id = xr_instance.system(xr::FormFactor::HEAD_MOUNTED_DISPLAY)?;
|
||||||
|
info!("created OpenXR system");
|
||||||
|
let system_props = xr_instance.system_properties(xr_system_id).unwrap();
|
||||||
|
info!(
|
||||||
|
"loaded OpenXR runtime: {} {} {}",
|
||||||
|
instance_props.runtime_name,
|
||||||
|
instance_props.runtime_version,
|
||||||
|
if system_props.system_name.is_empty() {
|
||||||
|
"<unnamed>"
|
||||||
|
} else {
|
||||||
|
&system_props.system_name
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
let blend_modes = xr_instance.enumerate_environment_blend_modes(xr_system_id, VIEW_TYPE)?;
|
||||||
|
let blend_mode: EnvironmentBlendMode = match prefered_blend_mode {
|
||||||
|
XrPreferdBlendMode::Opaque if blend_modes.contains(&EnvironmentBlendMode::OPAQUE) => {
|
||||||
|
bevy::log::info!("Using Opaque");
|
||||||
|
EnvironmentBlendMode::OPAQUE
|
||||||
|
}
|
||||||
|
XrPreferdBlendMode::Additive if blend_modes.contains(&EnvironmentBlendMode::ADDITIVE) => {
|
||||||
|
bevy::log::info!("Using Additive");
|
||||||
|
EnvironmentBlendMode::ADDITIVE
|
||||||
|
}
|
||||||
|
XrPreferdBlendMode::AlphaBlend
|
||||||
|
if blend_modes.contains(&EnvironmentBlendMode::ALPHA_BLEND) =>
|
||||||
|
{
|
||||||
|
bevy::log::info!("Using AlphaBlend");
|
||||||
|
EnvironmentBlendMode::ALPHA_BLEND
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
bevy::log::info!("Using Opaque");
|
||||||
|
EnvironmentBlendMode::OPAQUE
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let reqs = xr_instance.graphics_requirements::<xr::D3D12>(xr_system_id)?;
|
||||||
|
|
||||||
|
let instance_descriptor = &wgpu_hal::InstanceDescriptor {
|
||||||
|
name: &app_info.name,
|
||||||
|
dx12_shader_compiler: wgpu::util::dx12_shader_compiler_from_env().unwrap_or(
|
||||||
|
wgpu::Dx12Compiler::Dxc {
|
||||||
|
dxil_path: None,
|
||||||
|
dxc_path: None,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
flags: wgpu::InstanceFlags::from_build_config().with_env(),
|
||||||
|
gles_minor_version: Default::default(),
|
||||||
|
};
|
||||||
|
let wgpu_raw_instance: wgpu_hal::dx12::Instance =
|
||||||
|
unsafe { wgpu_hal::dx12::Instance::init(instance_descriptor)? };
|
||||||
|
let wgpu_adapters: Vec<wgpu_hal::ExposedAdapter<wgpu_hal::dx12::Api>> =
|
||||||
|
unsafe { wgpu_raw_instance.enumerate_adapters() };
|
||||||
|
let wgpu_exposed_adapter = wgpu_adapters
|
||||||
|
.into_iter()
|
||||||
|
.find(|a| {
|
||||||
|
let mut desc = unsafe { std::mem::zeroed() };
|
||||||
|
unsafe { a.adapter.raw_adapter().GetDesc1(&mut desc) };
|
||||||
|
desc.AdapterLuid.HighPart == reqs.adapter_luid.HighPart
|
||||||
|
&& desc.AdapterLuid.LowPart == reqs.adapter_luid.LowPart
|
||||||
|
})
|
||||||
|
.context("failed to find DXGI adapter matching LUID provided by runtime")?;
|
||||||
|
|
||||||
|
let wgpu_instance =
|
||||||
|
unsafe { wgpu::Instance::from_hal::<wgpu_hal::api::Dx12>(wgpu_raw_instance) };
|
||||||
|
|
||||||
|
let wgpu_features = wgpu::Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES
|
||||||
|
| wgpu::Features::MULTIVIEW
|
||||||
|
| wgpu::Features::MULTI_DRAW_INDIRECT_COUNT
|
||||||
|
| wgpu::Features::MULTI_DRAW_INDIRECT;
|
||||||
|
|
||||||
|
let wgpu_limits = wgpu::Limits {
|
||||||
|
max_bind_groups: 8,
|
||||||
|
max_storage_buffer_binding_size: wgpu_exposed_adapter
|
||||||
|
.capabilities
|
||||||
|
.limits
|
||||||
|
.max_storage_buffer_binding_size,
|
||||||
|
max_push_constant_size: 4,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let wgpu_open_device = unsafe {
|
||||||
|
wgpu_exposed_adapter
|
||||||
|
.adapter
|
||||||
|
.open(wgpu_features, &wgpu_limits)?
|
||||||
|
};
|
||||||
|
|
||||||
|
let device_supported_feature_level: d3d12::FeatureLevel =
|
||||||
|
get_device_feature_level(wgpu_open_device.device.raw_device());
|
||||||
|
|
||||||
|
if (device_supported_feature_level as u32) < (reqs.min_feature_level as u32) {
|
||||||
|
panic!(
|
||||||
|
"OpenXR runtime requires D3D12 feature level >= {}",
|
||||||
|
reqs.min_feature_level
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let (session, frame_wait, frame_stream) = unsafe {
|
||||||
|
xr_instance.create_session::<xr::D3D12>(
|
||||||
|
xr_system_id,
|
||||||
|
&xr::d3d::SessionCreateInfoD3D12 {
|
||||||
|
device: wgpu_open_device.device.raw_device().as_mut_ptr().cast(),
|
||||||
|
queue: wgpu_open_device.device.raw_queue().as_mut_ptr().cast(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}?;
|
||||||
|
|
||||||
|
let wgpu_adapter = unsafe { wgpu_instance.create_adapter_from_hal(wgpu_exposed_adapter) };
|
||||||
|
let raw_device = wgpu_open_device.device.raw_device().as_mut_ptr();
|
||||||
|
let raw_queue = wgpu_open_device.device.raw_queue().as_mut_ptr();
|
||||||
|
let (wgpu_device, wgpu_queue) = unsafe {
|
||||||
|
wgpu_adapter.create_device_from_hal(
|
||||||
|
wgpu_open_device,
|
||||||
|
&wgpu::DeviceDescriptor {
|
||||||
|
label: Some("bevy_oxr device"),
|
||||||
|
required_features: wgpu_features,
|
||||||
|
required_limits: wgpu_limits,
|
||||||
|
},
|
||||||
|
None,
|
||||||
|
)?
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok((
|
||||||
|
xr_instance.into(),
|
||||||
|
OXrSessionSetupInfo::D3D12(D3D12OXrSessionSetupInfo {
|
||||||
|
raw_device,
|
||||||
|
raw_queue,
|
||||||
|
xr_system_id,
|
||||||
|
}),
|
||||||
|
blend_mode.into(),
|
||||||
|
wgpu_device.into(),
|
||||||
|
RenderQueue(wgpu_queue.into()),
|
||||||
|
RenderAdapterInfo(wgpu_adapter.get_info()),
|
||||||
|
RenderAdapter(wgpu_adapter.into()),
|
||||||
|
wgpu_instance.into(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn start_xr_session(
|
||||||
|
window: Option<RawHandleWrapper>,
|
||||||
|
ptrs: &OXrSessionSetupInfo,
|
||||||
|
xr_instance: &XrInstance,
|
||||||
|
render_device: &RenderDevice,
|
||||||
|
render_adapter: &RenderAdapter,
|
||||||
|
wgpu_instance: &Instance,
|
||||||
|
) -> eyre::Result<(
|
||||||
|
XrSession,
|
||||||
|
XrResolution,
|
||||||
|
XrFormat,
|
||||||
|
XrSessionRunning,
|
||||||
|
XrFrameWaiter,
|
||||||
|
XrSwapchain,
|
||||||
|
XrInput,
|
||||||
|
XrViews,
|
||||||
|
XrFrameState,
|
||||||
|
)> {
|
||||||
|
let wgpu_device = render_device.wgpu_device();
|
||||||
|
let wgpu_adapter = &render_adapter.0;
|
||||||
|
|
||||||
|
#[allow(unreachable_patterns)]
|
||||||
|
let setup_info = match ptrs {
|
||||||
|
OXrSessionSetupInfo::D3D12(v) => v,
|
||||||
|
_ => eyre::bail!("Wrong Graphics Api"),
|
||||||
|
};
|
||||||
|
let (session, frame_wait, frame_stream) = unsafe {
|
||||||
|
xr_instance.create_session::<xr::D3D12>(
|
||||||
|
setup_info.xr_system_id,
|
||||||
|
&xr::d3d::SessionCreateInfoD3D12 {
|
||||||
|
device: setup_info.raw_device.cast(),
|
||||||
|
queue: setup_info.raw_queue.cast(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}?;
|
||||||
|
|
||||||
|
let views =
|
||||||
|
xr_instance.enumerate_view_configuration_views(setup_info.xr_system_id, VIEW_TYPE)?;
|
||||||
|
let surface = window.map(|wrapper| unsafe {
|
||||||
|
// SAFETY: Plugins should be set up on the main thread.
|
||||||
|
let handle = wrapper.get_handle();
|
||||||
|
wgpu_instance
|
||||||
|
.create_surface(handle)
|
||||||
|
.expect("Failed to create wgpu surface")
|
||||||
|
});
|
||||||
|
let swapchain_format = surface
|
||||||
|
.as_ref()
|
||||||
|
.map(|surface| surface.get_capabilities(wgpu_adapter).formats[0])
|
||||||
|
.unwrap_or(wgpu::TextureFormat::Rgba8UnormSrgb);
|
||||||
|
|
||||||
|
// TODO: Log swapchain format
|
||||||
|
|
||||||
|
let resolution = uvec2(
|
||||||
|
views[0].recommended_image_rect_width,
|
||||||
|
views[0].recommended_image_rect_height,
|
||||||
|
);
|
||||||
|
|
||||||
|
let handle = session
|
||||||
|
.create_swapchain(&xr::SwapchainCreateInfo {
|
||||||
|
create_flags: xr::SwapchainCreateFlags::EMPTY,
|
||||||
|
usage_flags: xr::SwapchainUsageFlags::COLOR_ATTACHMENT
|
||||||
|
| xr::SwapchainUsageFlags::SAMPLED,
|
||||||
|
format: wgpu_to_d3d12(swapchain_format).expect("Unsupported texture format"),
|
||||||
|
// The Vulkan graphics pipeline we create is not set up for multisampling,
|
||||||
|
// so we hardcode this to 1. If we used a proper multisampling setup, we
|
||||||
|
// could set this to `views[0].recommended_swapchain_sample_count`.
|
||||||
|
sample_count: 1,
|
||||||
|
width: resolution.x,
|
||||||
|
height: resolution.y,
|
||||||
|
face_count: 1,
|
||||||
|
array_size: 2,
|
||||||
|
mip_count: 1,
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let images = handle.enumerate_images().unwrap();
|
||||||
|
|
||||||
|
let buffers = images
|
||||||
|
.into_iter()
|
||||||
|
.map(|color_image| {
|
||||||
|
info!("image map swapchain");
|
||||||
|
let wgpu_hal_texture = unsafe {
|
||||||
|
<Dx12 as Api>::Device::texture_from_raw(
|
||||||
|
d3d12::ComPtr::from_raw(color_image as *mut _),
|
||||||
|
swapchain_format,
|
||||||
|
wgpu::TextureDimension::D2,
|
||||||
|
wgpu::Extent3d {
|
||||||
|
width: resolution.x,
|
||||||
|
height: resolution.y,
|
||||||
|
depth_or_array_layers: 2,
|
||||||
|
},
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
let texture = unsafe {
|
||||||
|
wgpu_device.create_texture_from_hal::<Dx12>(
|
||||||
|
wgpu_hal_texture,
|
||||||
|
&wgpu::TextureDescriptor {
|
||||||
|
label: Some("bevy_openxr swapchain"),
|
||||||
|
size: wgpu::Extent3d {
|
||||||
|
width: resolution.x,
|
||||||
|
height: resolution.y,
|
||||||
|
depth_or_array_layers: 2,
|
||||||
|
},
|
||||||
|
mip_level_count: 1,
|
||||||
|
sample_count: 1,
|
||||||
|
dimension: wgpu::TextureDimension::D2,
|
||||||
|
format: swapchain_format,
|
||||||
|
usage: wgpu::TextureUsages::RENDER_ATTACHMENT
|
||||||
|
| wgpu::TextureUsages::COPY_DST,
|
||||||
|
view_formats: &[],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
};
|
||||||
|
texture
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Ok((
|
||||||
|
XrSession::D3D12(session.clone()),
|
||||||
|
resolution.into(),
|
||||||
|
swapchain_format.into(),
|
||||||
|
// TODO: this shouldn't be in here
|
||||||
|
AtomicBool::new(false).into(),
|
||||||
|
frame_wait.into(),
|
||||||
|
Swapchain::D3D12(SwapchainInner {
|
||||||
|
stream: Mutex::new(frame_stream),
|
||||||
|
handle: Mutex::new(handle),
|
||||||
|
buffers,
|
||||||
|
image_index: Mutex::new(0),
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
XrInput::new(xr_instance, &session.into_any_graphics())?,
|
||||||
|
Vec::default().into(),
|
||||||
|
// TODO: Feels wrong to return a FrameState here, we probably should just wait for the next frame
|
||||||
|
xr::FrameState {
|
||||||
|
predicted_display_time: xr::Time::from_nanos(1),
|
||||||
|
predicted_display_period: xr::Duration::from_nanos(1),
|
||||||
|
should_render: true,
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extracted from https://github.com/gfx-rs/wgpu/blob/1161a22f4fbb4fc204eb06f2ac4243f83e0e980d/wgpu-hal/src/dx12/adapter.rs#L73-L94
|
||||||
|
// license: MIT OR Apache-2.0
|
||||||
|
fn get_device_feature_level(
|
||||||
|
device: &d3d12::ComPtr<winapi_d3d12::ID3D12Device>,
|
||||||
|
) -> d3d12::FeatureLevel {
|
||||||
|
// Detect the highest supported feature level.
|
||||||
|
let d3d_feature_level = [
|
||||||
|
d3d12::FeatureLevel::L12_1,
|
||||||
|
d3d12::FeatureLevel::L12_0,
|
||||||
|
d3d12::FeatureLevel::L11_1,
|
||||||
|
d3d12::FeatureLevel::L11_0,
|
||||||
|
];
|
||||||
|
type FeatureLevelsInfo = winapi_d3d12::D3D12_FEATURE_DATA_FEATURE_LEVELS;
|
||||||
|
let mut device_levels: FeatureLevelsInfo = unsafe { std::mem::zeroed() };
|
||||||
|
device_levels.NumFeatureLevels = d3d_feature_level.len() as u32;
|
||||||
|
device_levels.pFeatureLevelsRequested = d3d_feature_level.as_ptr().cast();
|
||||||
|
unsafe {
|
||||||
|
device.CheckFeatureSupport(
|
||||||
|
winapi_d3d12::D3D12_FEATURE_FEATURE_LEVELS,
|
||||||
|
(&mut device_levels as *mut FeatureLevelsInfo).cast(),
|
||||||
|
std::mem::size_of::<FeatureLevelsInfo>() as _,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
// This cast should never fail because we only requested feature levels that are already in the enum.
|
||||||
|
let max_feature_level = d3d12::FeatureLevel::try_from(device_levels.MaxSupportedFeatureLevel)
|
||||||
|
.expect("Unexpected feature level");
|
||||||
|
max_feature_level
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wgpu_to_d3d12(format: wgpu::TextureFormat) -> Option<DXGI_FORMAT> {
|
||||||
|
// Copied wholesale from:
|
||||||
|
// https://github.com/gfx-rs/wgpu/blob/v0.19/wgpu-hal/src/auxil/dxgi/conv.rs#L12-L94
|
||||||
|
// license: MIT OR Apache-2.0
|
||||||
|
use wgpu::TextureFormat as Tf;
|
||||||
|
use winapi::shared::dxgiformat::*;
|
||||||
|
|
||||||
|
Some(match format {
|
||||||
|
Tf::R8Unorm => DXGI_FORMAT_R8_UNORM,
|
||||||
|
Tf::R8Snorm => DXGI_FORMAT_R8_SNORM,
|
||||||
|
Tf::R8Uint => DXGI_FORMAT_R8_UINT,
|
||||||
|
Tf::R8Sint => DXGI_FORMAT_R8_SINT,
|
||||||
|
Tf::R16Uint => DXGI_FORMAT_R16_UINT,
|
||||||
|
Tf::R16Sint => DXGI_FORMAT_R16_SINT,
|
||||||
|
Tf::R16Unorm => DXGI_FORMAT_R16_UNORM,
|
||||||
|
Tf::R16Snorm => DXGI_FORMAT_R16_SNORM,
|
||||||
|
Tf::R16Float => DXGI_FORMAT_R16_FLOAT,
|
||||||
|
Tf::Rg8Unorm => DXGI_FORMAT_R8G8_UNORM,
|
||||||
|
Tf::Rg8Snorm => DXGI_FORMAT_R8G8_SNORM,
|
||||||
|
Tf::Rg8Uint => DXGI_FORMAT_R8G8_UINT,
|
||||||
|
Tf::Rg8Sint => DXGI_FORMAT_R8G8_SINT,
|
||||||
|
Tf::Rg16Unorm => DXGI_FORMAT_R16G16_UNORM,
|
||||||
|
Tf::Rg16Snorm => DXGI_FORMAT_R16G16_SNORM,
|
||||||
|
Tf::R32Uint => DXGI_FORMAT_R32_UINT,
|
||||||
|
Tf::R32Sint => DXGI_FORMAT_R32_SINT,
|
||||||
|
Tf::R32Float => DXGI_FORMAT_R32_FLOAT,
|
||||||
|
Tf::Rg16Uint => DXGI_FORMAT_R16G16_UINT,
|
||||||
|
Tf::Rg16Sint => DXGI_FORMAT_R16G16_SINT,
|
||||||
|
Tf::Rg16Float => DXGI_FORMAT_R16G16_FLOAT,
|
||||||
|
Tf::Rgba8Unorm => DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||||
|
Tf::Rgba8UnormSrgb => DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
|
||||||
|
Tf::Bgra8UnormSrgb => DXGI_FORMAT_B8G8R8A8_UNORM_SRGB,
|
||||||
|
Tf::Rgba8Snorm => DXGI_FORMAT_R8G8B8A8_SNORM,
|
||||||
|
Tf::Bgra8Unorm => DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||||
|
Tf::Rgba8Uint => DXGI_FORMAT_R8G8B8A8_UINT,
|
||||||
|
Tf::Rgba8Sint => DXGI_FORMAT_R8G8B8A8_SINT,
|
||||||
|
Tf::Rgb9e5Ufloat => DXGI_FORMAT_R9G9B9E5_SHAREDEXP,
|
||||||
|
Tf::Rgb10a2Uint => DXGI_FORMAT_R10G10B10A2_UINT,
|
||||||
|
Tf::Rgb10a2Unorm => DXGI_FORMAT_R10G10B10A2_UNORM,
|
||||||
|
Tf::Rg11b10Float => DXGI_FORMAT_R11G11B10_FLOAT,
|
||||||
|
Tf::Rg32Uint => DXGI_FORMAT_R32G32_UINT,
|
||||||
|
Tf::Rg32Sint => DXGI_FORMAT_R32G32_SINT,
|
||||||
|
Tf::Rg32Float => DXGI_FORMAT_R32G32_FLOAT,
|
||||||
|
Tf::Rgba16Uint => DXGI_FORMAT_R16G16B16A16_UINT,
|
||||||
|
Tf::Rgba16Sint => DXGI_FORMAT_R16G16B16A16_SINT,
|
||||||
|
Tf::Rgba16Unorm => DXGI_FORMAT_R16G16B16A16_UNORM,
|
||||||
|
Tf::Rgba16Snorm => DXGI_FORMAT_R16G16B16A16_SNORM,
|
||||||
|
Tf::Rgba16Float => DXGI_FORMAT_R16G16B16A16_FLOAT,
|
||||||
|
Tf::Rgba32Uint => DXGI_FORMAT_R32G32B32A32_UINT,
|
||||||
|
Tf::Rgba32Sint => DXGI_FORMAT_R32G32B32A32_SINT,
|
||||||
|
Tf::Rgba32Float => DXGI_FORMAT_R32G32B32A32_FLOAT,
|
||||||
|
Tf::Stencil8 => DXGI_FORMAT_D24_UNORM_S8_UINT,
|
||||||
|
Tf::Depth16Unorm => DXGI_FORMAT_D16_UNORM,
|
||||||
|
Tf::Depth24Plus => DXGI_FORMAT_D24_UNORM_S8_UINT,
|
||||||
|
Tf::Depth24PlusStencil8 => DXGI_FORMAT_D24_UNORM_S8_UINT,
|
||||||
|
Tf::Depth32Float => DXGI_FORMAT_D32_FLOAT,
|
||||||
|
Tf::Depth32FloatStencil8 => DXGI_FORMAT_D32_FLOAT_S8X24_UINT,
|
||||||
|
Tf::NV12 => DXGI_FORMAT_NV12,
|
||||||
|
Tf::Bc1RgbaUnorm => DXGI_FORMAT_BC1_UNORM,
|
||||||
|
Tf::Bc1RgbaUnormSrgb => DXGI_FORMAT_BC1_UNORM_SRGB,
|
||||||
|
Tf::Bc2RgbaUnorm => DXGI_FORMAT_BC2_UNORM,
|
||||||
|
Tf::Bc2RgbaUnormSrgb => DXGI_FORMAT_BC2_UNORM_SRGB,
|
||||||
|
Tf::Bc3RgbaUnorm => DXGI_FORMAT_BC3_UNORM,
|
||||||
|
Tf::Bc3RgbaUnormSrgb => DXGI_FORMAT_BC3_UNORM_SRGB,
|
||||||
|
Tf::Bc4RUnorm => DXGI_FORMAT_BC4_UNORM,
|
||||||
|
Tf::Bc4RSnorm => DXGI_FORMAT_BC4_SNORM,
|
||||||
|
Tf::Bc5RgUnorm => DXGI_FORMAT_BC5_UNORM,
|
||||||
|
Tf::Bc5RgSnorm => DXGI_FORMAT_BC5_SNORM,
|
||||||
|
Tf::Bc6hRgbUfloat => DXGI_FORMAT_BC6H_UF16,
|
||||||
|
Tf::Bc6hRgbFloat => DXGI_FORMAT_BC6H_SF16,
|
||||||
|
Tf::Bc7RgbaUnorm => DXGI_FORMAT_BC7_UNORM,
|
||||||
|
Tf::Bc7RgbaUnormSrgb => DXGI_FORMAT_BC7_UNORM_SRGB,
|
||||||
|
Tf::Etc2Rgb8Unorm
|
||||||
|
| Tf::Etc2Rgb8UnormSrgb
|
||||||
|
| Tf::Etc2Rgb8A1Unorm
|
||||||
|
| Tf::Etc2Rgb8A1UnormSrgb
|
||||||
|
| Tf::Etc2Rgba8Unorm
|
||||||
|
| Tf::Etc2Rgba8UnormSrgb
|
||||||
|
| Tf::EacR11Unorm
|
||||||
|
| Tf::EacR11Snorm
|
||||||
|
| Tf::EacRg11Unorm
|
||||||
|
| Tf::EacRg11Snorm
|
||||||
|
| Tf::Astc {
|
||||||
|
block: _,
|
||||||
|
channel: _,
|
||||||
|
} => return None,
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -1,4 +1,8 @@
|
|||||||
pub mod extensions;
|
pub mod extensions;
|
||||||
|
|
||||||
|
#[cfg(all(feature = "d3d12", windows))]
|
||||||
|
mod d3d12;
|
||||||
|
#[cfg(feature = "vulkan")]
|
||||||
mod vulkan;
|
mod vulkan;
|
||||||
|
|
||||||
use bevy::ecs::query::With;
|
use bevy::ecs::query::With;
|
||||||
@@ -17,6 +21,8 @@ use crate::resources::{
|
|||||||
};
|
};
|
||||||
use crate::OXrSessionSetupInfo;
|
use crate::OXrSessionSetupInfo;
|
||||||
|
|
||||||
|
use crate::Backend;
|
||||||
|
|
||||||
use openxr as xr;
|
use openxr as xr;
|
||||||
|
|
||||||
use self::extensions::XrExtensions;
|
use self::extensions::XrExtensions;
|
||||||
@@ -63,16 +69,29 @@ pub fn start_xr_session(
|
|||||||
XrViews,
|
XrViews,
|
||||||
XrFrameState,
|
XrFrameState,
|
||||||
)> {
|
)> {
|
||||||
vulkan::start_xr_session(
|
match session_setup_data {
|
||||||
|
#[cfg(feature = "vulkan")]
|
||||||
|
OXrSessionSetupInfo::Vulkan(_) => vulkan::start_xr_session(
|
||||||
window,
|
window,
|
||||||
session_setup_data,
|
session_setup_data,
|
||||||
xr_instance,
|
xr_instance,
|
||||||
render_device,
|
render_device,
|
||||||
render_adapter,
|
render_adapter,
|
||||||
wgpu_instance,
|
wgpu_instance,
|
||||||
)
|
),
|
||||||
|
#[cfg(all(feature = "d3d12", windows))]
|
||||||
|
OXrSessionSetupInfo::D3D12(_) => d3d12::start_xr_session(
|
||||||
|
window,
|
||||||
|
session_setup_data,
|
||||||
|
xr_instance,
|
||||||
|
render_device,
|
||||||
|
render_adapter,
|
||||||
|
wgpu_instance,
|
||||||
|
),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pub fn initialize_xr_instance(
|
pub fn initialize_xr_instance(
|
||||||
|
backend_preference: &[Backend],
|
||||||
window: Option<RawHandleWrapper>,
|
window: Option<RawHandleWrapper>,
|
||||||
reqeusted_extensions: XrExtensions,
|
reqeusted_extensions: XrExtensions,
|
||||||
prefered_blend_mode: XrPreferdBlendMode,
|
prefered_blend_mode: XrPreferdBlendMode,
|
||||||
@@ -87,11 +106,57 @@ pub fn initialize_xr_instance(
|
|||||||
RenderAdapter,
|
RenderAdapter,
|
||||||
Instance,
|
Instance,
|
||||||
)> {
|
)> {
|
||||||
vulkan::initialize_xr_instance(window, reqeusted_extensions, prefered_blend_mode, app_info)
|
if backend_preference.is_empty() {
|
||||||
|
eyre::bail!("Cannot initialize with no backend selected");
|
||||||
|
}
|
||||||
|
let xr_entry = xr_entry()?;
|
||||||
|
|
||||||
|
#[cfg(target_os = "android")]
|
||||||
|
xr_entry.initialize_android_loader()?;
|
||||||
|
|
||||||
|
let available_extensions: XrExtensions = xr_entry.enumerate_extensions()?.into();
|
||||||
|
|
||||||
|
for backend in backend_preference {
|
||||||
|
match backend {
|
||||||
|
#[cfg(feature = "vulkan")]
|
||||||
|
Backend::Vulkan => {
|
||||||
|
if !available_extensions.raw().khr_vulkan_enable2 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return vulkan::initialize_xr_instance(
|
||||||
|
window,
|
||||||
|
xr_entry,
|
||||||
|
reqeusted_extensions,
|
||||||
|
available_extensions,
|
||||||
|
prefered_blend_mode,
|
||||||
|
app_info,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#[cfg(all(feature = "d3d12", windows))]
|
||||||
|
Backend::D3D12 => {
|
||||||
|
if !available_extensions.raw().khr_d3d12_enable {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return d3d12::initialize_xr_instance(
|
||||||
|
window,
|
||||||
|
xr_entry,
|
||||||
|
reqeusted_extensions,
|
||||||
|
available_extensions,
|
||||||
|
prefered_blend_mode,
|
||||||
|
app_info,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
eyre::bail!(
|
||||||
|
"No selected backend was supported by the runtime. Selected: {:?}",
|
||||||
|
backend_preference
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn try_full_init(
|
pub fn try_full_init(
|
||||||
world: &mut World,
|
world: &mut World,
|
||||||
|
backend_preference: &[Backend],
|
||||||
reqeusted_extensions: XrExtensions,
|
reqeusted_extensions: XrExtensions,
|
||||||
prefered_blend_mode: XrPreferdBlendMode,
|
prefered_blend_mode: XrPreferdBlendMode,
|
||||||
app_info: XrAppInfo,
|
app_info: XrAppInfo,
|
||||||
@@ -115,6 +180,7 @@ pub fn try_full_init(
|
|||||||
render_adapter,
|
render_adapter,
|
||||||
wgpu_instance,
|
wgpu_instance,
|
||||||
) = initialize_xr_instance(
|
) = initialize_xr_instance(
|
||||||
|
backend_preference,
|
||||||
primary_window.clone(),
|
primary_window.clone(),
|
||||||
reqeusted_extensions,
|
reqeusted_extensions,
|
||||||
prefered_blend_mode,
|
prefered_blend_mode,
|
||||||
|
|||||||
@@ -28,7 +28,9 @@ use super::{XrAppInfo, XrPreferdBlendMode};
|
|||||||
|
|
||||||
pub fn initialize_xr_instance(
|
pub fn initialize_xr_instance(
|
||||||
window: Option<RawHandleWrapper>,
|
window: Option<RawHandleWrapper>,
|
||||||
|
xr_entry: xr::Entry,
|
||||||
reqeusted_extensions: XrExtensions,
|
reqeusted_extensions: XrExtensions,
|
||||||
|
available_extensions: XrExtensions,
|
||||||
prefered_blend_mode: XrPreferdBlendMode,
|
prefered_blend_mode: XrPreferdBlendMode,
|
||||||
app_info: XrAppInfo,
|
app_info: XrAppInfo,
|
||||||
) -> eyre::Result<(
|
) -> eyre::Result<(
|
||||||
@@ -41,14 +43,11 @@ pub fn initialize_xr_instance(
|
|||||||
RenderAdapter,
|
RenderAdapter,
|
||||||
Instance,
|
Instance,
|
||||||
)> {
|
)> {
|
||||||
let xr_entry = super::xr_entry()?;
|
|
||||||
|
|
||||||
#[cfg(target_os = "android")]
|
#[cfg(target_os = "android")]
|
||||||
xr_entry.initialize_android_loader()?;
|
xr_entry.initialize_android_loader()?;
|
||||||
|
|
||||||
let available_extensions: XrExtensions = xr_entry.enumerate_extensions()?.into();
|
|
||||||
assert!(available_extensions.raw().khr_vulkan_enable2);
|
assert!(available_extensions.raw().khr_vulkan_enable2);
|
||||||
//info!("available xr exts: {:#?}", available_extensions);
|
// info!("available OpenXR extensions: {:#?}", available_extensions);
|
||||||
|
|
||||||
let mut enabled_extensions: xr::ExtensionSet =
|
let mut enabled_extensions: xr::ExtensionSet =
|
||||||
(available_extensions & reqeusted_extensions).into();
|
(available_extensions & reqeusted_extensions).into();
|
||||||
@@ -59,7 +58,7 @@ pub fn initialize_xr_instance(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let available_layers = xr_entry.enumerate_layers()?;
|
let available_layers = xr_entry.enumerate_layers()?;
|
||||||
//info!("available xr layers: {:#?}", available_layers);
|
// info!("available OpenXR layers: {:#?}", available_layers);
|
||||||
|
|
||||||
let xr_instance = xr_entry.create_instance(
|
let xr_instance = xr_entry.create_instance(
|
||||||
&xr::ApplicationInfo {
|
&xr::ApplicationInfo {
|
||||||
@@ -70,10 +69,10 @@ pub fn initialize_xr_instance(
|
|||||||
&enabled_extensions,
|
&enabled_extensions,
|
||||||
&[],
|
&[],
|
||||||
)?;
|
)?;
|
||||||
info!("created instance");
|
info!("created OpenXR instance");
|
||||||
let instance_props = xr_instance.properties()?;
|
let instance_props = xr_instance.properties()?;
|
||||||
let xr_system_id = xr_instance.system(xr::FormFactor::HEAD_MOUNTED_DISPLAY)?;
|
let xr_system_id = xr_instance.system(xr::FormFactor::HEAD_MOUNTED_DISPLAY)?;
|
||||||
info!("created system");
|
info!("created OpenXR system");
|
||||||
let system_props = xr_instance.system_properties(xr_system_id).unwrap();
|
let system_props = xr_instance.system_properties(xr_system_id).unwrap();
|
||||||
info!(
|
info!(
|
||||||
"loaded OpenXR runtime: {} {} {}",
|
"loaded OpenXR runtime: {} {} {}",
|
||||||
@@ -123,7 +122,7 @@ pub fn initialize_xr_instance(
|
|||||||
|| vk_target_version_xr.major() > reqs.max_api_version_supported.major()
|
|| vk_target_version_xr.major() > reqs.max_api_version_supported.major()
|
||||||
{
|
{
|
||||||
panic!(
|
panic!(
|
||||||
"OpenXR runtime requires Vulkan version > {}, < {}.0.0",
|
"OpenXR runtime requires Vulkan version >= {}, < {}.0.0",
|
||||||
reqs.min_api_version_supported,
|
reqs.min_api_version_supported,
|
||||||
reqs.max_api_version_supported.major() + 1
|
reqs.max_api_version_supported.major() + 1
|
||||||
);
|
);
|
||||||
@@ -139,7 +138,7 @@ pub fn initialize_xr_instance(
|
|||||||
ash::extensions::khr::TimelineSemaphore::name(),
|
ash::extensions::khr::TimelineSemaphore::name(),
|
||||||
];
|
];
|
||||||
info!(
|
info!(
|
||||||
"creating vulkan instance with these extensions: {:#?}",
|
"creating Vulkan instance with these extensions: {:#?}",
|
||||||
extensions
|
extensions
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -163,7 +162,7 @@ pub fn initialize_xr_instance(
|
|||||||
.enabled_extension_names(&extensions_cchar) as *const _
|
.enabled_extension_names(&extensions_cchar) as *const _
|
||||||
as *const _,
|
as *const _,
|
||||||
)
|
)
|
||||||
.context("XR error creating Vulkan instance")
|
.context("OpenXR error creating Vulkan instance")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.map_err(vk::Result::from_raw)
|
.map_err(vk::Result::from_raw)
|
||||||
.context("Vulkan error creating Vulkan instance")
|
.context("Vulkan error creating Vulkan instance")
|
||||||
@@ -174,7 +173,7 @@ pub fn initialize_xr_instance(
|
|||||||
vk::Instance::from_raw(vk_instance as _),
|
vk::Instance::from_raw(vk_instance as _),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
info!("created vulkan instance");
|
info!("created Vulkan instance");
|
||||||
|
|
||||||
let vk_instance_ptr = vk_instance.handle().as_raw() as *const c_void;
|
let vk_instance_ptr = vk_instance.handle().as_raw() as *const c_void;
|
||||||
|
|
||||||
@@ -247,7 +246,7 @@ pub fn initialize_xr_instance(
|
|||||||
vk_physical_device.as_raw() as _,
|
vk_physical_device.as_raw() as _,
|
||||||
&info as *const _ as *const _,
|
&info as *const _ as *const _,
|
||||||
)
|
)
|
||||||
.context("XR error creating Vulkan device")?
|
.context("OpenXR error creating Vulkan device")?
|
||||||
.map_err(vk::Result::from_raw)
|
.map_err(vk::Result::from_raw)
|
||||||
.context("Vulkan error creating Vulkan device")?;
|
.context("Vulkan error creating Vulkan device")?;
|
||||||
|
|
||||||
@@ -401,7 +400,7 @@ pub fn start_xr_session(
|
|||||||
<V as Api>::Device::texture_from_raw(
|
<V as Api>::Device::texture_from_raw(
|
||||||
color_image,
|
color_image,
|
||||||
&wgpu_hal::TextureDescriptor {
|
&wgpu_hal::TextureDescriptor {
|
||||||
label: Some("VR Swapchain"),
|
label: Some("bevy_openxr swapchain"), // unused internally
|
||||||
size: wgpu::Extent3d {
|
size: wgpu::Extent3d {
|
||||||
width: resolution.x,
|
width: resolution.x,
|
||||||
height: resolution.y,
|
height: resolution.y,
|
||||||
@@ -423,7 +422,7 @@ pub fn start_xr_session(
|
|||||||
wgpu_device.create_texture_from_hal::<V>(
|
wgpu_device.create_texture_from_hal::<V>(
|
||||||
wgpu_hal_texture,
|
wgpu_hal_texture,
|
||||||
&wgpu::TextureDescriptor {
|
&wgpu::TextureDescriptor {
|
||||||
label: Some("VR Swapchain"),
|
label: Some("bevy_openxr swapchain"),
|
||||||
size: wgpu::Extent3d {
|
size: wgpu::Extent3d {
|
||||||
width: resolution.x,
|
width: resolution.x,
|
||||||
height: resolution.y,
|
height: resolution.y,
|
||||||
@@ -470,67 +469,136 @@ pub fn start_xr_session(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn wgpu_to_vulkan(format: wgpu::TextureFormat) -> vk::Format {
|
fn wgpu_to_vulkan(format: wgpu::TextureFormat) -> vk::Format {
|
||||||
use vk::Format;
|
// Copied with minor modification from:
|
||||||
|
// https://github.com/gfx-rs/wgpu/blob/v0.19/wgpu-hal/src/vulkan/conv.rs#L5C1-L153
|
||||||
|
// license: MIT OR Apache-2.0
|
||||||
|
use ash::vk::Format as F;
|
||||||
|
use wgpu::TextureFormat as Tf;
|
||||||
|
use wgpu::{AstcBlock, AstcChannel};
|
||||||
match format {
|
match format {
|
||||||
wgpu::TextureFormat::R8Unorm => Format::R8_UNORM,
|
Tf::R8Unorm => F::R8_UNORM,
|
||||||
wgpu::TextureFormat::R8Snorm => Format::R8_SNORM,
|
Tf::R8Snorm => F::R8_SNORM,
|
||||||
wgpu::TextureFormat::R8Uint => Format::R8_UINT,
|
Tf::R8Uint => F::R8_UINT,
|
||||||
wgpu::TextureFormat::R8Sint => Format::R8_SINT,
|
Tf::R8Sint => F::R8_SINT,
|
||||||
wgpu::TextureFormat::R16Uint => Format::R16_UINT,
|
Tf::R16Uint => F::R16_UINT,
|
||||||
wgpu::TextureFormat::R16Sint => Format::R16_SINT,
|
Tf::R16Sint => F::R16_SINT,
|
||||||
wgpu::TextureFormat::R16Unorm => Format::R16_UNORM,
|
Tf::R16Unorm => F::R16_UNORM,
|
||||||
wgpu::TextureFormat::R16Snorm => Format::R16_SNORM,
|
Tf::R16Snorm => F::R16_SNORM,
|
||||||
wgpu::TextureFormat::R16Float => Format::R16_SFLOAT,
|
Tf::R16Float => F::R16_SFLOAT,
|
||||||
wgpu::TextureFormat::Rg8Unorm => Format::R8G8_UNORM,
|
Tf::Rg8Unorm => F::R8G8_UNORM,
|
||||||
wgpu::TextureFormat::Rg8Snorm => Format::R8G8_SNORM,
|
Tf::Rg8Snorm => F::R8G8_SNORM,
|
||||||
wgpu::TextureFormat::Rg8Uint => Format::R8G8_UINT,
|
Tf::Rg8Uint => F::R8G8_UINT,
|
||||||
wgpu::TextureFormat::Rg8Sint => Format::R8G8_SINT,
|
Tf::Rg8Sint => F::R8G8_SINT,
|
||||||
wgpu::TextureFormat::R32Uint => Format::R32_UINT,
|
Tf::Rg16Unorm => F::R16G16_UNORM,
|
||||||
wgpu::TextureFormat::R32Sint => Format::R32_SINT,
|
Tf::Rg16Snorm => F::R16G16_SNORM,
|
||||||
wgpu::TextureFormat::R32Float => Format::R32_SFLOAT,
|
Tf::R32Uint => F::R32_UINT,
|
||||||
wgpu::TextureFormat::Rg16Uint => Format::R16G16_UINT,
|
Tf::R32Sint => F::R32_SINT,
|
||||||
wgpu::TextureFormat::Rg16Sint => Format::R16G16_SINT,
|
Tf::R32Float => F::R32_SFLOAT,
|
||||||
wgpu::TextureFormat::Rg16Unorm => Format::R16G16_UNORM,
|
Tf::Rg16Uint => F::R16G16_UINT,
|
||||||
wgpu::TextureFormat::Rg16Snorm => Format::R16G16_SNORM,
|
Tf::Rg16Sint => F::R16G16_SINT,
|
||||||
wgpu::TextureFormat::Rg16Float => Format::R16G16_SFLOAT,
|
Tf::Rg16Float => F::R16G16_SFLOAT,
|
||||||
wgpu::TextureFormat::Rgba8Unorm => Format::R8G8B8A8_UNORM,
|
Tf::Rgba8Unorm => F::R8G8B8A8_UNORM,
|
||||||
wgpu::TextureFormat::Rgba8UnormSrgb => Format::R8G8B8A8_SRGB,
|
Tf::Rgba8UnormSrgb => F::R8G8B8A8_SRGB,
|
||||||
wgpu::TextureFormat::Rgba8Snorm => Format::R8G8B8A8_SNORM,
|
Tf::Bgra8UnormSrgb => F::B8G8R8A8_SRGB,
|
||||||
wgpu::TextureFormat::Rgba8Uint => Format::R8G8B8A8_UINT,
|
Tf::Rgba8Snorm => F::R8G8B8A8_SNORM,
|
||||||
wgpu::TextureFormat::Rgba8Sint => Format::R8G8B8A8_SINT,
|
Tf::Bgra8Unorm => F::B8G8R8A8_UNORM,
|
||||||
wgpu::TextureFormat::Bgra8Unorm => Format::B8G8R8A8_UNORM,
|
Tf::Rgba8Uint => F::R8G8B8A8_UINT,
|
||||||
wgpu::TextureFormat::Bgra8UnormSrgb => Format::B8G8R8A8_SRGB,
|
Tf::Rgba8Sint => F::R8G8B8A8_SINT,
|
||||||
wgpu::TextureFormat::Rgb9e5Ufloat => Format::E5B9G9R9_UFLOAT_PACK32, // this might be the wrong type??? i can't tell
|
Tf::Rgb10a2Uint => F::A2B10G10R10_UINT_PACK32,
|
||||||
wgpu::TextureFormat::Rgb10a2Unorm => Format::A2R10G10B10_UNORM_PACK32,
|
Tf::Rgb10a2Unorm => F::A2B10G10R10_UNORM_PACK32,
|
||||||
wgpu::TextureFormat::Rg11b10Float => panic!("this texture type invokes nothing but fear within my soul and i don't think vulkan has a proper type for this"),
|
Tf::Rg11b10Float => F::B10G11R11_UFLOAT_PACK32,
|
||||||
wgpu::TextureFormat::Rg32Uint => Format::R32G32_UINT,
|
Tf::Rg32Uint => F::R32G32_UINT,
|
||||||
wgpu::TextureFormat::Rg32Sint => Format::R32G32_SINT,
|
Tf::Rg32Sint => F::R32G32_SINT,
|
||||||
wgpu::TextureFormat::Rg32Float => Format::R32G32_SFLOAT,
|
Tf::Rg32Float => F::R32G32_SFLOAT,
|
||||||
wgpu::TextureFormat::Rgba16Uint => Format::R16G16B16A16_UINT,
|
Tf::Rgba16Uint => F::R16G16B16A16_UINT,
|
||||||
wgpu::TextureFormat::Rgba16Sint => Format::R16G16B16A16_SINT,
|
Tf::Rgba16Sint => F::R16G16B16A16_SINT,
|
||||||
wgpu::TextureFormat::Rgba16Unorm => Format::R16G16B16A16_UNORM,
|
Tf::Rgba16Unorm => F::R16G16B16A16_UNORM,
|
||||||
wgpu::TextureFormat::Rgba16Snorm => Format::R16G16B16A16_SNORM,
|
Tf::Rgba16Snorm => F::R16G16B16A16_SNORM,
|
||||||
wgpu::TextureFormat::Rgba16Float => Format::R16G16B16A16_SFLOAT,
|
Tf::Rgba16Float => F::R16G16B16A16_SFLOAT,
|
||||||
wgpu::TextureFormat::Rgba32Uint => Format::R32G32B32A32_UINT,
|
Tf::Rgba32Uint => F::R32G32B32A32_UINT,
|
||||||
wgpu::TextureFormat::Rgba32Sint => Format::R32G32B32A32_SINT,
|
Tf::Rgba32Sint => F::R32G32B32A32_SINT,
|
||||||
wgpu::TextureFormat::Rgba32Float => Format::R32G32B32A32_SFLOAT,
|
Tf::Rgba32Float => F::R32G32B32A32_SFLOAT,
|
||||||
wgpu::TextureFormat::Stencil8 => Format::S8_UINT,
|
Tf::Depth32Float => F::D32_SFLOAT,
|
||||||
wgpu::TextureFormat::Depth16Unorm => Format::D16_UNORM,
|
Tf::Depth32FloatStencil8 => F::D32_SFLOAT_S8_UINT,
|
||||||
wgpu::TextureFormat::Depth24Plus => Format::X8_D24_UNORM_PACK32,
|
Tf::Depth24Plus | Tf::Depth24PlusStencil8 | Tf::Stencil8 => {
|
||||||
wgpu::TextureFormat::Depth24PlusStencil8 => Format::D24_UNORM_S8_UINT,
|
panic!("Cannot convert format that is dependent on device properties")
|
||||||
wgpu::TextureFormat::Depth32Float => Format::D32_SFLOAT,
|
}
|
||||||
wgpu::TextureFormat::Depth32FloatStencil8 => Format::D32_SFLOAT_S8_UINT,
|
Tf::Depth16Unorm => F::D16_UNORM,
|
||||||
wgpu::TextureFormat::Etc2Rgb8Unorm => Format::ETC2_R8G8B8_UNORM_BLOCK,
|
Tf::NV12 => F::G8_B8R8_2PLANE_420_UNORM,
|
||||||
wgpu::TextureFormat::Etc2Rgb8UnormSrgb => Format::ETC2_R8G8B8_SRGB_BLOCK,
|
Tf::Rgb9e5Ufloat => F::E5B9G9R9_UFLOAT_PACK32,
|
||||||
wgpu::TextureFormat::Etc2Rgb8A1Unorm => Format::ETC2_R8G8B8A1_UNORM_BLOCK,
|
Tf::Bc1RgbaUnorm => F::BC1_RGBA_UNORM_BLOCK,
|
||||||
wgpu::TextureFormat::Etc2Rgb8A1UnormSrgb => Format::ETC2_R8G8B8A1_SRGB_BLOCK,
|
Tf::Bc1RgbaUnormSrgb => F::BC1_RGBA_SRGB_BLOCK,
|
||||||
wgpu::TextureFormat::Etc2Rgba8Unorm => Format::ETC2_R8G8B8A8_UNORM_BLOCK,
|
Tf::Bc2RgbaUnorm => F::BC2_UNORM_BLOCK,
|
||||||
wgpu::TextureFormat::Etc2Rgba8UnormSrgb => Format::ETC2_R8G8B8A8_SRGB_BLOCK,
|
Tf::Bc2RgbaUnormSrgb => F::BC2_SRGB_BLOCK,
|
||||||
wgpu::TextureFormat::EacR11Unorm => Format::EAC_R11_UNORM_BLOCK,
|
Tf::Bc3RgbaUnorm => F::BC3_UNORM_BLOCK,
|
||||||
wgpu::TextureFormat::EacR11Snorm => Format::EAC_R11_SNORM_BLOCK,
|
Tf::Bc3RgbaUnormSrgb => F::BC3_SRGB_BLOCK,
|
||||||
wgpu::TextureFormat::EacRg11Unorm => Format::EAC_R11G11_UNORM_BLOCK,
|
Tf::Bc4RUnorm => F::BC4_UNORM_BLOCK,
|
||||||
wgpu::TextureFormat::EacRg11Snorm => Format::EAC_R11G11_SNORM_BLOCK,
|
Tf::Bc4RSnorm => F::BC4_SNORM_BLOCK,
|
||||||
wgpu::TextureFormat::Astc { .. } => panic!("please god kill me now"),
|
Tf::Bc5RgUnorm => F::BC5_UNORM_BLOCK,
|
||||||
_ => panic!("fuck no")
|
Tf::Bc5RgSnorm => F::BC5_SNORM_BLOCK,
|
||||||
|
Tf::Bc6hRgbUfloat => F::BC6H_UFLOAT_BLOCK,
|
||||||
|
Tf::Bc6hRgbFloat => F::BC6H_SFLOAT_BLOCK,
|
||||||
|
Tf::Bc7RgbaUnorm => F::BC7_UNORM_BLOCK,
|
||||||
|
Tf::Bc7RgbaUnormSrgb => F::BC7_SRGB_BLOCK,
|
||||||
|
Tf::Etc2Rgb8Unorm => F::ETC2_R8G8B8_UNORM_BLOCK,
|
||||||
|
Tf::Etc2Rgb8UnormSrgb => F::ETC2_R8G8B8_SRGB_BLOCK,
|
||||||
|
Tf::Etc2Rgb8A1Unorm => F::ETC2_R8G8B8A1_UNORM_BLOCK,
|
||||||
|
Tf::Etc2Rgb8A1UnormSrgb => F::ETC2_R8G8B8A1_SRGB_BLOCK,
|
||||||
|
Tf::Etc2Rgba8Unorm => F::ETC2_R8G8B8A8_UNORM_BLOCK,
|
||||||
|
Tf::Etc2Rgba8UnormSrgb => F::ETC2_R8G8B8A8_SRGB_BLOCK,
|
||||||
|
Tf::EacR11Unorm => F::EAC_R11_UNORM_BLOCK,
|
||||||
|
Tf::EacR11Snorm => F::EAC_R11_SNORM_BLOCK,
|
||||||
|
Tf::EacRg11Unorm => F::EAC_R11G11_UNORM_BLOCK,
|
||||||
|
Tf::EacRg11Snorm => F::EAC_R11G11_SNORM_BLOCK,
|
||||||
|
Tf::Astc { block, channel } => match channel {
|
||||||
|
AstcChannel::Unorm => match block {
|
||||||
|
AstcBlock::B4x4 => F::ASTC_4X4_UNORM_BLOCK,
|
||||||
|
AstcBlock::B5x4 => F::ASTC_5X4_UNORM_BLOCK,
|
||||||
|
AstcBlock::B5x5 => F::ASTC_5X5_UNORM_BLOCK,
|
||||||
|
AstcBlock::B6x5 => F::ASTC_6X5_UNORM_BLOCK,
|
||||||
|
AstcBlock::B6x6 => F::ASTC_6X6_UNORM_BLOCK,
|
||||||
|
AstcBlock::B8x5 => F::ASTC_8X5_UNORM_BLOCK,
|
||||||
|
AstcBlock::B8x6 => F::ASTC_8X6_UNORM_BLOCK,
|
||||||
|
AstcBlock::B8x8 => F::ASTC_8X8_UNORM_BLOCK,
|
||||||
|
AstcBlock::B10x5 => F::ASTC_10X5_UNORM_BLOCK,
|
||||||
|
AstcBlock::B10x6 => F::ASTC_10X6_UNORM_BLOCK,
|
||||||
|
AstcBlock::B10x8 => F::ASTC_10X8_UNORM_BLOCK,
|
||||||
|
AstcBlock::B10x10 => F::ASTC_10X10_UNORM_BLOCK,
|
||||||
|
AstcBlock::B12x10 => F::ASTC_12X10_UNORM_BLOCK,
|
||||||
|
AstcBlock::B12x12 => F::ASTC_12X12_UNORM_BLOCK,
|
||||||
|
},
|
||||||
|
AstcChannel::UnormSrgb => match block {
|
||||||
|
AstcBlock::B4x4 => F::ASTC_4X4_SRGB_BLOCK,
|
||||||
|
AstcBlock::B5x4 => F::ASTC_5X4_SRGB_BLOCK,
|
||||||
|
AstcBlock::B5x5 => F::ASTC_5X5_SRGB_BLOCK,
|
||||||
|
AstcBlock::B6x5 => F::ASTC_6X5_SRGB_BLOCK,
|
||||||
|
AstcBlock::B6x6 => F::ASTC_6X6_SRGB_BLOCK,
|
||||||
|
AstcBlock::B8x5 => F::ASTC_8X5_SRGB_BLOCK,
|
||||||
|
AstcBlock::B8x6 => F::ASTC_8X6_SRGB_BLOCK,
|
||||||
|
AstcBlock::B8x8 => F::ASTC_8X8_SRGB_BLOCK,
|
||||||
|
AstcBlock::B10x5 => F::ASTC_10X5_SRGB_BLOCK,
|
||||||
|
AstcBlock::B10x6 => F::ASTC_10X6_SRGB_BLOCK,
|
||||||
|
AstcBlock::B10x8 => F::ASTC_10X8_SRGB_BLOCK,
|
||||||
|
AstcBlock::B10x10 => F::ASTC_10X10_SRGB_BLOCK,
|
||||||
|
AstcBlock::B12x10 => F::ASTC_12X10_SRGB_BLOCK,
|
||||||
|
AstcBlock::B12x12 => F::ASTC_12X12_SRGB_BLOCK,
|
||||||
|
},
|
||||||
|
AstcChannel::Hdr => match block {
|
||||||
|
AstcBlock::B4x4 => F::ASTC_4X4_SFLOAT_BLOCK_EXT,
|
||||||
|
AstcBlock::B5x4 => F::ASTC_5X4_SFLOAT_BLOCK_EXT,
|
||||||
|
AstcBlock::B5x5 => F::ASTC_5X5_SFLOAT_BLOCK_EXT,
|
||||||
|
AstcBlock::B6x5 => F::ASTC_6X5_SFLOAT_BLOCK_EXT,
|
||||||
|
AstcBlock::B6x6 => F::ASTC_6X6_SFLOAT_BLOCK_EXT,
|
||||||
|
AstcBlock::B8x5 => F::ASTC_8X5_SFLOAT_BLOCK_EXT,
|
||||||
|
AstcBlock::B8x6 => F::ASTC_8X6_SFLOAT_BLOCK_EXT,
|
||||||
|
AstcBlock::B8x8 => F::ASTC_8X8_SFLOAT_BLOCK_EXT,
|
||||||
|
AstcBlock::B10x5 => F::ASTC_10X5_SFLOAT_BLOCK_EXT,
|
||||||
|
AstcBlock::B10x6 => F::ASTC_10X6_SFLOAT_BLOCK_EXT,
|
||||||
|
AstcBlock::B10x8 => F::ASTC_10X8_SFLOAT_BLOCK_EXT,
|
||||||
|
AstcBlock::B10x10 => F::ASTC_10X10_SFLOAT_BLOCK_EXT,
|
||||||
|
AstcBlock::B12x10 => F::ASTC_12X10_SFLOAT_BLOCK_EXT,
|
||||||
|
AstcBlock::B12x12 => F::ASTC_12X12_SFLOAT_BLOCK_EXT,
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
42
src/lib.rs
42
src/lib.rs
@@ -47,6 +47,7 @@ pub const RIGHT_XR_TEXTURE_HANDLE: ManualTextureViewHandle = ManualTextureViewHa
|
|||||||
|
|
||||||
/// Adds OpenXR support to an App
|
/// Adds OpenXR support to an App
|
||||||
pub struct OpenXrPlugin {
|
pub struct OpenXrPlugin {
|
||||||
|
pub backend_preference: Vec<Backend>,
|
||||||
pub reqeusted_extensions: XrExtensions,
|
pub reqeusted_extensions: XrExtensions,
|
||||||
pub prefered_blend_mode: XrPreferdBlendMode,
|
pub prefered_blend_mode: XrPreferdBlendMode,
|
||||||
pub app_info: XrAppInfo,
|
pub app_info: XrAppInfo,
|
||||||
@@ -59,6 +60,7 @@ impl Plugin for OpenXrPlugin {
|
|||||||
app.insert_resource(ExitAppOnSessionExit::default());
|
app.insert_resource(ExitAppOnSessionExit::default());
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
match graphics::initialize_xr_instance(
|
match graphics::initialize_xr_instance(
|
||||||
|
&self.backend_preference,
|
||||||
SystemState::<Query<&RawHandleWrapper, With<PrimaryWindow>>>::new(&mut app.world)
|
SystemState::<Query<&RawHandleWrapper, With<PrimaryWindow>>>::new(&mut app.world)
|
||||||
.get(&app.world)
|
.get(&app.world)
|
||||||
.get_single()
|
.get_single()
|
||||||
@@ -169,6 +171,17 @@ impl Plugin for OpenXrPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(all(not(feature = "vulkan"), not(all(feature = "d3d12", windows))))]
|
||||||
|
compile_error!("At least one platform-compatible backend feature must be enabled.");
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Backend {
|
||||||
|
#[cfg(feature = "vulkan")]
|
||||||
|
Vulkan,
|
||||||
|
#[cfg(all(feature = "d3d12", windows))]
|
||||||
|
D3D12,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Resource)]
|
#[derive(Resource)]
|
||||||
struct DoPipelinedRendering;
|
struct DoPipelinedRendering;
|
||||||
|
|
||||||
@@ -213,8 +226,9 @@ fn xr_skip_frame(
|
|||||||
) {
|
) {
|
||||||
let swapchain: &Swapchain = &xr_swapchain;
|
let swapchain: &Swapchain = &xr_swapchain;
|
||||||
match swapchain {
|
match swapchain {
|
||||||
Swapchain::Vulkan(swap) => {
|
#[cfg(feature = "vulkan")]
|
||||||
swap.stream
|
Swapchain::Vulkan(swap) => &swap
|
||||||
|
.stream
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.end(
|
.end(
|
||||||
@@ -222,12 +236,23 @@ fn xr_skip_frame(
|
|||||||
**environment_blend_mode,
|
**environment_blend_mode,
|
||||||
&[],
|
&[],
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap(),
|
||||||
}
|
#[cfg(all(feature = "d3d12", windows))]
|
||||||
}
|
Swapchain::D3D12(swap) => &swap
|
||||||
|
.stream
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.end(
|
||||||
|
xr_frame_state.predicted_display_time,
|
||||||
|
**environment_blend_mode,
|
||||||
|
&[],
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DefaultXrPlugins {
|
pub struct DefaultXrPlugins {
|
||||||
|
pub backend_preference: Vec<Backend>,
|
||||||
pub reqeusted_extensions: XrExtensions,
|
pub reqeusted_extensions: XrExtensions,
|
||||||
pub prefered_blend_mode: XrPreferdBlendMode,
|
pub prefered_blend_mode: XrPreferdBlendMode,
|
||||||
pub app_info: XrAppInfo,
|
pub app_info: XrAppInfo,
|
||||||
@@ -236,6 +261,12 @@ pub struct DefaultXrPlugins {
|
|||||||
impl Default for DefaultXrPlugins {
|
impl Default for DefaultXrPlugins {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
backend_preference: vec![
|
||||||
|
#[cfg(feature = "vulkan")]
|
||||||
|
Backend::Vulkan,
|
||||||
|
#[cfg(all(feature = "d3d12", windows))]
|
||||||
|
Backend::D3D12,
|
||||||
|
],
|
||||||
reqeusted_extensions: default(),
|
reqeusted_extensions: default(),
|
||||||
prefered_blend_mode: default(),
|
prefered_blend_mode: default(),
|
||||||
app_info: default(),
|
app_info: default(),
|
||||||
@@ -261,6 +292,7 @@ impl PluginGroup for DefaultXrPlugins {
|
|||||||
})
|
})
|
||||||
.disable::<RenderPlugin>()
|
.disable::<RenderPlugin>()
|
||||||
.add_before::<RenderPlugin, _>(OpenXrPlugin {
|
.add_before::<RenderPlugin, _>(OpenXrPlugin {
|
||||||
|
backend_preference: self.backend_preference,
|
||||||
prefered_blend_mode: self.prefered_blend_mode,
|
prefered_blend_mode: self.prefered_blend_mode,
|
||||||
reqeusted_extensions: self.reqeusted_extensions,
|
reqeusted_extensions: self.reqeusted_extensions,
|
||||||
app_info: self.app_info.clone(),
|
app_info: self.app_info.clone(),
|
||||||
|
|||||||
@@ -195,17 +195,25 @@ pub fn supports_passthrough(instance: &XrInstance, system: xr::SystemId) -> xr::
|
|||||||
pub fn create_passthrough(
|
pub fn create_passthrough(
|
||||||
xr_session: &XrSession,
|
xr_session: &XrSession,
|
||||||
) -> xr::Result<(xr::Passthrough, xr::PassthroughLayer)> {
|
) -> xr::Result<(xr::Passthrough, xr::PassthroughLayer)> {
|
||||||
|
let flags = xr::PassthroughFlagsFB::IS_RUNNING_AT_CREATION;
|
||||||
|
let purpose = xr::PassthroughLayerPurposeFB::RECONSTRUCTION;
|
||||||
let passthrough = match xr_session {
|
let passthrough = match xr_session {
|
||||||
|
#[cfg(feature = "vulkan")]
|
||||||
XrSession::Vulkan(session) => {
|
XrSession::Vulkan(session) => {
|
||||||
session.create_passthrough(xr::PassthroughFlagsFB::IS_RUNNING_AT_CREATION)
|
session.create_passthrough(xr::PassthroughFlagsFB::IS_RUNNING_AT_CREATION)
|
||||||
}
|
}
|
||||||
|
#[cfg(all(feature = "d3d12", windows))]
|
||||||
|
XrSession::D3D12(session) => {
|
||||||
|
session.create_passthrough(xr::PassthroughFlagsFB::IS_RUNNING_AT_CREATION)
|
||||||
|
}
|
||||||
}?;
|
}?;
|
||||||
let passthrough_layer = match xr_session {
|
let passthrough_layer = match xr_session {
|
||||||
XrSession::Vulkan(session) => session.create_passthrough_layer(
|
#[cfg(feature = "vulkan")]
|
||||||
&passthrough,
|
XrSession::Vulkan(session) => {
|
||||||
xr::PassthroughFlagsFB::IS_RUNNING_AT_CREATION,
|
session.create_passthrough_layer(&passthrough, flags, purpose)
|
||||||
xr::PassthroughLayerPurposeFB::RECONSTRUCTION,
|
}
|
||||||
),
|
#[cfg(all(feature = "d3d12", windows))]
|
||||||
|
XrSession::D3D12(session) => session.create_passthrough_layer(&passthrough, flags, purpose),
|
||||||
}?;
|
}?;
|
||||||
Ok((passthrough, passthrough_layer))
|
Ok((passthrough, passthrough_layer))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ use bevy::render::extract_component::ExtractComponent;
|
|||||||
use bevy::render::extract_resource::{ExtractResource, ExtractResourcePlugin};
|
use bevy::render::extract_resource::{ExtractResource, ExtractResourcePlugin};
|
||||||
use core::ptr;
|
use core::ptr;
|
||||||
use openxr as xr;
|
use openxr as xr;
|
||||||
|
#[cfg(all(feature = "d3d12", windows))]
|
||||||
|
use winapi::um::d3d12::{ID3D12CommandQueue, ID3D12Device};
|
||||||
|
|
||||||
xr_resource_wrapper!(XrInstance, xr::Instance);
|
xr_resource_wrapper!(XrInstance, xr::Instance);
|
||||||
xr_resource_wrapper_copy!(XrEnvironmentBlendMode, xr::EnvironmentBlendMode);
|
xr_resource_wrapper_copy!(XrEnvironmentBlendMode, xr::EnvironmentBlendMode);
|
||||||
@@ -27,7 +29,10 @@ xr_no_clone_resource_wrapper!(XrFrameWaiter, xr::FrameWaiter);
|
|||||||
|
|
||||||
#[derive(Clone, Resource, ExtractResource)]
|
#[derive(Clone, Resource, ExtractResource)]
|
||||||
pub enum XrSession {
|
pub enum XrSession {
|
||||||
|
#[cfg(feature = "vulkan")]
|
||||||
Vulkan(xr::Session<xr::Vulkan>),
|
Vulkan(xr::Session<xr::Vulkan>),
|
||||||
|
#[cfg(all(feature = "d3d12", windows))]
|
||||||
|
D3D12(xr::Session<xr::D3D12>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::ops::Deref for XrSession {
|
impl std::ops::Deref for XrSession {
|
||||||
@@ -37,12 +42,16 @@ impl std::ops::Deref for XrSession {
|
|||||||
// SAFTEY: should be fine i think -Schmarni
|
// SAFTEY: should be fine i think -Schmarni
|
||||||
unsafe {
|
unsafe {
|
||||||
match self {
|
match self {
|
||||||
|
#[cfg(feature = "vulkan")]
|
||||||
XrSession::Vulkan(sess) => std::mem::transmute(sess),
|
XrSession::Vulkan(sess) => std::mem::transmute(sess),
|
||||||
|
#[cfg(all(feature = "d3d12", windows))]
|
||||||
|
XrSession::D3D12(sess) => std::mem::transmute(sess),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "vulkan")]
|
||||||
pub struct VulkanOXrSessionSetupInfo {
|
pub struct VulkanOXrSessionSetupInfo {
|
||||||
pub(crate) device_ptr: *const c_void,
|
pub(crate) device_ptr: *const c_void,
|
||||||
pub(crate) physical_device_ptr: *const c_void,
|
pub(crate) physical_device_ptr: *const c_void,
|
||||||
@@ -51,8 +60,18 @@ pub struct VulkanOXrSessionSetupInfo {
|
|||||||
pub(crate) xr_system_id: xr::SystemId,
|
pub(crate) xr_system_id: xr::SystemId,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "d3d12", windows))]
|
||||||
|
pub struct D3D12OXrSessionSetupInfo {
|
||||||
|
pub(crate) raw_device: *mut ID3D12Device,
|
||||||
|
pub(crate) raw_queue: *mut ID3D12CommandQueue,
|
||||||
|
pub(crate) xr_system_id: xr::SystemId,
|
||||||
|
}
|
||||||
|
|
||||||
pub enum OXrSessionSetupInfo {
|
pub enum OXrSessionSetupInfo {
|
||||||
|
#[cfg(feature = "vulkan")]
|
||||||
Vulkan(VulkanOXrSessionSetupInfo),
|
Vulkan(VulkanOXrSessionSetupInfo),
|
||||||
|
#[cfg(all(feature = "d3d12", windows))]
|
||||||
|
D3D12(D3D12OXrSessionSetupInfo),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct XrResourcePlugin;
|
pub struct XrResourcePlugin;
|
||||||
@@ -72,37 +91,55 @@ impl Plugin for XrResourcePlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub enum Swapchain {
|
pub enum Swapchain {
|
||||||
|
#[cfg(feature = "vulkan")]
|
||||||
Vulkan(SwapchainInner<xr::Vulkan>),
|
Vulkan(SwapchainInner<xr::Vulkan>),
|
||||||
|
#[cfg(all(feature = "d3d12", windows))]
|
||||||
|
D3D12(SwapchainInner<xr::D3D12>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Swapchain {
|
impl Swapchain {
|
||||||
pub(crate) fn begin(&self) -> xr::Result<()> {
|
pub(crate) fn begin(&self) -> xr::Result<()> {
|
||||||
match self {
|
match self {
|
||||||
|
#[cfg(feature = "vulkan")]
|
||||||
Swapchain::Vulkan(swapchain) => swapchain.begin(),
|
Swapchain::Vulkan(swapchain) => swapchain.begin(),
|
||||||
|
#[cfg(all(feature = "d3d12", windows))]
|
||||||
|
Swapchain::D3D12(swapchain) => swapchain.begin(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_render_views(&self) -> (wgpu::TextureView, wgpu::TextureView) {
|
pub(crate) fn get_render_views(&self) -> (wgpu::TextureView, wgpu::TextureView) {
|
||||||
match self {
|
match self {
|
||||||
|
#[cfg(feature = "vulkan")]
|
||||||
Swapchain::Vulkan(swapchain) => swapchain.get_render_views(),
|
Swapchain::Vulkan(swapchain) => swapchain.get_render_views(),
|
||||||
|
#[cfg(all(feature = "d3d12", windows))]
|
||||||
|
Swapchain::D3D12(swapchain) => swapchain.get_render_views(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn acquire_image(&self) -> xr::Result<()> {
|
pub(crate) fn acquire_image(&self) -> xr::Result<()> {
|
||||||
match self {
|
match self {
|
||||||
|
#[cfg(feature = "vulkan")]
|
||||||
Swapchain::Vulkan(swapchain) => swapchain.acquire_image(),
|
Swapchain::Vulkan(swapchain) => swapchain.acquire_image(),
|
||||||
|
#[cfg(all(feature = "d3d12", windows))]
|
||||||
|
Swapchain::D3D12(swapchain) => swapchain.acquire_image(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn wait_image(&self) -> xr::Result<()> {
|
pub(crate) fn wait_image(&self) -> xr::Result<()> {
|
||||||
match self {
|
match self {
|
||||||
|
#[cfg(feature = "vulkan")]
|
||||||
Swapchain::Vulkan(swapchain) => swapchain.wait_image(),
|
Swapchain::Vulkan(swapchain) => swapchain.wait_image(),
|
||||||
|
#[cfg(all(feature = "d3d12", windows))]
|
||||||
|
Swapchain::D3D12(swapchain) => swapchain.wait_image(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn release_image(&self) -> xr::Result<()> {
|
pub(crate) fn release_image(&self) -> xr::Result<()> {
|
||||||
match self {
|
match self {
|
||||||
|
#[cfg(feature = "vulkan")]
|
||||||
Swapchain::Vulkan(swapchain) => swapchain.release_image(),
|
Swapchain::Vulkan(swapchain) => swapchain.release_image(),
|
||||||
|
#[cfg(all(feature = "d3d12", windows))]
|
||||||
|
Swapchain::D3D12(swapchain) => swapchain.release_image(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,6 +153,7 @@ impl Swapchain {
|
|||||||
passthrough_layer: Option<&XrPassthroughLayer>,
|
passthrough_layer: Option<&XrPassthroughLayer>,
|
||||||
) -> xr::Result<()> {
|
) -> xr::Result<()> {
|
||||||
match self {
|
match self {
|
||||||
|
#[cfg(feature = "vulkan")]
|
||||||
Swapchain::Vulkan(swapchain) => swapchain.end(
|
Swapchain::Vulkan(swapchain) => swapchain.end(
|
||||||
predicted_display_time,
|
predicted_display_time,
|
||||||
views,
|
views,
|
||||||
@@ -124,6 +162,15 @@ impl Swapchain {
|
|||||||
environment_blend_mode,
|
environment_blend_mode,
|
||||||
passthrough_layer,
|
passthrough_layer,
|
||||||
),
|
),
|
||||||
|
#[cfg(all(feature = "d3d12", windows))]
|
||||||
|
Swapchain::D3D12(swapchain) => swapchain.end(
|
||||||
|
predicted_display_time,
|
||||||
|
views,
|
||||||
|
stage,
|
||||||
|
resolution,
|
||||||
|
environment_blend_mode,
|
||||||
|
passthrough_layer,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user