Skip to content

Commit

Permalink
surface.acquire_texture: ignore timeout for Android < 11
Browse files Browse the repository at this point in the history
Prior to Android 11 then Android's vkAcquireNextImageKHR implementation was
non-conformant and didn't support timeouts and additionally would log a
verbose warning if a timeout was requested.

For reference this version of AcquireNextImageKHR doesn't support timeouts:
https://android.googlesource.com/platform/frameworks/native/+/refs/tags/android-mainline-10.0.0_r13/vulkan/libvulkan/swapchain.cpp#1426
and this version does:
https://android.googlesource.com/platform/frameworks/native/+/refs/tags/android-mainline-11.0.0_r45/vulkan/libvulkan/swapchain.cpp#1438
(i.e. timeout support was added in Android 11)

This patch adds a dependency on the `android-properties` crate that provides
a simple wrapper for the `__system_property_set` syscall so that the
platform version can be read via the `ro.build.version.sdk` property
and then for versions < 30 (corresponds to Android 11) any timeout
given to `acquire_texture` will be ignored (and `u64::MAX` will be
passed to Vulkan)
  • Loading branch information
rib committed Jun 4, 2022
1 parent f7bccc1 commit e982fd4
Show file tree
Hide file tree
Showing 8 changed files with 67 additions and 8 deletions.
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 6 additions & 2 deletions wgpu-core/src/present.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ extract it from the hub.
!*/

use std::borrow::Borrow;
use std::time::Duration;

#[cfg(feature = "trace")]
use crate::device::trace::Action;
Expand Down Expand Up @@ -124,7 +123,12 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let _ = device;

