Merge pull request #3530 from degasus/syncgpufix

Fifo: Fix SyncGPU.
This commit is contained in:
Pierre Bourdon 2016-01-25 10:46:08 +01:00
commit 0bd649248f
6 changed files with 40 additions and 27 deletions

View File

@ -498,6 +498,9 @@ void EmuThread()
CBoot::BootUp(); CBoot::BootUp();
// This adds the SyncGPU handler to CoreTiming, so now CoreTiming::Advance might block.
Fifo::Prepare();
// Thread is no longer acting as CPU Thread // Thread is no longer acting as CPU Thread
UndeclareAsCPUThread(); UndeclareAsCPUThread();

View File

@ -446,7 +446,7 @@ void Idle()
//the VI will be desynchronized. So, We are waiting until the FIFO finish and //the VI will be desynchronized. So, We are waiting until the FIFO finish and
//while we process only the events required by the FIFO. //while we process only the events required by the FIFO.
ProcessFifoWaitEvents(); ProcessFifoWaitEvents();
Fifo::Update(0); Fifo::FlushGpu();
} }
idledCycles += DowncountToCycles(PowerPC::ppcState.downcount); idledCycles += DowncountToCycles(PowerPC::ppcState.downcount);

View File

@ -66,7 +66,6 @@ namespace SystemTimers
static int et_Dec; static int et_Dec;
static int et_VI; static int et_VI;
static int et_CP;
static int et_AudioDMA; static int et_AudioDMA;
static int et_DSP; static int et_DSP;
static int et_IPC_HLE; static int et_IPC_HLE;
@ -74,7 +73,6 @@ static int et_PatchEngine; // PatchEngine updates every 1/60th of a second by de
static int et_Throttle; static int et_Throttle;
static u32 s_cpu_core_clock = 486000000u; // 486 mhz (its not 485, stop bugging me!) static u32 s_cpu_core_clock = 486000000u; // 486 mhz (its not 485, stop bugging me!)
static u64 s_last_sync_gpu_tick;
// These two are badly educated guesses. // These two are badly educated guesses.
// Feel free to experiment. Set them in Init below. // Feel free to experiment. Set them in Init below.
@ -123,16 +121,6 @@ static void VICallback(u64 userdata, int cyclesLate)
CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerHalfLine() - cyclesLate, et_VI); CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerHalfLine() - cyclesLate, et_VI);
} }
static void CPCallback(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, et_CP);
}
static void DecrementerCallback(u64 userdata, int cyclesLate) static void DecrementerCallback(u64 userdata, int cyclesLate)
{ {
PowerPC::ppcState.spr[SPR_DEC] = 0xFFFFFFFF; PowerPC::ppcState.spr[SPR_DEC] = 0xFFFFFFFF;
@ -238,8 +226,6 @@ void Init()
et_Dec = CoreTiming::RegisterEvent("DecCallback", DecrementerCallback); et_Dec = CoreTiming::RegisterEvent("DecCallback", DecrementerCallback);
et_VI = CoreTiming::RegisterEvent("VICallback", VICallback); et_VI = CoreTiming::RegisterEvent("VICallback", VICallback);
if (SConfig::GetInstance().bCPUThread && SConfig::GetInstance().bSyncGPU)
et_CP = CoreTiming::RegisterEvent("CPCallback", CPCallback);
et_DSP = CoreTiming::RegisterEvent("DSPCallback", DSPCallback); et_DSP = CoreTiming::RegisterEvent("DSPCallback", DSPCallback);
et_AudioDMA = CoreTiming::RegisterEvent("AudioDMACallback", AudioDMACallback); et_AudioDMA = CoreTiming::RegisterEvent("AudioDMACallback", AudioDMACallback);
et_IPC_HLE = CoreTiming::RegisterEvent("IPC_HLE_UpdateCallback", IPC_HLE_UpdateCallback); et_IPC_HLE = CoreTiming::RegisterEvent("IPC_HLE_UpdateCallback", IPC_HLE_UpdateCallback);
@ -250,9 +236,6 @@ void Init()
CoreTiming::ScheduleEvent(0, et_DSP); CoreTiming::ScheduleEvent(0, et_DSP);
CoreTiming::ScheduleEvent(s_audio_dma_period, et_AudioDMA); CoreTiming::ScheduleEvent(s_audio_dma_period, et_AudioDMA);
CoreTiming::ScheduleEvent(0, et_Throttle, Common::Timer::GetTimeMs()); CoreTiming::ScheduleEvent(0, et_Throttle, Common::Timer::GetTimeMs());
if (SConfig::GetInstance().bCPUThread && SConfig::GetInstance().bSyncGPU)
CoreTiming::ScheduleEvent(0, et_CP);
s_last_sync_gpu_tick = CoreTiming::GetTicks();
CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerField(), et_PatchEngine); CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerField(), et_PatchEngine);

