mirror of https://github.com/PCSX2/pcsx2.git
GS/HW: Fix Double Half Clear bug + better detect double buffer changes
This commit is contained in:
parent
2f105cbe15
commit
b96978494b
|
@ -2490,7 +2490,7 @@ void GSRendererHW::Draw()
|
|||
// Grandia Xtreme, Onimusha Warlord.
|
||||
if (!new_rect && new_height && old_end_block != rt->m_end_block)
|
||||
{
|
||||
old_rt = g_texture_cache->FindTargetOverlap(old_end_block, rt->m_end_block, GSTextureCache::RenderTarget, m_cached_ctx.FRAME.PSM);
|
||||
old_rt = g_texture_cache->FindTargetOverlap(rt, GSTextureCache::RenderTarget, m_cached_ctx.FRAME.PSM);
|
||||
|
||||
if (old_rt && old_rt != rt && GSUtil::HasSharedBits(old_rt->m_TEX0.PSM, rt->m_TEX0.PSM))
|
||||
{
|
||||
|
@ -2528,7 +2528,7 @@ void GSRendererHW::Draw()
|
|||
|
||||
if (!new_rect && new_height && old_end_block != ds->m_end_block)
|
||||
{
|
||||
old_ds = g_texture_cache->FindTargetOverlap(old_end_block, ds->m_end_block, GSTextureCache::DepthStencil, m_cached_ctx.ZBUF.PSM);
|
||||
old_ds = g_texture_cache->FindTargetOverlap(ds, GSTextureCache::DepthStencil, m_cached_ctx.ZBUF.PSM);
|
||||
|
||||
if (old_ds && old_ds != ds && GSUtil::HasSharedBits(old_ds->m_TEX0.PSM, ds->m_TEX0.PSM))
|
||||
{
|
||||
|
@ -5459,7 +5459,8 @@ bool GSRendererHW::DetectDoubleHalfClear(bool& no_rt, bool& no_ds)
|
|||
// GTA: LCS does this setup, along with a few other games. Thankfully if it's a zero clear, we'll clear both
|
||||
// separately, and the end result is the same because it gets invalidated. That's better than falsely detecting
|
||||
// double half clears, and ending up with 1024 high render targets which really shouldn't be.
|
||||
if (frame_psm.fmt != zbuf_psm.fmt && m_cached_ctx.FRAME.FBMSK != ((zbuf_psm.fmt == 1) ? 0xFF000000u : 0))
|
||||
if ((frame_psm.fmt != zbuf_psm.fmt && m_cached_ctx.FRAME.FBMSK != ((zbuf_psm.fmt == 1) ? 0xFF000000u : 0)) ||
|
||||
!GSUtil::HasCompatibleBits(m_cached_ctx.FRAME.PSM & ~0x30, m_cached_ctx.ZBUF.PSM & ~0x30)) // Bit depth is not the same (i.e. 32bit + 16bit).
|
||||
{
|
||||
GL_INS("Inconsistent FRAME [%s, %08x] and ZBUF [%s] formats, not using double-half clear.",
|
||||
psm_str(m_cached_ctx.FRAME.PSM), m_cached_ctx.FRAME.FBMSK, psm_str(m_cached_ctx.ZBUF.PSM));
|
||||
|
|
|
@ -1222,14 +1222,13 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con
|
|||
return src;
|
||||
}
|
||||
|
||||
GSTextureCache::Target* GSTextureCache::FindTargetOverlap(u32 bp, u32 end_block, int type, int psm)
|
||||
GSTextureCache::Target* GSTextureCache::FindTargetOverlap(Target* target, int type, int psm)
|
||||
{
|
||||
u32 end_block_bp = end_block < bp ? (MAX_BP + 1) : end_block;
|
||||
|
||||
for (auto t : m_dst[type])
|
||||
{
|
||||
// Only checks that the texure starts at the requested bp, which shares data. Size isn't considered.
|
||||
if (t->m_TEX0.TBP0 >= bp && t->m_TEX0.TBP0 < end_block_bp && GSUtil::HasCompatibleBits(t->m_TEX0.PSM, psm))
|
||||
if (t != target && t->m_TEX0.TBW == target->m_TEX0.TBW && t->m_TEX0.TBP0 >= target->m_TEX0.TBP0 &&
|
||||
t->UnwrappedEndBlock() <= target->UnwrappedEndBlock() && GSUtil::HasCompatibleBits(t->m_TEX0.PSM, psm))
|
||||
return t;
|
||||
}
|
||||
return nullptr;
|
||||
|
@ -1746,6 +1745,29 @@ void GSTextureCache::PreloadTarget(GIFRegTEX0 TEX0, const GSVector2i& size, cons
|
|||
{
|
||||
dst->UpdateValidity(GSVector4i::loadh(valid_size));
|
||||
}
|
||||
|
||||
for (int type = 0; type < 2; type++)
|
||||
{
|
||||
auto& list = m_dst[type];
|
||||
for (auto i = list.begin(); i != list.end();)
|
||||
{
|
||||
auto j = i;
|
||||
Target* t = *j;
|
||||
|
||||
// could be overwriting a double buffer, so if it's the second half of it, just reduce the size down to half.
|
||||
if (dst != t && t->m_TEX0.TBW == dst->m_TEX0.TBW &&
|
||||
t->m_TEX0.PSM == dst->m_TEX0.PSM &&
|
||||
((((t->m_end_block + 1) - t->m_TEX0.TBP0) >> 1) + t->m_TEX0.TBP0) == dst->m_TEX0.TBP0)
|
||||
{
|
||||
//DevCon.Warning("Found one %x->%x BW %d PSM %x (new target %x->%x BW %d PSM %x)", t->m_TEX0.TBP0, t->m_end_block, t->m_TEX0.TBW, t->m_TEX0.PSM, dst->m_TEX0.TBP0, dst->m_end_block, dst->m_TEX0.TBW, dst->m_TEX0.PSM);
|
||||
GSVector4i new_valid = t->m_valid;
|
||||
new_valid.w /= 2;
|
||||
t->ResizeValidity(new_valid);
|
||||
return;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GSTextureCache::Target* GSTextureCache::LookupDisplayTarget(GIFRegTEX0 TEX0, const GSVector2i& size, float scale)
|
||||
|
@ -2958,7 +2980,7 @@ void GSTextureCache::InvalidateLocalMem(const GSOffset& off, const GSVector4i& r
|
|||
t->m_drawn_since_read.z = targetr.x;
|
||||
}
|
||||
|
||||
if (exact_bp)
|
||||
if (exact_bp && read_end <= t->m_end_block)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -5149,8 +5171,6 @@ void GSTextureCache::Target::Update()
|
|||
g_gs_device->DrawMultiStretchRects(drects, ndrects, m_texture, shader);
|
||||
}
|
||||
|
||||
UpdateValidity(total_rect);
|
||||
// We don't know what the dirty alpha is gonna be, so assume max.
|
||||
m_alpha_min = 0;
|
||||
m_alpha_max = 255;
|
||||
g_gs_device->Recycle(t);
|
||||
|
|
|
@ -469,14 +469,14 @@ public:
|
|||
bool CanTranslate(u32 bp, u32 bw, u32 spsm, GSVector4i r, u32 dbp, u32 dpsm, u32 dbw);
|
||||
GSVector4i TranslateAlignedRectByPage(Target* t, u32 sbp, u32 spsm, u32 sbw, GSVector4i src_r, bool is_invalidation = false);
|
||||
void DirtyRectByPage(u32 sbp, u32 spsm, u32 sbw, Target* t, GSVector4i src_r);
|
||||
|
||||
void DirtyRectByPageOld(u32 sbp, u32 spsm, u32 sbw, Target* t, GSVector4i src_r);
|
||||
GSTexture* LookupPaletteSource(u32 CBP, u32 CPSM, u32 CBW, GSVector2i& offset, float* scale, const GSVector2i& size);
|
||||
std::shared_ptr<Palette> LookupPaletteObject(const u32* clut, u16 pal, bool need_gs_texture);
|
||||
|
||||
Source* LookupSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GIFRegCLAMP& CLAMP, const GSVector4i& r, const GSVector2i* lod, const bool possible_shuffle);
|
||||
Source* LookupDepthSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GIFRegCLAMP& CLAMP, const GSVector4i& r, const bool possible_shuffle, bool palette = false);
|
||||
|
||||
Target* FindTargetOverlap(u32 bp, u32 end_block, int type, int psm);
|
||||
Target* FindTargetOverlap(Target* target, int type, int psm);
|
||||
Target* LookupTarget(GIFRegTEX0 TEX0, const GSVector2i& 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());
|
||||
|
|
Loading…
Reference in New Issue