mirror of https://github.com/PCSX2/pcsx2.git
GS/HW: Only update dirty if intersects + fix tex is rt regions
This commit is contained in:
parent
3230287a5f
commit
c552d717ff
|
@ -804,7 +804,20 @@ bool GSRendererHW::IsPossibleChannelShuffle() const
|
||||||
|
|
||||||
const int mask = (((m_vt.m_max.p - m_vt.m_min.p) <= GSVector4(64.0f)).mask() & 0x3);
|
const int mask = (((m_vt.m_max.p - m_vt.m_min.p) <= GSVector4(64.0f)).mask() & 0x3);
|
||||||
if (mask == 0x3) // single_page
|
if (mask == 0x3) // single_page
|
||||||
|
{
|
||||||
|
const GSVertex* v = &m_vertex.buff[0];
|
||||||
|
|
||||||
|
const int draw_width = std::abs(v[1].XYZ.X - v[0].XYZ.X) >> 4;
|
||||||
|
const int draw_height = std::abs(v[1].XYZ.Y - v[0].XYZ.Y) >> 4;
|
||||||
|
|
||||||
|
const bool mask_clamp = (m_cached_ctx.CLAMP.WMS | m_cached_ctx.CLAMP.WMT) & 0x2;
|
||||||
|
const bool draw_match = (draw_height == 2) || (draw_width == 8);
|
||||||
|
|
||||||
|
if (draw_match || mask_clamp)
|
||||||
return true;
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
else if (mask != 0x1) // Not a single page in width.
|
else if (mask != 0x1) // Not a single page in width.
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -813,7 +826,18 @@ bool GSRendererHW::IsPossibleChannelShuffle() const
|
||||||
if (m_cached_ctx.TEX0.TBW == (m_cached_ctx.FRAME.FBW * 2) &&
|
if (m_cached_ctx.TEX0.TBW == (m_cached_ctx.FRAME.FBW * 2) &&
|
||||||
GSLocalMemory::IsPageAligned(m_cached_ctx.FRAME.PSM, GSVector4i(m_vt.m_min.p.upld(m_vt.m_max.p))))
|
GSLocalMemory::IsPageAligned(m_cached_ctx.FRAME.PSM, GSVector4i(m_vt.m_min.p.upld(m_vt.m_max.p))))
|
||||||
{
|
{
|
||||||
|
const GSVertex* v = &m_vertex.buff[0];
|
||||||
|
|
||||||
|
const int draw_width = std::abs(v[1].XYZ.X - v[0].XYZ.X) >> 4;
|
||||||
|
const int draw_height = std::abs(v[1].XYZ.Y - v[0].XYZ.Y) >> 4;
|
||||||
|
|
||||||
|
const bool mask_clamp = (m_cached_ctx.CLAMP.WMS | m_cached_ctx.CLAMP.WMT) & 0x2;
|
||||||
|
const bool draw_match = (draw_height == 2) || (draw_width == 8);
|
||||||
|
|
||||||
|
if (draw_match || mask_clamp)
|
||||||
return true;
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -2195,7 +2219,7 @@ void GSRendererHW::Draw()
|
||||||
}
|
}
|
||||||
|
|
||||||
GIFRegTEX0 FRAME_TEX0;
|
GIFRegTEX0 FRAME_TEX0;
|
||||||
bool rt_32bit = false;
|
bool shuffle_target = false;
|
||||||
if (!no_rt && m_cached_ctx.FRAME.Block() != m_cached_ctx.TEX0.TBP0 && GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].bpp == 16)
|
if (!no_rt && m_cached_ctx.FRAME.Block() != m_cached_ctx.TEX0.TBP0 && GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].bpp == 16)
|
||||||
{
|
{
|
||||||
// FBW is going to be wrong for channel shuffling into a new target, so take it from the source.
|
// FBW is going to be wrong for channel shuffling into a new target, so take it from the source.
|
||||||
|
@ -2208,11 +2232,24 @@ void GSRendererHW::Draw()
|
||||||
fm);
|
fm);
|
||||||
|
|
||||||
if (tgt)
|
if (tgt)
|
||||||
rt_32bit = tgt->m_32_bits_fmt;
|
shuffle_target = tgt->m_32_bits_fmt;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const GSVertex* v = &m_vertex.buff[0];
|
||||||
|
|
||||||
|
const int first_x = ((v[0].XYZ.X - m_context->XYOFFSET.OFX) + 8) >> 4;
|
||||||
|
const int first_u = PRIM->FST ? ((v[0].U + 8) >> 4) : static_cast<int>(((1 << m_cached_ctx.TEX0.TW) * (v[0].ST.S / v[1].RGBAQ.Q)) + 0.5f);
|
||||||
|
const int second_u = PRIM->FST ? ((v[1].U + 8) >> 4) : static_cast<int>(((1 << m_cached_ctx.TEX0.TW) * (v[1].ST.S / v[1].RGBAQ.Q)) + 0.5f);
|
||||||
|
const bool shuffle_coords = (first_x ^ first_u) & 8;
|
||||||
|
const int draw_width = std::abs(v[1].XYZ.X - v[0].XYZ.X) >> 4;
|
||||||
|
const int read_width = std::abs(second_u - first_u);
|
||||||
|
|
||||||
|
shuffle_target = shuffle_coords && draw_width == 8 && draw_width == read_width;
|
||||||
|
}
|
||||||
|
|
||||||
tgt = nullptr;
|
tgt = nullptr;
|
||||||
}
|
}
|
||||||
const bool possible_shuffle = ((rt_32bit && GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].bpp == 16) || m_cached_ctx.FRAME.Block() == m_cached_ctx.TEX0.TBP0) || IsPossibleChannelShuffle();
|
const bool possible_shuffle = ((shuffle_target && GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].bpp == 16) || m_cached_ctx.FRAME.Block() == m_cached_ctx.TEX0.TBP0) || IsPossibleChannelShuffle();
|
||||||
const bool need_aem_color = GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].trbpp <= 24 && GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].pal == 0 && m_context->ALPHA.C == 0 && m_env.TEXA.AEM;
|
const bool need_aem_color = GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].trbpp <= 24 && GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].pal == 0 && m_context->ALPHA.C == 0 && m_env.TEXA.AEM;
|
||||||
const bool req_color = (!PRIM->ABE || (PRIM->ABE && (m_context->ALPHA.IsUsingCs() || need_aem_color))) && (possible_shuffle || (m_cached_ctx.FRAME.FBMSK & (fm_mask & 0x00FFFFFF)) != (fm_mask & 0x00FFFFFF));
|
const bool req_color = (!PRIM->ABE || (PRIM->ABE && (m_context->ALPHA.IsUsingCs() || need_aem_color))) && (possible_shuffle || (m_cached_ctx.FRAME.FBMSK & (fm_mask & 0x00FFFFFF)) != (fm_mask & 0x00FFFFFF));
|
||||||
const bool alpha_used = m_context->TEX0.TCC && ((PRIM->ABE && m_context->ALPHA.IsUsingAs()) || (m_cached_ctx.TEST.ATE && m_cached_ctx.TEST.ATST > ATST_ALWAYS) || (possible_shuffle || (m_cached_ctx.FRAME.FBMSK & (fm_mask & 0xFF000000)) != (fm_mask & 0xFF000000)));
|
const bool alpha_used = m_context->TEX0.TCC && ((PRIM->ABE && m_context->ALPHA.IsUsingAs()) || (m_cached_ctx.TEST.ATE && m_cached_ctx.TEST.ATST > ATST_ALWAYS) || (possible_shuffle || (m_cached_ctx.FRAME.FBMSK & (fm_mask & 0xFF000000)) != (fm_mask & 0xFF000000)));
|
||||||
|
@ -2224,8 +2261,8 @@ void GSRendererHW::Draw()
|
||||||
m_process_texture = false;
|
m_process_texture = false;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
src = tex_psm.depth ? g_texture_cache->LookupDepthSource(TEX0, env.TEXA, MIP_CLAMP, tmm.coverage, possible_shuffle, m_vt.IsLinear(), m_cached_ctx.FRAME.Block(), req_color, req_alpha) :
|
src = tex_psm.depth ? g_texture_cache->LookupDepthSource(true, TEX0, env.TEXA, MIP_CLAMP, tmm.coverage, possible_shuffle, m_vt.IsLinear(), m_cached_ctx.FRAME.Block(), req_color, req_alpha) :
|
||||||
g_texture_cache->LookupSource(TEX0, env.TEXA, MIP_CLAMP, tmm.coverage, (GSConfig.HWMipmap >= HWMipmapLevel::Basic || GSConfig.TriFilter == TriFiltering::Forced) ? &hash_lod_range : nullptr,
|
g_texture_cache->LookupSource(true, TEX0, env.TEXA, MIP_CLAMP, tmm.coverage, (GSConfig.HWMipmap >= HWMipmapLevel::Basic || GSConfig.TriFilter == TriFiltering::Forced) ? &hash_lod_range : nullptr,
|
||||||
possible_shuffle, m_vt.IsLinear(), m_cached_ctx.FRAME.Block(), req_color, req_alpha);
|
possible_shuffle, m_vt.IsLinear(), m_cached_ctx.FRAME.Block(), req_color, req_alpha);
|
||||||
|
|
||||||
if (!src) [[unlikely]]
|
if (!src) [[unlikely]]
|
||||||
|
@ -2631,9 +2668,19 @@ void GSRendererHW::Draw()
|
||||||
ds->UpdateValidChannels(ZBUF_TEX0.PSM, zm);
|
ds->UpdateValidChannels(ZBUF_TEX0.PSM, zm);
|
||||||
|
|
||||||
if (rt)
|
if (rt)
|
||||||
|
{
|
||||||
|
if (m_texture_shuffle || m_channel_shuffle || (!rt->m_dirty.empty() && !rt->m_dirty.GetTotalRect(rt->m_TEX0, rt->m_unscaled_size).rintersect(m_r).rempty()))
|
||||||
rt->Update();
|
rt->Update();
|
||||||
|
else
|
||||||
|
rt->m_age = 0;
|
||||||
|
}
|
||||||
if (ds)
|
if (ds)
|
||||||
|
{
|
||||||
|
if (m_texture_shuffle || m_channel_shuffle || (!ds->m_dirty.empty() && !ds->m_dirty.GetTotalRect(ds->m_TEX0, ds->m_unscaled_size).rintersect(m_r).rempty()))
|
||||||
ds->Update();
|
ds->Update();
|
||||||
|
else
|
||||||
|
ds->m_age = 0;
|
||||||
|
}
|
||||||
|
|
||||||
const GSVector2i resolution = PCRTCDisplays.GetResolution();
|
const GSVector2i resolution = PCRTCDisplays.GetResolution();
|
||||||
GSTextureCache::Target* old_rt = nullptr;
|
GSTextureCache::Target* old_rt = nullptr;
|
||||||
|
|
|
@ -776,7 +776,7 @@ __ri static GSTextureCache::Source* FindSourceInMap(const GIFRegTEX0& TEX0, cons
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
GSTextureCache::Source* GSTextureCache::LookupDepthSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GIFRegCLAMP& CLAMP, const GSVector4i& r, const bool possible_shuffle, const bool linear, const u32 frame_fbp, bool req_color, bool req_alpha, bool palette)
|
GSTextureCache::Source* GSTextureCache::LookupDepthSource(const bool is_depth, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GIFRegCLAMP& CLAMP, const GSVector4i& r, const bool possible_shuffle, const bool linear, const u32 frame_fbp, bool req_color, bool req_alpha, bool palette)
|
||||||
{
|
{
|
||||||
if (GSConfig.UserHacks_DisableDepthSupport)
|
if (GSConfig.UserHacks_DisableDepthSupport)
|
||||||
{
|
{
|
||||||
|
@ -811,7 +811,7 @@ GSTextureCache::Source* GSTextureCache::LookupDepthSource(const GIFRegTEX0& TEX0
|
||||||
|
|
||||||
for (auto t : m_dst[DepthStencil])
|
for (auto t : m_dst[DepthStencil])
|
||||||
{
|
{
|
||||||
if (!t->m_used || !t->m_dirty.empty())
|
if (!t->m_used || (!t->m_dirty.empty() && !is_depth))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (GSUtil::HasSharedBits(bp, psm, t->m_TEX0.TBP0, t->m_TEX0.PSM))
|
if (GSUtil::HasSharedBits(bp, psm, t->m_TEX0.TBP0, t->m_TEX0.PSM))
|
||||||
|
@ -907,7 +907,7 @@ GSTextureCache::Source* GSTextureCache::LookupDepthSource(const GIFRegTEX0& TEX0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dst)
|
if (!dst && is_depth)
|
||||||
{
|
{
|
||||||
// Retry on the render target (Silent Hill 4)
|
// Retry on the render target (Silent Hill 4)
|
||||||
for (auto t : m_dst[RenderTarget])
|
for (auto t : m_dst[RenderTarget])
|
||||||
|
@ -966,7 +966,7 @@ GSTextureCache::Source* GSTextureCache::LookupDepthSource(const GIFRegTEX0& TEX0
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// This is a bit of a worry, since it could load junk from local memory... but it's better than skipping the draw.
|
// This is a bit of a worry, since it could load junk from local memory... but it's better than skipping the draw.
|
||||||
return LookupSource(TEX0, TEXA, CLAMP, r, nullptr, possible_shuffle, linear, frame_fbp, req_color, req_alpha);
|
return is_depth ? LookupSource(false, TEX0, TEXA, CLAMP, r, nullptr, possible_shuffle, linear, frame_fbp, req_color, req_alpha) : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
pxAssert(src->m_texture);
|
pxAssert(src->m_texture);
|
||||||
|
@ -975,7 +975,7 @@ GSTextureCache::Source* GSTextureCache::LookupDepthSource(const GIFRegTEX0& TEX0
|
||||||
return src;
|
return src;
|
||||||
}
|
}
|
||||||
|
|
||||||
GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GIFRegCLAMP& CLAMP, const GSVector4i& r, const GSVector2i* lod, const bool possible_shuffle, const bool linear, const u32 frame_fbp, bool req_color, bool req_alpha)
|
GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GIFRegCLAMP& CLAMP, const GSVector4i& r, const GSVector2i* lod, const bool possible_shuffle, const bool linear, const u32 frame_fbp, bool req_color, bool req_alpha)
|
||||||
{
|
{
|
||||||
GL_CACHE("TC: Lookup Source <%d,%d => %d,%d> (0x%x, %s, BW: %u, CBP: 0x%x, TW: %d, TH: %d)", r.x, r.y, r.z, r.w, TEX0.TBP0, psm_str(TEX0.PSM), TEX0.TBW, TEX0.CBP, 1 << TEX0.TW, 1 << TEX0.TH);
|
GL_CACHE("TC: Lookup Source <%d,%d => %d,%d> (0x%x, %s, BW: %u, CBP: 0x%x, TW: %d, TH: %d)", r.x, r.y, r.z, r.w, TEX0.TBP0, psm_str(TEX0.PSM), TEX0.TBW, TEX0.CBP, 1 << TEX0.TW, 1 << TEX0.TH);
|
||||||
|
|
||||||
|
@ -1010,7 +1010,6 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con
|
||||||
if (!src)
|
if (!src)
|
||||||
src = FindSourceInMap(TEX0, TEXA, psm_s, clut, gpu_clut, compare_lod, region, is_fixed_tex0, m_src.m_map[lookup_page]);
|
src = FindSourceInMap(TEX0, TEXA, psm_s, clut, gpu_clut, compare_lod, region, is_fixed_tex0, m_src.m_map[lookup_page]);
|
||||||
|
|
||||||
|
|
||||||
Target* dst = nullptr;
|
Target* dst = nullptr;
|
||||||
bool half_right = false;
|
bool half_right = false;
|
||||||
int x_offset = 0;
|
int x_offset = 0;
|
||||||
|
@ -1026,6 +1025,14 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con
|
||||||
const u32 psm = TEX0.PSM;
|
const u32 psm = TEX0.PSM;
|
||||||
const u32 bw = TEX0.TBW;
|
const u32 bw = TEX0.TBW;
|
||||||
|
|
||||||
|
GSVector4i req_rect = r;
|
||||||
|
// The read area might be offset but the start of the texture is at the beginning of the space.
|
||||||
|
req_rect.x = 0;
|
||||||
|
req_rect.y = 0;
|
||||||
|
|
||||||
|
if (region.HasX() || region.HasY())
|
||||||
|
req_rect = req_rect + region.GetOffset(req_rect.z, req_rect.w);
|
||||||
|
|
||||||
// Arc the Lad finds the wrong surface here when looking for a depth stencil.
|
// Arc the Lad finds the wrong surface here when looking for a depth stencil.
|
||||||
// Since we're currently not caching depth stencils (check ToDo in CreateSource) we should not look for it here.
|
// Since we're currently not caching depth stencils (check ToDo in CreateSource) we should not look for it here.
|
||||||
|
|
||||||
|
@ -1046,10 +1053,10 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con
|
||||||
if (((bp & (BLOCKS_PER_PAGE - 1)) != (t->m_TEX0.TBP0 & (BLOCKS_PER_PAGE - 1))) && (bp & (BLOCKS_PER_PAGE - 1)))
|
if (((bp & (BLOCKS_PER_PAGE - 1)) != (t->m_TEX0.TBP0 & (BLOCKS_PER_PAGE - 1))) && (bp & (BLOCKS_PER_PAGE - 1)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const bool overlaps = t->Overlaps(bp, bw, psm, r);
|
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.
|
// Try to make sure the target has available what we need, be careful of self referencing frames with font in the alpha.
|
||||||
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))
|
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)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const bool width_match = (std::max(64U, bw * 64U) >> GSLocalMemory::m_psm[psm].info.pageShiftX()) ==
|
const bool width_match = (std::max(64U, bw * 64U) >> GSLocalMemory::m_psm[psm].info.pageShiftX()) ==
|
||||||
|
@ -1067,7 +1074,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con
|
||||||
|
|
||||||
for (iter = GSRendererHW::GetInstance()->m_draw_transfers.rbegin(); iter != GSRendererHW::GetInstance()->m_draw_transfers.rend(); )
|
for (iter = GSRendererHW::GetInstance()->m_draw_transfers.rbegin(); iter != GSRendererHW::GetInstance()->m_draw_transfers.rend(); )
|
||||||
{
|
{
|
||||||
if (TEX0.TBP0 == iter->blit.DBP && GSUtil::HasCompatibleBits(iter->blit.DPSM, TEX0.PSM) && r.rintersect(iter->rect).eq(r))
|
if (TEX0.TBP0 == iter->blit.DBP && GSUtil::HasCompatibleBits(iter->blit.DPSM, TEX0.PSM) && req_rect.rintersect(iter->rect).eq(req_rect))
|
||||||
{
|
{
|
||||||
can_use = false;
|
can_use = false;
|
||||||
break;
|
break;
|
||||||
|
@ -1104,7 +1111,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con
|
||||||
const bool real_fmt_match = (GSLocalMemory::m_psm[psm].trbpp == 16) == (t->m_32_bits_fmt == false);
|
const bool real_fmt_match = (GSLocalMemory::m_psm[psm].trbpp == 16) == (t->m_32_bits_fmt == false);
|
||||||
if (rect_clean && tex_overlaps && !t->m_dirty.empty() && width_match)
|
if (rect_clean && tex_overlaps && !t->m_dirty.empty() && width_match)
|
||||||
{
|
{
|
||||||
GSVector4i new_rect = r;
|
GSVector4i new_rect = req_rect;
|
||||||
|
|
||||||
if (linear)
|
if (linear)
|
||||||
{
|
{
|
||||||
|
@ -1208,14 +1215,14 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con
|
||||||
rect_clean = t->m_dirty.empty();
|
rect_clean = t->m_dirty.empty();
|
||||||
if (!possible_shuffle && rect_clean && bp == t->m_TEX0.TBP0 && t && GSUtil::HasCompatibleBits(psm, t->m_TEX0.PSM) && width_match && real_fmt_match)
|
if (!possible_shuffle && rect_clean && bp == t->m_TEX0.TBP0 && t && GSUtil::HasCompatibleBits(psm, t->m_TEX0.PSM) && width_match && real_fmt_match)
|
||||||
{
|
{
|
||||||
if (t->Overlaps(bp, bw, psm, r))
|
if (!tex_merge_rt && t->Overlaps(bp, bw, psm, req_rect))
|
||||||
ResizeTarget(t, r, bp, psm, bw);
|
ResizeTarget(t, req_rect, bp, psm, bw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t->m_TEX0.TBP0 != frame_fbp && !possible_shuffle && bp > t->m_TEX0.TBP0 && t->Overlaps(bp, bw, psm, r) && GSUtil::GetChannelMask(psm) == GSUtil::GetChannelMask(t->m_TEX0.PSM) && !width_match)
|
if (t->m_TEX0.TBP0 != frame_fbp && !possible_shuffle && bp > t->m_TEX0.TBP0 && t->Overlaps(bp, bw, psm, req_rect) && GSUtil::GetChannelMask(psm) == GSUtil::GetChannelMask(t->m_TEX0.PSM) && !width_match)
|
||||||
{
|
{
|
||||||
GSVector4i new_rect = r;
|
GSVector4i new_rect = req_rect;
|
||||||
|
|
||||||
if (linear)
|
if (linear)
|
||||||
{
|
{
|
||||||
|
@ -1244,16 +1251,34 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool overlapping_dirty = true;
|
||||||
|
|
||||||
|
if (!rect_clean)
|
||||||
|
{
|
||||||
|
const u32 read_start = GSLocalMemory::GetStartBlockAddress(bp, bw, psm, req_rect);
|
||||||
|
const u32 read_end = GSLocalMemory::GetUnwrappedEndBlockAddress(bp, bw, psm, req_rect);
|
||||||
|
const GSVector4i dirty_rect = t->m_dirty.GetTotalRect(t->m_TEX0, t->m_unscaled_size);
|
||||||
|
const u32 dirty_start = GSLocalMemory::GetStartBlockAddress(t->m_TEX0.TBP0, t->m_TEX0.TBW, t->m_TEX0.PSM, dirty_rect);
|
||||||
|
const u32 dirty_end = GSLocalMemory::GetUnwrappedEndBlockAddress(t->m_TEX0.TBP0, t->m_TEX0.TBW, t->m_TEX0.PSM, dirty_rect);
|
||||||
|
|
||||||
|
overlapping_dirty = read_start <= dirty_end && read_end >= dirty_start;
|
||||||
|
}
|
||||||
|
|
||||||
const bool t_clean = ((t->m_dirty.GetDirtyChannels() & GSUtil::GetChannelMask(psm)) == 0) || rect_clean;
|
const bool t_clean = ((t->m_dirty.GetDirtyChannels() & GSUtil::GetChannelMask(psm)) == 0) || rect_clean;
|
||||||
const u32 color_psm = ((psm & 0x30) == 0x30) ? (psm & ~0x30) : psm;
|
const u32 color_psm = ((psm & 0x30) == 0x30) ? (psm & ~0x30) : psm;
|
||||||
const u32 tex_color_psm = ((t->m_TEX0.PSM & 0x30) == 0x30) ? (t->m_TEX0.PSM & ~0x30) : t->m_TEX0.PSM;
|
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
|
// Match if we haven't already got a tex in rt
|
||||||
if (t_clean && GSUtil::HasSharedBits(bp, psm, t->m_TEX0.TBP0, t_psm))
|
if (((!t_clean && can_convert) || t_clean || !overlapping_dirty) && GSUtil::HasSharedBits(bp, psm, t->m_TEX0.TBP0, t_psm))
|
||||||
{
|
{
|
||||||
bool match = true;
|
bool match = true;
|
||||||
if (found_t && (bw != t->m_TEX0.TBW || t->m_TEX0.PSM != psm))
|
if (found_t && (bw != t->m_TEX0.TBW || t->m_TEX0.PSM != psm))
|
||||||
match = false;
|
match = false;
|
||||||
|
|
||||||
|
//if (!t_clean && can_convert)
|
||||||
|
// DevCon.Warning("Expected %x Got %x shuffle %d draw %d", psm, t_psm, possible_shuffle, GSState::s_n);
|
||||||
if (match)
|
if (match)
|
||||||
{
|
{
|
||||||
// It is a complex to convert the code in shader. As a reference, let's do it on the CPU, it will be slow but
|
// It is a complex to convert the code in shader. As a reference, let's do it on the CPU, it will be slow but
|
||||||
|
@ -1282,19 +1307,30 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (!t_clean)
|
||||||
|
t->Update();
|
||||||
|
|
||||||
dst = t;
|
dst = t;
|
||||||
|
|
||||||
found_t = true;
|
found_t = true;
|
||||||
tex_merge_rt = false;
|
|
||||||
x_offset = 0;
|
x_offset = 0;
|
||||||
y_offset = 0;
|
y_offset = 0;
|
||||||
|
|
||||||
|
if (GSConfig.UserHacks_TextureInsideRt >= GSTextureInRtMode::MergeTargets && GSLocalMemory::GetUnwrappedEndBlockAddress(bp, bw, psm, req_rect) > dst->m_end_block)
|
||||||
|
continue;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tex_merge_rt = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (t_clean && (t->m_TEX0.TBW >= 16) && GSUtil::HasSharedBits(bp, psm, t->m_TEX0.TBP0 + t->m_TEX0.TBW * 0x10, t->m_TEX0.PSM))
|
}
|
||||||
|
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)
|
// Detect half of the render target (fix snow engine game)
|
||||||
// Target Page (8KB) have always a width of 64 pixels
|
// Target Page (8KB) have always a width of 64 pixels
|
||||||
// Half of the Target is TBW/2 pages * 8KB / (1 block * 256B) = 0x10
|
// Half of the Target is TBW/2 pages * 8KB / (1 block * 256B) = 0x10
|
||||||
|
@ -1311,12 +1347,12 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con
|
||||||
else if (GSConfig.UserHacks_TextureInsideRt >= GSTextureInRtMode::InsideTargets && color_psm >= PSMCT32 &&
|
else if (GSConfig.UserHacks_TextureInsideRt >= GSTextureInRtMode::InsideTargets && color_psm >= PSMCT32 &&
|
||||||
color_psm <= PSMCT16S && (GSUtil::HasCompatibleBits(tex_color_psm, color_psm) ||
|
color_psm <= PSMCT16S && (GSUtil::HasCompatibleBits(tex_color_psm, color_psm) ||
|
||||||
(possible_shuffle && tex_color_psm <= PSMCT24 && ((((t->UnwrappedEndBlock() + 1) - t->m_TEX0.TBP0) >> 1) + t->m_TEX0.TBP0) == bp)) &&
|
(possible_shuffle && tex_color_psm <= PSMCT24 && ((((t->UnwrappedEndBlock() + 1) - t->m_TEX0.TBP0) >> 1) + t->m_TEX0.TBP0) == bp)) &&
|
||||||
(t->Overlaps(bp, bw, psm, r) || t->Wraps()) &&
|
(t->Overlaps(bp, bw, psm, req_rect) || t->Wraps()) &&
|
||||||
t->m_age <= 1 && (!found_t || dst->m_TEX0.TBW < bw))
|
t->m_age <= 1 && (!found_t || dst->m_TEX0.TBW < bw))
|
||||||
{
|
{
|
||||||
// PSM equality needed because CreateSource does not handle PSM conversion.
|
// PSM equality needed because CreateSource does not handle PSM conversion.
|
||||||
// Only inclusive hit to limit false hits.
|
// Only inclusive hit to limit false hits.
|
||||||
GSVector4i rect = r;
|
GSVector4i rect = req_rect;
|
||||||
int src_bw = bw;
|
int src_bw = bw;
|
||||||
int src_psm = psm;
|
int src_psm = psm;
|
||||||
|
|
||||||
|
@ -1500,7 +1536,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con
|
||||||
|
|
||||||
if (!found_t && !dst && !GSConfig.UserHacks_DisableDepthSupport)
|
if (!found_t && !dst && !GSConfig.UserHacks_DisableDepthSupport)
|
||||||
{
|
{
|
||||||
GSVector4i new_rect = r;
|
GSVector4i new_rect = req_rect;
|
||||||
|
|
||||||
// Just in case the TextureMinMax trolls us as it does, when checking if inside the target.
|
// Just in case the TextureMinMax trolls us as it does, when checking if inside the target.
|
||||||
new_rect.z -= 2;
|
new_rect.z -= 2;
|
||||||
|
@ -1510,6 +1546,8 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con
|
||||||
// Unfortunately, I don't have any Arc the Lad testcase
|
// Unfortunately, I don't have any Arc the Lad testcase
|
||||||
//
|
//
|
||||||
// 1/ Check only current frame, I guess it is only used as a postprocessing effect
|
// 1/ Check only current frame, I guess it is only used as a postprocessing effect
|
||||||
|
if (is_color)
|
||||||
|
{
|
||||||
for (auto t : m_dst[DepthStencil])
|
for (auto t : m_dst[DepthStencil])
|
||||||
{
|
{
|
||||||
if (t->m_age <= 1 && t->m_used && t->m_dirty.empty() && GSUtil::HasSharedBits(bp, psm, t->m_TEX0.TBP0, t->m_TEX0.PSM) && t->Inside(bp, bw, psm, new_rect))
|
if (t->m_age <= 1 && t->m_used && t->m_dirty.empty() && GSUtil::HasSharedBits(bp, psm, t->m_TEX0.TBP0, t->m_TEX0.PSM) && t->Inside(bp, bw, psm, new_rect))
|
||||||
|
@ -1522,7 +1560,10 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con
|
||||||
GIFRegTEX0 depth_TEX0;
|
GIFRegTEX0 depth_TEX0;
|
||||||
depth_TEX0.U32[0] = TEX0.U32[0] | (0x30u << 20u);
|
depth_TEX0.U32[0] = TEX0.U32[0] | (0x30u << 20u);
|
||||||
depth_TEX0.U32[1] = TEX0.U32[1];
|
depth_TEX0.U32[1] = TEX0.U32[1];
|
||||||
return LookupDepthSource(depth_TEX0, TEXA, CLAMP, r, possible_shuffle, linear, frame_fbp, req_color, req_alpha);
|
src = LookupDepthSource(false, depth_TEX0, TEXA, CLAMP, req_rect, possible_shuffle, linear, frame_fbp, req_color, req_alpha);
|
||||||
|
|
||||||
|
if(src != nullptr)
|
||||||
|
return src;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1531,7 +1572,13 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return LookupDepthSource(TEX0, TEXA, CLAMP, r, possible_shuffle, linear, frame_fbp, req_color, req_alpha, true);
|
{
|
||||||
|
src = LookupDepthSource(false, TEX0, TEXA, CLAMP, req_rect, possible_shuffle, linear, frame_fbp, req_color, req_alpha, true);
|
||||||
|
|
||||||
|
if (src != nullptr)
|
||||||
|
return src;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1999,7 +2046,10 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// The old target's going to get invalidated (at least until we handle concurrent frame+depth at the same BP),
|
// The old target's going to get invalidated (at least until we handle concurrent frame+depth at the same BP),
|
||||||
// so just move the dirty rects across.
|
// so just move the dirty rects across, unless the format is diffent, in which case we need to update it.
|
||||||
|
if (dst->m_TEX0.PSM != dst_match->m_TEX0.PSM)
|
||||||
|
dst_match->Update();
|
||||||
|
|
||||||
dst->m_dirty = std::move(dst_match->m_dirty);
|
dst->m_dirty = std::move(dst_match->m_dirty);
|
||||||
dst_match->m_dirty = {};
|
dst_match->m_dirty = {};
|
||||||
dst->m_alpha_max = dst_match->m_alpha_max;
|
dst->m_alpha_max = dst_match->m_alpha_max;
|
||||||
|
|
|
@ -461,8 +461,8 @@ public:
|
||||||
GSTexture* LookupPaletteSource(u32 CBP, u32 CPSM, u32 CBW, GSVector2i& offset, float* scale, const GSVector2i& size);
|
GSTexture* LookupPaletteSource(u32 CBP, u32 CPSM, u32 CBW, GSVector2i& offset, float* scale, const GSVector2i& size);
|
||||||
std::shared_ptr<Palette> LookupPaletteObject(const u32* clut, u16 pal, bool need_gs_texture);
|
std::shared_ptr<Palette> LookupPaletteObject(const u32* clut, u16 pal, bool need_gs_texture);
|
||||||
|
|
||||||
Source* LookupSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GIFRegCLAMP& CLAMP, const GSVector4i& r, const GSVector2i* lod, const bool possible_shuffle, const bool linear, const u32 frame_fbp = 0xFFFFFFFF, bool req_color = true, bool req_alpha = true);
|
Source* LookupSource(const bool is_color, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GIFRegCLAMP& CLAMP, const GSVector4i& r, const GSVector2i* lod, const bool possible_shuffle, const bool linear, const u32 frame_fbp = 0xFFFFFFFF, bool req_color = true, bool req_alpha = true);
|
||||||
Source* LookupDepthSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GIFRegCLAMP& CLAMP, const GSVector4i& r, const bool possible_shuffle, const bool linear, const u32 frame_fbp = 0xFFFFFFFF, bool req_color = true, bool req_alpha = true, bool palette = false);
|
Source* LookupDepthSource(const bool is_depth, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GIFRegCLAMP& CLAMP, const GSVector4i& r, const bool possible_shuffle, const bool linear, const u32 frame_fbp = 0xFFFFFFFF, bool req_color = true, bool req_alpha = true, bool palette = false);
|
||||||
|
|
||||||
Target* FindTargetOverlap(Target* target, int type, int psm);
|
Target* FindTargetOverlap(Target* target, int type, int psm);
|
||||||
Target* LookupTarget(GIFRegTEX0 TEX0, const GSVector2i& size, float scale, int type, bool used = true, u32 fbmask = 0,
|
Target* LookupTarget(GIFRegTEX0 TEX0, const GSVector2i& size, float scale, int type, bool used = true, u32 fbmask = 0,
|
||||||
|
|
Loading…
Reference in New Issue