From a90a7a3107d6d9cf6ba7dd69445ea27594937b46 Mon Sep 17 00:00:00 2001 From: hack3rmann Date: Mon, 15 Jun 2026 12:59:07 +0300 Subject: [PATCH 1/5] add `texture_release` for best-effort surface texture dropping --- player/src/lib.rs | 3 ++- wgpu-core/src/device/trace.rs | 1 + wgpu-core/src/device/trace/record.rs | 1 + wgpu-core/src/present.rs | 38 ++++++++++++++++++++++++++++ wgpu/src/api/surface_texture.rs | 11 ++++++-- wgpu/src/backend/wgpu_core.rs | 10 ++++++++ wgpu/src/dispatch.rs | 1 + 7 files changed, 62 insertions(+), 3 deletions(-) diff --git a/player/src/lib.rs b/player/src/lib.rs index e6d7139549a..87adce5231b 100644 --- a/player/src/lib.rs +++ b/player/src/lib.rs @@ -126,7 +126,8 @@ impl Player { } Action::ConfigureSurface { .. } | Action::Present(_) - | Action::DiscardSurfaceTexture(_) => { + | Action::DiscardSurfaceTexture(_) + | Action::ReleaseSurfaceTexture(_) => { panic!("Unexpected Surface action: winit feature is not enabled") } Action::CreateBuffer(id, desc) => { diff --git a/wgpu-core/src/device/trace.rs b/wgpu-core/src/device/trace.rs index 8852798e232..1379a507aa2 100644 --- a/wgpu-core/src/device/trace.rs +++ b/wgpu-core/src/device/trace.rs @@ -154,6 +154,7 @@ pub enum Action<'a, R: ReferenceType> { }, Present(R::Surface), DiscardSurfaceTexture(R::Surface), + ReleaseSurfaceTexture(R::Surface), CreateBindGroupLayout( PointerId, crate::binding_model::BindGroupLayoutDescriptor<'a>, diff --git a/wgpu-core/src/device/trace/record.rs b/wgpu-core/src/device/trace/record.rs index 630e49affd1..2d7eeccfef6 100644 --- a/wgpu-core/src/device/trace/record.rs +++ b/wgpu-core/src/device/trace/record.rs @@ -905,6 +905,7 @@ fn action_to_owned(action: Action<'_, PointerReferences>) -> Action<'static, Poi A::GetSurfaceTexture { id, parent } => A::GetSurfaceTexture { id, parent }, A::Present(surface) => A::Present(surface), A::DiscardSurfaceTexture(surface) => A::DiscardSurfaceTexture(surface), + A::ReleaseSurfaceTexture(surface) => A::ReleaseSurfaceTexture(surface), A::DestroyBindGroupLayout(layout) => A::DestroyBindGroupLayout(layout), A::GetRenderPipelineBindGroupLayout { id, diff --git a/wgpu-core/src/present.rs b/wgpu-core/src/present.rs index b7f92b58435..3d2bcfd34cf 100644 --- a/wgpu-core/src/present.rs +++ b/wgpu-core/src/present.rs @@ -401,6 +401,28 @@ impl Surface { Ok(()) } + + /// Like `discard`, drops the inner texture reference, but skips the + /// HAL `discard_texture` call. Safe to call during unwinding; best-effort, ignores errors. + pub fn release_ref(&self) -> Result<(), SurfaceError> { + profiling::scope!("Surface::discard_on_panic"); + + let mut presentation = self.presentation.lock(); + let Some(present) = presentation.as_mut() else { + return Err(SurfaceError::NotConfigured); + }; + + // `texture` is dropped here, decrementing the refcount of + // Arc. If this was the last Arc, the Texture + // is freed, which drops NativeSurfaceTextureMetadata and + // its Arc. + _ = present + .acquired_texture + .take() + .ok_or(SurfaceError::NothingToPresent)?; + + Ok(()) + } } impl Global { @@ -463,4 +485,20 @@ impl Global { surface.discard() } + + pub fn surface_texture_release( + &self, + surface_id: id::SurfaceId, + ) -> Result<(), SurfaceError> { + let surface = self.surfaces.get(surface_id); + + #[cfg(feature = "trace")] + if let Some(present) = surface.presentation.lock().as_ref() { + if let Some(ref mut trace) = *present.device.trace.lock() { + trace.add(Action::ReleaseSurfaceTexture(surface.to_trace())); + } + } + + surface.release_ref() + } } diff --git a/wgpu/src/api/surface_texture.rs b/wgpu/src/api/surface_texture.rs index 5126c10bb85..acb83867726 100644 --- a/wgpu/src/api/surface_texture.rs +++ b/wgpu/src/api/surface_texture.rs @@ -28,8 +28,15 @@ impl SurfaceTexture { impl Drop for SurfaceTexture { fn drop(&mut self) { - if !self.presented && !thread_panicking() { - self.detail.texture_discard(); + if !self.presented { + if thread_panicking() { + // Best effort: release reference to `SwapchainAcquireSemaphore` + // This fixes + // `Trying to destroy a SwapchainAcquireSemaphore that is still in use by a SurfaceTexture` + self.detail.texture_release(); + } else { + self.detail.texture_discard(); + } } } } diff --git a/wgpu/src/backend/wgpu_core.rs b/wgpu/src/backend/wgpu_core.rs index 738c847b5f2..f693bf6d1c6 100644 --- a/wgpu/src/backend/wgpu_core.rs +++ b/wgpu/src/backend/wgpu_core.rs @@ -4025,6 +4025,16 @@ impl dispatch::SurfaceOutputDetailInterface for CoreSurfaceOutputDetail { } } } + + fn texture_release(&self) { + match self.context.0.surface_texture_release(self.surface_id) { + Ok(_status) => (), + Err(err) => { + self.context + .handle_error_nolabel(&self.error_sink, err, "Surface::release_texture") + } + } + } } impl Drop for CoreSurfaceOutputDetail { fn drop(&mut self) { diff --git a/wgpu/src/dispatch.rs b/wgpu/src/dispatch.rs index 2f07d362258..bd7e9e1eb19 100644 --- a/wgpu/src/dispatch.rs +++ b/wgpu/src/dispatch.rs @@ -607,6 +607,7 @@ pub trait SurfaceInterface: CommonTraits { pub trait SurfaceOutputDetailInterface: CommonTraits { fn texture_discard(&self); + fn texture_release(&self); } pub trait QueueWriteBufferInterface: CommonTraits { From 39e8856309f6f99418cce540e5ffe771f47a9268 Mon Sep 17 00:00:00 2001 From: hack3rmann Date: Mon, 15 Jun 2026 13:46:43 +0300 Subject: [PATCH 2/5] format `wgpu-core/src/present.rs` --- wgpu-core/src/present.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/wgpu-core/src/present.rs b/wgpu-core/src/present.rs index 3d2bcfd34cf..4afbd914133 100644 --- a/wgpu-core/src/present.rs +++ b/wgpu-core/src/present.rs @@ -486,10 +486,7 @@ impl Global { surface.discard() } - pub fn surface_texture_release( - &self, - surface_id: id::SurfaceId, - ) -> Result<(), SurfaceError> { + pub fn surface_texture_release(&self, surface_id: id::SurfaceId) -> Result<(), SurfaceError> { let surface = self.surfaces.get(surface_id); #[cfg(feature = "trace")] From 8829edbdf7bd5bb02a5ef8300f0eb949e71621d4 Mon Sep 17 00:00:00 2001 From: hack3rmann Date: Mon, 15 Jun 2026 13:50:31 +0300 Subject: [PATCH 3/5] rename `Surface::release` --- wgpu-core/src/present.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/wgpu-core/src/present.rs b/wgpu-core/src/present.rs index 4afbd914133..4303b0c14e2 100644 --- a/wgpu-core/src/present.rs +++ b/wgpu-core/src/present.rs @@ -403,9 +403,9 @@ impl Surface { } /// Like `discard`, drops the inner texture reference, but skips the - /// HAL `discard_texture` call. Safe to call during unwinding; best-effort, ignores errors. - pub fn release_ref(&self) -> Result<(), SurfaceError> { - profiling::scope!("Surface::discard_on_panic"); + /// HAL `discard_texture` call. Safe to call during unwinding + pub fn release(&self) -> Result<(), SurfaceError> { + profiling::scope!("Surface::release"); let mut presentation = self.presentation.lock(); let Some(present) = presentation.as_mut() else { @@ -496,6 +496,6 @@ impl Global { } } - surface.release_ref() + surface.release() } } From 4a4815ecdb9df3df4f38cac9d466e10cb63698ae Mon Sep 17 00:00:00 2001 From: hack3rmann Date: Mon, 15 Jun 2026 13:52:35 +0300 Subject: [PATCH 4/5] update `CHANGELOG.md` --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ed0469eb233..27ad8f661a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -216,6 +216,7 @@ By @beholdnec in [#8505](https://github.com/gfx-rs/wgpu/pull/8505). - Increase recursion limits to please `-Znext-solver`. By @nazar-pc in [#9609](https://github.com/gfx-rs/wgpu/pull/9609) - Stencil clear and reference values are now truncated to 8 bits. By @beicause in [#9607](https://github.com/gfx-rs/wgpu/pull/9607). - Fixed missing initialization of other aspects when writing to a single aspect of a multi-aspect texture. By @andyleiserson in [#9626](https://github.com/gfx-rs/wgpu/pull/9626). +- Fix process abort when a `SurfaceTexture` is dropped during panic unwind between `get_current_texture` and `Queue::present`. The acquired texture reference is now released without calling HAL discard. By @hack3rmann in [#9678](https://github.com/gfx-rs/wgpu/pull/9678). #### naga From 9d96388a1c8329482a21a4f3e14aae756b72b972 Mon Sep 17 00:00:00 2001 From: hack3rmann Date: Mon, 15 Jun 2026 13:57:20 +0300 Subject: [PATCH 5/5] fix `SurfaceOutputDetailInterface` impl for `SurfaceOutputDetailInterface` --- wgpu/src/backend/webgpu.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/wgpu/src/backend/webgpu.rs b/wgpu/src/backend/webgpu.rs index ce2803952d3..49c5c9f8ee9 100644 --- a/wgpu/src/backend/webgpu.rs +++ b/wgpu/src/backend/webgpu.rs @@ -4023,6 +4023,10 @@ impl dispatch::SurfaceOutputDetailInterface for WebSurfaceOutputDetail { fn texture_discard(&self) { // Can't really discard the texture on the web. } + + fn texture_release(&self) { + // Can't really discard the texture on the web, so there's no point of releasing too + } } impl Drop for WebSurfaceOutputDetail { fn drop(&mut self) {