-
-
Save Noxime/ba570ca38c4e91470ddd34a3e23babd4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pub(crate) fn create_session( | |
openxr: &xr::Instance, | |
system: xr::SystemId, | |
features: wgpu::Features, | |
limits: wgpu::Limits, | |
) -> Result<Create> { | |
// MUST be queried before OpenXR is happy | |
let requirements = openxr.graphics_requirements::<xr::Vulkan>(system)?; | |
let flags = InstanceFlags::VALIDATION | InstanceFlags::DEBUG; | |
let api_min = requirements.min_api_version_supported; | |
let api_max = requirements.max_api_version_supported; | |
// Load our Vulkan library | |
let entry = unsafe { Entry::load()? }; | |
let app_info = vk::ApplicationInfo::builder().api_version(vk::make_api_version( | |
0, | |
api_max.major() as u32, | |
api_max.minor() as u32, | |
api_max.patch(), | |
)); | |
// WGPU requires some vulkan extensions to function that depend on the flags | |
let extensions = <Vulkan as Api>::Instance::required_extensions(&entry, flags)?; | |
let raw_extensions: Vec<_> = extensions.iter().map(|c| c.as_ptr()).collect(); | |
let instance_info = vk::InstanceCreateInfo::builder() | |
.enabled_extension_names(&raw_extensions) | |
.application_info(&app_info); | |
unsafe { | |
let gipa = std::mem::transmute(entry.static_fn().get_instance_proc_addr); | |
// Create vulkan instance and physical device compatible with our OpenXR system | |
let vulkan_handle = openxr | |
.create_vulkan_instance(system, gipa, as_ptr(&instance_info))? | |
.map_err(vk_err)?; | |
let physical_handle = openxr.vulkan_graphics_device(system, vulkan_handle)?; | |
let physical_device = as_handle(physical_handle); | |
// Load the ash instance from our vulkan instance | |
let vulkan = ash::Instance::load(entry.static_fn(), as_handle(vulkan_handle)); | |
let properties = vulkan.get_physical_device_properties(physical_device); | |
let api = vk_version(properties.api_version); | |
// Check our API version is compatible | |
if api < api_min || api > api_max { | |
warn!("Vulkan version is {api}, though we requested max {api_max}"); | |
} | |
// Find a queue family which has GRAPHICS capability | |
let queue_family = vulkan | |
.get_physical_device_queue_family_properties(physical_device) | |
.into_iter() | |
.enumerate() | |
.find_map(|(i, info)| { | |
info.queue_flags | |
.contains(vk::QueueFlags::GRAPHICS) | |
.then_some(i as u32) | |
}) | |
.ok_or(Error::BackendUnavailable)?; | |
// Create the HAL primitives | |
let instance = <Vulkan as Api>::Instance::from_raw( | |
entry, | |
vulkan, | |
properties.api_version, | |
0, // TODO: No Android support | |
extensions, | |
flags, | |
false, // TODO: No NVidia Optimus detection | |
None, | |
)?; | |
// "Expose" the physical device as an adapter | |
let exposed = instance | |
.expose_adapter(physical_device) | |
.ok_or(Error::BackendUnavailable)?; | |
// Query the required instance extensions for using WGPU on Vulkan | |
let extensions = exposed.adapter.required_device_extensions(features); | |
let raw_extensions: Vec<*const i8> = extensions.iter().map(|s| s.as_ptr()).collect(); | |
// Configure the vulkan virtual device | |
let queue_info = vk::DeviceQueueCreateInfo::builder() | |
.queue_family_index(queue_family) | |
.queue_priorities(&[1.0]) | |
.build(); | |
let device_info = vk::DeviceCreateInfo::builder() | |
.enabled_extension_names(&raw_extensions) | |
.queue_create_infos(&[queue_info]) | |
.build(); | |
// Acquire a raw handle to a vulkan virtual device, using WGPU required extensions | |
let device_handle = openxr | |
.create_vulkan_device(system, gipa, physical_handle, as_ptr(&device_info))? | |
.map_err(vk_err)?; | |
let vk_device = ash::Device::load( | |
instance.shared_instance().raw_instance().fp_v1_0(), | |
as_handle(device_handle), | |
); | |
let uab = wgpu_hal::UpdateAfterBindTypes::from_limits(&limits, &properties.limits); | |
// "Open" the WGPU virtual device | |
let open = exposed.adapter.device_from_raw( | |
vk_device, | |
true, | |
&extensions, | |
features, | |
uab, | |
queue_family, // family_index, | |
0, // queue_index, this should be something! | |
)?; | |
// Create our concrete WGPU types from their HAL counterparts | |
let instance = wgpu::Instance::from_hal::<wgpu_hal::api::Vulkan>(instance); | |
let adapter = instance.create_adapter_from_hal(exposed); | |
let (device, queue) = adapter.create_device_from_hal( | |
open, | |
&wgpu::DeviceDescriptor { | |
label: Some("OpenXR"), | |
features, | |
limits, | |
}, | |
None, | |
)?; | |
let (session, waiter, stream) = openxr.create_session::<Wgpu>( | |
system, | |
&SessionCreateInfo::Vulkan(openxr::vulkan::SessionCreateInfo { | |
instance: vulkan_handle, | |
physical_device: physical_device.as_raw() as *const _, | |
device: device_handle, | |
queue_family_index: queue_family, | |
queue_index: 0, | |
}), | |
)?; | |
Ok(Create { | |
instance, | |
adapter, | |
device, | |
queue, | |
session, | |
waiter, | |
stream, | |
}) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment