From 79d8c1b9ecfc8a8d3b763a85d0ef7933c4b9def6 Mon Sep 17 00:00:00 2001 From: Hans-Kristian Arntzen Date: Sun, 29 Oct 2023 11:39:37 +0100 Subject: [PATCH] Add next_frame_context_in_async_thread. Only reclaim frame contexts when WSI thread actually goes to sleep. --- video/ffmpeg_decode.cpp | 2 +- vulkan/device.cpp | 18 ++++++++++++++++++ vulkan/device.hpp | 9 +++++++++ vulkan/wsi.cpp | 2 ++ 4 files changed, 30 insertions(+), 1 deletion(-) diff --git a/video/ffmpeg_decode.cpp b/video/ffmpeg_decode.cpp index 49d269a9..49ed8c91 100644 --- a/video/ffmpeg_decode.cpp +++ b/video/ffmpeg_decode.cpp @@ -1576,7 +1576,7 @@ void VideoDecoder::Impl::process_video_frame_in_task_upload(DecodedImage &img, A // we don't leak unbounded memory when the window is minimized on Windows. // In that scenario the main thread will not pump frame contexts regularly. if (opts.realtime) - device->next_frame_context(); + device->next_frame_context_in_async_thread(); } void VideoDecoder::Impl::process_video_frame_in_task(unsigned frame, AVFrame *av_frame) diff --git a/vulkan/device.cpp b/vulkan/device.cpp index 9679be62..14d1363a 100644 --- a/vulkan/device.cpp +++ b/vulkan/device.cpp @@ -2565,6 +2565,24 @@ void Device::promote_read_write_caches_to_read_only() } } +bool Device::set_enable_async_thread_frame_context(bool enable) +{ + LOCK(); + lock.async_frame_context = enable; +} + +void Device::next_frame_context_in_async_thread() +{ + bool do_next_frame_context; + { + LOCK(); + do_next_frame_context = lock.async_frame_context; + } + + if (do_next_frame_context) + next_frame_context(); +} + void Device::next_frame_context() { DRAIN_FRAME_LOCK(); diff --git a/vulkan/device.hpp b/vulkan/device.hpp index b6eae3df..cbaee4d8 100644 --- a/vulkan/device.hpp +++ b/vulkan/device.hpp @@ -249,6 +249,14 @@ class Device // Frame-pushing interface. void next_frame_context(); + + // Normally, the main thread ensures forward progress of the frame context + // so that async tasks don't have to care about it, + // but in the case where async threads are continuously pumping Vulkan work + // in the background, they need to reclaim memory if WSI goes to sleep for a long period of time. + void next_frame_context_in_async_thread(); + bool set_enable_async_thread_frame_context(bool enable); + void wait_idle(); void end_frame_context(); @@ -587,6 +595,7 @@ class Device std::condition_variable cond; Util::RWSpinLock read_only_cache; unsigned counter = 0; + bool async_frame_context = false; } lock; struct PerFrame diff --git a/vulkan/wsi.cpp b/vulkan/wsi.cpp index 6cbd9733..23c965ce 100644 --- a/vulkan/wsi.cpp +++ b/vulkan/wsi.cpp @@ -886,7 +886,9 @@ bool WSI::blocking_init_swapchain(unsigned width, unsigned height) else if (err == SwapchainError::NoSurface) { LOGW("WSI cannot make forward progress due to minimization, blocking ...\n"); + device->set_enable_async_thread_frame_context(true); platform->block_until_wsi_forward_progress(*this); + device->set_enable_async_thread_frame_context(false); LOGW("Woke up!\n"); } } while (err != SwapchainError::None);