GS: Fix sub-page addressing of Z formats

They aren't just an offset of the base value like the color formats, but instead an xor of the associated color format
This commit is contained in:
TellowKrinkle 2023-07-22 02:42:14 -05:00 committed by refractionpcsx2
parent 2a6f2939be
commit bced0b91a0
4 changed files with 23 additions and 77 deletions

View File

@ -737,10 +737,7 @@ GSOffset::PageLooper GSOffset::pageLooperForRect(const GSVector4i& rect) const
// e.g. if bp is 1 on PSMCT32, the top left tile uses page 1 if the rect covers the bottom right block, and uses page 0 if the rect covers any block other than the bottom right
// - Center tiles (ones that aren't first or last) cover all blocks that the first and last do in a row
// Therefore, if the first tile in a row touches the higher of its two pages, subsequent non-last tiles will at least touch the higher of their pages as well (and same for center to last, etc)
// Therefore, with the exception of row covering two pages in a z swizzle (which could touch e.g. pages 1 and 3 but not 2), all rows touch contiguous pages
// For now, we won't deal with that case as it's rare (only possible with a thin, unaligned rect on an unaligned bp on a z swizzle), and the worst issue looping too many pages could cause is unneccessary cache invalidation
// If code is added later to deal with the case, you'll need to change loopPagesWithBreak's block deduplication code, as it currently works by forcing the page number to increase monotonically which could cause blocks to be missed if e.g. the first row touches 1 and 3, and the second row touches 2 and 4
// - Based on the above assumption, we calculate the range of pages a row could touch with full coverage, then add one to the start if the first tile doesn't touch its lower page, and subtract one from the end if the last tile doesn't touch its upper page
// - Based on the above, we calculate the range of pages a row could touch with full coverage, then add one to the start if the first tile doesn't touch its lower page, and subtract one from the end if the last tile doesn't touch its upper page
// - This is done separately for the first and last rows in the y axis, as they may not have the same coverage as a row in the middle
PageLooper out;

View File

