MTVU: Redesign of how to handle signals, seems more reliable

Added new variables to savestates
This commit is contained in:
refractionpcsx2 2020-12-23 12:16:33 +00:00
parent 6066f48d7c
commit d78de3237c
3 changed files with 56 additions and 50 deletions

View File

@ -107,8 +107,7 @@ 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.gsToClear = 0;
if (reg == 0x50) if (reg == 0x50)
{ {
Console.Error("GIF Handler Debug - BITBLTBUF"); Console.Error("GIF Handler Debug - BITBLTBUF");
@ -126,6 +125,7 @@ bool Gif_HandlerAD_MTVU(u8* pMem)
} }
else if (reg == 0x60) else if (reg == 0x60)
{ // SIGNAL { // SIGNAL
if (CSRreg.SIGNAL) if (CSRreg.SIGNAL)
{ // Time to ignore all subsequent drawing operations. { // Time to ignore all subsequent drawing operations.
Console.Error("GIF Handler MTVU - Double SIGNAL Not Handled"); Console.Error("GIF Handler MTVU - Double SIGNAL Not Handled");
@ -135,19 +135,19 @@ bool Gif_HandlerAD_MTVU(u8* pMem)
{ {
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.gsSignalCnt++;
} }
} }
else if (reg == 0x61) else if (reg == 0x61)
{ // FINISH { // FINISH
GUNIT_WARN("GIF Handler - FINISH"); GUNIT_WARN("GIF Handler - FINISH");
vu1Thread.gsInterrupts |= 1; vu1Thread.gsFinish = 1;
} }
else if (reg == 0x62) else if (reg == 0x62)
{ // LABEL { // 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.gsLabelCnt++;
} }
else if (reg >= 0x63 && reg != 0x7f) else if (reg >= 0x63 && reg != 0x7f)
{ {

View File

@ -62,23 +62,29 @@ void SaveStateBase::mtvuFreeze()
unsigned int v = vu1Thread.vuCycles[i].load(); unsigned int v = vu1Thread.vuCycles[i].load();
Freeze(v); Freeze(v);
} }
u32 gsInterrupts; u32 gsFinishInt;
u64 gsSignals; u64 gsSignals;
u32 gsSignalsCnt;
gsInterrupts = vu1Thread.gsToClear.load(); gsFinishInt = vu1Thread.gsFinish.load();
Freeze(gsInterrupts); Freeze(gsFinishInt);
vu1Thread.gsToClear.store(gsInterrupts); vu1Thread.gsFinish.store(gsFinishInt);
gsInterrupts = vu1Thread.gsInterrupts.load();
Freeze(gsInterrupts);
vu1Thread.gsInterrupts.store(gsInterrupts);
gsSignals = vu1Thread.gsSignal.load(); gsSignals = vu1Thread.gsSignal.load();
Freeze(gsSignals); Freeze(gsSignals);
vu1Thread.gsSignal.store(gsSignals); vu1Thread.gsSignal.store(gsSignals);
gsSignalsCnt = vu1Thread.gsSignalCnt.load();
Freeze(gsSignalsCnt);
vu1Thread.gsSignalCnt.store(gsSignalsCnt);
gsSignals = vu1Thread.gsLabel.load(); gsSignals = vu1Thread.gsLabel.load();
Freeze(gsSignals); Freeze(gsSignals);
vu1Thread.gsLabel.store(gsSignals); vu1Thread.gsLabel.store(gsSignals);
gsSignalsCnt = vu1Thread.gsLabelCnt.load();
Freeze(gsSignalsCnt);
vu1Thread.gsLabelCnt.store(gsSignalsCnt);
Freeze(vu1Thread.vuCycleIdx); Freeze(vu1Thread.vuCycleIdx);
Freeze(vu1Thread.lastLabel);
Freeze(vu1Thread.lastSignal);
} }
VU_Thread::VU_Thread(BaseVUmicroCPU*& _vuCPU, VURegs& _vuRegs) VU_Thread::VU_Thread(BaseVUmicroCPU*& _vuCPU, VURegs& _vuRegs)
@ -103,6 +109,8 @@ void VU_Thread::Reset()
ScopedLock lock(mtxBusy); ScopedLock lock(mtxBusy);
vuCycleIdx = 0; vuCycleIdx = 0;
lastLabel = 0;
lastSignal = 0;
isBusy = false; isBusy = false;
m_ato_write_pos = 0; m_ato_write_pos = 0;
m_write_pos = 0; m_write_pos = 0;
@ -112,6 +120,8 @@ void VU_Thread::Reset()
memzero(vifRegs); memzero(vifRegs);
for (size_t i = 0; i < 4; ++i) for (size_t i = 0; i < 4; ++i)
vu1Thread.vuCycles[i] = 0; vu1Thread.vuCycles[i] = 0;
vu1Thread.gsSignal = 0;
vu1Thread.gsLabel = 0;
} }
void VU_Thread::ExecuteTaskInThread() void VU_Thread::ExecuteTaskInThread()
@ -336,59 +346,54 @@ u32 VU_Thread::Get_vuCycles()
void VU_Thread::Get_GSChanges() void VU_Thread::Get_GSChanges()
{ {
u32 interrupts = gsInterrupts.load(std::memory_order_acquire); u32 finishInt = gsFinish.load(std::memory_order_acquire);
u64 signalCnt = gsSignalCnt.load(std::memory_order_acquire);
// If there's no interrupts, return early, just saves on waiting for some atomics and whatnot u64 labelCnt = gsLabelCnt.load(std::memory_order_acquire);
if (!interrupts)
return; if (signalCnt != lastSignal)
u32 clearedInterrupts = gsToClear.load(std::memory_order_acquire);
if (interrupts == clearedInterrupts)
return;
interrupts &= ~clearedInterrupts;
bool triggerInt = false;
u32 finalInterrupts = 0;
if (interrupts & 2)
{ {
GUNIT_WARN("SIGNAL firing");
const u64 signal = gsSignal.load(std::memory_order_acquire); const u64 signal = gsSignal.load(std::memory_order_acquire);
const u32 signalMsk = (u32)(signal >> 32); const u32 signalMsk = (u32)(signal >> 32);
const u32 signalData = (u32)signal; const u32 signalData = (u32)signal;
CSRreg.SIGNAL = true; lastSignal = signalCnt;
GSSIGLBLID.SIGID = (GSSIGLBLID.SIGID & ~signalMsk) | (signalData & signalMsk); if (CSRreg.SIGNAL)
{
GUNIT_WARN("Queue SIGNAL");
gifUnit.gsSIGNAL.queued = true;
//DevCon.Warning("Firing pending signal");
gifUnit.gsSIGNAL.data[0] = signalData;
gifUnit.gsSIGNAL.data[1] = signalMsk;
}
else
{
CSRreg.SIGNAL = true;
GSSIGLBLID.SIGID = (GSSIGLBLID.SIGID & ~signalMsk) | (signalData & signalMsk);
if (!GSIMR.SIGMSK) if (!GSIMR.SIGMSK)
triggerInt = true; gsIrq();
}
finalInterrupts |= 2;
} }
if (interrupts & 1) if (finishInt)
{ {
GUNIT_WARN("Finish firing");
CSRreg.FINISH = true; CSRreg.FINISH = true;
gifUnit.gsFINISH.gsFINISHFired = false;
if (!gifRegs.stat.APATH) if (!gifRegs.stat.APATH)
Gif_FinishIRQ(); Gif_FinishIRQ();
finalInterrupts |= 1; gsFinish.store(0);
} }
if (labelCnt != lastLabel)
if (interrupts & 4)
{ {
GUNIT_WARN("LABEL firing");
const u64 label = gsLabel.load(std::memory_order_acquire); const u64 label = gsLabel.load(std::memory_order_acquire);
const u32 labelMsk = (u32)(label >> 32); const u32 labelMsk = (u32)(label >> 32);
const u32 labelData = (u32)label; const u32 labelData = (u32)label;
lastLabel = labelCnt;
GSSIGLBLID.LBLID = (GSSIGLBLID.LBLID & ~labelMsk) | (labelData & labelMsk); GSSIGLBLID.LBLID = (GSSIGLBLID.LBLID & ~labelMsk) | (labelData & labelMsk);
finalInterrupts |= 4;
} }
clearedInterrupts |= finalInterrupts;
gsToClear.store(clearedInterrupts);
if (triggerInt)
gsIrq();
} }
void VU_Thread::KickStart(bool forceKick) void VU_Thread::KickStart(bool forceKick)
@ -422,8 +427,6 @@ void VU_Thread::ExecuteVU(u32 vu_addr, u32 vif_top, u32 vif_itop)
MTVU_LOG("MTVU - ExecuteVU!"); MTVU_LOG("MTVU - ExecuteVU!");
Get_GSChanges(); // Clear any pending interrupts Get_GSChanges(); // Clear any pending interrupts
ReserveSpace(4); ReserveSpace(4);
gsToClear.store(0);
gsInterrupts.store(0);
Write(MTVU_VU_EXECUTE); Write(MTVU_VU_EXECUTE);
Write(vu_addr); Write(vu_addr);
Write(vif_top); Write(vif_top);

