Skip to content

Commit

Permalink
GS/Vulkan: Don't ever fully clear stencil on DATE draws
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
stenzek committed Mar 2, 2024
1 parent 0ae3cbf commit 875fdc4
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 32 deletions.
40 changes: 16 additions & 24 deletions pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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++)
{
Expand All @@ -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<VkAttachmentLoadOp>(opa),
static_cast<VkAttachmentLoadOp>(opb), static_cast<VkAttachmentLoadOp>(opc));
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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
Expand All @@ -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;
}

Expand Down Expand Up @@ -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<true>(&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);
}
Expand All @@ -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},
Expand Down Expand Up @@ -5846,15 +5838,15 @@ 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);
draw_rt->SetState(GSTexture::State::Dirty);
}
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());
Expand Down
10 changes: 2 additions & 8 deletions pcsx2/GS/Renderers/Vulkan/GSDeviceVK.h
Original file line number Diff line number Diff line change
Expand Up @@ -390,12 +390,6 @@ class GSDeviceVK final : public GSDevice

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<VKSwapChain> m_swap_chain;
Expand Down Expand Up @@ -514,10 +508,10 @@ class GSDeviceVK final : public GSDevice
/// 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; }
Expand Down

0 comments on commit 875fdc4

Please sign in to comment.