@ -60,6 +60,8 @@ class GSSwizzleInfo
u8 m_pageShiftY; ///< Amount to rshift y value by to get page offset
u8 m_blockShiftX; ///< Amount to rshift x value by to get offset in block
u8 m_blockShiftY; ///< Amount to rshift y value by to get offset in block
u32 m_blockAddressXor; ///< Value to xor with the final block address (used for Z swizzles)
u32 m_pixelAddressXor; ///< Value to xor with the final pixel address
static constexpr u8 ilog2(u32 i) { return i < 2 ? 0 : 1 + ilog2(i >> 1); }
public:
@ -67,7 +69,7 @@ public:
/// @param blockSize Size of block in pixels
template <int PageWidth, int PageHeight, int BlocksWide, int BlocksHigh, int PixelRowMask>
constexpr GSSwizzleInfo(GSSwizzleTableList<PageHeight, PageWidth, BlocksHigh, BlocksWide, PixelRowMask> list)
constexpr GSSwizzleInfo(GSSwizzleTableList<PageHeight, PageWidth, BlocksHigh, BlocksWide, PixelRowMask> list, u32 blockXor)
: m_blockSwizzle(&list.block)
, m_pixelSwizzleCol(list.col.value)
, m_pixelSwizzleRow(list.row.rows)
@ -76,6 +78,8 @@ public:
, m_pixelRowMask(PixelRowMask)
, m_pageShiftX(ilog2(PageWidth)), m_pageShiftY(ilog2(PageHeight))
, m_blockShiftX(ilog2(PageWidth / BlocksWide)), m_blockShiftY(ilog2(PageHeight / BlocksHigh))
, m_blockAddressXor(blockXor)
, m_pixelAddressXor(blockXor << (m_blockShiftX + m_blockShiftY))
{
static_assert(1 << ilog2(PageWidth) == PageWidth, "PageWidth must be a power of 2");
static_assert(1 << ilog2(PageHeight) == PageHeight, "PageHeight must be a power of 2");
@ -127,6 +131,7 @@ public:
int m_pageMaskX; ///< mask for x value of block coordinate to get position within page (to detect page crossing)
int m_pageMaskY; ///< mask for y value of block coordinate to get position within page (to detect page crossing)
int m_addY; ///< Amount to add to bp to advance one page in y direction
u32 m_xor; ///< XOR mask for final address
public:
BNHelper(const GSOffset& off, int x, int y)
{
@ -139,6 +144,7 @@ public:
m_pageMaskX = (1 << (off.m_pageShiftX - off.m_blockShiftX)) - 1;
m_pageMaskY = (1 << (off.m_pageShiftY - off.m_blockShiftY)) - 1;
m_addY = 32 * off.m_bwPg;
m_xor = off.m_blockAddressXor;
}
/// Get the current x position as an offset in blocks
@ -168,7 +174,7 @@ public:
/// Get the current block number without wrapping at MAX_BLOCKS
u32 valueNoWrap() const
{
return m_bp + m_blockSwizzle->lookup(m_blkX, m_blkY);
return (m_bp + m_blockSwizzle->lookup(m_blkX, m_blkY)) ^ m_xor;
}
/// Get the current block number
@ -217,8 +223,8 @@ public:
fn(bn.value());
}
/// Calculate the pixel address at the given y position with x of 0
int pixelAddressZeroX(int y) const
/// Calculate the pixel address at the given y position with x of 0 minus the final xor
int pixelAddressZeroXRaw(int y) const
{
int base = m_bp << (m_pageShiftX + m_pageShiftY - 5); // Offset from base pointer
base += ((y & ~m_pageMask.y) * m_bwPg) << m_pageShiftX; // Offset from pages in y direction
@ -234,19 +240,21 @@ public:
/// Pixel swizzle array
const int* m_pixelSwizzleRow;
int m_base;
u32 m_xor;
public:
PAHelper() = default;
PAHelper(const GSOffset& off, int x, int y)
{
m_pixelSwizzleRow = off.m_pixelSwizzleRow[y & off.m_pixelRowMask]->value + x;
m_base = off.pixelAddressZeroX(y);
m_base = off.pixelAddressZeroXRaw(y);
m_xor = off.m_pixelAddressXor;
}
/// Get pixel reference for the given x offset from the one used to create the PAHelper
u32 value(int x) const
{
return m_base + m_pixelSwizzleRow[x];
return (m_base + m_pixelSwizzleRow[x]) ^ m_xor;
}
};
@ -467,14 +475,14 @@ public:
GSClut m_clut;
public:
static constexpr GSSwizzleInfo swizzle32 {swizzleTables32};
static constexpr GSSwizzleInfo swizzle32Z {swizzleTables32Z};
static constexpr GSSwizzleInfo swizzle16 {swizzleTables16};
static constexpr GSSwizzleInfo swizzle16S {swizzleTables16S};
static constexpr GSSwizzleInfo swizzle16Z {swizzleTables16Z};
static constexpr GSSwizzleInfo swizzle16SZ {swizzleTables16SZ};
static constexpr GSSwizzleInfo swizzle8 {swizzleTables8};
static constexpr GSSwizzleInfo swizzle4 {swizzleTables4};
static constexpr GSSwizzleInfo swizzle32 {swizzleTables32, 0x00};
static constexpr GSSwizzleInfo swizzle32Z {swizzleTables32, 0x18};
static constexpr GSSwizzleInfo swizzle16 {swizzleTables16, 0x00};
static constexpr GSSwizzleInfo swizzle16S {swizzleTables16S, 0x00};
static constexpr GSSwizzleInfo swizzle16Z {swizzleTables16, 0x18};
static constexpr GSSwizzleInfo swizzle16SZ {swizzleTables16S, 0x18};
static constexpr GSSwizzleInfo swizzle8 {swizzleTables8, 0x00};
static constexpr GSSwizzleInfo swizzle4 {swizzleTables4, 0x00};
protected:
__forceinline static u32 Expand24To32(u32 c, const GIFRegTEXA& TEXA)

View File

