summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
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.cpp67
-rw-r--r--src/video_core/renderer_vulkan/vk_present_manager.h10
-rw-r--r--src/video_core/vulkan_common/vulkan_wrapper.h3
6 files changed, 36 insertions, 52 deletions
diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp
index 9cf71680c..598f4e8bf 100644
--- a/src/android/app/src/main/jni/native.cpp
+++ b/src/android/app/src/main/jni/native.cpp
@@ -218,7 +218,6 @@ public:
218 return; 218 return;
219 } 219 }
220 m_window->OnSurfaceChanged(m_native_window); 220 m_window->OnSurfaceChanged(m_native_window);
221 m_system.Renderer().NotifySurfaceChanged();
222 } 221 }
223 222
224 void ConfigureFilesystemProvider(const std::string& filepath) { 223 void ConfigureFilesystemProvider(const std::string& filepath) {
diff --git a/src/video_core/renderer_base.h b/src/video_core/renderer_base.h
index 3e12a8813..78ea5208b 100644
--- a/src/video_core/renderer_base.h
+++ b/src/video_core/renderer_base.h
@@ -89,9 +89,6 @@ public:
89 void RequestScreenshot(void* data, std::function<void(bool)> callback, 89 void RequestScreenshot(void* data, std::function<void(bool)> callback,
90 const Layout::FramebufferLayout& layout); 90 const Layout::FramebufferLayout& layout);
91 91
92 /// This is called to notify the rendering backend of a surface change
93 virtual void NotifySurfaceChanged() {}
94
95protected: 92protected:
96 Core::Frontend::EmuWindow& render_window; ///< Reference to the render window handle. 93 Core::Frontend::EmuWindow& render_window; ///< Reference to the render window handle.
97 std::unique_ptr<Core::Frontend::GraphicsContext> context; 94 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 590bc1c64..14e257cf7 100644
--- a/src/video_core/renderer_vulkan/renderer_vulkan.h
+++ b/src/video_core/renderer_vulkan/renderer_vulkan.h
@@ -56,10 +56,6 @@ public:
56 return device.GetDriverName(); 56 return device.GetDriverName();
57 } 57 }
58 58
59 void NotifySurfaceChanged() override {
60 present_manager.NotifySurfaceChanged();
61 }
62
63private: 59private:
64 void Report() const; 60 void Report() const;
65 61
diff --git a/src/video_core/renderer_vulkan/vk_present_manager.cpp b/src/video_core/renderer_vulkan/vk_present_manager.cpp
index d681bd22a..2ef36583b 100644
--- a/src/video_core/renderer_vulkan/vk_present_manager.cpp
+++ b/src/video_core/renderer_vulkan/vk_present_manager.cpp
@@ -103,8 +103,7 @@ PresentManager::PresentManager(const vk::Instance& instance_,
103 surface{surface_}, blit_supported{CanBlitToSwapchain(device.GetPhysical(), 103 surface{surface_}, blit_supported{CanBlitToSwapchain(device.GetPhysical(),
104 swapchain.GetImageViewFormat())}, 104 swapchain.GetImageViewFormat())},
105 use_present_thread{Settings::values.async_presentation.GetValue()}, 105 use_present_thread{Settings::values.async_presentation.GetValue()},
106 image_count{swapchain.GetImageCount()}, last_render_surface{ 106 image_count{swapchain.GetImageCount()} {
107 render_window_.GetWindowInfo().render_surface} {
108 107
109 auto& dld = device.GetLogical(); 108 auto& dld = device.GetLogical();
110 cmdpool = dld.CreateCommandPool({ 109 cmdpool = dld.CreateCommandPool({
@@ -289,44 +288,36 @@ void PresentManager::PresentThread(std::stop_token token) {
289 } 288 }
290} 289}
291 290
292void PresentManager::NotifySurfaceChanged() { 291void PresentManager::RecreateSwapchain(Frame* frame) {
293#ifdef ANDROID 292 swapchain.Create(*surface, frame->width, frame->height, frame->is_srgb);
294 std::scoped_lock lock{recreate_surface_mutex}; 293 image_count = swapchain.GetImageCount();
295 recreate_surface_cv.notify_one();
296#endif
297} 294}
298 295
299void PresentManager::CopyToSwapchain(Frame* frame) { 296void PresentManager::CopyToSwapchain(Frame* frame) {
300 MICROPROFILE_SCOPE(Vulkan_CopyToSwapchain); 297 bool requires_recreation = false;
301 298
302 const auto recreate_swapchain = [&] { 299 while (true) {
303 swapchain.Create(*surface, frame->width, frame->height, frame->is_srgb); 300 try {
304 image_count = swapchain.GetImageCount(); 301 // Recreate surface and swapchain if needed.
305 }; 302 if (requires_recreation) {
306 303 surface = CreateSurface(instance, render_window.GetWindowInfo());
307#ifdef ANDROID 304 RecreateSwapchain(frame);
308 std::unique_lock lock{recreate_surface_mutex}; 305 }
309 306
310 const auto needs_recreation = [&] { 307 // Draw to swapchain.
311 if (last_render_surface != render_window.GetWindowInfo().render_surface) { 308 return CopyToSwapchainImpl(frame);
312 return true; 309 } catch (const vk::Exception& except) {
313 } 310 if (except.GetResult() != VK_ERROR_SURFACE_LOST_KHR) {
314 if (swapchain.NeedsRecreation(frame->is_srgb)) { 311 throw;
315 return true; 312 }
313
314 requires_recreation = true;
316 } 315 }
317 return false;
318 };
319
320 recreate_surface_cv.wait_for(lock, std::chrono::milliseconds(400),
321 [&]() { return !needs_recreation(); });
322
323 // If the frontend recreated the surface, recreate the renderer surface and swapchain.
324 if (last_render_surface != render_window.GetWindowInfo().render_surface) {
325 last_render_surface = render_window.GetWindowInfo().render_surface;
326 surface = CreateSurface(instance, render_window.GetWindowInfo());
327 recreate_swapchain();
328 } 316 }
329#endif 317}
318
319void PresentManager::CopyToSwapchainImpl(Frame* frame) {
320 MICROPROFILE_SCOPE(Vulkan_CopyToSwapchain);
330 321
331 // If the size or colorspace of the incoming frames has changed, recreate the swapchain 322 // If the size or colorspace of the incoming frames has changed, recreate the swapchain
332 // to account for that. 323 // to account for that.
@@ -334,11 +325,11 @@ void PresentManager::CopyToSwapchain(Frame* frame) {
334 const bool size_changed = 325 const bool size_changed =
335 swapchain.GetWidth() != frame->width || swapchain.GetHeight() != frame->height; 326 swapchain.GetWidth() != frame->width || swapchain.GetHeight() != frame->height;
336 if (srgb_changed || size_changed) { 327 if (srgb_changed || size_changed) {
337 recreate_swapchain(); 328 RecreateSwapchain(frame);
338 } 329 }
339 330
340 while (swapchain.AcquireNextImage()) { 331 while (swapchain.AcquireNextImage()) {
341 recreate_swapchain(); 332 RecreateSwapchain(frame);
342 } 333 }
343 334
344 const vk::CommandBuffer cmdbuf{frame->cmdbuf}; 335 const vk::CommandBuffer cmdbuf{frame->cmdbuf};
@@ -488,4 +479,4 @@ void PresentManager::CopyToSwapchain(Frame* frame) {
488 swapchain.Present(render_semaphore); 479 swapchain.Present(render_semaphore);
489} 480}
490 481
491} // namespace Vulkan \ No newline at end of file 482} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_present_manager.h b/src/video_core/renderer_vulkan/vk_present_manager.h
index 83e859416..a3d825fe6 100644
--- a/src/video_core/renderer_vulkan/vk_present_manager.h
+++ b/src/video_core/renderer_vulkan/vk_present_manager.h
@@ -54,14 +54,15 @@ public:
54 /// Waits for the present thread to finish presenting all queued frames. 54 /// Waits for the present thread to finish presenting all queued frames.
55 void WaitPresent(); 55 void WaitPresent();
56 56
57 /// This is called to notify the rendering backend of a surface change
58 void NotifySurfaceChanged();
59
60private: 57private:
61 void PresentThread(std::stop_token token); 58 void PresentThread(std::stop_token token);
62 59
63 void CopyToSwapchain(Frame* frame); 60 void CopyToSwapchain(Frame* frame);
64 61
62 void CopyToSwapchainImpl(Frame* frame);
63
64 void RecreateSwapchain(Frame* frame);
65
65private: 66private:
66 const vk::Instance& instance; 67 const vk::Instance& instance;
67 Core::Frontend::EmuWindow& render_window; 68 Core::Frontend::EmuWindow& render_window;
@@ -76,16 +77,13 @@ private:
76 std::queue<Frame*> free_queue; 77 std::queue<Frame*> free_queue;
77 std::condition_variable_any frame_cv; 78 std::condition_variable_any frame_cv;
78 std::condition_variable free_cv; 79 std::condition_variable free_cv;
79 std::condition_variable recreate_surface_cv;
80 std::mutex swapchain_mutex; 80 std::mutex swapchain_mutex;
81 std::mutex recreate_surface_mutex;
82 std::mutex queue_mutex; 81 std::mutex queue_mutex;
83 std::mutex free_mutex; 82 std::mutex free_mutex;
84 std::jthread present_thread; 83 std::jthread present_thread;
85 bool blit_supported; 84 bool blit_supported;
86 bool use_present_thread; 85 bool use_present_thread;
87 std::size_t image_count{}; 86 std::size_t image_count{};
88 void* last_render_surface{};
89}; 87};
90 88
91} // namespace Vulkan 89} // namespace Vulkan
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.h b/src/video_core/vulkan_common/vulkan_wrapper.h
index 1e3c0fa64..0487cd3b6 100644
--- a/src/video_core/vulkan_common/vulkan_wrapper.h
+++ b/src/video_core/vulkan_common/vulkan_wrapper.h
@@ -117,6 +117,9 @@ public:
117 virtual ~Exception() = default; 117 virtual ~Exception() = default;
118 118
119 const char* what() const noexcept override; 119 const char* what() const noexcept override;
120 VkResult GetResult() const noexcept {
121 return result;
122 }
120 123
121private: 124private:
122 VkResult result; 125 VkResult result;