From 0bf7a35a538fd89cca34b721156222e6f24dc93f Mon Sep 17 00:00:00 2001 From: Gregory Hainaut Date: Fri, 2 May 2014 23:03:02 +0200 Subject: [PATCH] pcsx2: improve the GS read fifo API 1/ initReadFifo will be first called on the GS thread (openGL can only be done on the GS thread) 2/ readFifo will be called on the EE thread. It is not safe too access eeMem from GS because of memory is virtual Fix "recent" regression (crash) on Kingdom heart and others game too. v2: add a len check on GSState::InitReadFIFO --- common/include/PS2Edefs.h | 6 ++++++ pcsx2/FiFo.cpp | 7 +++++-- pcsx2/GS.h | 4 ++-- pcsx2/MTGS.cpp | 10 ++++++---- pcsx2/PluginManager.cpp | 4 ++++ pcsx2/Vif1_Dma.cpp | 7 +++++-- plugins/GSdx/GS.cpp | 22 ++++++++++++++++++++++ plugins/GSdx/GSState.cpp | 30 +++++++++++++++++++++++++++++- plugins/GSdx/GSState.h | 2 ++ plugins/GSdx/GSdx.def | 6 ++++-- 10 files changed, 85 insertions(+), 13 deletions(-) diff --git a/common/include/PS2Edefs.h b/common/include/PS2Edefs.h index e148f508fa..3b2feea96e 100644 --- a/common/include/PS2Edefs.h +++ b/common/include/PS2Edefs.h @@ -255,7 +255,9 @@ void CALLBACK GSgifTransfer3(u32 *pMem, u32 size); void CALLBACK GSgetLastTag(u64* ptag); // returns the last tag processed (64 bits) void CALLBACK GSgifSoftReset(u32 mask); void CALLBACK GSreadFIFO(u64 *mem); +void CALLBACK GSinitReadFIFO(u64 *mem); void CALLBACK GSreadFIFO2(u64 *mem, int qwc); +void CALLBACK GSinitReadFIFO2(u64 *mem, int qwc); // extended funcs @@ -580,6 +582,8 @@ typedef void (CALLBACK* _GSgifTransfer3)(u32 *pMem, u32 size); typedef void (CALLBACK* _GSgifSoftReset)(u32 mask); typedef void (CALLBACK* _GSreadFIFO)(u64 *pMem); typedef void (CALLBACK* _GSreadFIFO2)(u64 *pMem, int qwc); +typedef void (CALLBACK* _GSinitReadFIFO)(u64 *pMem); +typedef void (CALLBACK* _GSinitReadFIFO2)(u64 *pMem, int qwc); typedef void (CALLBACK* _GSchangeSaveState)(int, const char* filename); typedef void (CALLBACK* _GSgetTitleInfo2)(char* dest, size_t length); @@ -734,7 +738,9 @@ extern _GSgifTransfer2 GSgifTransfer2; extern _GSgifTransfer3 GSgifTransfer3; extern _GSgifSoftReset GSgifSoftReset; extern _GSreadFIFO GSreadFIFO; +extern _GSinitReadFIFO GSinitReadFIFO; extern _GSreadFIFO2 GSreadFIFO2; +extern _GSinitReadFIFO2 GSinitReadFIFO2; extern _GSchangeSaveState GSchangeSaveState; extern _GSgetTitleInfo2 GSgetTitleInfo2; diff --git a/pcsx2/FiFo.cpp b/pcsx2/FiFo.cpp index ed658bc0eb..c393f57749 100644 --- a/pcsx2/FiFo.cpp +++ b/pcsx2/FiFo.cpp @@ -51,8 +51,11 @@ void __fastcall ReadFIFO_VIF1(mem128_t* out) } if (vif1Regs.stat.FQC > 0) { GetMTGS().WaitGS(); - GetMTGS().SendPointerPacket(GS_RINGTYPE_READ_FIFO1, 0, out); - GetMTGS().WaitGS(false); // wait without reg sync + if (GSinitReadFIFO) { + GetMTGS().SendPointerPacket(GS_RINGTYPE_INIT_READ_FIFO1, 0, out); + GetMTGS().WaitGS(false); // wait without reg sync + } + GSreadFIFO((u64*)out); vif1.GSLastDownloadSize--; GUNIT_LOG("ReadFIFO_VIF1"); if (vif1.GSLastDownloadSize <= 16) diff --git a/pcsx2/GS.h b/pcsx2/GS.h index f9193b4c97..234c59d2c8 100644 --- a/pcsx2/GS.h +++ b/pcsx2/GS.h @@ -247,8 +247,8 @@ enum MTGS_RingCommand , GS_RINGTYPE_CRC , GS_RINGTYPE_GSPACKET , GS_RINGTYPE_MTVU_GSPACKET -, GS_RINGTYPE_READ_FIFO1 -, GS_RINGTYPE_READ_FIFO2 +, GS_RINGTYPE_INIT_READ_FIFO1 +, GS_RINGTYPE_INIT_READ_FIFO2 }; diff --git a/pcsx2/MTGS.cpp b/pcsx2/MTGS.cpp index abafa728a4..dba3a04b45 100644 --- a/pcsx2/MTGS.cpp +++ b/pcsx2/MTGS.cpp @@ -495,14 +495,16 @@ void SysMtgsThread::ExecuteTaskInThread() GSsetGameCRC( tag.data[0], 0 ); break; - case GS_RINGTYPE_READ_FIFO1: + case GS_RINGTYPE_INIT_READ_FIFO1: MTGS_LOG( "(MTGS Packet Read) ringtype=Fifo1" ); - GSreadFIFO( (u64*)tag.data[1]); + if (GSinitReadFIFO) + GSinitReadFIFO( (u64*)tag.data[1]); break; - case GS_RINGTYPE_READ_FIFO2: + case GS_RINGTYPE_INIT_READ_FIFO2: MTGS_LOG( "(MTGS Packet Read) ringtype=Fifo2, size=%d", tag.data[0] ); - GSreadFIFO2( (u64*)tag.data[1], tag.data[0]); + if (GSinitReadFIFO2) + GSinitReadFIFO2( (u64*)tag.data[1], tag.data[0]); break; #ifdef PCSX2_DEVBUILD diff --git a/pcsx2/PluginManager.cpp b/pcsx2/PluginManager.cpp index d8e88d0974..35f530c37c 100644 --- a/pcsx2/PluginManager.cpp +++ b/pcsx2/PluginManager.cpp @@ -156,6 +156,8 @@ _GSgifTransfer3 GSgifTransfer3; _GSgifSoftReset GSgifSoftReset; _GSreadFIFO GSreadFIFO; _GSreadFIFO2 GSreadFIFO2; +_GSinitReadFIFO GSinitReadFIFO; +_GSinitReadFIFO2 GSinitReadFIFO2; _GSchangeSaveState GSchangeSaveState; _GSgetTitleInfo2 GSgetTitleInfo2; _GSmakeSnapshot GSmakeSnapshot; @@ -406,6 +408,8 @@ static const LegacyApi_OptMethod s_MethMessOpt_GS[] = { "GSmakeSnapshot2", (vMeth**)&GSmakeSnapshot2 }, { "GSgifSoftReset", (vMeth**)&GSgifSoftReset }, { "GSreadFIFO", (vMeth**)&GSreadFIFO }, + { "GSinitReadFIFO", (vMeth**)&GSinitReadFIFO }, + { "GSinitReadFIFO2", (vMeth**)&GSinitReadFIFO2 }, { "GSgifTransfer1", (vMeth**)&GSgifTransfer1 }, { NULL } }; diff --git a/pcsx2/Vif1_Dma.cpp b/pcsx2/Vif1_Dma.cpp index af3fdb0238..7dca3f5088 100644 --- a/pcsx2/Vif1_Dma.cpp +++ b/pcsx2/Vif1_Dma.cpp @@ -68,8 +68,11 @@ void vif1TransferToMemory() } GetMTGS().WaitGS(); - GetMTGS().SendPointerPacket(GS_RINGTYPE_READ_FIFO2, size, pMem); - GetMTGS().WaitGS(false); // wait without reg sync + if (GSinitReadFIFO2) { + GetMTGS().SendPointerPacket(GS_RINGTYPE_INIT_READ_FIFO2, size, pMem); + GetMTGS().WaitGS(false); // wait without reg sync + } + GSreadFIFO2((u64*)pMem, size); pMem += size; if(pMem < pMemEnd) { diff --git a/plugins/GSdx/GS.cpp b/plugins/GSdx/GS.cpp index b7fae89a0b..e23c60d907 100644 --- a/plugins/GSdx/GS.cpp +++ b/plugins/GSdx/GS.cpp @@ -542,6 +542,17 @@ EXPORT_C GSwriteCSR(uint32 csr) } } +EXPORT_C GSinitReadFIFO(uint8* mem) +{ + try + { + s_gs->InitReadFIFO(mem, 1); + } + catch (GSDXRecoverableError) + { + } +} + EXPORT_C GSreadFIFO(uint8* mem) { try @@ -553,6 +564,17 @@ EXPORT_C GSreadFIFO(uint8* mem) } } +EXPORT_C GSinitReadFIFO2(uint8* mem, uint32 size) +{ + try + { + s_gs->InitReadFIFO(mem, size); + } + catch (GSDXRecoverableError) + { + } +} + EXPORT_C GSreadFIFO2(uint8* mem, uint32 size) { try diff --git a/plugins/GSdx/GSState.cpp b/plugins/GSdx/GSState.cpp index 2c7995c1ce..d36fe42d8a 100644 --- a/plugins/GSdx/GSState.cpp +++ b/plugins/GSdx/GSState.cpp @@ -30,6 +30,7 @@ GSState::GSState() , m_mt(false) , m_irq(NULL) , m_path3hack(0) + , m_init_read_fifo_supported(false) , m_q(1.0f) , m_texflush(true) , m_vt(this) @@ -1509,10 +1510,13 @@ void GSState::Write(const uint8* mem, int len) m_mem.m_clut.Invalidate(); } -void GSState::Read(uint8* mem, int len) +void GSState::InitReadFIFO(uint8* mem, int len) { if(len <= 0) return; + // Allow to keep compatibility with older PCSX2 + m_init_read_fifo_supported = true; + int sx = m_env.TRXPOS.SSAX; int sy = m_env.TRXPOS.SSAY; int w = m_env.TRXREG.RRW; @@ -1529,6 +1533,30 @@ void GSState::Read(uint8* mem, int len) { InvalidateLocalMem(m_env.BITBLTBUF, GSVector4i(sx, sy, sx + w, sy + h)); } +} + +void GSState::Read(uint8* mem, int len) +{ + if(len <= 0) return; + + int sx = m_env.TRXPOS.SSAX; + int sy = m_env.TRXPOS.SSAY; + int w = m_env.TRXREG.RRW; + int h = m_env.TRXREG.RRH; + + // printf("Read len=%d SBP=%05x SBW=%d SPSM=%d SSAX=%d SSAY=%d RRW=%d RRH=%d\n", len, (int)m_env.BITBLTBUF.SBP, (int)m_env.BITBLTBUF.SBW, (int)m_env.BITBLTBUF.SPSM, sx, sy, w, h); + + if(!m_tr.Update(w, h, GSLocalMemory::m_psm[m_env.BITBLTBUF.SPSM].trbpp, len)) + { + return; + } + + if (!m_init_read_fifo_supported) { + if(m_tr.x == sx && m_tr.y == sy) + { + InvalidateLocalMem(m_env.BITBLTBUF, GSVector4i(sx, sy, sx + w, sy + h)); + } + } m_mem.ReadImageX(m_tr.x, m_tr.y, mem, len, m_env.BITBLTBUF, m_env.TRXPOS, m_env.TRXREG); } diff --git a/plugins/GSdx/GSState.h b/plugins/GSdx/GSState.h index d3c364fa80..1d190ff5fe 100644 --- a/plugins/GSdx/GSState.h +++ b/plugins/GSdx/GSState.h @@ -122,6 +122,7 @@ class GSState : public GSAlignedClass<32> bool m_mt; void (*m_irq)(); bool m_path3hack; + bool m_init_read_fifo_supported; struct GSTransferBuffer { @@ -232,6 +233,7 @@ public: void Move(); void Write(const uint8* mem, int len); void Read(uint8* mem, int len); + void InitReadFIFO(uint8* mem, int len); void SoftReset(uint32 mask); void WriteCSR(uint32 csr) {m_regs->CSR.u32[1] = csr;} diff --git a/plugins/GSdx/GSdx.def b/plugins/GSdx/GSdx.def index 2de7fecd48..c4ecf77fa5 100644 --- a/plugins/GSdx/GSdx.def +++ b/plugins/GSdx/GSdx.def @@ -27,8 +27,10 @@ EXPORTS GSconfigure GStest GSabout - GSreadFIFO - GSreadFIFO2 + GSinitReadFIFO + GSreadFIFO + GSinitReadFIFO2 + GSreadFIFO2 GSirqCallback GSsetupRecording GSsetGameCRC