From 4d11fa405ab5e8c50de53bab410fadacadf52c7f Mon Sep 17 00:00:00 2001 From: Schmarni Date: Sun, 9 Feb 2025 03:47:46 +0100 Subject: [PATCH] fix: do a more proper wgpu init, use adapter features and limits Signed-off-by: Schmarni --- Cargo.lock | 1 + crates/bevy_openxr/Cargo.toml | 5 +- .../bevy_openxr/src/openxr/graphics/vulkan.rs | 63 +++++++++++++------ 3 files changed, 48 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a47bb84..6908772 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -878,6 +878,7 @@ dependencies = [ name = "bevy_mod_openxr" version = "0.1.1" dependencies = [ + "android_system_properties", "ash", "bevy", "bevy_mod_xr", diff --git a/crates/bevy_openxr/Cargo.toml b/crates/bevy_openxr/Cargo.toml index 8e93909..e34c04c 100644 --- a/crates/bevy_openxr/Cargo.toml +++ b/crates/bevy_openxr/Cargo.toml @@ -9,7 +9,7 @@ keywords = ["gamedev", "bevy", "Xr", "Vr", "OpenXR"] [features] default = ["vulkan", "d3d12", "passthrough"] -vulkan = ["dep:ash"] +vulkan = ["dep:ash", "dep:android_system_properties"] d3d12 = ["wgpu/dx12", "wgpu-hal/dx12", "dep:winapi"] passthrough = [] @@ -20,6 +20,7 @@ bevy = { workspace = true, default-features = true } [target.'cfg(target_os = "android")'.dependencies] ndk-context = "0.1" 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 [dependencies] @@ -39,7 +40,7 @@ openxr = { workspace = true, features = ["mint"] } wgpu = { workspace = true, features = ["vulkan-portability"] } [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 } [lints.clippy] diff --git a/crates/bevy_openxr/src/openxr/graphics/vulkan.rs b/crates/bevy_openxr/src/openxr/graphics/vulkan.rs index d3b6cd9..433ac54 100644 --- a/crates/bevy_openxr/src/openxr/graphics/vulkan.rs +++ b/crates/bevy_openxr/src/openxr/graphics/vulkan.rs @@ -1,7 +1,7 @@ use std::ffi::{c_void, CString}; use ash::vk::Handle; -use bevy::log::error; +use bevy::log::{debug, error}; use bevy::math::UVec2; use openxr::{sys, Version}; use wgpu_hal::api::Vulkan; @@ -154,6 +154,13 @@ unsafe impl GraphicsExt for openxr::Vulkan { 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; @@ -176,31 +183,54 @@ unsafe impl GraphicsExt for openxr::Vulkan { 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::() { + 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 { ::Instance::from_raw( vk_entry.clone(), vk_instance.clone(), - VK_TARGET_VERSION_ASH, - 0, + vk_device_properties.api_version, + android_sdk_version, None, extensions, flags, - false, + has_nv_optimus, 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 { error!("WGPU failed to provide an adapter"); return Err(OxrError::FailedGraphicsRequirements); }; + let wgpu_features = wgpu_exposed_adapter.features; + debug!("wgpu features: {wgpu_features:#?}"); let enabled_extensions = wgpu_exposed_adapter .adapter @@ -267,20 +297,15 @@ unsafe impl GraphicsExt for openxr::Vulkan { let wgpu_instance = unsafe { wgpu::Instance::from_hal::(wgpu_vk_instance) }; 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 { wgpu_adapter.create_device_from_hal( wgpu_open_device, &wgpu::DeviceDescriptor { label: None, required_features: wgpu_features, - required_limits: wgpu::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() - }, + required_limits: limits, memory_hints: wgpu::MemoryHints::Performance, }, None,