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)?;