diff options
| author | Pierre Bourdon <delroth@gmail.com> | 2016-01-25 10:46:08 +0100 |
|---|---|---|
| committer | Pierre Bourdon <delroth@gmail.com> | 2016-01-25 10:46:08 +0100 |
| commit | 0bd649248f544f0d37fb7807d49bb34b1320f74e (patch) | |
| tree | a88a96e3c4f40b86cdd177fb1a47648743d0dfd2 /Source/Core/VideoCommon/Fifo.cpp | |
| parent | 7b4e9654657f583572082ef5334ebb6c8ab3c97e (diff) | |
| parent | 4295751662abc0f3018d6cdef66cc30257010426 (diff) | |
Merge pull request #3530 from degasus/syncgpufix
Fifo: Fix SyncGPU.
Diffstat (limited to 'Source/Core/VideoCommon/Fifo.cpp')
| -rw-r--r-- | Source/Core/VideoCommon/Fifo.cpp | 41 |
1 files changed, 34 insertions, 7 deletions
diff --git a/Source/Core/VideoCommon/Fifo.cpp b/Source/Core/VideoCommon/Fifo.cpp index 506024c193..e04f3ffcbf 100644 --- a/Source/Core/VideoCommon/Fifo.cpp +++ b/Source/Core/VideoCommon/Fifo.cpp @@ -15,6 +15,7 @@ #include "Common/MsgHandler.h" #include "Core/ConfigManager.h" +#include "Core/CoreTiming.h" #include "Core/NetPlayProto.h" #include "Core/HW/Memmap.h" @@ -45,6 +46,9 @@ static u8* s_fifo_aux_read_ptr; bool g_use_deterministic_gpu_thread; +static u64 s_last_sync_gpu_tick; +static int s_event_sync_gpu; + // STATE_TO_SAVE static u8* s_video_buffer; static u8* s_video_buffer_read_ptr; @@ -79,6 +83,7 @@ void DoState(PointerWrap &p) s_video_buffer_seen_ptr = s_video_buffer_pp_read_ptr = s_video_buffer_read_ptr; } p.Do(g_bSkipCurrentFrame); + p.Do(s_last_sync_gpu_tick); } void PauseAndLock(bool doLock, bool unpauseOnUnlock) @@ -492,16 +497,15 @@ void UpdateWantDeterminism(bool want) } } -int Update(int ticks) +/* This function checks the emulated CPU - GPU distance and may wake up the GPU, + * or block the CPU if required. It should be called by the CPU thread regulary. + * @ticks The gone emulated CPU time. + * @return A good time to call Update() next. + */ +static int Update(int ticks) { const SConfig& param = SConfig::GetInstance(); - if (ticks == 0) - { - FlushGpu(); - return param.iSyncGpuMaxDistance; - } - // GPU is sleeping, so no need for synchronization if (s_gpu_mainloop.IsDone() || g_use_deterministic_gpu_thread) { @@ -514,10 +518,12 @@ int Update(int ticks) return param.iSyncGpuMaxDistance; } + // Wakeup GPU int old = s_sync_ticks.fetch_add(ticks); if (old < param.iSyncGpuMinDistance && old + ticks >= param.iSyncGpuMinDistance) RunGpu(); + // Wait for GPU if (s_sync_ticks.load() >= param.iSyncGpuMaxDistance) { while (s_sync_ticks.load() > 0) @@ -529,4 +535,25 @@ int Update(int ticks) return param.iSyncGpuMaxDistance - s_sync_ticks.load(); } +static void SyncGPUCallback(u64 userdata, int cyclesLate) +{ + u64 now = CoreTiming::GetTicks(); + int next = Fifo::Update((int)(now - s_last_sync_gpu_tick)); + s_last_sync_gpu_tick = now; + + if (next > 0) + CoreTiming::ScheduleEvent(next, s_event_sync_gpu); +} + +// Initialize GPU - CPU thread syncing, this gives us a deterministic way to start the GPU thread. +void Prepare() +{ + if (SConfig::GetInstance().bCPUThread && SConfig::GetInstance().bSyncGPU) + { + s_event_sync_gpu = CoreTiming::RegisterEvent("SyncGPUCallback", SyncGPUCallback); + CoreTiming::ScheduleEvent(0, s_event_sync_gpu); + s_last_sync_gpu_tick = CoreTiming::GetTicks(); + } +} + } |
