From bcbf39033441fc6a899cebfeb3ff03f6a88e70e8 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sun, 31 Dec 2023 00:04:01 +1000 Subject: [PATCH] GS/HW: Don't discard alpha in C32 targets being used as C24 --- pcsx2/GS/Renderers/HW/GSTextureCache.cpp | 36 ++++++++++++++++++------ 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp index 72c91325ae..3da211109d 100644 --- a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp +++ b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp @@ -1948,15 +1948,35 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe // Drop dirty rect if we're overwriting the whole target. if (!preserve_target && draw_rect.rintersect(dst->m_valid).eq(dst->m_valid)) { - if (!dst->m_dirty.empty()) + // Preserve alpha if this is a 32-bit target being used as 24-bit. + const bool dont_invalidate_alpha = (dst->HasValidAlpha() && (psm_s.fmt == GSLocalMemory::PSM_FMT_24 || (fbmask & 0xFF000000u) != 0)); + if (dont_invalidate_alpha) { - GL_INS("TC: Clearing dirty list for %s[%x] because we're overwriting the whole target.", to_string(type), dst->m_TEX0.TBP0); - dst->m_dirty.clear(); - } + GL_INS("TC: Preserving alpha on 24-bit/masked %s[%x] because it was previously valid.", to_string(type), dst->m_TEX0.TBP0); - // And invalidate the target, we're drawing over it so we don't care what's there. - GL_INS("TC: Invalidating target %s[%x] because it's completely overwritten.", to_string(type), dst->m_TEX0.TBP0); - g_gs_device->InvalidateRenderTarget(dst->m_texture); + // We can still toss all dirty RGB writes though. Gotta save those uploads. + if (!dst->m_dirty.empty()) + { + GL_INS("TC: Clearing RGB dirty list for %s[%x] because we're overwriting the whole target.", to_string(type), dst->m_TEX0.TBP0); + for (s32 i = static_cast(dst->m_dirty.size()) - 1; i >= 0; i--) + { + if (!dst->m_dirty[i].rgba.c.a) + dst->m_dirty.erase(dst->m_dirty.begin() + static_cast(i)); + } + } + } + else + { + if (!dst->m_dirty.empty()) + { + GL_INS("TC: Clearing dirty list for %s[%x] because we're overwriting the whole target.", to_string(type), dst->m_TEX0.TBP0); + dst->m_dirty.clear(); + } + + // And invalidate the target, we're drawing over it so we don't care what's there. + GL_INS("TC: Invalidating target %s[%x] because it's completely overwritten.", to_string(type), dst->m_TEX0.TBP0); + g_gs_device->InvalidateRenderTarget(dst->m_texture); + } } } else if (!is_frame && !GSConfig.UserHacks_DisableDepthSupport) @@ -2025,7 +2045,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe calcRescale(dst_match); // If we don't need A, and the existing target doesn't have valid alpha, don't bother converting it. - const bool has_alpha = dst_match->m_valid_alpha_low || dst_match->m_valid_alpha_high; + const bool has_alpha = dst_match->HasValidAlpha(); const bool preserve_target = (preserve_rgb || (preserve_alpha && has_alpha)) || !draw_rect.rintersect(dst_match->m_valid).eq(dst_match->m_valid);