-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Description
Surface::drop panics "Trying to destroy a SwapchainAcquireSemaphore that is still in use by a SurfaceTexture" after device loss
After a GPU device loss, dropping a wgpu::Surface that had a frame in progress panics with:
thread 'main' panicked at wgpu-hal-29.0.0/src/vulkan/swapchain/native.rs:359:
Trying to destroy a SwapchainAcquireSemaphore that is still in use by a SurfaceTexture
Steps to Reproduce
- Call
Surface::get_current_texture()successfully — this setsPresentation::acquired_texture = Some(...)inside wgpu-core and clones theArc<SwapchainAcquireSemaphore>into the HALSurfaceTexture(refcount goes 1 → 2). - Submit GPU work with
Queue::submit()— device loss is detected here; wgpu-core callsDevice::lose(), marking the device invalid, and fires theset_device_lost_callbackcallback. - Call
SurfaceTexture::present()— this callswgpu_core::Surface::present(), which callsdevice.check_is_valid(), getsErr(DeviceError::Lost), and returns early without takingacquired_texture. The field remainsSome(...). - Drop the
wgpu::Surface(e.g. while recreating graphics resources after device loss) —Drop for wgpu_core::Surfaceruns:
// wgpu-core/src/instance.rs
impl Drop for Surface {
fn drop(&mut self) {
if let Some(present) = self.presentation.lock().take() {
for (&backend, surface) in &self.surface_per_backend {
if backend == present.device.backend() {
unsafe { surface.unconfigure(present.device.raw()) }; // ← called here
}
}
} // ← `present` (with non-None acquired_texture) dropped HERE
}
}surface.unconfigure() is called while present is still in scope, so acquired_texture is still alive. It holds an Arc<SwapchainAcquireSemaphore> clone (refcount = 2). Inside unconfigure():
// wgpu-hal/src/vulkan/swapchain/native.rs
unsafe fn release_resources(&mut self, device: &super::Device) {
// ...
for semaphore in self.acquire_semaphores.drain(..) {
let arc_removed = Arc::into_inner(semaphore).expect(
"Trying to destroy a SwapchainAcquireSemaphore that is still in use by a SurfaceTexture",
); // ← PANIC: Arc refcount is 2, not 1
}
}Arc::into_inner() returns None because refcount = 2, causing the panic.
Root Cause
Drop for wgpu_core::Surface violates unconfigure()'s own documented contract ("no resources derived from the swapchain in use") because it does not drain acquired_texture before calling unconfigure().
The underlying cause is that wgpu_core::Surface::present() (and discard()) guard themselves with device.check_is_valid()? and return early on device loss, leaving acquired_texture populated. The Drop impl doesn't account for this case.
Expected Behavior
Dropping a wgpu::Surface should not panic, regardless of device state.
Environment
- wgpu version: 29.0.0
- wgpu-hal version: 29.0.0
- wgpu-core version: 29.0.0
- Backend: Vulkan
- OS: Windows 11
- GPU: GeForce 5090 mobile
Metadata
Metadata
Assignees
Labels
Type
Projects
Status