From 2fd88b901bf96769d63584958f925de5a1c2cd90 Mon Sep 17 00:00:00 2001 From: refractionpcsx2 Date: Sun, 29 Jan 2023 21:02:30 +0000 Subject: [PATCH] GS-TC: Don't clear on reset, only invalidate frames. Fixes bug with counting writes before flushing. Track what textures are used as frames. It's possible that further to this the PCRTC disables on CSR reset, but we need to test this first, but that would fix the logo at the bottom when booting through the bios in Software mode. --- pcsx2/GS/GSState.cpp | 21 ++++++++++----------- pcsx2/GS/Renderers/HW/GSRendererHW.cpp | 5 +++-- pcsx2/GS/Renderers/HW/GSTextureCache.cpp | 17 ++++++++++++++++- pcsx2/GS/Renderers/HW/GSTextureCache.h | 2 ++ 4 files changed, 31 insertions(+), 14 deletions(-) diff --git a/pcsx2/GS/GSState.cpp b/pcsx2/GS/GSState.cpp index ad148ce36a..03c3fd3225 100644 --- a/pcsx2/GS/GSState.cpp +++ b/pcsx2/GS/GSState.cpp @@ -56,11 +56,13 @@ GSState::GSState() memset(&m_v, 0, sizeof(m_v)); memset(&m_vertex, 0, sizeof(m_vertex)); memset(&m_index, 0, sizeof(m_index)); - + memset(m_mem.m_vm8, 0, m_mem.m_vmsize); m_v.RGBAQ.Q = 1.0f; GrowVertexBuffer(); + m_draw_transfers.clear(); + m_sssize = 0; m_sssize += sizeof(m_version); @@ -140,15 +142,11 @@ void GSState::Reset(bool hardware_reset) Flush(GSFlushReason::RESET); // FIXME: bios logo not shown cut in half after reset, missing graphics in GoW after first FMV - if (hardware_reset) - memset(m_mem.m_vm8, 0, m_mem.m_vmsize); memset(&m_path, 0, sizeof(m_path)); memset(&m_v, 0, sizeof(m_v)); m_env.Reset(); - m_draw_transfers.clear(); - PRIM = &m_env.PRIM; UpdateContext(); @@ -1986,12 +1984,6 @@ void GSState::Write(const u8* mem, int len) if (!m_tr.Update(w, h, psm.trbpp, len)) return; - if (GSConfig.PreloadFrameWithGSData) - { - // Store the transfer for preloading new RT's. - m_draw_transfers.push_front(blit); - } - GIFRegTEX0& prev_tex0 = m_prev_env.CTXT[m_prev_env.PRIM.CTXT].TEX0; const u32 write_start_bp = m_mem.m_psm[blit.DPSM].info.bn(m_env.TRXPOS.DSAX, m_env.TRXPOS.DSAY, blit.DBP, blit.DBW); // (m_mem.*psm.pa)(static_cast(m_env.TRXPOS.DSAX), static_cast(m_env.TRXPOS.DSAY), blit.DBP, blit.DBW) >> 6; @@ -2006,6 +1998,13 @@ void GSState::Write(const u8* mem, int len) // Invalid the CLUT if it crosses paths. m_mem.m_clut.InvalidateRange(write_start_bp, write_end_bp); + if (GSConfig.PreloadFrameWithGSData) + { + // Store the transfer for preloading new RT's. + if(m_draw_transfers.size() == 0 || (m_draw_transfers.size() > 0 && blit.DBP != m_draw_transfers.front().DBP)) + m_draw_transfers.push_front(blit); + } + GL_CACHE("Write! ... => 0x%x W:%d F:%s (DIR %d%d), dPos(%d %d) size(%d %d)", blit.DBP, blit.DBW, psm_str(blit.DPSM), m_env.TRXPOS.DIRX, m_env.TRXPOS.DIRY, diff --git a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp index 3f1f8d2578..053cf5498b 100644 --- a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp +++ b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp @@ -202,16 +202,17 @@ void GSRendererHW::VSync(u32 field, bool registers_written) { if (m_reset) { - m_tc->RemoveAll(); + m_tc->InvalidateFrameAge(); m_reset = false; } if (GSConfig.LoadTextureReplacements) GSTextureReplacements::ProcessAsyncLoadedTextures(); + m_tc->IncAge(); + GSRenderer::VSync(field, registers_written); - m_tc->IncAge(); if (m_tc->GetHashCacheMemoryUsage() > 1024 * 1024 * 1024) { diff --git a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp index b437549f0f..c0e289924b 100644 --- a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp +++ b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp @@ -61,6 +61,19 @@ void GSTextureCache::RemovePartial() } } +// Causes old frames to be flushed +void GSTextureCache::InvalidateFrameAge() +{ + for (int type = 0; type < 2; type++) + { + for (auto t : m_dst[type]) + { + if (t->m_is_frame) + t->m_age = 9999; + } + } +} + void GSTextureCache::RemoveAll() { m_src.RemoveAll(); @@ -728,8 +741,8 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(const GIFRegTEX0& TEX0, con AddDirtyRectTarget(dst, newrect, TEX0.PSM, TEX0.TBW); dst->Update(true); } + static_cast(g_gs_renderer.get())->m_draw_transfers.clear(); } - static_cast(g_gs_renderer.get())->m_draw_transfers.clear(); } if (used) { @@ -737,6 +750,8 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(const GIFRegTEX0& TEX0, con } if (is_frame) dst->m_dirty_alpha = false; + dst->m_is_frame |= is_frame; + assert(dst && dst->m_texture && dst->m_texture->GetScale() == new_s); assert(dst && dst->m_dirty.empty()); return dst; diff --git a/pcsx2/GS/Renderers/HW/GSTextureCache.h b/pcsx2/GS/Renderers/HW/GSTextureCache.h index 38253a9ac6..3bf8a5bee6 100644 --- a/pcsx2/GS/Renderers/HW/GSTextureCache.h +++ b/pcsx2/GS/Renderers/HW/GSTextureCache.h @@ -198,6 +198,7 @@ public: GSVector4i m_valid; const bool m_depth_supported; bool m_dirty_alpha; + bool m_is_frame; public: Target(const GIFRegTEX0& TEX0, const bool depth_supported, const int type); @@ -352,6 +353,7 @@ public: void Read(Target* t, const GSVector4i& r); void Read(Source* t, const GSVector4i& r); void RemoveAll(); + void InvalidateFrameAge(); void RemovePartial(); void AddDirtyRectTarget(Target* target, GSVector4i rect, u32 psm, u32 bw);