renderer_vulkan: Address vulkan surface recreation issues

This commit is contained in:
GPUCode 2024-04-06 03:38:58 +03:00
parent 775ceac27d
commit ffe0632608
6 changed files with 22 additions and 13 deletions

View file

@ -27,14 +27,18 @@ static void UpdateLandscapeScreenLayout() {
IDCache::GetNativeLibraryClass(), IDCache::GetLandscapeScreenLayout()));
}
void EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) {
render_window = surface;
bool EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) {
if (render_window == surface) {
return false;
}
render_window = surface;
window_info.type = Frontend::WindowSystemType::Android;
window_info.render_surface = surface;
StopPresenting();
OnFramebufferSizeChanged();
return true;
}
bool EmuWindow_Android::OnTouchEvent(int x, int y, bool pressed) {

View file

@ -17,7 +17,7 @@ public:
~EmuWindow_Android();
/// Called by the onSurfaceChanges() method to change the surface
void OnSurfaceChanged(ANativeWindow* surface);
bool OnSurfaceChanged(ANativeWindow* surface);
/// Handles touch event that occur.(Touched or released)
bool OnTouchEvent(int x, int y, bool pressed);

View file

@ -288,12 +288,13 @@ void Java_org_citra_citra_1emu_NativeLibrary_surfaceChanged(JNIEnv* env,
jobject surf) {
s_surf = ANativeWindow_fromSurface(env, surf);
bool notify = false;
if (window) {
window->OnSurfaceChanged(s_surf);
notify = window->OnSurfaceChanged(s_surf);
}
auto& system = Core::System::GetInstance();
if (system.IsPoweredOn()) {
if (notify && system.IsPoweredOn()) {
system.GPU().Renderer().NotifySurfaceChanged();
}

View file

@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip

View file

@ -473,7 +473,7 @@ void PresentWindow::CopyToSwapchain(Frame* frame) {
.pSignalSemaphores = &present_ready,
};
std::scoped_lock submit_lock{scheduler.submit_mutex};
std::scoped_lock submit_lock{scheduler.submit_mutex, recreate_surface_mutex};
try {
graphics_queue.submit(submit_info, frame->present_done);

View file

@ -78,9 +78,13 @@ void Swapchain::Create(u32 width_, u32 height_, vk::SurfaceKHR surface_) {
}
bool Swapchain::AcquireNextImage() {
if (needs_recreation) {
return false;
}
MICROPROFILE_SCOPE(Vulkan_Acquire);
vk::Device device = instance.GetDevice();
vk::Result result =
const vk::Device device = instance.GetDevice();
const vk::Result result =
device.acquireNextImageKHR(swapchain, std::numeric_limits<u64>::max(),
image_acquired[frame_index], VK_NULL_HANDLE, &image_index);
@ -102,10 +106,6 @@ bool Swapchain::AcquireNextImage() {
}
void Swapchain::Present() {
if (needs_recreation) {
return;
}
const vk::PresentInfoKHR present_info = {
.waitSemaphoreCount = 1,
.pWaitSemaphores = &present_ready[image_index],
@ -119,6 +119,10 @@ void Swapchain::Present() {
[[maybe_unused]] vk::Result result = instance.GetPresentQueue().presentKHR(present_info);
} catch (vk::OutOfDateKHRError&) {
needs_recreation = true;
return;
} catch (vk::SurfaceLostKHRError&) {
needs_recreation = true;
return;
} catch (const vk::SystemError& err) {
LOG_CRITICAL(Render_Vulkan, "Swapchain presentation failed {}", err.what());
UNREACHABLE();