mirror of
https://github.com/izzy2lost/dolphin.git
synced 2026-06-19 01:16:48 -07:00
Big Fifo Commit Part2: Now the fifo is more stable than my first commit, so is time...
- ReImplementing Single Core Mode like Dual Core Mode Style. - Stage 1: My goal is, we have the Fifo, CommandProccessor code the more clear, maintenible and documented possible. When I quit dolphin I want any developer can continue with the work only reading the code. * Big Refactoring: A lot of functions was changed the names, and modularized. Now the FifoLoop and CatchUpGPU does not exist, was replaced by RunGpu() and RunGpuLoop(). The general idea is modeling the code like the real HW. The fifo is only a buffer where the Write Gather Pipe write the commands and from the Graphic Processor read these. * Big Clean UP a lot of obsolete code and comments was deleted, like DcFakeWachDog, "Fifo very soon hack", etc. In the stage 2, I will refactoring more code doing emphasis in the division of CommandProcessor, Fifo, Gpu Emulation. Beside I will comment all functions and variables in the code (Don't worry I will ask for English help for this part ;) ) Please test a lot SC mode and DC mode :) Thank you so much for testing always and the patience. I don't like broke your favorite game but... you must believe me this part is very sensible, I only try to contribute for have a better and stable dolphin emulator. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@7185 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
@@ -72,7 +72,7 @@ struct SCPFifoStruct
|
||||
|
||||
// for GP watchdog hack
|
||||
volatile u32 Fake_GPWDToken; // cicular incrementer
|
||||
volatile u32 isFifoProcesingData;
|
||||
volatile u32 isGpuReadingData;
|
||||
};
|
||||
|
||||
class VideoBackend
|
||||
@@ -114,7 +114,6 @@ public:
|
||||
|
||||
static void Video_GatherPipeBursted();
|
||||
|
||||
virtual void Video_WaitForFrameFinish() = 0;
|
||||
virtual bool Video_IsPossibleWaitingSetDrawDone() = 0;
|
||||
virtual void Video_AbortFrame() = 0;
|
||||
|
||||
@@ -146,7 +145,6 @@ class VideoBackendHLE : public VideoBackend
|
||||
|
||||
void Video_SetRendering(bool bEnabled);
|
||||
|
||||
void Video_WaitForFrameFinish();
|
||||
bool Video_IsPossibleWaitingSetDrawDone();
|
||||
void Video_AbortFrame();
|
||||
};
|
||||
|
||||
@@ -224,13 +224,6 @@ u64 GetFakeTimeBase()
|
||||
return CoreTiming::GetFakeTBStartValue() + ((CoreTiming::GetTicks() - CoreTiming::GetFakeTBStartTicks()) / TIMER_RATIO);
|
||||
}
|
||||
|
||||
// For DC watchdog hack
|
||||
void FakeGPWatchdogCallback(u64 userdata, int cyclesLate)
|
||||
{
|
||||
g_video_backend->Video_WaitForFrameFinish(); // lock CPUThread until frame finish
|
||||
CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerFrame() - cyclesLate, et_FakeGPWD);
|
||||
}
|
||||
|
||||
void PatchEngineCallback(u64 userdata, int cyclesLate)
|
||||
{
|
||||
// Patch mem and run the Action Replay
|
||||
@@ -289,8 +282,6 @@ void Init()
|
||||
et_DSP = CoreTiming::RegisterEvent("DSPCallback", DSPCallback);
|
||||
et_AudioDMA = CoreTiming::RegisterEvent("AudioDMACallback", AudioDMACallback);
|
||||
et_IPC_HLE = CoreTiming::RegisterEvent("IPC_HLE_UpdateCallback", IPC_HLE_UpdateCallback);
|
||||
// Always register this. Increases chances of DC/SC save state compatibility.
|
||||
et_FakeGPWD = CoreTiming::RegisterEvent("FakeGPWatchdogCallback", FakeGPWatchdogCallback);
|
||||
et_PatchEngine = CoreTiming::RegisterEvent("PatchEngine", PatchEngineCallback);
|
||||
|
||||
CoreTiming::ScheduleEvent(AI_PERIOD, et_AI);
|
||||
@@ -299,10 +290,6 @@ void Init()
|
||||
CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerFrame(), et_SI);
|
||||
CoreTiming::ScheduleEvent(AUDIO_DMA_PERIOD, et_AudioDMA);
|
||||
|
||||
// For DC watchdog hack
|
||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread)
|
||||
CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerFrame(), et_FakeGPWD);
|
||||
|
||||
CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerFrame(), et_PatchEngine);
|
||||
|
||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -151,25 +151,15 @@ void Write16(const u16 _Data, const u32 _Address);
|
||||
void Read32(u32& _rReturnValue, const u32 _Address);
|
||||
void Write32(const u32 _Data, const u32 _Address);
|
||||
|
||||
// for CGPFIFO
|
||||
void CatchUpGPU();
|
||||
void SetStatus();
|
||||
void SetCpStatus();
|
||||
void GatherPipeBursted();
|
||||
void UpdateFifoRegister();
|
||||
void UpdateInterrupts(u64 userdata);
|
||||
void UpdateInterruptsFromVideoBackend(u64 userdata);
|
||||
void UpdateInterruptsScMode();
|
||||
void SetFifoIdleFromVideoBackend();
|
||||
|
||||
bool AllowIdleSkipping();
|
||||
|
||||
// for DC GP watchdog hack
|
||||
void IncrementGPWDToken();
|
||||
void WaitForFrameFinish();
|
||||
|
||||
void FifoCriticalEnter();
|
||||
void FifoCriticalLeave();
|
||||
|
||||
void SetCpControlRegister();
|
||||
void SetCpStatusRegister();
|
||||
void SetOverflowStatusFromGatherPipe();
|
||||
void ProcessFifoToLoWatermark();
|
||||
void ProcessFifoAllDistance();
|
||||
|
||||
@@ -31,8 +31,8 @@ extern u8* g_pVideoData;
|
||||
|
||||
namespace
|
||||
{
|
||||
static volatile bool fifoStateRun = false;
|
||||
static volatile bool EmuRunning = false;
|
||||
static volatile bool GpuRunningState = false;
|
||||
static volatile bool EmuRunningState = false;
|
||||
static u8 *videoBuffer;
|
||||
// STATE_TO_SAVE
|
||||
static int size = 0;
|
||||
@@ -53,21 +53,21 @@ void Fifo_Init()
|
||||
{
|
||||
videoBuffer = (u8*)AllocateMemoryPages(FIFO_SIZE);
|
||||
size = 0;
|
||||
fifoStateRun = false;
|
||||
GpuRunningState = false;
|
||||
}
|
||||
|
||||
void Fifo_Shutdown()
|
||||
{
|
||||
if (fifoStateRun) PanicAlert("Fifo shutting down while active");
|
||||
if (GpuRunningState) PanicAlert("Fifo shutting down while active");
|
||||
FreeMemoryPages(videoBuffer, FIFO_SIZE);
|
||||
}
|
||||
|
||||
u8* FAKE_GetFifoStartPtr()
|
||||
u8* GetVideoBufferStartPtr()
|
||||
{
|
||||
return videoBuffer;
|
||||
}
|
||||
|
||||
u8* FAKE_GetFifoEndPtr()
|
||||
u8* GetVideoBufferEndPtr()
|
||||
{
|
||||
return &videoBuffer[size];
|
||||
}
|
||||
@@ -79,25 +79,25 @@ void Fifo_SetRendering(bool enabled)
|
||||
|
||||
// May be executed from any thread, even the graphics thread.
|
||||
// Created to allow for self shutdown.
|
||||
void Fifo_ExitLoop()
|
||||
void ExitGpuLoop()
|
||||
{
|
||||
// This should break the wait loop in CPU thread
|
||||
CommandProcessor::fifo.bFF_GPReadEnable = false;
|
||||
SCPFifoStruct &_fifo = CommandProcessor::fifo;
|
||||
while(_fifo.isFifoProcesingData) Common::YieldCPU();
|
||||
SCPFifoStruct &fifo = CommandProcessor::fifo;
|
||||
while(fifo.isGpuReadingData) Common::YieldCPU();
|
||||
// Terminate GPU thread loop
|
||||
fifoStateRun = false;
|
||||
EmuRunning = true;
|
||||
GpuRunningState = false;
|
||||
EmuRunningState = true;
|
||||
}
|
||||
|
||||
void Fifo_RunLoop(bool run)
|
||||
void EmulatorState(bool running)
|
||||
{
|
||||
EmuRunning = run;
|
||||
EmuRunningState = running;
|
||||
}
|
||||
|
||||
|
||||
// Description: Fifo_EnterLoop() sends data through this function.
|
||||
void Fifo_SendFifoData(u8* _uData, u32 len)
|
||||
// Description: RunGpuLoop() sends data through this function.
|
||||
void ReadDataFromFifo(u8* _uData, u32 len)
|
||||
{
|
||||
if (size + len >= FIFO_SIZE)
|
||||
{
|
||||
@@ -124,54 +124,45 @@ void ResetVideoBuffer()
|
||||
|
||||
// Description: Main FIFO update loop
|
||||
// Purpose: Keep the Core HW updated about the CPU-GPU distance
|
||||
void Fifo_EnterLoop()
|
||||
void RunGpuLoop()
|
||||
{
|
||||
fifoStateRun = true;
|
||||
SCPFifoStruct &_fifo = CommandProcessor::fifo;
|
||||
s32 distToSend;
|
||||
GpuRunningState = true;
|
||||
SCPFifoStruct &fifo = CommandProcessor::fifo;
|
||||
|
||||
while (fifoStateRun)
|
||||
while (GpuRunningState)
|
||||
{
|
||||
g_video_backend->PeekMessages();
|
||||
|
||||
VideoFifo_CheckAsyncRequest();
|
||||
|
||||
// check if we are able to run this buffer
|
||||
|
||||
CommandProcessor::SetStatus();
|
||||
|
||||
while (!CommandProcessor::interruptWaiting && _fifo.bFF_GPReadEnable &&
|
||||
_fifo.CPReadWriteDistance && (!AtBreakpoint() || CommandProcessor::OnOverflow))
|
||||
|
||||
CommandProcessor::SetCpStatus();
|
||||
// check if we are able to run this buffer
|
||||
while (!CommandProcessor::interruptWaiting && fifo.bFF_GPReadEnable &&
|
||||
fifo.CPReadWriteDistance && (!AtBreakpoint() || CommandProcessor::OnOverflow))
|
||||
{
|
||||
_fifo.isFifoProcesingData = true;
|
||||
CommandProcessor::isPossibleWaitingSetDrawDone = _fifo.bFF_GPLinkEnable;
|
||||
if (!GpuRunningState) break;
|
||||
|
||||
if (!fifoStateRun) break;
|
||||
|
||||
// Create pointer to video data and send it to the VideoBackend
|
||||
u32 readPtr = _fifo.CPReadPointer;
|
||||
fifo.isGpuReadingData = true;
|
||||
CommandProcessor::isPossibleWaitingSetDrawDone = fifo.bFF_GPLinkEnable;
|
||||
|
||||
u32 readPtr = fifo.CPReadPointer;
|
||||
u8 *uData = Memory::GetPointer(readPtr);
|
||||
|
||||
distToSend = 32;
|
||||
|
||||
if (readPtr == _fifo.CPEnd)
|
||||
readPtr = _fifo.CPBase;
|
||||
else
|
||||
readPtr += 32;
|
||||
if (readPtr == fifo.CPEnd) readPtr = fifo.CPBase;
|
||||
else readPtr += 32;
|
||||
|
||||
_assert_msg_(COMMANDPROCESSOR, (s32)_fifo.CPReadWriteDistance - distToSend >= 0 ,
|
||||
"Negative fifo.CPReadWriteDistance = %i in FIFO Loop !\nThat can produce inestabilty in the game. Please report it.", _fifo.CPReadWriteDistance - distToSend);
|
||||
_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);
|
||||
|
||||
// Execute new instructions found in uData
|
||||
Fifo_SendFifoData(uData, distToSend);
|
||||
ReadDataFromFifo(uData, 32);
|
||||
|
||||
OpcodeDecoder_Run(g_bSkipCurrentFrame);
|
||||
|
||||
Common::AtomicStore(_fifo.CPReadPointer, readPtr);
|
||||
Common::AtomicAdd(_fifo.CPReadWriteDistance, -distToSend);
|
||||
if((FAKE_GetFifoEndPtr() - g_pVideoData) == 0)
|
||||
Common::AtomicStore(_fifo.SafeCPReadPointer, _fifo.CPReadPointer);
|
||||
CommandProcessor::SetStatus();
|
||||
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.
|
||||
// If we don't, s_swapRequested or s_efbAccessRequested won't be set to false
|
||||
@@ -180,16 +171,15 @@ void Fifo_EnterLoop()
|
||||
CommandProcessor::isPossibleWaitingSetDrawDone = false;
|
||||
}
|
||||
|
||||
_fifo.isFifoProcesingData = false;
|
||||
fifo.isGpuReadingData = false;
|
||||
|
||||
CommandProcessor::SetFifoIdleFromVideoBackend();
|
||||
|
||||
if (EmuRunning)
|
||||
if (EmuRunningState)
|
||||
Common::YieldCPU();
|
||||
else
|
||||
{
|
||||
// While the emu is paused, we still handle async request such as Savestates then sleep.
|
||||
while (!EmuRunning)
|
||||
while (!EmuRunningState)
|
||||
{
|
||||
g_video_backend->PeekMessages();
|
||||
VideoFifo_CheckStateRequest();
|
||||
@@ -202,6 +192,29 @@ void Fifo_EnterLoop()
|
||||
|
||||
bool AtBreakpoint()
|
||||
{
|
||||
SCPFifoStruct &_fifo = CommandProcessor::fifo;
|
||||
return _fifo.bFF_BPEnable && (_fifo.CPReadPointer == _fifo.CPBreakpoint);
|
||||
SCPFifoStruct &fifo = CommandProcessor::fifo;
|
||||
return fifo.bFF_BPEnable && (fifo.CPReadPointer == fifo.CPBreakpoint);
|
||||
}
|
||||
|
||||
void RunGpu()
|
||||
{
|
||||
SCPFifoStruct &fifo = CommandProcessor::fifo;
|
||||
while (fifo.bFF_GPReadEnable && fifo.CPReadWriteDistance && !AtBreakpoint() )
|
||||
{
|
||||
u8 *uData = Memory::GetPointer(fifo.CPReadPointer);
|
||||
|
||||
SaveSSEState();
|
||||
LoadDefaultSSEState();
|
||||
ReadDataFromFifo(uData, 32);
|
||||
OpcodeDecoder_Run(g_bSkipCurrentFrame);
|
||||
LoadSSEState();
|
||||
|
||||
//DEBUG_LOG(COMMANDPROCESSOR, "Fifo wraps to base");
|
||||
|
||||
if (fifo.CPReadPointer == fifo.CPEnd) fifo.CPReadPointer = fifo.CPBase;
|
||||
else fifo.CPReadPointer += 32;
|
||||
|
||||
fifo.CPReadWriteDistance -= 32;
|
||||
}
|
||||
CommandProcessor::SetCpStatus();
|
||||
}
|
||||
@@ -30,18 +30,18 @@ extern volatile bool g_bSkipCurrentFrame;
|
||||
|
||||
void Fifo_Init();
|
||||
void Fifo_Shutdown();
|
||||
|
||||
void Fifo_SendFifoData(u8* _uData, u32 len);
|
||||
|
||||
// These two are for dual core mode only.
|
||||
void Fifo_EnterLoop();
|
||||
void Fifo_ExitLoop();
|
||||
void Fifo_RunLoop(bool run);
|
||||
bool AtBreakpoint();
|
||||
void Fifo_DoState(PointerWrap &f);
|
||||
|
||||
void ReadDataFromFifo(u8* _uData, u32 len);
|
||||
|
||||
void RunGpu();
|
||||
void RunGpuLoop();
|
||||
void ExitGpuLoop();
|
||||
void EmulatorState(bool running);
|
||||
bool AtBreakpoint();
|
||||
void ResetVideoBuffer();
|
||||
void Fifo_SetRendering(bool bEnabled);
|
||||
bool IsFifoProcesingData();
|
||||
|
||||
|
||||
// Implemented by the Video Backend
|
||||
void VideoFifo_CheckAsyncRequest();
|
||||
|
||||
@@ -41,18 +41,18 @@ static u32 s_AccessEFBResult = 0;
|
||||
|
||||
void VideoBackendHLE::EmuStateChange(EMUSTATE_CHANGE newState)
|
||||
{
|
||||
Fifo_RunLoop((newState == EMUSTATE_CHANGE_PLAY) ? true : false);
|
||||
EmulatorState((newState == EMUSTATE_CHANGE_PLAY) ? true : false);
|
||||
}
|
||||
|
||||
// Enter and exit the video loop
|
||||
void VideoBackendHLE::Video_EnterLoop()
|
||||
{
|
||||
Fifo_EnterLoop();
|
||||
RunGpuLoop();
|
||||
}
|
||||
|
||||
void VideoBackendHLE::Video_ExitLoop()
|
||||
{
|
||||
Fifo_ExitLoop();
|
||||
ExitGpuLoop();
|
||||
s_FifoShuttingDown = true;
|
||||
}
|
||||
|
||||
@@ -233,11 +233,6 @@ void VideoBackend::Video_GatherPipeBursted()
|
||||
CommandProcessor::GatherPipeBursted();
|
||||
}
|
||||
|
||||
void VideoBackendHLE::Video_WaitForFrameFinish()
|
||||
{
|
||||
CommandProcessor::WaitForFrameFinish();
|
||||
}
|
||||
|
||||
bool VideoBackendHLE::Video_IsPossibleWaitingSetDrawDone()
|
||||
{
|
||||
return CommandProcessor::isPossibleWaitingSetDrawDone;
|
||||
|
||||
@@ -90,8 +90,8 @@ DataReadU32xNfunc DataReadU32xFuncs[16] = {
|
||||
DataReadU32xN<16>
|
||||
};
|
||||
|
||||
extern u8* FAKE_GetFifoStartPtr();
|
||||
extern u8* FAKE_GetFifoEndPtr();
|
||||
extern u8* GetVideoBufferStartPtr();
|
||||
extern u8* GetVideoBufferEndPtr();
|
||||
|
||||
static void Decode();
|
||||
|
||||
@@ -135,7 +135,7 @@ void ExecuteDisplayList(u32 address, u32 size)
|
||||
|
||||
bool FifoCommandRunnable()
|
||||
{
|
||||
u32 buffer_size = (u32)(FAKE_GetFifoEndPtr() - g_pVideoData);
|
||||
u32 buffer_size = (u32)(GetVideoBufferEndPtr() - g_pVideoData);
|
||||
if (buffer_size == 0)
|
||||
return false; // can't peek
|
||||
|
||||
@@ -420,7 +420,7 @@ static void DecodeSemiNop()
|
||||
|
||||
void OpcodeDecoder_Init()
|
||||
{
|
||||
g_pVideoData = FAKE_GetFifoStartPtr();
|
||||
g_pVideoData = GetVideoBufferStartPtr();
|
||||
|
||||
#if _M_SSE >= 0x301
|
||||
if (cpu_info.bSSSE3)
|
||||
|
||||
@@ -367,8 +367,7 @@ 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
|
||||
{
|
||||
// This seems smelly...
|
||||
CommandProcessor::IncrementGPWDToken(); // for DC watchdog hack since PEToken seems to be a frame-finish too
|
||||
|
||||
Common::AtomicStore(*(volatile u32*)&CommandProcessor::fifo.PEToken, _token);
|
||||
CommandProcessor::interruptTokenWaiting = true;
|
||||
CoreTiming::ScheduleEvent_Threadsafe(0, et_SetTokenOnMainThread, _token | (_bSetTokenAcknowledge << 16));
|
||||
@@ -389,7 +388,6 @@ void SetToken(const u16 _token, const int _bSetTokenAcknowledge)
|
||||
// THIS IS EXECUTED FROM VIDEO THREAD (BPStructs.cpp) when a new frame has been drawn
|
||||
void SetFinish()
|
||||
{
|
||||
CommandProcessor::IncrementGPWDToken(); // for DC watchdog hack
|
||||
CommandProcessor::interruptFinishWaiting = true;
|
||||
CoreTiming::ScheduleEvent_Threadsafe(0, et_SetFinishOnMainThread, 0);
|
||||
INFO_LOG(PIXELENGINE, "VIDEO Set Finish");
|
||||
|
||||
@@ -58,5 +58,5 @@ void VideoCommon_DoState(PointerWrap &p)
|
||||
|
||||
void VideoCommon_RunLoop(bool enable)
|
||||
{
|
||||
Fifo_RunLoop(enable);
|
||||
EmulatorState(enable);
|
||||
}
|
||||
|
||||
@@ -174,9 +174,6 @@ void VideoBackend::Video_SetRendering(bool bEnabled)
|
||||
Fifo_SetRendering(bEnabled);
|
||||
}
|
||||
|
||||
void VideoBackend::Video_WaitForFrameFinish(void)
|
||||
{
|
||||
}
|
||||
|
||||
bool VideoBackend::Video_IsPossibleWaitingSetDrawDone(void)
|
||||
{
|
||||
|
||||
@@ -35,7 +35,6 @@ class VideoBackend : public VideoBackendLLE
|
||||
|
||||
void Video_SetRendering(bool bEnabled);
|
||||
|
||||
void Video_WaitForFrameFinish();
|
||||
bool Video_IsPossibleWaitingSetDrawDone();
|
||||
void Video_AbortFrame();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user