From f85881c18c338d3c8d47e6485ec106f785def287 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Mon, 31 May 2021 22:59:39 +0300 Subject: [PATCH] vk: Enable use of input attachments --- rpcs3/Emu/RSX/VK/VKFramebuffer.cpp | 28 +++- rpcs3/Emu/RSX/VK/VKFramebuffer.h | 4 +- rpcs3/Emu/RSX/VK/VKGSRender.cpp | 5 +- rpcs3/Emu/RSX/VK/VKOverlays.cpp | 94 +++++++---- rpcs3/Emu/RSX/VK/VKOverlays.h | 4 +- rpcs3/Emu/RSX/VK/VKPresent.cpp | 4 +- rpcs3/Emu/RSX/VK/VKRenderPass.cpp | 247 ++++++++++++++++++++--------- rpcs3/Emu/RSX/VK/VKRenderPass.h | 2 +- rpcs3/Emu/RSX/VK/VKRenderTargets.h | 2 +- 9 files changed, 273 insertions(+), 117 deletions(-) diff --git a/rpcs3/Emu/RSX/VK/VKFramebuffer.cpp b/rpcs3/Emu/RSX/VK/VKFramebuffer.cpp index aeb7bd17b4..e0bbad628a 100644 --- a/rpcs3/Emu/RSX/VK/VKFramebuffer.cpp +++ b/rpcs3/Emu/RSX/VK/VKFramebuffer.cpp @@ -10,10 +10,26 @@ namespace vk { std::unordered_map>> g_framebuffers_cache; - vk::framebuffer_holder* get_framebuffer(VkDevice dev, u16 width, u16 height, VkRenderPass renderpass, const std::vector& image_list) + union framebuffer_storage_key { - u64 key = u64(width) | (u64(height) << 16); - auto &queue = g_framebuffers_cache[key]; + u64 encoded; + + struct + { + u64 width : 16; // Width of FBO + u64 height : 16; // Height of FBO + u64 ia_ref : 1; // Input attachment references? + }; + + framebuffer_storage_key(u16 width_, u16 height_, VkBool32 has_input_attachments) + : width(width_), height(height_), ia_ref(has_input_attachments) + {} + }; + + vk::framebuffer_holder* get_framebuffer(VkDevice dev, u16 width, u16 height, VkBool32 has_input_attachments, VkRenderPass renderpass, const std::vector& image_list) + { + framebuffer_storage_key key(width, height, has_input_attachments); + auto &queue = g_framebuffers_cache[key.encoded]; for (auto &fbo : queue) { @@ -39,10 +55,10 @@ namespace vk return ret; } - vk::framebuffer_holder* get_framebuffer(VkDevice dev, u16 width, u16 height, VkRenderPass renderpass, VkFormat format, VkImage attachment) + vk::framebuffer_holder* get_framebuffer(VkDevice dev, u16 width, u16 height, VkBool32 has_input_attachments, VkRenderPass renderpass, VkFormat format, VkImage attachment) { - u64 key = u64(width) | (u64(height) << 16); - auto &queue = g_framebuffers_cache[key]; + framebuffer_storage_key key(width, height, has_input_attachments); + auto &queue = g_framebuffers_cache[key.encoded]; for (const auto &e : queue) { diff --git a/rpcs3/Emu/RSX/VK/VKFramebuffer.h b/rpcs3/Emu/RSX/VK/VKFramebuffer.h index 25cfbb7152..c00ba24768 100644 --- a/rpcs3/Emu/RSX/VK/VKFramebuffer.h +++ b/rpcs3/Emu/RSX/VK/VKFramebuffer.h @@ -9,8 +9,8 @@ namespace vk using framebuffer::framebuffer; }; - vk::framebuffer_holder* get_framebuffer(VkDevice dev, u16 width, u16 height, VkRenderPass renderpass, const std::vector& image_list); - vk::framebuffer_holder* get_framebuffer(VkDevice dev, u16 width, u16 height, VkRenderPass renderpass, VkFormat format, VkImage attachment); + vk::framebuffer_holder* get_framebuffer(VkDevice dev, u16 width, u16 height, VkBool32 has_input_attachments, VkRenderPass renderpass, const std::vector& image_list); + vk::framebuffer_holder* get_framebuffer(VkDevice dev, u16 width, u16 height, VkBool32 has_input_attachments, VkRenderPass renderpass, VkFormat format, VkImage attachment); void remove_unused_framebuffers(); void clear_framebuffer_cache(); diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index 2baf62906a..ae87008b19 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -1289,7 +1289,8 @@ void VKGSRender::clear_surface(u32 mask) if (!renderpass) { std::vector surfaces = { rtt }; - const auto key = vk::get_renderpass_key(surfaces); + std::vector input_attachments = { 0 }; + const auto key = vk::get_renderpass_key(surfaces, input_attachments); renderpass = vk::get_renderpass(*m_device, key); } @@ -2277,7 +2278,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, m_cached_renderpass, m_fbo_images); + m_draw_fbo = vk::get_framebuffer(*m_device, fbo_width, fbo_height, VK_FALSE, m_cached_renderpass, m_fbo_images); m_draw_fbo->add_ref(); set_viewport(); diff --git a/rpcs3/Emu/RSX/VK/VKOverlays.cpp b/rpcs3/Emu/RSX/VK/VKOverlays.cpp index 701cb9ba2c..3c717e5fbf 100644 --- a/rpcs3/Emu/RSX/VK/VKOverlays.cpp +++ b/rpcs3/Emu/RSX/VK/VKOverlays.cpp @@ -60,16 +60,26 @@ namespace vk void overlay_pass::init_descriptors() { - VkDescriptorPoolSize descriptor_pool_sizes[2] = + std::vector descriptor_pool_sizes = { - { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_OVERLAY_MAX_DRAW_CALLS * m_num_usable_samplers }, - { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_OVERLAY_MAX_DRAW_CALLS }, + { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_OVERLAY_MAX_DRAW_CALLS } }; - // Reserve descriptor pools - m_descriptor_pool.create(*m_device, descriptor_pool_sizes, 2, VK_OVERLAY_MAX_DRAW_CALLS, 2); + if (m_num_usable_samplers) + { + descriptor_pool_sizes.push_back({ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_OVERLAY_MAX_DRAW_CALLS * m_num_usable_samplers }); + } - std::vector bindings(1 + m_num_usable_samplers); + if (m_num_input_attachments) + { + descriptor_pool_sizes.push_back({ VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_OVERLAY_MAX_DRAW_CALLS * m_num_input_attachments }); + } + + // Reserve descriptor pools + m_descriptor_pool.create(*m_device, descriptor_pool_sizes.data(), ::size32(descriptor_pool_sizes), VK_OVERLAY_MAX_DRAW_CALLS, 2); + + const auto num_bindings = 1 + m_num_usable_samplers + m_num_input_attachments; + std::vector bindings(num_bindings); bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; bindings[0].descriptorCount = 1; @@ -77,19 +87,31 @@ namespace vk bindings[0].binding = 0; bindings[0].pImmutableSamplers = nullptr; - for (u32 n = 1; n <= m_num_usable_samplers; ++n) + u32 descriptor_index = 1; + for (u32 n = 0; n < m_num_usable_samplers; ++n, ++descriptor_index) { - bindings[n].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - bindings[n].descriptorCount = 1; - bindings[n].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - bindings[n].binding = n; - bindings[n].pImmutableSamplers = nullptr; + bindings[descriptor_index].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + bindings[descriptor_index].descriptorCount = 1; + bindings[descriptor_index].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + bindings[descriptor_index].binding = descriptor_index; + bindings[descriptor_index].pImmutableSamplers = nullptr; } + for (u32 n = 0; n < m_num_input_attachments; ++n, ++descriptor_index) + { + bindings[descriptor_index].descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; + bindings[descriptor_index].descriptorCount = 1; + bindings[descriptor_index].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + bindings[descriptor_index].binding = descriptor_index; + bindings[descriptor_index].pImmutableSamplers = nullptr; + } + + ensure(descriptor_index == num_bindings); + VkDescriptorSetLayoutCreateInfo infos = {}; infos.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; infos.pBindings = bindings.data(); - infos.bindingCount = 1 + m_num_usable_samplers; + infos.bindingCount = ::size32(bindings); CHECK_RESULT(vkCreateDescriptorSetLayout(*m_device, &infos, nullptr, &m_descriptor_layout)); @@ -119,9 +141,15 @@ namespace vk std::vector fs_inputs; fs_inputs.push_back({ ::glsl::program_domain::glsl_fragment_program, vk::glsl::program_input_type::input_type_uniform_buffer,{},{}, 0, "static_data" }); - for (u32 n = 1; n <= m_num_usable_samplers; ++n) + u32 binding = 1; + for (u32 n = 0; n < m_num_usable_samplers; ++n, ++binding) { - fs_inputs.push_back({ ::glsl::program_domain::glsl_fragment_program, vk::glsl::program_input_type::input_type_texture,{},{}, n, "fs" + std::to_string(n-1) }); + fs_inputs.push_back({ ::glsl::program_domain::glsl_fragment_program, vk::glsl::program_input_type::input_type_texture,{},{}, binding, "fs" + std::to_string(n) }); + } + + for (u32 n = 0; n < m_num_input_attachments; ++n, ++binding) + { + fs_inputs.push_back({ ::glsl::program_domain::glsl_fragment_program, vk::glsl::program_input_type::input_type_texture,{},{}, binding, "sp" + std::to_string(n) }); } return fs_inputs; @@ -222,7 +250,7 @@ namespace vk CHECK_RESULT(vkAllocateDescriptorSets(*m_device, &alloc_info, &m_descriptor_set)); m_used_descriptors++; - if (!m_sampler) + if (!m_sampler && !src.empty()) { m_sampler = std::make_unique(*m_device, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, @@ -290,7 +318,7 @@ namespace vk vk::framebuffer* overlay_pass::get_framebuffer(vk::image* target, VkRenderPass render_pass) { VkDevice dev = (*vk::get_current_renderer()); - return vk::get_framebuffer(dev, target->width(), target->height(), render_pass, { target }); + return vk::get_framebuffer(dev, target->width(), target->height(), m_num_input_attachments > 0, render_pass, { target }); } void overlay_pass::emit_geometry(vk::command_buffer& cmd) @@ -778,15 +806,12 @@ namespace vk "#version 450\n" "#extension GL_ARB_separate_shader_objects : enable\n" "layout(push_constant) uniform static_data{ vec4 regs[2]; };\n" - "layout(location=0) out vec2 tc0;\n" - "layout(location=1) out vec4 color;\n" - "layout(location=2) out vec4 mask;\n" + "layout(location=0) out vec4 color;\n" + "layout(location=1) out vec4 mask;\n" "\n" "void main()\n" "{\n" " vec2 positions[] = {vec2(-1., -1.), vec2(1., -1.), vec2(-1., 1.), vec2(1., 1.)};\n" - " vec2 coords[] = {vec2(0., 0.), vec2(1., 0.), vec2(0., 1.), vec2(1., 1.)};\n" - " tc0 = coords[gl_VertexIndex % 4];\n" " color = regs[0];\n" " mask = regs[1];\n" " gl_Position = vec4(positions[gl_VertexIndex % 4], 0., 1.);\n" @@ -795,18 +820,23 @@ namespace vk fs_src = "#version 420\n" "#extension GL_ARB_separate_shader_objects : enable\n" - "layout(set=0, binding=1) uniform sampler2D fs0;\n" - "layout(location=0) in vec2 tc0;\n" - "layout(location=1) in vec4 color;\n" - "layout(location=2) in vec4 mask;\n" + "layout(input_attachment_index=0, binding=1) uniform subpassInput sp0;\n" + "layout(location=0) in vec4 color;\n" + "layout(location=1) in vec4 mask;\n" "layout(location=0) out vec4 out_color;\n" "\n" "void main()\n" "{\n" - " vec4 original_color = texture(fs0, tc0);\n" + " vec4 original_color = subpassLoad(sp0);\n" " out_color = mix(original_color, color, bvec4(mask));\n" "}\n"; + // Disable samplers + m_num_usable_samplers = 0; + + // Enable subpass attachment 0 + m_num_input_attachments = 1; + renderpass_config.set_depth_mask(false); renderpass_config.set_color_mask(0, true, true, true, true); renderpass_config.set_attachment_count(1); @@ -822,7 +852,7 @@ namespace vk return { constant }; } - void attachment_clear_pass::update_uniforms(vk::command_buffer& cmd, vk::glsl::program* /*program*/) + void attachment_clear_pass::update_uniforms(vk::command_buffer& cmd, vk::glsl::program* program) { f32 data[8]; data[0] = clear_color.r; @@ -835,6 +865,9 @@ namespace vk data[7] = colormask.a; vkCmdPushConstants(cmd, m_pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, 0, 32, data); + + // Bind subpass attachment 0 + program->bind_uniform(input_attachment_info, "sp0", VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, m_descriptor_set); } void attachment_clear_pass::set_up_viewport(vk::command_buffer& cmd, u32 x, u32 y, u32 w, u32 h) @@ -872,13 +905,14 @@ namespace vk void attachment_clear_pass::run(vk::command_buffer& cmd, vk::render_target* target, VkRect2D rect, VkRenderPass render_pass) { region = rect; + input_attachment_info = { VK_NULL_HANDLE, target->get_view(0xAAE4, rsx::default_remap_vector)->value, target->current_layout }; + target->read_barrier(cmd); // Coverage sampling disabled, but actually report correct number of samples renderpass_config.set_multisample_state(target->samples(), 0xFFFF, false, false, false); - overlay_pass::run(cmd, { 0, 0, target->width(), target->height() }, target, - target->get_view(0xAAE4, rsx::default_remap_vector), render_pass); + overlay_pass::run(cmd, { 0, 0, target->width(), target->height() }, target, std::vector{}, render_pass); } stencil_clear_pass::stencil_clear_pass() diff --git a/rpcs3/Emu/RSX/VK/VKOverlays.h b/rpcs3/Emu/RSX/VK/VKOverlays.h index 97d357b10c..7d25a71c46 100644 --- a/rpcs3/Emu/RSX/VK/VKOverlays.h +++ b/rpcs3/Emu/RSX/VK/VKOverlays.h @@ -49,6 +49,7 @@ namespace vk VkFilter m_sampler_filter = VK_FILTER_LINEAR; u32 m_num_usable_samplers = 1; + u32 m_num_input_attachments = 0; std::unordered_map> m_program_cache; std::unique_ptr m_sampler; @@ -175,12 +176,13 @@ namespace vk color4f clear_color = { 0.f, 0.f, 0.f, 0.f }; color4f colormask = { 1.f, 1.f, 1.f, 1.f }; VkRect2D region = {}; + VkDescriptorImageInfo input_attachment_info = {}; attachment_clear_pass(); std::vector get_push_constants() override; - void update_uniforms(vk::command_buffer& cmd, vk::glsl::program* /*program*/) override; + void update_uniforms(vk::command_buffer& cmd, vk::glsl::program* program) override; void set_up_viewport(vk::command_buffer& cmd, u32 x, u32 y, u32 w, u32 h) override; diff --git a/rpcs3/Emu/RSX/VK/VKPresent.cpp b/rpcs3/Emu/RSX/VK/VKPresent.cpp index a5441d24d4..c3fffabe65 100644 --- a/rpcs3/Emu/RSX/VK/VKPresent.cpp +++ b/rpcs3/Emu/RSX/VK/VKPresent.cpp @@ -637,7 +637,7 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info) single_target_pass = vk::get_renderpass(*m_device, key); ensure(single_target_pass != VK_NULL_HANDLE); - direct_fbo = vk::get_framebuffer(*m_device, m_swapchain_dims.width, m_swapchain_dims.height, single_target_pass, m_swapchain->get_surface_format(), target_image); + direct_fbo = vk::get_framebuffer(*m_device, m_swapchain_dims.width, m_swapchain_dims.height, VK_FALSE, single_target_pass, m_swapchain->get_surface_format(), target_image); direct_fbo->add_ref(); image_to_flip->push_layout(*m_current_command_buffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); @@ -715,7 +715,7 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info) single_target_pass = vk::get_renderpass(*m_device, key); ensure(single_target_pass != VK_NULL_HANDLE); - direct_fbo = vk::get_framebuffer(*m_device, m_swapchain_dims.width, m_swapchain_dims.height, single_target_pass, m_swapchain->get_surface_format(), target_image); + direct_fbo = vk::get_framebuffer(*m_device, m_swapchain_dims.width, m_swapchain_dims.height, VK_FALSE, single_target_pass, m_swapchain->get_surface_format(), target_image); } direct_fbo->add_ref(); diff --git a/rpcs3/Emu/RSX/VK/VKRenderPass.cpp b/rpcs3/Emu/RSX/VK/VKRenderPass.cpp index 8581d300f8..240c0ec29a 100644 --- a/rpcs3/Emu/RSX/VK/VKRenderPass.cpp +++ b/rpcs3/Emu/RSX/VK/VKRenderPass.cpp @@ -19,77 +19,187 @@ namespace vk shared_mutex g_renderpass_cache_mutex; std::unordered_map g_renderpass_cache; - u64 get_renderpass_key(const std::vector& images) + // Key structure + // 0-7 color_format + // 8-15 depth_format + // 16-21 sample_counts + // 22-36 current layouts + // 37-41 input attachments + union renderpass_key_blob { - // Key structure - // 0-8 color_format - // 8-16 depth_format - // 16-21 sample_counts - // 21-37 current layouts - u64 key = 0; - u64 layout_offset = 22; - for (const auto &surface : images) + private: + // Internal utils + static u64 encode_layout(VkImageLayout layout) { - const auto format_code = u64(surface->format()) & 0xFF; - switch (format_code) + switch (layout) + { + case VK_IMAGE_LAYOUT_GENERAL: + case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: + return static_cast(layout); + default: + fmt::throw_exception("Unsupported layout 0x%llx here", static_cast(layout)); + } + } + + static VkImageLayout decode_layout(u64 encoded) + { + switch (encoded) + { + case 1: + case 2: + case 3: + return static_cast(encoded); + default: + fmt::throw_exception("Unsupported layout encoding 0x%llx here", encoded); + } + } + + public: + u64 encoded; + + struct + { + u64 color_format : 8; + u64 depth_format : 8; + u64 sample_count : 6; + u64 layout_blob : 15; + u64 input_attachments_mask : 5; + }; + + renderpass_key_blob(u64 encoded_) : encoded(encoded_) + {} + + // Encoders + inline void set_layout(u32 index, VkImageLayout layout) + { + switch (layout) + { + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: + case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: + case VK_IMAGE_LAYOUT_GENERAL: + layout_blob |= encode_layout(layout) << (index * 3); + break; + default: + fmt::throw_exception("Unsupported image layout 0x%x", static_cast(layout)); + } + } + + inline void set_input_attachment(u32 index) + { + input_attachments_mask |= (1ull << index); + } + + inline void set_format(VkFormat format) + { + switch (format) { case VK_FORMAT_D16_UNORM: case VK_FORMAT_D32_SFLOAT: case VK_FORMAT_D24_UNORM_S8_UINT: case VK_FORMAT_D32_SFLOAT_S8_UINT: - key |= (format_code << 8); + depth_format = static_cast(format); break; default: - key |= format_code; + color_format = static_cast(format); break; } - - switch (const auto layout = surface->current_layout) - { - case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: - case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: - case VK_IMAGE_LAYOUT_GENERAL: - key |= (u64(layout) << layout_offset); - layout_offset += 3; - break; - default: - fmt::throw_exception("Unsupported image layout 0x%x", static_cast(layout)); - } } - key |= u64(images[0]->samples()) << 16; - return key; + // Decoders + inline VkSampleCountFlagBits get_sample_count() const + { + return static_cast(sample_count); + } + + inline VkFormat get_color_format() const + { + return static_cast(color_format); + } + + inline VkFormat get_depth_format() const + { + return static_cast(depth_format); + } + + std::vector get_input_attachments() const + { + if (input_attachments_mask == 0) [[likely]] + { + return {}; + } + + std::vector result; + for (u32 i = 0; i < 5; ++i) + { + if (input_attachments_mask & (1ull << i)) + { + const auto layout = decode_layout((layout_blob >> (i * 3)) & 0x7); + result.push_back({i, layout}); + } + } + + return result; + } + + std::vector get_image_layouts() const + { + std::vector result; + + for (u32 i = 0, layout_offset = 0; i < 5; ++i, layout_offset += 3) + { + if (const auto layout = VkImageLayout((layout_blob >> layout_offset) & 0x7)) + { + result.push_back(layout); + } + else + { + break; + } + } + + return result; + } + }; + + u64 get_renderpass_key(const std::vector& images, const std::vector& input_attachment_ids) + { + renderpass_key_blob key(0); + + for (u32 i = 0; i < ::size32(images); ++i) + { + const auto& surface = images[i]; + key.set_format(surface->format()); + key.set_layout(i, surface->current_layout); + } + + for (const auto& ref_id : input_attachment_ids) + { + key.set_input_attachment(ref_id); + } + + key.sample_count = images[0]->samples(); + return key.encoded; } u64 get_renderpass_key(const std::vector& images, u64 previous_key) { // Partial update; assumes compatible renderpass keys - const u64 layout_mask = (0x7FFFull << 22); + renderpass_key_blob key(previous_key); + key.layout_blob = 0; - u64 key = previous_key & ~layout_mask; - u64 layout_offset = 22; - - for (const auto &surface : images) + for (u32 i = 0; i < ::size32(images); ++i) { - switch (const auto layout = surface->current_layout) - { - case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: - case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: - case VK_IMAGE_LAYOUT_GENERAL: - key |= (u64(layout) << layout_offset); - layout_offset += 3; - break; - default: - fmt::throw_exception("Unsupported image layout 0x%x", static_cast(layout)); - } + key.set_layout(i, images[i]->current_layout); } - return key; + return key.encoded; } u64 get_renderpass_key(VkFormat surface_format) { - u64 key = (1ull << 16); + renderpass_key_blob key(0); + key.sample_count = 1; switch (surface_format) { @@ -97,16 +207,16 @@ namespace vk case VK_FORMAT_D32_SFLOAT: case VK_FORMAT_D24_UNORM_S8_UINT: case VK_FORMAT_D32_SFLOAT_S8_UINT: - key |= (u64(surface_format) << 8); - key |= (u64(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) << 22); + key.depth_format = static_cast(surface_format); + key.layout_blob = static_cast(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); break; default: - key |= u64(surface_format); - key |= (u64(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) << 22); + key.color_format = static_cast(surface_format); + key.layout_blob = static_cast(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); break; } - return key; + return key.encoded; } VkRenderPass get_renderpass(VkDevice dev, u64 renderpass_key) @@ -132,38 +242,24 @@ namespace vk } // Decode - VkSampleCountFlagBits samples = VkSampleCountFlagBits((renderpass_key >> 16) & 0xF); + renderpass_key_blob key(renderpass_key); + VkSampleCountFlagBits samples = static_cast(key.sample_count); std::vector rtv_layouts; VkImageLayout dsv_layout; - u64 layout_offset = 22; - for (int n = 0; n < 5; ++n) - { - const VkImageLayout layout = VkImageLayout((renderpass_key >> layout_offset) & 0x7); - layout_offset += 3; + VkFormat color_format = static_cast(key.color_format); + VkFormat depth_format = static_cast(key.depth_format); - if (layout) - { - rtv_layouts.push_back(layout); - } - else - { - break; - } - } - - VkFormat color_format = VkFormat(renderpass_key & 0xFF); - VkFormat depth_format = VkFormat((renderpass_key >> 8) & 0xFF); + std::vector attachments = {}; + std::vector attachment_references; + rtv_layouts = key.get_image_layouts(); if (depth_format) { dsv_layout = rtv_layouts.back(); rtv_layouts.pop_back(); } - std::vector attachments = {}; - std::vector attachment_references; - u32 attachment_count = 0; for (const auto &layout : rtv_layouts) { @@ -203,9 +299,16 @@ namespace vk subpass.pColorAttachments = attachment_count? attachment_references.data() : nullptr; subpass.pDepthStencilAttachment = depth_format? &attachment_references.back() : nullptr; + const auto input_attachments = key.get_input_attachments(); + if (!input_attachments.empty()) + { + subpass.inputAttachmentCount = ::size32(input_attachments); + subpass.pInputAttachments = input_attachments.data(); + } + VkRenderPassCreateInfo rp_info = {}; rp_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - rp_info.attachmentCount = static_cast(attachments.size()); + rp_info.attachmentCount = ::size32(attachments); rp_info.pAttachments = attachments.data(); rp_info.subpassCount = 1; rp_info.pSubpasses = &subpass; diff --git a/rpcs3/Emu/RSX/VK/VKRenderPass.h b/rpcs3/Emu/RSX/VK/VKRenderPass.h index e6268c92ff..0753a3fb0e 100644 --- a/rpcs3/Emu/RSX/VK/VKRenderPass.h +++ b/rpcs3/Emu/RSX/VK/VKRenderPass.h @@ -7,7 +7,7 @@ namespace vk { class image; - u64 get_renderpass_key(const std::vector& images); + 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(VkFormat surface_format); VkRenderPass get_renderpass(VkDevice dev, u64 renderpass_key); diff --git a/rpcs3/Emu/RSX/VK/VKRenderTargets.h b/rpcs3/Emu/RSX/VK/VKRenderTargets.h index c82c5d390e..a0cf6f05aa 100644 --- a/rpcs3/Emu/RSX/VK/VKRenderTargets.h +++ b/rpcs3/Emu/RSX/VK/VKRenderTargets.h @@ -98,7 +98,7 @@ namespace rsx sample_layout = surface_sample_layout::null; } - VkImageUsageFlags usage_flags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + VkImageUsageFlags usage_flags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; if (samples == 1) [[likely]] { usage_flags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;