From 875fdc40a5ab07bb786d7bea2a2294b842dd0fd2 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Fri, 1 Mar 2024 17:07:06 +1000 Subject: [PATCH] GS/Vulkan: Don't ever fully clear stencil on DATE draws We manually clear the drawn region when it's needed, in all other cases it's pre-filled with the setup. Therefore, the two load actions should be preserve and don't care. --- pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp | 40 ++++++++++-------------- pcsx2/GS/Renderers/Vulkan/GSDeviceVK.h | 10 ++---- 2 files changed, 18 insertions(+), 32 deletions(-) diff --git a/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp b/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp index a1d2c2f24b..2cc63e6043 100644 --- a/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp +++ b/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp @@ -3826,7 +3826,7 @@ bool GSDeviceVK::CreateRenderPasses() { for (u32 hdr = 0; hdr < 2; hdr++) { - for (u32 date = DATE_RENDER_PASS_NONE; date <= DATE_RENDER_PASS_STENCIL_ONE; date++) + for (u32 stencil = 0; stencil < 2; stencil++) { for (u32 fbl = 0; fbl < 2; fbl++) { @@ -3840,12 +3840,10 @@ bool GSDeviceVK::CreateRenderPasses() const VkFormat rp_rt_format = (rt != 0) ? ((hdr != 0) ? hdr_rt_format : rt_format) : VK_FORMAT_UNDEFINED; const VkFormat rp_depth_format = (ds != 0) ? depth_format : VK_FORMAT_UNDEFINED; - const VkAttachmentLoadOp opc = - ((date == DATE_RENDER_PASS_NONE || !m_features.stencil_buffer) ? - VK_ATTACHMENT_LOAD_OP_DONT_CARE : - (date == DATE_RENDER_PASS_STENCIL_ONE ? VK_ATTACHMENT_LOAD_OP_CLEAR : - VK_ATTACHMENT_LOAD_OP_LOAD)); - GET(m_tfx_render_pass[rt][ds][hdr][date][fbl][dsp][opa][opb], rp_rt_format, + const VkAttachmentLoadOp opc = (!stencil || !m_features.stencil_buffer) ? + VK_ATTACHMENT_LOAD_OP_DONT_CARE : + VK_ATTACHMENT_LOAD_OP_LOAD; + GET(m_tfx_render_pass[rt][ds][hdr][stencil][fbl][dsp][opa][opb], rp_rt_format, rp_depth_format, (fbl != 0), (dsp != 0), static_cast(opa), static_cast(opb), static_cast(opc)); } @@ -4004,7 +4002,7 @@ bool GSDeviceVK::CompileConvertPipelines() { pxAssert(!arr[ds][fbl]); - gpb.SetRenderPass(GetTFXRenderPass(true, ds != 0, is_setup, DATE_RENDER_PASS_NONE, fbl != 0, false, + gpb.SetRenderPass(GetTFXRenderPass(true, ds != 0, is_setup, false, fbl != 0, false, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_LOAD_OP_DONT_CARE), 0); arr[ds][fbl] = gpb.Create(m_device, g_vulkan_shader_cache->GetPipelineCache(true), false); @@ -4805,7 +4803,7 @@ VkPipeline GSDeviceVK::CreateTFXPipeline(const PipelineSelector& p) else { gpb.SetRenderPass( - GetTFXRenderPass(p.rt, p.ds, p.ps.hdr, p.dss.date ? DATE_RENDER_PASS_STENCIL : DATE_RENDER_PASS_NONE, + GetTFXRenderPass(p.rt, p.ds, p.ps.hdr, p.dss.date, p.IsRTFeedbackLoop(), p.IsTestingAndSamplingDepth(), p.rt ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_DONT_CARE, p.ds ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_DONT_CARE), @@ -5557,7 +5555,6 @@ GSTextureVK* GSDeviceVK::SetupPrimitiveTrackingDATE(GSHWDrawConfig& config) void GSDeviceVK::RenderHW(GSHWDrawConfig& config) { // Destination Alpha Setup - DATE_RENDER_PASS DATE_rp = DATE_RENDER_PASS_NONE; switch (config.destination_alpha) { case GSHWDrawConfig::DestinationAlphaMode::Off: // No setup @@ -5570,18 +5567,13 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config) if (!m_features.texture_barrier) { SetupDATE(config.rt, config.ds, config.datm, config.drawarea); - DATE_rp = DATE_RENDER_PASS_STENCIL; - } - else - { - DATE_rp = DATE_RENDER_PASS_STENCIL_ONE; + config.destination_alpha = GSHWDrawConfig::DestinationAlphaMode::Stencil; } } break; case GSHWDrawConfig::DestinationAlphaMode::Stencil: SetupDATE(config.rt, config.ds, config.datm, config.drawarea); - DATE_rp = DATE_RENDER_PASS_STENCIL; break; } @@ -5731,22 +5723,21 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config) { const VkAttachmentLoadOp rt_op = GetLoadOpForTexture(draw_rt); const VkAttachmentLoadOp ds_op = GetLoadOpForTexture(draw_ds); - const VkRenderPass rp = GetTFXRenderPass(pipe.rt, pipe.ds, pipe.ps.hdr, DATE_rp, pipe.IsRTFeedbackLoop(), + const VkRenderPass rp = GetTFXRenderPass(pipe.rt, pipe.ds, pipe.ps.hdr, + config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::Stencil, pipe.IsRTFeedbackLoop(), pipe.IsTestingAndSamplingDepth(), rt_op, ds_op); const bool is_clearing_rt = (rt_op == VK_ATTACHMENT_LOAD_OP_CLEAR || ds_op == VK_ATTACHMENT_LOAD_OP_CLEAR); const GSVector4i render_area = GSVector4i::loadh(rtsize); - if (is_clearing_rt || DATE_rp == DATE_RENDER_PASS_STENCIL_ONE) + if (is_clearing_rt) { // when we're clearing, we set the draw area to the whole fb, otherwise part of it will be undefined alignas(16) VkClearValue cvs[2]; u32 cv_count = 0; if (draw_rt) GSVector4::store(&cvs[cv_count++].color, draw_rt->GetUNormClearColor()); - - // the only time the stencil value is used here is DATE_one, so setting it to 1 is fine (not used otherwise) if (draw_ds) - cvs[cv_count++].depthStencil = {draw_ds->GetClearDepth(), 1}; + cvs[cv_count++].depthStencil = {draw_ds->GetClearDepth(), 0}; BeginClearRenderPass(rp, render_area, cvs, cv_count); } @@ -5755,7 +5746,8 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config) BeginRenderPass(rp, render_area); } } - else if (DATE_rp == DATE_RENDER_PASS_STENCIL_ONE) + + if (config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::StencilOne) { const VkClearAttachment ca = {VK_IMAGE_ASPECT_STENCIL_BIT, 0u, {.depthStencil = {0.0f, 1u}}}; const VkClearRect rc = {{{config.drawarea.left, config.drawarea.top}, @@ -5846,7 +5838,7 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config) if (draw_ds) cvs[cv_count++].depthStencil = {draw_ds->GetClearDepth(), 1}; - BeginClearRenderPass(GetTFXRenderPass(true, pipe.ds, false, DATE_RENDER_PASS_NONE, pipe.IsRTFeedbackLoop(), + BeginClearRenderPass(GetTFXRenderPass(true, pipe.ds, false, false, pipe.IsRTFeedbackLoop(), pipe.IsTestingAndSamplingDepth(), VK_ATTACHMENT_LOAD_OP_CLEAR, pipe.ds ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_DONT_CARE), draw_rt->GetRect(), cvs, cv_count); @@ -5854,7 +5846,7 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config) } else { - BeginRenderPass(GetTFXRenderPass(true, pipe.ds, false, DATE_RENDER_PASS_NONE, pipe.IsRTFeedbackLoop(), + BeginRenderPass(GetTFXRenderPass(true, pipe.ds, false, false, pipe.IsRTFeedbackLoop(), pipe.IsTestingAndSamplingDepth(), VK_ATTACHMENT_LOAD_OP_LOAD, pipe.ds ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_DONT_CARE), draw_rt->GetRect()); diff --git a/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.h b/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.h index a36355ad93..04b57ab516 100644 --- a/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.h +++ b/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.h @@ -390,12 +390,6 @@ public: NUM_TFX_TEXTURES }; - enum DATE_RENDER_PASS : u32 - { - DATE_RENDER_PASS_NONE = 0, - DATE_RENDER_PASS_STENCIL = 1, - DATE_RENDER_PASS_STENCIL_ONE = 2, - }; private: std::unique_ptr m_swap_chain; @@ -514,10 +508,10 @@ public: /// Returns true if Vulkan is suitable as a default for the devices in the system. static bool IsSuitableDefaultRenderer(); - __fi VkRenderPass GetTFXRenderPass(bool rt, bool ds, bool hdr, DATE_RENDER_PASS date, bool fbl, bool dsp, + __fi VkRenderPass GetTFXRenderPass(bool rt, bool ds, bool hdr, bool stencil, bool fbl, bool dsp, VkAttachmentLoadOp rt_op, VkAttachmentLoadOp ds_op) const { - return m_tfx_render_pass[rt][ds][hdr][date][fbl][dsp][rt_op][ds_op]; + return m_tfx_render_pass[rt][ds][hdr][stencil][fbl][dsp][rt_op][ds_op]; } __fi VkSampler GetPointSampler() const { return m_point_sampler; } __fi VkSampler GetLinearSampler() const { return m_linear_sampler; }