GS/DX11: Skip barrier/copy if it's not needed.

It is possible to skip one barrier copy when using draw_ds_as_rt if only one pass needs a barrier, we already have a copy and draw_ds_as_rt doesn't need updating.
This commit is contained in:
lightningterror
2026-06-29 15:04:42 +02:00
parent f83e4ff4bf
commit f01dfec52f
2 changed files with 40 additions and 22 deletions
+37 -19
View File
@@ -3234,17 +3234,28 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
const bool ds_feedbackloop_pass1 = config.IsFeedbackLoopDepth(config.ps);
const bool ds_feedbackloop_pass2 = config.IsFeedbackLoopDepth(config.alpha_second_pass.ps);
// It is possible to skip one barrier copy when using draw_ds_as_rt if only one pass needs a barrier, we already have a copy and draw_ds_as_rt doesn't need updating.
const bool can_skip_ds_barrier = draw_ds_as_rt &&
// Pass 1 needs barrier only.
((ds_feedbackloop_pass1 && config.require_one_barrier && !ds_feedbackloop_pass2 && !config.alpha_second_pass.require_one_barrier) ||
// Pass 2 needs barrier only.
(!ds_feedbackloop_pass1 && !config.require_one_barrier && ds_feedbackloop_pass2 && config.alpha_second_pass.require_one_barrier));
if (draw_ds && !draw_ds_rov && (config.require_one_barrier || (config.require_full_barrier && m_features.multidraw_fb_copy)) &&
(ds_feedbackloop_pass1 || ds_feedbackloop_pass2))
{
// Requires a copy of the DS.
draw_ds_clone = CreateTexture(rtsize.x, rtsize.y, 1, (draw_ds_as_rt ? draw_ds_as_rt : draw_ds)->GetFormat(), true);
if (can_skip_ds_barrier)
draw_ds_clone = CreateFeedbackTarget(rtsize.x, rtsize.y, (draw_ds_as_rt ? draw_ds_as_rt : draw_ds)->GetFormat(), false, true);
else
draw_ds_clone = CreateTexture(rtsize.x, rtsize.y, 1, (draw_ds_as_rt ? draw_ds_as_rt : draw_ds)->GetFormat(), true);
if (!draw_ds_clone)
Console.Warning("D3D11: Failed to allocate temp texture for DS copy.");
}
OMSetRenderTargets(draw_rt, draw_ds_as_rt, draw_ds, draw_rt_rov, draw_ds_rov, &config.scissor, read_only_dsv);
OMSetRenderTargets(draw_rt, can_skip_ds_barrier ? draw_ds_clone : draw_ds_as_rt, draw_ds, draw_rt_rov, draw_ds_rov, &config.scissor, read_only_dsv);
SetRenderHWShaderResources(config, primid_texture);
SetupOM(config.depth, OMBlendSelector(config.colormask, config.blend), config.blend.constant);
@@ -3253,7 +3264,7 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
m_ctx->ClearDepthStencilView(*static_cast<GSTexture11*>(draw_ds), D3D11_CLEAR_STENCIL, 0.0f, 1);
SendHWDraw(config, rt_feedbackloop_pass1 ? draw_rt_clone : nullptr, draw_rt, ds_feedbackloop_pass1 ? draw_ds_clone : nullptr, draw_ds_as_rt ? draw_ds_as_rt : draw_ds,
config.require_one_barrier, config.require_full_barrier, rtsize);
config.require_one_barrier, config.require_full_barrier, can_skip_ds_barrier, rtsize);
if (config.blend_multi_pass.enable)
{
@@ -3281,7 +3292,7 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
const bool one_barrier = config.alpha_second_pass.require_one_barrier && m_features.multidraw_fb_copy;
SetupOM(config.alpha_second_pass.depth, OMBlendSelector(config.alpha_second_pass.colormask, config.blend), config.blend.constant);
SendHWDraw(config, rt_feedbackloop_pass2 ? draw_rt_clone : nullptr, draw_rt, ds_feedbackloop_pass2 ? draw_ds_clone : nullptr, draw_ds_as_rt ? draw_ds_as_rt : draw_ds,
one_barrier, config.alpha_second_pass.require_full_barrier, rtsize);
one_barrier, config.alpha_second_pass.require_full_barrier, can_skip_ds_barrier, rtsize);
}
if (colclip_rt)
@@ -3302,27 +3313,34 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
}
void GSDevice11::FeedbackCopyAndBind(const GSHWDrawConfig& config,
GSTexture* rt, GSTexture* rt_clone, GSTexture* ds, GSTexture* ds_clone, const GSVector4i& copyarea)
GSTexture* rt, GSTexture* rt_clone, GSTexture* ds, GSTexture* ds_clone, const bool skip_ds_barrier, const GSVector4i& copyarea)
{
if (rt_clone)
{
CopyRect(rt, rt_clone, copyarea, copyarea.left, copyarea.top);
PSSetShaderResource(2, rt_clone);
PSSetShaderResource(TEXTURE_RT, rt_clone);
if (config.tex_hazard == GSHWDrawConfig::TEX_HAZARD_RT)
PSSetShaderResource(0, rt_clone);
}
if (ds_clone)
{
CopyRect(ds, ds_clone, copyarea, copyarea.left, copyarea.top);
PSSetShaderResource(4, ds_clone);
if (config.tex_hazard == GSHWDrawConfig::TEX_HAZARD_DEPTH)
PSSetShaderResource(0, ds_clone);
if (skip_ds_barrier)
{
PSSetShaderResource(TEXTURE_DEPTH, ds);
}
else
{
CopyRect(ds, ds_clone, copyarea, copyarea.left, copyarea.top);
PSSetShaderResource(TEXTURE_DEPTH, ds_clone);
if (config.tex_hazard == GSHWDrawConfig::TEX_HAZARD_DEPTH)
PSSetShaderResource(0, ds_clone);
}
}
}
// Choose the best copy area based on the hazards and whether we need RT and/or DS copies.
void GSDevice11::FeedbackCopyAndBind(const GSHWDrawConfig& config,
GSTexture* rt, GSTexture* rt_clone, GSTexture* ds, GSTexture* ds_clone,
GSTexture* rt, GSTexture* rt_clone, GSTexture* ds, GSTexture* ds_clone, const bool skip_ds_barrier,
const GSVector4i& copyarea, const GSVector4i& samplearea)
{
const GSVector4i rtsize = (rt ? rt : ds)->GetRect();
@@ -3338,24 +3356,24 @@ void GSDevice11::FeedbackCopyAndBind(const GSHWDrawConfig& config,
// Do an individual copy if the union is larger than the sum of individual areas.
if (size_union > size_indiv)
{
FeedbackCopyAndBind(config, rt, rt_clone, ds, ds_clone, ProcessCopyArea(rtsize, config.drawarea));
FeedbackCopyAndBind(config, rt, rt_clone, ds, ds_clone, ProcessCopyArea(rtsize, config.samplearea));
FeedbackCopyAndBind(config, rt, rt_clone, ds, ds_clone, skip_ds_barrier, ProcessCopyArea(rtsize, config.drawarea));
FeedbackCopyAndBind(config, rt, rt_clone, ds, ds_clone, skip_ds_barrier, ProcessCopyArea(rtsize, config.samplearea));
}
else
{
FeedbackCopyAndBind(config, rt, rt_clone, ds, ds_clone, ProcessCopyArea(rtsize, union_rect));
FeedbackCopyAndBind(config, rt, rt_clone, ds, ds_clone, skip_ds_barrier, ProcessCopyArea(rtsize, union_rect));
}
}
else
{
// No RT hazards so just need the draw area (or full area for DS).
FeedbackCopyAndBind(config, rt, rt_clone, ds, ds_clone, ProcessCopyArea(rtsize, config.drawarea));
FeedbackCopyAndBind(config, rt, rt_clone, ds, ds_clone, skip_ds_barrier, ProcessCopyArea(rtsize, config.drawarea));
}
};
void GSDevice11::SendHWDraw(const GSHWDrawConfig& config,
GSTexture* draw_rt_clone, GSTexture* draw_rt, GSTexture* draw_ds_clone, GSTexture* draw_ds,
const bool one_barrier, const bool full_barrier, GSVector2i rtsize)
const bool one_barrier, const bool full_barrier, const bool skip_ds_barrier, GSVector2i rtsize)
{
#ifdef PCSX2_DEVBUILD
if ((one_barrier || full_barrier) && !(config.IsFeedbackLoopRT(config.ps) || config.IsFeedbackLoopDepth(config.ps))) [[unlikely]]
@@ -3371,7 +3389,7 @@ void GSDevice11::SendHWDraw(const GSHWDrawConfig& config,
pxAssert(config.drawlist_bbox && static_cast<u32>(config.drawlist_bbox->size()) == draw_list_size);
if (config.tex_hazard != config.TEX_HAZARD_NONE)
FeedbackCopyAndBind(config, draw_rt, draw_rt_clone, draw_ds, draw_ds_clone, config.samplearea);
FeedbackCopyAndBind(config, draw_rt, draw_rt_clone, draw_ds, draw_ds_clone, skip_ds_barrier, config.samplearea);
for (u32 n = 0, p = 0; n < draw_list_size; n++)
{
@@ -3379,7 +3397,7 @@ void GSDevice11::SendHWDraw(const GSHWDrawConfig& config,
const GSVector4i bbox = config.drawlist_bbox->at(n).rintersect(config.drawarea);
FeedbackCopyAndBind(config, draw_rt, draw_rt_clone, draw_ds, draw_ds_clone, bbox);
FeedbackCopyAndBind(config, draw_rt, draw_rt_clone, draw_ds, draw_ds_clone, skip_ds_barrier, bbox);
Draw(config, p, count);
@@ -3391,7 +3409,7 @@ void GSDevice11::SendHWDraw(const GSHWDrawConfig& config,
if (one_barrier)
{
FeedbackCopyAndBind(config, draw_rt, draw_rt_clone, draw_ds, draw_ds_clone, config.drawarea, config.samplearea);
FeedbackCopyAndBind(config, draw_rt, draw_rt_clone, draw_ds, draw_ds_clone, skip_ds_barrier, config.drawarea, config.samplearea);
}
Draw(config);
+3 -3
View File
@@ -416,13 +416,13 @@ public:
void RenderHW(GSHWDrawConfig& config) override;
void FeedbackCopyAndBind(const GSHWDrawConfig& config,
GSTexture* rt, GSTexture* rt_clone, GSTexture* ds, GSTexture* ds_clone, const GSVector4i& copyarea);
GSTexture* rt, GSTexture* rt_clone, GSTexture* ds, GSTexture* ds_clone, const bool skip_ds_barrier, const GSVector4i& copyarea);
void FeedbackCopyAndBind(const GSHWDrawConfig& config,
GSTexture* rt, GSTexture* rt_clone, GSTexture* ds, GSTexture* ds_clone,
GSTexture* rt, GSTexture* rt_clone, GSTexture* ds, GSTexture* ds_clone, const bool skip_ds_barrier,
const GSVector4i& copyarea, const GSVector4i& samplearea);
void SendHWDraw(const GSHWDrawConfig& config,
GSTexture* draw_rt_clone, GSTexture* draw_rt, GSTexture* draw_ds_clone, GSTexture* draw_ds,
const bool one_barrier, const bool full_barrier, GSVector2i rtsize);
const bool one_barrier, const bool full_barrier, const bool skip_ds_barrier, GSVector2i rtsize);
void SetRenderHWShaderResources(const GSHWDrawConfig& config, GSTexture* primid_texture);
void ClearSamplerCache() override;