Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VIF: Correct DMA stall for VIF1 MFIFO - Improve IPU Core/DMA call flow #9951

Merged
merged 4 commits into from
Sep 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pcsx2/Dmac.h
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,7 @@ union tDMAC_CTRL {
tDMAC_CTRL(u32 val) { _u32 = val; }

bool test(u32 flags) const { return !!(_u32 & flags); }
bool is_mfifo(bool is_vif) const { return (is_vif) ? (MFD == MFD_VIF1) : (MFD == MFD_GIF); }
void set_flags(u32 flags) { _u32 |= flags; }
void clear_flags(u32 flags) { _u32 &= ~flags; }
void reset() { _u32 = 0; }
Expand Down
2 changes: 2 additions & 0 deletions pcsx2/GS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ static __fi void gsCSRwrite( const tGS_CSR& csr )
//gifUnit.Reset(true); // Don't think gif should be reset...
gifUnit.gsSIGNAL.queued = false;
gifUnit.gsFINISH.gsFINISHFired = true;
gifUnit.gsFINISH.gsFINISHPending = false;
// Privilage registers also reset.
std::memset(g_RealGSMem, 0, sizeof(g_RealGSMem));
GSIMR.reset();
Expand Down Expand Up @@ -84,6 +85,7 @@ static __fi void gsCSRwrite( const tGS_CSR& csr )
if (csr.FINISH) {
CSRreg.FINISH = false;
gifUnit.gsFINISH.gsFINISHFired = false; //Clear the previously fired FINISH (YS, Indiecar 2005, MGS3)
gifUnit.gsFINISH.gsFINISHPending = false;
}
if(csr.HSINT) CSRreg.HSINT = false;
if(csr.VSINT) CSRreg.VSINT = false;
Expand Down
7 changes: 6 additions & 1 deletion pcsx2/Gif_Unit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ bool Gif_HandlerAD(u8* pMem)
else if (reg == GIF_A_D_REG_FINISH)
{ // FINISH
GUNIT_WARN("GIF Handler - FINISH");
CSRreg.FINISH = true;
gifUnit.gsFINISH.gsFINISHFired = false;
gifUnit.gsFINISH.gsFINISHPending = true;
}
else if (reg == GIF_A_D_REG_LABEL)
{ // LABEL
Expand Down Expand Up @@ -188,6 +188,11 @@ bool Gif_HandlerAD_Debug(u8* pMem)

void Gif_FinishIRQ()
{
if (gifUnit.gsFINISH.gsFINISHPending)
{
CSRreg.FINISH = true;
gifUnit.gsFINISH.gsFINISHPending = false;
}
if (CSRreg.FINISH && !GSIMR.FINISHMSK && !gifUnit.gsFINISH.gsFINISHFired)
{
gsIrq();
Expand Down
4 changes: 3 additions & 1 deletion pcsx2/Gif_Unit.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ struct GS_SIGNAL
struct GS_FINISH
{
bool gsFINISHFired;
bool gsFINISHPending;

void Reset() { std::memset(this, 0, sizeof(*this)); }
};
Expand Down Expand Up @@ -838,7 +839,8 @@ struct Gif_Unit
FlushToMTGS();
}

Gif_FinishIRQ();
if(!checkPaths(true, true, true, true))
Gif_FinishIRQ();

//Path3 can rewind the DMA, so we send back the amount we go back!
if (isPath3)
Expand Down
20 changes: 9 additions & 11 deletions pcsx2/IPU/IPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
alignas(16) tIPU_cmd ipu_cmd;
alignas(16) tIPU_BP g_BP;
alignas(16) decoder_t decoder;
IPUStatus IPUCoreStatus;

static void (*IPUWorker)();

Expand Down Expand Up @@ -92,15 +93,8 @@ void tIPU_cmd::clear()

__fi void IPUProcessInterrupt()
{
if (ipuRegs.ctrl.BUSY && !CommandExecuteQueued)
if (ipuRegs.ctrl.BUSY)
IPUWorker();

if (ipuRegs.ctrl.BUSY && !IPU1Status.DataRequested && !(cpuRegs.interrupt & 1 << IPU_PROCESS))
{
CPU_INT(IPU_PROCESS, ProcessedData ? ProcessedData : 64);
}
else
ProcessedData = 0;
}

/////////////////////////////////////////////////////////
Expand All @@ -112,6 +106,9 @@ void ipuReset()
std::memset(&ipuRegs, 0, sizeof(ipuRegs));
std::memset(&g_BP, 0, sizeof(g_BP));
std::memset(&decoder, 0, sizeof(decoder));
IPUCoreStatus.DataRequested = false;
IPUCoreStatus.WaitingOnIPUFrom= false;
IPUCoreStatus.WaitingOnIPUTo = false;

decoder.picture_structure = FRAME_PICTURE; //default: progressive...my guess:P

Expand Down Expand Up @@ -149,6 +146,7 @@ bool SaveStateBase::ipuFreeze()
Freeze(coded_block_pattern);
Freeze(decoder);
Freeze(ipu_cmd);
Freeze(IPUCoreStatus);

return IsOkay();
}
Expand Down Expand Up @@ -471,7 +469,6 @@ __fi void IPUCMD_WRITE(u32 val)
{
// don't process anything if currently busy
//if (ipuRegs.ctrl.BUSY) Console.WriteLn("IPU BUSY!"); // wait for thread
ProcessedData = 0;
ipuRegs.ctrl.ECD = 0;
ipuRegs.ctrl.SCD = 0;
ipu_cmd.clear();
Expand Down Expand Up @@ -538,9 +535,10 @@ __fi void IPUCMD_WRITE(u32 val)

// Have a short delay immitating the time it takes to run IDEC/BDEC, other commands are near instant.
// Mana Khemia/Metal Saga start IDEC then change IPU0 expecting there to be a delay before IDEC sends data.
if (!CommandExecuteQueued && (ipu_cmd.CMD == SCE_IPU_IDEC || ipu_cmd.CMD == SCE_IPU_BDEC))
if (ipu_cmd.CMD == SCE_IPU_IDEC || ipu_cmd.CMD == SCE_IPU_BDEC)
{
CommandExecuteQueued = true;
IPUCoreStatus.WaitingOnIPUFrom = false;
IPUCoreStatus.WaitingOnIPUTo = false;
CPU_INT(IPU_PROCESS, 64);
}
else
Expand Down
4 changes: 1 addition & 3 deletions pcsx2/IPU/IPU.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ struct alignas(16) tIPU_BP {
// be possible -- so if the fill fails we'll only return 0 if we don't have enough
// remaining bits in the FIFO to fill the request.
// Used to do ((FP!=0) && (BP + bits) <= 128) if we get here there's defo not enough data now though

IPUCoreStatus.WaitingOnIPUTo = true;
return false;
}

Expand Down Expand Up @@ -293,8 +293,6 @@ extern bool EnableFMV;

alignas(16) extern tIPU_cmd ipu_cmd;
extern uint eecount_on_last_vdec;
extern bool CommandExecuteQueued;
extern u32 ProcessedData;

extern void ipuReset();

Expand Down
19 changes: 9 additions & 10 deletions pcsx2/IPU/IPU_Fifo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ void IPU_Fifo_Input::clear()
writepos = 0;

// Because the FIFO is drained it will request more data immediately
IPU1Status.DataRequested = true;
IPUCoreStatus.DataRequested = true;

if (ipu1ch.chcr.STR && cpuRegs.eCycle[4] == 0x9999)
{
Expand Down Expand Up @@ -91,9 +91,7 @@ int IPU_Fifo_Input::write(const u32* pMem, int size)
g_BP.IFC += transfer_size;

if (g_BP.IFC == 8)
IPU1Status.DataRequested = false;

CPU_INT(IPU_PROCESS, transfer_size * BIAS);
IPUCoreStatus.DataRequested = false;

return transfer_size;
}
Expand All @@ -104,7 +102,7 @@ int IPU_Fifo_Input::read(void *value)
if (g_BP.IFC <= 1)
{
// IPU FIFO is empty and DMA is waiting so lets tell the DMA we are ready to put data in the FIFO
IPU1Status.DataRequested = true;
IPUCoreStatus.DataRequested = true;

if(ipu1ch.chcr.STR && cpuRegs.eCycle[4] == 0x9999)
{
Expand Down Expand Up @@ -142,7 +140,7 @@ int IPU_Fifo_Output::write(const u32 *value, uint size)
ipuRegs.ctrl.OFC += transfer_size;

if(ipu0ch.chcr.STR)
IPU_INT_FROM(ipuRegs.ctrl.OFC * BIAS);
IPU_INT_FROM(1);

return transfer_size;
}
Expand Down Expand Up @@ -181,12 +179,13 @@ void WriteFIFO_IPUin(const mem128_t* value)
IPU_LOG( "WriteFIFO/IPUin <- 0x%08X.%08X.%08X.%08X", value->_u32[0], value->_u32[1], value->_u32[2], value->_u32[3]);

//committing every 16 bytes
if( ipu_fifo.in.write(value->_u32, 1) == 0 )
if( ipu_fifo.in.write(value->_u32, 1) > 0 )
{
if (ipuRegs.ctrl.BUSY && !CommandExecuteQueued)
if (ipuRegs.ctrl.BUSY && IPUCoreStatus.WaitingOnIPUTo)
{
CommandExecuteQueued = false;
CPU_INT(IPU_PROCESS, 8);
IPUCoreStatus.WaitingOnIPUFrom = false;
IPUCoreStatus.WaitingOnIPUTo = false;
CPU_INT(IPU_PROCESS, 2 * BIAS);
}
}
}
34 changes: 30 additions & 4 deletions pcsx2/IPU/IPU_MultiISA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1010,6 +1010,7 @@ __ri static bool mpeg2sliceIDEC()
// IPU0 isn't ready for data, so let's wait for it to be
if ((!ipu0ch.chcr.STR || ipuRegs.ctrl.OFC || ipu0ch.qwc == 0) && ipu_cmd.pos[1] <= 2)
{
IPUCoreStatus.WaitingOnIPUFrom = true;
return false;
}
macroblock_8& mb8 = decoder.mb8;
Expand Down Expand Up @@ -1123,6 +1124,8 @@ __ri static bool mpeg2sliceIDEC()
if (ready_to_decode == true)
{
ready_to_decode = false;
IPUCoreStatus.WaitingOnIPUFrom = false;
IPUCoreStatus.WaitingOnIPUTo = false;
CPU_INT(IPU_PROCESS, 64); // Should probably be much higher, but myst 3 doesn't like it right now.
ipu_cmd.pos[1] = 2;
return false;
Expand All @@ -1134,13 +1137,15 @@ __ri static bool mpeg2sliceIDEC()
if (decoder.ipu0_data != 0)
{
// IPU FIFO filled up -- Will have to finish transferring later.
IPUCoreStatus.WaitingOnIPUFrom = true;
ipu_cmd.pos[1] = 2;
return false;
}

mbaCount = 0;
if (read)
{
IPUCoreStatus.WaitingOnIPUFrom = true;
ipu_cmd.pos[1] = 3;
return false;
}
Expand Down Expand Up @@ -1308,6 +1313,7 @@ __fi static bool mpeg2_slice()
// IPU0 isn't ready for data, so let's wait for it to be
if ((!ipu0ch.chcr.STR || ipuRegs.ctrl.OFC || ipu0ch.qwc == 0) && ipu_cmd.pos[0] <= 3)
{
IPUCoreStatus.WaitingOnIPUFrom = true;
return false;
}

Expand Down Expand Up @@ -1514,6 +1520,8 @@ __fi static bool mpeg2_slice()
{
ipu_cmd.pos[0] = 3;
ready_to_decode = false;
IPUCoreStatus.WaitingOnIPUFrom = false;
IPUCoreStatus.WaitingOnIPUTo = false;
CPU_INT(IPU_PROCESS, 64); // Should probably be much higher, but myst 3 doesn't like it right now.
return false;
}
Expand All @@ -1525,13 +1533,15 @@ __fi static bool mpeg2_slice()
if (decoder.ipu0_data != 0)
{
// IPU FIFO filled up -- Will have to finish transferring later.
IPUCoreStatus.WaitingOnIPUFrom = true;
ipu_cmd.pos[0] = 3;
return false;
}

mbaCount = 0;
if (read)
{
IPUCoreStatus.WaitingOnIPUFrom = true;
ipu_cmd.pos[0] = 4;
return false;
}
Expand Down Expand Up @@ -1801,12 +1811,20 @@ __ri static bool ipuCSC(tIPU_CMD_CSC csc)
if (csc.OFM)
{
ipu_cmd.pos[1] += ipu_fifo.out.write(((u32*) & decoder.rgb16) + 4 * ipu_cmd.pos[1], 32 - ipu_cmd.pos[1]);
if (ipu_cmd.pos[1] < 32) return false;
if (ipu_cmd.pos[1] < 32)
{
IPUCoreStatus.WaitingOnIPUFrom = true;
return false;
}
}
else
{
ipu_cmd.pos[1] += ipu_fifo.out.write(((u32*) & decoder.rgb32) + 4 * ipu_cmd.pos[1], 64 - ipu_cmd.pos[1]);
if (ipu_cmd.pos[1] < 64) return false;
if (ipu_cmd.pos[1] < 64)
{
IPUCoreStatus.WaitingOnIPUFrom = true;
return false;
}
}

ipu_cmd.pos[0] = 0;
Expand Down Expand Up @@ -1834,12 +1852,20 @@ __ri static bool ipuPACK(tIPU_CMD_CSC csc)
if (csc.OFM)
{
ipu_cmd.pos[1] += ipu_fifo.out.write(((u32*) & decoder.rgb16) + 4 * ipu_cmd.pos[1], 32 - ipu_cmd.pos[1]);
if (ipu_cmd.pos[1] < 32) return false;
if (ipu_cmd.pos[1] < 32)
{
IPUCoreStatus.WaitingOnIPUFrom = true;
return false;
}
}
else
{
ipu_cmd.pos[1] += ipu_fifo.out.write(((u32*)g_ipu_indx4) + 4 * ipu_cmd.pos[1], 8 - ipu_cmd.pos[1]);
if (ipu_cmd.pos[1] < 8) return false;
if (ipu_cmd.pos[1] < 8)
{
IPUCoreStatus.WaitingOnIPUFrom = true;
return false;
}
}

ipu_cmd.pos[0] = 0;
Expand Down
Loading