From 275d84d56632236a222980c872c8ef2a798e5229 Mon Sep 17 00:00:00 2001 From: Junkui Zhang <364772080@qq.com> Date: Tue, 22 Jul 2025 15:35:27 +0800 Subject: [PATCH] init `handle_device_lost` --- .../src/platform/windows/directx_renderer.rs | 43 +++++++++++++++++-- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/crates/gpui/src/platform/windows/directx_renderer.rs b/crates/gpui/src/platform/windows/directx_renderer.rs index 2cad807ae1f882c00c36c2ccfa4d6fab1266bea2..91f85458d04d67e0a459005299de9835b4db6c69 100644 --- a/crates/gpui/src/platform/windows/directx_renderer.rs +++ b/crates/gpui/src/platform/windows/directx_renderer.rs @@ -179,7 +179,7 @@ impl DirectXRenderer { Ok(()) } - fn present(&self) -> Result<()> { + fn present(&mut self) -> Result<()> { unsafe { self.devices.device_context.ResolveSubresource( &*self.resources.render_target, @@ -191,11 +191,26 @@ impl DirectXRenderer { self.devices .device_context .OMSetRenderTargets(Some(&self.resources.render_target_view), None); - self.resources.swap_chain.Present(0, DXGI_PRESENT(0)).ok()?; + let result = self.resources.swap_chain.Present(0, DXGI_PRESENT(0)); + // Presenting the swap chain can fail if the DirectX device was removed or reset. + if result == DXGI_ERROR_DEVICE_REMOVED || result == DXGI_ERROR_DEVICE_RESET { + let reason = self.devices.device.GetDeviceRemovedReason(); + log::error!( + "DirectX device removed or reset when drawing. Reason: {:?}", + reason + ); + self.handle_device_lost()?; + } else { + result.ok()?; + } } Ok(()) } + fn handle_device_lost(&mut self) -> Result<()> { + Ok(()) + } + pub(crate) fn draw(&mut self, scene: &Scene) -> Result<()> { self.pre_draw()?; for batch in scene.batches() { @@ -237,13 +252,33 @@ impl DirectXRenderer { ManuallyDrop::drop(&mut self.resources.render_target); drop(self.resources.render_target_view[0].take().unwrap()); - self.resources.swap_chain.ResizeBuffers( + let result = self.resources.swap_chain.ResizeBuffers( BUFFER_COUNT as u32, width, height, RENDER_TARGET_FORMAT, DXGI_SWAP_CHAIN_FLAG(0), - )?; + ); + // Resizing the swap chain requires a call to the underlying DXGI adapter, which can return the device removed error. + // The app might have moved to a monitor that's attached to a different graphics device. + // When a graphics device is removed or reset, the desktop resolution often changes, resulting in a window size change. + match result { + Ok(_) => {} + Err(e) => { + if e.code() == DXGI_ERROR_DEVICE_REMOVED || e.code() == DXGI_ERROR_DEVICE_RESET + { + let reason = self.devices.device.GetDeviceRemovedReason(); + log::error!( + "DirectX device removed or reset when resizing. Reason: {:?}", + reason + ); + self.handle_device_lost()?; + return Ok(()); + } + log::error!("Failed to resize swap chain: {:?}", e); + return Err(e.into()); + } + } self.resources .recreate_resources(&self.devices, width, height)?;