Skip to content

Commit

Permalink
GS-HW: Expand target on EE write and improve overlap check
Browse files Browse the repository at this point in the history
  • Loading branch information
refractionpcsx2 committed Nov 20, 2022
1 parent a95492f commit e212c61
Show file tree
Hide file tree
Showing 8 changed files with 52 additions and 3 deletions.
4 changes: 2 additions & 2 deletions pcsx2/GS/GSState.cpp
Expand Up @@ -1764,7 +1764,7 @@ void GSState::FlushWrite()
r.top = m_env.TRXPOS.DSAY;
r.right = r.left + m_env.TRXREG.RRW;
r.bottom = r.top + m_env.TRXREG.RRH;

ExpandTarget(m_env.BITBLTBUF, r);
InvalidateVideoMem(m_env.BITBLTBUF, r);

const GSLocalMemory::writeImage wi = GSLocalMemory::m_psm[m_env.BITBLTBUF.DPSM].wi;
Expand Down Expand Up @@ -2026,7 +2026,7 @@ void GSState::Write(const u8* mem, int len)
r.top = m_env.TRXPOS.DSAY;
r.right = r.left + m_env.TRXREG.RRW;
r.bottom = r.top + m_env.TRXREG.RRH;

ExpandTarget(m_env.BITBLTBUF, r);
InvalidateVideoMem(blit, r);

(m_mem.*psm.wi)(m_tr.x, m_tr.y, mem, m_tr.total, blit, m_env.TRXPOS, m_env.TRXREG);
Expand Down
1 change: 1 addition & 0 deletions pcsx2/GS/GSState.h
Expand Up @@ -373,6 +373,7 @@ class GSState : public GSAlignedClass<32>
virtual void PurgePool() = 0;
virtual void InvalidateVideoMem(const GIFRegBITBLTBUF& BITBLTBUF, const GSVector4i& r) {}
virtual void InvalidateLocalMem(const GIFRegBITBLTBUF& BITBLTBUF, const GSVector4i& r, bool clut = false) {}
virtual void ExpandTarget(const GIFRegBITBLTBUF& BITBLTBUF, const GSVector4i& r) {}

virtual void Move();

Expand Down
5 changes: 5 additions & 0 deletions pcsx2/GS/Renderers/HW/GSRendererHW.cpp
Expand Up @@ -853,6 +853,11 @@ GSVector2i GSRendererHW::GetTargetSize(GSVector2i* unscaled_size)
static_cast<int>(static_cast<float>(height) * GSConfig.UpscaleMultiplier));
}

void GSRendererHW::ExpandTarget(const GIFRegBITBLTBUF& BITBLTBUF, const GSVector4i& r)
{
m_tc->ExpandTarget(BITBLTBUF, r);
}

