diff --git a/rpcs3/Emu/RSX/VK/VKDraw.cpp b/rpcs3/Emu/RSX/VK/VKDraw.cpp index a63deca25f..d6bac9977f 100644 --- a/rpcs3/Emu/RSX/VK/VKDraw.cpp +++ b/rpcs3/Emu/RSX/VK/VKDraw.cpp @@ -147,7 +147,14 @@ VkRenderPass VKGSRender::get_render_pass() void VKGSRender::invalidate_render_pass() { // Regenerate renderpass key for the next draw call - if (const auto key = vk::get_renderpass_key(m_fbo_images, m_current_renderpass_key); + std::vector input_attachments{}; + if (current_fragment_program.ctrl & RSX_SHADER_CONTROL_PROGRAMMABLE_BLENDING) + { + input_attachments.resize(m_draw_buffers.size()); + std::iota(input_attachments.begin(), input_attachments.end(), 0); + } + + if (const auto key = vk::get_renderpass_key(m_fbo_images, m_current_renderpass_key, input_attachments); key != m_current_renderpass_key) { m_current_renderpass_key = key; diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index f701beac2f..1c3a22f957 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -1804,6 +1804,12 @@ bool VKGSRender::load_program() get_current_vertex_program(vs_sampler_state); + if (!!(current_fragment_program.ctrl & RSX_SHADER_CONTROL_PROGRAMMABLE_BLENDING) != + vk::renderpass_has_input_attachments(m_current_renderpass_key)) + { + invalidate_render_pass(); + } + m_graphics_state.clear(rsx::pipeline_state::invalidate_pipeline_bits); } else if (!(m_graphics_state & rsx::pipeline_state::pipeline_config_dirty) && @@ -2665,7 +2671,15 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context) } } - m_current_renderpass_key = vk::get_renderpass_key(m_fbo_images); + std::vector input_attachments{}; + if ((current_fragment_program.ctrl & RSX_SHADER_CONTROL_PROGRAMMABLE_BLENDING) && + !m_graphics_state.test(rsx::pipeline_state::fragment_program_state_dirty)) + { + input_attachments.resize(m_draw_buffers.size()); + std::iota(input_attachments.begin(), input_attachments.end(), 0); + } + + m_current_renderpass_key = vk::get_renderpass_key(m_fbo_images, input_attachments); m_cached_renderpass = vk::get_renderpass(*m_device, m_current_renderpass_key); // Search old framebuffers for this same configuration @@ -2677,7 +2691,7 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context) m_draw_fbo->release(); } - m_draw_fbo = vk::get_framebuffer(*m_device, fbo_width, fbo_height, VK_FALSE, m_cached_renderpass, m_fbo_images); + m_draw_fbo = vk::get_framebuffer(*m_device, fbo_width, fbo_height, vk::to_bool32(!input_attachments.empty()), m_cached_renderpass, m_fbo_images); m_draw_fbo->add_ref(); set_viewport(); diff --git a/rpcs3/Emu/RSX/VK/VKRenderPass.cpp b/rpcs3/Emu/RSX/VK/VKRenderPass.cpp index 9dc578ef66..b517054990 100644 --- a/rpcs3/Emu/RSX/VK/VKRenderPass.cpp +++ b/rpcs3/Emu/RSX/VK/VKRenderPass.cpp @@ -189,17 +189,23 @@ namespace vk return key.encoded; } - u64 get_renderpass_key(const std::vector& images, u64 previous_key) + u64 get_renderpass_key(const std::vector& images, u64 previous_key, const std::vector& input_attachment_ids) { // Partial update; assumes compatible renderpass keys renderpass_key_blob key(previous_key); key.layout_blob = 0; + key.input_attachments_mask = 0; for (u32 i = 0; i < ::size32(images); ++i) { key.set_layout(i, images[i]->current_layout); } + for (const auto& ref_id : input_attachment_ids) + { + key.set_input_attachment(ref_id); + } + return key.encoded; } @@ -348,6 +354,12 @@ namespace vk return result; } + bool renderpass_has_input_attachments(u64 renderpass_key) + { + renderpass_key_blob key(renderpass_key); + return key.input_attachments_mask != 0u; + } + void clear_renderpass_cache(VkDevice dev) { // Wipe current status diff --git a/rpcs3/Emu/RSX/VK/VKRenderPass.h b/rpcs3/Emu/RSX/VK/VKRenderPass.h index 5c23e749df..7b9494c934 100644 --- a/rpcs3/Emu/RSX/VK/VKRenderPass.h +++ b/rpcs3/Emu/RSX/VK/VKRenderPass.h @@ -9,11 +9,13 @@ namespace vk class command_buffer; u64 get_renderpass_key(const std::vector& images, const std::vector& input_attachment_ids = {}); - u64 get_renderpass_key(const std::vector& images, u64 previous_key); + u64 get_renderpass_key(const std::vector& images, u64 previous_key, const std::vector& input_attachment_ids = {}); u64 get_renderpass_key(VkFormat surface_format, u8 sample_count = 1); u64 get_renderpass_key(VkFormat color_format, VkFormat depth_format, u8 sample_count = 1); VkRenderPass get_renderpass(VkDevice dev, u64 renderpass_key); + bool renderpass_has_input_attachments(u64 renderpass_key); + void clear_renderpass_cache(VkDevice dev); // Renderpass scope management helpers. diff --git a/rpcs3/Emu/RSX/VK/VulkanAPI.h b/rpcs3/Emu/RSX/VK/VulkanAPI.h index ad40634659..57e366c2a9 100644 --- a/rpcs3/Emu/RSX/VK/VulkanAPI.h +++ b/rpcs3/Emu/RSX/VK/VulkanAPI.h @@ -59,4 +59,6 @@ constexpr VkStructureType VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_UNIFORM_BUFFE namespace vk { void init(); + + inline VkBool32 to_bool32(bool x) { return x ? VK_TRUE : VK_FALSE; } }