mirror of
https://github.com/PCSX2/pcsx2.git
synced 2025-12-16 04:08:48 +00:00
GS/HW/TC: Force a temporary source creation in edges cases.
Case: When looking up a source, we find a perfect BP hit for a target. However, the requested area is outside the target's valid area. Don't use the target direct and instead load from memory in a temporary source. Co-authored-by: refraction
This commit is contained in:
parent
b5a2d04b2e
commit
44f47f11b8
@ -1347,6 +1347,11 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
|
||||
int x_offset = 0;
|
||||
int y_offset = 0;
|
||||
|
||||
// Indicates that in looking for targets that match the source BP, we found a perfect BP match
|
||||
// but the target's valid area was outside the required area for the source. In such cases
|
||||
// we want to create a temporary source and load the data from memory.
|
||||
bool target_bp_hit_outside_valid_area = false;
|
||||
|
||||
#ifdef DISABLE_HW_TEXTURE_CACHE
|
||||
if (0)
|
||||
#else
|
||||
@ -1725,6 +1730,15 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
|
||||
|
||||
if (!possible_shuffle && outside_target)
|
||||
{
|
||||
// Hit a target but source required area outside the target's valid area.
|
||||
target_bp_hit_outside_valid_area = true;
|
||||
GL_CACHE(
|
||||
"TC: LookupSource: Target BP match but outside valid area;"
|
||||
" Source=(BP=%04x, BW=%d, PSM=%s, req=(%x,%x - %x,%x));"
|
||||
" Target=(BP=%04x, BW=%d, PSM=%s, valid_area=(%x,%x - %x,%x))",
|
||||
bp, bw, GSUtil::GetPSMName(psm), r.x, r.y, r.z, r.w,
|
||||
t->m_TEX0.TBP0, t->m_TEX0.TBW, GSUtil::GetPSMName(t->m_TEX0.PSM),
|
||||
t->m_valid.x, t->m_valid.y, t->m_valid.z, t->m_valid.w);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
@ -2034,7 +2048,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
|
||||
//
|
||||
// Sigh... They don't help us.
|
||||
|
||||
if (!found_t && !dst && !GSConfig.UserHacks_DisableDepthSupport)
|
||||
if (!found_t && !dst && !GSConfig.UserHacks_DisableDepthSupport && !target_bp_hit_outside_valid_area)
|
||||
{
|
||||
// Let's try a trick to avoid to use wrongly a depth buffer
|
||||
// Unfortunately, I don't have any Arc the Lad testcase
|
||||
@ -2172,7 +2186,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
|
||||
}
|
||||
}
|
||||
|
||||
src = CreateSource(src_TEX0, TEXA, dst, x_offset, y_offset, lod, &rect, gpu_clut, region);
|
||||
src = CreateSource(src_TEX0, TEXA, dst, x_offset, y_offset, lod, &rect, gpu_clut, region, target_bp_hit_outside_valid_area);
|
||||
if (!src) [[unlikely]]
|
||||
return nullptr;
|
||||
}
|
||||
@ -5773,7 +5787,7 @@ void GSTextureCache::IncAge()
|
||||
}
|
||||
|
||||
//Fixme: Several issues in here. Not handling depth stencil, pitch conversion doesnt work.
|
||||
GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, Target* dst, int x_offset, int y_offset, const GSVector2i* lod, const GSVector4i* src_range, GSTexture* gpu_clut, SourceRegion region)
|
||||
GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, Target* dst, int x_offset, int y_offset, const GSVector2i* lod, const GSVector4i* src_range, GSTexture* gpu_clut, SourceRegion region, bool target_bp_hit)
|
||||
{
|
||||
const GSLocalMemory::psm_t& psm = GSLocalMemory::m_psm[TEX0.PSM];
|
||||
Source* src = new Source(TEX0, TEXA);
|
||||
@ -6239,7 +6253,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GSUtil::GetChannelMask(TEX0.PSM) == 0xf && TEX0.TBP0 != GSRendererHW::GetInstance()->GetCachedCtx()->FRAME.Block() && TEX0.TBP0 != GSRendererHW::GetInstance()->GetCachedCtx()->ZBUF.Block())
|
||||
if (GSUtil::GetChannelMask(TEX0.PSM) == 0xf && TEX0.TBP0 != GSRendererHW::GetInstance()->GetCachedCtx()->FRAME.Block() && TEX0.TBP0 != GSRendererHW::GetInstance()->GetCachedCtx()->ZBUF.Block() && !target_bp_hit)
|
||||
{
|
||||
// Kill any possible targets we missed, they might be wrong now.
|
||||
g_texture_cache->InvalidateVideoMemType(GSTextureCache::RenderTarget, TEX0.TBP0, TEX0.PSM, GSRendererHW::GetInstance()->GetCachedCtx()->FRAME.FBMSK, true);
|
||||
@ -6247,7 +6261,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
|
||||
}
|
||||
|
||||
// kill source immediately after the draw if it's the RT, because that'll get invalidated immediately.
|
||||
if (GSRendererHW::GetInstance()->IsTBPFrameOrZ(TEX0.TBP0, true) && GSRendererHW::GetInstance()->ChannelsSharedTEX0FRAME())
|
||||
if (target_bp_hit || (GSRendererHW::GetInstance()->IsTBPFrameOrZ(TEX0.TBP0, true) && GSRendererHW::GetInstance()->ChannelsSharedTEX0FRAME()))
|
||||
{
|
||||
GL_CACHE("TC: Source == RT before RT creation, invalidating after draw.");
|
||||
m_temporary_source = src;
|
||||
|
||||
@ -445,7 +445,7 @@ protected:
|
||||
std::unique_ptr<GSDownloadTexture> m_uint16_download_texture;
|
||||
std::unique_ptr<GSDownloadTexture> m_uint32_download_texture;
|
||||
|
||||
Source* CreateSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, Target* t, int x_offset, int y_offset, const GSVector2i* lod, const GSVector4i* src_range, GSTexture* gpu_clut, SourceRegion region);
|
||||
Source* CreateSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, Target* t, int x_offset, int y_offset, const GSVector2i* lod, const GSVector4i* src_range, GSTexture* gpu_clut, SourceRegion region, bool force_temporary = false);
|
||||
|
||||
bool PreloadTarget(GIFRegTEX0 TEX0, const GSVector2i& size, const GSVector2i& valid_size, bool is_frame,
|
||||
bool preload, bool preserve_target, const GSVector4i draw_rect, Target* dst, GSTextureCache::Source* src = nullptr);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user