diff --git a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp index 3edd01ad1f..ed47bc0922 100644 --- a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp +++ b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp @@ -1761,6 +1761,10 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const if (GSLocalMemory::m_psm[psm].bpp == GSLocalMemory::m_psm[t->m_TEX0.PSM].bpp && bw != rt_tbw && block_boundary_rect.height() > GSLocalMemory::m_psm[psm].pgs.y) continue; + // Reading 16bit as 32bit, or vice versa (when there isn't a shuffle) isn't really possible and no conversion is done. + if (!possible_shuffle && std::abs(GSLocalMemory::m_psm[psm].bpp - GSLocalMemory::m_psm[t->m_TEX0.PSM].bpp) == 16) + continue; + if (GSLocalMemory::m_psm[color_psm].bpp == 16 && GSLocalMemory::m_psm[t->m_TEX0.PSM].bpp == 32 && bw != 1 && ((t->m_TEX0.TBW < (horz_page_offset + ((block_boundary_rect.z + GSLocalMemory::m_psm[psm].pgs.x - 1) / GSLocalMemory::m_psm[psm].pgs.x)) || (t->m_TEX0.TBW != bw && block_boundary_rect.w > GSLocalMemory::m_psm[psm].pgs.y)))) @@ -1823,6 +1827,10 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const continue; } + // Make sure it's inside if not a shuffle, sometimes valid areas can get messy, like TOCA Race Driver 2 where it goes over to 480, but it's rounded up to 512 in the shuffle. + if (!possible_shuffle && !t->Inside(bp, bw, psm, block_boundary_rect)) + continue; + GSVector4i new_rect = (GSLocalMemory::m_psm[color_psm].bpp != GSLocalMemory::m_psm[t->m_TEX0.PSM].bpp && (psm & 0x7) != PSMCT16) ? block_boundary_rect : rect; // If the sizing is completely wrong on the frame vs the source when reading from alpha then it's likely the target has 2 different sizes for rgb and alpha. @@ -3451,6 +3459,10 @@ bool GSTextureCache::PreloadTarget(GIFRegTEX0 TEX0, const GSVector2i& size, cons // When the write covers the entire target, don't bother checking any earlier writes. if (iter->blit.DBP <= TEX0.TBP0 && transfer_end >= rect_end) { + // If it was a clear draw then we can use that as our target size. + if (iter->zero_clear && iter->blit.DBP == TEX0.TBP0 && iter->blit.DPSM == TEX0.PSM) + dst->UpdateValidity(iter->rect); + // Some games clear RT and Z at the same time, only erase if it's specifically this target. if (iter->blit.DBP == TEX0.TBP0 && transfer_end == rect_end) transfers.erase(iter.base() - 1);