diff --git a/rpcs3/rpcs3/Emu/RSX/VK/VKGSRender.h b/rpcs3/rpcs3/Emu/RSX/VK/VKGSRender.h index 88e1e2b00..1749ffffd 100644 --- a/rpcs3/rpcs3/Emu/RSX/VK/VKGSRender.h +++ b/rpcs3/rpcs3/Emu/RSX/VK/VKGSRender.h @@ -128,6 +128,7 @@ private: sizeu m_swapchain_dims{}; bool swapchain_unavailable = false; bool should_reinitialize_swapchain = false; + bool surface_lost = false; u64 m_last_heap_sync_time = 0; u32 m_texbuffer_view_size = 0; diff --git a/rpcs3/rpcs3/Emu/RSX/VK/VKPresent.cpp b/rpcs3/rpcs3/Emu/RSX/VK/VKPresent.cpp index 6bc09588d..7f71f4b6d 100644 --- a/rpcs3/rpcs3/Emu/RSX/VK/VKPresent.cpp +++ b/rpcs3/rpcs3/Emu/RSX/VK/VKPresent.cpp @@ -35,6 +35,18 @@ namespace void VKGSRender::reinitialize_swapchain() { + if (surface_lost) + { + surface_lost = false; + +#ifdef ANDROID + vkDeviceWaitIdle(*m_device); + + auto handle = m_frame->handle(); + m_swapchain->create(handle); +#endif + } + m_swapchain_dims.width = m_frame->client_width(); m_swapchain_dims.height = m_frame->client_height(); @@ -123,6 +135,11 @@ void VKGSRender::present(vk::frame_context_t *ctx) case VK_ERROR_OUT_OF_DATE_KHR: swapchain_unavailable = true; break; + case VK_ERROR_SURFACE_LOST_KHR: + surface_lost = true; + swapchain_unavailable = true; + break; + default: // Other errors not part of rpcs3. This can be caused by 3rd party injectors with bad code, of which we have no control over. // Let the application attempt to recover instead of crashing outright. @@ -591,6 +608,13 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info) swapchain_unavailable = true; reinitialize_swapchain(); continue; + + case VK_ERROR_SURFACE_LOST_KHR: + surface_lost = true; + swapchain_unavailable = true; + reinitialize_swapchain(); + break; + default: vk::die_with_error(status); } diff --git a/rpcs3/rpcs3/Emu/RSX/VK/vkutils/swapchain.cpp b/rpcs3/rpcs3/Emu/RSX/VK/vkutils/swapchain.cpp index a296e393e..dd4a27fd3 100644 --- a/rpcs3/rpcs3/Emu/RSX/VK/vkutils/swapchain.cpp +++ b/rpcs3/rpcs3/Emu/RSX/VK/vkutils/swapchain.cpp @@ -133,6 +133,27 @@ namespace vk } } + void swapchain_WSI::create(display_handle_t& handle) + { +#ifdef ANDROID + if (!dev) + { + return; + } + + if (m_vk_swapchain) + { + _vkDestroySwapchainKHR(dev, m_vk_swapchain, nullptr); + m_vk_swapchain = nullptr; + } + + swapchain_images.clear(); + + WSI_config config{}; + m_surface = make_WSI_surface(dev.gpu(), handle, &config); +#endif + } + void swapchain_WSI::destroy(bool) { if (VkDevice pdev = dev) diff --git a/rpcs3/rpcs3/Emu/RSX/VK/vkutils/swapchain_core.h b/rpcs3/rpcs3/Emu/RSX/VK/vkutils/swapchain_core.h index aaf8426b9..2bc373862 100644 --- a/rpcs3/rpcs3/Emu/RSX/VK/vkutils/swapchain_core.h +++ b/rpcs3/rpcs3/Emu/RSX/VK/vkutils/swapchain_core.h @@ -184,8 +184,7 @@ namespace vk ~swapchain_WSI() override = default; - void create(display_handle_t&) override - {} + void create(display_handle_t&) override; void destroy(bool = true) override;