[vulkan] Implenting layouts use for indexing descriptors

This commit is contained in:
CamilleLaVey 2026-02-14 23:46:25 -04:00 committed by crueter
parent 603b07a8a4
commit 191af43721
7 changed files with 123 additions and 21 deletions

View File

@ -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

View File

@ -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<u32>(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<u32>(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<VkDescriptorSetLayoutBinding, 32> bindings;
boost::container::small_vector<VkDescriptorUpdateTemplateEntry, 32> entries;
mutable boost::container::small_vector<VkDescriptorBindingFlags, 32> binding_flags;
u32 binding{};
u32 num_descriptors{};
mutable u32 variable_descriptor_count{};
size_t offset{};
};

View File

@ -9,6 +9,7 @@
#include <numeric>
#include <optional>
#include <utility>
#include <vector>
#include "video_core/renderer_vulkan/vk_texture_cache.h"
@ -237,9 +238,36 @@ ComputePass::ComputePass(const Device& device_, DescriptorPool& descriptor_pool,
vk::Span<VkPushConstantRange> push_constants, std::span<const u32> code,
std::optional<u32> optional_subgroup_size)
: device{device_} {
u32 variable_descriptor_count{};
std::vector<VkDescriptorBindingFlags> 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<u32>(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;

View File

@ -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<VkDescriptorSetLayout> layouts(count, layout);
std::vector<u32> 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<u32>(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<u32>(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<const Shader::Info> infos) {
return Allocator(layout, MakeBankInfo(infos));
std::span<const Shader::Info> 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) {

View File

@ -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<vk::DescriptorSets> sets;
};
@ -69,9 +74,12 @@ public:
DescriptorPool(const DescriptorPool&) = delete;
DescriptorAllocator Allocator(VkDescriptorSetLayout layout,
std::span<const Shader::Info> infos);
DescriptorAllocator Allocator(VkDescriptorSetLayout layout, const Shader::Info& info);
DescriptorAllocator Allocator(VkDescriptorSetLayout layout, const DescriptorBankInfo& info);
std::span<const Shader::Info> 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);

View File

@ -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};

View File

@ -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);