From 191af43721cb7a61b73d869612549f1206be2e66 Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Sat, 14 Feb 2026 23:46:25 -0400 Subject: [PATCH] [vulkan] Implenting layouts use for indexing descriptors --- .../ir_opt/collect_shader_info_pass.cpp | 2 +- .../renderer_vulkan/pipeline_helper.h | 46 +++++++++++++++++-- .../renderer_vulkan/vk_compute_pass.cpp | 33 ++++++++++++- .../renderer_vulkan/vk_descriptor_pool.cpp | 41 +++++++++++++---- .../renderer_vulkan/vk_descriptor_pool.h | 16 +++++-- .../renderer_vulkan/vk_graphics_pipeline.cpp | 3 +- .../vulkan_common/vulkan_device.cpp | 3 ++ 7 files changed, 123 insertions(+), 21 deletions(-) diff --git a/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp b/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp index 2bfa3227a8..62eb8ccf5f 100644 --- a/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp +++ b/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project diff --git a/src/video_core/renderer_vulkan/pipeline_helper.h b/src/video_core/renderer_vulkan/pipeline_helper.h index 910e07a606..9725e5fe32 100644 --- a/src/video_core/renderer_vulkan/pipeline_helper.h +++ b/src/video_core/renderer_vulkan/pipeline_helper.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -27,23 +30,58 @@ public: return device->IsKhrPushDescriptorSupported() && num_descriptors <= device->MaxPushDescriptors(); } - - // TODO(crueter): utilize layout binding flags + vk::DescriptorSetLayout CreateDescriptorSetLayout(bool use_push_descriptor) const { if (bindings.empty()) { return nullptr; } + + variable_descriptor_count = 0; + binding_flags.clear(); + + VkDescriptorSetLayoutBindingFlagsCreateInfo binding_flags_ci{ + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO, + .pNext = nullptr, + .bindingCount = 0, + .pBindingFlags = nullptr, + }; + + const bool use_descriptor_indexing = + !use_push_descriptor && device->isExtDescriptorIndexingSupported(); + const void* layout_next = nullptr; + if (use_descriptor_indexing) { + binding_flags.assign(bindings.size(), 0); + for (size_t i = 0; i < bindings.size(); ++i) { + if (bindings[i].descriptorCount > 1) { + binding_flags[i] |= VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT; + } + } + + if (bindings.back().descriptorCount > 1) { + binding_flags.back() |= VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT; + variable_descriptor_count = bindings.back().descriptorCount; + } + + binding_flags_ci.bindingCount = static_cast(binding_flags.size()); + binding_flags_ci.pBindingFlags = binding_flags.data(); + layout_next = &binding_flags_ci; + } + const VkDescriptorSetLayoutCreateFlags flags = use_push_descriptor ? VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR : 0; return device->GetLogical().CreateDescriptorSetLayout({ .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, - .pNext = nullptr, + .pNext = layout_next, .flags = flags, .bindingCount = static_cast(bindings.size()), .pBindings = bindings.data(), }); } + u32 VariableDescriptorCount() const noexcept { + return variable_descriptor_count; + } + vk::DescriptorUpdateTemplate CreateTemplate(VkDescriptorSetLayout descriptor_set_layout, VkPipelineLayout pipeline_layout, bool use_push_descriptor) const { @@ -130,8 +168,10 @@ private: bool is_compute{}; boost::container::small_vector bindings; boost::container::small_vector entries; + mutable boost::container::small_vector binding_flags; u32 binding{}; u32 num_descriptors{}; + mutable u32 variable_descriptor_count{}; size_t offset{}; }; diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.cpp b/src/video_core/renderer_vulkan/vk_compute_pass.cpp index c978906c38..b587e92712 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pass.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pass.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include "video_core/renderer_vulkan/vk_texture_cache.h" @@ -237,9 +238,36 @@ ComputePass::ComputePass(const Device& device_, DescriptorPool& descriptor_pool, vk::Span push_constants, std::span code, std::optional optional_subgroup_size) : device{device_} { + u32 variable_descriptor_count{}; + std::vector binding_flags; + VkDescriptorSetLayoutBindingFlagsCreateInfo binding_flags_ci{ + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO, + .pNext = nullptr, + .bindingCount = 0, + .pBindingFlags = nullptr, + }; + const bool use_descriptor_indexing = device.isExtDescriptorIndexingSupported(); + const void* layout_next = nullptr; + if (use_descriptor_indexing && !bindings.empty()) { + binding_flags.assign(bindings.size(), 0); + for (size_t i = 0; i < bindings.size(); ++i) { + if (bindings[i].descriptorCount > 1) { + binding_flags[i] |= VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT; + } + } + if (bindings.back().descriptorCount > 1) { + binding_flags.back() |= VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT; + variable_descriptor_count = bindings.back().descriptorCount; + } + + binding_flags_ci.bindingCount = static_cast(binding_flags.size()); + binding_flags_ci.pBindingFlags = binding_flags.data(); + layout_next = &binding_flags_ci; + } + descriptor_set_layout = device.GetLogical().CreateDescriptorSetLayout({ .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, - .pNext = nullptr, + .pNext = layout_next, .flags = 0, .bindingCount = bindings.size(), .pBindings = bindings.data(), @@ -266,7 +294,8 @@ ComputePass::ComputePass(const Device& device_, DescriptorPool& descriptor_pool, .pipelineLayout = *layout, .set = 0, }); - descriptor_allocator = descriptor_pool.Allocator(*descriptor_set_layout, bank_info); + descriptor_allocator = + descriptor_pool.Allocator(*descriptor_set_layout, bank_info, variable_descriptor_count); } if (code.empty()) { return; diff --git a/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp b/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp index 3af9758a31..97f51988bc 100644 --- a/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp +++ b/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project @@ -88,9 +88,10 @@ static void AllocatePool(const Device& device, DescriptorBank& bank) { } DescriptorAllocator::DescriptorAllocator(const Device& device_, MasterSemaphore& master_semaphore_, - DescriptorBank& bank_, VkDescriptorSetLayout layout_) + DescriptorBank& bank_, VkDescriptorSetLayout layout_, + u32 variable_descriptor_count_) : ResourcePool(master_semaphore_, SETS_GROW_RATE), device{&device_}, bank{&bank_}, - layout{layout_} {} + layout{layout_}, variable_descriptor_count{variable_descriptor_count_} {} VkDescriptorSet DescriptorAllocator::Commit() { const size_t index = CommitResource(); @@ -103,9 +104,25 @@ void DescriptorAllocator::Allocate(size_t begin, size_t end) { vk::DescriptorSets DescriptorAllocator::AllocateDescriptors(size_t count) { const std::vector layouts(count, layout); + + std::vector variable_descriptor_counts; + VkDescriptorSetVariableDescriptorCountAllocateInfo variable_descriptor_count_info{ + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO, + .pNext = nullptr, + .descriptorSetCount = 0, + .pDescriptorCounts = nullptr, + }; + const void* allocate_next = nullptr; + if (variable_descriptor_count != 0) { + variable_descriptor_counts.assign(count, variable_descriptor_count); + variable_descriptor_count_info.descriptorSetCount = static_cast(count); + variable_descriptor_count_info.pDescriptorCounts = variable_descriptor_counts.data(); + allocate_next = &variable_descriptor_count_info; + } + VkDescriptorSetAllocateInfo allocate_info{ .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, - .pNext = nullptr, + .pNext = allocate_next, .descriptorPool = *bank->pools.back(), .descriptorSetCount = static_cast(count), .pSetLayouts = layouts.data(), @@ -131,18 +148,22 @@ DescriptorPool::DescriptorPool(const Device& device_, Scheduler& scheduler) DescriptorPool::~DescriptorPool() = default; DescriptorAllocator DescriptorPool::Allocator(VkDescriptorSetLayout layout, - std::span infos) { - return Allocator(layout, MakeBankInfo(infos)); + std::span infos, + u32 variable_descriptor_count) { + return Allocator(layout, MakeBankInfo(infos), variable_descriptor_count); } DescriptorAllocator DescriptorPool::Allocator(VkDescriptorSetLayout layout, - const Shader::Info& info) { - return Allocator(layout, MakeBankInfo(std::array{info})); + const Shader::Info& info, + u32 variable_descriptor_count) { + return Allocator(layout, MakeBankInfo(std::array{info}), variable_descriptor_count); } DescriptorAllocator DescriptorPool::Allocator(VkDescriptorSetLayout layout, - const DescriptorBankInfo& info) { - return DescriptorAllocator(device, master_semaphore, Bank(info), layout); + const DescriptorBankInfo& info, + u32 variable_descriptor_count) { + return DescriptorAllocator(device, master_semaphore, Bank(info), layout, + variable_descriptor_count); } DescriptorBank& DescriptorPool::Bank(const DescriptorBankInfo& reqs) { diff --git a/src/video_core/renderer_vulkan/vk_descriptor_pool.h b/src/video_core/renderer_vulkan/vk_descriptor_pool.h index 4aada5a006..fed43a45f8 100644 --- a/src/video_core/renderer_vulkan/vk_descriptor_pool.h +++ b/src/video_core/renderer_vulkan/vk_descriptor_pool.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -47,7 +50,8 @@ public: private: explicit DescriptorAllocator(const Device& device_, MasterSemaphore& master_semaphore_, - DescriptorBank& bank_, VkDescriptorSetLayout layout_); + DescriptorBank& bank_, VkDescriptorSetLayout layout_, + u32 variable_descriptor_count_); void Allocate(size_t begin, size_t end) override; @@ -56,6 +60,7 @@ private: const Device* device{}; DescriptorBank* bank{}; VkDescriptorSetLayout layout{}; + u32 variable_descriptor_count{}; std::vector sets; }; @@ -69,9 +74,12 @@ public: DescriptorPool(const DescriptorPool&) = delete; DescriptorAllocator Allocator(VkDescriptorSetLayout layout, - std::span infos); - DescriptorAllocator Allocator(VkDescriptorSetLayout layout, const Shader::Info& info); - DescriptorAllocator Allocator(VkDescriptorSetLayout layout, const DescriptorBankInfo& info); + std::span infos, + u32 variable_descriptor_count = 0); + DescriptorAllocator Allocator(VkDescriptorSetLayout layout, const Shader::Info& info, + u32 variable_descriptor_count = 0); + DescriptorAllocator Allocator(VkDescriptorSetLayout layout, const DescriptorBankInfo& info, + u32 variable_descriptor_count = 0); private: DescriptorBank& Bank(const DescriptorBankInfo& reqs); diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 02fc9170b4..bd6bd088cc 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -273,7 +273,8 @@ GraphicsPipeline::GraphicsPipeline( descriptor_set_layout = builder.CreateDescriptorSetLayout(uses_push_descriptor); if (!uses_push_descriptor) { - descriptor_allocator = descriptor_pool.Allocator(*descriptor_set_layout, stage_infos); + descriptor_allocator = descriptor_pool.Allocator( + *descriptor_set_layout, stage_infos, builder.VariableDescriptorCount()); } const VkDescriptorSetLayout set_layout{*descriptor_set_layout}; diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index e0e567ab29..d2aebe72bb 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp @@ -475,6 +475,9 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR if (extensions.descriptor_indexing && Settings::values.descriptor_indexing.GetValue()) { first_next = &descriptor_indexing; + } else { + RemoveExtension(extensions.descriptor_indexing, + VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME); } is_blit_depth24_stencil8_supported = TestDepthStencilBlits(VK_FORMAT_D24_UNORM_S8_UINT);