mirror of https://github.com/PCSX2/pcsx2.git
GS/HW: Avoid barriers on second alpha pass when only writing to Z
Completely redundant. We also don't need to use the drawlist.
This commit is contained in:
parent
ba7096c9fa
commit
20dbcfd2eb
|
@ -387,7 +387,7 @@ struct alignas(16) GSHWDrawConfig
|
||||||
__fi bool IsFeedbackLoop() const
|
__fi bool IsFeedbackLoop() const
|
||||||
{
|
{
|
||||||
const u32 sw_blend_bits = blend_a | blend_b | blend_d;
|
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);
|
const bool sw_blend_needs_rt = (sw_blend_bits != 0 && ((sw_blend_bits | blend_c) & 1u)) || ((a_masked & blend_c) != 0);
|
||||||
return tex_is_fb || fbmask || (date > 0 && date != 3) || sw_blend_needs_rt;
|
return tex_is_fb || fbmask || (date > 0 && date != 3) || sw_blend_needs_rt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -688,7 +688,9 @@ struct alignas(16) GSHWDrawConfig
|
||||||
struct AlphaPass
|
struct AlphaPass
|
||||||
{
|
{
|
||||||
alignas(8) PSSelector ps;
|
alignas(8) PSSelector ps;
|
||||||
bool enable;
|
bool enable : 1;
|
||||||
|
bool require_one_barrier : 1;
|
||||||
|
bool require_full_barrier : 1;
|
||||||
ColorMaskSelector colormask;
|
ColorMaskSelector colormask;
|
||||||
DepthStencilSelector depth;
|
DepthStencilSelector depth;
|
||||||
float ps_aref;
|
float ps_aref;
|
||||||
|
|
|
@ -5917,11 +5917,10 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta
|
||||||
|
|
||||||
SetupIA(rtscale, sx, sy);
|
SetupIA(rtscale, sx, sy);
|
||||||
|
|
||||||
m_conf.alpha_second_pass.enable = ate_second_pass;
|
|
||||||
|
|
||||||
if (ate_second_pass)
|
if (ate_second_pass)
|
||||||
{
|
{
|
||||||
pxAssert(!env.PABE.PABE);
|
pxAssert(!env.PABE.PABE);
|
||||||
|
|
||||||
std::memcpy(&m_conf.alpha_second_pass.ps, &m_conf.ps, sizeof(m_conf.ps));
|
std::memcpy(&m_conf.alpha_second_pass.ps, &m_conf.ps, sizeof(m_conf.ps));
|
||||||
std::memcpy(&m_conf.alpha_second_pass.colormask, &m_conf.colormask, sizeof(m_conf.colormask));
|
std::memcpy(&m_conf.alpha_second_pass.colormask, &m_conf.colormask, sizeof(m_conf.colormask));
|
||||||
std::memcpy(&m_conf.alpha_second_pass.depth, &m_conf.depth, sizeof(m_conf.depth));
|
std::memcpy(&m_conf.alpha_second_pass.depth, &m_conf.depth, sizeof(m_conf.depth));
|
||||||
|
@ -5965,6 +5964,8 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta
|
||||||
r = g = b = a = false;
|
r = g = b = a = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_conf.alpha_second_pass.enable = true;
|
||||||
|
|
||||||
if (z || r || g || b || a)
|
if (z || r || g || b || a)
|
||||||
{
|
{
|
||||||
m_conf.alpha_second_pass.depth.zwe = z;
|
m_conf.alpha_second_pass.depth.zwe = z;
|
||||||
|
@ -5973,8 +5974,15 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta
|
||||||
m_conf.alpha_second_pass.colormask.wb = b;
|
m_conf.alpha_second_pass.colormask.wb = b;
|
||||||
m_conf.alpha_second_pass.colormask.wa = a;
|
m_conf.alpha_second_pass.colormask.wa = a;
|
||||||
if (m_conf.alpha_second_pass.colormask.wrgba == 0)
|
if (m_conf.alpha_second_pass.colormask.wrgba == 0)
|
||||||
|
{
|
||||||
m_conf.alpha_second_pass.ps.DisableColorOutput();
|
m_conf.alpha_second_pass.ps.DisableColorOutput();
|
||||||
}
|
}
|
||||||
|
if (m_conf.alpha_second_pass.ps.IsFeedbackLoop())
|
||||||
|
{
|
||||||
|
m_conf.alpha_second_pass.require_one_barrier = m_conf.require_one_barrier;
|
||||||
|
m_conf.alpha_second_pass.require_full_barrier = m_conf.require_full_barrier;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_conf.alpha_second_pass.enable = false;
|
m_conf.alpha_second_pass.enable = false;
|
||||||
|
|
|
@ -5839,7 +5839,7 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
|
||||||
|
|
||||||
// now we can do the actual draw
|
// now we can do the actual draw
|
||||||
if (BindDrawPipeline(pipe))
|
if (BindDrawPipeline(pipe))
|
||||||
SendHWDraw(config, draw_rt, skip_first_barrier);
|
SendHWDraw(config, draw_rt, config.require_one_barrier, config.require_full_barrier, skip_first_barrier);
|
||||||
|
|
||||||
// blend second pass
|
// blend second pass
|
||||||
if (config.blend_second_pass.enable)
|
if (config.blend_second_pass.enable)
|
||||||
|
@ -5851,8 +5851,11 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
|
||||||
pipe.ps.blend_hw = config.blend_second_pass.blend_hw;
|
pipe.ps.blend_hw = config.blend_second_pass.blend_hw;
|
||||||
pipe.ps.dither = config.blend_second_pass.dither;
|
pipe.ps.dither = config.blend_second_pass.dither;
|
||||||
if (BindDrawPipeline(pipe))
|
if (BindDrawPipeline(pipe))
|
||||||
|
{
|
||||||
|
// TODO: This probably should have barriers, in case we want to use it conditionally.
|
||||||
DrawIndexedPrimitive();
|
DrawIndexedPrimitive();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// and the alpha pass
|
// and the alpha pass
|
||||||
if (config.alpha_second_pass.enable)
|
if (config.alpha_second_pass.enable)
|
||||||
|
@ -5869,7 +5872,10 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
|
||||||
pipe.dss = config.alpha_second_pass.depth;
|
pipe.dss = config.alpha_second_pass.depth;
|
||||||
pipe.bs = config.blend;
|
pipe.bs = config.blend;
|
||||||
if (BindDrawPipeline(pipe))
|
if (BindDrawPipeline(pipe))
|
||||||
SendHWDraw(config, draw_rt, false);
|
{
|
||||||
|
SendHWDraw(config, draw_rt, config.alpha_second_pass.require_one_barrier,
|
||||||
|
config.alpha_second_pass.require_full_barrier, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (draw_rt_clone)
|
if (draw_rt_clone)
|
||||||
|
@ -5972,8 +5978,25 @@ VkImageMemoryBarrier GSDeviceVK::GetColorBufferBarrier(GSTextureVK* rt) const
|
||||||
VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, rt->GetImage(), {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u}};
|
VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, rt->GetImage(), {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u}};
|
||||||
}
|
}
|
||||||
|
|
||||||
void GSDeviceVK::SendHWDraw(const GSHWDrawConfig& config, GSTextureVK* draw_rt, bool skip_first_barrier)
|
void GSDeviceVK::SendHWDraw(const GSHWDrawConfig& config, GSTextureVK* draw_rt,
|
||||||
|
bool one_barrier, bool full_barrier, bool skip_first_barrier)
|
||||||
{
|
{
|
||||||
|
if (!m_features.texture_barrier) [[unlikely]]
|
||||||
|
{
|
||||||
|
DrawIndexedPrimitive();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef PCSX2_DEVBUILD
|
||||||
|
if ((one_barrier || full_barrier) && !m_pipeline_selector.ps.IsFeedbackLoop()) [[unlikely]]
|
||||||
|
Console.Warning("GS: Possible unnecessary barrier detected.");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (full_barrier)
|
||||||
|
{
|
||||||
|
const VkImageMemoryBarrier barrier = GetColorBufferBarrier(draw_rt);
|
||||||
|
const u32 indices_per_prim = config.indices_per_prim;
|
||||||
|
|
||||||
if (config.drawlist)
|
if (config.drawlist)
|
||||||
{
|
{
|
||||||
GL_PUSH("Split the draw (SPRITE)");
|
GL_PUSH("Split the draw (SPRITE)");
|
||||||
|
@ -6003,18 +6026,9 @@ void GSDeviceVK::SendHWDraw(const GSHWDrawConfig& config, GSTextureVK* draw_rt,
|
||||||
DrawIndexedPrimitive(p, count);
|
DrawIndexedPrimitive(p, count);
|
||||||
p += count;
|
p += count;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (m_features.texture_barrier && m_pipeline_selector.ps.IsFeedbackLoop())
|
|
||||||
{
|
{
|
||||||
const VkImageMemoryBarrier barrier = GetColorBufferBarrier(draw_rt);
|
|
||||||
|
|
||||||
if (config.require_full_barrier)
|
|
||||||
{
|
|
||||||
const u32 indices_per_prim = config.indices_per_prim;
|
|
||||||
|
|
||||||
GL_PUSH("Split single draw in %d draw", config.nindices / indices_per_prim);
|
GL_PUSH("Split single draw in %d draw", config.nindices / indices_per_prim);
|
||||||
g_perfmon.Put(
|
g_perfmon.Put(
|
||||||
GSPerfMon::Barriers, (config.nindices / indices_per_prim) - static_cast<u32>(skip_first_barrier));
|
GSPerfMon::Barriers, (config.nindices / indices_per_prim) - static_cast<u32>(skip_first_barrier));
|
||||||
|
@ -6033,17 +6047,19 @@ void GSDeviceVK::SendHWDraw(const GSHWDrawConfig& config, GSTextureVK* draw_rt,
|
||||||
|
|
||||||
DrawIndexedPrimitive(p, indices_per_prim);
|
DrawIndexedPrimitive(p, indices_per_prim);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.require_one_barrier && !skip_first_barrier)
|
if (one_barrier && !skip_first_barrier)
|
||||||
{
|
{
|
||||||
g_perfmon.Put(GSPerfMon::Barriers, 1);
|
g_perfmon.Put(GSPerfMon::Barriers, 1);
|
||||||
|
|
||||||
|
const VkImageMemoryBarrier barrier = GetColorBufferBarrier(draw_rt);
|
||||||
vkCmdPipelineBarrier(GetCurrentCommandBuffer(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
vkCmdPipelineBarrier(GetCurrentCommandBuffer(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, &barrier);
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, &barrier);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
DrawIndexedPrimitive();
|
DrawIndexedPrimitive();
|
||||||
}
|
}
|
||||||
|
|
|
@ -588,7 +588,8 @@ public:
|
||||||
void UpdateHWPipelineSelector(GSHWDrawConfig& config, PipelineSelector& pipe);
|
void UpdateHWPipelineSelector(GSHWDrawConfig& config, PipelineSelector& pipe);
|
||||||
void UploadHWDrawVerticesAndIndices(const GSHWDrawConfig& config);
|
void UploadHWDrawVerticesAndIndices(const GSHWDrawConfig& config);
|
||||||
VkImageMemoryBarrier GetColorBufferBarrier(GSTextureVK* rt) const;
|
VkImageMemoryBarrier GetColorBufferBarrier(GSTextureVK* rt) const;
|
||||||
void SendHWDraw(const GSHWDrawConfig& config, GSTextureVK* draw_rt, bool skip_first_barrier);
|
void SendHWDraw(const GSHWDrawConfig& config, GSTextureVK* draw_rt,
|
||||||
|
bool one_barrier, bool full_barrier, bool skip_first_barrier);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
// Vulkan State
|
// Vulkan State
|
||||||
|
|
Loading…
Reference in New Issue