diff options
| author | Nicolas James <Eele1Ephe7uZahRie@tutanota.com> | 2026-04-01 16:58:17 +1100 |
|---|---|---|
| committer | Nicolas James <Eele1Ephe7uZahRie@tutanota.com> | 2026-04-01 16:58:17 +1100 |
| commit | b8759422bc22127831e40d502d5b5767572605c9 (patch) | |
| tree | 6261453df4fea01922aeb22f58131f10c3bc8a3e /src | |
| parent | 43ddb16f8c30c3a269b1ff80162b4225b051cbb6 (diff) | |
Fix AntiLagUpdateAMD race, reduce thread contention in both paths
Diffstat (limited to 'src')
| -rw-r--r-- | src/swapchain_monitor.cc | 32 | ||||
| -rw-r--r-- | src/swapchain_monitor.hh | 6 |
2 files changed, 26 insertions, 12 deletions
diff --git a/src/swapchain_monitor.cc b/src/swapchain_monitor.cc index 002f729..a79010d 100644 --- a/src/swapchain_monitor.cc +++ b/src/swapchain_monitor.cc @@ -65,19 +65,25 @@ void ReflexSwapchainMonitor::do_monitor(const std::stop_token stoken) { break; } + // Grab the most recent semaphore we want to signal off the queue - + // and keep the lock held. + const auto wakeup_semaphore = this->wakeup_semaphores.back(); + this->wakeup_semaphores.clear(); + // Look for the latest submission and make sure it's completed. + // We have to unlock while we wait. if (!this->in_flight_submissions.empty()) { - this->in_flight_submissions.back()->await_completed(); + const auto last = std::move(this->in_flight_submissions.back()); this->in_flight_submissions.clear(); - } - // We might want to signal them all? In theory it's the same timeline - // semaphore so obviously it's redundant to signal them one by one. In - // almost all cases, there should just be one here anyway. - const auto wakeup_semaphore = this->wakeup_semaphores.back(); - wakeup_semaphores.clear(); + lock.unlock(); + last->await_completed(); + } else { + lock.unlock(); + } + // Signal the semaphore wakeup_semaphore.signal(this->device); } } @@ -106,14 +112,12 @@ void ReflexSwapchainMonitor::notify_present( std::unique_ptr<QueueContext::Submissions> submissions) { const auto lock = std::scoped_lock{this->mutex}; - if (!this->was_low_latency_requested) { return; } // Fast path where this work has already completed. - // In this case, don't wake up the thread. We can just signal - // what we have immediately on this thread. + // In this case, don't wake up the thread - we can just signal immediately. if (!this->wakeup_semaphores.empty() && submissions->has_completed()) { this->wakeup_semaphores.back().signal(this->device); this->wakeup_semaphores.clear(); @@ -134,6 +138,7 @@ AntiLagSwapchainMonitor::~AntiLagSwapchainMonitor() {} void AntiLagSwapchainMonitor::notify_present( std::unique_ptr<QueueContext::Submissions> submissions) { + const auto lock = std::scoped_lock{this->mutex}; if (!this->was_low_latency_requested) { return; } @@ -143,12 +148,17 @@ void AntiLagSwapchainMonitor::notify_present( } void AntiLagSwapchainMonitor::await_submissions() { + + auto lock = std::unique_lock{this->mutex}; if (this->in_flight_submissions.empty()) { return; } - this->in_flight_submissions.back()->await_completed(); + const auto last = std::move(this->in_flight_submissions.back()); this->in_flight_submissions.clear(); + lock.unlock(); + + last->await_completed(); } } // namespace low_latency
\ No newline at end of file diff --git a/src/swapchain_monitor.hh b/src/swapchain_monitor.hh index 4fed3f8..e8603b5 100644 --- a/src/swapchain_monitor.hh +++ b/src/swapchain_monitor.hh @@ -92,8 +92,12 @@ class ReflexSwapchainMonitor final : public SwapchainMonitor { std::unique_ptr<QueueContext::Submissions> submissions) override; }; -// Much simpler synchronous waiting with no thread requirement. +// Much simpler synchronous waiting without another monitor thread - still need +// to synchronise across threads however. class AntiLagSwapchainMonitor final : public SwapchainMonitor { + private: + std::mutex mutex; + public: AntiLagSwapchainMonitor(const DeviceContext& device, const bool was_low_latency_requested); |
