diff --git a/bin/resources/shaders/vulkan/convert.glsl b/bin/resources/shaders/vulkan/convert.glsl index ab02c9d502ad9e..9ed50972a2fc49 100644 --- a/bin/resources/shaders/vulkan/convert.glsl +++ b/bin/resources/shaders/vulkan/convert.glsl @@ -92,6 +92,23 @@ void ps_datm0() } #endif +#ifdef ps_datm1_rta_correction +void ps_datm1_rta_correction() +{ + if(sample_c(v_tex).a < (255.0f / 255.0f)) // >= 0x80 pass + discard; + +} +#endif + +#ifdef ps_datm0_rta_correction +void ps_datm0_rta_correction() +{ + if((255.0f / 255.0f) < sample_c(v_tex).a) // < 0x80 pass (== 0x80 should not pass) + discard; +} +#endif + #ifdef ps_rta_correction void ps_rta_correction() { @@ -416,7 +433,7 @@ void ps_yuv() } #endif -#if defined(ps_stencil_image_init_0) || defined(ps_stencil_image_init_1) +#if defined(ps_stencil_image_init_0) || defined(ps_stencil_image_init_1) || defined(ps_stencil_image_rta_init_0) || defined(ps_stencil_image_rta_init_1) void main() { @@ -430,6 +447,14 @@ void main() if(sample_c(v_tex).a < (127.5f / 255.0f)) // >= 0x80 pass o_col0 = vec4(-1); #endif + #ifdef ps_stencil_image_rta_init_0 + if((255.0f / 255.0f) < sample_c(v_tex).a) // < 0x80 pass (== 0x80 should not pass) + o_col0 = vec4(-1); + #endif + #ifdef ps_stencil_image_rta_init_1 + if(sample_c(v_tex).a < (255.0f / 255.0f)) // >= 0x80 pass + o_col0 = vec4(-1); + #endif } #endif diff --git a/bin/resources/shaders/vulkan/tfx.glsl b/bin/resources/shaders/vulkan/tfx.glsl index 4c7faf30c5f2cf..fc5736ea262557 100644 --- a/bin/resources/shaders/vulkan/tfx.glsl +++ b/bin/resources/shaders/vulkan/tfx.glsl @@ -1181,10 +1181,18 @@ void main() #if (PS_DATE & 3) == 1 // DATM == 0: Pixel with alpha equal to 1 will failed - bool bad = (127.5f / 255.0f) < rt_a; + #if PS_RTA_CORRECTION + bool bad = (255.0f / 255.0f) < rt_a; + #else + bool bad = (127.5f / 255.0f) < rt_a; + #endif #elif (PS_DATE & 3) == 2 // DATM == 1: Pixel with alpha equal to 0 will failed - bool bad = rt_a < (127.5f / 255.0f); + #if PS_RTA_CORRECTION + bool bad = rt_a < (255.0f / 255.0f); + #else + bool bad = rt_a < (127.5f / 255.0f); + #endif #endif if (bad) { diff --git a/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp b/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp index 84b477460879ac..0169ab4d3567e7 100644 --- a/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp +++ b/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp @@ -4031,6 +4031,18 @@ bool GSDeviceVK::CompileConvertPipelines() ds ? VK_ATTACHMENT_STORE_OP_STORE : VK_ATTACHMENT_STORE_OP_DONT_CARE); } } + for (u32 ds = 0; ds < 2; ds++) + { + for (u32 clear = 0; clear < 2; clear++) + { + m_date_image_rta_setup_render_passes[ds][clear] = GetRenderPass(LookupNativeFormat(GSTexture::Format::PrimID), + ds ? LookupNativeFormat(GSTexture::Format::DepthStencil) : VK_FORMAT_UNDEFINED, + VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE, + ds ? (clear ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD) : + VK_ATTACHMENT_LOAD_OP_DONT_CARE, + ds ? VK_ATTACHMENT_STORE_OP_STORE : VK_ATTACHMENT_STORE_OP_DONT_CARE); + } + } for (u32 datm = 0; datm < 2; datm++) { @@ -4061,6 +4073,35 @@ bool GSDeviceVK::CompileConvertPipelines() } } + for (u32 datm = 0; datm < 2; datm++) + { + VkShaderModule ps = + GetUtilityFragmentShader(*shader, datm ? "ps_stencil_image_rta_init_1" : "ps_stencil_image_rta_init_0"); + if (ps == VK_NULL_HANDLE) + return false; + + ScopedGuard ps_guard([this, &ps]() { vkDestroyShaderModule(m_device, ps, nullptr); }); + gpb.SetPipelineLayout(m_utility_pipeline_layout); + gpb.SetFragmentShader(ps); + gpb.SetNoDepthTestState(); + gpb.SetNoStencilState(); + gpb.ClearBlendAttachments(); + gpb.SetBlendAttachment(0, false, VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_ZERO, VK_BLEND_OP_ADD, + VK_BLEND_FACTOR_ZERO, VK_BLEND_FACTOR_ZERO, VK_BLEND_OP_ADD, VK_COLOR_COMPONENT_R_BIT); + + for (u32 ds = 0; ds < 2; ds++) + { + gpb.SetRenderPass(m_date_image_rta_setup_render_passes[ds][0], 0); + m_date_image_rta_setup_pipelines[ds][datm] = + gpb.Create(m_device, g_vulkan_shader_cache->GetPipelineCache(true), false); + if (!m_date_image_rta_setup_pipelines[ds][datm]) + return false; + + Vulkan::SetObjectName(m_device, m_date_image_rta_setup_pipelines[ds][datm], + "DATE RTA image clear pipeline (ds=%u, datm=%u)", ds, datm); + } + } + return true; } @@ -4594,6 +4635,14 @@ void GSDeviceVK::DestroyResources() vkDestroyPipeline(m_device, m_date_image_setup_pipelines[ds][datm], nullptr); } } + for (u32 ds = 0; ds < 2; ds++) + { + for (u32 datm = 0; datm < 2; datm++) + { + if (m_date_image_rta_setup_pipelines[ds][datm] != VK_NULL_HANDLE) + vkDestroyPipeline(m_device, m_date_image_rta_setup_pipelines[ds][datm], nullptr); + } + } if (m_fxaa_pipeline != VK_NULL_HANDLE) vkDestroyPipeline(m_device, m_fxaa_pipeline, nullptr); if (m_shadeboost_pipeline != VK_NULL_HANDLE) @@ -4801,7 +4850,7 @@ VkPipeline GSDeviceVK::CreateTFXPipeline(const PipelineSelector& p) if (IsDATEModePrimIDInit(p.ps.date)) { // DATE image prepass - gpb.SetRenderPass(m_date_image_setup_render_passes[p.ds][0], 0); + gpb.SetRenderPass(p.ps.rta_correction ? m_date_image_rta_setup_render_passes[p.ds][0] : m_date_image_setup_render_passes[p.ds][0], 0); } else { @@ -5494,17 +5543,19 @@ GSTextureVK* GSDeviceVK::SetupPrimitiveTrackingDATE(GSHWDrawConfig& config) // if the depth target has been cleared, we need to preserve that clear const VkAttachmentLoadOp ds_load_op = GetLoadOpForTexture(static_cast(config.ds)); const u32 ds = (config.ds ? 1 : 0); + const bool datm_rta = config.datm > 1; + const bool datm = (config.datm == 1 || config.datm == 3); if (ds_load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) { VkClearValue cv[2] = {}; cv[1].depthStencil.depth = static_cast(config.ds)->GetClearDepth(); cv[1].depthStencil.stencil = 1; - BeginClearRenderPass(m_date_image_setup_render_passes[ds][1], GSVector4i::loadh(rtsize), cv, 2); + BeginClearRenderPass(datm_rta ? m_date_image_rta_setup_render_passes[ds][1] : m_date_image_setup_render_passes[ds][1], GSVector4i::loadh(rtsize), cv, 2); } else { - BeginRenderPass(m_date_image_setup_render_passes[ds][0], config.drawarea); + BeginRenderPass(datm_rta ? m_date_image_rta_setup_render_passes[ds][0] : m_date_image_setup_render_passes[ds][0], config.drawarea); } // draw the quad to prefill the image @@ -5516,7 +5567,7 @@ GSTextureVK* GSDeviceVK::SetupPrimitiveTrackingDATE(GSHWDrawConfig& config) {GSVector4(dst.x, -dst.w, 0.5f, 1.0f), GSVector2(src.x, src.w)}, {GSVector4(dst.z, -dst.w, 0.5f, 1.0f), GSVector2(src.z, src.w)}, }; - const VkPipeline pipeline = m_date_image_setup_pipelines[ds][config.datm]; + const VkPipeline pipeline = datm_rta ? m_date_image_rta_setup_pipelines[ds][datm] : m_date_image_setup_pipelines[ds][datm]; SetPipeline(pipeline); IASetVertexBuffer(vertices, sizeof(vertices[0]), std::size(vertices)); if (ApplyUtilityState()) diff --git a/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.h b/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.h index a36355ad935242..576a3bda079f9d 100644 --- a/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.h +++ b/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.h @@ -429,6 +429,8 @@ class GSDeviceVK final : public GSDevice VkPipeline m_hdr_finish_pipelines[2][2] = {}; // [depth][feedback_loop] VkRenderPass m_date_image_setup_render_passes[2][2] = {}; // [depth][clear] VkPipeline m_date_image_setup_pipelines[2][2] = {}; // [depth][datm] + VkRenderPass m_date_image_rta_setup_render_passes[2][2] = {}; // [depth][clear] + VkPipeline m_date_image_rta_setup_pipelines[2][2] = {}; // [depth][datm] VkPipeline m_fxaa_pipeline = {}; VkPipeline m_shadeboost_pipeline = {};