Skip to content

Commit

Permalink
GS/HW: Restrict making new targets if no uploads
Browse files Browse the repository at this point in the history
  • Loading branch information
refractionpcsx2 committed Nov 24, 2023
1 parent 7fcc47d commit 7cc6af8
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 5 deletions.
4 changes: 2 additions & 2 deletions pcsx2/GS/Renderers/HW/GSRendererHW.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ GSTexture* GSRendererHW::GetOutput(int i, float& scale, int& y_offset)
TEX0.TBW = curFramebuffer.FBW;
TEX0.PSM = curFramebuffer.PSM;

if (GSTextureCache::Target* rt = g_texture_cache->LookupDisplayTarget(TEX0, framebufferSize, GetTextureScaleFactor()))
if (GSTextureCache::Target* rt = g_texture_cache->LookupDisplayTarget(TEX0, framebufferSize, GetTextureScaleFactor(), false))
{
rt->Update();
t = rt->m_texture;
Expand Down Expand Up @@ -214,7 +214,7 @@ GSTexture* GSRendererHW::GetFeedbackOutput(float& scale)
TEX0.TBW = m_regs->EXTBUF.EXBW;
TEX0.PSM = PCRTCDisplays.PCRTCDisplays[index].PSM;

GSTextureCache::Target* rt = g_texture_cache->LookupDisplayTarget(TEX0, fb_size, GetTextureScaleFactor());
GSTextureCache::Target* rt = g_texture_cache->LookupDisplayTarget(TEX0, fb_size, GetTextureScaleFactor(), true);
if (!rt)
return nullptr;

Expand Down
59 changes: 57 additions & 2 deletions pcsx2/GS/Renderers/HW/GSTextureCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2361,13 +2361,68 @@ bool GSTextureCache::PreloadTarget(GIFRegTEX0 TEX0, const GSVector2i& size, cons
return hw_clear;
}

GSTextureCache::Target* GSTextureCache::LookupDisplayTarget(GIFRegTEX0 TEX0, const GSVector2i& size, float scale)
GSTextureCache::Target* GSTextureCache::LookupDisplayTarget(GIFRegTEX0 TEX0, const GSVector2i& size, float scale, bool is_feedback)
{
Target* dst = LookupTarget(TEX0, size, scale, RenderTarget, true, 0, true);
if (dst)
return dst;

return CreateTarget(TEX0, size, size, scale, RenderTarget, true, 0, true);
// Didn't find a target, check if the frame was uploaded.

bool can_create = is_feedback;

if (!is_feedback && GSRendererHW::GetInstance()->m_draw_transfers.size() > 0)
{
const GSVector4i newrect = GSVector4i::loadh(size);
const u32 rect_end = GSLocalMemory::GetUnwrappedEndBlockAddress(TEX0.TBP0, TEX0.TBW, TEX0.PSM, newrect);

std::vector<GSState::GSUploadQueue>::reverse_iterator iter;
GSVector4i eerect = GSVector4i::zero();
const int last_draw = GSRendererHW::GetInstance()->m_draw_transfers.back().draw;

for (iter = GSRendererHW::GetInstance()->m_draw_transfers.rbegin(); iter != GSRendererHW::GetInstance()->m_draw_transfers.rend(); )
{
// Would be nice to make this 100, but B-Boy seems to rely on data uploaded ~200 draws ago. Making it bigger for now to be safe.
if (last_draw - iter->draw > 500)
break;

const u32 transfer_end = GSLocalMemory::GetUnwrappedEndBlockAddress(iter->blit.DBP, iter->blit.DBW, iter->blit.DPSM, iter->rect);

// If the format, and location doesn't overlap
if (transfer_end >= TEX0.TBP0 && iter->blit.DBP <= rect_end && GSUtil::HasCompatibleBits(iter->blit.DPSM, TEX0.PSM))
{
GSVector4i targetr = iter->rect;

if (eerect.rempty())
eerect = targetr;
else
eerect = eerect.runion(targetr);

if (iter->zero_clear && iter->draw == last_draw)
{
can_create = false;
break;
}

if (iter->blit.DBP == TEX0.TBP0 && transfer_end == rect_end)
{
iter = std::vector<GSState::GSUploadQueue>::reverse_iterator(GSRendererHW::GetInstance()->m_draw_transfers.erase(iter.base() - 1));
}
else
++iter;

if (eerect.rintersect(newrect).eq(newrect))
{
can_create = true;
break;
}
}
else
++iter;
}
}

return can_create ? CreateTarget(TEX0, size, size, scale, RenderTarget, true, 0, true) : nullptr;
}

void GSTextureCache::ScaleTargetForDisplay(Target* t, const GIFRegTEX0& dispfb, int real_w, int real_h)
Expand Down
2 changes: 1 addition & 1 deletion pcsx2/GS/Renderers/HW/GSTextureCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,7 @@ class GSTextureCache
Target* CreateTarget(GIFRegTEX0 TEX0, const GSVector2i& size, const GSVector2i& valid_size,float scale, int type, bool used = true, u32 fbmask = 0,
bool is_frame = false, bool preload = GSConfig.PreloadFrameWithGSData, bool preserve_target = true,
const GSVector4i draw_rc = GSVector4i::zero(), GSTextureCache::Source* src = nullptr);
Target* LookupDisplayTarget(GIFRegTEX0 TEX0, const GSVector2i& size, float scale);
Target* LookupDisplayTarget(GIFRegTEX0 TEX0, const GSVector2i& size, float scale, bool is_feedback);

/// Looks up a target in the cache, and only returns it if the BP/BW match exactly.
Target* GetExactTarget(u32 BP, u32 BW, int type, u32 end_bp);
Expand Down

0 comments on commit 7cc6af8

Please sign in to comment.