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]; data[1] = value[1];
GSgifTransferDummy(2, (u32*)data, 1); GSgifTransferDummy(2, (u32*)data, 1);
GSRINGBUF_DONECOPY((u8*)data, 16); 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 { else {
FreezeXMMRegs(1); 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() void gsShutdown()
{ {
if( CHECK_MULTIGS ) { if( CHECK_MULTIGS ) {
@ -310,80 +323,88 @@ u8* GSRingBufCopy(void* mem, u32 size, u32 type)
// is reading it. // is reading it.
u8* writepos = g_pGSWritePos; u8* writepos = g_pGSWritePos;
u8* tempbuf;
assert( size < GS_RINGBUFFERSIZE ); assert( size < GS_RINGBUFFERSIZE );
assert( writepos < GS_RINGBUFFEREND ); assert( writepos < GS_RINGBUFFEREND );
assert( ((uptr)writepos & 15) == 0 ); assert( ((uptr)writepos & 15) == 0 );
assert( (size&15) == 0); assert( (size&15) == 0);
size += 16; 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 // We have to be careful not to leapfrog our readposition. If it's
while( writepos < tempbuf || tempbuf == GS_RINGBUFFERBASE ) { // 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(); gsSetEventWait();
tempbuf = *(volatile PU8*)&g_pGSRingPos;
}
// notify GS GSRingBufSimplePacket( GS_RINGTYPE_RESTART, 0, 0, 0 );
if( writepos != GS_RINGBUFFEREND ) {
InterlockedExchangePointer((void**)writepos, GS_RINGTYPE_RESTART); 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); InterlockedExchangePointer((void**)&g_pGSWritePos, GS_RINGBUFFERBASE);
writepos = GS_RINGBUFFERBASE;
} }
else if( writepos + size == GS_RINGBUFFEREND ) { else if( writepos + size == GS_RINGBUFFEREND )
while(tempbuf == GS_RINGBUFFERBASE && tempbuf != writepos) { {
gsSetEventWait(); // Yay. Perfect fit. What are the odds?
tempbuf = *(volatile PU8*)&g_pGSRingPos; // ... 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)) ) { while( writepos < *(volatile PU8*)&g_pGSRingPos )
gsSetEventWait(); gsSetEventWait();
tempbuf = *(volatile PU8*)&g_pGSRingPos; }
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 // just copy
*(u32*)writepos = type|(((size-16)>>4)<<16); *(u32*)writepos = type | (((size-16)>>4)<<16);
return writepos+16; return writepos+16;
} }
void GSRingBufSimplePacket(int type, int data0, int data1, int data2) void GSRingBufSimplePacket(int type, int data0, int data1, int data2)
{ {
u8* writepos = g_pGSWritePos; 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; if( future_writepos == GS_RINGBUFFEREND )
while(writepos < tempbuf && writepos+16 >= tempbuf ) { future_writepos = GS_RINGBUFFERBASE;
while( future_writepos == *(volatile PU8*)&g_pGSRingPos )
gsSetEventWait(); gsSetEventWait();
tempbuf = *(volatile PU8*)&g_pGSRingPos;
}
*(u32*)writepos = type; *(u32*)writepos = type;
*(u32*)(writepos+4) = data0; *(u32*)(writepos+4) = data0;
*(u32*)(writepos+8) = data1; *(u32*)(writepos+8) = data1;
*(u32*)(writepos+12) = data2; *(u32*)(writepos+12) = data2;
writepos += 16; InterlockedExchangePointer((void**)&g_pGSWritePos, future_writepos);
if( writepos == GS_RINGBUFFEREND ) {
while(tempbuf == GS_RINGBUFFERBASE && tempbuf != g_pGSWritePos) { if( !CHECK_DUALCORE )
gsSetEventWait();
tempbuf = *(volatile PU8*)&g_pGSRingPos;
}
writepos = GS_RINGBUFFERBASE;
}
InterlockedExchangePointer((void**)&g_pGSWritePos, writepos);
if( !CHECK_DUALCORE ) {
GS_SETEVENT(); GS_SETEVENT();
}
} }
void gsReset() void gsReset()
@ -939,8 +960,6 @@ static __forceinline void WRITERING_DMA(u32 *pMem, u32 qwc) {
GSRINGBUF_DONECOPY(pgsmem, sizetoread); GSRINGBUF_DONECOPY(pgsmem, sizetoread);
GSgifTransferDummy(2, pMem, qwc); GSgifTransferDummy(2, pMem, qwc);
} }
if( !CHECK_DUALCORE ) GS_SETEVENT();
} }
else { else {
GSGIFTRANSFER3(pMem, qwc); GSGIFTRANSFER3(pMem, qwc);
@ -1500,7 +1519,8 @@ void* GSThreadProc(void* lpParam)
break; break;
case GS_RINGTYPE_FRAMESKIP: case GS_RINGTYPE_FRAMESKIP:
GSsetFrameSkip(*(int*)(g_pGSRingPos+4)); if( GSsetFrameSkip != NULL )
GSsetFrameSkip(*(int*)(g_pGSRingPos+4));
break; break;
case GS_RINGTYPE_MEMWRITE8: case GS_RINGTYPE_MEMWRITE8:
g_MTGSMem[*(int*)(g_pGSRingPos+4)] = *(u8*)(g_pGSRingPos+8); g_MTGSMem[*(int*)(g_pGSRingPos+4)] = *(u8*)(g_pGSRingPos+8);

View File

@ -97,15 +97,6 @@ extern u8* g_pGSWritePos;
//#endif //#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) #if defined(_WIN32) && !defined(WIN32_PTHREADS)
#define GS_SETEVENT() SetEvent(g_hGsEvent) #define GS_SETEVENT() SetEvent(g_hGsEvent)
@ -125,6 +116,8 @@ void gsInit();
void gsShutdown(); void gsShutdown();
void gsReset(); void gsReset();
// mem and size are the ones from GSRingBufCopy
extern void GSRINGBUF_DONECOPY(const u8 *mem, u32 size);
extern void gsWaitGS(); extern void gsWaitGS();
// used for resetting GIF fifo // used for resetting GIF fifo

View File

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

View File

@ -1668,11 +1668,10 @@ static int Vif1TransDirectHL(u32 *data){
if( gsmem != NULL ) { if( gsmem != NULL ) {
FreezeMMXRegs(1); FreezeMMXRegs(1);
memcpy_fast(gsmem, (u32*)splittransfer[0], 16); memcpy_fast(gsmem, (u32*)splittransfer[0], 16);
FreezeMMXRegs(0);
GSRINGBUF_DONECOPY(gsmem, 16); GSRINGBUF_DONECOPY(gsmem, 16);
GSgifTransferDummy(1, (u32*)splittransfer[0], 1); GSgifTransferDummy(1, (u32*)splittransfer[0], 1);
} }
FreezeMMXRegs(0);
if( !CHECK_DUALCORE ) GS_SETEVENT();
} }
else { else {
FreezeXMMRegs(1); FreezeXMMRegs(1);
@ -1718,8 +1717,6 @@ static int Vif1TransDirectHL(u32 *data){
GSRINGBUF_DONECOPY(gsmem, ret<<2); GSRINGBUF_DONECOPY(gsmem, ret<<2);
GSgifTransferDummy(1, data, ret>>2); GSgifTransferDummy(1, data, ret>>2);
} }
if( !CHECK_DUALCORE ) GS_SETEVENT();
} }
else { else {
@ -2331,9 +2328,6 @@ void dmaVIF1()
GSRINGBUF_DONECOPY(pMem, 0); GSRINGBUF_DONECOPY(pMem, 0);
if( !CHECK_DUALCORE )
GS_SETEVENT();
g_MTGSVifStart = cpuRegs.cycle; g_MTGSVifStart = cpuRegs.cycle;
g_MTGSVifCount = 4000000; // a little less than 1/60th of a second 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); FreezeMMXRegs(0);
GSRINGBUF_DONECOPY(pmem, size); GSRINGBUF_DONECOPY(pmem, size);
if( !CHECK_DUALCORE ) {
#if defined(_WIN32) && !defined(WIN32_PTHREADS)
SetEvent(g_hGsEvent);
#else
pthread_cond_signal(&g_condGsEvent);
#endif
}
} }
} }