diff --git a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp index 120b389854..96e3eaece3 100644 --- a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp +++ b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp @@ -1083,7 +1083,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const const bool overlaps = t->Overlaps(bp, bw, psm, req_rect); // Try to make sure the target has available what we need, be careful of self referencing frames with font in the alpha. - if (!overlaps || (overlaps && !t->HasValidBitsForFormat(psm, req_color, req_alpha) && !(possible_shuffle && GSLocalMemory::m_psm[psm].bpp == 16 && GSLocalMemory::m_psm[t->m_TEX0.PSM].bpp == 32))) + if (!overlaps) continue; const bool width_match = (std::max(64U, bw * 64U) >> GSLocalMemory::m_psm[psm].info.pageShiftX()) == @@ -1297,6 +1297,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const const u32 tex_color_psm = ((t->m_TEX0.PSM & 0x30) == 0x30) ? (t->m_TEX0.PSM & ~0x30) : t->m_TEX0.PSM; const bool can_convert = (GSUtil::HasCompatibleBits(psm, t_psm) && ((bw == t->m_TEX0.TBW) || (bw <= 1 && req_rect.w < GSLocalMemory::m_psm[psm].pgs.y))) || (possible_shuffle && ((bw == t->m_TEX0.TBW) || (bw == (t->m_TEX0.TBW * 2) || bw <= 2)) && GSLocalMemory::m_psm[t->m_TEX0.PSM].bpp == 32); + // Match if we haven't already got a tex in rt if (((!t_clean && can_convert) || t_clean || !overlapping_dirty) && GSUtil::HasSharedBits(bp, psm, t->m_TEX0.TBP0, t_psm)) { @@ -1334,9 +1335,6 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const } else { - if (!t_clean) - t->Update(); - if ((psm == PSMT4 || psm == PSMT8) && t->m_was_dst_matched && !t->m_valid_rgb) { @@ -1357,6 +1355,9 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const } + if (overlaps && !t->HasValidBitsForFormat(psm, req_color, req_alpha) && !(possible_shuffle && GSLocalMemory::m_psm[psm].bpp == 16 && GSLocalMemory::m_psm[t->m_TEX0.PSM].bpp == 32)) + continue; + dst = t; found_t = true; @@ -1376,11 +1377,12 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const } else if ((t->m_TEX0.TBW >= 16) && GSUtil::HasSharedBits(bp, psm, t->m_TEX0.TBP0 + t->m_TEX0.TBW * 0x10, t->m_TEX0.PSM)) { - if (!t_clean) - t->Update(); // Detect half of the render target (fix snow engine game) // Target Page (8KB) have always a width of 64 pixels // Half of the Target is TBW/2 pages * 8KB / (1 block * 256B) = 0x10 + if (overlaps && !t->HasValidBitsForFormat(psm, req_color, req_alpha) && !(possible_shuffle && GSLocalMemory::m_psm[psm].bpp == 16 && GSLocalMemory::m_psm[t->m_TEX0.PSM].bpp == 32)) + continue; + half_right = true; dst = t; found_t = true; @@ -1397,6 +1399,9 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const (t->Overlaps(bp, bw, psm, req_rect) || t->Wraps()) && t->m_age <= 1 && (!found_t || dst->m_TEX0.TBW < bw)) { + if (overlaps && !t->HasValidBitsForFormat(psm, req_color, req_alpha) && !(possible_shuffle && GSLocalMemory::m_psm[psm].bpp == 16 && GSLocalMemory::m_psm[t->m_TEX0.PSM].bpp == 32)) + continue; + // PSM equality needed because CreateSource does not handle PSM conversion. // Only inclusive hit to limit false hits. GSVector4i rect = req_rect; @@ -1476,13 +1481,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const if (!t->m_dirty.empty()) { const GSVector4i dirty_rect = t->m_dirty.GetTotalRect(t->m_TEX0, GSVector2i(rect.z, rect.w)).rintersect(rect); - if (!dirty_rect.eq(rect)) - { - // Only update if the rect isn't empty - if (!dirty_rect.rempty()) - t->Update(); - } - else + if (dirty_rect.eq(rect)) continue; } @@ -2778,11 +2777,8 @@ bool GSTextureCache::CopyRGBFromDepthToColor(Target* dst, Target* depth_src) GL_CACHE("TC: Remove dirty rect (%d,%d=>%d,%d) from %s[%x, %s] due to incoming depth.", drc.left, drc.top, drc.right, drc.bottom, to_string(dst->m_type), dst->m_TEX0.TBP0, psm_str(dst->m_TEX0.PSM)); dst->m_dirty.erase(dst->m_dirty.begin() + i); - continue; } } - - i++; } // Depth source should be up to date. @@ -4183,6 +4179,8 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con const int w = static_cast(std::ceil(scale * tw)); const int h = static_cast(std::ceil(scale * th)); + dst->Update(); + // If we have a source larger than the target (from tex-in-rt), texelFetch() for target region will return black. if constexpr (force_target_copy) { @@ -4315,6 +4313,9 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con src->m_valid_rect = dst->m_valid; src->m_end_block = dst->m_end_block; + // Do this first as we could be adding in alpha from an upgraded 24bit target. + dst->Update(); + if ((src->m_TEX0.PSM & 0xf) == PSMCT24) { src->m_alpha_minmax.first = TEXA.AEM ? 0 : TEXA.TA0; @@ -4336,8 +4337,6 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con } src->m_32_bits_fmt = dst->m_32_bits_fmt; - dst->Update(); - // Rounding up should never exceed the texture size (since it itself should be rounded up), but just in case. GSVector2i new_size( std::min(static_cast(std::ceil(static_cast(src->m_unscaled_size.x) * dst->m_scale)), @@ -6010,13 +6009,19 @@ bool GSTextureCache::Target::HasValidBitsForFormat(u32 psm, bool req_color, bool return m_valid_alpha_high; case PSMT8: // Down here because of channel shuffles. default: - alpha_valid = ((m_TEX0.PSM & 0xF) == 0x1) ? true : (m_valid_alpha_low || m_valid_alpha_high); + alpha_valid = m_valid_alpha_low || m_valid_alpha_high; color_valid = m_valid_rgb; - if (req_alpha && !alpha_valid && color_valid) + + if (req_alpha && !alpha_valid && color_valid && (m_TEX0.PSM & 0xF) <= PSMCT24 && (psm & 0xF) == PSMCT32) { + RGBAMask mask; mask._u32 = 0x8; - AddDirtyRectTarget(this, this->m_valid, m_TEX0.PSM, m_TEX0.TBW, mask, false); + m_TEX0.PSM &= ~PSMCT24; + + if (!(m_dirty.GetDirtyChannels() & 0x8)) + AddDirtyRectTarget(this, m_valid, m_TEX0.PSM, m_TEX0.TBW, mask, false); + alpha_valid = true; // This is going to get resolved going forward. m_valid_alpha_low = true; m_valid_alpha_high = true;