mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-10-11 22:49:56 +00:00
GS/HW: Avoid hazard copy if read and draw don't overlap + fix CSBW typo
This commit is contained in:
committed by
lightningterror
parent
f86cd4c3d2
commit
054e0509c4
@@ -7884,10 +7884,10 @@ __ri void GSRendererHW::HandleTextureHazards(const GSTextureCache::Target* rt, c
|
||||
const GSTextureCache::Target* src_target = nullptr;
|
||||
if (!m_downscale_source || !tex->m_from_target)
|
||||
{
|
||||
if (rt && m_conf.tex == m_conf.rt && !(m_channel_shuffle && tex && tex_diff != frame_diff))
|
||||
if (rt && m_conf.tex == m_conf.rt)
|
||||
{
|
||||
// Can we read the framebuffer directly? (i.e. sample location matches up).
|
||||
if (CanUseTexIsFB(rt, tex, tmm))
|
||||
if (CanUseTexIsFB(rt, tex, tmm) && !(m_channel_shuffle && tex_diff != frame_diff))
|
||||
{
|
||||
m_conf.tex = nullptr;
|
||||
m_conf.ps.tex_is_fb = true;
|
||||
@@ -7901,18 +7901,30 @@ __ri void GSRendererHW::HandleTextureHazards(const GSTextureCache::Target* rt, c
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_channel_shuffle)
|
||||
{
|
||||
const GSVector4i src_box_rect = GSVector4i(m_vt.m_min.t.x, m_vt.m_min.t.y, m_vt.m_max.t.x, m_vt.m_max.t.y);
|
||||
const GSVector4i src_rect = src_box_rect + source_region.GetRect(rt->GetUnscaledSize().x, rt->GetUnscaledSize().y).xyxy();
|
||||
|
||||
// If the two don't overlap, there's no need to copy.
|
||||
if (m_r.rintersect(src_rect).rempty())
|
||||
{
|
||||
unscaled_size = rt->GetUnscaledSize();
|
||||
scale = rt->GetScale();
|
||||
return;
|
||||
}
|
||||
}
|
||||
GL_CACHE("HW: Source is render target, taking copy.");
|
||||
src_target = rt;
|
||||
}
|
||||
// Be careful of single page channel shuffles where depth is the source but it's not going to the same place, we can't read this directly.
|
||||
else if (ds && m_conf.tex == m_conf.ds && (!m_channel_shuffle || (rt && static_cast<int>(m_cached_ctx.FRAME.Block() - rt->m_TEX0.TBP0) == static_cast<int>(m_cached_ctx.ZBUF.Block() - ds->m_TEX0.TBP0))))
|
||||
else if (ds && m_conf.tex == m_conf.ds)
|
||||
{
|
||||
// GL, Vulkan (in General layout), DirectX11 (binding dsv as read only) no support for DirectX12 yet!
|
||||
const bool can_read_current_depth_buffer = g_gs_device->Features().test_and_sample_depth;
|
||||
|
||||
// If this is our current Z buffer, we might not be able to read it directly if it's being written to.
|
||||
// Rather than leaving the backend to do it, we'll check it here.
|
||||
if (can_read_current_depth_buffer && (m_cached_ctx.ZBUF.ZMSK || m_cached_ctx.TEST.ZTST == ZTST_NEVER))
|
||||
if ((!m_channel_shuffle || tex_diff == frame_diff) && g_gs_device->Features().test_and_sample_depth && (m_cached_ctx.ZBUF.ZMSK || m_cached_ctx.TEST.ZTST == ZTST_NEVER))
|
||||
{
|
||||
// Safe to read!
|
||||
GL_CACHE("HW: Source is depth buffer, not writing, safe to read.");
|
||||
@@ -7921,6 +7933,20 @@ __ri void GSRendererHW::HandleTextureHazards(const GSTextureCache::Target* rt, c
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_channel_shuffle)
|
||||
{
|
||||
const GSVector4i src_box_rect = GSVector4i(m_vt.m_min.t.x, m_vt.m_min.t.y, m_vt.m_max.t.x, m_vt.m_max.t.y);
|
||||
const GSVector4i src_rect = src_box_rect + source_region.GetRect(rt->GetUnscaledSize().x, rt->GetUnscaledSize().y).xyxy();
|
||||
|
||||
// If the two don't overlap, there's no need to copy.
|
||||
if (m_r.rintersect(src_rect).rempty())
|
||||
{
|
||||
unscaled_size = ds->GetUnscaledSize();
|
||||
scale = ds->GetScale();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Can't safely read the depth buffer, so we need to take a copy of it.
|
||||
GL_CACHE("HW: Source is depth buffer, unsafe to read, taking copy.");
|
||||
src_target = ds;
|
||||
@@ -9266,7 +9292,7 @@ bool GSRendererHW::CanUseSwPrimRender(bool no_rt, bool no_ds, bool draw_sprite_t
|
||||
else
|
||||
{
|
||||
// If the target isn't dirty we might have valid data, so let's check their areas overlap, if so we need to read it back for SW.
|
||||
GSVector4i src_rect = GSVector4i(m_vt.m_min.t.x, m_vt.m_min.t.y, m_vt.m_max.t.x, m_vt.m_max.t.x);
|
||||
GSVector4i src_rect = GSVector4i(m_vt.m_min.t.x, m_vt.m_min.t.y, m_vt.m_max.t.x, m_vt.m_max.t.y);
|
||||
GSVector4i area = g_texture_cache->TranslateAlignedRectByPage(src_target, m_cached_ctx.TEX0.TBP0, m_cached_ctx.TEX0.PSM, m_cached_ctx.TEX0.TBW, src_rect, false);
|
||||
req_readback = !area.rintersect(src_target->m_drawn_since_read).eq(GSVector4i::zero());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user