diff --git a/rpcs3/Emu/RSX/VK/vkutils/descriptors.cpp b/rpcs3/Emu/RSX/VK/vkutils/descriptors.cpp index 34a9f5c706..27b70d3932 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/descriptors.cpp +++ b/rpcs3/Emu/RSX/VK/vkutils/descriptors.cpp @@ -56,11 +56,24 @@ namespace vk infos.bindingCount = ::size32(bindings); VkDescriptorSetLayoutBindingFlagsCreateInfo binding_infos = {}; - std::vector binding_flags; + rsx::simple_array binding_flags; if (g_render_device->get_descriptor_indexing_support()) { - binding_flags.resize(bindings.size(), VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT); + const auto deferred_mask = g_render_device->get_descriptor_update_after_bind_support(); + binding_flags.resize(::size32(bindings)); + + for (u32 i = 0; i < binding_flags.size(); ++i) + { + if ((1ull << bindings[i].descriptorType) & ~deferred_mask) + { + binding_flags[i] = 0u; + } + else + { + binding_flags[i] = VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT; + } + } binding_infos.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT; binding_infos.pNext = nullptr; @@ -197,19 +210,19 @@ namespace vk { if (!m_in_use) [[unlikely]] { - 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); + m_image_info_pool.reserve(m_pool_size); + m_buffer_view_pool.reserve(m_pool_size); + m_buffer_info_pool.reserve(m_pool_size); m_in_use = true; - m_update_after_bind = g_render_device->get_descriptor_indexing_support(); + m_update_after_bind_mask = g_render_device->get_descriptor_update_after_bind_support(); - if (m_update_after_bind) + if (m_update_after_bind_mask) { g_fxo->get().notify(this); } } - else if (!m_update_after_bind) + else if (m_push_type_mask & ~m_update_after_bind_mask) { flush(); } @@ -233,6 +246,11 @@ namespace vk VkDescriptorSet* descriptor_set::ptr() { + if (!m_in_use) [[likely]] + { + init(m_handle); + } + return &m_handle; } @@ -243,11 +261,7 @@ namespace vk void descriptor_set::push(const VkBufferView& buffer_view, VkDescriptorType type, u32 binding) { - if (m_pending_writes.size() > max_cache_size) - { - flush(); - } - + m_push_type_mask |= (1ull << type); m_buffer_view_pool.push_back(buffer_view); m_pending_writes.push_back( { @@ -266,11 +280,7 @@ namespace vk void descriptor_set::push(const VkDescriptorBufferInfo& buffer_info, VkDescriptorType type, u32 binding) { - if (m_pending_writes.size() > max_cache_size) - { - flush(); - } - + m_push_type_mask |= (1ull << type); m_buffer_info_pool.push_back(buffer_info); m_pending_writes.push_back( { @@ -289,11 +299,7 @@ namespace vk void descriptor_set::push(const VkDescriptorImageInfo& image_info, VkDescriptorType type, u32 binding) { - if (m_pending_writes.size() >= max_cache_size) - { - flush(); - } - + m_push_type_mask |= (1ull << type); m_image_info_pool.push_back(image_info); m_pending_writes.push_back( { @@ -336,8 +342,8 @@ namespace vk } else { - const size_t old_size = m_pending_copies.size(); - const size_t new_size = copy_cmd.size() + old_size; + const auto old_size = m_pending_copies.size(); + const auto 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); } @@ -345,7 +351,7 @@ namespace vk void descriptor_set::bind(VkCommandBuffer cmd, VkPipelineBindPoint bind_point, VkPipelineLayout layout) { - if (!m_update_after_bind) + if ((m_push_type_mask & ~m_update_after_bind_mask) || (m_pending_writes.size() >= max_cache_size)) { flush(); } @@ -360,7 +366,7 @@ namespace vk void descriptor_set::flush() { - if (m_pending_writes.empty() && m_pending_copies.empty()) + if (!m_push_type_mask) { return; } @@ -369,6 +375,7 @@ namespace vk 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_push_type_mask = 0; m_pending_writes.clear(); m_pending_copies.clear(); m_image_info_pool.clear(); diff --git a/rpcs3/Emu/RSX/VK/vkutils/descriptors.h b/rpcs3/Emu/RSX/VK/vkutils/descriptors.h index 9a80592511..cd225f2241 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/descriptors.h +++ b/rpcs3/Emu/RSX/VK/vkutils/descriptors.h @@ -33,7 +33,7 @@ namespace vk VkDescriptorPool m_current_pool_handle = VK_NULL_HANDLE; u32 m_current_pool_index = 0; - static const size_t max_cache_size = 64; + static constexpr size_t max_cache_size = 64; VkDescriptorSetLayout m_cached_layout = VK_NULL_HANDLE; rsx::simple_array m_descriptor_set_cache; rsx::simple_array m_allocation_request_cache; @@ -41,7 +41,10 @@ namespace vk class descriptor_set { - static const size_t max_cache_size = 16384; + static constexpr size_t max_cache_size = 16384; + static constexpr size_t max_overflow_size = 64; + static constexpr size_t m_pool_size = max_cache_size + max_overflow_size; + void init(VkDescriptorSet new_set); public: @@ -69,7 +72,8 @@ namespace vk private: VkDescriptorSet m_handle = VK_NULL_HANDLE; - bool m_update_after_bind = false; + u64 m_update_after_bind_mask = 0; + u64 m_push_type_mask = 0; bool m_in_use = false; rsx::simple_array m_buffer_view_pool; diff --git a/rpcs3/Emu/RSX/VK/vkutils/device.cpp b/rpcs3/Emu/RSX/VK/vkutils/device.cpp index a52599b618..e538ef73ce 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/device.cpp +++ b/rpcs3/Emu/RSX/VK/vkutils/device.cpp @@ -30,6 +30,7 @@ namespace vk features2.pNext = nullptr; VkPhysicalDeviceFloat16Int8FeaturesKHR shader_support_info{}; + VkPhysicalDeviceDescriptorIndexingFeatures descriptor_indexing_info{}; if (device_extensions.is_supported(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME)) { @@ -44,6 +45,14 @@ namespace vk features2.pNext = &driver_properties; } + if (device_extensions.is_supported(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME)) + { + descriptor_indexing_info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT; + descriptor_indexing_info.pNext = features2.pNext; + features2.pNext = &descriptor_indexing_info; + descriptor_indexing_support = true; + } + auto _vkGetPhysicalDeviceFeatures2KHR = reinterpret_cast(vkGetInstanceProcAddr(parent, "vkGetPhysicalDeviceFeatures2KHR")); ensure(_vkGetPhysicalDeviceFeatures2KHR); // "vkGetInstanceProcAddress failed to find entry point!" _vkGetPhysicalDeviceFeatures2KHR(dev, &features2); @@ -52,11 +61,23 @@ namespace vk shader_types_support.allow_float16 = !!shader_support_info.shaderFloat16; shader_types_support.allow_int8 = !!shader_support_info.shaderInt8; features = features2.features; + + if (descriptor_indexing_support) + { +#define SET_DESCRIPTOR_BITFLAG(field, bit) if (descriptor_indexing_info.field) descriptor_update_after_bind_mask |= (1ull << bit) + SET_DESCRIPTOR_BITFLAG(descriptorBindingUniformBufferUpdateAfterBind, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER); + SET_DESCRIPTOR_BITFLAG(descriptorBindingSampledImageUpdateAfterBind, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); + SET_DESCRIPTOR_BITFLAG(descriptorBindingSampledImageUpdateAfterBind, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE); + SET_DESCRIPTOR_BITFLAG(descriptorBindingStorageImageUpdateAfterBind, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE); + SET_DESCRIPTOR_BITFLAG(descriptorBindingStorageBufferUpdateAfterBind, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); + SET_DESCRIPTOR_BITFLAG(descriptorBindingUniformTexelBufferUpdateAfterBind, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER); + SET_DESCRIPTOR_BITFLAG(descriptorBindingStorageTexelBufferUpdateAfterBind, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER); +#undef SET_DESCRIPTOR_BITFLAG + } } stencil_export_support = device_extensions.is_supported(VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME); conditional_render_support = device_extensions.is_supported(VK_EXT_CONDITIONAL_RENDERING_EXTENSION_NAME); - descriptor_indexing_support = device_extensions.is_supported(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME); external_memory_host_support = device_extensions.is_supported(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME); sampler_mirror_clamped_support = device_extensions.is_supported(VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME); unrestricted_depth_range_support = device_extensions.is_supported(VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME); @@ -464,11 +485,17 @@ namespace vk VkPhysicalDeviceDescriptorIndexingFeatures indexing_features{}; if (pgpu->descriptor_indexing_support) { +#define SET_DESCRIPTOR_BITFLAG(field, bit) if (pgpu->descriptor_update_after_bind_mask & (1ull << bit)) indexing_features.field = VK_TRUE + SET_DESCRIPTOR_BITFLAG(descriptorBindingUniformBufferUpdateAfterBind, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER); + SET_DESCRIPTOR_BITFLAG(descriptorBindingSampledImageUpdateAfterBind, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); + SET_DESCRIPTOR_BITFLAG(descriptorBindingSampledImageUpdateAfterBind, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE); + SET_DESCRIPTOR_BITFLAG(descriptorBindingStorageImageUpdateAfterBind, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE); + SET_DESCRIPTOR_BITFLAG(descriptorBindingStorageBufferUpdateAfterBind, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); + SET_DESCRIPTOR_BITFLAG(descriptorBindingUniformTexelBufferUpdateAfterBind, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER); + SET_DESCRIPTOR_BITFLAG(descriptorBindingStorageTexelBufferUpdateAfterBind, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER); +#undef SET_DESCRIPTOR_BITFLAG + indexing_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT; - indexing_features.descriptorBindingUniformTexelBufferUpdateAfterBind = VK_TRUE; - indexing_features.descriptorBindingUniformBufferUpdateAfterBind = VK_TRUE; - indexing_features.descriptorBindingStorageBufferUpdateAfterBind = VK_TRUE; - indexing_features.descriptorBindingSampledImageUpdateAfterBind = VK_TRUE; device.pNext = &indexing_features; } @@ -682,6 +709,11 @@ namespace vk return pgpu->descriptor_indexing_support; } + u64 render_device::get_descriptor_update_after_bind_support() const + { + return pgpu->descriptor_update_after_bind_mask; + } + mem_allocator_base* render_device::get_allocator() const { return m_allocator.get(); diff --git a/rpcs3/Emu/RSX/VK/vkutils/device.h b/rpcs3/Emu/RSX/VK/vkutils/device.h index 249f1aa229..993ac69d01 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/device.h +++ b/rpcs3/Emu/RSX/VK/vkutils/device.h @@ -61,6 +61,8 @@ namespace vk bool sampler_mirror_clamped_support = false; bool descriptor_indexing_support = false; + u64 descriptor_update_after_bind_mask = 0; + friend class render_device; private: void get_physical_device_features(bool allow_extensions); @@ -144,6 +146,8 @@ namespace vk bool get_debug_utils_support() const; bool get_descriptor_indexing_support() const; + u64 get_descriptor_update_after_bind_support() const; + VkQueue get_present_queue() const; VkQueue get_graphics_queue() const; VkQueue get_transfer_queue() const;