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.
This commit is contained in:
parent
867bfaa696
commit
9a4e9da7c2
|
@ -464,7 +464,7 @@ void STACKALIGN GatherPipeBursted()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsOnThread())
|
if (IsOnThread())
|
||||||
SetOverflowStatusFromGatherPipe();
|
SetWatermarkFromGatherPipe();
|
||||||
|
|
||||||
// update the fifo-pointer
|
// update the fifo-pointer
|
||||||
if (fifo.CPWritePointer >= fifo.CPEnd)
|
if (fifo.CPWritePointer >= fifo.CPEnd)
|
||||||
|
@ -514,7 +514,7 @@ void AbortFrame()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetOverflowStatusFromGatherPipe()
|
void SetWatermarkFromGatherPipe()
|
||||||
{
|
{
|
||||||
fifo.bFF_HiWatermark = (fifo.CPReadWriteDistance > fifo.CPHiWatermark);
|
fifo.bFF_HiWatermark = (fifo.CPReadWriteDistance > fifo.CPHiWatermark);
|
||||||
fifo.bFF_LoWatermark = (fifo.CPReadWriteDistance < fifo.CPLoWatermark);
|
fifo.bFF_LoWatermark = (fifo.CPReadWriteDistance < fifo.CPLoWatermark);
|
||||||
|
@ -634,10 +634,6 @@ void SetCpStatusRegister()
|
||||||
m_CPStatusReg.UnderflowLoWatermark = fifo.bFF_LoWatermark;
|
m_CPStatusReg.UnderflowLoWatermark = fifo.bFF_LoWatermark;
|
||||||
m_CPStatusReg.OverflowHiWatermark = fifo.bFF_HiWatermark;
|
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);
|
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"
|
DEBUG_LOG(COMMANDPROCESSOR, "(r) status: iBP %s | fReadIdle %s | fCmdIdle %s | iOvF %s | iUndF %s"
|
||||||
, m_CPStatusReg.Breakpoint ? "ON" : "OFF"
|
, m_CPStatusReg.Breakpoint ? "ON" : "OFF"
|
||||||
|
|
|
@ -162,7 +162,7 @@ bool AllowIdleSkipping();
|
||||||
void SetCpClearRegister();
|
void SetCpClearRegister();
|
||||||
void SetCpControlRegister();
|
void SetCpControlRegister();
|
||||||
void SetCpStatusRegister();
|
void SetCpStatusRegister();
|
||||||
void SetOverflowStatusFromGatherPipe();
|
void SetWatermarkFromGatherPipe();
|
||||||
void ProcessFifoToLoWatermark();
|
void ProcessFifoToLoWatermark();
|
||||||
void ProcessFifoAllDistance();
|
void ProcessFifoAllDistance();
|
||||||
void ProcessFifoEvents();
|
void ProcessFifoEvents();
|
||||||
|
|
|
@ -157,7 +157,7 @@ void RunGpuLoop()
|
||||||
CommandProcessor::SetCpStatus();
|
CommandProcessor::SetCpStatus();
|
||||||
|
|
||||||
// check if we are able to run this buffer
|
// 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;
|
if (!GpuRunningState) break;
|
||||||
|
|
||||||
|
|
|
@ -376,20 +376,14 @@ void UpdateFinishInterrupt(bool active)
|
||||||
// Called only if BPMEM_PE_TOKEN_INT_ID is ack by GP
|
// Called only if BPMEM_PE_TOKEN_INT_ID is ack by GP
|
||||||
void SetToken_OnMainThread(u64 userdata, int cyclesLate)
|
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);
|
INFO_LOG(PIXELENGINE, "VIDEO Backend raises INT_CAUSE_PE_TOKEN (btw, token: %04x)", CommandProcessor::fifo.PEToken);
|
||||||
UpdateInterrupts();
|
UpdateInterrupts();
|
||||||
CommandProcessor::interruptTokenWaiting = false;
|
CommandProcessor::interruptTokenWaiting = false;
|
||||||
IncrementCheckContextId();
|
IncrementCheckContextId();
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetFinish_OnMainThread(u64 userdata, int cyclesLate)
|
void SetFinish_OnMainThread(u64 userdata, int cyclesLate)
|
||||||
{
|
{
|
||||||
g_bSignalFinishInterrupt = 1;
|
|
||||||
UpdateInterrupts();
|
UpdateInterrupts();
|
||||||
CommandProcessor::interruptFinishWaiting = false;
|
CommandProcessor::interruptFinishWaiting = false;
|
||||||
CommandProcessor::isPossibleWaitingSetDrawDone = false;
|
CommandProcessor::isPossibleWaitingSetDrawDone = false;
|
||||||
|
@ -398,16 +392,6 @@ void SetFinish_OnMainThread(u64 userdata, int cyclesLate)
|
||||||
// SetToken
|
// SetToken
|
||||||
// THIS IS EXECUTED FROM VIDEO THREAD
|
// THIS IS EXECUTED FROM VIDEO THREAD
|
||||||
void SetToken(const u16 _token, const int _bSetTokenAcknowledge)
|
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.
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
else // set token value
|
|
||||||
{
|
{
|
||||||
// we do it directly from videoThread because of
|
// we do it directly from videoThread because of
|
||||||
// Super Monkey Ball
|
// Super Monkey Ball
|
||||||
|
@ -415,7 +399,14 @@ void SetToken(const u16 _token, const int _bSetTokenAcknowledge)
|
||||||
// That's what we've always done. We're counting on fifo.PEToken to be
|
// That's what we've always done. We're counting on fifo.PEToken to be
|
||||||
// 4-byte padded.
|
// 4-byte padded.
|
||||||
Common::AtomicStore(*(volatile u32*)&CommandProcessor::fifo.PEToken, _token);
|
Common::AtomicStore(*(volatile u32*)&CommandProcessor::fifo.PEToken, _token);
|
||||||
|
|
||||||
|
if (_bSetTokenAcknowledge) // set token INT
|
||||||
|
{
|
||||||
|
CommandProcessor::interruptTokenWaiting = true;
|
||||||
|
CoreTiming::ScheduleEvent_Threadsafe(0, et_SetTokenOnMainThread, _token | (_bSetTokenAcknowledge << 16));
|
||||||
|
g_bSignalTokenInterrupt = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
IncrementCheckContextId();
|
IncrementCheckContextId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -425,6 +416,7 @@ void SetFinish()
|
||||||
{
|
{
|
||||||
CommandProcessor::interruptFinishWaiting = true;
|
CommandProcessor::interruptFinishWaiting = true;
|
||||||
CoreTiming::ScheduleEvent_Threadsafe(0, et_SetFinishOnMainThread, 0);
|
CoreTiming::ScheduleEvent_Threadsafe(0, et_SetFinishOnMainThread, 0);
|
||||||
|
g_bSignalFinishInterrupt = true;
|
||||||
INFO_LOG(PIXELENGINE, "VIDEO Set Finish");
|
INFO_LOG(PIXELENGINE, "VIDEO Set Finish");
|
||||||
IncrementCheckContextId();
|
IncrementCheckContextId();
|
||||||
}
|
}
|
||||||
|
@ -438,7 +430,6 @@ void ResetSetFinish()
|
||||||
{
|
{
|
||||||
UpdateFinishInterrupt(false);
|
UpdateFinishInterrupt(false);
|
||||||
g_bSignalFinishInterrupt = false;
|
g_bSignalFinishInterrupt = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -453,7 +444,6 @@ void ResetSetToken()
|
||||||
{
|
{
|
||||||
UpdateTokenInterrupt(false);
|
UpdateTokenInterrupt(false);
|
||||||
g_bSignalTokenInterrupt = false;
|
g_bSignalTokenInterrupt = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -466,12 +456,4 @@ bool WaitingForPEInterrupt()
|
||||||
{
|
{
|
||||||
return !CommandProcessor::waitingForPEInterruptDisable && (CommandProcessor::interruptFinishWaiting || CommandProcessor::interruptTokenWaiting || interruptSetFinish || interruptSetToken);
|
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
|
} // end of namespace PixelEngine
|
||||||
|
|
|
@ -81,7 +81,6 @@ void SetFinish(void);
|
||||||
void ResetSetFinish(void);
|
void ResetSetFinish(void);
|
||||||
void ResetSetToken(void);
|
void ResetSetToken(void);
|
||||||
bool WaitingForPEInterrupt();
|
bool WaitingForPEInterrupt();
|
||||||
void ResumeWaitingForPEInterrupt();
|
|
||||||
|
|
||||||
// Bounding box functionality. Paper Mario (both) are a couple of the few games that use it.
|
// Bounding box functionality. Paper Mario (both) are a couple of the few games that use it.
|
||||||
extern u16 bbox[4];
|
extern u16 bbox[4];
|
||||||
|
|
Loading…
Reference in New Issue