aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorbunnei <[email protected]>2023-06-01 20:07:18 -0700
committerbunnei <[email protected]>2023-06-03 00:06:07 -0700
commit098e2c4077f62890f83c0785e858080e9e18296c (patch)
tree1b76d9222948d49fbaa1252471774e81aae1419b /src
parent057117f0096a47b07f9070d48a0dbd952ab0522e (diff)
downloadyuzu-mainline-098e2c4077f62890f83c0785e858080e9e18296c.tar.gz
yuzu-mainline-098e2c4077f62890f83c0785e858080e9e18296c.zip
android: renderer_vulkan: Fix crash with surface recreation.
Diffstat (limited to 'src')
-rw-r--r--src/android/app/src/main/jni/native.cpp1
-rw-r--r--src/video_core/renderer_base.h3
-rw-r--r--src/video_core/renderer_vulkan/renderer_vulkan.h4
-rw-r--r--src/video_core/renderer_vulkan/vk_present_manager.cpp24
-rw-r--r--src/video_core/renderer_vulkan/vk_present_manager.h5
5 files changed, 36 insertions, 1 deletions
diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp
index d503ef61d..b87e04b3d 100644
--- a/src/android/app/src/main/jni/native.cpp
+++ b/src/android/app/src/main/jni/native.cpp
@@ -148,6 +148,7 @@ public:
return;
}
m_window->OnSurfaceChanged(m_native_window);
+ m_system.Renderer().NotifySurfaceChanged();
}
Core::SystemResultStatus InitializeEmulation(const std::string& filepath) {
diff --git a/src/video_core/renderer_base.h b/src/video_core/renderer_base.h
index 78ea5208b..3e12a8813 100644
--- a/src/video_core/renderer_base.h
+++ b/src/video_core/renderer_base.h
@@ -89,6 +89,9 @@ public:
void RequestScreenshot(void* data, std::function<void(bool)> callback,
const Layout::FramebufferLayout& layout);
+ /// This is called to notify the rendering backend of a surface change
+ virtual void NotifySurfaceChanged() {}
+
protected:
Core::Frontend::EmuWindow& render_window; ///< Reference to the render window handle.
std::unique_ptr<Core::Frontend::GraphicsContext> context;
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.h b/src/video_core/renderer_vulkan/renderer_vulkan.h
index 3c63a2004..b2e8cbd1b 100644
--- a/src/video_core/renderer_vulkan/renderer_vulkan.h
+++ b/src/video_core/renderer_vulkan/renderer_vulkan.h
@@ -54,6 +54,10 @@ public:
return device.GetDriverName();
}
+ void NotifySurfaceChanged() override {
+ present_manager.NotifySurfaceChanged();
+ }
+
private:
void Report() const;
diff --git a/src/video_core/renderer_vulkan/vk_present_manager.cpp b/src/video_core/renderer_vulkan/vk_present_manager.cpp
index 77832720d..dc42982e9 100644
--- a/src/video_core/renderer_vulkan/vk_present_manager.cpp
+++ b/src/video_core/renderer_vulkan/vk_present_manager.cpp
@@ -291,6 +291,13 @@ void PresentManager::PresentThread(std::stop_token token) {
}
}
+void PresentManager::NotifySurfaceChanged() {
+#ifdef ANDROID
+ std::scoped_lock lock{recreate_surface_mutex};
+ recreate_surface_cv.notify_one();
+#endif
+}
+
void PresentManager::CopyToSwapchain(Frame* frame) {
MICROPROFILE_SCOPE(Vulkan_CopyToSwapchain);
@@ -299,7 +306,22 @@ void PresentManager::CopyToSwapchain(Frame* frame) {
image_count = swapchain.GetImageCount();
};
+ const auto needs_recreation = [&] {
+ if (last_render_surface != render_window.GetWindowInfo().render_surface) {
+ return true;
+ }
+ if (swapchain.NeedsRecreation(frame->is_srgb)) {
+ return true;
+ }
+ return false;
+ };
+
#ifdef ANDROID
+ std::unique_lock lock{recreate_surface_mutex};
+
+ recreate_surface_cv.wait_for(lock, std::chrono::milliseconds(400),
+ [&]() { return !needs_recreation(); });
+
// If the frontend recreated the surface, recreate the renderer surface and swapchain.
if (last_render_surface != render_window.GetWindowInfo().render_surface) {
last_render_surface = render_window.GetWindowInfo().render_surface;
@@ -450,7 +472,7 @@ void PresentManager::CopyToSwapchain(Frame* frame) {
// Submit the image copy/blit to the swapchain
{
- std::scoped_lock lock{scheduler.submit_mutex};
+ std::scoped_lock submit_lock{scheduler.submit_mutex};
switch (const VkResult result =
device.GetGraphicsQueue().Submit(submit_info, *frame->present_done)) {
case VK_SUCCESS:
diff --git a/src/video_core/renderer_vulkan/vk_present_manager.h b/src/video_core/renderer_vulkan/vk_present_manager.h
index 3cbfce4ed..4ac2e2395 100644
--- a/src/video_core/renderer_vulkan/vk_present_manager.h
+++ b/src/video_core/renderer_vulkan/vk_present_manager.h
@@ -55,6 +55,9 @@ public:
/// Waits for the present thread to finish presenting all queued frames.
void WaitPresent();
+ /// This is called to notify the rendering backend of a surface change
+ void NotifySurfaceChanged();
+
private:
void PresentThread(std::stop_token token);
@@ -74,7 +77,9 @@ private:
std::queue<Frame*> free_queue;
std::condition_variable_any frame_cv;
std::condition_variable free_cv;
+ std::condition_variable recreate_surface_cv;
std::mutex swapchain_mutex;
+ std::mutex recreate_surface_mutex;
std::mutex queue_mutex;
std::mutex free_mutex;
std::jthread present_thread;