summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon
diff options
context:
space:
mode:
authordegasus <wickmarkus@web.de>2013-03-12 11:28:56 +0100
committerdegasus <wickmarkus@web.de>2013-03-12 11:28:56 +0100
commit382be2aabdf0635c67f9ec945283f77f8ed9b0c9 (patch)
tree8df3cf8a3539e4b4b1a96772f17c353f99393ed5 /Source/Core/VideoCommon
parente1ca002937cf8915ab9fb04f82e2dc5e68db1fa2 (diff)
parent83fc5f4747f9c8c6066bf002730827ecc17458aa (diff)
Merge branch 'master' into GLSL-master
Conflicts: .gitignore
Diffstat (limited to 'Source/Core/VideoCommon')
-rw-r--r--Source/Core/VideoCommon/Src/CommandProcessor.cpp101
-rw-r--r--Source/Core/VideoCommon/Src/CommandProcessor.h9
-rw-r--r--Source/Core/VideoCommon/Src/Fifo.cpp71
-rw-r--r--Source/Core/VideoCommon/Src/Fifo.h2
-rw-r--r--Source/Core/VideoCommon/Src/OpcodeDecoding.cpp85
-rw-r--r--Source/Core/VideoCommon/Src/OpcodeDecoding.h2
-rw-r--r--Source/Core/VideoCommon/Src/PixelEngine.cpp87
-rw-r--r--Source/Core/VideoCommon/Src/PixelEngine.h2
8 files changed, 206 insertions, 153 deletions
diff --git a/Source/Core/VideoCommon/Src/CommandProcessor.cpp b/Source/Core/VideoCommon/Src/CommandProcessor.cpp
index a4dddf537f..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
{
@@ -57,12 +59,15 @@ static bool bProcessFifoAllDistance = false;
volatile bool isPossibleWaitingSetDrawDone = false;
volatile bool isHiWatermarkActive = false;
+volatile bool isLoWatermarkActive = false;
volatile bool interruptSet= false;
volatile bool interruptWaiting= false;
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;
@@ -88,6 +93,7 @@ void DoState(PointerWrap &p)
p.Do(bProcessFifoToLoWatermark);
p.Do(bProcessFifoAllDistance);
p.Do(isHiWatermarkActive);
+ p.Do(isLoWatermarkActive);
p.Do(isPossibleWaitingSetDrawDone);
p.Do(interruptSet);
p.Do(interruptWaiting);
@@ -119,7 +125,7 @@ void Init()
m_tokenReg = 0;
memset(&fifo,0,sizeof(fifo));
- fifo.CPCmdIdle = 1 ;
+ fifo.CPCmdIdle = 1;
fifo.CPReadIdle = 1;
fifo.bFF_Breakpoint = 0;
fifo.bFF_HiWatermark = 0;
@@ -136,6 +142,7 @@ void Init()
bProcessFifoAllDistance = false;
isPossibleWaitingSetDrawDone = false;
isHiWatermarkActive = false;
+ isLoWatermarkActive = false;
et_UpdateInterrupts = CoreTiming::RegisterEvent("UpdateInterrupts", UpdateInterrupts_Wrapper);
}
@@ -294,7 +301,6 @@ void Read16(u16& _rReturnValue, const u32 _Address)
void Write16(const u16 _Value, const u32 _Address)
{
-
INFO_LOG(COMMANDPROCESSOR, "(write16): 0x%04x @ 0x%08x",_Value,_Address);
switch (_Address & 0xFFF)
@@ -405,7 +411,8 @@ void Write16(const u16 _Value, const u32 _Address)
{
GPFifo::ResetGatherPipe();
ResetVideoBuffer();
- }else
+ }
+ else
{
ResetVideoBuffer();
}
@@ -461,7 +468,7 @@ void STACKALIGN GatherPipeBursted()
}
if (IsOnThread())
- SetOverflowStatusFromGatherPipe();
+ SetCpStatus();
// update the fifo-pointer
if (fifo.CPWritePointer >= fifo.CPEnd)
@@ -511,19 +518,6 @@ void AbortFrame()
}
-void SetOverflowStatusFromGatherPipe()
-{
- fifo.bFF_HiWatermark = (fifo.CPReadWriteDistance > fifo.CPHiWatermark);
- isHiWatermarkActive = fifo.bFF_HiWatermark && fifo.bFF_HiWatermarkInt && m_CPCtrlReg.GPReadEnable;
-
- if (isHiWatermarkActive)
- {
- interruptSet = true;
- INFO_LOG(COMMANDPROCESSOR,"Interrupt set");
- ProcessorInterface::SetInterrupt(INT_CAUSE_CP, true);
- }
-}
-
void SetCpStatus()
{
// overflow & underflow check
@@ -531,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;
@@ -562,17 +559,27 @@ void SetCpStatus()
bool interrupt = (bpInt || ovfInt || undfInt) && m_CPCtrlReg.GPReadEnable;
- isHiWatermarkActive = ovfInt && m_CPCtrlReg.GPReadEnable;
+ isHiWatermarkActive = ovfInt && m_CPCtrlReg.GPReadEnable;
+ isLoWatermarkActive = undfInt && m_CPCtrlReg.GPReadEnable;
if (interrupt != interruptSet && !interruptWaiting)
{
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
@@ -596,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;
@@ -617,15 +624,11 @@ 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.CPReadWriteDistance;
+ 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;
- // 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"
@@ -693,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
diff --git a/Source/Core/VideoCommon/Src/CommandProcessor.h b/Source/Core/VideoCommon/Src/CommandProcessor.h
index 5d31453537..6190c48e14 100644
--- a/Source/Core/VideoCommon/Src/CommandProcessor.h
+++ b/Source/Core/VideoCommon/Src/CommandProcessor.h
@@ -31,6 +31,7 @@ namespace CommandProcessor
extern SCPFifoStruct fifo; //This one is shared between gfx thread and emulator thread.
extern volatile bool isPossibleWaitingSetDrawDone; //This one is used for sync gfx thread and emulator thread.
extern volatile bool isHiWatermarkActive;
+extern volatile bool isLoWatermarkActive;
extern volatile bool interruptSet;
extern volatile bool interruptWaiting;
extern volatile bool interruptTokenWaiting;
@@ -140,6 +141,9 @@ union UCPClearReg
UCPClearReg(u16 _hex) {Hex = _hex; }
};
+// Can be any number, low enough to not be below the number of clocks executed by the GPU per CP_PERIOD
+const static u32 m_cpClockOrigin = 200000;
+
// Init
void Init();
void Shutdown();
@@ -161,11 +165,14 @@ bool AllowIdleSkipping();
void SetCpClearRegister();
void SetCpControlRegister();
void SetCpStatusRegister();
-void SetOverflowStatusFromGatherPipe();
void ProcessFifoToLoWatermark();
void ProcessFifoAllDistance();
void ProcessFifoEvents();
void AbortFrame();
+
+void Update();
+extern volatile u32 VITicks;
+
} // namespace CommandProcessor
#endif // _COMMANDPROCESSOR_H
diff --git a/Source/Core/VideoCommon/Src/Fifo.cpp b/Source/Core/VideoCommon/Src/Fifo.cpp
index 413b163ced..93decf7ce3 100644
--- a/Source/Core/VideoCommon/Src/Fifo.cpp
+++ b/Source/Core/VideoCommon/Src/Fifo.cpp
@@ -26,6 +26,7 @@
#include "Fifo.h"
#include "HW/Memmap.h"
#include "Core.h"
+#include "CoreTiming.h"
volatile bool g_bSkipCurrentFrame = false;
extern u8* g_pVideoData;
@@ -72,6 +73,7 @@ void Fifo_Init()
videoBuffer = (u8*)AllocateMemoryPages(FIFO_SIZE);
size = 0;
GpuRunningState = false;
+ Common::AtomicStore(CommandProcessor::VITicks, CommandProcessor::m_cpClockOrigin);
}
void Fifo_Shutdown()
@@ -123,7 +125,7 @@ void ReadDataFromFifo(u8* _uData, u32 len)
size -= pos;
if (size + len > FIFO_SIZE)
{
- PanicAlert("FIFO out of bounds (sz = %i, at %08x)", size, pos);
+ PanicAlert("FIFO out of bounds (sz = %i, len = %i at %08x)", size, len, pos);
}
memmove(&videoBuffer[0], &videoBuffer[pos], size);
g_pVideoData = videoBuffer;
@@ -147,6 +149,7 @@ void RunGpuLoop()
std::lock_guard<std::mutex> lk(m_csHWVidOccupied);
GpuRunningState = true;
SCPFifoStruct &fifo = CommandProcessor::fifo;
+ u32 cyclesExecuted = 0;
while (GpuRunningState)
{
@@ -155,31 +158,41 @@ void RunGpuLoop()
VideoFifo_CheckAsyncRequest();
CommandProcessor::SetCpStatus();
+
+ Common::AtomicStore(CommandProcessor::VITicks, CommandProcessor::m_cpClockOrigin);
+
// 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;
fifo.isGpuReadingData = true;
CommandProcessor::isPossibleWaitingSetDrawDone = fifo.bFF_GPLinkEnable ? true : false;
-
- u32 readPtr = fifo.CPReadPointer;
- u8 *uData = Memory::GetPointer(readPtr);
- if (readPtr == fifo.CPEnd) readPtr = fifo.CPBase;
+ if (Common::AtomicLoad(CommandProcessor::VITicks) > CommandProcessor::m_cpClockOrigin || !Core::g_CoreStartupParameter.bSyncGPU)
+ {
+ u32 readPtr = fifo.CPReadPointer;
+ u8 *uData = Memory::GetPointer(readPtr);
+
+ if (readPtr == fifo.CPEnd) readPtr = fifo.CPBase;
else readPtr += 32;
-
- _assert_msg_(COMMANDPROCESSOR, (s32)fifo.CPReadWriteDistance - 32 >= 0 ,
- "Negative fifo.CPReadWriteDistance = %i in FIFO Loop !\nThat can produce inestabilty in the game. Please report it.", fifo.CPReadWriteDistance - 32);
-
- ReadDataFromFifo(uData, 32);
-
- OpcodeDecoder_Run(g_bSkipCurrentFrame);
- Common::AtomicStore(fifo.CPReadPointer, readPtr);
- Common::AtomicAdd(fifo.CPReadWriteDistance, -32);
- if((GetVideoBufferEndPtr() - g_pVideoData) == 0)
- Common::AtomicStore(fifo.SafeCPReadPointer, fifo.CPReadPointer);
+ _assert_msg_(COMMANDPROCESSOR, (s32)fifo.CPReadWriteDistance - 32 >= 0 ,
+ "Negative fifo.CPReadWriteDistance = %i in FIFO Loop !\nThat can produce instabilty in the game. Please report it.", fifo.CPReadWriteDistance - 32);
+
+ ReadDataFromFifo(uData, 32);
+
+ cyclesExecuted = OpcodeDecoder_Run(g_bSkipCurrentFrame);
+
+ if (Common::AtomicLoad(CommandProcessor::VITicks) > cyclesExecuted && Core::g_CoreStartupParameter.bSyncGPU)
+ Common::AtomicAdd(CommandProcessor::VITicks, -(s32)cyclesExecuted);
+
+ Common::AtomicStore(fifo.CPReadPointer, readPtr);
+ Common::AtomicAdd(fifo.CPReadWriteDistance, -32);
+ if((GetVideoBufferEndPtr() - g_pVideoData) == 0)
+ Common::AtomicStore(fifo.SafeCPReadPointer, fifo.CPReadPointer);
+ }
+
CommandProcessor::SetCpStatus();
// This call is pretty important in DualCore mode and must be called in the FIFO Loop.
@@ -188,7 +201,7 @@ void RunGpuLoop()
VideoFifo_CheckAsyncRequest();
CommandProcessor::isPossibleWaitingSetDrawDone = false;
}
-
+
fifo.isGpuReadingData = false;
@@ -217,23 +230,23 @@ bool AtBreakpoint()
void RunGpu()
{
- SCPFifoStruct &fifo = CommandProcessor::fifo;
- while (fifo.bFF_GPReadEnable && fifo.CPReadWriteDistance && !AtBreakpoint() )
- {
- u8 *uData = Memory::GetPointer(fifo.CPReadPointer);
+ SCPFifoStruct &fifo = CommandProcessor::fifo;
+ while (fifo.bFF_GPReadEnable && fifo.CPReadWriteDistance && !AtBreakpoint() )
+ {
+ u8 *uData = Memory::GetPointer(fifo.CPReadPointer);
FPURoundMode::SaveSIMDState();
FPURoundMode::LoadDefaultSIMDState();
ReadDataFromFifo(uData, 32);
- OpcodeDecoder_Run(g_bSkipCurrentFrame);
+ u32 count = OpcodeDecoder_Run(g_bSkipCurrentFrame);
FPURoundMode::LoadSIMDState();
- //DEBUG_LOG(COMMANDPROCESSOR, "Fifo wraps to base");
+ //DEBUG_LOG(COMMANDPROCESSOR, "Fifo wraps to base");
- if (fifo.CPReadPointer == fifo.CPEnd) fifo.CPReadPointer = fifo.CPBase;
- else fifo.CPReadPointer += 32;
+ if (fifo.CPReadPointer == fifo.CPEnd) fifo.CPReadPointer = fifo.CPBase;
+ else fifo.CPReadPointer += 32;
- fifo.CPReadWriteDistance -= 32;
- }
- CommandProcessor::SetCpStatus();
+ fifo.CPReadWriteDistance -= 32;
+ }
+ CommandProcessor::SetCpStatus();
}
diff --git a/Source/Core/VideoCommon/Src/Fifo.h b/Source/Core/VideoCommon/Src/Fifo.h
index 75e7d782f5..f465db8f85 100644
--- a/Source/Core/VideoCommon/Src/Fifo.h
+++ b/Source/Core/VideoCommon/Src/Fifo.h
@@ -23,7 +23,7 @@
class PointerWrap;
-#define FIFO_SIZE (1024*1024)
+#define FIFO_SIZE (2*1024*1024)
extern volatile bool g_bSkipCurrentFrame;
diff --git a/Source/Core/VideoCommon/Src/OpcodeDecoding.cpp b/Source/Core/VideoCommon/Src/OpcodeDecoding.cpp
index a1ff1a9985..2e2664e219 100644
--- a/Source/Core/VideoCommon/Src/OpcodeDecoding.cpp
+++ b/Source/Core/VideoCommon/Src/OpcodeDecoding.cpp
@@ -136,29 +136,38 @@ void ExecuteDisplayList(u32 address, u32 size)
InterpretDisplayList(address, size);
}
-bool FifoCommandRunnable()
+u32 FifoCommandRunnable(u32 &command_size)
{
+ u32 cycleTime = 0;
u32 buffer_size = (u32)(GetVideoBufferEndPtr() - g_pVideoData);
if (buffer_size == 0)
- return false; // can't peek
+ return 0; // can't peek
u8 cmd_byte = DataPeek8(0);
- u32 command_size = 0;
switch (cmd_byte)
{
case GX_NOP: // Hm, this means that we scan over nop streams pretty slowly...
+ command_size = 1;
+ cycleTime = 6;
+ break;
case GX_CMD_INVL_VC: // Invalidate Vertex Cache - no parameters
+ command_size = 1;
+ cycleTime = 6;
+ break;
case GX_CMD_UNKNOWN_METRICS: // zelda 4 swords calls it and checks the metrics registers after that
command_size = 1;
+ cycleTime = 6;
break;
case GX_LOAD_BP_REG:
command_size = 5;
+ cycleTime = 12;
break;
case GX_LOAD_CP_REG:
command_size = 6;
+ cycleTime = 12;
break;
case GX_LOAD_INDX_A:
@@ -166,10 +175,39 @@ bool FifoCommandRunnable()
case GX_LOAD_INDX_C:
case GX_LOAD_INDX_D:
command_size = 5;
+ cycleTime = 6; // TODO
break;
- case GX_CMD_CALL_DL:
- command_size = 9;
+ case GX_CMD_CALL_DL:
+ {
+ // FIXME: Calculate the cycle time of the display list.
+ //u32 address = DataPeek32(1);
+ //u32 size = DataPeek32(5);
+ //u8* old_pVideoData = g_pVideoData;
+ //u8* startAddress = Memory::GetPointer(address);
+
+ //// Avoid the crash if Memory::GetPointer failed ..
+ //if (startAddress != 0)
+ //{
+ // g_pVideoData = startAddress;
+ // u8 *end = g_pVideoData + size;
+ // u32 step = 0;
+ // while (g_pVideoData < end)
+ // {
+ // cycleTime += FifoCommandRunnable(step);
+ // g_pVideoData += step;
+ // }
+ //}
+ //else
+ //{
+ // cycleTime = 45;
+ //}
+
+ //// reset to the old pointer
+ //g_pVideoData = old_pVideoData;
+ command_size = 9;
+ cycleTime = 45; // This is unverified
+ }
break;
case GX_LOAD_XF_REG:
@@ -180,11 +218,12 @@ bool FifoCommandRunnable()
command_size = 1 + 4;
u32 Cmd2 = DataPeek32(1);
int transfer_size = ((Cmd2 >> 16) & 15) + 1;
- command_size += transfer_size * 4;
+ command_size += transfer_size * 4;
+ cycleTime = 18 + 6 * transfer_size;
}
else
{
- return false;
+ return 0;
}
}
break;
@@ -198,10 +237,11 @@ bool FifoCommandRunnable()
command_size = 1 + 2;
u16 numVertices = DataPeek16(1);
command_size += numVertices * VertexLoaderManager::GetVertexSize(cmd_byte & GX_VAT_MASK);
+ cycleTime = 1600; // This depends on the number of pixels rendered
}
else
{
- return false;
+ return 0;
}
}
else
@@ -248,11 +288,19 @@ bool FifoCommandRunnable()
}
if (command_size > buffer_size)
- return false;
+ return 0;
// INFO_LOG("OP detected: cmd_byte 0x%x size %i buffer %i",cmd_byte, command_size, buffer_size);
+ if (cycleTime == 0)
+ cycleTime = 6;
- return true;
+ return cycleTime;
+}
+
+u32 FifoCommandRunnable()
+{
+ u32 command_size = 0;
+ return FifoCommandRunnable(command_size);
}
static void Decode()
@@ -461,16 +509,15 @@ void OpcodeDecoder_Shutdown()
}
}
-void OpcodeDecoder_Run(bool skipped_frame)
+u32 OpcodeDecoder_Run(bool skipped_frame)
{
- if (!skipped_frame)
- {
- while (FifoCommandRunnable())
- Decode();
- }
- else
+ u32 totalCycles = 0;
+ u32 cycles = FifoCommandRunnable();
+ while (cycles > 0)
{
- while (FifoCommandRunnable())
- DecodeSemiNop();
+ skipped_frame ? DecodeSemiNop() : Decode();
+ totalCycles += cycles;
+ cycles = FifoCommandRunnable();
}
+ return totalCycles;
}
diff --git a/Source/Core/VideoCommon/Src/OpcodeDecoding.h b/Source/Core/VideoCommon/Src/OpcodeDecoding.h
index f2e9cd1321..71a15477a3 100644
--- a/Source/Core/VideoCommon/Src/OpcodeDecoding.h
+++ b/Source/Core/VideoCommon/Src/OpcodeDecoding.h
@@ -50,6 +50,6 @@ extern bool g_bRecordFifoData;
void OpcodeDecoder_Init();
void OpcodeDecoder_Shutdown();
-void OpcodeDecoder_Run(bool skipped_frame);
+u32 OpcodeDecoder_Run(bool skipped_frame);
void ExecuteDisplayList(u32 address, u32 size);
#endif // _OPCODE_DECODING_H
diff --git a/Source/Core/VideoCommon/Src/PixelEngine.cpp b/Source/Core/VideoCommon/Src/PixelEngine.cpp
index e5ba554678..974fdb8203 100644
--- a/Source/Core/VideoCommon/Src/PixelEngine.cpp
+++ b/Source/Core/VideoCommon/Src/PixelEngine.cpp
@@ -33,7 +33,6 @@
#include "HW/ProcessorInterface.h"
#include "DLCache.h"
#include "State.h"
-#include "PerfQueryBase.h"
namespace PixelEngine
{
@@ -113,14 +112,14 @@ 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 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;
@@ -164,10 +163,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);
@@ -214,7 +213,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;
@@ -351,8 +350,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;
@@ -398,14 +397,14 @@ void UpdateInterrupts()
void UpdateTokenInterrupt(bool active)
{
- ProcessorInterface::SetInterrupt(INT_CAUSE_PE_TOKEN, active);
- interruptSetToken = active;
+ ProcessorInterface::SetInterrupt(INT_CAUSE_PE_TOKEN, active);
+ Common::AtomicStore(interruptSetToken, active ? 1 : 0);
}
void UpdateFinishInterrupt(bool active)
{
- ProcessorInterface::SetInterrupt(INT_CAUSE_PE_FINISH, active);
- interruptSetFinish = active;
+ ProcessorInterface::SetInterrupt(INT_CAUSE_PE_FINISH, active);
+ Common::AtomicStore(interruptSetFinish, active ? 1 : 0);
}
// TODO(mb2): Refactor SetTokenINT_OnMainThread(u64 userdata, int cyclesLate).
@@ -415,20 +414,23 @@ 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);
+ // 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);
+ if (userdata >> 16)
+ {
+ Common::AtomicStore(*(volatile u32*)&g_bSignalTokenInterrupt, 1);
UpdateInterrupts();
- CommandProcessor::interruptTokenWaiting = false;
- IncrementCheckContextId();
- //}
+ }
+ CommandProcessor::interruptTokenWaiting = false;
+ IncrementCheckContextId();
}
void SetFinish_OnMainThread(u64 userdata, int cyclesLate)
{
- g_bSignalFinishInterrupt = 1;
+ Common::AtomicStore(*(volatile u32*)&g_bSignalFinishInterrupt, 1);
UpdateInterrupts();
CommandProcessor::interruptFinishWaiting = false;
CommandProcessor::isPossibleWaitingSetDrawDone = false;
@@ -438,23 +440,13 @@ 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.
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
- // 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);
+ Common::AtomicStore(*(volatile u32*)&g_bSignalTokenInterrupt, 1);
}
+
+ CommandProcessor::interruptTokenWaiting = true;
+ CoreTiming::ScheduleEvent_Threadsafe(0, et_SetTokenOnMainThread, _token | (_bSetTokenAcknowledge << 16));
IncrementCheckContextId();
}
@@ -477,7 +469,6 @@ void ResetSetFinish()
{
UpdateFinishInterrupt(false);
g_bSignalFinishInterrupt = false;
-
}
else
{
@@ -491,8 +482,7 @@ void ResetSetToken()
if (g_bSignalTokenInterrupt)
{
UpdateTokenInterrupt(false);
- g_bSignalTokenInterrupt = false;
-
+ g_bSignalTokenInterrupt = 0;
}
else
{
@@ -500,17 +490,4 @@ void ResetSetToken()
}
CommandProcessor::interruptTokenWaiting = false;
}
-
-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 eaf55f0031..9689104b8b 100644
--- a/Source/Core/VideoCommon/Src/PixelEngine.h
+++ b/Source/Core/VideoCommon/Src/PixelEngine.h
@@ -81,8 +81,6 @@ void SetToken(const u16 _token, const int _bSetTokenAcknowledge);
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];