core descriptor pool/set objects

This commit is contained in:
PancakeTAS 2025-06-29 18:08:17 +02:00
parent 013950596c
commit d3a903524a
No known key found for this signature in database
4 changed files with 195 additions and 0 deletions

View file

@ -0,0 +1,49 @@
#ifndef DESCRIPTORPOOL_HPP
#define DESCRIPTORPOOL_HPP
#include "device.hpp"
#include <vulkan/vulkan_core.h>
#include <memory>
namespace Vulkan::Core {
///
/// C++ wrapper class for a Vulkan descriptor pool.
///
/// This class manages the lifetime of a Vulkan descriptor pool.
///
class DescriptorPool {
public:
///
/// Create the descriptor pool.
///
/// @param device Vulkan device
///
/// @throws std::invalid_argument if the device is invalid.
/// @throws ls::vulkan_error if object creation fails.
///
DescriptorPool(const Device& device);
/// Get the Vulkan handle.
[[nodiscard]] auto handle() const { return *this->descriptorPool; }
/// Check whether the object is valid.
[[nodiscard]] bool isValid() const { return static_cast<bool>(this->descriptorPool); }
/// if (obj) operator. Checks if the object is valid.
explicit operator bool() const { return this->isValid(); }
/// Trivially copyable, moveable and destructible
DescriptorPool(const DescriptorPool&) noexcept = default;
DescriptorPool& operator=(const DescriptorPool&) noexcept = default;
DescriptorPool(DescriptorPool&&) noexcept = default;
DescriptorPool& operator=(DescriptorPool&&) noexcept = default;
~DescriptorPool() = default;
private:
std::shared_ptr<VkDescriptorPool> descriptorPool;
};
}
#endif // DESCRIPTORPOOL_HPP

View file

@ -0,0 +1,66 @@
#ifndef DESCRIPTORSET_HPP
#define DESCRIPTORSET_HPP
#include "core/commandbuffer.hpp"
#include "core/descriptorpool.hpp"
#include "core/pipeline.hpp"
#include "core/shadermodule.hpp"
#include "device.hpp"
#include <vulkan/vulkan_core.h>
#include <memory>
namespace Vulkan::Core {
///
/// C++ wrapper class for a Vulkan descriptor set.
///
/// This class manages the lifetime of a Vulkan descriptor set.
///
class DescriptorSet {
public:
///
/// Create the descriptor set.
///
/// @param device Vulkan device
/// @param pool Descriptor pool to allocate from
/// @param shaderModule Shader module to use for the descriptor set
///
/// @throws std::invalid_argument if the device or pool is invalid.
/// @throws ls::vulkan_error if object creation fails.
///
DescriptorSet(const Device& device,
DescriptorPool pool, const ShaderModule& shaderModule);
///
/// Bind a descriptor set to a command buffer.
///
/// @param commandBuffer Command buffer to bind the descriptor set to.
/// @param pipeline Pipeline to bind the descriptor set to.
///
/// @throws std::invalid_argument if the command buffer is invalid.
///
void bind(const CommandBuffer& commandBuffer, const Pipeline& pipeline) const;
/// Get the Vulkan handle.
[[nodiscard]] auto handle() const { return *this->descriptorSet; }
/// Check whether the object is valid.
[[nodiscard]] bool isValid() const { return static_cast<bool>(this->descriptorSet); }
/// if (obj) operator. Checks if the object is valid.
explicit operator bool() const { return this->isValid(); }
/// Trivially copyable, moveable and destructible
DescriptorSet(const DescriptorSet&) noexcept = default;
DescriptorSet& operator=(const DescriptorSet&) noexcept = default;
DescriptorSet(DescriptorSet&&) noexcept = default;
DescriptorSet& operator=(DescriptorSet&&) noexcept = default;
~DescriptorSet() = default;
private:
std::shared_ptr<VkDescriptorSet> descriptorSet;
};
}
#endif // DESCRIPTORSET_HPP

View file

@ -0,0 +1,37 @@
#include "core/descriptorpool.hpp"
#include "utils/exceptions.hpp"
#include <array>
using namespace Vulkan::Core;
DescriptorPool::DescriptorPool(const Device& device) {
if (!device)
throw std::invalid_argument("Invalid Vulkan device");
// create descriptor pool
const std::array<VkDescriptorPoolSize, 4> pools{{ // arbitrary limits
{ .type = VK_DESCRIPTOR_TYPE_SAMPLER, .descriptorCount = 4096 },
{ .type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, .descriptorCount = 4096 },
{ .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, .descriptorCount = 4096 },
{ .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, .descriptorCount = 4096 }
}};
const VkDescriptorPoolCreateInfo desc{
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
.maxSets = 16384, // arbitrary limit
.poolSizeCount = static_cast<uint32_t>(pools.size()),
.pPoolSizes = pools.data()
};
VkDescriptorPool poolHandle{};
auto res = vkCreateDescriptorPool(device.handle(), &desc, nullptr, &poolHandle);
if (res != VK_SUCCESS || poolHandle == VK_NULL_HANDLE)
throw ls::vulkan_error(res, "Unable to create descriptor pool");
/// store pool in shared ptr
this->descriptorPool = std::shared_ptr<VkDescriptorPool>(
new VkDescriptorPool(poolHandle),
[dev = device.handle()](VkDescriptorPool* poolHandle) {
vkDestroyDescriptorPool(dev, *poolHandle, nullptr);
}
);
}

View file

@ -0,0 +1,43 @@
#include "core/descriptorset.hpp"
#include "utils/exceptions.hpp"
using namespace Vulkan::Core;
DescriptorSet::DescriptorSet(const Device& device,
DescriptorPool pool, const ShaderModule& shaderModule) {
if (!device || !pool)
throw std::invalid_argument("Invalid Vulkan device");
// create descriptor set
VkDescriptorSetLayout layout = shaderModule.getDescriptorSetLayout();
const VkDescriptorSetAllocateInfo desc{
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
.descriptorPool = pool.handle(),
.descriptorSetCount = 1,
.pSetLayouts = &layout
};
VkDescriptorSet descriptorSetHandle{};
auto res = vkAllocateDescriptorSets(device.handle(), &desc, &descriptorSetHandle);
if (res != VK_SUCCESS || descriptorSetHandle == VK_NULL_HANDLE)
throw ls::vulkan_error(res, "Unable to allocate descriptor set");
/// store descriptor set in shared ptr
this->descriptorSet = std::shared_ptr<VkDescriptorSet>(
new VkDescriptorSet(descriptorSetHandle),
[dev = device.handle(), pool = std::move(pool)](VkDescriptorSet* setHandle) {
vkFreeDescriptorSets(dev, pool.handle(), 1, setHandle);
}
);
}
void DescriptorSet::bind(const CommandBuffer& commandBuffer, const Pipeline& pipeline) const {
if (!commandBuffer)
throw std::invalid_argument("Invalid command buffer");
// bind descriptor set
VkDescriptorSet descriptorSetHandle = this->handle();
vkCmdBindDescriptorSets(commandBuffer.handle(),
VK_PIPELINE_BIND_POINT_COMPUTE, pipeline.getLayout(),
0, 1, &descriptorSetHandle,
0, nullptr);
}