void GSRendererHW::InvalidateVideoMem(const GIFRegBITBLTBUF& BITBLTBUF, const GSVector4i& r)
{
// printf("[%d] InvalidateVideoMem %d,%d - %d,%d %05x (%d)\n", (int)m_perfmon.GetFrame(), r.left, r.top, r.right, r.bottom, (int)BITBLTBUF.DBP, (int)BITBLTBUF.DPSM);
Expand Down
1 change: 1 addition & 0 deletions pcsx2/GS/Renderers/HW/GSRendererHW.h
Expand Up @@ -198,6 +198,7 @@ class GSRendererHW : public GSRenderer

GSTexture* GetOutput(int i, int& y_offset) override;
GSTexture* GetFeedbackOutput() override;
void ExpandTarget(const GIFRegBITBLTBUF& BITBLTBUF, const GSVector4i& r);
void InvalidateVideoMem(const GIFRegBITBLTBUF& BITBLTBUF, const GSVector4i& r) override;
void InvalidateLocalMem(const GIFRegBITBLTBUF& BITBLTBUF, const GSVector4i& r, bool clut = false) override;
void Move() override;
Expand Down
40 changes: 39 additions & 1 deletion pcsx2/GS/Renderers/HW/GSTextureCache.cpp
Expand Up @@ -700,6 +700,43 @@ void GSTextureCache::ScaleTargetForDisplay(Target* t, const GIFRegTEX0& dispfb,
GetTargetHeight(t->m_TEX0.TBP0, t->m_TEX0.TBW, t->m_TEX0.PSM, static_cast<u32>(needed_height));
}

// Expands targets where the write from the EE overlaps the edge of a render target and uses the same base pointer.
void GSTextureCache::ExpandTarget(const GIFRegBITBLTBUF& BITBLTBUF, const GSVector4i& r)
{
GIFRegTEX0 TEX0;
TEX0.TBP0 = BITBLTBUF.DBP;
TEX0.TBW = BITBLTBUF.DBW;
TEX0.PSM = BITBLTBUF.DPSM;
Target* dst = nullptr;
auto& list = m_dst[RenderTarget];

for (auto i = list.begin(); i != list.end(); ++i)
{
Target* t = *i;

if (TEX0.TBP0 == t->m_TEX0.TBP0 && t->Overlaps(TEX0.TBP0, TEX0.TBW, TEX0.PSM, r))
{
list.MoveFront(i.Index());

dst = t;
break;
}
}

if (dst)
{
const GSVector2i rect_scaled = GSVector2i(r.z * g_gs_renderer->GetUpscaleMultiplier(), r.w * g_gs_renderer->GetUpscaleMultiplier());
const int upsc_width = std::max(rect_scaled.x, dst->m_texture->GetWidth());
const int upsc_height = std::max(rect_scaled.y, dst->m_texture->GetHeight());
if (dst->m_texture->GetWidth() < upsc_width || dst->m_texture->GetHeight() < upsc_height)
{
dst->ResizeTexture(upsc_width, upsc_height);
dst->m_dirty.push_back(GSDirtyRect(r, TEX0.PSM, TEX0.TBW));
GetTargetHeight(TEX0.TBP0, TEX0.TBW, TEX0.PSM, r.w);
dst->Update();
}
}
}
// Goal: Depth And Target at the same address is not possible. On GS it is
// the same memory but not on the Dx/GL. Therefore a write to the Depth/Target
// must invalidate the Target/Depth respectively
Expand Down Expand Up @@ -2283,7 +2320,8 @@ bool GSTextureCache::Surface::Overlaps(u32 bp, u32 bw, u32 psm, const GSVector4i
{
// Valid only for color formats.
const u32 end_block = GSLocalMemory::m_psm[psm].info.bn(rect.z - 1, rect.w - 1, bp, bw);
const bool overlap = GSTextureCache::CheckOverlap(m_TEX0.TBP0, m_end_block, bp, end_block);
const u32 start_block = GSLocalMemory::m_psm[psm].info.bn(rect.x, rect.y, bp, bw);
const bool overlap = GSTextureCache::CheckOverlap(m_TEX0.TBP0, m_end_block, start_block, end_block);
return overlap;
}

Expand Down
1 change: 1 addition & 0 deletions pcsx2/GS/Renderers/HW/GSTextureCache.h
Expand Up @@ -345,6 +345,7 @@ class GSTextureCache

u32 GetTargetHeight(u32 fbp, u32 fbw, u32 psm, u32 min_height);

void ExpandTarget(const GIFRegBITBLTBUF& BITBLTBUF, const GSVector4i& r);
void InvalidateVideoMemType(int type, u32 bp);
void InvalidateVideoMemSubTarget(GSTextureCache::Target* rt);
void InvalidateVideoMem(const GSOffset& off, const GSVector4i& r, bool target = true);
Expand Down
2 changes: 2 additions & 0 deletions pcsx2/GS/Renderers/SW/GSRendererSW.cpp
Expand Up @@ -616,6 +616,8 @@ void GSRendererSW::Sync(int reason)
g_perfmon.Put(GSPerfMon::Fillrate, pixels);
}

void GSRendererSW::ExpandTarget(const GIFRegBITBLTBUF& BITBLTBUF, const GSVector4i& r) {}

void GSRendererSW::InvalidateVideoMem(const GIFRegBITBLTBUF& BITBLTBUF, const GSVector4i& r)
{
if (LOG)
Expand Down
1 change: 1 addition & 0 deletions pcsx2/GS/Renderers/SW/GSRendererSW.h
Expand Up @@ -75,6 +75,7 @@ class GSRendererSW final : public GSRenderer
void Draw() override;
void Queue(GSRingHeap::SharedPtr<GSRasterizerData>& item);
void Sync(int reason);
void ExpandTarget(const GIFRegBITBLTBUF& BITBLTBUF, const GSVector4i& r);
void InvalidateVideoMem(const GIFRegBITBLTBUF& BITBLTBUF, const GSVector4i& r) override;
void InvalidateLocalMem(const GIFRegBITBLTBUF& BITBLTBUF, const GSVector4i& r, bool clut = false) override;

Expand Down

0 comments on commit e212c61

Please sign in to comment.