Gif MFIFO: Slight Optimisation for GIF MFIFO heavily used area.

Hopefully this translates well to slower systems :)

Tekken Tag:

Before: 79-81fps
After: 82-84fps

Front Mission 4 intro (as it pans over the roofs)
Before: 158-159fps
After: 165-166fps
This commit is contained in:
refractionpcsx2 2016-12-24 20:09:47 +00:00
parent 7aa554b8eb
commit af3c1fc510
1 changed files with 51 additions and 38 deletions

View File

@ -468,10 +468,12 @@ static u16 QWCinGIFMFIFO(u32 DrainADDR)
{ {
u32 ret; u32 ret;
GIF_LOG("GIF MFIFO Requesting %x QWC from the MFIFO Base %x, SPR MADR %x Drain %x", gifch.qwc, dmacRegs.rbor.ADDR, spr0ch.madr, DrainADDR); GIF_LOG("GIF MFIFO Requesting %x QWC from the MFIFO Base %x, SPR MADR %x Drain %x", gifch.qwc, dmacRegs.rbor.ADDR, spr0ch.madr, DrainADDR);
//Calculate what we have in the fifo. //Calculate what we have in the fifo.
if(DrainADDR <= spr0ch.madr) { if(DrainADDR <= spr0ch.madr) {
//Drain is below the tadr, calculate the difference between them //Drain is below the write position, calculate the difference between them
ret = (spr0ch.madr - DrainADDR) >> 4; ret = (spr0ch.madr - DrainADDR) >> 4;
} }
else { else {
@ -480,56 +482,63 @@ static u16 QWCinGIFMFIFO(u32 DrainADDR)
//calculate from base to the SPR tag addr and what is left in the top of the ring //calculate from base to the SPR tag addr and what is left in the top of the ring
ret = ((spr0ch.madr - dmacRegs.rbor.ADDR) + (limit - DrainADDR)) >> 4; ret = ((spr0ch.madr - dmacRegs.rbor.ADDR) + (limit - DrainADDR)) >> 4;
} }
if(ret == 0)
gifstate |= GIF_STATE_EMPTY;
GIF_LOG("%x Available of the %x requested", ret, gifch.qwc); GIF_LOG("%x Available of the %x requested", ret, gifch.qwc);
if((s32)ret < 0) DevCon.Warning("GIF Returning %x!", ret); pxAssert(ret >= 0);
return ret; return ret;
} }
static __fi bool mfifoGIFrbTransfer() static __fi bool mfifoGIFrbTransfer()
{ {
u16 mfifoqwc = std::min(QWCinGIFMFIFO(gifch.madr), gifch.qwc); u16 qwc = std::min(QWCinGIFMFIFO(gifch.madr), gifch.qwc);
if (mfifoqwc == 0) return true; //Lets skip all this, we don't have the data if (qwc == 0) return true; //Lets skip all this, we don't have any data
/*if(!gifUnit.CanDoPath3()) {
DevCon.Warning("mfifoGIFrbTransfer() - Can't do path3");
GifDMAInt(16);
return true; // Skip if can't do path3
}*/
bool needWrap = (gifch.madr + (mfifoqwc * 16u)) > (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16u);
uint s1 = ((dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16) - gifch.madr) >> 4;
uint s2 = mfifoqwc - s1;
uint s3 = needWrap ? s1 : mfifoqwc;
u32 t1, t2;
gifch.madr = dmacRegs.rbor.ADDR + (gifch.madr & dmacRegs.rbsr.RMSK);
u8* src = (u8*)PSM(gifch.madr); u8* src = (u8*)PSM(gifch.madr);
if (src == NULL) return false; if (src == NULL) return false;
if (CHECK_GIFFIFOHACK) { u32 MFIFOUntilEnd = ((dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16) - gifch.madr) >> 4;
t1 = gif_fifo.write((u32*)src, s3); bool needWrap = MFIFOUntilEnd < qwc;
u32 firstTransQWC = needWrap ? MFIFOUntilEnd : qwc;
u32 transferred;
if (!CHECK_GIFFIFOHACK) {
transferred = gifUnit.TransferGSPacketData(GIF_TRANS_DMA, src, firstTransQWC * 16) / 16; // First part
} }
else { else {
t1 = gifUnit.TransferGSPacketData(GIF_TRANS_DMA, src, s3 * 16) / 16; // First part transferred = gif_fifo.write((u32*)src, firstTransQWC);
} }
incGifChAddr(t1); incGifChAddr(transferred);
mfifocycles += t1 * 2; // guessing
if (needWrap && transferred == MFIFOUntilEnd) { // Need to do second transfer to wrap around
//DevCon.Warning("mfifoGIFrbTransfer() - Wrap");
u32 transferred2;
uint secondTransQWC = qwc - MFIFOUntilEnd;
if (needWrap && t1 == s1) { // Need to do second transfer to wrap around
GUNIT_WARN("mfifoGIFrbTransfer() - Wrap");
src = (u8*)PSM(dmacRegs.rbor.ADDR); src = (u8*)PSM(dmacRegs.rbor.ADDR);
gifch.madr = dmacRegs.rbor.ADDR;
if (src == NULL) return false; if (src == NULL) return false;
if (CHECK_GIFFIFOHACK) {
t2 = gif_fifo.write((u32*)src, s2); if (!CHECK_GIFFIFOHACK) {
transferred2 = gifUnit.TransferGSPacketData(GIF_TRANS_DMA, src, secondTransQWC * 16) / 16; // Second part
} }
else { else {
t2 = gifUnit.TransferGSPacketData(GIF_TRANS_DMA, src, s2 * 16) / 16; // First part transferred2 = gif_fifo.write((u32*)src, secondTransQWC);
} }
incGifChAddr(t2); incGifChAddr(transferred2);
mfifocycles += t2 * 2; // guessing mfifocycles += (transferred2 + transferred) * 2; // guessing
} }
else {
mfifocycles += transferred * 2; // guessing
}
QWCinGIFMFIFO(gifch.madr);
return true; return true;
} }
@ -537,18 +546,17 @@ static __fi bool mfifoGIFchain()
{ {
/* Is QWC = 0? if so there is nothing to transfer */ /* Is QWC = 0? if so there is nothing to transfer */
if (gifch.qwc == 0) return true; if (gifch.qwc == 0) return true;
if (gifch.madr == (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16u)) DevCon.Warning("Edge Case?"); //if (gifch.madr == (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16u)) DevCon.Warning("Edge Case?");
if (gifch.madr >= dmacRegs.rbor.ADDR &&
gifch.madr < (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16u)) if ((gifch.madr & ~dmacRegs.rbsr.RMSK) == dmacRegs.rbor.ADDR)
{ {
bool ret = true; bool ret = true;
// if(gifch.madr == (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16)) DevCon.Warning("Edge GIF");
if (!mfifoGIFrbTransfer()) ret = false; if (!mfifoGIFrbTransfer()) ret = false;
if(QWCinGIFMFIFO(gifch.madr) == 0) gifstate |= GIF_STATE_EMPTY;
//This ends up being done more often but it's safer :P
//Make sure we wrap the addresses, dont want it being stuck outside the ring when reading from the ring! //Make sure we wrap the addresses, dont want it being stuck outside the ring when reading from the ring!
gifch.madr = dmacRegs.rbor.ADDR + (gifch.madr & dmacRegs.rbsr.RMSK); gifch.madr = dmacRegs.rbor.ADDR + (gifch.madr & dmacRegs.rbsr.RMSK);
gifch.tadr = dmacRegs.rbor.ADDR + (gifch.tadr & dmacRegs.rbsr.RMSK); //Check this too, tadr can suffer the same issue. gifch.tadr = dmacRegs.rbor.ADDR + (gifch.tadr & dmacRegs.rbsr.RMSK); //Front Mission 4 tag increments to end of ring
return ret; return ret;
} }
@ -582,7 +590,7 @@ void mfifoGifMaskMem(int id)
{ {
//DevCon.Warning("GIF MFIFO MADR below bottom of ring buffer, wrapping GIF MADR = %x Ring Bottom %x", gifch.madr, dmacRegs.rbor.ADDR); //DevCon.Warning("GIF MFIFO MADR below bottom of ring buffer, wrapping GIF MADR = %x Ring Bottom %x", gifch.madr, dmacRegs.rbor.ADDR);
gifch.madr = qwctag(gifch.madr); gifch.madr = qwctag(gifch.madr);
} } else
if(gifch.madr > (dmacRegs.rbor.ADDR + (u32)dmacRegs.rbsr.RMSK)) //Usual scenario is the tag is near the end (Front Mission 4) if(gifch.madr > (dmacRegs.rbor.ADDR + (u32)dmacRegs.rbsr.RMSK)) //Usual scenario is the tag is near the end (Front Mission 4)
{ {
//DevCon.Warning("GIF MFIFO MADR outside top of ring buffer, wrapping GIF MADR = %x Ring Top %x", gifch.madr, (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK)+16); //DevCon.Warning("GIF MFIFO MADR outside top of ring buffer, wrapping GIF MADR = %x Ring Top %x", gifch.madr, (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK)+16);
@ -621,6 +629,9 @@ void mfifoGIFtransfer(int qwc)
} }
if (gifch.qwc == 0) { if (gifch.qwc == 0) {
gifch.madr = dmacRegs.rbor.ADDR + (gifch.madr & dmacRegs.rbsr.RMSK);
gifch.tadr = dmacRegs.rbor.ADDR + (gifch.tadr & dmacRegs.rbsr.RMSK); //Front Mission 4 tag increments to end of ring
gifch.tadr = qwctag(gifch.tadr); gifch.tadr = qwctag(gifch.tadr);
ptag = dmaGetAddr(gifch.tadr, false); ptag = dmaGetAddr(gifch.tadr, false);
@ -633,6 +644,9 @@ void mfifoGIFtransfer(int qwc)
ptag[1]._u32, ptag[0]._u32, gifch.qwc, ptag->ID, gifch.madr, gifch.tadr, gifqwc, spr0ch.madr); ptag[1]._u32, ptag[0]._u32, gifch.qwc, ptag->ID, gifch.madr, gifch.tadr, gifqwc, spr0ch.madr);
gspath3done = hwDmacSrcChainWithStack(gifch, ptag->ID); gspath3done = hwDmacSrcChainWithStack(gifch, ptag->ID);
if (dmacRegs.ctrl.STD == STD_GIF && (ptag->ID == TAG_REFS)) if (dmacRegs.ctrl.STD == STD_GIF && (ptag->ID == TAG_REFS))
{ {
Console.WriteLn("GIF MFIFO DMA Stall not implemented - Report which game to PCSX2 Team"); Console.WriteLn("GIF MFIFO DMA Stall not implemented - Report which game to PCSX2 Team");
@ -647,7 +661,7 @@ void mfifoGIFtransfer(int qwc)
gifstate = GIF_STATE_DONE; gifstate = GIF_STATE_DONE;
gifmfifoirq = true; gifmfifoirq = true;
} }
if (QWCinGIFMFIFO(gifch.tadr) == 0) gifstate |= GIF_STATE_EMPTY; QWCinGIFMFIFO(gifch.tadr);
} }
if (!mfifoGIFchain()) { if (!mfifoGIFchain()) {
@ -759,7 +773,6 @@ void gifMFIFOInterrupt()
if (!(gifstate & GIF_STATE_STALL)) { if (!(gifstate & GIF_STATE_STALL)) {
if (QWCinGIFMFIFO(gifch.tadr) == 0) { if (QWCinGIFMFIFO(gifch.tadr) == 0) {
gifstate |= GIF_STATE_EMPTY;
GifDMAInt(4); GifDMAInt(4);
if (CHECK_GIFFIFOHACK) if (CHECK_GIFFIFOHACK)
GifDMAInt(128); GifDMAInt(128);