android: More robust surface recreation

This commit is contained in:
GPUCode
2023-08-25 03:33:57 +03:00
parent ff10decc2c
commit a608e33593
4 changed files with 14 additions and 17 deletions

View File

@ -35,6 +35,7 @@ void EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) {
window_info.render_surface = surface;
StopPresenting();
OnFramebufferSizeChanged();
}
bool EmuWindow_Android::OnTouchEvent(int x, int y, bool pressed) {

View File

@ -100,8 +100,8 @@ PresentWindow::PresentWindow(Frontend::EmuWindow& emu_window_, const Instance& i
Scheduler& scheduler_)
: emu_window{emu_window_}, instance{instance_}, scheduler{scheduler_},
surface{CreateSurface(instance.GetInstance(), emu_window)},
swapchain{instance, emu_window.GetFramebufferLayout().width,
emu_window.GetFramebufferLayout().height, surface},
next_surface{surface}, swapchain{instance, emu_window.GetFramebufferLayout().width,
emu_window.GetFramebufferLayout().height, surface},
graphics_queue{instance.GetGraphicsQueue()}, present_renderpass{CreateRenderpass()},
vsync_enabled{Settings::values.use_vsync_new.GetValue()},
blit_supported{
@ -328,32 +328,26 @@ void PresentWindow::PresentThread(std::stop_token token) {
void PresentWindow::NotifySurfaceChanged() {
#ifdef ANDROID
std::scoped_lock lock{recreate_surface_mutex};
next_surface = CreateSurface(instance.GetInstance(), emu_window);
recreate_surface_cv.notify_one();
#endif
}
void PresentWindow::CopyToSwapchain(Frame* frame) {
const auto recreate_swapchain = [&] {
#ifdef ANDROID
{
std::unique_lock lock{recreate_surface_mutex};
recreate_surface_cv.wait(lock, [this]() { return surface != next_surface; });
surface = next_surface;
}
#endif
std::scoped_lock submit_lock{scheduler.submit_mutex};
graphics_queue.waitIdle();
swapchain.Create(frame->width, frame->height, surface);
};
#ifdef ANDROID
std::unique_lock lock{recreate_surface_mutex};
recreate_surface_cv.wait_for(lock, std::chrono::milliseconds(400), [&]() {
return last_render_surface == emu_window.GetWindowInfo().render_surface;
});
// If the frontend recreated the surface, recreate the renderer surface and swapchain.
void* const render_surface = emu_window.GetWindowInfo().render_surface;
if (last_render_surface != render_surface) {
last_render_surface = render_surface;
surface = CreateSurface(instance.GetInstance(), emu_window);
recreate_swapchain();
}
#else
#ifndef ANDROID
const bool use_vsync = Settings::values.use_vsync_new.GetValue();
const bool size_changed =
swapchain.GetWidth() != frame->width || swapchain.GetHeight() != frame->height;

View File

@ -75,6 +75,7 @@ private:
const Instance& instance;
Scheduler& scheduler;
vk::SurfaceKHR surface;
vk::SurfaceKHR next_surface{};
Swapchain swapchain;
vk::CommandPool command_pool;
vk::Queue graphics_queue;

View File

@ -88,6 +88,7 @@ bool Swapchain::AcquireNextImage() {
case vk::Result::eSuccess:
break;
case vk::Result::eSuboptimalKHR:
case vk::Result::eErrorSurfaceLostKHR:
case vk::Result::eErrorOutOfDateKHR:
needs_recreation = true;
break;