From 9d03125fdbb0a56f57cdff9b912cf5e7c0c5eb2d Mon Sep 17 00:00:00 2001 From: imbris Date: Thu, 18 Jan 2024 00:16:09 -0500 Subject: [PATCH] Make sure to unset current context when releasing lock in Surface::present and Surface::configure of wgl backend. So that we don't fail to set the context on other threads. --- wgpu-hal/src/gles/egl.rs | 2 ++ wgpu-hal/src/gles/wgl.rs | 41 +++++++++++++++++++++++----------------- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/wgpu-hal/src/gles/egl.rs b/wgpu-hal/src/gles/egl.rs index ef0ff4b6f37..b2be827d4af 100644 --- a/wgpu-hal/src/gles/egl.rs +++ b/wgpu-hal/src/gles/egl.rs @@ -1092,7 +1092,9 @@ impl Surface { .map_err(|e| { log::error!("swap_buffers failed: {}", e); crate::SurfaceError::Lost + // TODO: should we unset the current context here? })?; + self.egl .instance .make_current(self.egl.display, None, None, None) diff --git a/wgpu-hal/src/gles/wgl.rs b/wgpu-hal/src/gles/wgl.rs index a09a50330d1..dbe8218501e 100644 --- a/wgpu-hal/src/gles/wgl.rs +++ b/wgpu-hal/src/gles/wgl.rs @@ -77,6 +77,24 @@ impl AdapterContext { AdapterContextLock { inner } } + + /// Obtain a lock to the WGL context and get handle to the [`glow::Context`] that can be used to + /// do rendering. + /// + /// Unlike [`lock`](Self::lock), this accepts a device to pass to `make_current` and exposes the error + /// when `make_current` fails. + #[track_caller] + fn lock_with_dc(&self, device: HDC) -> Result, Error> { + let inner = self + .inner + .try_lock_for(Duration::from_secs(CONTEXT_LOCK_TIMEOUT_SECS)) + .expect("Could not lock adapter context. This is most-likely a deadlock."); + + inner + .context + .make_current(device) + .map(|()| AdapterContextLock { inner }) + } } /// A guard containing a lock to an [`AdapterContext`] @@ -603,16 +621,10 @@ impl Surface { window: self.window, }; - let inner = context.inner.lock(); - - if let Err(e) = inner.context.make_current(dc.device) { + let gl = context.lock_with_dc(dc.device).map_err(|e| { log::error!("unable to make the OpenGL context current for surface: {e}",); - return Err(crate::SurfaceError::Other( - "unable to make the OpenGL context current for surface", - )); - } - - let gl = &inner.gl; + crate::SurfaceError::Other("unable to make the OpenGL context current for surface") + })?; unsafe { gl.bind_framebuffer(glow::DRAW_FRAMEBUFFER, None) }; unsafe { gl.bind_framebuffer(glow::READ_FRAMEBUFFER, Some(sc.framebuffer)) }; @@ -693,16 +705,11 @@ impl crate::Surface for Surface { } let format_desc = device.shared.describe_texture_format(config.format); - let inner = &device.shared.context.inner.lock(); - - if let Err(e) = inner.context.make_current(dc.device) { + let gl = &device.shared.context.lock_with_dc(dc.device).map_err(|e| { log::error!("unable to make the OpenGL context current for surface: {e}",); - return Err(crate::SurfaceError::Other( - "unable to make the OpenGL context current for surface", - )); - } + crate::SurfaceError::Other("unable to make the OpenGL context current for surface") + })?; - let gl = &inner.gl; let renderbuffer = unsafe { gl.create_renderbuffer() }.map_err(|error| { log::error!("Internal swapchain renderbuffer creation failed: {error}"); crate::DeviceError::OutOfMemory