View File

@ -47,8 +47,11 @@ public:
__aligned(4) Semaphore semaXGkick; __aligned(4) Semaphore semaXGkick;
__aligned(4) std::atomic<unsigned int> vuCycles[4]; // Used for VU cycle stealing hack __aligned(4) std::atomic<unsigned int> vuCycles[4]; // Used for VU cycle stealing hack
__aligned(4) u32 vuCycleIdx; // Used for VU cycle stealing hack __aligned(4) u32 vuCycleIdx; // Used for VU cycle stealing hack
__aligned(4) std::atomic<unsigned int> gsInterrupts; // Used for GS Signal, Finish etc __aligned(4) u32 lastSignal;
__aligned(4) std::atomic<unsigned int> gsToClear; // Used for GS Signal, Finish etc __aligned(4) u32 lastLabel;
__aligned(4) std::atomic<unsigned int> gsFinish; // Used for GS Signal, Finish etc
__aligned(4) std::atomic<u32> gsLabelCnt; // Used for GS Label command
__aligned(4) std::atomic<u32> gsSignalCnt; // Used for GS Signal command
__aligned(4) std::atomic<u64> gsLabel; // Used for GS Label command __aligned(4) std::atomic<u64> gsLabel; // Used for GS Label command
__aligned(4) std::atomic<u64> gsSignal; // Used for GS Signal command __aligned(4) std::atomic<u64> gsSignal; // Used for GS Signal command