More MTGS improvements and cleanups. I actually changed some of how the MTGS ring buffer is managed this time, so it might introduce some bugs (lets hope not!).

Removed the SPU2timestretch auto-enable/disable code.  Also added checks for frameskipping support to the F4 keypress (just in case).

git-svn-id: http://pcsx2-playground.googlecode.com/svn/trunk@344 a6443dda-0b58-4228-96e9-037be469359c
This commit is contained in:
Jake.Stine 2008-11-19 18:23:05 +00:00 committed by Gregory Hainaut
parent 2f08ff5e70
commit 2f23574430
6 changed files with 89 additions and 93 deletions

View File

@ -133,14 +133,6 @@ void WriteFIFO(u32 mem, u64 *value) {
data[1] = value[1];
GSgifTransferDummy(2, (u32*)data, 1);
GSRINGBUF_DONECOPY((u8*)data, 16);
if( !CHECK_DUALCORE ) {
#if defined(_WIN32) && !defined(WIN32_PTHREADS)
SetEvent(g_hGsEvent);
#else
pthread_cond_signal(&g_condGsEvent);
#endif
}
}
else {
FreezeXMMRegs(1);

View File

@ -253,6 +253,19 @@ static __forceinline void gsSetEventWait()
}
}
// mem and size are the ones from GSRingBufCopy
void GSRINGBUF_DONECOPY(const u8 *mem, u32 size)
{
u8* temp = (u8*)(mem) + (size);
assert( temp <= GS_RINGBUFFEREND);
if( temp == GS_RINGBUFFEREND ) temp = GS_RINGBUFFERBASE;
InterlockedExchangePointer((void**)&g_pGSWritePos, temp);
if( !CHECK_DUALCORE ) GS_SETEVENT();
}
void gsShutdown()
{
if( CHECK_MULTIGS ) {
@ -310,80 +323,88 @@ u8* GSRingBufCopy(void* mem, u32 size, u32 type)
// is reading it.
u8* writepos = g_pGSWritePos;
u8* tempbuf;
assert( size < GS_RINGBUFFERSIZE );
assert( writepos < GS_RINGBUFFEREND );
assert( ((uptr)writepos & 15) == 0 );
assert( (size&15) == 0);
size += 16;
tempbuf = *(volatile PU8*)&g_pGSRingPos;
if( writepos + size > GS_RINGBUFFEREND ) {
if( writepos + size > GS_RINGBUFFEREND )
{
// If the incoming packet doesn't fit, then start over from
// the start of the ring buffer (it's a lot easier than trying
// to wrap the packet around the end of the buffer).
// skip to beginning
while( writepos < tempbuf || tempbuf == GS_RINGBUFFERBASE ) {
// We have to be careful not to leapfrog our readposition. If it's
// greater than the current write position then we need to stall
// until it loops around:
//const u8* readps = *(volatile PU8*)&g_pGSRingPos;
while( *(volatile PU8*)&g_pGSRingPos > writepos ) // && readpos == GS_RINGBUFFERBASE )
gsSetEventWait();
tempbuf = *(volatile PU8*)&g_pGSRingPos;
}
// notify GS
if( writepos != GS_RINGBUFFEREND ) {
InterlockedExchangePointer((void**)writepos, GS_RINGTYPE_RESTART);
}
GSRingBufSimplePacket( GS_RINGTYPE_RESTART, 0, 0, 0 );
writepos = GS_RINGBUFFERBASE;
// stall until the read position is past the end of our incoming block:
while( writepos+size >= *(volatile PU8*)&g_pGSRingPos )
gsSetEventWait();
InterlockedExchangePointer((void**)&g_pGSWritePos, GS_RINGBUFFERBASE);
writepos = GS_RINGBUFFERBASE;
}
else if( writepos + size == GS_RINGBUFFEREND ) {
while(tempbuf == GS_RINGBUFFERBASE && tempbuf != writepos) {
gsSetEventWait();
tempbuf = *(volatile PU8*)&g_pGSRingPos;
}
}
else if( writepos + size == GS_RINGBUFFEREND )
{
// Yay. Perfect fit. What are the odds?
// ... apparently very slim because the old code just performed the equivalent
// of a gsWaitGS (stalling the GS until the ring buffer emptied completely) and
// no one noticed enough to fix it. :)
while( writepos < tempbuf && (writepos+size >= tempbuf || (writepos+size == GS_RINGBUFFEREND && tempbuf == GS_RINGBUFFERBASE)) ) {
gsSetEventWait();
tempbuf = *(volatile PU8*)&g_pGSRingPos;
while( writepos < *(volatile PU8*)&g_pGSRingPos )
gsSetEventWait();
}
else
{
// two conditionals in the following while() loop, so precache
// the readpos for more efficient behavior:
const u8* readpos = *(volatile PU8*)&g_pGSRingPos;
// generic gs wait/stall.
// Waits until the readpos is outside the scope of the write area.
while( writepos < readpos && writepos+size >= readpos ) // || (writepos+size == GS_RINGBUFFEREND && readpos == GS_RINGBUFFERBASE)) ) {
{
gsSetEventWait();
readpos = *(volatile PU8*)&g_pGSRingPos;
}
}
// just copy
*(u32*)writepos = type|(((size-16)>>4)<<16);
*(u32*)writepos = type | (((size-16)>>4)<<16);
return writepos+16;
}
void GSRingBufSimplePacket(int type, int data0, int data1, int data2)
{
u8* writepos = g_pGSWritePos;
u8* tempbuf;
u8* future_writepos = writepos+16;
assert( writepos + 16 <= GS_RINGBUFFEREND );
assert( future_writepos <= GS_RINGBUFFEREND );
tempbuf = *(volatile PU8*)&g_pGSRingPos;
while(writepos < tempbuf && writepos+16 >= tempbuf ) {
if( future_writepos == GS_RINGBUFFEREND )
future_writepos = GS_RINGBUFFERBASE;
while( future_writepos == *(volatile PU8*)&g_pGSRingPos )
gsSetEventWait();
tempbuf = *(volatile PU8*)&g_pGSRingPos;
}
*(u32*)writepos = type;
*(u32*)(writepos+4) = data0;
*(u32*)(writepos+8) = data1;
*(u32*)(writepos+12) = data2;
writepos += 16;
if( writepos == GS_RINGBUFFEREND ) {
InterlockedExchangePointer((void**)&g_pGSWritePos, future_writepos);
while(tempbuf == GS_RINGBUFFERBASE && tempbuf != g_pGSWritePos) {
gsSetEventWait();
tempbuf = *(volatile PU8*)&g_pGSRingPos;
}
writepos = GS_RINGBUFFERBASE;
}
InterlockedExchangePointer((void**)&g_pGSWritePos, writepos);
if( !CHECK_DUALCORE ) {
if( !CHECK_DUALCORE )
GS_SETEVENT();
}
}
void gsReset()
@ -939,8 +960,6 @@ static __forceinline void WRITERING_DMA(u32 *pMem, u32 qwc) {
GSRINGBUF_DONECOPY(pgsmem, sizetoread);
GSgifTransferDummy(2, pMem, qwc);
}
if( !CHECK_DUALCORE ) GS_SETEVENT();
}
else {
GSGIFTRANSFER3(pMem, qwc);
@ -1500,7 +1519,8 @@ void* GSThreadProc(void* lpParam)
break;
case GS_RINGTYPE_FRAMESKIP:
GSsetFrameSkip(*(int*)(g_pGSRingPos+4));
if( GSsetFrameSkip != NULL )
GSsetFrameSkip(*(int*)(g_pGSRingPos+4));
break;
case GS_RINGTYPE_MEMWRITE8:
g_MTGSMem[*(int*)(g_pGSRingPos+4)] = *(u8*)(g_pGSRingPos+8);

View File

@ -97,15 +97,6 @@ extern u8* g_pGSWritePos;
//#endif
// mem and size are the ones from GSRingBufCopy
static __forceinline void GSRINGBUF_DONECOPY(const u8 *mem, u32 size) {
u8* temp = (u8*)(mem) + (size);
assert( temp <= GS_RINGBUFFEREND);
// MTGS_RECWRITE(mem, size);
if( temp == GS_RINGBUFFEREND ) temp = GS_RINGBUFFERBASE;
InterlockedExchangePointer((void**)&g_pGSWritePos, temp);
}
#if defined(_WIN32) && !defined(WIN32_PTHREADS)
#define GS_SETEVENT() SetEvent(g_hGsEvent)
@ -125,6 +116,8 @@ void gsInit();
void gsShutdown();
void gsReset();
// mem and size are the ones from GSRingBufCopy
extern void GSRINGBUF_DONECOPY(const u8 *mem, u32 size);
extern void gsWaitGS();
// used for resetting GIF fifo

View File

@ -863,7 +863,8 @@ void ProcessFKeys(int fkey, int shift)
break;
case 4:
{
const char* limitMsg;
#ifdef PCSX2_NORECBUILD
SysPrintf("frame skipping only valid for recompiler build\n");
#else
@ -882,33 +883,37 @@ void ProcessFKeys(int fkey, int shift)
if( CHECK_MULTIGS ) GSRingBufSimplePacket(GS_RINGTYPE_FRAMESKIP, 0, 0, 0);
else GSsetFrameSkip(0);
Cpu->ExecuteVU1Block = recExecuteVU1Block;
if(SPU2setTimeStretcher != NULL)
SPU2setTimeStretcher(1);
SysPrintf("Normal - Frame Limit Mode Changed\n");
limitMsg = "None/Normal";
break;
case PCSX2_FRAMELIMIT_LIMIT:
if( CHECK_MULTIGS ) GSRingBufSimplePacket(GS_RINGTYPE_FRAMESKIP, 0, 0, 0);
else GSsetFrameSkip(0);
Cpu->ExecuteVU1Block = recExecuteVU1Block;
//Quality option, turn off timestretching on the SPU2 plugin
if(SPU2setTimeStretcher != NULL)
SPU2setTimeStretcher(0);
SysPrintf("Limit - Frame Limit Mode Changed\n");
limitMsg = "Limit";
break;
case PCSX2_FRAMELIMIT_SKIP:
Cpu->ExecuteVU1Block = recExecuteVU1Block;
if(SPU2setTimeStretcher != NULL)
SPU2setTimeStretcher(1);
SysPrintf("Frame Skip - Frame Limit Mode Changed\n");
break;
case PCSX2_FRAMELIMIT_VUSKIP:
if(SPU2setTimeStretcher != NULL)
SPU2setTimeStretcher(1);
SysPrintf("VU Skip - Frame Limit Mode Changed\n");
if( GSsetFrameSkip == NULL )
{
Config.Options &= ~PCSX2_FRAMELIMIT_MASK;
SysPrintf("Notice: GS Plugin does not support frameskipping.\n");
limitMsg = "None/Normal";
}
else
{
limitMsg = (CHECK_FRAMELIMIT == PCSX2_FRAMELIMIT_SKIP) ? "Skip" : "VUSkip";
}
break;
}
SysPrintf("Frame Limit Mode Changed: %s\n", limitMsg );
// [Air]: Do we really want to save runtime changes to frameskipping?
//SaveConfig();
//SaveConfig();
}
#endif
break;
// note: VK_F5-VK_F7 are reserved for GS

View File

@ -1668,11 +1668,10 @@ static int Vif1TransDirectHL(u32 *data){
if( gsmem != NULL ) {
FreezeMMXRegs(1);
memcpy_fast(gsmem, (u32*)splittransfer[0], 16);
FreezeMMXRegs(0);
GSRINGBUF_DONECOPY(gsmem, 16);
GSgifTransferDummy(1, (u32*)splittransfer[0], 1);
}
FreezeMMXRegs(0);
if( !CHECK_DUALCORE ) GS_SETEVENT();
}
else {
FreezeXMMRegs(1);
@ -1718,8 +1717,6 @@ static int Vif1TransDirectHL(u32 *data){
GSRINGBUF_DONECOPY(gsmem, ret<<2);
GSgifTransferDummy(1, data, ret>>2);
}
if( !CHECK_DUALCORE ) GS_SETEVENT();
}
else {
@ -2331,9 +2328,6 @@ void dmaVIF1()
GSRINGBUF_DONECOPY(pMem, 0);
if( !CHECK_DUALCORE )
GS_SETEVENT();
g_MTGSVifStart = cpuRegs.cycle;
g_MTGSVifCount = 4000000; // a little less than 1/60th of a second

View File

@ -5633,14 +5633,6 @@ void VU1XGKICK_MTGSTransfer(u32 *pMem, u32 addr)
FreezeMMXRegs(0);
GSRINGBUF_DONECOPY(pmem, size);
if( !CHECK_DUALCORE ) {
#if defined(_WIN32) && !defined(WIN32_PTHREADS)
SetEvent(g_hGsEvent);
#else
pthread_cond_signal(&g_condGsEvent);
#endif
}
}
}