GS: Compensate for misaligned 24bit partial local->host transfers

This commit is contained in:
refractionpcsx2 2023-03-19 18:40:51 +00:00
parent fc88d1de85
commit 3a042d8c14
4 changed files with 28 additions and 15 deletions

View File

@ -460,7 +460,7 @@ public:
typedef u32 (GSLocalMemory::*readPixelAddr)(u32 addr) const; typedef u32 (GSLocalMemory::*readPixelAddr)(u32 addr) const;
typedef u32 (GSLocalMemory::*readTexelAddr)(u32 addr, const GIFRegTEXA& TEXA) const; typedef u32 (GSLocalMemory::*readTexelAddr)(u32 addr, const GIFRegTEXA& TEXA) const;
typedef void (*writeImage)(GSLocalMemory& mem, int& tx, int& ty, const u8* src, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG); typedef void (*writeImage)(GSLocalMemory& mem, int& tx, int& ty, const u8* src, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG);
typedef void (*readImage)(const GSLocalMemory& mem, int& tx, int& ty, u8* dst, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG); typedef void (*readImage)(const GSLocalMemory& mem, int& tx, int& ty, int& offset, u8* dst, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG);
typedef void (*readTexture)(GSLocalMemory& mem, const GSOffset& off, const GSVector4i& r, u8* dst, int dstpitch, const GIFRegTEXA& TEXA); typedef void (*readTexture)(GSLocalMemory& mem, const GSOffset& off, const GSVector4i& r, u8* dst, int dstpitch, const GIFRegTEXA& TEXA);
typedef void (*readTextureBlock)(const GSLocalMemory& mem, u32 bp, u8* dst, int dstpitch, const GIFRegTEXA& TEXA); typedef void (*readTextureBlock)(const GSLocalMemory& mem, u32 bp, u8* dst, int dstpitch, const GIFRegTEXA& TEXA);
@ -1123,9 +1123,9 @@ public:
return ReadTexel16(PixelAddress16SZ(x, y, TEX0.TBP0, TEX0.TBW), TEXA); return ReadTexel16(PixelAddress16SZ(x, y, TEX0.TBP0, TEX0.TBW), TEXA);
} }
__forceinline void ReadImageX(int& tx, int& ty, u8* dst, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG) const __forceinline void ReadImageX(int& tx, int& ty, int& offset, u8* dst, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG) const
{ {
m_readImageX(*this, tx, ty, dst, len, BITBLTBUF, TRXPOS, TRXREG); m_readImageX(*this, tx, ty, offset, dst, len, BITBLTBUF, TRXPOS, TRXREG);
} }
void ReadTexture(const GSOffset& off, const GSVector4i& r, u8* dst, int dstpitch, const GIFRegTEXA& TEXA); void ReadTexture(const GSOffset& off, const GSVector4i& r, u8* dst, int dstpitch, const GIFRegTEXA& TEXA);

View File

