Merge pull request #174 from Schmarni-Dev/proper_wgpu_init

More correct wgpu init
This commit is contained in:
Schmarni
2025-02-10 01:07:21 +01:00
committed by GitHub
3 changed files with 48 additions and 21 deletions

1
Cargo.lock generated
View File

@@ -878,6 +878,7 @@ dependencies = [
name = "bevy_mod_openxr" name = "bevy_mod_openxr"
version = "0.1.1" version = "0.1.1"
dependencies = [ dependencies = [
"android_system_properties",
"ash", "ash",
"bevy", "bevy",
"bevy_mod_xr", "bevy_mod_xr",

View File

@@ -9,7 +9,7 @@ keywords = ["gamedev", "bevy", "Xr", "Vr", "OpenXR"]
[features] [features]
default = ["vulkan", "d3d12", "passthrough"] default = ["vulkan", "d3d12", "passthrough"]
vulkan = ["dep:ash"] vulkan = ["dep:ash", "dep:android_system_properties"]
d3d12 = ["wgpu/dx12", "wgpu-hal/dx12", "dep:winapi"] d3d12 = ["wgpu/dx12", "wgpu-hal/dx12", "dep:winapi"]
passthrough = [] passthrough = []
@@ -20,6 +20,7 @@ bevy = { workspace = true, default-features = true }
[target.'cfg(target_os = "android")'.dependencies] [target.'cfg(target_os = "android")'.dependencies]
ndk-context = "0.1" ndk-context = "0.1"
jni = "0.20" jni = "0.20"
android_system_properties = { version = "0.1.5", optional = true }
# bevy can't be placed behind target or proc macros won't work properly # bevy can't be placed behind target or proc macros won't work properly
[dependencies] [dependencies]
@@ -39,7 +40,7 @@ openxr = { workspace = true, features = ["mint"] }
wgpu = { workspace = true, features = ["vulkan-portability"] } wgpu = { workspace = true, features = ["vulkan-portability"] }
[target.'cfg(target_family = "windows")'.dependencies] [target.'cfg(target_family = "windows")'.dependencies]
openxr = { workspace=true, features = ["mint", "static"] } openxr = { workspace = true, features = ["mint", "static"] }
winapi = { version = "0.3.9", optional = true } winapi = { version = "0.3.9", optional = true }
[lints.clippy] [lints.clippy]

View File

@@ -1,7 +1,7 @@
use std::ffi::{c_void, CString}; use std::ffi::{c_void, CString};
use ash::vk::Handle; use ash::vk::Handle;
use bevy::log::error; use bevy::log::{debug, error};
use bevy::math::UVec2; use bevy::math::UVec2;
use openxr::{sys, Version}; use openxr::{sys, Version};
use wgpu_hal::api::Vulkan; use wgpu_hal::api::Vulkan;
@@ -154,6 +154,13 @@ unsafe impl GraphicsExt for openxr::Vulkan {
ash::vk::Instance::from_raw(vk_instance as _), ash::vk::Instance::from_raw(vk_instance as _),
) )
}; };
let api_layers = unsafe { vk_entry.enumerate_instance_layer_properties()? };
let has_nv_optimus = api_layers.iter().any(|v| {
v.layer_name_as_c_str()
.is_ok_and(|v| v == c"VK_LAYER_NV_optimus")
});
drop(api_layers);
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;
@@ -176,31 +183,54 @@ unsafe impl GraphicsExt for openxr::Vulkan {
return Err(OxrError::FailedGraphicsRequirements); return Err(OxrError::FailedGraphicsRequirements);
} }
// the android_sdk_version stuff is copied from wgpu
#[cfg(target_os = "android")]
let android_sdk_version = {
let properties = android_system_properties::AndroidSystemProperties::new();
// See: https://developer.android.com/reference/android/os/Build.VERSION_CODES
if let Some(val) = properties.get("ro.build.version.sdk") {
match val.parse::<u32>() {
Ok(sdk_ver) => sdk_ver,
Err(err) => {
error!(
concat!(
"Couldn't parse Android's ",
"ro.build.version.sdk system property ({}): {}",
),
val,
err,
);
0
}
}
} else {
error!("Couldn't read Android's ro.build.version.sdk system property");
0
}
};
#[cfg(not(target_os = "android"))]
let android_sdk_version = 0;
let wgpu_vk_instance = unsafe { let wgpu_vk_instance = unsafe {
<Vulkan as Api>::Instance::from_raw( <Vulkan as Api>::Instance::from_raw(
vk_entry.clone(), vk_entry.clone(),
vk_instance.clone(), vk_instance.clone(),
VK_TARGET_VERSION_ASH, vk_device_properties.api_version,
0, android_sdk_version,
None, None,
extensions, extensions,
flags, flags,
false, has_nv_optimus,
None, None,
)? )?
}; };
let wgpu_features = wgpu::Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES
| wgpu::Features::MULTIVIEW
| wgpu::Features::MULTI_DRAW_INDIRECT_COUNT
| wgpu::Features::MULTI_DRAW_INDIRECT
| wgpu::Features::TEXTURE_FORMAT_16BIT_NORM
| wgpu::Features::CLEAR_TEXTURE;
let Some(wgpu_exposed_adapter) = wgpu_vk_instance.expose_adapter(vk_physical_device) else { let Some(wgpu_exposed_adapter) = wgpu_vk_instance.expose_adapter(vk_physical_device) else {
error!("WGPU failed to provide an adapter"); error!("WGPU failed to provide an adapter");
return Err(OxrError::FailedGraphicsRequirements); return Err(OxrError::FailedGraphicsRequirements);
}; };
let wgpu_features = wgpu_exposed_adapter.features;
debug!("wgpu features: {wgpu_features:#?}");
let enabled_extensions = wgpu_exposed_adapter let enabled_extensions = wgpu_exposed_adapter
.adapter .adapter
@@ -267,20 +297,15 @@ unsafe impl GraphicsExt for openxr::Vulkan {
let wgpu_instance = let wgpu_instance =
unsafe { wgpu::Instance::from_hal::<wgpu_hal::api::Vulkan>(wgpu_vk_instance) }; unsafe { wgpu::Instance::from_hal::<wgpu_hal::api::Vulkan>(wgpu_vk_instance) };
let wgpu_adapter = unsafe { wgpu_instance.create_adapter_from_hal(wgpu_exposed_adapter) }; let wgpu_adapter = unsafe { wgpu_instance.create_adapter_from_hal(wgpu_exposed_adapter) };
let limits = wgpu_adapter.limits();
debug!("wgpu_limits: {limits:#?}");
let (wgpu_device, wgpu_queue) = unsafe { let (wgpu_device, wgpu_queue) = unsafe {
wgpu_adapter.create_device_from_hal( wgpu_adapter.create_device_from_hal(
wgpu_open_device, wgpu_open_device,
&wgpu::DeviceDescriptor { &wgpu::DeviceDescriptor {
label: None, label: None,
required_features: wgpu_features, required_features: wgpu_features,
required_limits: wgpu::Limits { required_limits: limits,
max_bind_groups: 8,
max_storage_buffer_binding_size: wgpu_adapter
.limits()
.max_storage_buffer_binding_size,
max_push_constant_size: 4,
..Default::default()
},
memory_hints: wgpu::MemoryHints::Performance, memory_hints: wgpu::MemoryHints::Performance,
}, },
None, None,