GS/TC: Update depth lookup when looking up targets.

This commit is contained in:
lightningterror
2026-01-21 15:30:25 +01:00
parent 955b925633
commit a0bc7a5d0e

View File

@@ -2404,13 +2404,20 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
};
Target* dst = nullptr;
auto& list = m_dst[type];
Target* dst_match = nullptr;
auto* list = &m_dst[type];
const GSVector4i min_rect = draw_rect.max_u32(GSVector4i(0, 0, draw_rect.x, draw_rect.y));
// TODO: Move all frame stuff to its own routine too.
if (!is_frame)
{
for (auto i = list.begin(); i != list.end();)
for (int iteration = 0; iteration < 2; iteration++)
{
if (dst != nullptr)
break;
list = &m_dst[iteration == 0 ? type : (1 - type)];
for (auto i = list->begin(); i != list->end();)
{
Target* t = *i;
if (bp == t->m_TEX0.TBP0)
@@ -2492,17 +2499,26 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
if (can_use)
{
if (used)
list.MoveFront(i.Index());
dst = t;
list->MoveFront(i.Index());
if (iteration == 1)
{
dst_match = t;
dst_match->m_32_bits_fmt |= (psm_s.bpp != 16);
}
else
{
dst = t;
dst->m_32_bits_fmt |= (psm_s.bpp != 16);
}
break;
}
else if (!(src && src->m_from_target == t))
{
GL_INS("TC: Deleting RT BP 0x%x BW %d PSM %s due to change in target", t->m_TEX0.TBP0, t->m_TEX0.TBW, GSUtil::GetPSMName(t->m_TEX0.PSM));
InvalidateSourcesFromTarget(t);
i = list.erase(i);
i = list->erase(i);
delete t;
continue;
@@ -2551,7 +2567,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
{
GL_INS("TC: Deleting RT BP 0x%x BW %d PSM %s offset overwrite shuffle", t->m_TEX0.TBP0, t->m_TEX0.TBW, GSUtil::GetPSMName(t->m_TEX0.PSM));
InvalidateSourcesFromTarget(t);
i = list.erase(i);
i = list->erase(i);
delete t;
continue;
@@ -2580,7 +2596,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
{
GL_INS("TC: Deleting RT BP 0x%x BW %d PSM %s due to change in target", t->m_TEX0.TBP0, t->m_TEX0.TBW, GSUtil::GetPSMName(t->m_TEX0.PSM));
InvalidateSourcesFromTarget(t);
i = list.erase(i);
i = list->erase(i);
delete t;
}
@@ -2601,7 +2617,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
{
GL_INS("TC: Deleting RT BP 0x%x BW %d PSM %s due to dirty areas not preserved (Likely change in target)", t->m_TEX0.TBP0, t->m_TEX0.TBW, GSUtil::GetPSMName(t->m_TEX0.PSM));
InvalidateSourcesFromTarget(t);
i = list.erase(i);
i = list->erase(i);
delete t;
continue;
@@ -2626,12 +2642,21 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
}
//DevCon.Warning("Here draw %d wanted %x PSM %x got %x PSM %x offset of %d pages width %d pages draw width %d", GSState::s_n, bp, TEX0.PSM, t->m_TEX0.TBP0, t->m_TEX0.PSM, (bp - t->m_TEX0.TBP0) >> 5, t->m_TEX0.TBW, draw_rect.width());
dst = t;
if (iteration == 1)
{
dst_match = t;
dst_match->m_32_bits_fmt |= (psm_s.bpp != 16);
break;
}
else
{
dst = t;
dst->m_32_bits_fmt |= (psm_s.bpp != 16);
}
//Continue just in case there's a newer target
if (used)
list.MoveFront(i.Index());
list->MoveFront(i.Index());
if (t->m_TEX0.TBP0 <= bp || GSLocalMemory::GetStartBlockAddress(TEX0.TBP0, TEX0.TBW, TEX0.PSM, min_rect) >= bp)
break;
else
@@ -2643,11 +2668,12 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
i++;
}
}
}
else
{
pxAssert(type == RenderTarget);
// Let's try to find a perfect frame that contains valid data
for (auto i = list.begin(); i != list.end(); ++i)
for (auto i = list->begin(); i != list->end(); ++i)
{
Target* t = *i;
@@ -2673,7 +2699,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
{
DevCon.Warning("Wanted %x psm %x bw %x, got %x psm %x bw %x, deleting", TEX0.TBP0, TEX0.PSM, TEX0.TBW, t->m_TEX0.TBP0, t->m_TEX0.PSM, t->m_TEX0.TBW);
InvalidateSourcesFromTarget(t);
i = list.erase(i);
i = list->erase(i);
delete t;
continue;
}
@@ -2691,7 +2717,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
// 2nd try ! Try to find a frame at the requested bp -> bp + size is inside of (or equal to)
if (!dst)
{
for (auto i = list.begin(); i != list.end(); ++i)
for (auto i = list->begin(); i != list->end(); ++i)
{
Target* t = *i;
const u32 end_block = GSLocalMemory::GetEndBlockAddress(bp, TEX0.TBW, TEX0.PSM, GSVector4i(0, size.y, size.x, size.y + 1));
@@ -2711,7 +2737,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
{
DevCon.Warning("2 Wanted %x psm %x bw %x, got %x psm %x bw %x, deleting", TEX0.TBP0, TEX0.PSM, TEX0.TBW, t->m_TEX0.TBP0, t->m_TEX0.PSM, t->m_TEX0.TBW);
InvalidateSourcesFromTarget(t);
i = list.erase(i);
i = list->erase(i);
delete t;
continue;
}
@@ -2731,7 +2757,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
// 3rd try ! Try to find a frame that doesn't contain valid data (honestly I'm not sure we need to do it)
if (!dst)
{
for (auto i = list.begin(); i != list.end(); ++i)
for (auto i = list->begin(); i != list->end(); ++i)
{
Target* t = *i;
if (bp == t->m_TEX0.TBP0 && TEX0.TBW == t->m_TEX0.TBW)
@@ -2743,7 +2769,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
{
DevCon.Warning("3 Wanted %x psm %x bw %x, got %x psm %x bw %x, deleting", TEX0.TBP0, TEX0.PSM, TEX0.TBW, t->m_TEX0.TBP0, t->m_TEX0.PSM, t->m_TEX0.TBW);
InvalidateSourcesFromTarget(t);
i = list.erase(i);
i = list->erase(i);
delete t;
continue;
}
@@ -2969,21 +2995,21 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
if (!is_frame)
{
GL_CACHE("TC: Attempt to repopulate RGB for %s[%x]", to_string(type), dst->m_TEX0.TBP0);
for (Target* dst_match : m_dst[1 - type])
for (Target* dst_match_repopulate : m_dst[1 - type])
{
if (dst_match->m_TEX0.TBP0 != dst->m_TEX0.TBP0 || !dst_match->m_valid_rgb)
if (dst_match_repopulate->m_TEX0.TBP0 != dst->m_TEX0.TBP0 || !dst_match_repopulate->m_valid_rgb)
continue;
dst->m_TEX0.TBW = dst_match->m_TEX0.TBW;
dst->m_TEX0.TBW = dst_match_repopulate->m_TEX0.TBW;
// Force the valid rect to the new size in case of shrinkage.
dst->m_valid = dst_match->m_valid;
dst->UpdateValidity(dst_match->m_valid);
dst->m_valid = dst_match_repopulate->m_valid;
dst->UpdateValidity(dst_match_repopulate->m_valid);
if (type == RenderTarget)
{
dst_match->m_valid_rgb = (fbmask & mask) == (mask & 0x00FFFFFFu);
dst_match_repopulate->m_valid_rgb = (fbmask & mask) == (mask & 0x00FFFFFFu);
dst->m_was_dst_matched = true;
if (!CopyRGBFromDepthToColor(dst, dst_match))
if (!CopyRGBFromDepthToColor(dst, dst_match_repopulate))
{
// Needed new texture and memory allocation failed.
return nullptr;
@@ -2991,10 +3017,10 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
}
else
{
dst_match->m_valid_rgb &= (fbmask & mask) == (mask & 0x00FFFFFFu);
dst_match_repopulate->m_valid_rgb &= (fbmask & mask) == (mask & 0x00FFFFFFu);
dst->Update();
if (!dst->ResizeTexture(dst_match->m_unscaled_size.x, dst_match->m_unscaled_size.y))
if (!dst->ResizeTexture(dst_match_repopulate->m_unscaled_size.x, dst_match_repopulate->m_unscaled_size.y))
{
// Needed new texture and memory allocation failed.
return nullptr;
@@ -3004,14 +3030,14 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
(GSLocalMemory::m_psm[dst->m_TEX0.PSM].trbpp == 32) ? ShaderConvert::RGBA8_TO_FLOAT32 :
ShaderConvert::RGBA8_TO_FLOAT24;
g_gs_device->StretchRect(dst_match->m_texture, GSVector4(0, 0, 1, 1),
g_gs_device->StretchRect(dst_match_repopulate->m_texture, GSVector4(0, 0, 1, 1),
dst->m_texture, GSVector4(dst->GetUnscaledRect()) * GSVector4(dst->GetScale()), shader, false);
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
dst_match->m_valid_rgb = !used;
dst_match->m_was_dst_matched = true;
dst_match_repopulate->m_valid_rgb = !used;
dst_match_repopulate->m_was_dst_matched = true;
dst->m_valid_rgb = true;
dst->m_32_bits_fmt = dst_match->m_32_bits_fmt;
dst->m_32_bits_fmt = dst_match_repopulate->m_32_bits_fmt;
}
break;
}
@@ -3087,13 +3113,13 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
}
}
else if (!is_frame && !GSConfig.UserHacks_DisableDepthSupport)
{
if (!dst_match)
{
const int rev_type = (type == DepthStencil) ? RenderTarget : DepthStencil;
// Depth stencil/RT can be an older RT/DS but only check recent RT/DS to avoid to pick
// some bad data.
auto& rev_list = m_dst[rev_type];
Target* dst_match = nullptr;
for (auto i = rev_list.begin(); i != rev_list.end(); ++i)
{
Target* t = *i;
@@ -3173,9 +3199,11 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
dst_match = t;
}
}
// We only want to use a matched target if it's actually being used.
if (dst_match)
}
else
{
// dst_match, we only want to use a matched target if it's actually being used.
calcRescale(dst_match);
// If we don't need A, and the existing target doesn't have valid alpha, don't bother converting it.
@@ -3192,7 +3220,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
// Clear instead of invalidating if there is anything which isn't touched.
clear |= (!preserve_target && fbmask != 0);
GIFRegTEX0 new_TEX0;
new_TEX0.TBP0 = TEX0.TBP0;
new_TEX0.TBP0 = GSConfig.UserHacks_TextureInsideRt >= GSTextureInRtMode::InsideTargets ? dst_match->m_TEX0.TBP0 : TEX0.TBP0;
new_TEX0.TBW = (!half_width) ? dst_match->m_TEX0.TBW : TEX0.TBW;
new_TEX0.PSM = is_shuffle ? dst_match->m_TEX0.PSM : TEX0.PSM;