GS/HW: Split LookupTarget() and CreateTarget()

This commit is contained in:
Stenzek 2023-06-22 20:15:46 +10:00 committed by Connor McLaughlin
parent 9c71bec4a0
commit 29b97209fe
3 changed files with 155 additions and 124 deletions

View File

@ -2050,16 +2050,22 @@ void GSRendererHW::Draw()
const bool is_square = (t_size.y == t_size.x) && m_r.w >= 1023 && PrimitiveCoversWithoutGaps(); const bool is_square = (t_size.y == t_size.x) && m_r.w >= 1023 && PrimitiveCoversWithoutGaps();
const bool is_clear = is_possible_mem_clear && is_square; const bool is_clear = is_possible_mem_clear && is_square;
rt = g_texture_cache->LookupTarget(FRAME_TEX0, t_size, target_scale, GSTextureCache::RenderTarget, true, rt = g_texture_cache->LookupTarget(FRAME_TEX0, t_size, target_scale, GSTextureCache::RenderTarget, true,
fm, false, is_clear, force_preload, preload_uploads); fm, false, force_preload, preload_uploads);
// Draw skipped because it was a clear and there was no target. // Draw skipped because it was a clear and there was no target.
if (!rt) if (!rt)
{
if (is_clear)
{ {
GL_INS("Clear draw with no target, skipping."); GL_INS("Clear draw with no target, skipping.");
cleanup_cancelled_draw(); cleanup_cancelled_draw();
OI_GsMemClear(); OI_GsMemClear();
return; return;
} }
rt = g_texture_cache->CreateTarget(FRAME_TEX0, t_size, target_scale, GSTextureCache::RenderTarget, true,
fm, false, force_preload, preload_uploads);
}
} }
GSTextureCache::Target* ds = nullptr; GSTextureCache::Target* ds = nullptr;
@ -2072,7 +2078,12 @@ void GSRendererHW::Draw()
ZBUF_TEX0.PSM = m_cached_ctx.ZBUF.PSM; ZBUF_TEX0.PSM = m_cached_ctx.ZBUF.PSM;
ds = g_texture_cache->LookupTarget(ZBUF_TEX0, t_size, target_scale, GSTextureCache::DepthStencil, ds = g_texture_cache->LookupTarget(ZBUF_TEX0, t_size, target_scale, GSTextureCache::DepthStencil,
m_cached_ctx.DepthWrite(), 0, false, false, force_preload); m_cached_ctx.DepthWrite(), 0, false, force_preload);
if (!ds)
{
ds = g_texture_cache->CreateTarget(ZBUF_TEX0, t_size, target_scale, GSTextureCache::DepthStencil,
m_cached_ctx.DepthWrite(), 0, false, force_preload);
}
} }
if (process_texture) if (process_texture)

View File

