diff options
| author | skidau <skidau@gmail.com> | 2013-02-16 12:51:09 +1100 |
|---|---|---|
| committer | skidau <skidau@gmail.com> | 2013-02-16 12:51:09 +1100 |
| commit | 9bff8e00c86188354363e7b41dfe6f06c781cf5a (patch) | |
| tree | f6a630eece1dc1fdd7a165c7a79e4a9940b3dcca /Source/Core/VideoCommon/Src/CommandProcessor.cpp | |
| parent | 51795d8811a014a9cb0aaac6938ab83effb8797a (diff) | |
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.
Diffstat (limited to 'Source/Core/VideoCommon/Src/CommandProcessor.cpp')
| -rw-r--r-- | Source/Core/VideoCommon/Src/CommandProcessor.cpp | 93 |
1 files changed, 48 insertions, 45 deletions
diff --git a/Source/Core/VideoCommon/Src/CommandProcessor.cpp b/Source/Core/VideoCommon/Src/CommandProcessor.cpp index 7e976f256e..eb03730fc3 100644 --- a/Source/Core/VideoCommon/Src/CommandProcessor.cpp +++ b/Source/Core/VideoCommon/Src/CommandProcessor.cpp @@ -32,6 +32,8 @@ #include "HW/GPFifo.h" #include "HW/Memmap.h" #include "DLCache.h" +#include "HW/SystemTimers.h" +#include "Core.h" namespace CommandProcessor { @@ -64,6 +66,8 @@ volatile bool interruptTokenWaiting = false; volatile bool interruptFinishWaiting = false; volatile bool waitingForPEInterruptDisable = false; +volatile u32 VITicks = CommandProcessor::m_cpClockOrigin; + bool IsOnThread() { return SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread; @@ -464,7 +468,7 @@ void STACKALIGN GatherPipeBursted() } if (IsOnThread()) - SetWatermarkFromGatherPipe(); + SetCpStatus(); // update the fifo-pointer if (fifo.CPWritePointer >= fifo.CPEnd) @@ -514,27 +518,6 @@ void AbortFrame() } -void SetWatermarkFromGatherPipe() -{ - fifo.bFF_HiWatermark = (fifo.CPReadWriteDistance > fifo.CPHiWatermark); - fifo.bFF_LoWatermark = (fifo.CPReadWriteDistance < fifo.CPLoWatermark); - isHiWatermarkActive = fifo.bFF_HiWatermark && fifo.bFF_HiWatermarkInt && m_CPCtrlReg.GPReadEnable; - isLoWatermarkActive = fifo.bFF_LoWatermark && fifo.bFF_LoWatermarkInt && m_CPCtrlReg.GPReadEnable; - - if (isHiWatermarkActive) - { - interruptSet = true; - INFO_LOG(COMMANDPROCESSOR,"Interrupt set"); - ProcessorInterface::SetInterrupt(INT_CAUSE_CP, true); - } - else if (isLoWatermarkActive) - { - interruptSet = true; - INFO_LOG(COMMANDPROCESSOR,"Interrupt set"); - ProcessorInterface::SetInterrupt(INT_CAUSE_CP, true); - } -} - void SetCpStatus() { // overflow & underflow check @@ -542,30 +525,33 @@ void SetCpStatus() fifo.bFF_LoWatermark = (fifo.CPReadWriteDistance < fifo.CPLoWatermark); // breakpoint - if (fifo.bFF_BPEnable) - { - if (fifo.CPBreakpoint == fifo.CPReadPointer) - { - if (!fifo.bFF_Breakpoint) + if (Core::IsGPUThread()) + { + if (fifo.bFF_BPEnable) + { + if (fifo.CPBreakpoint == fifo.CPReadPointer) { - INFO_LOG(COMMANDPROCESSOR, "Hit breakpoint at %i", fifo.CPReadPointer); - fifo.bFF_Breakpoint = true; - IncrementCheckContextId(); + if (!fifo.bFF_Breakpoint) + { + INFO_LOG(COMMANDPROCESSOR, "Hit breakpoint at %i", fifo.CPReadPointer); + fifo.bFF_Breakpoint = true; + IncrementCheckContextId(); + } } - } + else + { + if (fifo.bFF_Breakpoint) + INFO_LOG(COMMANDPROCESSOR, "Cleared breakpoint at %i", fifo.CPReadPointer); + fifo.bFF_Breakpoint = false; + } + } else { if (fifo.bFF_Breakpoint) INFO_LOG(COMMANDPROCESSOR, "Cleared breakpoint at %i", fifo.CPReadPointer); - fifo.bFF_Breakpoint = false; + fifo.bFF_Breakpoint = false; } - } - else - { - if (fifo.bFF_Breakpoint) - INFO_LOG(COMMANDPROCESSOR, "Cleared breakpoint at %i", fifo.CPReadPointer); - fifo.bFF_Breakpoint = false; - } + } bool bpInt = fifo.bFF_Breakpoint && fifo.bFF_BPInt; bool ovfInt = fifo.bFF_HiWatermark && fifo.bFF_HiWatermarkInt; @@ -581,10 +567,19 @@ void SetCpStatus() u64 userdata = interrupt?1:0; if (IsOnThread()) { - if(!interrupt || bpInt || undfInt) + if(!interrupt || bpInt || undfInt || ovfInt) { - interruptWaiting = true; - CommandProcessor::UpdateInterruptsFromVideoBackend(userdata); + if (Core::IsGPUThread()) + { + interruptWaiting = true; + CommandProcessor::UpdateInterruptsFromVideoBackend(userdata); + } + else if (Core::IsCPUThread()) + { + interruptSet = interrupt; + INFO_LOG(COMMANDPROCESSOR,"Interrupt set"); + ProcessorInterface::SetInterrupt(INT_CAUSE_CP, interrupt); + } } } else @@ -608,7 +603,7 @@ void ProcessFifoAllDistance() if (IsOnThread()) { while (!CommandProcessor::interruptWaiting && fifo.bFF_GPReadEnable && - fifo.CPReadWriteDistance && !AtBreakpoint() && !PixelEngine::WaitingForPEInterrupt()) + fifo.CPReadWriteDistance && !AtBreakpoint()) Common::YieldCPU(); } bProcessFifoAllDistance = false; @@ -629,8 +624,8 @@ void SetCpStatusRegister() { // Here always there is one fifo attached to the GPU m_CPStatusReg.Breakpoint = fifo.bFF_Breakpoint; - m_CPStatusReg.ReadIdle = !fifo.CPReadWriteDistance || (fifo.CPReadPointer == fifo.CPWritePointer) || (fifo.CPReadPointer == fifo.CPBreakpoint) ; - m_CPStatusReg.CommandIdle = !fifo.isGpuReadingData; + m_CPStatusReg.ReadIdle = !fifo.CPReadWriteDistance || AtBreakpoint() || (fifo.CPReadPointer == fifo.CPWritePointer); + m_CPStatusReg.CommandIdle = !fifo.CPReadWriteDistance || AtBreakpoint() || !fifo.bFF_GPReadEnable; m_CPStatusReg.UnderflowLoWatermark = fifo.bFF_LoWatermark; m_CPStatusReg.OverflowHiWatermark = fifo.bFF_HiWatermark; @@ -701,4 +696,12 @@ void SetCpClearRegister() // } } +void Update() +{ + while (VITicks > m_cpClockOrigin && fifo.isGpuReadingData && IsOnThread()) + Common::YieldCPU(); + + if (fifo.isGpuReadingData) + Common::AtomicAdd(VITicks, SystemTimers::GetTicksPerSecond() / 10000); +} } // end of namespace CommandProcessor |
