android: fix recovering after surface lost

This commit is contained in:
DH 2025-03-12 16:18:51 +03:00
parent b41eb0a2f7
commit 321e508616
4 changed files with 47 additions and 2 deletions

View file

@ -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;

View file

@ -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);
}

View file

@ -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)

View file

@ -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;