GS-hw, TC: search tex in rt in dirty targets.

Also move any target BW update from InvalidateVideoMem to LookupTarget.
Fixes Indiana Jones map rendering in cutscenes.
This commit is contained in:
iMineLink 2020-12-23 13:21:44 +01:00 committed by refractionpcsx2
parent 44d0966892
commit c1e5e45431
1 changed files with 25 additions and 6 deletions

View File

@ -288,7 +288,8 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con
bool found_t = false;
for (auto t : m_dst[RenderTarget])
{
if (t->m_used && t->m_dirty.empty())
const bool t_clean = t->m_dirty.empty();
if (t->m_used)
{
// Typical bug (MGS3 blue cloud):
// 1/ RT used as 32 bits => alpha channel written
@ -299,7 +300,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con
// Solution: consider the RT as 32 bits if the alpha was used in the past
u32 t_psm = (t->m_dirty_alpha) ? t->m_TEX0.PSM & ~0x1 : t->m_TEX0.PSM;
if (GSUtil::HasSharedBits(bp, psm, t->m_TEX0.TBP0, t_psm))
if (t_clean && GSUtil::HasSharedBits(bp, psm, t->m_TEX0.TBP0, t_psm))
{
// It is a complex to convert the code in shader. As a reference, let's do it on the CPU, it will be slow but
// 1/ it just works :)
@ -316,7 +317,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con
found_t = true;
break;
}
else if ((t->m_TEX0.TBW >= 16) && GSUtil::HasSharedBits(bp, psm, t->m_TEX0.TBP0 + t->m_TEX0.TBW * 0x10, t->m_TEX0.PSM))
else if (t_clean && (t->m_TEX0.TBW >= 16) && GSUtil::HasSharedBits(bp, psm, t->m_TEX0.TBP0 + t->m_TEX0.TBW * 0x10, t->m_TEX0.PSM))
{
// Detect half of the render target (fix snow engine game)
// Target Page (8KB) have always a width of 64 pixels
@ -678,6 +679,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(const GIFRegTEX0& TEX0, int
}
else
{
dst->m_TEX0.TBW = TEX0.TBW;
dst->Update();
}
@ -877,7 +879,6 @@ void GSTextureCache::InvalidateVideoMem(const GSOffset& off, const GSVector4i& r
GL_CACHE("TC: Dirty Target(%s) %d (0x%x) r(%d,%d,%d,%d)", to_string(type),
t->m_texture ? t->m_texture->GetID() : 0,
t->m_TEX0.TBP0, r.x, r.y, r.z, r.w);
t->m_TEX0.TBW = bw;
t->m_dirty.push_back(GSDirtyRect(r, psm, bw));
}
else
@ -917,7 +918,6 @@ void GSTextureCache::InvalidateVideoMem(const GSOffset& off, const GSVector4i& r
t->m_texture ? t->m_texture->GetID() : 0,
t->m_TEX0.TBP0);
// TODO: do not add this rect above too
t->m_TEX0.TBW = bw;
t->m_dirty.push_back(GSDirtyRect(GSVector4i(r.left, r.top - y, r.right, r.bottom - y), psm, bw));
continue;
}
@ -945,7 +945,6 @@ void GSTextureCache::InvalidateVideoMem(const GSOffset& off, const GSVector4i& r
t->m_TEX0.TBP0, t->m_end_block,
r.left, r.top + y, r.right, r.bottom + y, bw);
t->m_TEX0.TBW = bw;
t->m_dirty.push_back(GSDirtyRect(GSVector4i(r.left, r.top + y, r.right, r.bottom + y), psm, bw));
continue;
}
@ -2422,6 +2421,26 @@ GSTextureCache::SurfaceOffset GSTextureCache::ComputeSurfaceOffset(const uint32_
sok.elems[1].psm = t->m_TEX0.PSM;
sok.elems[1].rect = t->m_valid;
const SurfaceOffset so = ComputeSurfaceOffset(sok);
// Check if any dirty rect in the target overlaps with the offset.
if (so.is_valid && !t->m_dirty.empty())
{
const SurfaceOffsetKeyElem& t_sok = sok.elems[1];
const GSLocalMemory::psm_t& t_psm_s = GSLocalMemory::m_psm[t_sok.psm];
const u32 so_bp = t_psm_s.info.bn(so.b2a_offset.x, so.b2a_offset.y, t_sok.bp, t_sok.bw);
const u32 so_bp_end = t_psm_s.info.bn(so.b2a_offset.z - 1, so.b2a_offset.w - 1, t_sok.bp, t_sok.bw);
for (const auto& dr : t->m_dirty)
{
const GSLocalMemory::psm_t& dr_psm_s = GSLocalMemory::m_psm[dr.psm];
const u32 dr_bp = dr_psm_s.info.bn(dr.r.x, dr.r.y, t_sok.bp, dr.bw);
const u32 dr_bp_end = dr_psm_s.info.bn(dr.r.z - 1, dr.r.w - 1, t_sok.bp, dr.bw);
const bool overlap = GSTextureCache::CheckOverlap(dr_bp, dr_bp_end, so_bp, so_bp_end);
if (overlap)
{
// Dirty rectangle in target overlaps with the found offset.
return { false };
}
}
}
return so;
}