diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/android/app/src/main/jni/native.cpp | 1 | ||||
| -rw-r--r-- | src/video_core/renderer_base.h | 3 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/renderer_vulkan.h | 4 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_present_manager.cpp | 67 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_present_manager.h | 10 | ||||
| -rw-r--r-- | src/video_core/vulkan_common/vulkan_wrapper.h | 3 |
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 | |||
| 95 | protected: | 92 | protected: |
| 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 | |||
| 63 | private: | 59 | private: |
| 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 | ||
| 292 | void PresentManager::NotifySurfaceChanged() { | 291 | void 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 | ||
| 299 | void PresentManager::CopyToSwapchain(Frame* frame) { | 296 | void 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 | |||
| 319 | void 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 | |||
| 60 | private: | 57 | private: |
| 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 | |||
| 65 | private: | 66 | private: |
| 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 | ||
| 121 | private: | 124 | private: |
| 122 | VkResult result; | 125 | VkResult result; |