android: More robust surface recreation
This commit is contained in:
@ -35,6 +35,7 @@ void EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) {
|
|||||||
window_info.render_surface = surface;
|
window_info.render_surface = surface;
|
||||||
|
|
||||||
StopPresenting();
|
StopPresenting();
|
||||||
|
OnFramebufferSizeChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EmuWindow_Android::OnTouchEvent(int x, int y, bool pressed) {
|
bool EmuWindow_Android::OnTouchEvent(int x, int y, bool pressed) {
|
||||||
|
@ -100,8 +100,8 @@ PresentWindow::PresentWindow(Frontend::EmuWindow& emu_window_, const Instance& i
|
|||||||
Scheduler& scheduler_)
|
Scheduler& scheduler_)
|
||||||
: emu_window{emu_window_}, instance{instance_}, scheduler{scheduler_},
|
: emu_window{emu_window_}, instance{instance_}, scheduler{scheduler_},
|
||||||
surface{CreateSurface(instance.GetInstance(), emu_window)},
|
surface{CreateSurface(instance.GetInstance(), emu_window)},
|
||||||
swapchain{instance, emu_window.GetFramebufferLayout().width,
|
next_surface{surface}, swapchain{instance, emu_window.GetFramebufferLayout().width,
|
||||||
emu_window.GetFramebufferLayout().height, surface},
|
emu_window.GetFramebufferLayout().height, surface},
|
||||||
graphics_queue{instance.GetGraphicsQueue()}, present_renderpass{CreateRenderpass()},
|
graphics_queue{instance.GetGraphicsQueue()}, present_renderpass{CreateRenderpass()},
|
||||||
vsync_enabled{Settings::values.use_vsync_new.GetValue()},
|
vsync_enabled{Settings::values.use_vsync_new.GetValue()},
|
||||||
blit_supported{
|
blit_supported{
|
||||||
@ -328,32 +328,26 @@ void PresentWindow::PresentThread(std::stop_token token) {
|
|||||||
void PresentWindow::NotifySurfaceChanged() {
|
void PresentWindow::NotifySurfaceChanged() {
|
||||||
#ifdef ANDROID
|
#ifdef ANDROID
|
||||||
std::scoped_lock lock{recreate_surface_mutex};
|
std::scoped_lock lock{recreate_surface_mutex};
|
||||||
|
next_surface = CreateSurface(instance.GetInstance(), emu_window);
|
||||||
recreate_surface_cv.notify_one();
|
recreate_surface_cv.notify_one();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void PresentWindow::CopyToSwapchain(Frame* frame) {
|
void PresentWindow::CopyToSwapchain(Frame* frame) {
|
||||||
const auto recreate_swapchain = [&] {
|
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};
|
std::scoped_lock submit_lock{scheduler.submit_mutex};
|
||||||
graphics_queue.waitIdle();
|
graphics_queue.waitIdle();
|
||||||
swapchain.Create(frame->width, frame->height, surface);
|
swapchain.Create(frame->width, frame->height, surface);
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef ANDROID
|
#ifndef 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
|
|
||||||
const bool use_vsync = Settings::values.use_vsync_new.GetValue();
|
const bool use_vsync = Settings::values.use_vsync_new.GetValue();
|
||||||
const bool size_changed =
|
const bool size_changed =
|
||||||
swapchain.GetWidth() != frame->width || swapchain.GetHeight() != frame->height;
|
swapchain.GetWidth() != frame->width || swapchain.GetHeight() != frame->height;
|
||||||
|
@ -75,6 +75,7 @@ private:
|
|||||||
const Instance& instance;
|
const Instance& instance;
|
||||||
Scheduler& scheduler;
|
Scheduler& scheduler;
|
||||||
vk::SurfaceKHR surface;
|
vk::SurfaceKHR surface;
|
||||||
|
vk::SurfaceKHR next_surface{};
|
||||||
Swapchain swapchain;
|
Swapchain swapchain;
|
||||||
vk::CommandPool command_pool;
|
vk::CommandPool command_pool;
|
||||||
vk::Queue graphics_queue;
|
vk::Queue graphics_queue;
|
||||||
|
@ -88,6 +88,7 @@ bool Swapchain::AcquireNextImage() {
|
|||||||
case vk::Result::eSuccess:
|
case vk::Result::eSuccess:
|
||||||
break;
|
break;
|
||||||
case vk::Result::eSuboptimalKHR:
|
case vk::Result::eSuboptimalKHR:
|
||||||
|
case vk::Result::eErrorSurfaceLostKHR:
|
||||||
case vk::Result::eErrorOutOfDateKHR:
|
case vk::Result::eErrorOutOfDateKHR:
|
||||||
needs_recreation = true;
|
needs_recreation = true;
|
||||||
break;
|
break;
|
||||||
|
Reference in New Issue
Block a user