GS/TextureCache: Flush dirty areas of textures during TC move

Dark Cloud does a bunch of VRAM writes overlapping the render target,
then moves over the top of it. If we didn't flush these, the target
would still be considered dirty, and later we'd trash the move
destination, and/or not use it as a source.
This commit is contained in:
Connor McLaughlin 2022-05-10 00:53:27 +10:00 committed by refractionpcsx2
parent bd3e1299a3
commit c88db3221c
2 changed files with 25 additions and 0 deletions

View File

@ -1069,6 +1069,11 @@ bool GSTextureCache::Move(u32 SBP, u32 SBW, u32 SPSM, int sx, int sy, u32 DBP, u
if (!src || !dst || src->m_texture->GetScale() != dst->m_texture->GetScale())
return false;
// We don't want to copy "old" data that the game has overwritten with writes,
// so flush any overlapping dirty area.
src->UpdateIfDirtyIntersects(GSVector4i(sx, sy, sx + w, sy + h));;
dst->UpdateIfDirtyIntersects(GSVector4i(dx, dy, dx + w, dy + h));
// Scale coordinates.
const GSVector2 scale(src->m_texture->GetScale());
const int scaled_sx = static_cast<int>(sx * scale.x);
@ -2233,6 +2238,23 @@ void GSTextureCache::Target::Update()
UpdateValidity(r);
}
void GSTextureCache::Target::UpdateIfDirtyIntersects(const GSVector4i& rc)
{
for (const auto& dirty : m_dirty)
{
const GSVector4i dirty_rc(dirty.GetDirtyRect(m_TEX0));
if (dirty_rc.rintersect(rc).rempty())
continue;
// strictly speaking, we only need to update the area outside of the move.
// but, to keep things simple, just update the whole thing
GL_CACHE("TC: Update dirty rectangle [%d,%d,%d,%d] due to intersection with [%d,%d,%d,%d]",
dirty_rc.x, dirty_rc.y, dirty_rc.z, dirty_rc.w, rc.x, rc.y, rc.z, rc.w);
Update();
break;
}
}
void GSTextureCache::Target::UpdateValidity(const GSVector4i& rect)
{
m_valid = m_valid.runion(rect);

View File

@ -200,6 +200,9 @@ public:
void UpdateValidity(const GSVector4i& rect);
void Update();
/// Updates the target, if the dirty area intersects with the specified rectangle.
void UpdateIfDirtyIntersects(const GSVector4i& rc);
};
class PaletteMap