From da088e62ad25dc53e20230c84b36c573bd95c46a Mon Sep 17 00:00:00 2001 From: "memberTwo.mb2" Date: Wed, 24 Sep 2008 10:52:58 +0000 Subject: [PATCH] DC idle skipping part 2: video thread is woken up when "OnIdle". For testing purpose only (I can't test with lots of games) because it may break some sync. Besides, I'm not satisfied with the way things are done. So just uncomment "//#define THREAD_VIDEO_WAKEUP_ONIDLE" in thread.h in order to test it. Works fine with movies, 2D and simple 3D in ZWW at least. If it's ok I'll clean up the code. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@658 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/Common/Src/Thread.cpp | 4 ++++ Source/Core/Common/Src/Thread.h | 8 +++++++ Source/Core/Core/Src/Core.cpp | 7 ++++++ Source/Core/Core/Src/HW/CommandProcessor.cpp | 14 ++++++----- Source/Core/Core/Src/PowerPC/PowerPC.cpp | 6 +++++ Source/Core/VideoCommon/Src/Fifo.cpp | 25 ++++++++++++++++++-- 6 files changed, 56 insertions(+), 8 deletions(-) diff --git a/Source/Core/Common/Src/Thread.cpp b/Source/Core/Common/Src/Thread.cpp index 18f0763b51..716f79ff55 100644 --- a/Source/Core/Common/Src/Thread.cpp +++ b/Source/Core/Common/Src/Thread.cpp @@ -28,6 +28,10 @@ #include "Thread.h" +#if defined(THREAD_VIDEO_WAKEUP_ONIDLE) && defined(_WIN32) +HANDLE g_hEventOnIdle=NULL; +#endif + namespace Common { #ifdef _WIN32 diff --git a/Source/Core/Common/Src/Thread.h b/Source/Core/Common/Src/Thread.h index af084c6b4b..6043215eef 100644 --- a/Source/Core/Common/Src/Thread.h +++ b/Source/Core/Common/Src/Thread.h @@ -32,6 +32,14 @@ #include "Common.h" + +// for testing purpose +//#define THREAD_VIDEO_WAKEUP_ONIDLE + +#if defined(THREAD_VIDEO_WAKEUP_ONIDLE) && defined(_WIN32) +extern HANDLE g_hEventOnIdle; +#endif + namespace Common { class CriticalSection diff --git a/Source/Core/Core/Src/Core.cpp b/Source/Core/Core/Src/Core.cpp index 10c65eafe9..5e6c003619 100644 --- a/Source/Core/Core/Src/Core.cpp +++ b/Source/Core/Core/Src/Core.cpp @@ -367,10 +367,17 @@ THREAD_RETURN EmuThread(void *pArg) } else { +#if defined(THREAD_VIDEO_WAKEUP_ONIDLE) && defined(_WIN32) + g_hEventOnIdle = CreateEvent( NULL, FALSE, FALSE, "EventOnIdle"); + if (g_hEventOnIdle == NULL) PanicAlert("EmuThread() -> Create EventOnIdle error"); +#endif cpuThread = new Common::Thread(CpuThread, pArg); PluginVideo::Video_Prepare(); //wglMakeCurrent Common::SetCurrentThreadName("Video thread"); PluginVideo::Video_EnterLoop(); +#if defined(THREAD_VIDEO_WAKEUP_ONIDLE) && defined(_WIN32) + CloseHandle(g_hEventOnIdle); +#endif } // Wait for CPU thread to exit - it should have been signaled to do so by now diff --git a/Source/Core/Core/Src/HW/CommandProcessor.cpp b/Source/Core/Core/Src/HW/CommandProcessor.cpp index 9fa506b16c..b9bcc3978d 100644 --- a/Source/Core/Core/Src/HW/CommandProcessor.cpp +++ b/Source/Core/Core/Src/HW/CommandProcessor.cpp @@ -459,9 +459,10 @@ void CatchUpGPU() void UpdateFifoRegister() { // update the distance -#ifdef _WIN32 - if (Core::g_CoreStartupParameter.bUseDualCore) EnterCriticalSection(&fifo.sync); -#endif +//#ifdef _WIN32 +// not needed since we are already in the critical section in DC mode -> see write16(...) (unique reference) +// if (Core::g_CoreStartupParameter.bUseDualCore) EnterCriticalSection(&fifo.sync); +//#endif int wp = fifo.CPWritePointer; int rp = fifo.CPReadPointer; if (wp >= rp) @@ -469,9 +470,10 @@ void UpdateFifoRegister() else fifo.CPReadWriteDistance = (wp - fifo.CPBase) + (fifo.CPEnd - rp); -#ifdef _WIN32 - if (Core::g_CoreStartupParameter.bUseDualCore) LeaveCriticalSection(&fifo.sync); -#endif +//#ifdef _WIN32 +// not needed since we are already in the critical section in DC mode (see write16) +// if (Core::g_CoreStartupParameter.bUseDualCore) LeaveCriticalSection(&fifo.sync); +//#endif if (!Core::g_CoreStartupParameter.bUseDualCore) CatchUpGPU(); } diff --git a/Source/Core/Core/Src/PowerPC/PowerPC.cpp b/Source/Core/Core/Src/PowerPC/PowerPC.cpp index 7058f4ec17..35ce178b7b 100644 --- a/Source/Core/Core/Src/PowerPC/PowerPC.cpp +++ b/Source/Core/Core/Src/PowerPC/PowerPC.cpp @@ -33,6 +33,8 @@ #include "../Host.h" +#include "thread.h" // for g_hEventOnIdle + namespace PowerPC { // STATE_TO_SAVE @@ -293,6 +295,10 @@ namespace PowerPC //DualCore OnIdle void OnIdleDC(void) { +#if defined(THREAD_VIDEO_WAKEUP_ONIDLE) && defined(_WIN32) + if (g_hEventOnIdle==NULL) PanicAlert("Idle() -> EventOnIdle NULL"); + if (! SetEvent(g_hEventOnIdle) ) { PanicAlert("Idle() -> SetEvent EventOnIdle failed");} +#endif CoreTiming::Idle(); } } diff --git a/Source/Core/VideoCommon/Src/Fifo.cpp b/Source/Core/VideoCommon/Src/Fifo.cpp index 4781a351c1..d6e6cef4b0 100644 --- a/Source/Core/VideoCommon/Src/Fifo.cpp +++ b/Source/Core/VideoCommon/Src/Fifo.cpp @@ -127,20 +127,36 @@ void Video_SendFifoData(u8* _uData) void Fifo_EnterLoop(const SVideoInitialize &video_initialize) { SCPFifoStruct &_fifo = *video_initialize.pCPFifo; +#if defined(THREAD_VIDEO_WAKEUP_ONIDLE) && defined(_WIN32) + HANDLE hEventOnIdle= OpenEventA(EVENT_ALL_ACCESS,FALSE,(LPCSTR)"EventOnIdle"); + if (hEventOnIdle==NULL) PanicAlert("Fifo_EnterLoop() -> EventOnIdle NULL"); +#endif // TODO(ector): Don't peek so often! while (video_initialize.pPeekMessages()) { +#if defined(THREAD_VIDEO_WAKEUP_ONIDLE) && defined(_WIN32) + if (MsgWaitForMultipleObjects(1, &hEventOnIdle, FALSE, 1L, QS_ALLEVENTS) == WAIT_ABANDONED) + break; +#endif if (_fifo.CPReadWriteDistance < 1) //fifo.CPLoWatermark) +#if defined(THREAD_VIDEO_WAKEUP_ONIDLE) && defined(_WIN32) + continue; +#else Common::SleepCurrentThread(1); +#endif //etc... // check if we are able to run this buffer if ((_fifo.bFF_GPReadEnable) && !(_fifo.bFF_BPEnable && _fifo.bFF_Breakpoint)) { - int count = 200; +#if defined(THREAD_VIDEO_WAKEUP_ONIDLE) && defined(_WIN32) + while(_fifo.CPReadWriteDistance > 0) +#else + int count = 200; while(_fifo.CPReadWriteDistance > 0 && count) - { +#endif + { // check if we are on a breakpoint if (_fifo.bFF_BPEnable) { @@ -169,10 +185,15 @@ void Fifo_EnterLoop(const SVideoInitialize &video_initialize) _fifo.CPReadPointer = _fifo.CPBase; //LOG(COMMANDPROCESSOR, "BUFFER LOOP"); } +#ifndef THREAD_VIDEO_WAKEUP_ONIDLE count--; +#endif } } } +#if defined(THREAD_VIDEO_WAKEUP_ONIDLE) && defined(_WIN32) + CloseHandle(hEventOnIdle); +#endif }