IPU: Improve DMA/IPU call locations to reduce looping

This commit is contained in:
refractionpcsx2 2023-08-05 02:51:17 +01:00
parent f2c032ba07
commit 3e78f8e87d
4 changed files with 46 additions and 37 deletions

View File

@ -95,7 +95,7 @@ __fi void IPUProcessInterrupt()
if (ipuRegs.ctrl.BUSY && !CommandExecuteQueued) if (ipuRegs.ctrl.BUSY && !CommandExecuteQueued)
IPUWorker(); IPUWorker();
if (ipuRegs.ctrl.BUSY) if (ipuRegs.ctrl.BUSY && !IPU1Status.DataRequested && !(cpuRegs.interrupt & 1 << IPU_PROCESS))
{ {
CPU_INT(IPU_PROCESS, ProcessedData ? ProcessedData : 64); CPU_INT(IPU_PROCESS, ProcessedData ? ProcessedData : 64);
} }

View File

@ -93,6 +93,8 @@ int IPU_Fifo_Input::write(const u32* pMem, int size)
if (g_BP.IFC == 8) if (g_BP.IFC == 8)
IPU1Status.DataRequested = false; IPU1Status.DataRequested = false;
CPU_INT(IPU_PROCESS, transfer_size * BIAS);
return transfer_size; return transfer_size;
} }
@ -106,7 +108,7 @@ int IPU_Fifo_Input::read(void *value)
if(ipu1ch.chcr.STR && cpuRegs.eCycle[4] == 0x9999) if(ipu1ch.chcr.STR && cpuRegs.eCycle[4] == 0x9999)
{ {
CPU_INT( DMAC_TO_IPU, 4); CPU_INT( DMAC_TO_IPU, std::min(8U, ipu1ch.qwc));
} }
if (g_BP.IFC == 0) return 0; if (g_BP.IFC == 0) return 0;
@ -183,7 +185,7 @@ void WriteFIFO_IPUin(const mem128_t* value)
{ {
if (ipuRegs.ctrl.BUSY && !CommandExecuteQueued) if (ipuRegs.ctrl.BUSY && !CommandExecuteQueued)
{ {
CommandExecuteQueued = true; CommandExecuteQueued = false;
CPU_INT(IPU_PROCESS, 8); CPU_INT(IPU_PROCESS, 8);
} }
} }

View File