@ -87,7 +87,7 @@ class CURRENT_ISA::GSLocalMemoryFunctions
static void ReadTexture(GSLocalMemory& mem, const GSOffset& off, const GSVector4i& r, u8* dst, int dstpitch, const GIFRegTEXA& TEXA); static void ReadTexture(GSLocalMemory& mem, const GSOffset& off, const GSVector4i& r, u8* dst, int dstpitch, const GIFRegTEXA& TEXA);
public: public:
static void ReadImageX(const GSLocalMemory& mem, int& tx, int& ty, u8* dst, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG); static void ReadImageX(const GSLocalMemory& mem, int& tx, int& ty, int& offset, u8* dst, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG);
static void PopulateFunctions(GSLocalMemory& mem); static void PopulateFunctions(GSLocalMemory& mem);
}; };
@ -931,7 +931,7 @@ void GSLocalMemoryFunctions::WriteImageX(GSLocalMemory& mem, int& tx, int& ty, c
// //
void GSLocalMemoryFunctions::ReadImageX(const GSLocalMemory& mem, int& tx, int& ty, u8* dst, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG) void GSLocalMemoryFunctions::ReadImageX(const GSLocalMemory& mem, int& tx, int& ty, int& offset, u8* dst, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG)
{ {
if (len <= 0) if (len <= 0)
return; return;
@ -1005,16 +1005,23 @@ void GSLocalMemoryFunctions::ReadImageX(const GSLocalMemory& mem, int& tx, int&
case PSM_PSMCT24: case PSM_PSMCT24:
case PSM_PSMZ24: case PSM_PSMZ24:
readWriteHelper(mem.vm32(), tx, ty, len / 3, 1, sx, w, off.assertSizesMatch(GSLocalMemory::swizzle32), [&](auto& pa, int x) {
const int length = len / 3;
const int aligned_length = (len + 2) / 3;
if (length != aligned_length)
{ {
u32 c = *pa.value(x); offset = 3 - (len - (length * 3));
pb[0] = (u8)(c); }
pb[1] = (u8)(c >> 8); readWriteHelper(mem.vm32(), tx, ty, aligned_length, 1, sx, w, off.assertSizesMatch(GSLocalMemory::swizzle32), [&](auto& pa, int x)
pb[2] = (u8)(c >> 16); {
pb += 3; u32 c = *pa.value(x);
}); pb[0] = (u8)(c);
pb[1] = (u8)(c >> 8);
pb[2] = (u8)(c >> 16);
pb += 3;
});
break; break;
}
case PSM_PSMCT16: case PSM_PSMCT16:
case PSM_PSMCT16S: case PSM_PSMCT16S:
case PSM_PSMZ16: case PSM_PSMZ16:

View File

@ -1845,7 +1845,9 @@ void GSState::Read(u8* mem, int len)
if (!m_tr.Update(w, h, bpp, len)) if (!m_tr.Update(w, h, bpp, len))
return; return;
m_mem.ReadImageX(m_tr.x, m_tr.y, mem, len, m_env.BITBLTBUF, m_env.TRXPOS, m_env.TRXREG); mem += m_tr.offset;
len -= m_tr.offset;
m_mem.ReadImageX(m_tr.x, m_tr.y, m_tr.offset, mem, len, m_env.BITBLTBUF, m_env.TRXPOS, m_env.TRXREG);
if (GSConfig.DumpGSData && GSConfig.SaveRT && s_n >= GSConfig.SaveN) if (GSConfig.DumpGSData && GSConfig.SaveRT && s_n >= GSConfig.SaveN)
{ {
@ -2136,7 +2138,9 @@ void GSState::ReadLocalMemoryUnsync(u8* mem, int qwc, GIFRegBITBLTBUF BITBLTBUF,
if (!tb.Update(w, h, bpp, len)) if (!tb.Update(w, h, bpp, len))
return; return;
m_mem.ReadImageX(tb.x, tb.y, mem, len, BITBLTBUF, TRXPOS, TRXREG); mem += tb.offset;
len -= tb.offset;
m_mem.ReadImageX(tb.x, tb.y, tb.offset, mem, len, BITBLTBUF, TRXPOS, TRXREG);
} }
void GSState::PurgePool() void GSState::PurgePool()
@ -3900,6 +3904,7 @@ void GSState::GSTransferBuffer::Init(int tx, int ty, const GIFRegBITBLTBUF& blit
x = tx; x = tx;
y = ty; y = ty;
total = 0; total = 0;
offset = 0;
m_blit = blit; m_blit = blit;
} }

View File

@ -123,6 +123,7 @@ private:
{ {
int x = 0, y = 0; int x = 0, y = 0;
int start = 0, end = 0, total = 0; int start = 0, end = 0, total = 0;
int offset = 0;
u8* buff = nullptr; u8* buff = nullptr;
GIFRegBITBLTBUF m_blit = {}; GIFRegBITBLTBUF m_blit = {};