GS/HW: Skip unnecessary barriers (usually two pass alpha)

This commit is contained in:
Connor McLaughlin 2022-03-28 21:32:43 +10:00 committed by refractionpcsx2
parent e8293b2e06
commit de724d9570
4 changed files with 61 additions and 42 deletions

View File

@ -270,7 +270,9 @@ struct alignas(16) GSHWDrawConfig
__fi bool IsFeedbackLoop() const __fi bool IsFeedbackLoop() const
{ {
return tex_is_fb || fbmask || (date > 0 && date != 3) || blend_a == 1 || blend_b == 1 || blend_c == 1 || blend_d == 1; 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);
return tex_is_fb || fbmask || (date > 0 && date != 3) || sw_blend_needs_rt;
} }
/// Disables color output from the pixel shader, this is done when all channels are masked. /// Disables color output from the pixel shader, this is done when all channels are masked.

View File

@ -1959,7 +1959,7 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
OMSetRenderTargets(hdr_rt ? hdr_rt : config.rt, config.ds, &config.scissor); OMSetRenderTargets(hdr_rt ? hdr_rt : config.rt, config.ds, &config.scissor);
SendHWDraw(config); SendHWDraw(config, psel.ps.IsFeedbackLoop());
if (config.separate_alpha_pass) if (config.separate_alpha_pass)
{ {
@ -1969,7 +1969,7 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
OMSetColorMaskState(config.alpha_second_pass.colormask); OMSetColorMaskState(config.alpha_second_pass.colormask);
SetupOM(config.alpha_second_pass.depth); SetupOM(config.alpha_second_pass.depth);
OMSetBlendState(); OMSetBlendState();
SendHWDraw(config); SendHWDraw(config, psel.ps.IsFeedbackLoop());
// restore blend state if we're doing a second pass // restore blend state if we're doing a second pass
if (config.alpha_second_pass.enable) if (config.alpha_second_pass.enable)
@ -1994,7 +1994,7 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
SetupPipeline(psel); SetupPipeline(psel);
OMSetColorMaskState(config.alpha_second_pass.colormask); OMSetColorMaskState(config.alpha_second_pass.colormask);
SetupOM(config.alpha_second_pass.depth); SetupOM(config.alpha_second_pass.depth);
SendHWDraw(config); SendHWDraw(config, psel.ps.IsFeedbackLoop());
if (config.second_separate_alpha_pass) if (config.second_separate_alpha_pass)
{ {
@ -2004,7 +2004,7 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
OMSetColorMaskState(config.alpha_second_pass.colormask); OMSetColorMaskState(config.alpha_second_pass.colormask);
SetupOM(config.alpha_second_pass.depth); SetupOM(config.alpha_second_pass.depth);
OMSetBlendState(); OMSetBlendState();
SendHWDraw(config); SendHWDraw(config, psel.ps.IsFeedbackLoop());
} }
} }
@ -2026,7 +2026,7 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
} }
} }
void GSDeviceOGL::SendHWDraw(const GSHWDrawConfig& config) void GSDeviceOGL::SendHWDraw(const GSHWDrawConfig& config, bool needs_barrier)
{ {
if (config.drawlist) if (config.drawlist)
{ {
@ -2051,31 +2051,40 @@ void GSDeviceOGL::SendHWDraw(const GSHWDrawConfig& config)
glTextureBarrier(); glTextureBarrier();
DrawIndexedPrimitive(p, count); DrawIndexedPrimitive(p, count);
} }
return;
} }
else if (config.require_full_barrier)
const bool tex_is_ds = config.tex && config.tex == config.ds;
if (needs_barrier || tex_is_ds)
{ {
GL_PUSH("Split the draw"); if (config.require_full_barrier)
GL_PERF("Split single draw in %d draw", config.nindices / config.indices_per_prim);
for (size_t p = 0; p < config.nindices; p += config.indices_per_prim)
{ {
GL_PUSH("Split the draw");
GL_PERF("Split single draw in %d draw", config.nindices / config.indices_per_prim);
for (size_t p = 0; p < config.nindices; p += config.indices_per_prim)
{
glTextureBarrier();
DrawIndexedPrimitive(p, config.indices_per_prim);
}
return;
}
if (config.require_one_barrier || tex_is_ds)
{
// The common renderer code doesn't put a barrier here because D3D/VK need to copy the DS, so we need to check it.
// One barrier needed for non-overlapping draw.
glTextureBarrier(); glTextureBarrier();
DrawIndexedPrimitive(p, config.indices_per_prim); DrawIndexedPrimitive();
return;
} }
} }
else if (config.require_one_barrier || (config.tex && config.tex == config.ds))
{ // No barriers needed
// The common renderer code doesn't put a barrier here because D3D/VK need to copy the DS, so we need to check it. DrawIndexedPrimitive();
// One barrier needed for non-overlapping draw.
glTextureBarrier();
DrawIndexedPrimitive();
}
else
{
// No barriers needed
DrawIndexedPrimitive();
}
} }
// Note: used as a callback of DebugMessageCallback. Don't change the signature // Note: used as a callback of DebugMessageCallback. Don't change the signature

View File

@ -356,7 +356,7 @@ public:
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, const GL::Program& ps, bool alpha_blend, OMColorMaskSelector cms, bool linear = true); void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, const GL::Program& ps, bool alpha_blend, OMColorMaskSelector cms, bool linear = true);
void RenderHW(GSHWDrawConfig& config) final; void RenderHW(GSHWDrawConfig& config) final;
void SendHWDraw(const GSHWDrawConfig& config); void SendHWDraw(const GSHWDrawConfig& config, bool needs_barrier);
void SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* vertices, bool datm); void SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* vertices, bool datm);

View File

@ -3152,25 +3152,33 @@ void GSDeviceVK::SendHWDraw(const GSHWDrawConfig& config, GSTextureVK* draw_rt)
ColorBufferBarrier(draw_rt); ColorBufferBarrier(draw_rt);
DrawIndexedPrimitive(p, count); DrawIndexedPrimitive(p, count);
} }
}
else if (config.require_full_barrier)
{
GL_PUSH("Split single draw in %d draw", config.nindices / config.indices_per_prim);
for (u32 p = 0; p < config.nindices; p += config.indices_per_prim) return;
}
if (m_features.texture_barrier && m_pipeline_selector.ps.IsFeedbackLoop())
{
if (config.require_full_barrier)
{
GL_PUSH("Split single draw in %d draw", config.nindices / config.indices_per_prim);
for (u32 p = 0; p < config.nindices; p += config.indices_per_prim)
{
ColorBufferBarrier(draw_rt);
DrawIndexedPrimitive(p, config.indices_per_prim);
}
return;
}
if (config.require_one_barrier)
{ {
ColorBufferBarrier(draw_rt); ColorBufferBarrier(draw_rt);
DrawIndexedPrimitive(p, config.indices_per_prim); DrawIndexedPrimitive();
return;
} }
} }
else if (config.require_one_barrier && m_features.texture_barrier)
{ // Don't need any barrier
ColorBufferBarrier(draw_rt); DrawIndexedPrimitive();
DrawIndexedPrimitive();
}
else
{
// Don't need any barrier
DrawIndexedPrimitive();
}
} }