summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon/Src/CommandProcessor.cpp
diff options
context:
space:
mode:
authorskidau <skidau@gmail.com>2013-02-16 12:51:09 +1100
committerskidau <skidau@gmail.com>2013-02-16 12:51:09 +1100
commit9bff8e00c86188354363e7b41dfe6f06c781cf5a (patch)
treef6a630eece1dc1fdd7a165c7a79e4a9940b3dcca /Source/Core/VideoCommon/Src/CommandProcessor.cpp
parent51795d8811a014a9cb0aaac6938ab83effb8797a (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.cpp93
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