Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 2 commits into from
Jan 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions bin/resources/GameIndex.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18328,6 +18328,11 @@ SLES-52563:
SLES-52567:
name: "Catwoman"
region: "PAL-M7"
gsHWFixes:
recommendedBlendingLevel: 4 # Fixes bloom.
autoFlush: 1 # Fixes ghosting.
textureInsideRT: 1 # Required for offset RTs/textures for post-processing.
roundSprite: 2 # Fixes misaligned post-processing.
SLES-52568:
name: "Crash Twinsanity"
region: "PAL-M5"
Expand Down Expand Up @@ -60461,6 +60466,11 @@ SLUS-20992:
name: "Catwoman"
region: "NTSC-U"
compat: 5
gsHWFixes:
recommendedBlendingLevel: 4 # Fixes bloom.
autoFlush: 1 # Fixes ghosting.
textureInsideRT: 1 # Required for offset RTs/textures for post-processing.
roundSprite: 2 # Fixes misaligned post-processing.
SLUS-20993:
name: "Ghosthunter"
region: "NTSC-U"
Expand Down
18 changes: 18 additions & 0 deletions pcsx2/GS/Renderers/HW/GSRendererHW.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
3 changes: 3 additions & 0 deletions pcsx2/GS/Renderers/HW/GSRendererHW.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,9 @@ class GSRendererHW : public GSRenderer
/// 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);
Expand Down
12 changes: 12 additions & 0 deletions pcsx2/GS/Renderers/HW/GSTextureCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down