diff options
| author | degasus <wickmarkus@web.de> | 2013-03-12 11:28:56 +0100 |
|---|---|---|
| committer | degasus <wickmarkus@web.de> | 2013-03-12 11:28:56 +0100 |
| commit | 382be2aabdf0635c67f9ec945283f77f8ed9b0c9 (patch) | |
| tree | 8df3cf8a3539e4b4b1a96772f17c353f99393ed5 /Source/Core/VideoCommon | |
| parent | e1ca002937cf8915ab9fb04f82e2dc5e68db1fa2 (diff) | |
| parent | 83fc5f4747f9c8c6066bf002730827ecc17458aa (diff) | |
Merge branch 'master' into GLSL-master
Conflicts:
.gitignore
Diffstat (limited to 'Source/Core/VideoCommon')
| -rw-r--r-- | Source/Core/VideoCommon/Src/CommandProcessor.cpp | 101 | ||||
| -rw-r--r-- | Source/Core/VideoCommon/Src/CommandProcessor.h | 9 | ||||
| -rw-r--r-- | Source/Core/VideoCommon/Src/Fifo.cpp | 71 | ||||
| -rw-r--r-- | Source/Core/VideoCommon/Src/Fifo.h | 2 | ||||
| -rw-r--r-- | Source/Core/VideoCommon/Src/OpcodeDecoding.cpp | 85 | ||||
| -rw-r--r-- | Source/Core/VideoCommon/Src/OpcodeDecoding.h | 2 | ||||
| -rw-r--r-- | Source/Core/VideoCommon/Src/PixelEngine.cpp | 87 | ||||
| -rw-r--r-- | Source/Core/VideoCommon/Src/PixelEngine.h | 2 |
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]; |
