Change the way the we send commands to the GPU in single core mode. This will enable me to make the jit slightly cleaner in the future.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@168 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
hrydgard 2008-08-10 18:15:48 +00:00
parent 1359943a62
commit 4cec78a13b
3 changed files with 71 additions and 53 deletions

View File

@ -15,6 +15,12 @@
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
// TODO
// * Kick GPU from dispatcher, not from writes
// * Thunking framework
// * Cleanup of messy now unnecessary safety code in jit
#include "Common.h" #include "Common.h"
#include "../Plugins/Plugin_Video.h" #include "../Plugins/Plugin_Video.h"
#include "../PowerPC/PowerPC.h" #include "../PowerPC/PowerPC.h"
@ -218,11 +224,11 @@ void Write16(const u16 _Value, const u32 _Address)
; ;
fifo.bPauseRead = true; fifo.bPauseRead = true;
} }
}
#ifdef _WIN32 #ifdef _WIN32
EnterCriticalSection(&fifo.sync); EnterCriticalSection(&fifo.sync);
#endif #endif
}
switch (_Address & 0xFFF) switch (_Address & 0xFFF)
{ {
case STATUS_REGISTER: case STATUS_REGISTER:
@ -304,6 +310,7 @@ void Write16(const u16 _Value, const u32 _Address)
// This will recursively enter fifo.sync, TODO(ector): is this good? // This will recursively enter fifo.sync, TODO(ector): is this good?
UpdateFifoRegister(); UpdateFifoRegister();
#ifdef _WIN32 #ifdef _WIN32
if (Core::g_CoreStartupParameter.bUseDualCore)
LeaveCriticalSection(&fifo.sync); LeaveCriticalSection(&fifo.sync);
#endif #endif
fifo.bPauseRead = false; // pauseread is not actually used anywhere! TOOD(ector): huh! fifo.bPauseRead = false; // pauseread is not actually used anywhere! TOOD(ector): huh!
@ -366,36 +373,9 @@ void GatherPipeBursted()
} }
} }
// __________________________________________________________________________________________________
// UpdateFifoRegister
// It's no problem if the gfx falls behind a little bit. Better make sure to stop the cpu thread void CatchUpGPU()
// when the distance is way huge, though.
// So:
// CPU thread
/// 0. Write data (done before entering this)
// 1. Compute distance
// 2. If distance > threshold, sleep and goto 1
// GPU thread
// 1. Compute distance
// 2. If distance < threshold, sleep and goto 1 (or wait for trigger?)
// 3. Read and use a bit of data, goto 1
void UpdateFifoRegister()
{
// update the distance
#ifdef _WIN32
if (Core::g_CoreStartupParameter.bUseDualCore) EnterCriticalSection(&fifo.sync);
#endif
int wp = fifo.CPWritePointer;
int rp = fifo.CPReadPointer;
if (wp >= rp)
fifo.CPReadWriteDistance = wp - rp;
else
fifo.CPReadWriteDistance = (wp - fifo.CPBase) +
(fifo.CPEnd - rp);
#ifdef _WIN32
if (Core::g_CoreStartupParameter.bUseDualCore) LeaveCriticalSection(&fifo.sync);
#endif
if (!Core::g_CoreStartupParameter.bUseDualCore)
{ {
// check if we are able to run this buffer // check if we are able to run this buffer
if ((fifo.bFF_GPReadEnable) && !(fifo.bFF_BPEnable && fifo.bFF_Breakpoint)) if ((fifo.bFF_GPReadEnable) && !(fifo.bFF_BPEnable && fifo.bFF_Breakpoint))
@ -434,11 +414,42 @@ void UpdateFifoRegister()
{ {
fifo.CPReadPointer = fifo.CPBase; fifo.CPReadPointer = fifo.CPBase;
LOG(COMMANDPROCESSOR, "BUFFER LOOP"); LOG(COMMANDPROCESSOR, "BUFFER LOOP");
// MessageBox(NULL, "loop", "now", MB_OK); // PanicAlert("loop now");
} }
} }
} }
} }
// __________________________________________________________________________________________________
// UpdateFifoRegister
// It's no problem if the gfx falls behind a little bit. Better make sure to stop the cpu thread
// when the distance is way huge, though.
// So:
// CPU thread
/// 0. Write data (done before entering this)
// 1. Compute distance
// 2. If distance > threshold, sleep and goto 1
// GPU thread
// 1. Compute distance
// 2. If distance < threshold, sleep and goto 1 (or wait for trigger?)
// 3. Read and use a bit of data, goto 1
void UpdateFifoRegister()
{
// update the distance
#ifdef _WIN32
if (Core::g_CoreStartupParameter.bUseDualCore) EnterCriticalSection(&fifo.sync);
#endif
int wp = fifo.CPWritePointer;
int rp = fifo.CPReadPointer;
if (wp >= rp)
fifo.CPReadWriteDistance = wp - rp;
else
fifo.CPReadWriteDistance = (wp - fifo.CPBase) +
(fifo.CPEnd - rp);
#ifdef _WIN32
if (Core::g_CoreStartupParameter.bUseDualCore) LeaveCriticalSection(&fifo.sync);
#endif
// if (!Core::g_CoreStartupParameter.bUseDualCore) CatchUpGPU();
} }
void UpdateInterrupts() void UpdateInterrupts()

View File