@ -1199,7 +1199,7 @@ GSTextureCache::Target* GSTextureCache::FindTargetOverlap(u32 bp, u32 end_block,
} }
GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVector2i& size, float scale, int type, GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVector2i& size, float scale, int type,
bool used, u32 fbmask, bool is_frame, bool is_clear, bool preload, bool preload_uploads) bool used, u32 fbmask, bool is_frame, bool preload, bool preload_uploads)
{ {
const GSLocalMemory::psm_t& psm_s = GSLocalMemory::m_psm[TEX0.PSM]; const GSLocalMemory::psm_t& psm_s = GSLocalMemory::m_psm[TEX0.PSM];
const u32 bp = TEX0.TBP0; const u32 bp = TEX0.TBP0;
@ -1226,6 +1226,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
auto& list = m_dst[type]; auto& list = m_dst[type];
Target* old_found = nullptr; Target* old_found = nullptr;
// TODO: Move all frame stuff to its own routine too.
if (!is_frame) if (!is_frame)
{ {
for (auto i = list.begin(); i != list.end(); ++i) for (auto i = list.begin(); i != list.end(); ++i)
@ -1421,15 +1422,27 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
} }
} }
if (!dst) if (dst)
{ {
// Skip full screen clears from making massive targets. dst->m_used |= used;
if (is_clear)
{ if (is_frame)
GL_CACHE("TC: Create RT skipped on clear draw"); dst->m_valid_alpha = false;
return nullptr;
dst->readbacks_since_draw = 0;
assert(dst && dst->m_texture && dst->m_scale == scale);
} }
return dst;
}
GSTextureCache::Target* GSTextureCache::CreateTarget(GIFRegTEX0 TEX0, const GSVector2i& size, float scale, int type,
bool used, u32 fbmask, bool is_frame, bool preload, bool preload_uploads)
{
const u32 bp = TEX0.TBP0;
const GSLocalMemory::psm_t& psm_s = GSLocalMemory::m_psm[TEX0.PSM];
if (type == DepthStencil) if (type == DepthStencil)
{ {
GL_CACHE("TC: Lookup Target(Depth) %dx%d, miss (0x%x, TBW %d, %s)", size.x, size.y, bp, GL_CACHE("TC: Lookup Target(Depth) %dx%d, miss (0x%x, TBW %d, %s)", size.x, size.y, bp,
@ -1441,7 +1454,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
size.x, size.y, fbmask, bp, TEX0.TBW, psm_str(TEX0.PSM)); size.x, size.y, fbmask, bp, TEX0.TBW, psm_str(TEX0.PSM));
} }
dst = CreateTarget(TEX0, size.x, size.y, scale, type, true); Target* dst = CreateTarget(TEX0, size.x, size.y, scale, type, true);
// In theory new textures contain invalidated data. Still in theory a new target // In theory new textures contain invalidated data. Still in theory a new target
// must contains the content of the GS memory. // must contains the content of the GS memory.
// In practice, TC will wrongly invalidate some RT. For example due to write on the alpha // In practice, TC will wrongly invalidate some RT. For example due to write on the alpha
@ -1553,7 +1566,6 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
} }
} }
dst->m_is_frame = is_frame; dst->m_is_frame = is_frame;
}
dst->m_used |= used; dst->m_used |= used;
@ -1568,7 +1580,11 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
GSTextureCache::Target* GSTextureCache::LookupDisplayTarget(GIFRegTEX0 TEX0, const GSVector2i& size, float scale) GSTextureCache::Target* GSTextureCache::LookupDisplayTarget(GIFRegTEX0 TEX0, const GSVector2i& size, float scale)
{ {
return LookupTarget(TEX0, size, scale, RenderTarget, true, 0, true); Target* dst = LookupTarget(TEX0, size, scale, RenderTarget, true, 0, true);
if (dst)
return dst;
return CreateTarget(TEX0, size, scale, RenderTarget, true, 0, true);
} }
void GSTextureCache::ScaleTargetForDisplay(Target* t, const GIFRegTEX0& dispfb, int real_w, int real_h) void GSTextureCache::ScaleTargetForDisplay(Target* t, const GIFRegTEX0& dispfb, int real_w, int real_h)
@ -2649,12 +2665,14 @@ bool GSTextureCache::Move(u32 SBP, u32 SBW, u32 SPSM, int sx, int sy, u32 DBP, u
const GSVector2i target_size = GetTargetSize(DBP, DBW, DPSM, Common::AlignUpPow2(w, 64), h); const GSVector2i target_size = GetTargetSize(DBP, DBW, DPSM, Common::AlignUpPow2(w, 64), h);
dst = LookupTarget(new_TEX0, target_size, src->m_scale, src->m_type); dst = LookupTarget(new_TEX0, target_size, src->m_scale, src->m_type);
if (dst) if (!dst)
{ dst = CreateTarget(new_TEX0, target_size, src->m_scale, src->m_type);
if (!dst)
return false;
dst->UpdateValidity(GSVector4i(dx, dy, dx + w, dy + h)); dst->UpdateValidity(GSVector4i(dx, dy, dx + w, dy + h));
dst->OffsetHack_modxy = src->OffsetHack_modxy; dst->OffsetHack_modxy = src->OffsetHack_modxy;
} }
}
if (!src || !dst || src->m_scale != dst->m_scale) if (!src || !dst || src->m_scale != dst->m_scale)
return false; return false;

View File

@ -456,7 +456,9 @@ public:
Target* FindTargetOverlap(u32 bp, u32 end_block, int type, int psm); Target* FindTargetOverlap(u32 bp, u32 end_block, int type, int psm);
Target* LookupTarget(GIFRegTEX0 TEX0, const GSVector2i& size, float scale, int type, bool used = true, u32 fbmask = 0, Target* LookupTarget(GIFRegTEX0 TEX0, const GSVector2i& size, float scale, int type, bool used = true, u32 fbmask = 0,
bool is_frame = false, bool is_clear = false, bool preload = GSConfig.PreloadFrameWithGSData, bool preload_uploads = true); bool is_frame = false, bool preload = GSConfig.PreloadFrameWithGSData, bool preload_uploads = true);
Target* CreateTarget(GIFRegTEX0 TEX0, const GSVector2i& size, float scale, int type, bool used = true, u32 fbmask = 0,
bool is_frame = false, bool preload = GSConfig.PreloadFrameWithGSData, bool preload_uploads = true);
Target* LookupDisplayTarget(GIFRegTEX0 TEX0, const GSVector2i& size, float scale); Target* LookupDisplayTarget(GIFRegTEX0 TEX0, const GSVector2i& size, float scale);
/// Looks up a target in the cache, and only returns it if the BP/BW match exactly. /// Looks up a target in the cache, and only returns it if the BP/BW match exactly.