[hal/vulkan] Wait for fence signalled in vkAcquireNextImage (#8420)

This commit is contained in:
Connor Fitzgerald 2025-10-22 23:16:09 -04:00 committed by GitHub
parent 7f644452f0
commit b3d94317d4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 37 additions and 1 deletions

View File

@ -578,6 +578,13 @@ impl super::Device {
let images =
unsafe { functor.get_swapchain_images(raw) }.map_err(super::map_host_device_oom_err)?;
let fence = unsafe {
self.shared
.raw
.create_fence(&vk::FenceCreateInfo::default(), None)
.map_err(super::map_host_device_oom_err)?
};
// NOTE: It's important that we define the same number of acquire/present semaphores
// as we will need to index into them with the image index.
let acquire_semaphores = (0..=images.len())
@ -597,6 +604,7 @@ impl super::Device {
functor,
device: Arc::clone(&self.shared),
images,
fence,
config: config.clone(),
acquire_semaphores,
next_acquire_index: 0,

View File

@ -187,6 +187,8 @@ impl super::Swapchain {
};
};
unsafe { device.destroy_fence(self.fence, None) }
// We cannot take this by value, as the function returns `self`.
for semaphore in self.acquire_semaphores.drain(..) {
let arc_removed = Arc::into_inner(semaphore).expect(
@ -1115,7 +1117,7 @@ impl crate::Surface for super::Surface {
swapchain.raw,
timeout_ns,
acquire_semaphore_guard.acquire,
vk::Fence::null(),
swapchain.fence,
)
} {
// We treat `VK_SUBOPTIMAL_KHR` as `VK_SUCCESS` on Android.
@ -1138,6 +1140,30 @@ impl crate::Surface for super::Surface {
}
};
// Wait for the image was acquired to be fully ready to be rendered too.
//
// This wait is very important on Windows to avoid bad frame pacing on
// Windows where the Vulkan driver is using a DXGI swapchain. See
// https://github.com/gfx-rs/wgpu/issues/8310 and
// https://github.com/gfx-rs/wgpu/issues/8354 for more details.
//
// On other platforms, this wait may serve to slightly decrease frame
// latency, depending on how the platform implements waiting within
// acquire.
unsafe {
swapchain
.device
.raw
.wait_for_fences(&[swapchain.fence], false, timeout_ns)
.map_err(super::map_host_device_oom_and_lost_err)?;
swapchain
.device
.raw
.reset_fences(&[swapchain.fence])
.map_err(super::map_host_device_oom_and_lost_err)?;
}
drop(acquire_semaphore_guard);
// We only advance the surface semaphores if we successfully acquired an image, otherwise
// we should try to re-acquire using the same semaphores.

View File

@ -390,6 +390,8 @@ struct Swapchain {
functor: khr::swapchain::Device,
device: Arc<DeviceShared>,
images: Vec<vk::Image>,
/// Fence used to wait on the acquired image.
fence: vk::Fence,
config: crate::SurfaceConfiguration,
/// Semaphores used between image acquisition and the first submission