Browse Source

[vk] Fix lost wakeup in fence mode using atomic wait (#3598)

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3598
Reviewed-by: crueter <crueter@eden-emu.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Co-authored-by: PavelBARABANOV <pavelbarabanov94@gmail.com>
Co-committed-by: PavelBARABANOV <pavelbarabanov94@gmail.com>
pull/3624/head
PavelBARABANOV 5 days ago
committed by crueter
parent
commit
40251c2115
No known key found for this signature in database GPG Key ID: 425ACD2D4830EBC6
  1. 36
      src/video_core/renderer_vulkan/vk_master_semaphore.cpp
  2. 4
      src/video_core/renderer_vulkan/vk_master_semaphore.h

36
src/video_core/renderer_vulkan/vk_master_semaphore.cpp

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
@ -78,11 +78,16 @@ void MasterSemaphore::Refresh() {
void MasterSemaphore::Wait(u64 tick) {
if (!semaphore) {
// If we don't support timeline semaphores, wait for the value normally
std::unique_lock lk{free_mutex};
free_cv.wait(lk, [&] {
return gpu_tick.load(std::memory_order_acquire) >= tick;
});
// Fast check: already reached the requested tick?
if (gpu_tick.load(std::memory_order_acquire) >= tick) {
return;
}
u64 last_tick = gpu_tick.load(std::memory_order_relaxed);
while (gpu_tick.load(std::memory_order_acquire) < tick) {
gpu_tick.wait(last_tick, std::memory_order_acquire);
last_tick = gpu_tick.load(std::memory_order_relaxed);
}
return;
}
@ -218,32 +223,15 @@ void MasterSemaphore::WaitThread(std::stop_token token) {
wait_queue.pop();
}
#ifdef ANDROID
VkResult status;
do {
status = fence.GetStatus();
if (status == VK_NOT_READY) {
std::this_thread::sleep_for(std::chrono::microseconds(100));
}
} while (status == VK_NOT_READY);
if (status == VK_SUCCESS) {
fence.Reset();
} else {
vk::Check(status);
continue;
}
#else
fence.Wait();
fence.Reset();
#endif
{
std::scoped_lock lock{free_mutex};
free_queue.push_front(std::move(fence));
gpu_tick.store(host_tick, std::memory_order_release);
}
free_cv.notify_all();
gpu_tick.notify_one();
}
}

4
src/video_core/renderer_vulkan/vk_master_semaphore.h

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@ -74,7 +77,6 @@ private:
std::atomic<u64> current_tick{1}; ///< Current logical tick.
std::mutex wait_mutex;
std::mutex free_mutex;
std::condition_variable free_cv;
std::condition_variable_any wait_cv;
std::queue<Waitable> wait_queue; ///< Queue for the fences to be waited on by the wait thread.
std::deque<vk::Fence> free_queue; ///< Holds available fences for submission.

Loading…
Cancel
Save