mirror of https://github.com/PCSX2/pcsx2.git
GS/HW: Handle end-of-memory wrapping for surface Overlaps()
This commit is contained in:
parent
753efd8c4a
commit
e08ae7e8fa
|
@ -180,6 +180,12 @@ public:
|
|||
return BNHelper(*this, x, y).value();
|
||||
}
|
||||
|
||||
/// Get the block number of the given pixel, without wrapping to MAX_BLOCKS
|
||||
u32 bnNoWrap(int x, int y) const
|
||||
{
|
||||
return BNHelper(*this, x, y).valueNoWrap();
|
||||
}
|
||||
|
||||
/// Get a helper class for efficiently calculating multiple block numbers
|
||||
BNHelper bnMulti(int x, int y) const
|
||||
{
|
||||
|
|
|
@ -1258,8 +1258,7 @@ void GSTextureCache::InvalidateVideoMem(const GSOffset& off, const GSVector4i& r
|
|||
return;
|
||||
|
||||
// Handle the case where the transfer wrapped around the end of GS memory.
|
||||
const u32 end_bp = off.bn(rect.z - 1, rect.w - 1);
|
||||
const u32 unwrapped_end_bp = end_bp + ((end_bp < bp) ? MAX_BLOCKS : 0);
|
||||
const u32 end_bp = off.bnNoWrap(rect.z - 1, rect.w - 1);
|
||||
|
||||
// Ideally in the future we can turn this on unconditionally, but for now it breaks too much.
|
||||
const bool check_inside_target = (GSConfig.UserHacks_TargetPartialInvalidation || GSConfig.UserHacks_TextureInsideRt);
|
||||
|
@ -1275,7 +1274,7 @@ void GSTextureCache::InvalidateVideoMem(const GSOffset& off, const GSVector4i& r
|
|||
Target* t = *j;
|
||||
|
||||
// Don't bother checking any further if the target doesn't overlap with the write/invalidation.
|
||||
if ((bp < t->m_TEX0.TBP0 && unwrapped_end_bp < t->m_TEX0.TBP0) || bp > t->UnwrappedEndBlock())
|
||||
if ((bp < t->m_TEX0.TBP0 && end_bp < t->m_TEX0.TBP0) || bp > t->UnwrappedEndBlock())
|
||||
{
|
||||
++i;
|
||||
continue;
|
||||
|
@ -2927,21 +2926,23 @@ void GSTextureCache::Surface::UpdateAge()
|
|||
bool GSTextureCache::Surface::Inside(u32 bp, u32 bw, u32 psm, const GSVector4i& rect)
|
||||
{
|
||||
// Valid only for color formats.
|
||||
const u32 end_block = GSLocalMemory::m_psm[psm].info.bn(rect.z - 1, rect.w - 1, bp, bw);
|
||||
return bp >= m_TEX0.TBP0 && end_block <= m_end_block;
|
||||
const GSOffset off(GSLocalMemory::m_psm[psm].info, bp, bw, psm);
|
||||
const u32 end_block = off.bnNoWrap(rect.z - 1, rect.w - 1);
|
||||
return bp >= m_TEX0.TBP0 && end_block <= UnwrappedEndBlock();
|
||||
}
|
||||
|
||||
bool GSTextureCache::Surface::Overlaps(u32 bp, u32 bw, u32 psm, const GSVector4i& rect)
|
||||
{
|
||||
// Valid only for color formats.
|
||||
u32 end_block = GSLocalMemory::m_psm[psm].info.bn(rect.z - 1, rect.w - 1, bp, bw);
|
||||
u32 start_block = GSLocalMemory::m_psm[psm].info.bn(rect.x, rect.y, bp, bw);
|
||||
const GSOffset off(GSLocalMemory::m_psm[psm].info, bp, bw, psm);
|
||||
u32 end_block = off.bnNoWrap(rect.z - 1, rect.w - 1);
|
||||
u32 start_block = off.bnNoWrap(rect.x, rect.y);
|
||||
// Due to block ordering, end can be below start in a page, so if it's within a page, swap them.
|
||||
if (end_block < start_block && ((start_block - end_block) < (1 << 5)))
|
||||
{
|
||||
std::swap(start_block, end_block);
|
||||
}
|
||||
const bool overlap = GSTextureCache::CheckOverlap(m_TEX0.TBP0, m_end_block, start_block, end_block);
|
||||
const bool overlap = GSTextureCache::CheckOverlap(m_TEX0.TBP0, UnwrappedEndBlock(), start_block, end_block);
|
||||
return overlap;
|
||||
}
|
||||
|
||||
|
|
|
@ -132,6 +132,13 @@ public:
|
|||
Surface();
|
||||
virtual ~Surface();
|
||||
|
||||
/// Returns true if the target wraps around the end of GS memory.
|
||||
bool Wraps() const { return (m_end_block < m_TEX0.TBP0); }
|
||||
|
||||
/// Returns the end block for the target, but doesn't wrap at 0x3FFF.
|
||||
/// Can be used for overlap tests.
|
||||
u32 UnwrappedEndBlock() const { return (m_end_block + (Wraps() ? MAX_BLOCKS : 0)); }
|
||||
|
||||
void UpdateAge();
|
||||
bool Inside(u32 bp, u32 bw, u32 psm, const GSVector4i& rect);
|
||||
bool Overlaps(u32 bp, u32 bw, u32 psm, const GSVector4i& rect);
|
||||
|
@ -249,13 +256,6 @@ public:
|
|||
Target(const GIFRegTEX0& TEX0, const bool depth_supported, const int type);
|
||||
~Target();
|
||||
|
||||
/// Returns true if the target wraps around the end of GS memory.
|
||||
bool Wraps() const { return (m_end_block < m_TEX0.TBP0); }
|
||||
|
||||
/// Returns the end block for the target, but doesn't wrap at 0x3FFF.
|
||||
/// Can be used for overlap tests.
|
||||
u32 UnwrappedEndBlock() const { return (m_end_block + (Wraps() ? MAX_BLOCKS : 0)); }
|
||||
|
||||
void ResizeValidity(const GSVector4i& rect);
|
||||
void UpdateValidity(const GSVector4i& rect, bool can_resize = true);
|
||||
void UpdateValidBits(u32 bits_written);
|
||||
|
|
Loading…
Reference in New Issue