diff --git a/pcsx2/GS/GSLocalMemory.h b/pcsx2/GS/GSLocalMemory.h index 7461ee5a84..b789d45cbf 100644 --- a/pcsx2/GS/GSLocalMemory.h +++ b/pcsx2/GS/GSLocalMemory.h @@ -81,6 +81,10 @@ public: static_assert(1 << ilog2(PageHeight) == PageHeight, "PageHeight must be a power of 2"); } + /// Returns the amount to shift to convert a width to pages. + u8 pageShiftX() const { return m_pageShiftX; } + u8 pageShiftY() const { return m_pageShiftY; } + /// Get the block number of the given pixel u32 bn(int x, int y, u32 bp, u32 bw) const; diff --git a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp index ab8fce6153..0c19342c14 100644 --- a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp +++ b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp @@ -711,12 +711,10 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con // Solution: consider the RT as 32 bits if the alpha was used in the past const u32 t_psm = (t->m_dirty_alpha) ? t->m_TEX0.PSM & ~0x1 : t->m_TEX0.PSM; bool rect_clean = GSUtil::HasSameSwizzleBits(psm, t_psm); - const u32 end_block = (t->m_TEX0.TBP0 > t->m_end_block) ? (t->m_end_block + MAX_BP + 1) : t->m_end_block; - const GSLocalMemory::psm_t& psm_src = GSLocalMemory::m_psm[psm]; - const GSLocalMemory::psm_t& psm_dst = GSLocalMemory::m_psm[t->m_TEX0.PSM]; - const bool width_match = (std::max(64U, bw * 64U) / psm_src.pgs.x) == (std::max(64U, t->m_TEX0.TBW * 64U) / psm_dst.pgs.x); - if (rect_clean && bp >= t->m_TEX0.TBP0 && bp < end_block && width_match && !t->m_dirty.empty()) + if (rect_clean && bp >= t->m_TEX0.TBP0 && bp < t->UnwrappedEndBlock() && !t->m_dirty.empty() && + (std::max(64U, bw * 64U) >> GSLocalMemory::m_psm[psm].info.pageShiftX()) == + (std::max(64U, t->m_TEX0.TBW * 64U) >> GSLocalMemory::m_psm[t->m_TEX0.PSM].info.pageShiftX())) { GSVector4i new_rect = r; bool partial = false; @@ -823,7 +821,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con rect_clean = t->m_dirty.empty(); const bool t_clean = ((t->m_dirty.GetDirtyChannels() & GSUtil::GetChannelMask(psm)) == 0) || rect_clean; - const bool t_wraps = end_block > GSTextureCache::MAX_BP; + // Match if we haven't already got a tex in rt if (t_clean && GSUtil::HasSharedBits(bp, psm, t->m_TEX0.TBP0, t_psm)) { @@ -876,7 +874,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con // Make sure the texture actually is INSIDE the RT, it's possibly not valid if it isn't. // Also check BP >= TBP, create source isn't equpped to expand it backwards and all data comes from the target. (GH3) else if (GSConfig.UserHacks_TextureInsideRt >= GSTextureInRtMode::InsideTargets && psm >= PSMCT32 && - psm <= PSMCT16S && t->m_TEX0.PSM == psm && (t->Overlaps(bp, bw, psm, r) || t_wraps) && + psm <= PSMCT16S && t->m_TEX0.PSM == psm && (t->Overlaps(bp, bw, psm, r) || t->Wraps()) && t->m_age <= 1 && !found_t) { // PSM equality needed because CreateSource does not handle PSM conversion. @@ -951,7 +949,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con else { SurfaceOffset so = ComputeSurfaceOffset(bp, bw, psm, r, t); - if (!so.is_valid && t_wraps) + if (!so.is_valid && t->Wraps()) { // Improves Beyond Good & Evil shadow. const u32 bp_unwrap = bp + GSTextureCache::MAX_BP + 0x1;