@ -983,7 +983,7 @@ __fi static void finishmpeg2sliceIDEC()
__ri static bool mpeg2sliceIDEC() __ri static bool mpeg2sliceIDEC()
{ {
u16 code; u16 code;
static bool ready_to_decode = true;
switch (ipu_cmd.pos[0]) switch (ipu_cmd.pos[0])
{ {
case 0: case 0:
@ -1007,6 +1007,13 @@ __ri static bool mpeg2sliceIDEC()
ipu_cmd.pos[0] = 2; ipu_cmd.pos[0] = 2;
while (1) while (1)
{ {
if (ready_to_decode == true)
{
ready_to_decode = false;
CPU_INT(IPU_PROCESS, 64); // Should probably be much higher, but myst 3 doesn't like it right now.
ipu_cmd.pos[0] = 2;
return false;
}
// IPU0 isn't ready for data, so let's wait for it to be // 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) if ((!ipu0ch.chcr.STR || ipuRegs.ctrl.OFC || ipu0ch.qwc == 0) && ipu_cmd.pos[1] <= 2)
{ {
@ -1116,15 +1123,13 @@ __ri static bool mpeg2sliceIDEC()
ipu_dither(rgb32, rgb16, decoder.dte); ipu_dither(rgb32, rgb16, decoder.dte);
decoder.SetOutputTo(rgb16); decoder.SetOutputTo(rgb16);
} }
ProcessedData += decoder.ipu0_data;
ipu_cmd.pos[1] = 2; ipu_cmd.pos[1] = 2;
return false; [[fallthrough]];
case 2: case 2:
{ {
pxAssert(decoder.ipu0_data > 0); pxAssert(decoder.ipu0_data > 0);
ready_to_decode = true;
uint read = ipu_fifo.out.write((u32*)decoder.GetIpuDataPtr(), decoder.ipu0_data); uint read = ipu_fifo.out.write((u32*)decoder.GetIpuDataPtr(), decoder.ipu0_data);
decoder.AdvanceIpuDataBy(read); decoder.AdvanceIpuDataBy(read);
@ -1205,6 +1210,7 @@ __ri static bool mpeg2sliceIDEC()
ipu_cmd.pos[1] = 0; ipu_cmd.pos[1] = 0;
ipu_cmd.pos[2] = 0; ipu_cmd.pos[2] = 0;
ready_to_decode = true;
} }
finish_idec: finish_idec:
@ -1269,6 +1275,7 @@ finish_idec:
__fi static bool mpeg2_slice() __fi static bool mpeg2_slice()
{ {
int DCT_offset, DCT_stride; int DCT_offset, DCT_stride;
static bool ready_to_decode = true;
macroblock_8& mb8 = decoder.mb8; macroblock_8& mb8 = decoder.mb8;
macroblock_16& mb16 = decoder.mb16; macroblock_16& mb16 = decoder.mb16;
@ -1299,7 +1306,12 @@ __fi static bool mpeg2_slice()
case 2: case 2:
ipu_cmd.pos[0] = 2; ipu_cmd.pos[0] = 2;
if (ready_to_decode == true)
{
ready_to_decode = false;
CPU_INT(IPU_PROCESS, 64); // Should probably be much higher, but myst 3 doesn't like it right now.
return false;
}
// IPU0 isn't ready for data, so let's wait for it to be // 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) if ((!ipu0ch.chcr.STR || ipuRegs.ctrl.OFC || ipu0ch.qwc == 0) && ipu_cmd.pos[0] <= 3)
{ {
@ -1406,23 +1418,23 @@ __fi static bool mpeg2_slice()
{ {
if (decoder.macroblock_modes & MACROBLOCK_PATTERN) if (decoder.macroblock_modes & MACROBLOCK_PATTERN)
{ {
switch(ipu_cmd.pos[1]) switch (ipu_cmd.pos[1])
{ {
case 0: case 0:
{ {
// Get coded block pattern // Get coded block pattern
const CBPtab* tab; const CBPtab* tab;
u16 code = UBITS(16); u16 code = UBITS(16);
if (code >= 0x2000) if (code >= 0x2000)
tab = CBP_7 + (UBITS(7) - 16); tab = CBP_7 + (UBITS(7) - 16);
else else
tab = CBP_9 + UBITS(9); tab = CBP_9 + UBITS(9);
DUMPBITS(tab->len); DUMPBITS(tab->len);
decoder.coded_block_pattern = tab->cbp; decoder.coded_block_pattern = tab->cbp;
} }
[[fallthrough]]; [[fallthrough]];
case 1: case 1:
if (decoder.coded_block_pattern & 0x20) if (decoder.coded_block_pattern & 0x20)
@ -1490,9 +1502,11 @@ __fi static bool mpeg2_slice()
} }
break; break;
jNO_DEFAULT; jNO_DEFAULT;
} }
} }
else
DevCon.Warning("No macroblock mode");
} }
// Send The MacroBlock via DmaIpuFrom // Send The MacroBlock via DmaIpuFrom
@ -1500,14 +1514,11 @@ __fi static bool mpeg2_slice()
coded_block_pattern = decoder.coded_block_pattern; coded_block_pattern = decoder.coded_block_pattern;
decoder.SetOutputTo(mb16); decoder.SetOutputTo(mb16);
ProcessedData += decoder.ipu0_data; [[fallthrough]];
ipu_cmd.pos[0] = 3;
return false;
case 3: case 3:
{ {
pxAssert(decoder.ipu0_data > 0); pxAssert(decoder.ipu0_data > 0);
ready_to_decode = true;
uint read = ipu_fifo.out.write((u32*)decoder.GetIpuDataPtr(), decoder.ipu0_data); uint read = ipu_fifo.out.write((u32*)decoder.GetIpuDataPtr(), decoder.ipu0_data);
decoder.AdvanceIpuDataBy(read); decoder.AdvanceIpuDataBy(read);
@ -1577,6 +1588,7 @@ __fi static bool mpeg2_slice()
break; break;
} }
ready_to_decode = true;
return true; return true;
} }

View File

@ -149,12 +149,6 @@ void IPU1dma()
} }
} }
if (ipuRegs.ctrl.BUSY && !CommandExecuteQueued)
{
CommandExecuteQueued = true;
CPU_INT(IPU_PROCESS, totalqwc * BIAS);
}
IPU_LOG("Completed Call IPU1 DMA QWC Remaining %x Finished %d In Progress %d tadr %x", ipu1ch.qwc, IPU1Status.DMAFinished, IPU1Status.InProgress, ipu1ch.tadr); IPU_LOG("Completed Call IPU1 DMA QWC Remaining %x Finished %d In Progress %d tadr %x", ipu1ch.qwc, IPU1Status.DMAFinished, IPU1Status.InProgress, ipu1ch.tadr);
} }
@ -198,13 +192,14 @@ void IPU0dma()
dmacRegs.stadr.ADDR = ipu0ch.madr; dmacRegs.stadr.ADDR = ipu0ch.madr;
} }
IPU_INT_FROM( readsize * BIAS ); if (!ipu0ch.qwc)
IPU_INT_FROM(readsize * BIAS);
if (ipuRegs.ctrl.BUSY && !CommandExecuteQueued) if (ipuRegs.ctrl.BUSY && !CommandExecuteQueued)
{ {
CommandExecuteQueued = true; CommandExecuteQueued = false;
CPU_SET_DMASTALL(DMAC_FROM_IPU, true); CPU_SET_DMASTALL(DMAC_FROM_IPU, true);
CPU_INT(IPU_PROCESS, readsize * BIAS); IPUProcessInterrupt();
} }
} }