@ -87,6 +87,7 @@ void HWCALL Read32(u32& _rReturnValue, const u32 _Address);
void HWCALL Write32(const u32 _Data, const u32 _Address); void HWCALL Write32(const u32 _Data, const u32 _Address);
// for CGPFIFO // for CGPFIFO
void CatchUpGPU();
void GatherPipeBursted(); void GatherPipeBursted();
void UpdateInterrupts(); void UpdateInterrupts();
void UpdateInterruptsFromVideoPlugin(); void UpdateInterruptsFromVideoPlugin();

View File

@ -23,6 +23,7 @@
#include "../HW/DSP.h" #include "../HW/DSP.h"
#include "../HW/AudioInterface.h" #include "../HW/AudioInterface.h"
#include "../HW/VideoInterface.h" #include "../HW/VideoInterface.h"
#include "../HW/CommandProcessor.h"
#include "../HW/SerialInterface.h" #include "../HW/SerialInterface.h"
#include "../PowerPC/PowerPC.h" #include "../PowerPC/PowerPC.h"
#include "../CoreTiming.h" #include "../CoreTiming.h"
@ -59,8 +60,8 @@ int
AI_PERIOD = GetTicksPerSecond() / 80, AI_PERIOD = GetTicksPerSecond() / 80,
DSP_PERIOD = GetTicksPerSecond() / 250, DSP_PERIOD = GetTicksPerSecond() / 250,
DSPINT_PERIOD = GetTicksPerSecond() / 230, DSPINT_PERIOD = GetTicksPerSecond() / 230,
HLE_IPC_PERIOD = GetTicksPerSecond() / 250; HLE_IPC_PERIOD = GetTicksPerSecond() / 250,
GPU_PERIOD = 10000;
u32 GetTicksPerSecond() u32 GetTicksPerSecond()
{ {
@ -84,7 +85,6 @@ void IPC_HLE_UpdateCallback(u64 userdata, int cyclesLate)
CoreTiming::ScheduleEvent(HLE_IPC_PERIOD-cyclesLate, &IPC_HLE_UpdateCallback, "IPC_HLE_UpdateCallback"); CoreTiming::ScheduleEvent(HLE_IPC_PERIOD-cyclesLate, &IPC_HLE_UpdateCallback, "IPC_HLE_UpdateCallback");
} }
void VICallback(u64 userdata, int cyclesLate) void VICallback(u64 userdata, int cyclesLate)
{ {
VideoInterface::Update(); VideoInterface::Update();
@ -112,7 +112,6 @@ void DSPInterruptCallback(u64 userdata, int cyclesLate)
CoreTiming::ScheduleEvent(DSPINT_PERIOD-cyclesLate, &DSPInterruptCallback, "DSPInterruptCallback"); CoreTiming::ScheduleEvent(DSPINT_PERIOD-cyclesLate, &DSPInterruptCallback, "DSPInterruptCallback");
} }
void DecrementerCallback(u64 userdata, int cyclesLate) void DecrementerCallback(u64 userdata, int cyclesLate)
{ {
//Why is fakeDec too big here? //Why is fakeDec too big here?
@ -121,7 +120,6 @@ void DecrementerCallback(u64 userdata, int cyclesLate)
PowerPC::ppcState.Exceptions |= EXCEPTION_DECREMENTER; PowerPC::ppcState.Exceptions |= EXCEPTION_DECREMENTER;
} }
void DecrementerSet() void DecrementerSet()
{ {
// MessageBox(0, "dec set",0,0); // MessageBox(0, "dec set",0,0);
@ -143,6 +141,11 @@ void AdvanceCallback(int cyclesExecuted)
PowerPC::ppcState.spr[SPR_DEC] = (u32)fakeDec / TIMER_RATIO; PowerPC::ppcState.spr[SPR_DEC] = (u32)fakeDec / TIMER_RATIO;
} }
void RunGPUCallback(u64 userdata, int cyclesLate)
{
CommandProcessor::CatchUpGPU();
CoreTiming::ScheduleEvent(GPU_PERIOD-cyclesLate, &RunGPUCallback, "RunGPUCallback");
}
// TODO(ector): improve, by using a more accurate timer // TODO(ector): improve, by using a more accurate timer
// calculate the timing over the past 7 frames // calculate the timing over the past 7 frames
@ -215,6 +218,9 @@ void Init()
CoreTiming::ScheduleEvent(SI_PERIOD, &SICallback, "SICallback"); CoreTiming::ScheduleEvent(SI_PERIOD, &SICallback, "SICallback");
CoreTiming::ScheduleEvent(DSPINT_PERIOD, &DSPInterruptCallback, "DSPInterruptCallback"); CoreTiming::ScheduleEvent(DSPINT_PERIOD, &DSPInterruptCallback, "DSPInterruptCallback");
if (!Core::GetStartupParameter().bUseDualCore)
CoreTiming::ScheduleEvent(GPU_PERIOD, &RunGPUCallback, "RunGPUCallback");
if (Core::GetStartupParameter().bWii) if (Core::GetStartupParameter().bWii)
{ {
CoreTiming::ScheduleEvent(HLE_IPC_PERIOD, &IPC_HLE_UpdateCallback, "IPC_HLE_UpdateCallback"); CoreTiming::ScheduleEvent(HLE_IPC_PERIOD, &IPC_HLE_UpdateCallback, "IPC_HLE_UpdateCallback");