View File

@ -71,7 +71,7 @@ static Common::Event g_compressAndDumpStateSyncEvent;
static std::thread g_save_thread; static std::thread g_save_thread;
// Don't forget to increase this after doing changes on the savestate system // Don't forget to increase this after doing changes on the savestate system
static const u32 STATE_VERSION = 50; // Last changed in PR 3457 static const u32 STATE_VERSION = 51; // Last changed in PR 3530
// Maps savestate versions to Dolphin versions. // Maps savestate versions to Dolphin versions.
// Versions after 42 don't need to be added to this list, // Versions after 42 don't need to be added to this list,

View File

@ -15,6 +15,7 @@
#include "Common/MsgHandler.h" #include "Common/MsgHandler.h"
#include "Core/ConfigManager.h" #include "Core/ConfigManager.h"
#include "Core/CoreTiming.h"
#include "Core/NetPlayProto.h" #include "Core/NetPlayProto.h"
#include "Core/HW/Memmap.h" #include "Core/HW/Memmap.h"
@ -45,6 +46,9 @@ static u8* s_fifo_aux_read_ptr;
bool g_use_deterministic_gpu_thread; bool g_use_deterministic_gpu_thread;
static u64 s_last_sync_gpu_tick;
static int s_event_sync_gpu;
// STATE_TO_SAVE // STATE_TO_SAVE
static u8* s_video_buffer; static u8* s_video_buffer;
static u8* s_video_buffer_read_ptr; 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; s_video_buffer_seen_ptr = s_video_buffer_pp_read_ptr = s_video_buffer_read_ptr;
} }
p.Do(g_bSkipCurrentFrame); p.Do(g_bSkipCurrentFrame);
p.Do(s_last_sync_gpu_tick);
} }
void PauseAndLock(bool doLock, bool unpauseOnUnlock) 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(); const SConfig& param = SConfig::GetInstance();
if (ticks == 0)
{
FlushGpu();
return param.iSyncGpuMaxDistance;
}
// GPU is sleeping, so no need for synchronization // GPU is sleeping, so no need for synchronization
if (s_gpu_mainloop.IsDone() || g_use_deterministic_gpu_thread) if (s_gpu_mainloop.IsDone() || g_use_deterministic_gpu_thread)
{ {
@ -514,10 +518,12 @@ int Update(int ticks)
return param.iSyncGpuMaxDistance; return param.iSyncGpuMaxDistance;
} }
// Wakeup GPU
int old = s_sync_ticks.fetch_add(ticks); int old = s_sync_ticks.fetch_add(ticks);
if (old < param.iSyncGpuMinDistance && old + ticks >= param.iSyncGpuMinDistance) if (old < param.iSyncGpuMinDistance && old + ticks >= param.iSyncGpuMinDistance)
RunGpu(); RunGpu();
// Wait for GPU
if (s_sync_ticks.load() >= param.iSyncGpuMaxDistance) if (s_sync_ticks.load() >= param.iSyncGpuMaxDistance)
{ {
while (s_sync_ticks.load() > 0) while (s_sync_ticks.load() > 0)
@ -529,4 +535,25 @@ int Update(int ticks)
return param.iSyncGpuMaxDistance - s_sync_ticks.load(); 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();
}
}
} }

View File

@ -22,6 +22,7 @@ extern std::atomic<u8*> g_video_buffer_write_ptr_xthread;
void Init(); void Init();
void Shutdown(); void Shutdown();
void Prepare(); // Must be called from the CPU thread.
void DoState(PointerWrap &f); void DoState(PointerWrap &f);
void PauseAndLock(bool doLock, bool unpauseOnUnlock); void PauseAndLock(bool doLock, bool unpauseOnUnlock);
void UpdateWantDeterminism(bool want); void UpdateWantDeterminism(bool want);
@ -52,6 +53,5 @@ void EmulatorState(bool running);
bool AtBreakpoint(); bool AtBreakpoint();
void ResetVideoBuffer(); void ResetVideoBuffer();
void SetRendering(bool bEnabled); void SetRendering(bool bEnabled);
int Update(int ticks);
}; };