[video_core] Add in-flight flush throttling to prevent CPU/GPU desync (#4085)

Prevent the CPU from getting too far ahead of the GPU by limiting pending flushes.

This fixes graphical issues in games that rely on better CPU and GPU synchronization in the Scheduler, such as the flickering bug inside shrines in The Legend of Zelda: Tears of the Kingdom.

This is enabled when the GPU is in Accurate mode.

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4085
Reviewed-by: crueter <crueter@eden-emu.dev>
Reviewed-by: Shinmegumi <shinmegumi@eden-emu.dev>
This commit is contained in:
MaranBr 2026-06-22 17:05:18 +02:00 committed by crueter
parent c22f57bc4e
commit ba608d2b57
No known key found for this signature in database
GPG key ID: 425ACD2D4830EBC6
2 changed files with 15 additions and 1 deletions

View file

@ -27,6 +27,7 @@
namespace Vulkan {
constexpr u64 MAX_PENDING_FLUSHES = 5;
void Scheduler::CommandChunk::ExecuteAll(vk::CommandBuffer cmdbuf,
vk::CommandBuffer upload_cmdbuf) {
@ -115,7 +116,18 @@ Scheduler::Scheduler(const Device& device_, StateTracker& state_tracker_)
Scheduler::~Scheduler() = default;
u64 Scheduler::Flush(VkSemaphore signal_semaphore, VkSemaphore wait_semaphore) {
// When flushing, we only send data to the worker thread; no waiting is necessary.
// Prevent the CPU from getting too far ahead of the GPU by limiting pending flushes.
const bool should_throttle = Settings::IsGPULevelHigh();
if (should_throttle) {
const u64 current_tick = master_semaphore->CurrentTick();
const u64 gap = current_tick > last_submitted_tick ? current_tick - last_submitted_tick : 0;
const u64 step = (std::min)(MAX_PENDING_FLUSHES, gap);
const u64 new_tick = last_submitted_tick + step;
if (new_tick < current_tick) {
last_submitted_tick = new_tick;
master_semaphore->Wait(last_submitted_tick);
}
}
const u64 signal_value = SubmitExecution(signal_semaphore, wait_semaphore);
AllocateNewContext();
return signal_value;

View file

@ -296,6 +296,8 @@ private:
double last_target_fps{};
u64 max_frame_count{};
u64 frame_counter{};
u64 last_submitted_tick = 0;
};
} // namespace Vulkan