@ -37,14 +37,6 @@ static constexpr u8 _blockTable32[4][8] =
{ 10, 11, 14, 15, 26, 27, 30, 31}
};
static constexpr u8 _blockTable32Z[4][8] =
{
{ 24, 25, 28, 29, 8, 9, 12, 13},
{ 26, 27, 30, 31, 10, 11, 14, 15},
{ 16, 17, 20, 21, 0, 1, 4, 5},
{ 18, 19, 22, 23, 2, 3, 6, 7}
};
static constexpr u8 _blockTable16[8][4] =
{
{ 0, 2, 8, 10 },
@ -69,30 +61,6 @@ static constexpr u8 _blockTable16S[8][4] =
{ 13, 15, 29, 31 }
};
static constexpr u8 _blockTable16Z[8][4] =
{
{ 24, 26, 16, 18 },
{ 25, 27, 17, 19 },
{ 28, 30, 20, 22 },
{ 29, 31, 21, 23 },
{ 8, 10, 0, 2 },
{ 9, 11, 1, 3 },
{ 12, 14, 4, 6 },
{ 13, 15, 5, 7 }
};
static constexpr u8 _blockTable16SZ[8][4] =
{
{ 24, 26, 8, 10 },
{ 25, 27, 9, 11 },
{ 16, 18, 0, 2 },
{ 17, 19, 1, 3 },
{ 28, 30, 12, 14 },
{ 29, 31, 13, 15 },
{ 20, 22, 4, 6 },
{ 21, 23, 5, 7 }
};
static constexpr u8 _blockTable8[4][8] =
{
{ 0, 1, 4, 5, 16, 17, 20, 21},
@ -114,11 +82,8 @@ static constexpr u8 _blockTable4[8][4] =
};
constexpr GSSizedBlockSwizzleTable<4, 8> blockTable32 = makeSwizzleTable(_blockTable32);
constexpr GSSizedBlockSwizzleTable<4, 8> blockTable32Z = makeSwizzleTable(_blockTable32Z);
constexpr GSSizedBlockSwizzleTable<8, 4> blockTable16 = makeSwizzleTable(_blockTable16);
constexpr GSSizedBlockSwizzleTable<8, 4> blockTable16S = makeSwizzleTable(_blockTable16S);
constexpr GSSizedBlockSwizzleTable<8, 4> blockTable16Z = makeSwizzleTable(_blockTable16Z);
constexpr GSSizedBlockSwizzleTable<8, 4> blockTable16SZ = makeSwizzleTable(_blockTable16SZ);
constexpr GSSizedBlockSwizzleTable<4, 8> blockTable8 = makeSwizzleTable(_blockTable8);
constexpr GSSizedBlockSwizzleTable<8, 4> blockTable4 = makeSwizzleTable(_blockTable4);
@ -328,20 +293,14 @@ constexpr GSSizedPixelRowOffsetTable<BlocksWide * ColWidth> makeRowOffsetTable(c
}
constexpr GSPixelColOffsetTable< 32> pixelColOffset32 = makeColOffsetTable(_blockTable32, columnTable32);
constexpr GSPixelColOffsetTable< 32> pixelColOffset32Z = makeColOffsetTable(_blockTable32Z, columnTable32);
constexpr GSPixelColOffsetTable< 64> pixelColOffset16 = makeColOffsetTable(_blockTable16, columnTable16);
constexpr GSPixelColOffsetTable< 64> pixelColOffset16S = makeColOffsetTable(_blockTable16S, columnTable16);
constexpr GSPixelColOffsetTable< 64> pixelColOffset16Z = makeColOffsetTable(_blockTable16Z, columnTable16);
constexpr GSPixelColOffsetTable< 64> pixelColOffset16SZ = makeColOffsetTable(_blockTable16SZ, columnTable16);
constexpr GSPixelColOffsetTable< 64> pixelColOffset8 = makeColOffsetTable(_blockTable8, columnTable8);
constexpr GSPixelColOffsetTable<128> pixelColOffset4 = makeColOffsetTable(_blockTable4, columnTable4);
// These can't be constexpr due to a GCC bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99901
CONSTINIT const GSSizedPixelRowOffsetTable< 64> GSTables::_pixelRowOffset32 = makeRowOffsetTable(_blockTable32, columnTable32, 0);
CONSTINIT const GSSizedPixelRowOffsetTable< 64> GSTables::_pixelRowOffset32Z = makeRowOffsetTable(_blockTable32Z, columnTable32, 0);
CONSTINIT const GSSizedPixelRowOffsetTable< 64> GSTables::_pixelRowOffset16 = makeRowOffsetTable(_blockTable16, columnTable16, 0);
CONSTINIT const GSSizedPixelRowOffsetTable< 64> GSTables::_pixelRowOffset16S = makeRowOffsetTable(_blockTable16S, columnTable16, 0);
CONSTINIT const GSSizedPixelRowOffsetTable< 64> GSTables::_pixelRowOffset16Z = makeRowOffsetTable(_blockTable16Z, columnTable16, 0);
CONSTINIT const GSSizedPixelRowOffsetTable< 64> GSTables::_pixelRowOffset16SZ = makeRowOffsetTable(_blockTable16SZ, columnTable16, 0);
CONSTINIT const GSSizedPixelRowOffsetTable<128> GSTables::_pixelRowOffset8[2] =
{
makeRowOffsetTable(_blockTable8, columnTable8, 0),
@ -354,10 +313,7 @@ CONSTINIT const GSSizedPixelRowOffsetTable<128> GSTables::_pixelRowOffset4[2] =
};
constexpr GSPixelRowOffsetTableList< 64, 0> GSTables::pixelRowOffset32;
constexpr GSPixelRowOffsetTableList< 64, 0> GSTables::pixelRowOffset32Z;
constexpr GSPixelRowOffsetTableList< 64, 0> GSTables::pixelRowOffset16;
constexpr GSPixelRowOffsetTableList< 64, 0> GSTables::pixelRowOffset16S;
constexpr GSPixelRowOffsetTableList< 64, 0> GSTables::pixelRowOffset16Z;
constexpr GSPixelRowOffsetTableList< 64, 0> GSTables::pixelRowOffset16SZ;
constexpr GSPixelRowOffsetTableList<128, 7> GSTables::pixelRowOffset8;
constexpr GSPixelRowOffsetTableList<128, 7> GSTables::pixelRowOffset4;