let suf = A::get_surface_mut(surface);
let (texture_id, status) = match unsafe { suf.raw.acquire_texture(Some(Duration::from_millis(FRAME_TIMEOUT_MS as u64))) } {
let (texture_id, status) = match unsafe {
suf.raw
.acquire_texture(Some(std::time::Duration::from_millis(
FRAME_TIMEOUT_MS as u64,
)))
} {
Ok(Some(ast)) => {
let clear_view_desc = hal::TextureViewDescriptor {
label: Some("(wgpu internal) clear surface texture view"),
Expand Down
3 changes: 3 additions & 0 deletions wgpu-hal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ wasm-bindgen = { version = "0.2" }
web-sys = { version = "0.3", features = ["Window", "HtmlCanvasElement", "WebGl2RenderingContext"] }
js-sys = { version = "0.3" }

[target.'cfg(target_os = "android")'.dependencies]
android-properties = "0.2"

[dependencies.naga]
git = "https://github.com/gfx-rs/naga"
rev = "571302e"
Expand Down
2 changes: 1 addition & 1 deletion wgpu-hal/src/dx11/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ impl crate::Surface<Api> for Surface {

unsafe fn acquire_texture(
&mut self,
timeout_ms: u32,
_timeout: Option<std::time::Duration>,
) -> Result<Option<crate::AcquiredSurfaceTexture<Api>>, crate::SurfaceError> {
todo!()
}
Expand Down
7 changes: 5 additions & 2 deletions wgpu-hal/src/dx12/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -527,10 +527,13 @@ impl SwapChain {
self.raw
}

unsafe fn wait(&mut self, timeout: Option<std::time::Duration>) -> Result<bool, crate::SurfaceError> {
unsafe fn wait(
&mut self,
timeout: Option<std::time::Duration>,
) -> Result<bool, crate::SurfaceError> {
let timeout_ms = match timeout {
Some(duration) => duration.as_millis() as u32,
None => winbase::INFINITE
None => winbase::INFINITE,
};
match synchapi::WaitForSingleObject(self.waitable, timeout_ms) {
winbase::WAIT_ABANDONED | winbase::WAIT_FAILED => Err(crate::SurfaceError::Lost),
Expand Down
9 changes: 9 additions & 0 deletions wgpu-hal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,15 @@ pub trait Surface<A: Api>: Send + Sync {

unsafe fn unconfigure(&mut self, device: &A::Device);

/// Returns the next texture to be presented by the swapchain for drawing
///
/// A `timeout` of `None` mean to wait indefinitely, with no timeout.
///
/// # Portability
///
/// Some backends can't support a timeout when acquiring a texture and
/// the timeout will be ignored.
///
/// Returns `None` on timing out.
unsafe fn acquire_texture(
&mut self,
Expand Down
38 changes: 35 additions & 3 deletions wgpu-hal/src/vulkan/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,10 +214,12 @@ impl super::Instance {
/// - `raw_instance` must be created respecting `driver_api_version`, `extensions` and `flags`
/// - `extensions` must be a superset of `required_extensions()` and must be created from the
/// same entry, driver_api_version and flags.
#[allow(clippy::too_many_arguments)]
pub unsafe fn from_raw(
entry: ash::Entry,
raw_instance: ash::Instance,
driver_api_version: u32,
android_sdk_version: u32,
extensions: Vec<&'static CStr>,
flags: crate::InstanceFlags,
has_nv_optimus: bool,
Expand Down Expand Up @@ -283,6 +285,7 @@ impl super::Instance {
entry,
has_nv_optimus,
driver_api_version,
android_sdk_version,
}),
extensions,
})
Expand Down Expand Up @@ -557,6 +560,21 @@ impl crate::Instance<super::Api> for super::Instance {
layers
};

#[cfg(target_os = "android")]
let android_sdk_version = {
// See: https://developer.android.com/reference/android/os/Build.VERSION_CODES
let mut prop = android_properties::getprop("ro.build.version.sdk");
if let Some(val) = prop.value() {
u32::from_str_radix(&val, 10)
.expect("Failed to parse ro.build.version.sdk property")
} else {
log::error!("Couldn't read Android's ro.build.version.sdk system property");
0
}
};
#[cfg(not(target_os = "android"))]
let android_sdk_version = 0;

let vk_instance = {
let str_pointers = layers
.iter()
Expand All @@ -583,6 +601,7 @@ impl crate::Instance<super::Api> for super::Instance {
entry,
vk_instance,
driver_api_version,
android_sdk_version,
extensions,
desc.flags,
has_nv_optimus,
Expand Down Expand Up @@ -707,15 +726,28 @@ impl crate::Surface<super::Api> for super::Surface {

unsafe fn acquire_texture(
&mut self,
timeout: Option<std::time::Duration>
timeout: Option<std::time::Duration>,
) -> Result<Option<crate::AcquiredSurfaceTexture<super::Api>>, crate::SurfaceError> {
let sc = self.swapchain.as_mut().unwrap();

let timeout_ns = match timeout {
let mut timeout_ns = match timeout {
Some(duration) => duration.as_nanos() as u64,
None => u64::MAX
None => u64::MAX,
};

// AcquireNextImageKHR on Android (prior to Android 11) doesn't support timeouts
// and will also log verbose warnings if tying to use a timeout.
//
// Android 10 implementation for reference:
// https://android.googlesource.com/platform/frameworks/native/+/refs/tags/android-mainline-10.0.0_r13/vulkan/libvulkan/swapchain.cpp#1426
// Android 11 implementation for reference:
// https://android.googlesource.com/platform/frameworks/native/+/refs/tags/android-mainline-11.0.0_r45/vulkan/libvulkan/swapchain.cpp#1438
//
// Android 11 corresponds to an SDK_INT/ro.build.version.sdk of 30
if cfg!(target_os = "android") && self.instance.android_sdk_version < 30 {
timeout_ns = u64::MAX;
}

// will block if no image is available
let (index, suboptimal) =
match sc
Expand Down
1 change: 1 addition & 0 deletions wgpu-hal/src/vulkan/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ struct InstanceShared {
get_physical_device_properties: Option<khr::GetPhysicalDeviceProperties2>,
entry: ash::Entry,
has_nv_optimus: bool,
android_sdk_version: u32,
driver_api_version: u32,
}

Expand Down

0 comments on commit e982fd4

Please sign in to comment.