Merge pull request #3264 from ReinUsesLisp/vk-descriptor-pool
vk_descriptor_pool: Initial implementation
This commit is contained in:
commit
56e450a3f7
3 changed files with 147 additions and 0 deletions
|
@ -155,6 +155,8 @@ if (ENABLE_VULKAN)
|
||||||
renderer_vulkan/maxwell_to_vk.h
|
renderer_vulkan/maxwell_to_vk.h
|
||||||
renderer_vulkan/vk_buffer_cache.cpp
|
renderer_vulkan/vk_buffer_cache.cpp
|
||||||
renderer_vulkan/vk_buffer_cache.h
|
renderer_vulkan/vk_buffer_cache.h
|
||||||
|
renderer_vulkan/vk_descriptor_pool.cpp
|
||||||
|
renderer_vulkan/vk_descriptor_pool.h
|
||||||
renderer_vulkan/vk_device.cpp
|
renderer_vulkan/vk_device.cpp
|
||||||
renderer_vulkan/vk_device.h
|
renderer_vulkan/vk_device.h
|
||||||
renderer_vulkan/vk_image.cpp
|
renderer_vulkan/vk_image.cpp
|
||||||
|
|
89
src/video_core/renderer_vulkan/vk_descriptor_pool.cpp
Normal file
89
src/video_core/renderer_vulkan/vk_descriptor_pool.cpp
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
// Copyright 2019 yuzu Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "common/common_types.h"
|
||||||
|
#include "video_core/renderer_vulkan/declarations.h"
|
||||||
|
#include "video_core/renderer_vulkan/vk_descriptor_pool.h"
|
||||||
|
#include "video_core/renderer_vulkan/vk_device.h"
|
||||||
|
#include "video_core/renderer_vulkan/vk_resource_manager.h"
|
||||||
|
|
||||||
|
namespace Vulkan {
|
||||||
|
|
||||||
|
// Prefer small grow rates to avoid saturating the descriptor pool with barely used pipelines.
|
||||||
|
constexpr std::size_t SETS_GROW_RATE = 0x20;
|
||||||
|
|
||||||
|
DescriptorAllocator::DescriptorAllocator(VKDescriptorPool& descriptor_pool,
|
||||||
|
vk::DescriptorSetLayout layout)
|
||||||
|
: VKFencedPool{SETS_GROW_RATE}, descriptor_pool{descriptor_pool}, layout{layout} {}
|
||||||
|
|
||||||
|
DescriptorAllocator::~DescriptorAllocator() = default;
|
||||||
|
|
||||||
|
vk::DescriptorSet DescriptorAllocator::Commit(VKFence& fence) {
|
||||||
|
return *descriptors[CommitResource(fence)];
|
||||||
|
}
|
||||||
|
|
||||||
|
void DescriptorAllocator::Allocate(std::size_t begin, std::size_t end) {
|
||||||
|
auto new_sets = descriptor_pool.AllocateDescriptors(layout, end - begin);
|
||||||
|
descriptors.insert(descriptors.end(), std::make_move_iterator(new_sets.begin()),
|
||||||
|
std::make_move_iterator(new_sets.end()));
|
||||||
|
}
|
||||||
|
|
||||||
|
VKDescriptorPool::VKDescriptorPool(const VKDevice& device)
|
||||||
|
: device{device}, active_pool{AllocateNewPool()} {}
|
||||||
|
|
||||||
|
VKDescriptorPool::~VKDescriptorPool() = default;
|
||||||
|
|
||||||
|
vk::DescriptorPool VKDescriptorPool::AllocateNewPool() {
|
||||||
|
static constexpr u32 num_sets = 0x20000;
|
||||||
|
static constexpr vk::DescriptorPoolSize pool_sizes[] = {
|
||||||
|
{vk::DescriptorType::eUniformBuffer, num_sets * 90},
|
||||||
|
{vk::DescriptorType::eStorageBuffer, num_sets * 60},
|
||||||
|
{vk::DescriptorType::eUniformTexelBuffer, num_sets * 64},
|
||||||
|
{vk::DescriptorType::eCombinedImageSampler, num_sets * 64},
|
||||||
|
{vk::DescriptorType::eStorageImage, num_sets * 40}};
|
||||||
|
|
||||||
|
const vk::DescriptorPoolCreateInfo create_info(
|
||||||
|
vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet, num_sets,
|
||||||
|
static_cast<u32>(std::size(pool_sizes)), std::data(pool_sizes));
|
||||||
|
const auto dev = device.GetLogical();
|
||||||
|
return *pools.emplace_back(
|
||||||
|
dev.createDescriptorPoolUnique(create_info, nullptr, device.GetDispatchLoader()));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<UniqueDescriptorSet> VKDescriptorPool::AllocateDescriptors(
|
||||||
|
vk::DescriptorSetLayout layout, std::size_t count) {
|
||||||
|
std::vector layout_copies(count, layout);
|
||||||
|
vk::DescriptorSetAllocateInfo allocate_info(active_pool, static_cast<u32>(count),
|
||||||
|
layout_copies.data());
|
||||||
|
|
||||||
|
std::vector<vk::DescriptorSet> sets(count);
|
||||||
|
const auto dev = device.GetLogical();
|
||||||
|
const auto& dld = device.GetDispatchLoader();
|
||||||
|
switch (const auto result = dev.allocateDescriptorSets(&allocate_info, sets.data(), dld)) {
|
||||||
|
case vk::Result::eSuccess:
|
||||||
|
break;
|
||||||
|
case vk::Result::eErrorOutOfPoolMemory:
|
||||||
|
active_pool = AllocateNewPool();
|
||||||
|
allocate_info.descriptorPool = active_pool;
|
||||||
|
if (dev.allocateDescriptorSets(&allocate_info, sets.data(), dld) == vk::Result::eSuccess) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
[[fallthrough]];
|
||||||
|
default:
|
||||||
|
vk::throwResultException(result, "vk::Device::allocateDescriptorSetsUnique");
|
||||||
|
}
|
||||||
|
|
||||||
|
vk::PoolFree deleter(dev, active_pool, dld);
|
||||||
|
std::vector<UniqueDescriptorSet> unique_sets;
|
||||||
|
unique_sets.reserve(count);
|
||||||
|
for (const auto set : sets) {
|
||||||
|
unique_sets.push_back(UniqueDescriptorSet{set, deleter});
|
||||||
|
}
|
||||||
|
return unique_sets;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Vulkan
|
56
src/video_core/renderer_vulkan/vk_descriptor_pool.h
Normal file
56
src/video_core/renderer_vulkan/vk_descriptor_pool.h
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
// Copyright 2019 yuzu Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "common/common_types.h"
|
||||||
|
#include "video_core/renderer_vulkan/declarations.h"
|
||||||
|
#include "video_core/renderer_vulkan/vk_resource_manager.h"
|
||||||
|
|
||||||
|
namespace Vulkan {
|
||||||
|
|
||||||
|
class VKDescriptorPool;
|
||||||
|
|
||||||
|
class DescriptorAllocator final : public VKFencedPool {
|
||||||
|
public:
|
||||||
|
explicit DescriptorAllocator(VKDescriptorPool& descriptor_pool, vk::DescriptorSetLayout layout);
|
||||||
|
~DescriptorAllocator() override;
|
||||||
|
|
||||||
|
DescriptorAllocator(const DescriptorAllocator&) = delete;
|
||||||
|
|
||||||
|
vk::DescriptorSet Commit(VKFence& fence);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void Allocate(std::size_t begin, std::size_t end) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
VKDescriptorPool& descriptor_pool;
|
||||||
|
const vk::DescriptorSetLayout layout;
|
||||||
|
|
||||||
|
std::vector<UniqueDescriptorSet> descriptors;
|
||||||
|
};
|
||||||
|
|
||||||
|
class VKDescriptorPool final {
|
||||||
|
friend DescriptorAllocator;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit VKDescriptorPool(const VKDevice& device);
|
||||||
|
~VKDescriptorPool();
|
||||||
|
|
||||||
|
private:
|
||||||
|
vk::DescriptorPool AllocateNewPool();
|
||||||
|
|
||||||
|
std::vector<UniqueDescriptorSet> AllocateDescriptors(vk::DescriptorSetLayout layout,
|
||||||
|
std::size_t count);
|
||||||
|
|
||||||
|
const VKDevice& device;
|
||||||
|
|
||||||
|
std::vector<UniqueDescriptorPool> pools;
|
||||||
|
vk::DescriptorPool active_pool;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Vulkan
|
Loading…
Reference in a new issue