View File

@ -102,11 +102,8 @@ makeSwizzleTableList(
}
extern const GSSizedBlockSwizzleTable<4, 8> blockTable32;
extern const GSSizedBlockSwizzleTable<4, 8> blockTable32Z;
extern const GSSizedBlockSwizzleTable<8, 4> blockTable16;
extern const GSSizedBlockSwizzleTable<8, 4> blockTable16S;
extern const GSSizedBlockSwizzleTable<8, 4> blockTable16Z;
extern const GSSizedBlockSwizzleTable<8, 4> blockTable16SZ;
extern const GSSizedBlockSwizzleTable<4, 8> blockTable8;
extern const GSSizedBlockSwizzleTable<8, 4> blockTable4;
extern const u8 columnTable32[8][8];
@ -118,11 +115,8 @@ extern const u8 clutTableT32I4[16];
extern const u8 clutTableT16I8[32];
extern const u8 clutTableT16I4[16];
extern const GSPixelColOffsetTable< 32> pixelColOffset32;
extern const GSPixelColOffsetTable< 32> pixelColOffset32Z;
extern const GSPixelColOffsetTable< 64> pixelColOffset16;
extern const GSPixelColOffsetTable< 64> pixelColOffset16S;
extern const GSPixelColOffsetTable< 64> pixelColOffset16Z;
extern const GSPixelColOffsetTable< 64> pixelColOffset16SZ;
extern const GSPixelColOffsetTable< 64> pixelColOffset8;
extern const GSPixelColOffsetTable<128> pixelColOffset4;
@ -145,29 +139,20 @@ constexpr GSPixelRowOffsetTableList<PageWidth, 7> makeRowOffsetTableList(
struct GSTables
{
static const GSSizedPixelRowOffsetTable< 64> _pixelRowOffset32;
static const GSSizedPixelRowOffsetTable< 64> _pixelRowOffset32Z;
static const GSSizedPixelRowOffsetTable< 64> _pixelRowOffset16;
static const GSSizedPixelRowOffsetTable< 64> _pixelRowOffset16S;
static const GSSizedPixelRowOffsetTable< 64> _pixelRowOffset16Z;
static const GSSizedPixelRowOffsetTable< 64> _pixelRowOffset16SZ;
static const GSSizedPixelRowOffsetTable<128> _pixelRowOffset8[2];
static const GSSizedPixelRowOffsetTable<128> _pixelRowOffset4[2];
static constexpr auto pixelRowOffset32 = makeRowOffsetTableList(&_pixelRowOffset32);
static constexpr auto pixelRowOffset32Z = makeRowOffsetTableList(&_pixelRowOffset32Z);
static constexpr auto pixelRowOffset16 = makeRowOffsetTableList(&_pixelRowOffset16);
static constexpr auto pixelRowOffset16S = makeRowOffsetTableList(&_pixelRowOffset16S);
static constexpr auto pixelRowOffset16Z = makeRowOffsetTableList(&_pixelRowOffset16Z);
static constexpr auto pixelRowOffset16SZ = makeRowOffsetTableList(&_pixelRowOffset16SZ);
static constexpr auto pixelRowOffset8 = makeRowOffsetTableList(&_pixelRowOffset8[0], &_pixelRowOffset8[1]);
static constexpr auto pixelRowOffset4 = makeRowOffsetTableList(&_pixelRowOffset4[0], &_pixelRowOffset4[1]);
};
constexpr auto swizzleTables32 = makeSwizzleTableList(blockTable32, pixelColOffset32, GSTables::pixelRowOffset32 );
constexpr auto swizzleTables32Z = makeSwizzleTableList(blockTable32Z, pixelColOffset32Z, GSTables::pixelRowOffset32Z );
constexpr auto swizzleTables16 = makeSwizzleTableList(blockTable16, pixelColOffset16, GSTables::pixelRowOffset16 );
constexpr auto swizzleTables16Z = makeSwizzleTableList(blockTable16Z, pixelColOffset16Z, GSTables::pixelRowOffset16Z );
constexpr auto swizzleTables16S = makeSwizzleTableList(blockTable16S, pixelColOffset16S, GSTables::pixelRowOffset16S );
constexpr auto swizzleTables16SZ = makeSwizzleTableList(blockTable16SZ, pixelColOffset16SZ, GSTables::pixelRowOffset16SZ);
constexpr auto swizzleTables8 = makeSwizzleTableList(blockTable8, pixelColOffset8, GSTables::pixelRowOffset8 );
constexpr auto swizzleTables4 = makeSwizzleTableList(blockTable4, pixelColOffset4, GSTables::pixelRowOffset4 );