mirror of https://github.com/PCSX2/pcsx2.git
GS: Fix looping over pages of textures with massive strides
This commit is contained in:
parent
cb18f11133
commit
013c292ffb
|
@ -1819,6 +1819,8 @@ GSOffset::PageLooper GSOffset::pageLooperForRect(const GSVector4i& rect) const
|
|||
out.yCnt = botPg - topPg;
|
||||
out.firstRowPgXStart = out.midRowPgXStart = out.lastRowPgXStart = rect.left >> m_pageShiftX;
|
||||
out.firstRowPgXEnd = out.midRowPgXEnd = out.lastRowPgXEnd = ((rect.right + m_pageMask.x) >> m_pageShiftX) + !aligned;
|
||||
out.slowPath = static_cast<u32>(out.yCnt * out.yInc + out.midRowPgXEnd - out.midRowPgXStart) > MAX_PAGES;
|
||||
|
||||
// Page-aligned bp is easy, all tiles touch their lower page but not the upper
|
||||
if (aligned)
|
||||
return out;
|
||||
|
|
|
@ -310,6 +310,7 @@ public:
|
|||
int bp; ///< Page offset of y=top x=0
|
||||
int yInc; ///< Amount to add to bp when increasing y by one page
|
||||
int yCnt; ///< Number of pages the rect covers in the y direction
|
||||
bool slowPath; ///< True if the texture is big enough to wrap around GS memory and overlap itself
|
||||
|
||||
friend class GSOffset;
|
||||
|
||||
|
@ -320,30 +321,66 @@ public:
|
|||
void loopPagesWithBreak(Fn&& fn) const
|
||||
{
|
||||
int lineBP = bp;
|
||||
int nextMin = 0;
|
||||
|
||||
int startOff = firstRowPgXStart;
|
||||
int endOff = firstRowPgXEnd;
|
||||
int yCnt = this->yCnt;
|
||||
for (int y = 0; y < yCnt; y++)
|
||||
{
|
||||
int start = std::max(nextMin, lineBP + startOff);
|
||||
int end = lineBP + endOff;
|
||||
nextMin = end;
|
||||
lineBP += yInc;
|
||||
for (int pos = start; pos < end; pos++)
|
||||
if (!fn(pos % MAX_PAGES))
|
||||
return;
|
||||
|
||||
if (y < yCnt - 1)
|
||||
if (unlikely(slowPath))
|
||||
{
|
||||
u32 touched[MAX_PAGES / 32] = {};
|
||||
for (int y = 0; y < yCnt; y++)
|
||||
{
|
||||
startOff = midRowPgXStart;
|
||||
endOff = midRowPgXEnd;
|
||||
u32 start = lineBP + startOff;
|
||||
u32 end = lineBP + endOff;
|
||||
lineBP += yInc;
|
||||
for (u32 pos = start; pos < end; pos++)
|
||||
{
|
||||
u32 page = pos % MAX_PAGES;
|
||||
u32 idx = page / 32;
|
||||
u32 mask = 1 << (page % 32);
|
||||
if (touched[idx] & mask)
|
||||
continue;
|
||||
if (!fn(page))
|
||||
return;
|
||||
touched[idx] |= mask;
|
||||
}
|
||||
|
||||
if (y < yCnt - 1)
|
||||
{
|
||||
startOff = midRowPgXStart;
|
||||
endOff = midRowPgXEnd;
|
||||
}
|
||||
else
|
||||
{
|
||||
startOff = lastRowPgXStart;
|
||||
endOff = lastRowPgXEnd;
|
||||
}
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 nextMin = 0;
|
||||
|
||||
for (int y = 0; y < yCnt; y++)
|
||||
{
|
||||
startOff = lastRowPgXStart;
|
||||
endOff = lastRowPgXEnd;
|
||||
u32 start = std::max<u32>(nextMin, lineBP + startOff);
|
||||
u32 end = lineBP + endOff;
|
||||
nextMin = end;
|
||||
lineBP += yInc;
|
||||
for (u32 pos = start; pos < end; pos++)
|
||||
if (!fn(pos % MAX_PAGES))
|
||||
return;
|
||||
|
||||
if (y < yCnt - 1)
|
||||
{
|
||||
startOff = midRowPgXStart;
|
||||
endOff = midRowPgXEnd;
|
||||
}
|
||||
else
|
||||
{
|
||||
startOff = lastRowPgXStart;
|
||||
endOff = lastRowPgXEnd;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue