Skip to content

Commit ac9bf45

Browse files
author
cottonvibes
committed
pcsx2: Implemented Threaded VU1 :D
Threading VU1 took a lot of rewrites and new code to make possible (MTGS, microVU, gifUnit...), but we finally got to the point where it was feasible, and now we've done it! (so now everyone can stop complaining that pcsx2 only takes advantages of 2 cores :p). The speedups in the games that benefit from it are great if you have a cpu with 3+ cores (generally a 10~45% speedup), however games that are GS limited can be a slowdown (especially on dual core cpu's). The option can be found in the speedhacks section as "MTVU (Multi-Threaded microVU1)". And when enabled it should should show the VU thread-time percentage on the title bar window (Like we currently do for EE/GS/UI threads). It is listed as a speedhack because in order for threading VU1 to have been a speedup, we need to assume that games will not send gif packets containing Signal/Finish/Label commands from path 1 (vu1's xgkick). The good news is very-few games ever do this, so the compatibility of MTVU is very high (a game that does do this will likely hang). Note: vs2010 builds and Linux builds need to be updated to include "MTVU.h" and "MTVU.cpp". git-svn-id: http://pcsx2.googlecode.com/svn/trunk@4865 96395faa-99c1-11dd-bbfe-3dabce05a288
1 parent 60cec5a commit ac9bf45

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+1180
-428
lines changed

common/include/Utilities/PageFaultSource.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -342,8 +342,8 @@ class SpatialArrayReserve : public BaseVmReserveListener
342342
struct _EXCEPTION_POINTERS;
343343
extern int SysPageFaultExceptionFilter(struct _EXCEPTION_POINTERS* eps);
344344

345-
# define PCSX2_PAGEFAULT_PROTECT __try
346-
# define PCSX2_PAGEFAULT_EXCEPT __except(SysPageFaultExceptionFilter(GetExceptionInformation())) {}
345+
# define PCSX2_PAGEFAULT_PROTECT __try
346+
# define PCSX2_PAGEFAULT_EXCEPT __except(SysPageFaultExceptionFilter(GetExceptionInformation())) {}
347347

348348
#else
349349
# error PCSX2 - Unsupported operating system platform.
@@ -352,5 +352,7 @@ extern int SysPageFaultExceptionFilter(struct _EXCEPTION_POINTERS* eps);
352352
extern void pxInstallSignalHandler();
353353
extern void _platform_InstallSignalHandler();
354354

355+
#include "Threading.h"
355356
extern SrcType_PageFault* Source_PageFault;
357+
extern Threading::Mutex PageFault_Mutex;
356358

common/include/Utilities/Threading.h

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,17 +179,20 @@ namespace Threading
179179
// from these little beasties! (these are all implemented internally using cross-platform
180180
// implementations of _InterlockedExchange and such)
181181

182+
extern u32 AtomicRead( volatile u32& Target );
183+
extern s32 AtomicRead( volatile s32& Target );
182184
extern u32 AtomicExchange( volatile u32& Target, u32 value );
183-
extern u32 AtomicExchangeAdd( volatile u32& Target, u32 value );
184-
extern u32 AtomicIncrement( volatile u32& Target );
185-
extern u32 AtomicDecrement( volatile u32& Target );
186185
extern s32 AtomicExchange( volatile s32& Target, s32 value );
186+
extern u32 AtomicExchangeAdd( volatile u32& Target, u32 value );
187187
extern s32 AtomicExchangeAdd( volatile s32& Target, s32 value );
188188
extern s32 AtomicExchangeSub( volatile s32& Target, s32 value );
189+
extern u32 AtomicIncrement( volatile u32& Target );
189190
extern s32 AtomicIncrement( volatile s32& Target );
191+
extern u32 AtomicDecrement( volatile u32& Target );
190192
extern s32 AtomicDecrement( volatile s32& Target );
191193

192194
extern bool AtomicBitTestAndReset( volatile u32& bitset, u8 bit );
195+
extern bool AtomicBitTestAndReset( volatile s32& bitset, u8 bit );
193196

194197
extern void* _AtomicExchangePointer( volatile uptr& target, uptr value );
195198
extern void* _AtomicCompareExchangePointer( volatile uptr& target, uptr value, uptr comparand );
@@ -393,5 +396,34 @@ namespace Threading
393396

394397
bool Failed() const { return !m_IsLocked; }
395398
};
399+
400+
// --------------------------------------------------------------------------------------
401+
// ScopedLockBool
402+
// --------------------------------------------------------------------------------------
403+
// A ScopedLock in which you specify an external bool to get updated on locks/unlocks.
404+
// Note that the isLockedBool should only be used as an indicator for the locked status,
405+
// and not actually depended on for thread synchronization...
406+
407+
struct ScopedLockBool {
408+
ScopedLock m_lock;
409+
volatile __aligned(4) bool& m_bool;
410+
411+
ScopedLockBool(Mutex& mutexToLock, volatile __aligned(4) bool& isLockedBool)
412+
: m_lock(mutexToLock),
413+
m_bool(isLockedBool) {
414+
m_bool = m_lock.IsLocked();
415+
}
416+
virtual ~ScopedLockBool() throw() {
417+
m_bool = false;
418+
}
419+
void Acquire() {
420+
m_lock.Acquire();
421+
m_bool = m_lock.IsLocked();
422+
}
423+
void Release() {
424+
m_bool = false;
425+
m_lock.Release();
426+
}
427+
};
396428
}
397429

common/include/x86emitter/x86types.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,12 @@ enum XMMSSEType
3535
// as a project option. The multithreaded emitter relies on native compiler support for
3636
// TLS -- Macs are crap out of luck there (for now).
3737

38+
#include "Utilities/Threading.h"
39+
3840
#ifndef x86EMIT_MULTITHREADED
39-
# define x86EMIT_MULTITHREADED 0
40-
#else
41-
# if !PCSX2_THREAD_LOCAL
41+
# if PCSX2_THREAD_LOCAL
42+
# define x86EMIT_MULTITHREADED 1
43+
# else
4244
// No TLS support? Force-clear the MT flag:
4345
# pragma message("x86emitter: TLS not available, multithreaded emitter disabled.")
4446
# undef x86EMIT_MULTITHREADED

common/src/Utilities/Linux/LnxHostSys.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@ static void SysPageFaultSignalFilter( int signal, siginfo_t *siginfo, void * )
4646
// Note: Use of stdio functions isn't safe here. Avoid console logs,
4747
// assertions, file logs, or just about anything else useful.
4848

49+
50+
// Note: This signal can be accessed by the EE or MTVU thread
51+
// Source_PageFault is a global variable with its own state information
52+
// so for now we lock this exception code unless someone can fix this better...
53+
Threading::ScopedLock lock(PageFault_Mutex);
54+
4955
Source_PageFault->Dispatch( PageFaultInfo( (uptr)siginfo->si_addr & ~m_pagemask ) );
5056

5157
// resumes execution right where we left off (re-executes instruction that

common/src/Utilities/ThreadTools.cpp

Lines changed: 32 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -786,72 +786,70 @@ void Threading::WaitEvent::Wait()
786786
// InterlockedExchanges / AtomicExchanges (PCSX2's Helper versions)
787787
// --------------------------------------------------------------------------------------
788788
// define some overloads for InterlockedExchanges for commonly used types, like u32 and s32.
789+
// Note: For all of these atomic operations below to be atomic, the variables need to be 4-byte
790+
// aligned. Read: http://msdn.microsoft.com/en-us/library/ms684122%28v=vs.85%29.aspx
789791

790-
__fi bool Threading::AtomicBitTestAndReset( volatile u32& bitset, u8 bit )
791-
{
792-
return _interlockedbittestandreset( (volatile long*)& bitset, bit ) != 0;
792+
__fi u32 Threading::AtomicRead(volatile u32& Target) {
793+
return Target; // Properly-aligned 32-bit reads are atomic
793794
}
794-
795-
__fi u32 Threading::AtomicExchange( volatile u32& Target, u32 value )
796-
{
797-
return _InterlockedExchange( (volatile long*)&Target, value );
795+
__fi s32 Threading::AtomicRead(volatile s32& Target) {
796+
return Target; // Properly-aligned 32-bit reads are atomic
798797
}
799798

800-
__fi u32 Threading::AtomicExchangeAdd( volatile u32& Target, u32 value )
801-
{
802-
return _InterlockedExchangeAdd( (volatile long*)&Target, value );
799+
__fi bool Threading::AtomicBitTestAndReset( volatile u32& bitset, u8 bit ) {
800+
return _interlockedbittestandreset( (volatile long*)& bitset, bit ) != 0;
803801
}
804-
805-
__fi u32 Threading::AtomicIncrement( volatile u32& Target )
806-
{
807-
return _InterlockedExchangeAdd( (volatile long*)&Target, 1 );
802+
__fi bool Threading::AtomicBitTestAndReset( volatile s32& bitset, u8 bit ) {
803+
return _interlockedbittestandreset( (volatile long*)& bitset, bit ) != 0;
808804
}
809805

810-
__fi u32 Threading::AtomicDecrement( volatile u32& Target )
811-
{
812-
return _InterlockedExchangeAdd( (volatile long*)&Target, -1 );
806+
__fi u32 Threading::AtomicExchange(volatile u32& Target, u32 value ) {
807+
return _InterlockedExchange( (volatile long*)&Target, value );
813808
}
814-
815-
__fi s32 Threading::AtomicExchange( volatile s32& Target, s32 value )
816-
{
809+
__fi s32 Threading::AtomicExchange( volatile s32& Target, s32 value ) {
817810
return _InterlockedExchange( (volatile long*)&Target, value );
818811
}
819812

820-
__fi s32 Threading::AtomicExchangeAdd( volatile s32& Target, s32 value )
821-
{
813+
__fi u32 Threading::AtomicExchangeAdd( volatile u32& Target, u32 value ) {
814+
return _InterlockedExchangeAdd( (volatile long*)&Target, value );
815+
}
816+
__fi s32 Threading::AtomicExchangeAdd( volatile s32& Target, s32 value ) {
822817
return _InterlockedExchangeAdd( (volatile long*)&Target, value );
823818
}
824819

825-
__fi s32 Threading::AtomicExchangeSub( volatile s32& Target, s32 value )
826-
{
820+
__fi s32 Threading::AtomicExchangeSub( volatile s32& Target, s32 value ) {
827821
return _InterlockedExchangeAdd( (volatile long*)&Target, -value );
828822
}
829823

830-
__fi s32 Threading::AtomicIncrement( volatile s32& Target )
831-
{
824+
__fi u32 Threading::AtomicIncrement( volatile u32& Target ) {
825+
return _InterlockedExchangeAdd( (volatile long*)&Target, 1 );
826+
}
827+
__fi s32 Threading::AtomicIncrement( volatile s32& Target) {
832828
return _InterlockedExchangeAdd( (volatile long*)&Target, 1 );
833829
}
834830

835-
__fi s32 Threading::AtomicDecrement( volatile s32& Target )
836-
{
831+
__fi u32 Threading::AtomicDecrement( volatile u32& Target ) {
837832
return _InterlockedExchangeAdd( (volatile long*)&Target, -1 );
838833
}
834+
__fi s32 Threading::AtomicDecrement(volatile s32& Target) {
835+
return _InterlockedExchangeAdd((volatile long*)&Target, -1);
836+
}
839837

840-
__fi void* Threading::_AtomicExchangePointer( volatile uptr& target, uptr value )
838+
__fi void* Threading::_AtomicExchangePointer(volatile uptr& target, uptr value)
841839
{
842840
#ifdef _M_AMD64 // high-level atomic ops, please leave these 64 bit checks in place.
843-
return (void*)_InterlockedExchange64( &(volatile s64&)target, value );
841+
return (void*)_InterlockedExchange64(&(volatile s64&)target, value);
844842
#else
845-
return (void*)_InterlockedExchange( (volatile long*)&target, value );
843+
return (void*)_InterlockedExchange((volatile long*)&target, value);
846844
#endif
847845
}
848846

849-
__fi void* Threading::_AtomicCompareExchangePointer( volatile uptr& target, uptr value, uptr comparand )
847+
__fi void* Threading::_AtomicCompareExchangePointer(volatile uptr& target, uptr value, uptr comparand)
850848
{
851849
#ifdef _M_AMD64 // high-level atomic ops, please leave these 64 bit checks in place.
852-
return (void*)_InterlockedCompareExchange64( &(volatile s64&)target, value );
850+
return (void*)_InterlockedCompareExchange64(&(volatile s64&)target, value);
853851
#else
854-
return (void*)_InterlockedCompareExchange( &(volatile long&)target, value, comparand );
852+
return (void*)_InterlockedCompareExchange(&(volatile long&)target, value, comparand);
855853
#endif
856854
}
857855

common/src/Utilities/VirtualMemory.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@
2626
template class EventSource< IEventListener_PageFault >;
2727

2828
SrcType_PageFault* Source_PageFault = NULL;
29+
Threading::Mutex PageFault_Mutex;
2930

3031
void pxInstallSignalHandler()
3132
{
32-
if (!Source_PageFault)
33-
{
33+
if(!Source_PageFault) {
3434
Source_PageFault = new SrcType_PageFault();
3535
}
3636

common/src/Utilities/Windows/WinHostSys.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ int SysPageFaultExceptionFilter( EXCEPTION_POINTERS* eps )
2525
if( eps->ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION )
2626
return EXCEPTION_CONTINUE_SEARCH;
2727

28+
// Note: This exception can be accessed by the EE or MTVU thread
29+
// Source_PageFault is a global variable with its own state information
30+
// so for now we lock this exception code unless someone can fix this better...
31+
Threading::ScopedLock lock(PageFault_Mutex);
2832
Source_PageFault->Dispatch( PageFaultInfo( (uptr)eps->ExceptionRecord->ExceptionInformation[1] ) );
2933
return Source_PageFault->WasHandled() ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_CONTINUE_SEARCH;
3034
}

pcsx2/Config.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,8 @@ struct Pcsx2Config
377377
IntcStat :1, // tells Pcsx2 to fast-forward through intc_stat waits.
378378
WaitLoop :1, // enables constant loop detection and fast-forwarding
379379
vuFlagHack :1, // microVU specific flag hack
380-
vuBlockHack :1; // microVU specific block flag no-propagation hack
380+
vuBlockHack :1, // microVU specific block flag no-propagation hack
381+
vuThread :1; // Enable Threaded VU1
381382
BITFIELD_END
382383

383384
u8 EECycleRate; // EE cycle rate selector (1.0, 1.5, 2.0)
@@ -471,6 +472,7 @@ TraceLogFilters& SetTraceConfig();
471472

472473
// ------------ CPU / Recompiler Options ---------------
473474

475+
#define THREAD_VU1 (EmuConfig.Cpu.Recompiler.UseMicroVU1 && EmuConfig.Speedhacks.vuThread)
474476
#define CHECK_MICROVU0 (EmuConfig.Cpu.Recompiler.UseMicroVU0)
475477
#define CHECK_MICROVU1 (EmuConfig.Cpu.Recompiler.UseMicroVU1)
476478
#define CHECK_EEREC (EmuConfig.Cpu.Recompiler.EnableEE && GetCpuProviders().IsRecAvailable_EE())

pcsx2/FiFo.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,8 @@
1717
#include "PrecompiledHeader.h"
1818
#include "Common.h"
1919

20-
#include "Gif.h"
21-
#include "Gif_Unit.h"
2220
#include "GS.h"
21+
#include "Gif_Unit.h"
2322
#include "Vif.h"
2423
#include "Vif_Dma.h"
2524
#include "IPU/IPU.h"

pcsx2/GS.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
#include <list>
2020

2121
#include "GS.h"
22-
#include "Gif.h"
2322
#include "Gif_Unit.h"
2423
#include "Counters.h"
2524

0 commit comments

Comments
 (0)