From 9a4e9da7c25f1aa72f5b47e9914f464e966ad7f9 Mon Sep 17 00:00:00 2001 From: skidau Date: Sun, 3 Feb 2013 18:05:46 +1100 Subject: [PATCH] Set the token and finish interrupt signal from the video thread. This fixes the inconsistent state caused by lag from the scheduler. Fixes Rayman 3: Hoodlum Havoc and Shamu's Deep Sea Adventures. Fixes issue 5401. Fixes issue 5589. --- .../Core/VideoCommon/Src/CommandProcessor.cpp | 8 +-- .../Core/VideoCommon/Src/CommandProcessor.h | 2 +- Source/Core/VideoCommon/Src/Fifo.cpp | 2 +- Source/Core/VideoCommon/Src/PixelEngine.cpp | 54 +++++++------------ Source/Core/VideoCommon/Src/PixelEngine.h | 1 - 5 files changed, 22 insertions(+), 45 deletions(-) diff --git a/Source/Core/VideoCommon/Src/CommandProcessor.cpp b/Source/Core/VideoCommon/Src/CommandProcessor.cpp index 12b11d7ea5..7e976f256e 100644 --- a/Source/Core/VideoCommon/Src/CommandProcessor.cpp +++ b/Source/Core/VideoCommon/Src/CommandProcessor.cpp @@ -464,7 +464,7 @@ void STACKALIGN GatherPipeBursted() } if (IsOnThread()) - SetOverflowStatusFromGatherPipe(); + SetWatermarkFromGatherPipe(); // update the fifo-pointer if (fifo.CPWritePointer >= fifo.CPEnd) @@ -514,7 +514,7 @@ void AbortFrame() } -void SetOverflowStatusFromGatherPipe() +void SetWatermarkFromGatherPipe() { fifo.bFF_HiWatermark = (fifo.CPReadWriteDistance > fifo.CPHiWatermark); fifo.bFF_LoWatermark = (fifo.CPReadWriteDistance < fifo.CPLoWatermark); @@ -634,10 +634,6 @@ void SetCpStatusRegister() m_CPStatusReg.UnderflowLoWatermark = fifo.bFF_LoWatermark; m_CPStatusReg.OverflowHiWatermark = fifo.bFF_HiWatermark; - // HACK to compensate for slow response to PE interrupts in Time Splitters: Future Perfect - if (IsOnThread()) - PixelEngine::ResumeWaitingForPEInterrupt(); - INFO_LOG(COMMANDPROCESSOR,"\t Read from STATUS_REGISTER : %04x", m_CPStatusReg.Hex); DEBUG_LOG(COMMANDPROCESSOR, "(r) status: iBP %s | fReadIdle %s | fCmdIdle %s | iOvF %s | iUndF %s" , m_CPStatusReg.Breakpoint ? "ON" : "OFF" diff --git a/Source/Core/VideoCommon/Src/CommandProcessor.h b/Source/Core/VideoCommon/Src/CommandProcessor.h index d70bcf475c..84b8fa7d66 100644 --- a/Source/Core/VideoCommon/Src/CommandProcessor.h +++ b/Source/Core/VideoCommon/Src/CommandProcessor.h @@ -162,7 +162,7 @@ bool AllowIdleSkipping(); void SetCpClearRegister(); void SetCpControlRegister(); void SetCpStatusRegister(); -void SetOverflowStatusFromGatherPipe(); +void SetWatermarkFromGatherPipe(); void ProcessFifoToLoWatermark(); void ProcessFifoAllDistance(); void ProcessFifoEvents(); diff --git a/Source/Core/VideoCommon/Src/Fifo.cpp b/Source/Core/VideoCommon/Src/Fifo.cpp index e21cc94da2..d4b4db3e42 100644 --- a/Source/Core/VideoCommon/Src/Fifo.cpp +++ b/Source/Core/VideoCommon/Src/Fifo.cpp @@ -157,7 +157,7 @@ void RunGpuLoop() CommandProcessor::SetCpStatus(); // check if we are able to run this buffer - while (GpuRunningState && !CommandProcessor::interruptWaiting && fifo.bFF_GPReadEnable && fifo.CPReadWriteDistance && !AtBreakpoint() && !PixelEngine::WaitingForPEInterrupt()) + while (GpuRunningState && !CommandProcessor::interruptWaiting && fifo.bFF_GPReadEnable && fifo.CPReadWriteDistance && !AtBreakpoint()) { if (!GpuRunningState) break; diff --git a/Source/Core/VideoCommon/Src/PixelEngine.cpp b/Source/Core/VideoCommon/Src/PixelEngine.cpp index a488e52b42..6d4659e309 100644 --- a/Source/Core/VideoCommon/Src/PixelEngine.cpp +++ b/Source/Core/VideoCommon/Src/PixelEngine.cpp @@ -359,14 +359,14 @@ void UpdateInterrupts() void UpdateTokenInterrupt(bool active) { - ProcessorInterface::SetInterrupt(INT_CAUSE_PE_TOKEN, active); - interruptSetToken = active; + ProcessorInterface::SetInterrupt(INT_CAUSE_PE_TOKEN, active); + interruptSetToken = active; } void UpdateFinishInterrupt(bool active) { - ProcessorInterface::SetInterrupt(INT_CAUSE_PE_FINISH, active); - interruptSetFinish = active; + ProcessorInterface::SetInterrupt(INT_CAUSE_PE_FINISH, active); + interruptSetFinish = active; } // TODO(mb2): Refactor SetTokenINT_OnMainThread(u64 userdata, int cyclesLate). @@ -376,20 +376,14 @@ void UpdateFinishInterrupt(bool active) // Called only if BPMEM_PE_TOKEN_INT_ID is ack by GP void SetToken_OnMainThread(u64 userdata, int cyclesLate) { - //if (userdata >> 16) - //{ - g_bSignalTokenInterrupt = true; - //_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 Backend raises INT_CAUSE_PE_TOKEN (btw, token: %04x)", CommandProcessor::fifo.PEToken); - UpdateInterrupts(); - CommandProcessor::interruptTokenWaiting = false; - IncrementCheckContextId(); - //} + INFO_LOG(PIXELENGINE, "VIDEO Backend raises INT_CAUSE_PE_TOKEN (btw, token: %04x)", CommandProcessor::fifo.PEToken); + UpdateInterrupts(); + CommandProcessor::interruptTokenWaiting = false; + IncrementCheckContextId(); } void SetFinish_OnMainThread(u64 userdata, int cyclesLate) { - g_bSignalFinishInterrupt = 1; UpdateInterrupts(); CommandProcessor::interruptFinishWaiting = false; CommandProcessor::isPossibleWaitingSetDrawDone = false; @@ -399,23 +393,20 @@ void SetFinish_OnMainThread(u64 userdata, int cyclesLate) // THIS IS EXECUTED FROM VIDEO THREAD void SetToken(const u16 _token, const int _bSetTokenAcknowledge) { - // TODO?: set-token-value and set-token-INT could be merged since set-token-INT own the token value. + // we do it directly from videoThread because of + // Super Monkey Ball + // XXX: No 16-bit atomic store available, so cheat and use 32-bit. + // That's what we've always done. We're counting on fifo.PEToken to be + // 4-byte padded. + Common::AtomicStore(*(volatile u32*)&CommandProcessor::fifo.PEToken, _token); + if (_bSetTokenAcknowledge) // set token INT { - - Common::AtomicStore(*(volatile u32*)&CommandProcessor::fifo.PEToken, _token); CommandProcessor::interruptTokenWaiting = true; CoreTiming::ScheduleEvent_Threadsafe(0, et_SetTokenOnMainThread, _token | (_bSetTokenAcknowledge << 16)); + g_bSignalTokenInterrupt = true; } - else // set token value - { - // we do it directly from videoThread because of - // Super Monkey Ball - // XXX: No 16-bit atomic store available, so cheat and use 32-bit. - // That's what we've always done. We're counting on fifo.PEToken to be - // 4-byte padded. - Common::AtomicStore(*(volatile u32*)&CommandProcessor::fifo.PEToken, _token); - } + IncrementCheckContextId(); } @@ -425,6 +416,7 @@ void SetFinish() { CommandProcessor::interruptFinishWaiting = true; CoreTiming::ScheduleEvent_Threadsafe(0, et_SetFinishOnMainThread, 0); + g_bSignalFinishInterrupt = true; INFO_LOG(PIXELENGINE, "VIDEO Set Finish"); IncrementCheckContextId(); } @@ -438,7 +430,6 @@ void ResetSetFinish() { UpdateFinishInterrupt(false); g_bSignalFinishInterrupt = false; - } else { @@ -453,7 +444,6 @@ void ResetSetToken() { UpdateTokenInterrupt(false); g_bSignalTokenInterrupt = false; - } else { @@ -466,12 +456,4 @@ bool WaitingForPEInterrupt() { return !CommandProcessor::waitingForPEInterruptDisable && (CommandProcessor::interruptFinishWaiting || CommandProcessor::interruptTokenWaiting || interruptSetFinish || interruptSetToken); } - -void ResumeWaitingForPEInterrupt() -{ - interruptSetFinish = false; - interruptSetToken = false; - CommandProcessor::interruptFinishWaiting = false; - CommandProcessor::interruptTokenWaiting = false; -} } // end of namespace PixelEngine diff --git a/Source/Core/VideoCommon/Src/PixelEngine.h b/Source/Core/VideoCommon/Src/PixelEngine.h index 64f959009f..5e64300ef3 100644 --- a/Source/Core/VideoCommon/Src/PixelEngine.h +++ b/Source/Core/VideoCommon/Src/PixelEngine.h @@ -81,7 +81,6 @@ void SetFinish(void); void ResetSetFinish(void); void ResetSetToken(void); bool WaitingForPEInterrupt(); -void ResumeWaitingForPEInterrupt(); // Bounding box functionality. Paper Mario (both) are a couple of the few games that use it. extern u16 bbox[4];