mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-10-12 02:08:45 +00:00
GS/HW: Further improve tex hazards.
Always enable test and sample depth on vk as well. Make sure there is no feedback depth when using barriers, as GL/DX12 have issues with it, so just stick with a plain copy which is equivalent to depth as rt which we would have to do anyway. Check for hazards properly for Hitman shuffle. Better handle depth read only condition, allow for a barrier if it isn't. Better handle hazard checks in device when doing a copy. We don't need two or union copies on dx11 for depth as dx11 can't do partial depth gpu copies.
This commit is contained in:
@@ -2907,10 +2907,8 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
|
||||
ID3D11DepthStencilView* read_only_dsv = nullptr;
|
||||
if (config.tex && config.tex == config.ds)
|
||||
{
|
||||
if (m_features.test_and_sample_depth && !config.depth.zwe && !config.ps.IsFeedbackLoopDepth() && !config.alpha_second_pass.ps.IsFeedbackLoopDepth())
|
||||
if (m_features.test_and_sample_depth && !config.depth.zwe && !config.IsFeedbackLoopDepth(config.ps) && !config.IsFeedbackLoopDepth(config.alpha_second_pass.ps))
|
||||
read_only_dsv = static_cast<GSTexture11*>(config.ds)->ReadOnlyDepthStencilView();
|
||||
else
|
||||
config.tex = nullptr;
|
||||
}
|
||||
|
||||
SetupVS(config.vs, &config.cb_vs);
|
||||
@@ -2960,8 +2958,8 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
|
||||
Console.Warning("D3D11: Failed to allocate temp texture for RT copy.");
|
||||
}
|
||||
|
||||
const bool ds_feedbackloop_pass1 = config.ps.IsFeedbackLoopDepth();
|
||||
const bool ds_feedbackloop_pass2 = config.alpha_second_pass.ps.IsFeedbackLoopDepth();
|
||||
const bool ds_feedbackloop_pass1 = config.IsFeedbackLoopDepth(config.ps);
|
||||
const bool ds_feedbackloop_pass2 = config.IsFeedbackLoopDepth(config.alpha_second_pass.ps);
|
||||
if (draw_ds && m_features.depth_feedback && (config.require_one_barrier || (config.require_full_barrier && m_features.multidraw_fb_copy)) &&
|
||||
(ds_feedbackloop_pass1 || ds_feedbackloop_pass2))
|
||||
{
|
||||
@@ -3034,7 +3032,7 @@ void GSDevice11::SendHWDraw(const GSHWDrawConfig& config,
|
||||
const bool one_barrier, const bool full_barrier)
|
||||
{
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
if ((one_barrier || full_barrier) && !((config.tex && config.tex == draw_rt) || config.IsFeedbackLoopRT(config.ps) || config.IsFeedbackLoopDepth(config.ps))) [[unlikely]]
|
||||
if ((one_barrier || full_barrier) && !(config.IsFeedbackLoopRT(config.ps) || config.IsFeedbackLoopDepth(config.ps))) [[unlikely]]
|
||||
Console.Warning("D3D11: Possible unnecessary copy detected.");
|
||||
#endif
|
||||
|
||||
@@ -3044,13 +3042,16 @@ void GSDevice11::SendHWDraw(const GSHWDrawConfig& config,
|
||||
CopyRect(draw_rt, draw_rt_clone, drawarea, drawarea.left, drawarea.top);
|
||||
if ((one_barrier || full_barrier))
|
||||
PSSetShaderResource(2, draw_rt_clone);
|
||||
if (config.tex && config.tex == draw_rt)
|
||||
if (config.tex_hazard == GSHWDrawConfig::TEX_HAZARD_RT)
|
||||
PSSetShaderResource(0, draw_rt_clone);
|
||||
}
|
||||
if (draw_ds_clone)
|
||||
{
|
||||
CopyRect(draw_ds, draw_ds_clone, drawarea, drawarea.left, drawarea.top);
|
||||
PSSetShaderResource(4, draw_ds_clone);
|
||||
if ((one_barrier || full_barrier))
|
||||
PSSetShaderResource(4, draw_ds_clone);
|
||||
if (config.tex_hazard == GSHWDrawConfig::TEX_HAZARD_DEPTH)
|
||||
PSSetShaderResource(0, draw_ds_clone);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -3081,7 +3082,8 @@ void GSDevice11::SendHWDraw(const GSHWDrawConfig& config,
|
||||
|
||||
if (one_barrier)
|
||||
{
|
||||
if (config.tex_hazard)
|
||||
// DX11 can't do partial depth copies.
|
||||
if (config.tex_hazard == GSHWDrawConfig::TEX_HAZARD_RT)
|
||||
{
|
||||
const GSVector4i union_rect = config.drawarea.runion(config.samplearea);
|
||||
const u32 size_union = union_rect.width() * union_rect.height();
|
||||
@@ -3110,7 +3112,7 @@ void GSDevice11::SendHWDraw(const GSHWDrawConfig& config,
|
||||
|
||||
void GSDevice11::SetRenderHWShaderResources(const GSHWDrawConfig& config, GSTexture* primid_texture)
|
||||
{
|
||||
if (config.tex && config.tex != config.rt)
|
||||
if (config.tex && config.tex_hazard == GSHWDrawConfig::TEX_HAZARD_NONE)
|
||||
{
|
||||
CommitClear(config.tex);
|
||||
PSSetShaderResource(0, config.tex);
|
||||
|
||||
@@ -4405,7 +4405,7 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
|
||||
|
||||
if (config.require_one_barrier)
|
||||
PSSetShaderResource(2, draw_rt_clone, true);
|
||||
if (config.tex && config.tex == draw_rt)
|
||||
if (config.tex_hazard == GSHWDrawConfig::TEX_HAZARD_RT)
|
||||
PSSetShaderResource(0, draw_rt_clone, true);
|
||||
}
|
||||
else
|
||||
@@ -4569,7 +4569,7 @@ void GSDevice12::SendHWDraw(const PipelineSelector& pipe, const GSHWDrawConfig&
|
||||
#endif
|
||||
if ((one_barrier || full_barrier) && feedback_rt)
|
||||
PSSetShaderResource(2, draw_rt, false, true);
|
||||
if (config.tex && config.tex == config.rt)
|
||||
if (config.tex_hazard == GSHWDrawConfig::TEX_HAZARD_RT)
|
||||
PSSetShaderResource(0, draw_rt, false, true);
|
||||
if ((one_barrier || full_barrier) && feedback_depth)
|
||||
PSSetShaderResource(4, draw_ds, false, true);
|
||||
|
||||
@@ -7907,7 +7907,14 @@ __ri void GSRendererHW::HandleTextureHazards(const GSTextureCache::Target* rt, c
|
||||
}
|
||||
else if (ds && m_conf.tex == m_conf.ds)
|
||||
{
|
||||
if (g_gs_device->Features().feedback_loops())
|
||||
// Check if we have depth feedback, if we do then we need to make a copy as
|
||||
// GL/DX12 has issues with depth feedback and depth as rt will basically do the same.
|
||||
const bool no_depth_write = (m_cached_ctx.ZBUF.ZMSK || m_cached_ctx.TEST.ZTST == ZTST_NEVER);
|
||||
if (g_gs_device->Features().test_and_sample_depth && no_depth_write)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (g_gs_device->Features().feedback_loops() && no_depth_write)
|
||||
{
|
||||
m_conf.tex_hazard = GSHWDrawConfig::TEX_HAZARD_DEPTH;
|
||||
if (m_prim_overlap == PRIM_OVERLAP_NO || src_empty || m_channel_shuffle)
|
||||
@@ -7971,13 +7978,17 @@ __ri void GSRendererHW::HandleTextureHazards(const GSTextureCache::Target* rt, c
|
||||
{
|
||||
// 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))
|
||||
if ((!m_channel_shuffle || tex_diff == frame_diff) && (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.");
|
||||
unscaled_size = ds->GetUnscaledSize();
|
||||
scale = ds->GetScale();
|
||||
return;
|
||||
// We need to make sure test_and_sample_depth is supported, otherwise we might still need a barrier/copy.
|
||||
if (HandleBarrierHazard(true))
|
||||
{
|
||||
// Safe to read!
|
||||
GL_CACHE("HW: Source is depth buffer, not writing, safe to read.");
|
||||
unscaled_size = ds->GetUnscaledSize();
|
||||
scale = ds->GetScale();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_channel_shuffle)
|
||||
@@ -8047,23 +8058,9 @@ __ri void GSRendererHW::HandleTextureHazards(const GSTextureCache::Target* rt, c
|
||||
const int horizontal_offset = ((page_offset % src_target->m_TEX0.TBW) * GSLocalMemory::m_psm[src_target->m_TEX0.PSM].pgs.x);
|
||||
const int vertical_offset = ((page_offset / src_target->m_TEX0.TBW) * GSLocalMemory::m_psm[src_target->m_TEX0.PSM].pgs.y);
|
||||
|
||||
if (g_gs_device->Features().feedback_loops())
|
||||
if (HandleBarrierHazard(false))
|
||||
{
|
||||
const u32 max_skip = ((m_channel_shuffle_finish || !m_channel_shuffle_width) ? 1 : m_channel_shuffle_width) << 5;
|
||||
const bool new_shuffle = !(m_last_channel_shuffle_fbmsk == m_context->FRAME.FBMSK &&
|
||||
m_last_channel_shuffle_fbp <= m_context->FRAME.Block() && (m_last_channel_shuffle_fbp + max_skip) >= m_context->FRAME.Block() &&
|
||||
m_last_channel_shuffle_end_block > m_context->FRAME.Block() && m_last_channel_shuffle_tbp <= m_context->TEX0.TBP0 && (m_last_channel_shuffle_tbp + max_skip) >= m_context->TEX0.TBP0);
|
||||
|
||||
if (rt == tex->m_from_target && new_shuffle)
|
||||
{
|
||||
if (m_prim_overlap == PRIM_OVERLAP_NO)
|
||||
m_conf.require_one_barrier = true;
|
||||
else
|
||||
m_conf.require_full_barrier = true;
|
||||
}
|
||||
|
||||
m_conf.cb_ps.ChannelShuffleOffset = GSVector2((horizontal_offset - m_r.x) * tex->GetScale(), (vertical_offset - m_r.y) * tex->GetScale());
|
||||
m_conf.tex_hazard = GSHWDrawConfig::TEX_HAZARD_RT;
|
||||
target_region = false;
|
||||
source_region.bits = 0;
|
||||
|
||||
|
||||
@@ -2797,7 +2797,7 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
|
||||
}
|
||||
IASetPrimitiveTopology(topology);
|
||||
|
||||
if (config.tex && (m_features.texture_barrier || (config.tex != config.rt)))
|
||||
if (config.tex && (m_features.texture_barrier || config.tex_hazard == GSHWDrawConfig::TEX_HAZARD_NONE))
|
||||
PSSetShaderResource(0, config.tex);
|
||||
if (config.pal)
|
||||
PSSetShaderResource(1, config.pal);
|
||||
@@ -3038,8 +3038,7 @@ void GSDeviceOGL::SendHWDraw(const GSHWDrawConfig& config,
|
||||
const bool one_barrier, const bool full_barrier)
|
||||
{
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
if ((one_barrier || full_barrier) &&
|
||||
!((!m_features.texture_barrier && config.tex && config.tex == draw_rt) || config.IsFeedbackLoopRT(config.ps) || config.IsFeedbackLoopDepth(config.ps))) [[unlikely]]
|
||||
if ((one_barrier || full_barrier) && !(config.IsFeedbackLoopRT(config.ps) || config.IsFeedbackLoopDepth(config.ps))) [[unlikely]]
|
||||
Console.Warning("OpenGL: Possible unnecessary barrier detected.");
|
||||
#endif
|
||||
|
||||
@@ -3049,13 +3048,16 @@ void GSDeviceOGL::SendHWDraw(const GSHWDrawConfig& config,
|
||||
CopyRect(draw_rt, draw_rt_clone, drawarea, drawarea.left, drawarea.top);
|
||||
if ((one_barrier || full_barrier))
|
||||
PSSetShaderResource(2, draw_rt_clone);
|
||||
if (config.tex && config.tex == draw_rt)
|
||||
if (config.tex_hazard == GSHWDrawConfig::TEX_HAZARD_RT)
|
||||
PSSetShaderResource(0, draw_rt_clone);
|
||||
}
|
||||
if (draw_ds_clone)
|
||||
{
|
||||
CopyRect(draw_ds, draw_ds_clone, drawarea, drawarea.left, drawarea.top);
|
||||
PSSetShaderResource(4, draw_ds_clone);
|
||||
if ((one_barrier || full_barrier))
|
||||
PSSetShaderResource(4, draw_ds_clone);
|
||||
if (config.tex_hazard == GSHWDrawConfig::TEX_HAZARD_DEPTH)
|
||||
PSSetShaderResource(0, draw_ds_clone);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -2691,7 +2691,7 @@ bool GSDeviceVK::CheckFeatures()
|
||||
m_features.framebuffer_fetch &= m_features.texture_barrier;
|
||||
|
||||
// Buggy drivers with broken barriers probably have no chance using GENERAL layout for depth either...
|
||||
m_features.test_and_sample_depth = m_features.texture_barrier;
|
||||
m_features.test_and_sample_depth = true;
|
||||
|
||||
// Use D32F depth instead of D32S8 when we have framebuffer fetch.
|
||||
m_features.stencil_buffer &= !m_features.framebuffer_fetch;
|
||||
@@ -6031,7 +6031,7 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
|
||||
|
||||
if (config.require_one_barrier)
|
||||
PSSetShaderResource(2, draw_rt_clone, true);
|
||||
if (config.tex && config.tex == draw_rt)
|
||||
if (config.tex_hazard == GSHWDrawConfig::TEX_HAZARD_RT)
|
||||
PSSetShaderResource(0, draw_rt_clone, true);
|
||||
}
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user