mirror of https://github.com/PCSX2/pcsx2.git
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:
parent
2f08ff5e70
commit
2f23574430
|
@ -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);
|
||||
|
|
112
pcsx2/GS.cpp
112
pcsx2/GS.cpp
|
@ -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 ) {
|
||||
|
||||
// skip to beginning
|
||||
while( writepos < tempbuf || tempbuf == GS_RINGBUFFERBASE ) {
|
||||
gsSetEventWait();
|
||||
tempbuf = *(volatile PU8*)&g_pGSRingPos;
|
||||
}
|
||||
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).
|
||||
|
||||
// notify GS
|
||||
if( writepos != GS_RINGBUFFEREND ) {
|
||||
InterlockedExchangePointer((void**)writepos, GS_RINGTYPE_RESTART);
|
||||
}
|
||||
// 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();
|
||||
|
||||
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 ) {
|
||||
|
||||
while(tempbuf == GS_RINGBUFFERBASE && tempbuf != g_pGSWritePos) {
|
||||
gsSetEventWait();
|
||||
tempbuf = *(volatile PU8*)&g_pGSRingPos;
|
||||
}
|
||||
InterlockedExchangePointer((void**)&g_pGSWritePos, future_writepos);
|
||||
|
||||
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);
|
||||
|
|
11
pcsx2/GS.h
11
pcsx2/GS.h
|
@ -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
|
||||
|
|
35
pcsx2/Misc.c
35
pcsx2/Misc.c
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue