mirror of https://github.com/PCSX2/pcsx2.git
MTVU: port write pointer to atomic and optimize atomic access
Write pointer can be relaxed-read from the EE thread Read pointer can be relaxed-read from the VU thread Warning: AtomicExchange calls were replaced by release-store However AtomicExchange generates a memory barrier (at least on linux) So either it is useless and it will be faster, or it will explode ;)
This commit is contained in:
parent
ca46921796
commit
3f0655c821
|
@ -75,11 +75,11 @@ void VU_Thread::Reset()
|
|||
{
|
||||
ScopedLock lock(mtxBusy);
|
||||
|
||||
write_pos = 0;
|
||||
write_offset = 0;
|
||||
vuCycleIdx = 0;
|
||||
read_pos = 0;
|
||||
isBusy = false;
|
||||
write_pos = 0;
|
||||
memzero(vif);
|
||||
memzero(vifRegs);
|
||||
memzero(vuCycles);
|
||||
|
@ -97,7 +97,7 @@ void VU_Thread::ExecuteRingBuffer()
|
|||
for(;;) {
|
||||
semaEvent.WaitWithoutYield();
|
||||
ScopedLockBool lock(mtxBusy, isBusy);
|
||||
while (read_pos != GetWritePos()) {
|
||||
while (read_pos.load(std::memory_order_relaxed) != GetWritePos()) {
|
||||
u32 tag = Read();
|
||||
switch (tag) {
|
||||
case MTVU_VU_EXECUTE: {
|
||||
|
@ -137,12 +137,12 @@ void VU_Thread::ExecuteRingBuffer()
|
|||
Read(&vif.tag, vif_copy_size);
|
||||
ReadRegs(&vifRegs);
|
||||
u32 size = Read();
|
||||
MTVU_Unpack(&buffer[read_pos], vifRegs);
|
||||
MTVU_Unpack(&buffer[read_pos.load(std::memory_order_relaxed)], vifRegs);
|
||||
incReadPos(size_u32(size));
|
||||
break;
|
||||
}
|
||||
case MTVU_NULL_PACKET:
|
||||
read_pos = 0;
|
||||
read_pos.store(0, std::memory_order_release);
|
||||
break;
|
||||
jNO_DEFAULT;
|
||||
}
|
||||
|
@ -156,8 +156,8 @@ __ri void VU_Thread::WaitOnSize(s32 size)
|
|||
{
|
||||
for(;;) {
|
||||
s32 readPos = GetReadPos();
|
||||
if (readPos <= write_pos) break; // MTVU is reading in back of write_pos
|
||||
if (readPos > write_pos + size) break; // Enough free front space
|
||||
if (readPos <= write_pos.load(std::memory_order_relaxed)) break; // MTVU is reading in back of write_pos
|
||||
if (readPos > write_pos.load(std::memory_order_relaxed) + size) break; // Enough free front space
|
||||
if (1) { // Let MTVU run to free up buffer space
|
||||
KickStart();
|
||||
if (IsDevBuild) DevCon.WriteLn("WaitOnSize()");
|
||||
|
@ -174,12 +174,12 @@ void VU_Thread::ReserveSpace(s32 size)
|
|||
pxAssert(size < buffer_size);
|
||||
pxAssert(size > 0);
|
||||
pxAssert(write_offset == 0);
|
||||
if (write_pos + size > buffer_size) {
|
||||
if (write_pos.load(std::memory_order_relaxed) + size > buffer_size) {
|
||||
pxAssert(write_pos > 0);
|
||||
WaitOnSize(1); // Size of MTVU_NULL_PACKET
|
||||
Write(MTVU_NULL_PACKET);
|
||||
write_offset = 0;
|
||||
AtomicExchange(volatize(write_pos), 0);
|
||||
write_pos.store(0, std::memory_order_release);
|
||||
}
|
||||
WaitOnSize(size);
|
||||
}
|
||||
|
@ -187,17 +187,17 @@ void VU_Thread::ReserveSpace(s32 size)
|
|||
// Use this when reading read_pos from ee thread
|
||||
__fi s32 VU_Thread::GetReadPos()
|
||||
{
|
||||
return read_pos.load();
|
||||
return read_pos.load(std::memory_order_acquire);
|
||||
}
|
||||
// Use this when reading write_pos from vu thread
|
||||
__fi s32 VU_Thread::GetWritePos()
|
||||
{
|
||||
return AtomicRead(volatize(write_pos));
|
||||
return write_pos.load(std::memory_order_acquire);
|
||||
}
|
||||
// Gets the effective write pointer after adding write_offset
|
||||
__fi u32* VU_Thread::GetWritePtr()
|
||||
{
|
||||
return &buffer[(write_pos + write_offset) & buffer_mask];
|
||||
return &buffer[(write_pos.load(std::memory_order_relaxed) + write_offset) & buffer_mask];
|
||||
}
|
||||
|
||||
__fi void VU_Thread::incReadPos(s32 offset)
|
||||
|
@ -206,29 +206,29 @@ __fi void VU_Thread::incReadPos(s32 offset)
|
|||
}
|
||||
__fi void VU_Thread::incWritePos()
|
||||
{ // Adds write_offset
|
||||
s32 temp = (write_pos + write_offset) & buffer_mask;
|
||||
s32 temp = (write_pos.load(std::memory_order_relaxed) + write_offset) & buffer_mask;
|
||||
write_offset = 0;
|
||||
AtomicExchange(volatize(write_pos), temp);
|
||||
write_pos.store(temp, std::memory_order_release);
|
||||
if (MTVU_ALWAYS_KICK) KickStart();
|
||||
if (MTVU_SYNC_MODE) WaitVU();
|
||||
}
|
||||
|
||||
__fi u32 VU_Thread::Read()
|
||||
{
|
||||
u32 ret = buffer[read_pos];
|
||||
u32 ret = buffer[read_pos.load(std::memory_order_relaxed)];
|
||||
incReadPos(1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
__fi void VU_Thread::Read(void* dest, u32 size)
|
||||
{
|
||||
memcpy(dest, &buffer[read_pos], size);
|
||||
memcpy(dest, &buffer[read_pos.load(std::memory_order_relaxed)], size);
|
||||
incReadPos(size_u32(size));
|
||||
}
|
||||
|
||||
__fi void VU_Thread::ReadRegs(VIFregisters* dest)
|
||||
{
|
||||
VIFregistersMTVU* src = (VIFregistersMTVU*)&buffer[read_pos];
|
||||
VIFregistersMTVU* src = (VIFregistersMTVU*)&buffer[read_pos.load(std::memory_order_relaxed)];
|
||||
dest->cycle = src->cycle;
|
||||
dest->mode = src->mode;
|
||||
dest->num = src->num;
|
||||
|
@ -272,7 +272,7 @@ u32 VU_Thread::Get_vuCycles()
|
|||
void VU_Thread::KickStart(bool forceKick)
|
||||
{
|
||||
if ((forceKick && !semaEvent.Count())
|
||||
|| (!isBusy.load(std::memory_order_relaxed) && GetReadPos() != write_pos)) semaEvent.Post();
|
||||
|| (!isBusy.load(std::memory_order_relaxed) && GetReadPos() != write_pos.load(std::memory_order_relaxed))) semaEvent.Post();
|
||||
}
|
||||
|
||||
bool VU_Thread::IsDone()
|
||||
|
|
|
@ -32,7 +32,7 @@ class VU_Thread : public pxThread {
|
|||
__aligned(4) u32 buffer[buffer_size];
|
||||
std::atomic<int> read_pos; // Only modified by VU thread
|
||||
std::atomic<bool> isBusy; // Is thread processing data?
|
||||
__aligned(4) s32 write_pos; // Only modified by EE thread
|
||||
std::atomic<int> write_pos; // Only modified by EE thread
|
||||
__aligned(4) s32 write_offset; // Only modified by EE thread
|
||||
__aligned(4) Mutex mtxBusy;
|
||||
__aligned(4) Semaphore semaEvent;
|
||||
|
|
Loading…
Reference in New Issue