mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-10-12 02:08:45 +00:00
GS/HW: Handle barrier hazards in RendererHW instead of Device.
Cleaner, easier to track.
This commit is contained in:
@@ -1469,7 +1469,7 @@ static void DumpPSSelector(DrawConfigWriter& out, const GSHWDrawConfig::PSSelect
|
||||
out.WriteLn("no_color: {}", ps.no_color);
|
||||
out.WriteLn("no_color1: {}", ps.no_color1);
|
||||
out.WriteLn("channel: {} ({})", GetPSChannelName(static_cast<ChannelFetch>(ps.channel)), ps.channel);
|
||||
out.WriteLn("channel_fb: {}", ps.channel_fb);
|
||||
out.WriteLn("tex_hazard: {}", ps.tex_hazard);
|
||||
out.WriteLn("dither: {} ({})", GetPSDitherName(ps.dither), ps.dither);
|
||||
out.WriteLn("dither_adjust: {}", ps.dither_adjust);
|
||||
out.WriteLn("zclamp: {}", ps.zclamp);
|
||||
|
||||
@@ -397,7 +397,7 @@ struct alignas(16) GSHWDrawConfig
|
||||
|
||||
// Others ways to fetch the texture
|
||||
u32 channel : 3;
|
||||
u32 channel_fb : 1;
|
||||
u32 tex_hazard : 2; // 1 rt, 2 ds
|
||||
|
||||
// Dithering
|
||||
u32 dither : 2;
|
||||
@@ -445,7 +445,7 @@ struct alignas(16) GSHWDrawConfig
|
||||
const u32 sw_blend_bits = blend_a | blend_b | blend_d;
|
||||
const bool sw_blend_needs_rt = (sw_blend_bits != 0 && ((sw_blend_bits | blend_c) & 1u)) || ((a_masked & blend_c) != 0);
|
||||
const bool afail_needs_rt = afail == PS_AFAIL::ZB_ONLY || afail == PS_AFAIL::RGB_ONLY || afail == PS_AFAIL::RGB_ONLY_SW_Z;
|
||||
return channel_fb || tex_is_fb || fbmask || (date >= 5) || sw_blend_needs_rt || afail_needs_rt;
|
||||
return tex_hazard == 1 || tex_is_fb || fbmask || (date >= 5) || sw_blend_needs_rt || afail_needs_rt;
|
||||
}
|
||||
|
||||
__fi bool IsFeedbackLoopDepth() const
|
||||
@@ -453,7 +453,7 @@ struct alignas(16) GSHWDrawConfig
|
||||
const bool afail_needs_depth = afail == PS_AFAIL::FB_ONLY || afail == PS_AFAIL::RGB_ONLY_SW_Z;
|
||||
const bool ztst_needs_depth = ztst == ZTST_GEQUAL || ztst == ZTST_GREATER;
|
||||
const bool aa1_needs_depth = aa1 == PS_AA1::TRIANGLE_SW_Z;
|
||||
return afail_needs_depth || ztst_needs_depth || aa1_needs_depth;
|
||||
return tex_hazard == 2 || afail_needs_depth || ztst_needs_depth || aa1_needs_depth;
|
||||
}
|
||||
|
||||
/// Disables color output from the pixel shader, this is done when all channels are masked.
|
||||
|
||||
@@ -7880,6 +7880,39 @@ __ri void GSRendererHW::HandleTextureHazards(const GSTextureCache::Target* rt, c
|
||||
const int tex_diff = tex->m_from_target ? static_cast<int>(m_cached_ctx.TEX0.TBP0 - tex->m_from_target->m_TEX0.TBP0) : static_cast<int>(m_cached_ctx.TEX0.TBP0 - tex->m_TEX0.TBP0);
|
||||
const int frame_diff = rt ? static_cast<int>(m_cached_ctx.FRAME.Block() - rt->m_TEX0.TBP0) : 0;
|
||||
|
||||
// Needs to be called everywhere we return early except tex is fb, or read only depth.
|
||||
auto HandleBarrierHazard = [&](bool src_empty) {
|
||||
if (rt && m_conf.tex == m_conf.rt)
|
||||
{
|
||||
m_conf.ps.tex_hazard = 1;
|
||||
if (m_prim_overlap == PRIM_OVERLAP_NO || src_empty || m_channel_shuffle || !g_gs_device->Features().feedback_loops())
|
||||
m_conf.require_one_barrier = true;
|
||||
else
|
||||
m_conf.require_full_barrier = true;
|
||||
}
|
||||
else if (ds && m_conf.tex == m_conf.ds)
|
||||
{
|
||||
// This might be hit again if it's called when there's no match.
|
||||
if (g_gs_device->Features().test_and_sample_depth && (m_cached_ctx.ZBUF.ZMSK || m_cached_ctx.TEST.ZTST == ZTST_NEVER))
|
||||
{
|
||||
// No barrier, depth can be read safely.
|
||||
}
|
||||
// TODO: Add gpu copies for depth on VK/DX12 that doesn't rely on feedback loops.
|
||||
else if (g_gs_device->Features().feedback_loops())
|
||||
{
|
||||
m_conf.ps.tex_hazard = 2;
|
||||
if (m_prim_overlap == PRIM_OVERLAP_NO || src_empty || m_channel_shuffle)
|
||||
m_conf.require_one_barrier = true;
|
||||
else
|
||||
m_conf.require_full_barrier = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_conf.tex = nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Detect framebuffer read that will need special handling
|
||||
const GSTextureCache::Target* src_target = nullptr;
|
||||
if (!m_downscale_source || !tex->m_from_target)
|
||||
@@ -7909,6 +7942,7 @@ __ri void GSRendererHW::HandleTextureHazards(const GSTextureCache::Target* rt, c
|
||||
// If the two don't overlap, there's no need to copy.
|
||||
if (m_r.rintersect(src_rect).rempty())
|
||||
{
|
||||
HandleBarrierHazard(true);
|
||||
unscaled_size = rt->GetUnscaledSize();
|
||||
scale = rt->GetScale();
|
||||
return;
|
||||
@@ -7919,9 +7953,6 @@ __ri void GSRendererHW::HandleTextureHazards(const GSTextureCache::Target* rt, c
|
||||
}
|
||||
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 ((!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))
|
||||
@@ -7941,6 +7972,7 @@ __ri void GSRendererHW::HandleTextureHazards(const GSTextureCache::Target* rt, c
|
||||
// If the two don't overlap, there's no need to copy.
|
||||
if (m_r.rintersect(src_rect).rempty())
|
||||
{
|
||||
HandleBarrierHazard(true);
|
||||
unscaled_size = ds->GetUnscaledSize();
|
||||
scale = ds->GetScale();
|
||||
return;
|
||||
@@ -7958,6 +7990,7 @@ __ri void GSRendererHW::HandleTextureHazards(const GSTextureCache::Target* rt, c
|
||||
else
|
||||
{
|
||||
// No match.
|
||||
HandleBarrierHazard(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -8013,7 +8046,7 @@ __ri void GSRendererHW::HandleTextureHazards(const GSTextureCache::Target* rt, c
|
||||
}
|
||||
|
||||
m_conf.cb_ps.ChannelShuffleOffset = GSVector2((horizontal_offset - m_r.x) * tex->GetScale(), (vertical_offset - m_r.y) * tex->GetScale());
|
||||
m_conf.ps.channel_fb = 1;
|
||||
m_conf.ps.tex_hazard = 1;
|
||||
target_region = false;
|
||||
source_region.bits = 0;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user