From 4752c4014b6519fae59c0d9ea85e636a59e37291 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Thu, 23 Sep 2021 01:29:23 +0300 Subject: [PATCH] vk: Implement basic descriptor updates batching --- rpcs3/Emu/RSX/VK/VKCompute.cpp | 4 +- rpcs3/Emu/RSX/VK/VKCompute.h | 2 +- rpcs3/Emu/RSX/VK/VKDraw.cpp | 18 ++- rpcs3/Emu/RSX/VK/VKGSRender.h | 4 +- rpcs3/Emu/RSX/VK/VKOverlays.cpp | 4 +- rpcs3/Emu/RSX/VK/VKOverlays.h | 2 +- rpcs3/Emu/RSX/VK/VKProgramPipeline.cpp | 33 +++--- rpcs3/Emu/RSX/VK/VKProgramPipeline.h | 17 ++- rpcs3/Emu/RSX/VK/VKShaderInterpreter.cpp | 6 +- rpcs3/Emu/RSX/VK/VKShaderInterpreter.h | 2 +- rpcs3/Emu/RSX/VK/VKTextOut.h | 6 +- rpcs3/Emu/RSX/VK/vkutils/descriptors.cpp | 139 +++++++++++++++++++++++ rpcs3/Emu/RSX/VK/vkutils/descriptors.h | 56 ++++++++- 13 files changed, 237 insertions(+), 56 deletions(-) diff --git a/rpcs3/Emu/RSX/VK/VKCompute.cpp b/rpcs3/Emu/RSX/VK/VKCompute.cpp index 51e0fc1154..d5a4065a8f 100644 --- a/rpcs3/Emu/RSX/VK/VKCompute.cpp +++ b/rpcs3/Emu/RSX/VK/VKCompute.cpp @@ -162,13 +162,13 @@ namespace vk alloc_info.pSetLayouts = &m_descriptor_layout; alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - CHECK_RESULT(vkAllocateDescriptorSets(*g_render_device, &alloc_info, &m_descriptor_set)); + CHECK_RESULT(vkAllocateDescriptorSets(*g_render_device, &alloc_info, m_descriptor_set.ptr())); m_used_descriptors++; bind_resources(); vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, m_program->pipeline); - vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, m_pipeline_layout, 0, 1, &m_descriptor_set, 0, nullptr); + m_descriptor_set.bind(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, m_pipeline_layout); } void compute_task::run(VkCommandBuffer cmd, u32 invocations_x, u32 invocations_y, u32 invocations_z) diff --git a/rpcs3/Emu/RSX/VK/VKCompute.h b/rpcs3/Emu/RSX/VK/VKCompute.h index 3bda14980d..30f15c5cf1 100644 --- a/rpcs3/Emu/RSX/VK/VKCompute.h +++ b/rpcs3/Emu/RSX/VK/VKCompute.h @@ -20,7 +20,7 @@ namespace vk std::unique_ptr m_param_buffer; vk::descriptor_pool m_descriptor_pool; - VkDescriptorSet m_descriptor_set = nullptr; + descriptor_set m_descriptor_set; VkDescriptorSetLayout m_descriptor_layout = nullptr; VkPipelineLayout m_pipeline_layout = nullptr; u32 m_used_descriptors = 0; diff --git a/rpcs3/Emu/RSX/VK/VKDraw.cpp b/rpcs3/Emu/RSX/VK/VKDraw.cpp index 6d42f79c88..19e9f5538a 100644 --- a/rpcs3/Emu/RSX/VK/VKDraw.cpp +++ b/rpcs3/Emu/RSX/VK/VKDraw.cpp @@ -791,28 +791,27 @@ void VKGSRender::emit_geometry(u32 sub_index) else if (persistent_buffer != old_persistent_buffer || volatile_buffer != old_volatile_buffer) { // Need to update descriptors; make a copy for the next draw - VkDescriptorSet new_descriptor_set = allocate_descriptor_set(); - std::vector copy_set(binding_table.total_descriptor_bindings); + VkDescriptorSet previous_set = m_current_frame->descriptor_set.value(); + m_current_frame->descriptor_set = allocate_descriptor_set(); + std::vector copy_cmds(binding_table.total_descriptor_bindings); for (u32 n = 0; n < binding_table.total_descriptor_bindings; ++n) { - copy_set[n] = + copy_cmds[n] = { VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET, // sType nullptr, // pNext - m_current_frame->descriptor_set, // srcSet + previous_set, // srcSet n, // srcBinding 0u, // srcArrayElement - new_descriptor_set, // dstSet + m_current_frame->descriptor_set.value(), // dstSet n, // dstBinding 0u, // dstArrayElement 1u // descriptorCount }; } - vkUpdateDescriptorSets(*m_device, 0, 0, binding_table.total_descriptor_bindings, copy_set.data()); - m_current_frame->descriptor_set = new_descriptor_set; - + m_current_frame->descriptor_set.push(copy_cmds); update_descriptors = true; } @@ -866,8 +865,7 @@ void VKGSRender::emit_geometry(u32 sub_index) } // Bind the new set of descriptors for use with this draw call - vkCmdBindDescriptorSets(*m_current_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_program->pipeline_layout, 0, 1, &m_current_frame->descriptor_set, 0, nullptr); - + m_current_frame->descriptor_set.bind(*m_current_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_program->pipeline_layout); m_frame_stats.setup_time += m_profiler.duration(); if (!upload_info.index_info) diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.h b/rpcs3/Emu/RSX/VK/VKGSRender.h index 6348ffdd7b..63a6f1dedf 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.h +++ b/rpcs3/Emu/RSX/VK/VKGSRender.h @@ -196,8 +196,8 @@ namespace vk { VkSemaphore acquire_signal_semaphore = VK_NULL_HANDLE; VkSemaphore present_wait_semaphore = VK_NULL_HANDLE; - VkDescriptorSet descriptor_set = VK_NULL_HANDLE; + vk::descriptor_set descriptor_set; vk::descriptor_pool descriptor_pool; u32 used_descriptors = 0; @@ -227,7 +227,7 @@ namespace vk { present_wait_semaphore = other.present_wait_semaphore; acquire_signal_semaphore = other.acquire_signal_semaphore; - descriptor_set = other.descriptor_set; + descriptor_set.swap(other.descriptor_set); descriptor_pool = other.descriptor_pool; used_descriptors = other.used_descriptors; flags = other.flags; diff --git a/rpcs3/Emu/RSX/VK/VKOverlays.cpp b/rpcs3/Emu/RSX/VK/VKOverlays.cpp index 2783ba68b6..9c754db01a 100644 --- a/rpcs3/Emu/RSX/VK/VKOverlays.cpp +++ b/rpcs3/Emu/RSX/VK/VKOverlays.cpp @@ -235,7 +235,7 @@ namespace vk alloc_info.pSetLayouts = &m_descriptor_layout; alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - CHECK_RESULT(vkAllocateDescriptorSets(*m_device, &alloc_info, &m_descriptor_set)); + CHECK_RESULT(vkAllocateDescriptorSets(*m_device, &alloc_info, m_descriptor_set.ptr())); m_used_descriptors++; if (!m_sampler && !src.empty()) @@ -256,7 +256,7 @@ namespace vk } vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, program->pipeline); - vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline_layout, 0, 1, &m_descriptor_set, 0, nullptr); + m_descriptor_set.bind(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline_layout); VkBuffer buffers = m_vao.heap->value; VkDeviceSize offsets = m_vao_offset; diff --git a/rpcs3/Emu/RSX/VK/VKOverlays.h b/rpcs3/Emu/RSX/VK/VKOverlays.h index 80756cf9d4..811f519f96 100644 --- a/rpcs3/Emu/RSX/VK/VKOverlays.h +++ b/rpcs3/Emu/RSX/VK/VKOverlays.h @@ -44,7 +44,7 @@ namespace vk vk::glsl::shader m_fragment_shader; vk::descriptor_pool m_descriptor_pool; - VkDescriptorSet m_descriptor_set = nullptr; + descriptor_set m_descriptor_set; VkDescriptorSetLayout m_descriptor_layout = nullptr; VkPipelineLayout m_pipeline_layout = nullptr; u32 m_used_descriptors = 0; diff --git a/rpcs3/Emu/RSX/VK/VKProgramPipeline.cpp b/rpcs3/Emu/RSX/VK/VKProgramPipeline.cpp index 38afcec690..886c28015a 100644 --- a/rpcs3/Emu/RSX/VK/VKProgramPipeline.cpp +++ b/rpcs3/Emu/RSX/VK/VKProgramPipeline.cpp @@ -1,5 +1,6 @@ #include "stdafx.h" #include "VKProgramPipeline.h" +#include "vkutils/descriptors.h" #include "vkutils/device.h" #include @@ -158,7 +159,7 @@ namespace vk }); } - void program::bind_uniform(const VkDescriptorImageInfo &image_descriptor, const std::string& uniform_name, VkDescriptorType type, VkDescriptorSet &descriptor_set) + void program::bind_uniform(const VkDescriptorImageInfo &image_descriptor, const std::string& uniform_name, VkDescriptorType type, vk::descriptor_set &set) { for (const auto &uniform : uniforms[program_input_type::input_type_texture]) { @@ -168,7 +169,7 @@ namespace vk { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // sType nullptr, // pNext - descriptor_set, // dstSet + VK_NULL_HANDLE, // dstSet uniform.location, // dstBinding 0, // dstArrayElement 1, // descriptorCount @@ -178,7 +179,7 @@ namespace vk nullptr // pTexelBufferView }; - vkUpdateDescriptorSets(m_device, 1, &descriptor_writer, 0, nullptr); + set.push(descriptor_writer); attribute_location_mask |= (1ull << uniform.location); return; } @@ -187,7 +188,7 @@ namespace vk rsx_log.notice("texture not found in program: %s", uniform_name.c_str()); } - void program::bind_uniform(const VkDescriptorImageInfo & image_descriptor, int texture_unit, ::glsl::program_domain domain, VkDescriptorSet &descriptor_set, bool is_stencil_mirror) + void program::bind_uniform(const VkDescriptorImageInfo & image_descriptor, int texture_unit, ::glsl::program_domain domain, vk::descriptor_set &set, bool is_stencil_mirror) { ensure(domain != ::glsl::program_domain::glsl_compute_program); @@ -207,7 +208,7 @@ namespace vk { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // sType nullptr, // pNext - descriptor_set, // dstSet + VK_NULL_HANDLE, // dstSet binding, // dstBinding 0, // dstArrayElement 1, // descriptorCount @@ -217,7 +218,7 @@ namespace vk nullptr // pTexelBufferView }; - vkUpdateDescriptorSets(m_device, 1, &descriptor_writer, 0, nullptr); + set.push(descriptor_writer); attribute_location_mask |= (1ull << binding); return; } @@ -225,18 +226,18 @@ namespace vk rsx_log.notice("texture not found in program: %stex%u", (domain == ::glsl::program_domain::glsl_vertex_program)? "v" : "", texture_unit); } - void program::bind_uniform(const VkDescriptorBufferInfo &buffer_descriptor, u32 binding_point, VkDescriptorSet &descriptor_set) + void program::bind_uniform(const VkDescriptorBufferInfo &buffer_descriptor, u32 binding_point, vk::descriptor_set &set) { - bind_buffer(buffer_descriptor, binding_point, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, descriptor_set); + bind_buffer(buffer_descriptor, binding_point, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, set); } - void program::bind_uniform(const VkBufferView &buffer_view, u32 binding_point, VkDescriptorSet &descriptor_set) + void program::bind_uniform(const VkBufferView &buffer_view, u32 binding_point, vk::descriptor_set &set) { const VkWriteDescriptorSet descriptor_writer = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // sType nullptr, // pNext - descriptor_set, // dstSet + VK_NULL_HANDLE, // dstSet binding_point, // dstBinding 0, // dstArrayElement 1, // descriptorCount @@ -246,17 +247,17 @@ namespace vk &buffer_view // pTexelBufferView }; - vkUpdateDescriptorSets(m_device, 1, &descriptor_writer, 0, nullptr); + set.push(descriptor_writer); attribute_location_mask |= (1ull << binding_point); } - void program::bind_uniform(const VkBufferView &buffer_view, program_input_type type, const std::string &binding_name, VkDescriptorSet &descriptor_set) + void program::bind_uniform(const VkBufferView &buffer_view, program_input_type type, const std::string &binding_name, vk::descriptor_set &set) { for (const auto &uniform : uniforms[type]) { if (uniform.name == binding_name) { - bind_uniform(buffer_view, uniform.location, descriptor_set); + bind_uniform(buffer_view, uniform.location, set); return; } } @@ -264,13 +265,13 @@ namespace vk rsx_log.notice("vertex buffer not found in program: %s", binding_name.c_str()); } - void program::bind_buffer(const VkDescriptorBufferInfo &buffer_descriptor, u32 binding_point, VkDescriptorType type, VkDescriptorSet &descriptor_set) + void program::bind_buffer(const VkDescriptorBufferInfo &buffer_descriptor, u32 binding_point, VkDescriptorType type, vk::descriptor_set &set) { const VkWriteDescriptorSet descriptor_writer = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // sType nullptr, // pNext - descriptor_set, // dstSet + VK_NULL_HANDLE, // dstSet binding_point, // dstBinding 0, // dstArrayElement 1, // descriptorCount @@ -280,7 +281,7 @@ namespace vk nullptr // pTexelBufferView }; - vkUpdateDescriptorSets(m_device, 1, &descriptor_writer, 0, nullptr); + set.push(descriptor_writer); attribute_location_mask |= (1ull << binding_point); } } diff --git a/rpcs3/Emu/RSX/VK/VKProgramPipeline.h b/rpcs3/Emu/RSX/VK/VKProgramPipeline.h index f6d8d94738..4b7cdd9092 100644 --- a/rpcs3/Emu/RSX/VK/VKProgramPipeline.h +++ b/rpcs3/Emu/RSX/VK/VKProgramPipeline.h @@ -2,7 +2,8 @@ #include "VulkanAPI.h" #include "VKCommonDecompiler.h" -#include "../Program/GLSLTypes.h" + +#include "vkutils/descriptors.h" #include #include @@ -99,14 +100,12 @@ namespace vk program& link(); bool has_uniform(program_input_type type, const std::string &uniform_name); - void bind_uniform(const VkDescriptorImageInfo &image_descriptor, const std::string &uniform_name, VkDescriptorType type, VkDescriptorSet &descriptor_set); - void bind_uniform(const VkDescriptorImageInfo &image_descriptor, int texture_unit, ::glsl::program_domain domain, VkDescriptorSet &descriptor_set, bool is_stencil_mirror = false); - void bind_uniform(const VkDescriptorBufferInfo &buffer_descriptor, u32 binding_point, VkDescriptorSet &descriptor_set); - void bind_uniform(const VkBufferView &buffer_view, u32 binding_point, VkDescriptorSet &descriptor_set); - void bind_uniform(const VkBufferView &buffer_view, program_input_type type, const std::string &binding_name, VkDescriptorSet &descriptor_set); - - void bind_buffer(const VkDescriptorBufferInfo &buffer_descriptor, u32 binding_point, VkDescriptorType type, VkDescriptorSet &descriptor_set); - void bind_descriptor_set(const VkCommandBuffer cmd, VkDescriptorSet descriptor_set); + void bind_uniform(const VkDescriptorImageInfo &image_descriptor, const std::string &uniform_name, VkDescriptorType type, vk::descriptor_set &set); + void bind_uniform(const VkDescriptorImageInfo &image_descriptor, int texture_unit, ::glsl::program_domain domain, vk::descriptor_set &set, bool is_stencil_mirror = false); + void bind_uniform(const VkDescriptorBufferInfo &buffer_descriptor, u32 binding_point, vk::descriptor_set &set); + void bind_uniform(const VkBufferView &buffer_view, u32 binding_point, vk::descriptor_set &set); + void bind_uniform(const VkBufferView &buffer_view, program_input_type type, const std::string &binding_name, vk::descriptor_set &set); + void bind_buffer(const VkDescriptorBufferInfo &buffer_descriptor, u32 binding_point, VkDescriptorType type, vk::descriptor_set &set); }; } } diff --git a/rpcs3/Emu/RSX/VK/VKShaderInterpreter.cpp b/rpcs3/Emu/RSX/VK/VKShaderInterpreter.cpp index f39aca242a..a6a33c1ed9 100644 --- a/rpcs3/Emu/RSX/VK/VKShaderInterpreter.cpp +++ b/rpcs3/Emu/RSX/VK/VKShaderInterpreter.cpp @@ -508,7 +508,7 @@ namespace vk return program.release(); } - void shader_interpreter::update_fragment_textures(const std::array& sampled_images, VkDescriptorSet descriptor_set) + void shader_interpreter::update_fragment_textures(const std::array& sampled_images, vk::descriptor_set &set) { const VkDescriptorImageInfo* texture_ptr = sampled_images.data(); for (u32 i = 0, binding = m_fragment_textures_start; i < 4; ++i, ++binding, texture_ptr += 16) @@ -517,7 +517,7 @@ namespace vk { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // sType nullptr, // pNext - descriptor_set, // dstSet + VK_NULL_HANDLE, // dstSet binding, // dstBinding 0, // dstArrayElement 16, // descriptorCount @@ -527,7 +527,7 @@ namespace vk nullptr // pTexelBufferView }; - vkUpdateDescriptorSets(m_device, 1, &descriptor_writer, 0, nullptr); + set.push(descriptor_writer); } } diff --git a/rpcs3/Emu/RSX/VK/VKShaderInterpreter.h b/rpcs3/Emu/RSX/VK/VKShaderInterpreter.h index db41c762db..ab676d8ebf 100644 --- a/rpcs3/Emu/RSX/VK/VKShaderInterpreter.h +++ b/rpcs3/Emu/RSX/VK/VKShaderInterpreter.h @@ -67,7 +67,7 @@ namespace vk u32 get_vertex_instruction_location() const; u32 get_fragment_instruction_location() const; - void update_fragment_textures(const std::array& sampled_images, VkDescriptorSet descriptor_set); + void update_fragment_textures(const std::array& sampled_images, vk::descriptor_set &set); VkDescriptorSet allocate_descriptor_set(); }; } diff --git a/rpcs3/Emu/RSX/VK/VKTextOut.h b/rpcs3/Emu/RSX/VK/VKTextOut.h index 09aef0e1f4..26d2b62a60 100644 --- a/rpcs3/Emu/RSX/VK/VKTextOut.h +++ b/rpcs3/Emu/RSX/VK/VKTextOut.h @@ -22,7 +22,7 @@ namespace vk vk::glsl::shader m_fragment_shader; vk::descriptor_pool m_descriptor_pool; - VkDescriptorSet m_descriptor_set = nullptr; + vk::descriptor_set m_descriptor_set; VkDescriptorSetLayout m_descriptor_layout = nullptr; VkPipelineLayout m_pipeline_layout = nullptr; u32 m_used_descriptors = 0; @@ -213,7 +213,7 @@ namespace vk alloc_info.pSetLayouts = &m_descriptor_layout; alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - CHECK_RESULT(vkAllocateDescriptorSets(device, &alloc_info, &m_descriptor_set)); + CHECK_RESULT(vkAllocateDescriptorSets(device, &alloc_info, m_descriptor_set.ptr())); m_used_descriptors++; float scale[] = { scale_x, scale_y }; @@ -236,7 +236,7 @@ namespace vk m_uniform_buffer_offset = (m_uniform_buffer_offset + 8192) % m_uniform_buffer_size; vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, m_program->pipeline); - vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline_layout, 0, 1, &m_descriptor_set, 0, nullptr); + m_descriptor_set.bind(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline_layout); VkDeviceSize zero = 0; vkCmdBindVertexBuffers(cmd, 0, 1, &m_vertex_buffer->value, &zero); diff --git a/rpcs3/Emu/RSX/VK/vkutils/descriptors.cpp b/rpcs3/Emu/RSX/VK/vkutils/descriptors.cpp index aa46ba7cf1..bf5c26bd09 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/descriptors.cpp +++ b/rpcs3/Emu/RSX/VK/vkutils/descriptors.cpp @@ -53,4 +53,143 @@ namespace vk m_current_pool_handle = m_device_pools[m_current_pool_index]; CHECK_RESULT(vkResetDescriptorPool(*m_owner, m_current_pool_handle, flags)); } + + descriptor_set::descriptor_set(VkDescriptorSet set) + { + flush(); + init(); + m_handle = set; + } + + descriptor_set::descriptor_set() + { + init(); + } + + void descriptor_set::init() + { + if (m_image_info_pool.capacity() == 0) + { + m_image_info_pool.reserve(max_cache_size + 16); + m_buffer_view_pool.reserve(max_cache_size + 16); + m_buffer_info_pool.reserve(max_cache_size + 16); + } + } + + VkBufferView* descriptor_set::dup(const VkBufferView* in) + { + if (!in) return nullptr; + + m_buffer_view_pool.push_back(*in); + return &m_buffer_view_pool.back(); + } + + VkDescriptorBufferInfo* descriptor_set::dup(const VkDescriptorBufferInfo* in) + { + if (!in) return nullptr; + + m_buffer_info_pool.push_back(*in); + return &m_buffer_info_pool.back(); + } + + VkDescriptorImageInfo* descriptor_set::dup(const VkDescriptorImageInfo* in) + { + if (!in) return nullptr; + + m_image_info_pool.push_back(*in); + return &m_image_info_pool.back(); + } + + void descriptor_set::swap(descriptor_set& other) + { + other.flush(); + flush(); + + std::swap(m_handle, other.m_handle); + } + + descriptor_set& descriptor_set::operator = (VkDescriptorSet set) + { + flush(); + m_handle = set; + return *this; + } + + VkDescriptorSet* descriptor_set::ptr() + { + // TODO: You shouldn't need this + // ensure(m_handle == VK_NULL_HANDLE); + return &m_handle; + } + + VkDescriptorSet descriptor_set::value() const + { + return m_handle; + } + + void descriptor_set::push(const VkWriteDescriptorSet& write_cmd) + { + if (m_pending_writes.size() >= max_cache_size) + { + flush(); + } + + m_pending_writes.push_back( + { + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .pNext = nullptr, + .dstSet = m_handle, + .dstBinding = write_cmd.dstBinding, + .dstArrayElement = write_cmd.dstArrayElement, + .descriptorCount = write_cmd.descriptorCount, + .descriptorType = write_cmd.descriptorType, + .pImageInfo = dup(write_cmd.pImageInfo), + .pBufferInfo = dup(write_cmd.pBufferInfo), + .pTexelBufferView = dup(write_cmd.pTexelBufferView) + }); + } + + void descriptor_set::push(std::vector& copy_cmd) + { + if (m_pending_copies.empty()) [[likely]] + { + m_pending_copies = std::move(copy_cmd); + } + else + { + const size_t old_size = m_pending_copies.size(); + const size_t new_size = copy_cmd.size() + old_size; + m_pending_copies.resize(new_size); + std::copy(copy_cmd.begin(), copy_cmd.end(), m_pending_copies.begin() + old_size); + } + } + + void descriptor_set::bind(VkCommandBuffer cmd, VkPipelineBindPoint bind_point, VkPipelineLayout layout) + { + flush(); + vkCmdBindDescriptorSets(cmd, bind_point, layout, 0, 1, &m_handle, 0, nullptr); + } + + void descriptor_set::bind(const command_buffer& cmd, VkPipelineBindPoint bind_point, VkPipelineLayout layout) + { + bind(static_cast(cmd), bind_point, layout); + } + + void descriptor_set::flush() + { + if (m_pending_writes.empty() && m_pending_copies.empty()) + { + return; + } + + const auto num_writes = ::size32(m_pending_writes); + const auto num_copies = ::size32(m_pending_copies); + vkUpdateDescriptorSets(*g_render_device, num_writes, m_pending_writes.data(), num_copies, m_pending_copies.data()); + + m_pending_writes.clear(); + m_pending_copies.clear(); + m_image_info_pool.clear(); + m_buffer_info_pool.clear(); + m_buffer_view_pool.clear(); + } } diff --git a/rpcs3/Emu/RSX/VK/vkutils/descriptors.h b/rpcs3/Emu/RSX/VK/vkutils/descriptors.h index cec06a55b5..4f067cafe6 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/descriptors.h +++ b/rpcs3/Emu/RSX/VK/vkutils/descriptors.h @@ -1,6 +1,7 @@ #pragma once #include "../VulkanAPI.h" +#include "commands.h" #include "device.h" #include @@ -9,12 +10,6 @@ namespace vk { class descriptor_pool { - const vk::render_device* m_owner = nullptr; - - std::vector m_device_pools; - VkDescriptorPool m_current_pool_handle = VK_NULL_HANDLE; - u32 m_current_pool_index = 0; - public: descriptor_pool() = default; ~descriptor_pool() = default; @@ -25,5 +20,54 @@ namespace vk bool valid() const; operator VkDescriptorPool(); + + private: + const vk::render_device* m_owner = nullptr; + + std::vector m_device_pools; + VkDescriptorPool m_current_pool_handle = VK_NULL_HANDLE; + u32 m_current_pool_index = 0; }; + + class descriptor_set + { + const size_t max_cache_size = 16384; + + VkBufferView* dup(const VkBufferView* in); + VkDescriptorBufferInfo* dup(const VkDescriptorBufferInfo* in); + VkDescriptorImageInfo* dup(const VkDescriptorImageInfo* in); + + void flush(); + void init(); + + public: + descriptor_set(VkDescriptorSet set); + descriptor_set(); + ~descriptor_set() = default; + + descriptor_set(const descriptor_set&) = delete; + + void swap(descriptor_set& other); + descriptor_set& operator = (VkDescriptorSet set); + + VkDescriptorSet* ptr(); + VkDescriptorSet value() const; + void push(const VkWriteDescriptorSet& write_cmd); + void push(std::vector& copy_cmd); + + void bind(VkCommandBuffer cmd, VkPipelineBindPoint bind_point, VkPipelineLayout layout); + void bind(const command_buffer& cmd, VkPipelineBindPoint bind_point, VkPipelineLayout layout); + + private: + VkDescriptorSet m_handle = VK_NULL_HANDLE; + + std::vector m_buffer_view_pool; + std::vector m_buffer_info_pool; + std::vector m_image_info_pool; + + std::vector m_pending_writes; + std::vector m_pending_copies; + }; + + void flush_descriptor_updates(); }