GS/HW: Handle offset RTs when offset texture is detected

Catwoman draws to the target at 2E60 via 2D00, one page back
horizontally, and one vertically.

The Destroy All Humans fix also works here, but it only applied to the
texture, not the RT. So do a very conservative form of RT-in-RT to
handle Catwoman.

Unfortunately nothing else benefits from it.
This commit is contained in:
Stenzek 2024-01-04 15:28:49 +10:00 committed by Connor McLaughlin
parent 0fb234f3e4
commit a247625095
3 changed files with 33 additions and 0 deletions

View File

@ -6592,6 +6592,24 @@ void GSRendererHW::ReplaceVerticesWithSprite(const GSVector4i& unscaled_rect, co
ReplaceVerticesWithSprite(unscaled_rect, unscaled_rect, unscaled_size, unscaled_rect);
}
void GSRendererHW::OffsetDraw(s32 fbp_offset, s32 zbp_offset, s32 xoffset, s32 yoffset)
{
GL_INS("Offseting render target by %d pages [%x -> %x], Z by %d pages [%x -> %x]",
fbp_offset, m_cached_ctx.FRAME.FBP << 5, zbp_offset, (m_cached_ctx.FRAME.FBP + fbp_offset) << 5);
GL_INS("Offseting vertices by [%d, %d]", xoffset, yoffset);
m_cached_ctx.FRAME.FBP += fbp_offset;
m_cached_ctx.ZBUF.ZBP += zbp_offset;
const s32 fp_xoffset = xoffset << 4;
const s32 fp_yoffset = yoffset << 4;
for (u32 i = 0; i < m_vertex.next; i++)
{
m_vertex.buff[i].XYZ.X += fp_xoffset;
m_vertex.buff[i].XYZ.Y += fp_yoffset;
}
}
GSHWDrawConfig& GSRendererHW::BeginHLEHardwareDraw(
GSTexture* rt, GSTexture* ds, float rt_scale, GSTexture* tex, float tex_scale, const GSVector4i& unscaled_rect)
{

View File

@ -217,6 +217,9 @@ public:
/// Returns true if the specified texture address matches the frame or Z buffer.
bool IsTBPFrameOrZ(u32 tbp) const;
/// Offsets the current draw, used for RT-in-RT. Offsets are relative to the *current* FBP, not the new FBP.
void OffsetDraw(s32 fbp_offset, s32 zbp_offset, s32 xoffset, s32 yoffset);
/// Replaces vertices with the specified fullscreen quad.
void ReplaceVerticesWithSprite(const GSVector4i& unscaled_rect, const GSVector4i& unscaled_uv_rect,
const GSVector2i& unscaled_size, const GSVector4i& scissor);

View File

@ -1541,6 +1541,18 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
dst = t;
tex_merge_rt = false;
found_t = true;
// Catwoman offsets the RT as well as the texture.
if (GSRendererHW::GetInstance()->GetCachedCtx()->FRAME.Block() == TEX0.TBP0)
{
// Should be page aligned.
pxAssert(((t->m_TEX0.TBP0 - TEX0.TBP0) % 32) == 0);
const s32 page_offset = (t->m_TEX0.TBP0 - TEX0.TBP0) >> 5;
GL_CACHE("TC: RT also in front of TBP, offsetting draw by %d pages and [%d,%d].", page_offset, x_offset, y_offset);
GSRendererHW::GetInstance()->OffsetDraw(page_offset, page_offset, x_offset, y_offset);
break;
}
if (dst->m_TEX0.TBP0 == frame_fbp && possible_shuffle)
break;
else