From 9a4e9da7c25f1aa72f5b47e9914f464e966ad7f9 Mon Sep 17 00:00:00 2001 From: skidau Date: Sun, 3 Feb 2013 18:05:46 +1100 Subject: 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. --- Source/Core/VideoCommon/Src/PixelEngine.cpp | 54 ++++++++++------------------- 1 file changed, 18 insertions(+), 36 deletions(-) (limited to 'Source/Core/VideoCommon/Src/PixelEngine.cpp') 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 -- cgit v1.2.3 From 2c8c8db731fe4d22fac0ec2f2064f6bceea35cd3 Mon Sep 17 00:00:00 2001 From: skidau Date: Sun, 3 Feb 2013 23:52:18 +1100 Subject: Used AtomicStore to write to the signal interrupts. --- Source/Core/VideoCommon/Src/PixelEngine.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'Source/Core/VideoCommon/Src/PixelEngine.cpp') diff --git a/Source/Core/VideoCommon/Src/PixelEngine.cpp b/Source/Core/VideoCommon/Src/PixelEngine.cpp index 6d4659e309..60d69ab1fd 100644 --- a/Source/Core/VideoCommon/Src/PixelEngine.cpp +++ b/Source/Core/VideoCommon/Src/PixelEngine.cpp @@ -110,8 +110,8 @@ static UPEAlphaReadReg m_AlphaRead; static UPECtrlReg m_Control; //static u16 m_Token; // token value most recently encountered -static bool g_bSignalTokenInterrupt; -static bool g_bSignalFinishInterrupt; +volatile bool g_bSignalTokenInterrupt; +volatile bool g_bSignalFinishInterrupt; static int et_SetTokenOnMainThread; static int et_SetFinishOnMainThread; @@ -404,7 +404,7 @@ void SetToken(const u16 _token, const int _bSetTokenAcknowledge) { CommandProcessor::interruptTokenWaiting = true; CoreTiming::ScheduleEvent_Threadsafe(0, et_SetTokenOnMainThread, _token | (_bSetTokenAcknowledge << 16)); - g_bSignalTokenInterrupt = true; + Common::AtomicStore(*(volatile u32*)&g_bSignalTokenInterrupt, 1); } IncrementCheckContextId(); @@ -416,7 +416,7 @@ void SetFinish() { CommandProcessor::interruptFinishWaiting = true; CoreTiming::ScheduleEvent_Threadsafe(0, et_SetFinishOnMainThread, 0); - g_bSignalFinishInterrupt = true; + Common::AtomicStore(*(volatile u32*)&g_bSignalFinishInterrupt, 1); INFO_LOG(PIXELENGINE, "VIDEO Set Finish"); IncrementCheckContextId(); } -- cgit v1.2.3 From 5f672baca319a8227c01c100275d4eaaa860782b Mon Sep 17 00:00:00 2001 From: skidau Date: Sat, 9 Feb 2013 17:46:48 +1100 Subject: Used Atomic functions to update variables shared between the CPU and GPU threads. Changed the variables from bool to u32 to match the atomic functions. --- Source/Core/VideoCommon/Src/PixelEngine.cpp | 31 +++++++++++++++-------------- 1 file changed, 16 insertions(+), 15 deletions(-) (limited to 'Source/Core/VideoCommon/Src/PixelEngine.cpp') diff --git a/Source/Core/VideoCommon/Src/PixelEngine.cpp b/Source/Core/VideoCommon/Src/PixelEngine.cpp index 60d69ab1fd..20601e6c3b 100644 --- a/Source/Core/VideoCommon/Src/PixelEngine.cpp +++ b/Source/Core/VideoCommon/Src/PixelEngine.cpp @@ -32,6 +32,7 @@ #include "HW/ProcessorInterface.h" #include "DLCache.h" #include "State.h" +#include "Thread.h" namespace PixelEngine { @@ -110,14 +111,14 @@ static UPEAlphaReadReg m_AlphaRead; static UPECtrlReg m_Control; //static u16 m_Token; // token value most recently encountered -volatile bool g_bSignalTokenInterrupt; -volatile bool g_bSignalFinishInterrupt; +volatile u32 g_bSignalTokenInterrupt; +volatile u32 g_bSignalFinishInterrupt; static int et_SetTokenOnMainThread; static int et_SetFinishOnMainThread; -volatile bool interruptSetToken = false; -volatile bool interruptSetFinish = false; +volatile u32 interruptSetToken = 0; +volatile u32 interruptSetFinish = 0; u16 bbox[4]; bool bbox_active; @@ -161,10 +162,10 @@ void Init() m_AlphaModeConf.Hex = 0; m_AlphaRead.Hex = 0; - g_bSignalTokenInterrupt = false; - g_bSignalFinishInterrupt = false; - interruptSetToken = false; - interruptSetFinish = false; + g_bSignalTokenInterrupt = 0; + g_bSignalFinishInterrupt = 0; + interruptSetToken = 0; + interruptSetFinish = 0; et_SetTokenOnMainThread = CoreTiming::RegisterEvent("SetToken", SetToken_OnMainThread); et_SetFinishOnMainThread = CoreTiming::RegisterEvent("SetFinish", SetFinish_OnMainThread); @@ -211,7 +212,7 @@ void Read16(u16& _uReturnValue, const u32 _iAddress) break; case PE_TOKEN_REG: - _uReturnValue = CommandProcessor::fifo.PEToken; + _uReturnValue = Common::AtomicLoad(*(volatile u32*)&CommandProcessor::fifo.PEToken); INFO_LOG(PIXELENGINE, "(r16) TOKEN_REG : %04x", _uReturnValue); break; @@ -312,8 +313,8 @@ void Write16(const u16 _iValue, const u32 _iAddress) { UPECtrlReg tmpCtrl(_iValue); - if (tmpCtrl.PEToken) g_bSignalTokenInterrupt = false; - if (tmpCtrl.PEFinish) g_bSignalFinishInterrupt = false; + if (tmpCtrl.PEToken) g_bSignalTokenInterrupt = 0; + if (tmpCtrl.PEFinish) g_bSignalFinishInterrupt = 0; m_Control.PETokenEnable = tmpCtrl.PETokenEnable; m_Control.PEFinishEnable = tmpCtrl.PEFinishEnable; @@ -360,13 +361,13 @@ void UpdateInterrupts() void UpdateTokenInterrupt(bool active) { ProcessorInterface::SetInterrupt(INT_CAUSE_PE_TOKEN, active); - interruptSetToken = active; + Common::AtomicStore(interruptSetToken, active ? 1 : 0); } void UpdateFinishInterrupt(bool active) { ProcessorInterface::SetInterrupt(INT_CAUSE_PE_FINISH, active); - interruptSetFinish = active; + Common::AtomicStore(interruptSetFinish, active ? 1 : 0); } // TODO(mb2): Refactor SetTokenINT_OnMainThread(u64 userdata, int cyclesLate). @@ -443,7 +444,7 @@ void ResetSetToken() if (g_bSignalTokenInterrupt) { UpdateTokenInterrupt(false); - g_bSignalTokenInterrupt = false; + g_bSignalTokenInterrupt = 0; } else { @@ -454,6 +455,6 @@ void ResetSetToken() bool WaitingForPEInterrupt() { - return !CommandProcessor::waitingForPEInterruptDisable && (CommandProcessor::interruptFinishWaiting || CommandProcessor::interruptTokenWaiting || interruptSetFinish || interruptSetToken); + return !CommandProcessor::waitingForPEInterruptDisable && (CommandProcessor::interruptFinishWaiting || CommandProcessor::interruptTokenWaiting || Common::AtomicLoad(interruptSetFinish) || Common::AtomicLoad(interruptSetToken)); } } // end of namespace PixelEngine -- cgit v1.2.3 From 0cafc33edafe235573f847500e81652a5a1b2ad0 Mon Sep 17 00:00:00 2001 From: skidau Date: Sun, 10 Feb 2013 18:24:30 +1100 Subject: Moved the token update to the CPU thread. --- Source/Core/VideoCommon/Src/PixelEngine.cpp | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'Source/Core/VideoCommon/Src/PixelEngine.cpp') diff --git a/Source/Core/VideoCommon/Src/PixelEngine.cpp b/Source/Core/VideoCommon/Src/PixelEngine.cpp index 20601e6c3b..33fedd1a81 100644 --- a/Source/Core/VideoCommon/Src/PixelEngine.cpp +++ b/Source/Core/VideoCommon/Src/PixelEngine.cpp @@ -377,8 +377,13 @@ void UpdateFinishInterrupt(bool active) // Called only if BPMEM_PE_TOKEN_INT_ID is ack by GP void SetToken_OnMainThread(u64 userdata, int cyclesLate) { + // 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, userdata & 0xffff); INFO_LOG(PIXELENGINE, "VIDEO Backend raises INT_CAUSE_PE_TOKEN (btw, token: %04x)", CommandProcessor::fifo.PEToken); - UpdateInterrupts(); + if (userdata >> 16) + UpdateInterrupts(); CommandProcessor::interruptTokenWaiting = false; IncrementCheckContextId(); } @@ -394,20 +399,13 @@ void SetFinish_OnMainThread(u64 userdata, int cyclesLate) // THIS IS EXECUTED FROM VIDEO THREAD void SetToken(const u16 _token, const int _bSetTokenAcknowledge) { - // 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 { - CommandProcessor::interruptTokenWaiting = true; - CoreTiming::ScheduleEvent_Threadsafe(0, et_SetTokenOnMainThread, _token | (_bSetTokenAcknowledge << 16)); Common::AtomicStore(*(volatile u32*)&g_bSignalTokenInterrupt, 1); } + CommandProcessor::interruptTokenWaiting = true; + CoreTiming::ScheduleEvent_Threadsafe(0, et_SetTokenOnMainThread, _token | (_bSetTokenAcknowledge << 16)); IncrementCheckContextId(); } @@ -455,6 +453,6 @@ void ResetSetToken() bool WaitingForPEInterrupt() { - return !CommandProcessor::waitingForPEInterruptDisable && (CommandProcessor::interruptFinishWaiting || CommandProcessor::interruptTokenWaiting || Common::AtomicLoad(interruptSetFinish) || Common::AtomicLoad(interruptSetToken)); + return !CommandProcessor::waitingForPEInterruptDisable && (CommandProcessor::interruptFinishWaiting || CommandProcessor::interruptTokenWaiting || Common::AtomicLoad(interruptSetFinish) || Common::AtomicLoad(interruptSetToken)); } } // end of namespace PixelEngine -- cgit v1.2.3 From 9bff8e00c86188354363e7b41dfe6f06c781cf5a Mon Sep 17 00:00:00 2001 From: skidau Date: Sat, 16 Feb 2013 12:51:09 +1100 Subject: Added preliminary support to synchronise the timing of the CPU and GPU threads. A new option has been added to the game properties for this purpose. This option may help with random freezes in Dual Core mode. Fixes Gladius and Baten Kaitos: Eternal Wings and the Lost Ocean Fixes issue 5150. --- Source/Core/VideoCommon/Src/PixelEngine.cpp | 5 ----- 1 file changed, 5 deletions(-) (limited to 'Source/Core/VideoCommon/Src/PixelEngine.cpp') diff --git a/Source/Core/VideoCommon/Src/PixelEngine.cpp b/Source/Core/VideoCommon/Src/PixelEngine.cpp index 33fedd1a81..24e8a02ab4 100644 --- a/Source/Core/VideoCommon/Src/PixelEngine.cpp +++ b/Source/Core/VideoCommon/Src/PixelEngine.cpp @@ -450,9 +450,4 @@ void ResetSetToken() } CommandProcessor::interruptTokenWaiting = false; } - -bool WaitingForPEInterrupt() -{ - return !CommandProcessor::waitingForPEInterruptDisable && (CommandProcessor::interruptFinishWaiting || CommandProcessor::interruptTokenWaiting || Common::AtomicLoad(interruptSetFinish) || Common::AtomicLoad(interruptSetToken)); -} } // end of namespace PixelEngine -- cgit v1.2.3 From 45efced2809a7201909f85f2ee87d4625939d932 Mon Sep 17 00:00:00 2001 From: skidau Date: Sat, 16 Feb 2013 18:30:20 +1100 Subject: Moved the setting of the Finish interrupt signal back to the main thread as it was causing Wii games like Resident Evil 4 (Wii) to hang. --- Source/Core/VideoCommon/Src/PixelEngine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Source/Core/VideoCommon/Src/PixelEngine.cpp') diff --git a/Source/Core/VideoCommon/Src/PixelEngine.cpp b/Source/Core/VideoCommon/Src/PixelEngine.cpp index 24e8a02ab4..aec160ddd2 100644 --- a/Source/Core/VideoCommon/Src/PixelEngine.cpp +++ b/Source/Core/VideoCommon/Src/PixelEngine.cpp @@ -390,6 +390,7 @@ void SetToken_OnMainThread(u64 userdata, int cyclesLate) void SetFinish_OnMainThread(u64 userdata, int cyclesLate) { + Common::AtomicStore(*(volatile u32*)&g_bSignalFinishInterrupt, 1); UpdateInterrupts(); CommandProcessor::interruptFinishWaiting = false; CommandProcessor::isPossibleWaitingSetDrawDone = false; @@ -415,7 +416,6 @@ void SetFinish() { CommandProcessor::interruptFinishWaiting = true; CoreTiming::ScheduleEvent_Threadsafe(0, et_SetFinishOnMainThread, 0); - Common::AtomicStore(*(volatile u32*)&g_bSignalFinishInterrupt, 1); INFO_LOG(PIXELENGINE, "VIDEO Set Finish"); IncrementCheckContextId(); } -- cgit v1.2.3 From d3e431af9e8e1f73dbcd4b0fd377749efc254f55 Mon Sep 17 00:00:00 2001 From: skidau Date: Thu, 7 Mar 2013 22:16:00 +1100 Subject: Set g_bSignalTokenInterrupt on the main thread. Fixes the random hang in Harry Potter: Prisoner of Azkaban. --- Source/Core/VideoCommon/Src/PixelEngine.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'Source/Core/VideoCommon/Src/PixelEngine.cpp') diff --git a/Source/Core/VideoCommon/Src/PixelEngine.cpp b/Source/Core/VideoCommon/Src/PixelEngine.cpp index aec160ddd2..ce4881252f 100644 --- a/Source/Core/VideoCommon/Src/PixelEngine.cpp +++ b/Source/Core/VideoCommon/Src/PixelEngine.cpp @@ -383,7 +383,10 @@ void SetToken_OnMainThread(u64 userdata, int cyclesLate) Common::AtomicStore(*(volatile u32*)&CommandProcessor::fifo.PEToken, userdata & 0xffff); INFO_LOG(PIXELENGINE, "VIDEO Backend raises INT_CAUSE_PE_TOKEN (btw, token: %04x)", CommandProcessor::fifo.PEToken); if (userdata >> 16) + { + Common::AtomicStore(*(volatile u32*)&g_bSignalTokenInterrupt, 1); UpdateInterrupts(); + } CommandProcessor::interruptTokenWaiting = false; IncrementCheckContextId(); } -- cgit v1.2.3