MTVU/GIF: Clang Formatting

This commit is contained in:
refractionpcsx2 2020-12-23 09:50:48 +00:00
parent 20695d6b15
commit 6066f48d7c
3 changed files with 614 additions and 352 deletions

View File

@ -24,23 +24,37 @@
Gif_Unit gifUnit; Gif_Unit gifUnit;
// Returns true on stalling SIGNAL // Returns true on stalling SIGNAL
bool Gif_HandlerAD(u8* pMem) { bool Gif_HandlerAD(u8* pMem)
u32 reg = pMem[8]; {
u32 reg = pMem[8];
u32* data = (u32*)pMem; u32* data = (u32*)pMem;
if (reg == 0x50) { if (reg == 0x50)
{
vif1.BITBLTBUF._u64 = *(u64*)pMem; vif1.BITBLTBUF._u64 = *(u64*)pMem;
} }
else if (reg == 0x52) { else if (reg == 0x52)
{
vif1.TRXREG._u64 = *(u64*)pMem; vif1.TRXREG._u64 = *(u64*)pMem;
} }
else if (reg == 0x53) { // TRXDIR else if (reg == 0x53)
if ((pMem[0] & 3) == 1) { // local -> host { // TRXDIR
if ((pMem[0] & 3) == 1)
{ // local -> host
u8 bpp = 32; // Onimusha does TRXDIR without BLTDIVIDE first, assume 32bit u8 bpp = 32; // Onimusha does TRXDIR without BLTDIVIDE first, assume 32bit
switch(vif1.BITBLTBUF.SPSM & 7) { switch (vif1.BITBLTBUF.SPSM & 7)
case 0: bpp = 32; break; {
case 1: bpp = 24; break; case 0:
case 2: bpp = 16; break; bpp = 32;
case 3: bpp = 8; break; break;
case 1:
bpp = 24;
break;
case 2:
bpp = 16;
break;
case 3:
bpp = 8;
break;
default: // 4 is 4 bit but this is forbidden default: // 4 is 4 bit but this is forbidden
Console.Error("Illegal format for GS upload: SPSM=0%02o", vif1.BITBLTBUF.SPSM); Console.Error("Illegal format for GS upload: SPSM=0%02o", vif1.BITBLTBUF.SPSM);
break; break;
@ -50,147 +64,213 @@ bool Gif_HandlerAD(u8* pMem) {
vif1.GSLastDownloadSize = vif1.TRXREG.RRW * vif1.TRXREG.RRH * bpp >> 7; vif1.GSLastDownloadSize = vif1.TRXREG.RRW * vif1.TRXREG.RRH * bpp >> 7;
} }
} }
else if (reg == 0x60) { // SIGNAL else if (reg == 0x60)
if (CSRreg.SIGNAL) { // Time to ignore all subsequent drawing operations. { // SIGNAL
if (CSRreg.SIGNAL)
{ // Time to ignore all subsequent drawing operations.
GUNIT_WARN(Color_Orange, "GIF Handler - Stalling SIGNAL"); GUNIT_WARN(Color_Orange, "GIF Handler - Stalling SIGNAL");
if(!gifUnit.gsSIGNAL.queued) { if (!gifUnit.gsSIGNAL.queued)
gifUnit.gsSIGNAL.queued = true; {
gifUnit.gsSIGNAL.queued = true;
gifUnit.gsSIGNAL.data[0] = data[0]; gifUnit.gsSIGNAL.data[0] = data[0];
gifUnit.gsSIGNAL.data[1] = data[1]; gifUnit.gsSIGNAL.data[1] = data[1];
return true; // Stalling SIGNAL return true; // Stalling SIGNAL
} }
} }
else { else
{
GUNIT_WARN("GIF Handler - SIGNAL"); GUNIT_WARN("GIF Handler - SIGNAL");
GSSIGLBLID.SIGID = (GSSIGLBLID.SIGID&~data[1])|(data[0]&data[1]); GSSIGLBLID.SIGID = (GSSIGLBLID.SIGID & ~data[1]) | (data[0] & data[1]);
if (!GSIMR.SIGMSK) gsIrq(); if (!GSIMR.SIGMSK)
gsIrq();
CSRreg.SIGNAL = true; CSRreg.SIGNAL = true;
} }
} }
else if (reg == 0x61) { // FINISH else if (reg == 0x61)
{ // FINISH
GUNIT_WARN("GIF Handler - FINISH"); GUNIT_WARN("GIF Handler - FINISH");
CSRreg.FINISH = true; CSRreg.FINISH = true;
} }
else if (reg == 0x62) { // LABEL else if (reg == 0x62)
{ // LABEL
GUNIT_WARN("GIF Handler - LABEL"); GUNIT_WARN("GIF Handler - LABEL");
GSSIGLBLID.LBLID = (GSSIGLBLID.LBLID&~data[1])|(data[0]&data[1]); GSSIGLBLID.LBLID = (GSSIGLBLID.LBLID & ~data[1]) | (data[0] & data[1]);
} }
else if (reg >= 0x63 && reg != 0x7f) { else if (reg >= 0x63 && reg != 0x7f)
{
//DevCon.Warning("GIF Handler - Write to unknown register! [reg=%x]", reg); //DevCon.Warning("GIF Handler - Write to unknown register! [reg=%x]", reg);
} }
return false; return false;
} }
bool Gif_HandlerAD_MTVU(u8* pMem) { bool Gif_HandlerAD_MTVU(u8* pMem)
u32 reg = pMem[8]; {
u32 reg = pMem[8];
u32* data = (u32*)pMem; u32* data = (u32*)pMem;
vu1Thread.gsInterrupts &= ~vu1Thread.gsToClear; vu1Thread.gsInterrupts &= ~vu1Thread.gsToClear;
vu1Thread.gsToClear = 0; vu1Thread.gsToClear = 0;
if (reg == 0x50) { Console.Error("GIF Handler Debug - BITBLTBUF"); return 1; } if (reg == 0x50)
else if (reg == 0x52) { Console.Error("GIF Handler Debug - TRXREG"); return 1; } {
else if (reg == 0x53) { Console.Error("GIF Handler Debug - TRXDIR"); return 1; } Console.Error("GIF Handler Debug - BITBLTBUF");
else if (reg == 0x60) { // SIGNAL return 1;
if (CSRreg.SIGNAL) { // Time to ignore all subsequent drawing operations. }
Console.Error("GIF Handler MTVU - Double SIGNAL Not Handled"); return 1; else if (reg == 0x52)
{
Console.Error("GIF Handler Debug - TRXREG");
return 1;
}
else if (reg == 0x53)
{
Console.Error("GIF Handler Debug - TRXDIR");
return 1;
}
else if (reg == 0x60)
{ // SIGNAL
if (CSRreg.SIGNAL)
{ // Time to ignore all subsequent drawing operations.
Console.Error("GIF Handler MTVU - Double SIGNAL Not Handled");
return 1;
} }
else { else
{
GUNIT_WARN("GIF Handler - SIGNAL"); GUNIT_WARN("GIF Handler - SIGNAL");
vu1Thread.gsSignal = ((u64)data[1] << 32) | data[0]; vu1Thread.gsSignal = ((u64)data[1] << 32) | data[0];
vu1Thread.gsInterrupts |= 2; vu1Thread.gsInterrupts |= 2;
} }
} }
else if (reg == 0x61) { // FINISH else if (reg == 0x61)
{ // FINISH
GUNIT_WARN("GIF Handler - FINISH"); GUNIT_WARN("GIF Handler - FINISH");
vu1Thread.gsInterrupts |= 1; vu1Thread.gsInterrupts |= 1;
} }
else if (reg == 0x62) { // LABEL else if (reg == 0x62)
{ // LABEL
GUNIT_WARN("GIF Handler - LABEL"); GUNIT_WARN("GIF Handler - LABEL");
vu1Thread.gsLabel = ((u64)data[1] << 32) | data[0]; vu1Thread.gsLabel = ((u64)data[1] << 32) | data[0];
vu1Thread.gsInterrupts |= 4; vu1Thread.gsInterrupts |= 4;
} }
else if (reg >= 0x63 && reg != 0x7f) { else if (reg >= 0x63 && reg != 0x7f)
{
DevCon.Warning("GIF Handler Debug - Write to unknown register! [reg=%x]", reg); DevCon.Warning("GIF Handler Debug - Write to unknown register! [reg=%x]", reg);
} }
return 0; return 0;
} }
// Returns true if pcsx2 needed to process the packet... // Returns true if pcsx2 needed to process the packet...
bool Gif_HandlerAD_Debug(u8* pMem) { bool Gif_HandlerAD_Debug(u8* pMem)
u32 reg = pMem[8]; {
if (reg == 0x50) { Console.Error("GIF Handler Debug - BITBLTBUF"); return 1; } u32 reg = pMem[8];
else if (reg == 0x52) { Console.Error("GIF Handler Debug - TRXREG"); return 1; } if (reg == 0x50)
else if (reg == 0x53) { Console.Error("GIF Handler Debug - TRXDIR"); return 1; } {
else if (reg == 0x60) { Console.Error("GIF Handler Debug - SIGNAL"); return 1; } Console.Error("GIF Handler Debug - BITBLTBUF");
else if (reg == 0x61) { Console.Error("GIF Handler Debug - FINISH"); return 1; } return 1;
else if (reg == 0x62) { Console.Error("GIF Handler Debug - LABEL"); return 1; } }
else if (reg >= 0x63 && reg != 0x7f) { else if (reg == 0x52)
{
Console.Error("GIF Handler Debug - TRXREG");
return 1;
}
else if (reg == 0x53)
{
Console.Error("GIF Handler Debug - TRXDIR");
return 1;
}
else if (reg == 0x60)
{
Console.Error("GIF Handler Debug - SIGNAL");
return 1;
}
else if (reg == 0x61)
{
Console.Error("GIF Handler Debug - FINISH");
return 1;
}
else if (reg == 0x62)
{
Console.Error("GIF Handler Debug - LABEL");
return 1;
}
else if (reg >= 0x63 && reg != 0x7f)
{
DevCon.Warning("GIF Handler Debug - Write to unknown register! [reg=%x]", reg); DevCon.Warning("GIF Handler Debug - Write to unknown register! [reg=%x]", reg);
} }
return 0; return 0;
} }
void Gif_FinishIRQ() { void Gif_FinishIRQ()
if (CSRreg.FINISH && !GSIMR.FINISHMSK && !gifUnit.gsFINISH.gsFINISHFired) { {
if (CSRreg.FINISH && !GSIMR.FINISHMSK && !gifUnit.gsFINISH.gsFINISHFired)
{
gsIrq(); gsIrq();
gifUnit.gsFINISH.gsFINISHFired = true; gifUnit.gsFINISH.gsFINISHFired = true;
} }
} }
// Used in MTVU mode... MTVU will later complete a real packet // Used in MTVU mode... MTVU will later complete a real packet
void Gif_AddGSPacketMTVU(GS_Packet& gsPack, GIF_PATH path) { void Gif_AddGSPacketMTVU(GS_Packet& gsPack, GIF_PATH path)
{
GetMTGS().SendSimpleGSPacket(GS_RINGTYPE_MTVU_GSPACKET, 0, 0, path); GetMTGS().SendSimpleGSPacket(GS_RINGTYPE_MTVU_GSPACKET, 0, 0, path);
} }
void Gif_AddCompletedGSPacket(GS_Packet& gsPack, GIF_PATH path) { void Gif_AddCompletedGSPacket(GS_Packet& gsPack, GIF_PATH path)
{
//DevCon.WriteLn("Adding Completed Gif Packet [size=%x]", gsPack.size); //DevCon.WriteLn("Adding Completed Gif Packet [size=%x]", gsPack.size);
if (COPY_GS_PACKET_TO_MTGS) { if (COPY_GS_PACKET_TO_MTGS)
GetMTGS().PrepDataPacket(path, gsPack.size/16); {
MemCopy_WrappedDest((u128*)&gifUnit.gifPath[path].buffer[gsPack.offset], RingBuffer.m_Ring, GetMTGS().PrepDataPacket(path, gsPack.size / 16);
GetMTGS().m_packet_writepos, RingBufferSize, gsPack.size/16); MemCopy_WrappedDest((u128*)&gifUnit.gifPath[path].buffer[gsPack.offset], RingBuffer.m_Ring,
GetMTGS().m_packet_writepos, RingBufferSize, gsPack.size / 16);
GetMTGS().SendDataPacket(); GetMTGS().SendDataPacket();
} }
else { else
{
pxAssertDev(!gsPack.readAmount, "Gif Unit - gsPack.readAmount only valid for MTVU path 1!"); pxAssertDev(!gsPack.readAmount, "Gif Unit - gsPack.readAmount only valid for MTVU path 1!");
gifUnit.gifPath[path].readAmount.fetch_add(gsPack.size); gifUnit.gifPath[path].readAmount.fetch_add(gsPack.size);
GetMTGS().SendSimpleGSPacket(GS_RINGTYPE_GSPACKET, gsPack.offset, gsPack.size, path); GetMTGS().SendSimpleGSPacket(GS_RINGTYPE_GSPACKET, gsPack.offset, gsPack.size, path);
} }
} }
void Gif_AddBlankGSPacket(u32 size, GIF_PATH path) { void Gif_AddBlankGSPacket(u32 size, GIF_PATH path)
{
//DevCon.WriteLn("Adding Blank Gif Packet [size=%x]", size); //DevCon.WriteLn("Adding Blank Gif Packet [size=%x]", size);
gifUnit.gifPath[path].readAmount.fetch_add(size); gifUnit.gifPath[path].readAmount.fetch_add(size);
GetMTGS().SendSimpleGSPacket(GS_RINGTYPE_GSPACKET, ~0u, size, path); GetMTGS().SendSimpleGSPacket(GS_RINGTYPE_GSPACKET, ~0u, size, path);
} }
void Gif_MTGS_Wait(bool isMTVU) { void Gif_MTGS_Wait(bool isMTVU)
{
GetMTGS().WaitGS(false, true, isMTVU); GetMTGS().WaitGS(false, true, isMTVU);
} }
void SaveStateBase::gifPathFreeze(u32 path) { void SaveStateBase::gifPathFreeze(u32 path)
{
Gif_Path& gifPath = gifUnit.gifPath[path]; Gif_Path& gifPath = gifUnit.gifPath[path];
pxAssertDev(!gifPath.readAmount, "Gif Path readAmount should be 0!"); pxAssertDev(!gifPath.readAmount, "Gif Path readAmount should be 0!");
pxAssertDev(!gifPath.gsPack.readAmount, "GS Pack readAmount should be 0!"); pxAssertDev(!gifPath.gsPack.readAmount, "GS Pack readAmount should be 0!");
pxAssertDev(!gifPath.GetPendingGSPackets(), "MTVU GS Pack Queue should be 0!"); pxAssertDev(!gifPath.GetPendingGSPackets(), "MTVU GS Pack Queue should be 0!");
if (!gifPath.isMTVU()) { // FixMe: savestate freeze bug (Gust games) with MTVU enabled if (!gifPath.isMTVU())
if (IsSaving()) { // Move all the buffered data to the start of buffer { // FixMe: savestate freeze bug (Gust games) with MTVU enabled
if (IsSaving())
{ // Move all the buffered data to the start of buffer
gifPath.RealignPacket(); // May add readAmount which we need to clear on load gifPath.RealignPacket(); // May add readAmount which we need to clear on load
} }
} }
u8* bufferPtr = gifPath.buffer; // Backup current buffer ptr u8* bufferPtr = gifPath.buffer; // Backup current buffer ptr
Freeze(gifPath.mtvu.fakePackets); Freeze(gifPath.mtvu.fakePackets);
FreezeMem(&gifPath, sizeof(gifPath) - sizeof(gifPath.mtvu)); FreezeMem(&gifPath, sizeof(gifPath) - sizeof(gifPath.mtvu));
FreezeMem(bufferPtr, gifPath.curSize); FreezeMem(bufferPtr, gifPath.curSize);
gifPath.buffer = bufferPtr; gifPath.buffer = bufferPtr;
if(!IsSaving()) { if (!IsSaving())
gifPath.readAmount = 0; {
gifPath.readAmount = 0;
gifPath.gsPack.readAmount = 0; gifPath.gsPack.readAmount = 0;
} }
} }
void SaveStateBase::gifFreeze() { void SaveStateBase::gifFreeze()
{
bool mtvuMode = THREAD_VU1; bool mtvuMode = THREAD_VU1;
pxAssert(vu1Thread.IsDone()); pxAssert(vu1Thread.IsDone());
GetMTGS().WaitGS(); GetMTGS().WaitGS();
@ -203,8 +283,10 @@ void SaveStateBase::gifFreeze() {
gifPathFreeze(GIF_PATH_1); gifPathFreeze(GIF_PATH_1);
gifPathFreeze(GIF_PATH_2); gifPathFreeze(GIF_PATH_2);
gifPathFreeze(GIF_PATH_3); gifPathFreeze(GIF_PATH_3);
if (!IsSaving()) { if (!IsSaving())
if (mtvuMode != THREAD_VU1) { {
if (mtvuMode != THREAD_VU1)
{
DevCon.Warning("gifUnit: MTVU Mode has switched between save/load state"); DevCon.Warning("gifUnit: MTVU Mode has switched between save/load state");
// ToDo: gifUnit.SwitchMTVU(mtvuMode); // ToDo: gifUnit.SwitchMTVU(mtvuMode);
} }

File diff suppressed because it is too large Load Diff

View File

@ -22,12 +22,13 @@
__aligned16 VU_Thread vu1Thread(CpuVU1, VU1); __aligned16 VU_Thread vu1Thread(CpuVU1, VU1);
#define MTVU_ALWAYS_KICK 0 #define MTVU_ALWAYS_KICK 0
#define MTVU_SYNC_MODE 0 #define MTVU_SYNC_MODE 0
// Rounds up a size in bytes for size in u32's // Rounds up a size in bytes for size in u32's
static __fi u32 size_u32(u32 x) { return (x + 3) >> 2; } static __fi u32 size_u32(u32 x) { return (x + 3) >> 2; }
enum MTVU_EVENT { enum MTVU_EVENT
{
MTVU_VU_EXECUTE, // Execute VU program MTVU_VU_EXECUTE, // Execute VU program
MTVU_VU_WRITE_MICRO, // Write to VU micro-mem MTVU_VU_WRITE_MICRO, // Write to VU micro-mem
MTVU_VU_WRITE_DATA, // Write to VU data-mem MTVU_VU_WRITE_DATA, // Write to VU data-mem
@ -43,8 +44,10 @@ static void MTVU_Unpack(void* data, VIFregisters& vifRegs)
{ {
u16 wl = vifRegs.cycle.wl > 0 ? vifRegs.cycle.wl : 256; u16 wl = vifRegs.cycle.wl > 0 ? vifRegs.cycle.wl : 256;
bool isFill = vifRegs.cycle.cl < wl; bool isFill = vifRegs.cycle.cl < wl;
if (newVifDynaRec) dVifUnpack<1>((u8*)data, isFill); if (newVifDynaRec)
else _nVifUnpack(1, (u8*)data, vifRegs.mode, isFill); dVifUnpack<1>((u8*)data, isFill);
else
_nVifUnpack(1, (u8*)data, vifRegs.mode, isFill);
} }
// Called on Saving/Loading states... // Called on Saving/Loading states...
@ -52,8 +55,10 @@ void SaveStateBase::mtvuFreeze()
{ {
FreezeTag("MTVU"); FreezeTag("MTVU");
pxAssert(vu1Thread.IsDone()); pxAssert(vu1Thread.IsDone());
if (!IsSaving()) vu1Thread.Reset(); if (!IsSaving())
for (size_t i = 0; i < 4; ++i) { vu1Thread.Reset();
for (size_t i = 0; i < 4; ++i)
{
unsigned int v = vu1Thread.vuCycles[i].load(); unsigned int v = vu1Thread.vuCycles[i].load();
Freeze(v); Freeze(v);
} }
@ -76,8 +81,9 @@ void SaveStateBase::mtvuFreeze()
Freeze(vu1Thread.vuCycleIdx); Freeze(vu1Thread.vuCycleIdx);
} }
VU_Thread::VU_Thread(BaseVUmicroCPU*& _vuCPU, VURegs& _vuRegs) : VU_Thread::VU_Thread(BaseVUmicroCPU*& _vuCPU, VURegs& _vuRegs)
vuCPU(_vuCPU), vuRegs(_vuRegs) : vuCPU(_vuCPU)
, vuRegs(_vuRegs)
{ {
m_name = L"MTVU"; m_name = L"MTVU";
Reset(); Reset();
@ -85,7 +91,8 @@ VU_Thread::VU_Thread(BaseVUmicroCPU*& _vuCPU, VURegs& _vuRegs) :
VU_Thread::~VU_Thread() VU_Thread::~VU_Thread()
{ {
try { try
{
pxThread::Cancel(); pxThread::Cancel();
} }
DESTRUCTOR_CATCHALL DESTRUCTOR_CATCHALL
@ -95,12 +102,12 @@ void VU_Thread::Reset()
{ {
ScopedLock lock(mtxBusy); ScopedLock lock(mtxBusy);
vuCycleIdx = 0; vuCycleIdx = 0;
isBusy = false; isBusy = false;
m_ato_write_pos = 0; m_ato_write_pos = 0;
m_write_pos = 0; m_write_pos = 0;
m_ato_read_pos = 0; m_ato_read_pos = 0;
m_read_pos = 0; m_read_pos = 0;
memzero(vif); memzero(vif);
memzero(vifRegs); memzero(vifRegs);
for (size_t i = 0; i < 4; ++i) for (size_t i = 0; i < 4; ++i)
@ -109,42 +116,51 @@ void VU_Thread::Reset()
void VU_Thread::ExecuteTaskInThread() void VU_Thread::ExecuteTaskInThread()
{ {
PCSX2_PAGEFAULT_PROTECT { PCSX2_PAGEFAULT_PROTECT
{
ExecuteRingBuffer(); ExecuteRingBuffer();
} PCSX2_PAGEFAULT_EXCEPT; }
PCSX2_PAGEFAULT_EXCEPT;
} }
void VU_Thread::ExecuteRingBuffer() void VU_Thread::ExecuteRingBuffer()
{ {
for(;;) { for (;;)
{
semaEvent.WaitWithoutYield(); semaEvent.WaitWithoutYield();
ScopedLockBool lock(mtxBusy, isBusy); ScopedLockBool lock(mtxBusy, isBusy);
while (m_ato_read_pos.load(std::memory_order_relaxed) != GetWritePos()) { while (m_ato_read_pos.load(std::memory_order_relaxed) != GetWritePos())
{
u32 tag = Read(); u32 tag = Read();
switch (tag) { switch (tag)
case MTVU_VU_EXECUTE: { {
case MTVU_VU_EXECUTE:
{
vuRegs.cycle = 0; vuRegs.cycle = 0;
s32 addr = Read(); s32 addr = Read();
vifRegs.top = Read(); vifRegs.top = Read();
vifRegs.itop = Read(); vifRegs.itop = Read();
if (addr != -1) vuRegs.VI[REG_TPC].UL = addr; if (addr != -1)
vuRegs.VI[REG_TPC].UL = addr;
vuCPU->SetStartPC(vuRegs.VI[REG_TPC].UL << 3); vuCPU->SetStartPC(vuRegs.VI[REG_TPC].UL << 3);
vuCPU->Execute(vu1RunCycles); vuCPU->Execute(vu1RunCycles);
gifUnit.gifPath[GIF_PATH_1].FinishGSPacketMTVU(); gifUnit.gifPath[GIF_PATH_1].FinishGSPacketMTVU();
semaXGkick.Post(); // Tell MTGS a path1 packet is complete semaXGkick.Post(); // Tell MTGS a path1 packet is complete
vuCycles[vuCycleIdx].store(vuRegs.cycle, std::memory_order_release); vuCycles[vuCycleIdx].store(vuRegs.cycle, std::memory_order_release);
vuCycleIdx = (vuCycleIdx + 1) & 3; vuCycleIdx = (vuCycleIdx + 1) & 3;
break; break;
} }
case MTVU_VU_WRITE_MICRO: { case MTVU_VU_WRITE_MICRO:
{
u32 vu_micro_addr = Read(); u32 vu_micro_addr = Read();
u32 size = Read(); u32 size = Read();
vuCPU->Clear(vu_micro_addr, size); vuCPU->Clear(vu_micro_addr, size);
Read(&vuRegs.Micro[vu_micro_addr], size); Read(&vuRegs.Micro[vu_micro_addr], size);
break; break;
} }
case MTVU_VU_WRITE_DATA: { case MTVU_VU_WRITE_DATA:
{
u32 vu_data_addr = Read(); u32 vu_data_addr = Read();
u32 size = Read(); u32 size = Read();
Read(&vuRegs.Mem[vu_data_addr], size); Read(&vuRegs.Mem[vu_data_addr], size);
@ -156,7 +172,8 @@ void VU_Thread::ExecuteRingBuffer()
case MTVU_VIF_WRITE_ROW: case MTVU_VIF_WRITE_ROW:
Read(&vif.MaskRow, sizeof(vif.MaskRow)); Read(&vif.MaskRow, sizeof(vif.MaskRow));
break; break;
case MTVU_VIF_UNPACK: { case MTVU_VIF_UNPACK:
{
u32 vif_copy_size = (uptr)&vif.StructEnd - (uptr)&vif.tag; u32 vif_copy_size = (uptr)&vif.StructEnd - (uptr)&vif.tag;
Read(&vif.tag, vif_copy_size); Read(&vif.tag, vif_copy_size);
ReadRegs(&vifRegs); ReadRegs(&vifRegs);
@ -168,7 +185,7 @@ void VU_Thread::ExecuteRingBuffer()
case MTVU_NULL_PACKET: case MTVU_NULL_PACKET:
m_read_pos = 0; m_read_pos = 0;
break; break;
jNO_DEFAULT; jNO_DEFAULT;
} }
CommitReadPos(); CommitReadPos();
@ -180,16 +197,19 @@ void VU_Thread::ExecuteRingBuffer()
// Should only be called by ReserveSpace() // Should only be called by ReserveSpace()
__ri void VU_Thread::WaitOnSize(s32 size) __ri void VU_Thread::WaitOnSize(s32 size)
{ {
for(;;) { for (;;)
s32 readPos = GetReadPos(); {
if (readPos <= m_write_pos) break; // MTVU is reading in back of write_pos s32 readPos = GetReadPos();
if (readPos <= m_write_pos)
break; // MTVU is reading in back of write_pos
// FIXME greg: there is a bug somewhere in the queue pointer // FIXME greg: there is a bug somewhere in the queue pointer
// management. It creates a deadlock/corruption in SotC intro (before // management. It creates a deadlock/corruption in SotC intro (before
// the first menu). I added a 4KB safety net which seem to avoid to // the first menu). I added a 4KB safety net which seem to avoid to
// trigger the bug. // trigger the bug.
// Note: a wait lock instead of a yield also helps to avoid the bug. // Note: a wait lock instead of a yield also helps to avoid the bug.
if (readPos > m_write_pos + size + _4kb) break; // Enough free front space if (readPos > m_write_pos + size + _4kb)
{ // Let MTVU run to free up buffer space break; // Enough free front space
{ // Let MTVU run to free up buffer space
KickStart(); KickStart();
// Locking might trigger a full flush of the ring buffer. Yield // Locking might trigger a full flush of the ring buffer. Yield
// will be more aggressive, and only flush the minimal size. // will be more aggressive, and only flush the minimal size.
@ -205,10 +225,11 @@ __ri void VU_Thread::WaitOnSize(s32 size)
void VU_Thread::ReserveSpace(s32 size) void VU_Thread::ReserveSpace(s32 size)
{ {
pxAssert(m_write_pos < buffer_size); pxAssert(m_write_pos < buffer_size);
pxAssert(size < buffer_size); pxAssert(size < buffer_size);
pxAssert(size > 0); pxAssert(size > 0);
if (m_write_pos + size > (buffer_size - 1)) { if (m_write_pos + size > (buffer_size - 1))
{
WaitOnSize(1); // Size of MTVU_NULL_PACKET WaitOnSize(1); // Size of MTVU_NULL_PACKET
Write(MTVU_NULL_PACKET); Write(MTVU_NULL_PACKET);
// Reset local write pointer/position // Reset local write pointer/position
@ -242,8 +263,10 @@ __fi void VU_Thread::CommitWritePos()
{ {
m_ato_write_pos.store(m_write_pos, std::memory_order_release); m_ato_write_pos.store(m_write_pos, std::memory_order_release);
if (MTVU_ALWAYS_KICK) KickStart(); if (MTVU_ALWAYS_KICK)
if (MTVU_SYNC_MODE) WaitVU(); KickStart();
if (MTVU_SYNC_MODE)
WaitVU();
} }
__fi void VU_Thread::CommitReadPos() __fi void VU_Thread::CommitReadPos()
@ -307,7 +330,8 @@ u32 VU_Thread::Get_vuCycles()
return (vuCycles[0].load(std::memory_order_acquire) + return (vuCycles[0].load(std::memory_order_acquire) +
vuCycles[1].load(std::memory_order_acquire) + vuCycles[1].load(std::memory_order_acquire) +
vuCycles[2].load(std::memory_order_acquire) + vuCycles[2].load(std::memory_order_acquire) +
vuCycles[3].load(std::memory_order_acquire)) >> 2; vuCycles[3].load(std::memory_order_acquire)) >>
2;
} }
void VU_Thread::Get_GSChanges() void VU_Thread::Get_GSChanges()
@ -369,8 +393,8 @@ void VU_Thread::Get_GSChanges()
void VU_Thread::KickStart(bool forceKick) void VU_Thread::KickStart(bool forceKick)
{ {
if ((forceKick && !semaEvent.Count()) if ((forceKick && !semaEvent.Count()) || (!isBusy.load(std::memory_order_acquire) && GetReadPos() != m_ato_write_pos.load(std::memory_order_relaxed)))
|| (!isBusy.load(std::memory_order_acquire) && GetReadPos() != m_ato_write_pos.load(std::memory_order_relaxed))) semaEvent.Post(); semaEvent.Post();
} }
bool VU_Thread::IsDone() bool VU_Thread::IsDone()
@ -381,8 +405,10 @@ bool VU_Thread::IsDone()
void VU_Thread::WaitVU() void VU_Thread::WaitVU()
{ {
MTVU_LOG("MTVU - WaitVU!"); MTVU_LOG("MTVU - WaitVU!");
for(;;) { for (;;)
if (IsDone()) break; {
if (IsDone())
break;
//DevCon.WriteLn("WaitVU()"); //DevCon.WriteLn("WaitVU()");
pxAssert(THREAD_VU1); pxAssert(THREAD_VU1);
KickStart(); KickStart();