#[cfg(feature = "vulkan")] pub mod vulkan; use std::any::TypeId; use bevy::math::UVec2; use crate::extensions::XrExtensions; use crate::types::*; pub unsafe trait GraphicsExt: openxr::Graphics { /// Wrap the graphics specific type into the [GraphicsWrap] enum fn wrap(item: T::Inner) -> GraphicsWrap; /// Convert from wgpu format to the graphics format fn from_wgpu_format(format: wgpu::TextureFormat) -> Option; /// Convert from the graphics format to wgpu format fn to_wgpu_format(format: Self::Format) -> Option; /// Initialize graphics for this backend fn init_graphics( app_info: &AppInfo, instance: &openxr::Instance, system_id: openxr::SystemId, ) -> Result<(WgpuGraphics, Self::SessionCreateInfo)>; /// Convert a swapchain function unsafe fn to_wgpu_img( image: Self::SwapchainImage, device: &wgpu::Device, format: wgpu::TextureFormat, resolution: UVec2, ) -> Result; fn required_exts() -> XrExtensions; } pub trait GraphicsType { type Inner; } impl GraphicsType for () { type Inner = (); } pub type GraphicsBackend = GraphicsWrap<()>; impl GraphicsBackend { const ALL: &'static [Self] = &[Self::Vulkan(())]; pub fn available_backends(exts: &XrExtensions) -> Vec { Self::ALL .iter() .copied() .filter(|backend| backend.is_available(exts)) .collect() } pub fn is_available(&self, exts: &XrExtensions) -> bool { self.required_exts().is_available(exts) } pub fn required_exts(&self) -> XrExtensions { graphics_match!( self; _ => Api::required_exts() ) } } #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum GraphicsWrap { #[cfg(feature = "vulkan")] Vulkan(T::Inner), } impl GraphicsWrap { /// Returns the name of the graphics api this struct is using. pub fn graphics_name(&self) -> &'static str { graphics_match!( self; _ => std::any::type_name::() ) } fn graphics_type(&self) -> TypeId { graphics_match!( self; _ => TypeId::of::() ) } /// Checks if this struct is using the wanted graphics api. pub fn using_graphics(&self) -> bool { self.graphics_type() == TypeId::of::() } /// Checks if the two values are both using the same graphics backend pub fn using_graphics_of_val(&self, other: &GraphicsWrap) -> bool { self.graphics_type() == other.graphics_type() } } macro_rules! graphics_match { ( $field:expr; $var:pat => $expr:expr $(=> $($return:tt)*)? ) => { match $field { #[cfg(feature = "vulkan")] $crate::graphics::GraphicsWrap::Vulkan($var) => { #[allow(unused)] type Api = openxr::Vulkan; graphics_match!(@arm_impl Vulkan; $expr $(=> $($return)*)?) }, } }; ( @arm_impl $variant:ident; $expr:expr => $wrap_ty:ty ) => { GraphicsWrap::<$wrap_ty>::$variant($expr) }; ( @arm_impl $variant:ident; $expr:expr ) => { $expr }; } pub(crate) use graphics_match;