diff --git a/pcsx2/GS/Renderers/Common/GSDevice.h b/pcsx2/GS/Renderers/Common/GSDevice.h index 525903213d..ff5695ec9b 100644 --- a/pcsx2/GS/Renderers/Common/GSDevice.h +++ b/pcsx2/GS/Renderers/Common/GSDevice.h @@ -270,7 +270,7 @@ struct alignas(16) GSHWDrawConfig __fi bool IsFeedbackLoop() const { - return tex_is_fb || fbmask || date > 0 || blend_a == 1 || blend_b == 1 || blend_c == 1 || blend_d == 1; + return tex_is_fb || fbmask || (date > 0 && date != 3) || blend_a == 1 || blend_b == 1 || blend_c == 1 || blend_d == 1; } /// Disables color output from the pixel shader, this is done when all channels are masked. diff --git a/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp b/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp index 302ec98a9b..d54fc1ceb1 100644 --- a/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp +++ b/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp @@ -248,7 +248,7 @@ bool GSDeviceVK::CheckFeatures() m_features.texture_barrier = GSConfig.OverrideTextureBarriers != 0; m_features.broken_point_sampler = isAMD; m_features.geometry_shader = features.geometryShader && GSConfig.OverrideGeometryShaders != 0; - m_features.image_load_store = features.fragmentStoresAndAtomics && m_features.texture_barrier; + m_features.image_load_store = features.fragmentStoresAndAtomics; m_features.prefer_new_textures = true; m_features.provoking_vertex_last = g_vulkan_context->GetOptionalExtensions().vk_ext_provoking_vertex; m_features.dual_source_blend = features.dualSrcBlend && !GSConfig.DisableDualSourceBlend; @@ -2718,7 +2718,7 @@ void GSDeviceVK::SetupDATE(GSTexture* rt, GSTexture* ds, bool datm, const GSVect EndRenderPass(); } -GSTextureVK* GSDeviceVK::SetupPrimitiveTrackingDATE(GSHWDrawConfig& config, PipelineSelector& pipe) +GSTextureVK* GSDeviceVK::SetupPrimitiveTrackingDATE(GSHWDrawConfig& config) { // How this is done: // - can't put a barrier for the image in the middle of the normal render pass, so that's out @@ -2742,6 +2742,7 @@ GSTextureVK* GSDeviceVK::SetupPrimitiveTrackingDATE(GSHWDrawConfig& config, Pipe // 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); VkClearValue cv[2] = {}; cv[0].color.float32[0] = static_cast(std::numeric_limits::max()); @@ -2749,11 +2750,11 @@ GSTextureVK* GSDeviceVK::SetupPrimitiveTrackingDATE(GSHWDrawConfig& config, Pipe { cv[1].depthStencil.depth = static_cast(config.ds)->GetClearDepth(); cv[1].depthStencil.stencil = 1; - BeginClearRenderPass(m_date_image_setup_render_passes[pipe.ds][1], GSVector4i(0, 0, rtsize.x, rtsize.y), cv, 2); + BeginClearRenderPass(m_date_image_setup_render_passes[ds][1], GSVector4i(0, 0, rtsize.x, rtsize.y), cv, 2); } else { - BeginClearRenderPass(m_date_image_setup_render_passes[pipe.ds][0], config.drawarea, cv, 1); + BeginClearRenderPass(m_date_image_setup_render_passes[ds][0], config.drawarea, cv, 1); } // draw the quad to prefill the image @@ -2765,7 +2766,7 @@ GSTextureVK* GSDeviceVK::SetupPrimitiveTrackingDATE(GSHWDrawConfig& config, Pipe {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[pipe.ds][config.datm]; + const VkPipeline pipeline = m_date_image_setup_pipelines[ds][config.datm]; SetPipeline(pipeline); IASetVertexBuffer(vertices, sizeof(vertices[0]), std::size(vertices)); if (ApplyUtilityState()) @@ -2776,24 +2777,25 @@ GSTextureVK* GSDeviceVK::SetupPrimitiveTrackingDATE(GSHWDrawConfig& config, Pipe IASetIndexBuffer(config.indices, config.nindices); // cut down the configuration for the prepass, we don't need blending or any feedback loop - PipelineSelector init_pipe(m_pipeline_selector); - init_pipe.dss.zwe = false; - init_pipe.cms.wrgba = 0; - init_pipe.bs = {}; - init_pipe.feedback_loop = false; - init_pipe.rt = true; - init_pipe.ps.blend_a = init_pipe.ps.blend_b = init_pipe.ps.blend_c = init_pipe.ps.blend_d = false; - init_pipe.ps.date += 10; - init_pipe.ps.no_color = false; - init_pipe.ps.no_color1 = true; - if (BindDrawPipeline(init_pipe)) + PipelineSelector& pipe = m_pipeline_selector; + UpdateHWPipelineSelector(config, pipe); + pipe.dss.zwe = false; + pipe.cms.wrgba = 0; + pipe.bs = {}; + pipe.feedback_loop = false; + pipe.rt = true; + pipe.ps.blend_a = pipe.ps.blend_b = pipe.ps.blend_c = pipe.ps.blend_d = false; + pipe.ps.date += 10; + pipe.ps.no_color = false; + pipe.ps.no_color1 = true; + if (BindDrawPipeline(pipe)) DrawIndexedPrimitive(); // image is initialized/prepass is done, so finish up and get ready to do the "real" draw EndRenderPass(); // .. by setting it to DATE=3 - pipe.ps.date = 3; + config.ps.date = 3; config.alpha_second_pass.ps.date = 3; // and bind the image to the primitive sampler @@ -2836,11 +2838,7 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config) SetVSConstantBuffer(config.cb_vs); SetPSConstantBuffer(config.cb_ps); - // figure out the pipeline - UpdateHWPipelineSelector(config); - // bind textures before checking the render pass, in case we need to transition them - PipelineSelector& pipe = m_pipeline_selector; if (config.tex) { PSSetShaderResource(0, config.tex, config.tex != config.rt); @@ -2855,8 +2853,7 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config) GSTextureVK* date_image = nullptr; if (config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::PrimIDTracking) { - pxAssert(pipe.feedback_loop); - date_image = SetupPrimitiveTrackingDATE(config, pipe); + date_image = SetupPrimitiveTrackingDATE(config); if (!date_image) { Console.WriteLn("Failed to allocate DATE image, aborting draw."); @@ -2864,6 +2861,10 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config) } } + // figure out the pipeline + PipelineSelector& pipe = m_pipeline_selector; + UpdateHWPipelineSelector(config, pipe); + // Align the render area to 128x128, hopefully avoiding render pass restarts for small render area changes (e.g. Ratchet and Clank). const int render_area_alignment = 128 * GSConfig.UpscaleMultiplier; const GSVector2i rtsize(config.rt ? config.rt->GetSize() : config.ds->GetSize()); @@ -3118,26 +3119,25 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config) } } -void GSDeviceVK::UpdateHWPipelineSelector(GSHWDrawConfig& config) +void GSDeviceVK::UpdateHWPipelineSelector(GSHWDrawConfig& config, PipelineSelector& pipe) { - m_pipeline_selector.vs.key = config.vs.key; - m_pipeline_selector.gs.key = config.gs.key; - m_pipeline_selector.ps.key_hi = config.ps.key_hi; - m_pipeline_selector.ps.key_lo = config.ps.key_lo; - m_pipeline_selector.dss.key = config.depth.key; - m_pipeline_selector.bs.key = config.blend.key; - m_pipeline_selector.bs.constant = 0; // don't dupe states with different alpha values - m_pipeline_selector.cms.key = config.colormask.key; - m_pipeline_selector.topology = static_cast(config.topology); - m_pipeline_selector.rt = config.rt != nullptr; - m_pipeline_selector.ds = config.ds != nullptr; - m_pipeline_selector.line_width = config.line_expand; - m_pipeline_selector.feedback_loop = m_features.texture_barrier && - (config.ps.IsFeedbackLoop() || config.require_one_barrier || config.require_full_barrier || - config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::PrimIDTracking); + pipe.vs.key = config.vs.key; + pipe.gs.key = config.gs.key; + pipe.ps.key_hi = config.ps.key_hi; + pipe.ps.key_lo = config.ps.key_lo; + pipe.dss.key = config.depth.key; + pipe.bs.key = config.blend.key; + pipe.bs.constant = 0; // don't dupe states with different alpha values + pipe.cms.key = config.colormask.key; + pipe.topology = static_cast(config.topology); + pipe.rt = config.rt != nullptr; + pipe.ds = config.ds != nullptr; + pipe.line_width = config.line_expand; + pipe.feedback_loop = m_features.texture_barrier && + (config.ps.IsFeedbackLoop() || config.require_one_barrier || config.require_full_barrier); // enable point size in the vertex shader if we're rendering points regardless of upscaling. - m_pipeline_selector.vs.point_size |= (config.topology == GSHWDrawConfig::Topology::Point); + pipe.vs.point_size |= (config.topology == GSHWDrawConfig::Topology::Point); } void GSDeviceVK::SendHWDraw(const GSHWDrawConfig& config, GSTextureVK* draw_rt) diff --git a/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.h b/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.h index 64283faf92..f9d1c439ab 100644 --- a/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.h +++ b/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.h @@ -240,7 +240,7 @@ public: u32 dLevel, bool linear); void SetupDATE(GSTexture* rt, GSTexture* ds, bool datm, const GSVector4i& bbox); - GSTextureVK* SetupPrimitiveTrackingDATE(GSHWDrawConfig& config, PipelineSelector& pipe); + GSTextureVK* SetupPrimitiveTrackingDATE(GSHWDrawConfig& config); void IASetVertexBuffer(const void* vertex, size_t stride, size_t count); bool IAMapVertexBuffer(void** vertex, size_t stride, size_t count); @@ -257,7 +257,7 @@ public: bool BindDrawPipeline(const PipelineSelector& p); void RenderHW(GSHWDrawConfig& config) override; - void UpdateHWPipelineSelector(GSHWDrawConfig& config); + void UpdateHWPipelineSelector(GSHWDrawConfig& config, PipelineSelector& pipe); void SendHWDraw(const GSHWDrawConfig& config, GSTextureVK* draw_rt); //////////////////////////////////////////////////////////////////////////