From 5fd99516499f186c697f0cf2b7a043e215d18b76 Mon Sep 17 00:00:00 2001 From: Marcos Vitali Date: Mon, 13 Dec 2010 07:56:54 +0000 Subject: [PATCH] - I've implemented cache of interrupt states for PEFINISH and PETOKEN - I've implemented calling to ProcessFifoEvents when is there is a pending event in the main queue from CP, PE & GP - I've implemented FifoIntReset(TRUE, TRUE) in write Clear Register. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6572 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/Core/Src/Core.cpp | 1 + .../Core/VideoCommon/Src/CommandProcessor.cpp | 25 +++++++-- .../Core/VideoCommon/Src/CommandProcessor.h | 3 ++ Source/Core/VideoCommon/Src/PixelEngine.cpp | 54 ++++++++++++++----- Source/PluginSpecs/pluginspecs_video.h | 3 ++ 5 files changed, 68 insertions(+), 18 deletions(-) diff --git a/Source/Core/Core/Src/Core.cpp b/Source/Core/Core/Src/Core.cpp index bfd0e5ca76..0370396ce6 100644 --- a/Source/Core/Core/Src/Core.cpp +++ b/Source/Core/Core/Src/Core.cpp @@ -330,6 +330,7 @@ THREAD_RETURN EmuThread(void *pArg) VideoInitialize.pRegisterEvent = CoreTiming::RegisterEvent; VideoInitialize.pScheduleEvent_Threadsafe = CoreTiming::ScheduleEvent_Threadsafe; VideoInitialize.pRemoveEvent = CoreTiming::RemoveAllEvents; + VideoInitialize.pProcessFifoEvents = CoreTiming::ProcessFifoWaitEvents; // This is first the m_Panel handle, then it is updated to have the new window handle VideoInitialize.pWindowHandle = _CoreParameter.hMainWindow; VideoInitialize.pLog = Callback_VideoLog; diff --git a/Source/Core/VideoCommon/Src/CommandProcessor.cpp b/Source/Core/VideoCommon/Src/CommandProcessor.cpp index 71c408be1c..e6a0589ba5 100644 --- a/Source/Core/VideoCommon/Src/CommandProcessor.cpp +++ b/Source/Core/VideoCommon/Src/CommandProcessor.cpp @@ -111,11 +111,13 @@ static u32 fake_GPWatchdogLastToken = 0; static Common::EventEx s_fifoIdleEvent; static Common::CriticalSection sFifoCritical; static bool bProcessFifoToLoWatemark = false; +static bool bProcessFifoAllDistance = false; volatile bool isFifoBusy = false; //This state is changed when the FIFO is processing data. volatile bool interruptSet= false; volatile bool interruptWaiting= false; - +volatile bool interruptTokenWaiting = false; +volatile bool interruptFinishWaiting = false; void FifoCriticalEnter() { @@ -177,6 +179,8 @@ void Init() interruptSet = false; interruptWaiting = false; + interruptFinishWaiting = false; + interruptTokenWaiting = false; s_fifoIdleEvent.Init(); @@ -192,6 +196,7 @@ void Read16(u16& _rReturnValue, const u32 _Address) { INFO_LOG(COMMANDPROCESSOR, "(r): 0x%08x", _Address); + ProcessFifoEvents(); switch (_Address & 0xFFF) { case STATUS_REGISTER: @@ -458,6 +463,9 @@ void Write16(const u16 _Value, const u32 _Address) // If overflown happens process the fifo to LoWatemark if (bProcessFifoToLoWatemark) ProcessFifoToLoWatemark(); + + if (bProcessFifoAllDistance) + ProcessFifoAllDistance(); INFO_LOG(COMMANDPROCESSOR,"\t Write to CTRL_REGISTER : %04x", _Value); DEBUG_LOG(COMMANDPROCESSOR, "\t GPREAD %s | BP %s | Int %s | OvF %s | UndF %s | LINK %s" @@ -479,6 +487,9 @@ void Write16(const u16 _Value, const u32 _Address) { if (!tmpCtrl.ClearFifoUnderflow && tmpCtrl.ClearFifoOverflow) bProcessFifoToLoWatemark = true; + + if (tmpCtrl.ClearFifoUnderflow && tmpCtrl.ClearFifoOverflow) + bProcessFifoAllDistance = true; } else { @@ -590,8 +601,7 @@ void Write16(const u16 _Value, const u32 _Address) if (!g_VideoInitialize.bOnThread) CatchUpGPU(); - - + ProcessFifoEvents(); } void Read32(u32& _rReturnValue, const u32 _Address) @@ -626,7 +636,7 @@ void WaitForFrameFinish() void STACKALIGN GatherPipeBursted() { - + ProcessFifoEvents(); // if we aren't linked, we don't care about gather pipe data if (!m_CPCtrlReg.GPLinkEnable) { @@ -862,6 +872,13 @@ void ProcessFifoAllDistance() fifo.CPReadWriteDistance && !AtBreakpoint()) Common::YieldCPU(); } + bProcessFifoAllDistance = false; +} + +void ProcessFifoEvents() +{ + if (g_VideoInitialize.bOnThread || interruptWaiting || interruptFinishWaiting || interruptTokenWaiting) + g_VideoInitialize.pProcessFifoEvents(); } diff --git a/Source/Core/VideoCommon/Src/CommandProcessor.h b/Source/Core/VideoCommon/Src/CommandProcessor.h index 68e0f32080..9d98c802d2 100644 --- a/Source/Core/VideoCommon/Src/CommandProcessor.h +++ b/Source/Core/VideoCommon/Src/CommandProcessor.h @@ -33,6 +33,8 @@ extern SCPFifoStruct fifo; //This one is shared between gfx thread and emulator extern volatile bool isFifoBusy; //This one is used for sync gfx thread and emulator thread. extern volatile bool interruptSet; extern volatile bool interruptWaiting; +extern volatile bool interruptTokenWaiting; +extern volatile bool interruptFinishWaiting; // internal hardware addresses enum @@ -170,6 +172,7 @@ void FifoCriticalLeave(); void SetOverflowStatusFromGatherPipe(); void ProcessFifoToLoWatemark(); void ProcessFifoAllDistance(); +void ProcessFifoEvents(); void AbortFrame(); } // namespace CommandProcessor diff --git a/Source/Core/VideoCommon/Src/PixelEngine.cpp b/Source/Core/VideoCommon/Src/PixelEngine.cpp index 4913e21cfc..cea6b46774 100644 --- a/Source/Core/VideoCommon/Src/PixelEngine.cpp +++ b/Source/Core/VideoCommon/Src/PixelEngine.cpp @@ -112,6 +112,9 @@ static bool g_bSignalFinishInterrupt; static int et_SetTokenOnMainThread; static int et_SetFinishOnMainThread; +volatile bool interruptSetToken = false; +volatile bool interruptSetFinish = false; + u16 bbox[4]; bool bbox_active; @@ -139,7 +142,8 @@ void DoState(PointerWrap &p) } void UpdateInterrupts(); - +void UpdateTokenInterrupt(bool active); +void UpdateFinishInterrupt(bool active); void SetToken_OnMainThread(u64 userdata, int cyclesLate); void SetFinish_OnMainThread(u64 userdata, int cyclesLate); @@ -161,7 +165,7 @@ void Init() void Read16(u16& _uReturnValue, const u32 _iAddress) { DEBUG_LOG(PIXELENGINE, "(r16) 0x%08x", _iAddress); - + CommandProcessor::ProcessFifoEvents(); switch (_iAddress & 0xFFF) { // CPU Direct Access EFB Raster State Config @@ -226,6 +230,7 @@ void Read16(u16& _uReturnValue, const u32 _iAddress) _uReturnValue = 1; break; } + } void Write16(const u16 _iValue, const u32 _iAddress) @@ -282,6 +287,8 @@ void Write16(const u16 _iValue, const u32 _iAddress) WARN_LOG(PIXELENGINE, "(w16) unknown %04x @ %08x", _iValue, _iAddress); break; } + + CommandProcessor::ProcessFifoEvents(); } void Write32(const u32 _iValue, const u32 _iAddress) @@ -291,22 +298,35 @@ void Write32(const u32 _iValue, const u32 _iAddress) bool AllowIdleSkipping() { - return !g_VideoInitialize.bOnThread|| (!m_Control.PETokenEnable && !m_Control.PEFinishEnable); + return !g_VideoInitialize.bOnThread || (!m_Control.PETokenEnable && !m_Control.PEFinishEnable); } void UpdateInterrupts() { // check if there is a token-interrupt - if (g_bSignalTokenInterrupt & m_Control.PETokenEnable) - g_VideoInitialize.pSetInterrupt(INT_CAUSE_PE_TOKEN, true); - else - g_VideoInitialize.pSetInterrupt(INT_CAUSE_PE_TOKEN, false); - + UpdateTokenInterrupt((g_bSignalTokenInterrupt & m_Control.PETokenEnable)); + // check if there is a finish-interrupt - if (g_bSignalFinishInterrupt & m_Control.PEFinishEnable) - g_VideoInitialize.pSetInterrupt(INT_CAUSE_PE_FINISH, true); - else - g_VideoInitialize.pSetInterrupt(INT_CAUSE_PE_FINISH, false); + UpdateFinishInterrupt((g_bSignalFinishInterrupt & m_Control.PEFinishEnable)); +} + +void UpdateTokenInterrupt(bool active) +{ + if(interruptSetToken != active) + { + g_VideoInitialize.pSetInterrupt(INT_CAUSE_PE_TOKEN, active); + interruptSetToken = active; + } +} + +void UpdateFinishInterrupt(bool active) +{ + + if(interruptSetFinish != active) + { + g_VideoInitialize.pSetInterrupt(INT_CAUSE_PE_FINISH, active); + interruptSetFinish = active; + } } // TODO(mb2): Refactor SetTokenINT_OnMainThread(u64 userdata, int cyclesLate). @@ -322,6 +342,7 @@ void SetToken_OnMainThread(u64 userdata, int cyclesLate) //_dbg_assert_msg_(PIXELENGINE, (CommandProcessor::fifo.PEToken == (userdata&0xFFFF)), "WTF? BPMEM_PE_TOKEN_INT_ID's token != BPMEM_PE_TOKEN_ID's token" ); INFO_LOG(PIXELENGINE, "VIDEO Plugin raises INT_CAUSE_PE_TOKEN (btw, token: %04x)", CommandProcessor::fifo.PEToken); UpdateInterrupts(); + CommandProcessor::interruptTokenWaiting = false; //} //else // LOGV(PIXELENGINE, 1, "VIDEO Plugin wrote token: %i", CommandProcessor::fifo.PEToken); @@ -331,6 +352,7 @@ void SetFinish_OnMainThread(u64 userdata, int cyclesLate) { g_bSignalFinishInterrupt = 1; UpdateInterrupts(); + CommandProcessor::interruptFinishWaiting = false; } // SetToken @@ -342,6 +364,7 @@ void SetToken(const u16 _token, const int _bSetTokenAcknowledge) { // This seems smelly... CommandProcessor::IncrementGPWDToken(); // for DC watchdog hack since PEToken seems to be a frame-finish too + CommandProcessor::interruptTokenWaiting = true; g_VideoInitialize.pScheduleEvent_Threadsafe( 0, et_SetTokenOnMainThread, _token | (_bSetTokenAcknowledge << 16)); } @@ -361,6 +384,7 @@ void SetToken(const u16 _token, const int _bSetTokenAcknowledge) void SetFinish() { CommandProcessor::IncrementGPWDToken(); // for DC watchdog hack + CommandProcessor::interruptFinishWaiting = true; g_VideoInitialize.pScheduleEvent_Threadsafe( 0, et_SetFinishOnMainThread, 0); INFO_LOG(PIXELENGINE, "VIDEO Set Finish"); @@ -373,25 +397,27 @@ void ResetSetFinish() //remove event from the queque if (g_bSignalFinishInterrupt) { - g_VideoInitialize.pSetInterrupt(INT_CAUSE_PE_FINISH, false); + UpdateFinishInterrupt(false); g_bSignalFinishInterrupt = false; }else { g_VideoInitialize.pRemoveEvent(et_SetFinishOnMainThread); } + CommandProcessor::interruptFinishWaiting = false; } void ResetSetToken() { if (g_bSignalTokenInterrupt) { - g_VideoInitialize.pSetInterrupt(INT_CAUSE_PE_TOKEN, false); + UpdateTokenInterrupt(false); g_bSignalTokenInterrupt = false; }else { g_VideoInitialize.pRemoveEvent(et_SetTokenOnMainThread); } + CommandProcessor::interruptTokenWaiting = false; } } // end of namespace PixelEngine diff --git a/Source/PluginSpecs/pluginspecs_video.h b/Source/PluginSpecs/pluginspecs_video.h index eab8a68100..835a6e9381 100644 --- a/Source/PluginSpecs/pluginspecs_video.h +++ b/Source/PluginSpecs/pluginspecs_video.h @@ -15,6 +15,7 @@ typedef void (*TSetInterrupt)(u32 _causemask, bool _bSet); typedef int (*TRegisterEvent)(const char *name, TimedCallback callback); typedef void (*TScheduleEvent_Threadsafe)(int cyclesIntoFuture, int event_type, u64 userdata); typedef void (*TRemoveEvent)(int event_type); +typedef void (*TProcessFifoEvents)(void); typedef unsigned char* (*TGetMemoryPointer)(const unsigned int _iAddress); typedef void (*TVideoLog)(const char* _pMessage, int _bBreak); typedef void (*TSysMessage)(const char *fmt, ...); @@ -82,6 +83,7 @@ typedef struct TRegisterEvent pRegisterEvent; TScheduleEvent_Threadsafe pScheduleEvent_Threadsafe; TRemoveEvent pRemoveEvent; + TProcessFifoEvents pProcessFifoEvents; TGetMemoryPointer pGetMemoryPointer; TVideoLog pLog; TSysMessage pSysMessage; @@ -197,5 +199,6 @@ EXPORT bool CALL Video_IsFifoBusy(void); EXPORT void CALL Video_AbortFrame(void); + #include "ExportEpilog.h" #endif