ReorderingMTGS: Some cleanups and minor fixes to thread benching.

git-svn-id: http://pcsx2.googlecode.com/svn/branches/ReorderingMTGS@3478 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2010-07-13 16:34:27 +00:00
parent d1e0922417
commit 168a60ad13
3 changed files with 33 additions and 68 deletions

View File

@ -256,9 +256,9 @@ __forceinline void memcpy_amd_qwc(void *dest, const void *src, size_t qwc)
__asm __asm
{ {
mov ecx, [dest] mov ecx, dest
mov edx, [src] mov edx, src
mov eax, [qwc] ; keep a copy of count mov eax, qwc ; keep a copy of count
shr eax, 1 shr eax, 1
jz $memcpy_qwc_1 ; only one 16 byte block to copy? jz $memcpy_qwc_1 ; only one 16 byte block to copy?
@ -306,7 +306,7 @@ $memcpy_qwc_loop1:
jnz $memcpy_qwc_loop1 ; last 64-byte block? jnz $memcpy_qwc_loop1 ; last 64-byte block?
$memcpy_qwc_1: $memcpy_qwc_1:
test [qwc],1 test qwc,1
jz $memcpy_qwc_final jz $memcpy_qwc_final
movq mm0,[edx] movq mm0,[edx]
movq mm1,[edx+8] movq mm1,[edx+8]

View File

@ -258,7 +258,6 @@ enum MTGS_RingCommand
GS_RINGTYPE_P1 GS_RINGTYPE_P1
, GS_RINGTYPE_P2 , GS_RINGTYPE_P2
, GS_RINGTYPE_P3 , GS_RINGTYPE_P3
, GS_RINGTYPE_RESTART
, GS_RINGTYPE_VSYNC , GS_RINGTYPE_VSYNC
, GS_RINGTYPE_FRAMESKIP , GS_RINGTYPE_FRAMESKIP
, GS_RINGTYPE_FREEZE , GS_RINGTYPE_FREEZE
@ -291,10 +290,12 @@ public:
volatile u32 m_SignalRingEnable; volatile u32 m_SignalRingEnable;
volatile s32 m_SignalRingPosition; volatile s32 m_SignalRingPosition;
int m_QueuedFrameCount; volatile s32 m_QueuedFrameCount;
volatile u32 m_VsyncSignalListener;
Mutex m_lock_RingBufferBusy; Mutex m_mtx_RingBufferBusy;
Semaphore m_sem_OnRingReset; Semaphore m_sem_OnRingReset;
Semaphore m_sem_Vsync;
// used to keep multiple threads from sending packets to the ringbuffer concurrently. // used to keep multiple threads from sending packets to the ringbuffer concurrently.
// (currently not used or implemented -- is a planned feature for a future threaded VU1) // (currently not used or implemented -- is a planned feature for a future threaded VU1)

View File

@ -77,6 +77,7 @@ void SysMtgsThread::OnStart()
m_packet_ringpos = 0; m_packet_ringpos = 0;
m_QueuedFrameCount = 0; m_QueuedFrameCount = 0;
m_VsyncSignalListener = false;
m_SignalRingEnable = 0; m_SignalRingEnable = 0;
m_SignalRingPosition= 0; m_SignalRingPosition= 0;
@ -106,6 +107,7 @@ void SysMtgsThread::ResetGS()
m_RingPos = m_WritePos; m_RingPos = m_WritePos;
m_QueuedFrameCount = 0; m_QueuedFrameCount = 0;
m_VsyncSignalListener = false;
MTGS_LOG( "MTGS: Sending Reset..." ); MTGS_LOG( "MTGS: Sending Reset..." );
SendSimplePacket( GS_RINGTYPE_RESET, 0, 0, 0 ); SendSimplePacket( GS_RINGTYPE_RESET, 0, 0, 0 );
@ -142,33 +144,19 @@ void SysMtgsThread::PostVsyncEnd()
SendDataPacket(); SendDataPacket();
// Vsyncs should always start the GS thread, regardless of how little has actually be queued.
if (m_CopyDataTally != 0) SetEvent();
// If the MTGS is allowed to queue a lot of frames in advance, it creates input lag. // If the MTGS is allowed to queue a lot of frames in advance, it creates input lag.
// Use the Queued FrameCount to stall the EE if another vsync is already queued in // Use the Queued FrameCount to stall the EE if another vsync (or two) are already queued
// the ringbuffer. // in the ringbuffer. The queue limit is disabled when FrameLimiting is disabled, since
// the queue can have perverse effects on framerate benchmarking.
if( AtomicIncrement(m_QueuedFrameCount) < EmuConfig.GS.VsyncQueueSize ) return; if ((AtomicIncrement(m_QueuedFrameCount) < EmuConfig.GS.VsyncQueueSize) || !EmuConfig.GS.FrameLimitEnable) return;
uint readpos = volatize(m_RingPos); m_VsyncSignalListener = true;
uint freeroom; //Console.WriteLn( Color_Blue, "(EEcore Sleep) Vsync\t\tringpos=0x%06x, writepos=0x%06x", volatize(m_RingPos), m_WritePos );
m_sem_Vsync.WaitNoCancel();
if (m_WritePos < readpos)
freeroom = readpos - m_WritePos;
else
freeroom = RingBufferSize - (m_WritePos - readpos);
uint totalAccum = RingBufferSize - freeroom;
uint somedone = totalAccum / 4;
m_SignalRingPosition = totalAccum;
//Console.WriteLn( Color_Blue, "(EEcore Sleep) Vsync\tringpos=0x%06x, writepos=0x%06x, signalpos=0x%06x", readpos, m_WritePos, m_SignalRingPosition );
AtomicExchange( m_SignalRingEnable, 1 );
SetEvent();
m_sem_OnRingReset.WaitWithoutYield();
readpos = volatize(m_RingPos);
pxAssertDev( m_SignalRingPosition <= 0, "MTGS Thread Synchronization Error" );
} }
struct PacketTagType struct PacketTagType
@ -256,7 +244,7 @@ protected:
public: public:
RingBufferLock( SysMtgsThread& mtgs ) RingBufferLock( SysMtgsThread& mtgs )
: ScopedLock( mtgs.m_lock_RingBufferBusy ) : ScopedLock( mtgs.m_mtx_RingBufferBusy )
, m_mtgs( mtgs ) , m_mtgs( mtgs )
{ {
m_mtgs.m_RingBufferIsBusy = true; m_mtgs.m_RingBufferIsBusy = true;
@ -397,11 +385,6 @@ void SysMtgsThread::ExecuteTaskInThread()
{ {
switch( tag.command ) switch( tag.command )
{ {
case GS_RINGTYPE_RESTART:
//MTGS_LOG( "(MTGS Packet Read) ringtype=Restart" );
m_RingPos = 0;
continue;
case GS_RINGTYPE_VSYNC: case GS_RINGTYPE_VSYNC:
{ {
const int qsize = tag.data[0]; const int qsize = tag.data[0];
@ -426,7 +409,12 @@ void SysMtgsThread::ExecuteTaskInThread()
PADupdate(0); PADupdate(0);
AtomicDecrement( m_QueuedFrameCount ); AtomicDecrement( m_QueuedFrameCount );
if (!!AtomicExchange(m_VsyncSignalListener, false))
m_sem_Vsync.Post();
busy.Release();
StateCheckInThread(); StateCheckInThread();
busy.Acquire();
} }
break; break;
@ -512,6 +500,9 @@ void SysMtgsThread::ExecuteTaskInThread()
m_sem_OnRingReset.Post(); m_sem_OnRingReset.Post();
} }
if (!!AtomicExchange(m_VsyncSignalListener, false))
m_sem_Vsync.Post();
//Console.Warning( "(MTGS Thread) Nothing to do! ringpos=0x%06x", m_RingPos ); //Console.Warning( "(MTGS Thread) Nothing to do! ringpos=0x%06x", m_RingPos );
} }
} }
@ -558,7 +549,7 @@ void SysMtgsThread::WaitGS()
RethrowException(); RethrowException();
do { do {
m_lock_RingBufferBusy.Wait(); m_mtx_RingBufferBusy.Wait();
RethrowException(); RethrowException();
} while( volatize(m_RingPos) != m_WritePos ); } while( volatize(m_RingPos) != m_WritePos );
} }
@ -588,32 +579,6 @@ void SysMtgsThread::SendDataPacket()
// make sure a previous copy block has been started somewhere. // make sure a previous copy block has been started somewhere.
pxAssert( m_packet_size != 0 ); pxAssert( m_packet_size != 0 );
#if 0
uint temp = m_packet_ringpos + m_packet_size;
pxAssert( temp <= RingBufferSize );
temp &= RingBufferMask;
if( IsDebugBuild )
{
if( m_packet_ringpos + m_packet_size < RingBufferSize )
{
uint readpos = volatize(m_RingPos);
if( readpos != m_WritePos )
{
// The writepos should never leapfrog the readpos
// since that indicates a bad write.
if( m_packet_ringpos < readpos )
pxAssert( temp < readpos );
}
// Updating the writepos should never make it equal the readpos, since
// that would stop the buffer prematurely (and indicates bad code in the
// ringbuffer manager)
pxAssert( readpos != temp );
}
}
#endif
uint actualSize = ((m_packet_ringpos - m_packet_startpos) & RingBufferMask)-1; uint actualSize = ((m_packet_ringpos - m_packet_startpos) & RingBufferMask)-1;
pxAssert( actualSize <= m_packet_size ); pxAssert( actualSize <= m_packet_size );
pxAssert( m_packet_ringpos < RingBufferSize ); pxAssert( m_packet_ringpos < RingBufferSize );
@ -621,7 +586,6 @@ void SysMtgsThread::SendDataPacket()
PacketTagType& tag = (PacketTagType&)RingBuffer[m_packet_startpos]; PacketTagType& tag = (PacketTagType&)RingBuffer[m_packet_startpos];
tag.data[0] = actualSize; tag.data[0] = actualSize;
//Threading::StoreFence();
m_WritePos = m_packet_ringpos; m_WritePos = m_packet_ringpos;
if( EmuConfig.GS.SynchronousMTGS ) if( EmuConfig.GS.SynchronousMTGS )