Skip to content
Snippets Groups Projects
Commit 47938552 authored by Tobias Frisch's avatar Tobias Frisch
Browse files

Merge branch '9-descriptor-set-managment' into 'develop'

Resolve "Descriptor Set Managment"

Closes #9

See merge request !3
parents f4ec5e9e 53310dfd
No related branches found
No related tags found
1 merge request!3Resolve "Descriptor Set Managment"
Pipeline #25178 passed
......@@ -55,4 +55,10 @@ set(vkcv_sources
${vkcv_source}/vkcv/Framebuffer.cpp
${vkcv_include}/vkcv/Event.hpp
${vkcv_source}/vkcv/DescriptorManager.hpp
${vkcv_source}/vkcv/DescriptorManager.cpp
${vkcv_include}/vkcv/DescriptorConfig.hpp
${vkcv_source}/vkcv/DescriptorConfig.cpp
)
......@@ -17,12 +17,14 @@
#include "CommandResources.hpp"
#include "SyncResources.hpp"
#include "Result.hpp"
#include "vkcv/DescriptorConfig.hpp"
namespace vkcv
{
// forward declarations
class PassManager;
class PipelineManager;
class DescriptorManager;
class BufferManager;
struct SubmitInfo {
......@@ -59,7 +61,9 @@ namespace vkcv
std::unique_ptr<PassManager> m_PassManager;
std::unique_ptr<PipelineManager> m_PipelineManager;
std::unique_ptr<DescriptorManager> m_DescriptorManager;
std::unique_ptr<BufferManager> m_BufferManager;
CommandResources m_CommandResources;
SyncResources m_SyncResources;
uint32_t m_currentSwapchainImageIndex;
......@@ -167,6 +171,13 @@ namespace vkcv
return Buffer<T>::create(m_BufferManager.get(), type, count, memoryType);
}
/** TODO:
* @param setDescriptions
* @return
*/
[[nodiscard]]
ResourcesHandle createResourceDescription(const std::vector<DescriptorSet> &descriptorSets);
/**
* @brief start recording command buffers and increment frame index
*/
......
#pragma once
#include <vkcv/ShaderProgram.hpp>
namespace vkcv
{
/*
* All the types of descriptors (resources) that can be retrieved by the shaders
*/
enum class DescriptorType
{
UNIFORM_BUFFER,
STORAGE_BUFFER,
SAMPLER,
IMAGE
};
/*
* One binding for a descriptor set
* @param[in] a unique binding ID
* @param[in] a descriptor type
* @param[in] the number of descriptors of this type (arrays of the same type possible)
* @param[in] the shader stage where the descriptor is supposed to be retrieved
*/
struct DescriptorBinding
{
DescriptorBinding() = delete;
DescriptorBinding(
DescriptorType descriptorType,
uint32_t descriptorCount,
ShaderStage shaderStage
) noexcept;
DescriptorType descriptorType;
uint32_t descriptorCount;
ShaderStage shaderStage;
};
/*
* One descriptor set struct that contains all the necessary information for the actual creation.
* @param[in] a number of bindings that were created beforehand
* @param[in] the number of (identical) sets that should be created from the attached bindings
*/
struct DescriptorSet
{
DescriptorSet() = delete;
explicit DescriptorSet(std::vector<DescriptorBinding> bindings) noexcept;
std::vector<DescriptorBinding> bindings;
};
}
......@@ -13,4 +13,5 @@ namespace vkcv
struct BufferHandle {uint64_t id;};
struct PassHandle {uint64_t id;};
struct PipelineHandle {uint64_t id;};
struct ResourcesHandle {uint64_t id;};
}
......@@ -3,6 +3,7 @@
#include <vkcv/Window.hpp>
#include <vkcv/ShaderProgram.hpp>
#include <GLFW/glfw3.h>
#include <vkcv/DescriptorConfig.hpp>
int main(int argc, const char** argv) {
const char* applicationName = "First Triangle";
......@@ -94,6 +95,24 @@ int main(int argc, const char** argv) {
return EXIT_FAILURE;
}
//just an example
//creates 20 descriptor sets, each containing bindings for 50 uniform buffers, images, and samplers
std::vector<vkcv::DescriptorSet> sets;
for (uint32_t i = 0; i < 20; i++)
{
vkcv::DescriptorBinding uniformBufBinding(vkcv::DescriptorType::UNIFORM_BUFFER, 50, vkcv::ShaderStage::VERTEX);
vkcv::DescriptorBinding storageBufBinding(vkcv::DescriptorType::STORAGE_BUFFER, 50, vkcv::ShaderStage::VERTEX);
vkcv::DescriptorBinding imageBinding(vkcv::DescriptorType::IMAGE, 50, vkcv::ShaderStage::VERTEX);
vkcv::DescriptorBinding samplerBinding(vkcv::DescriptorType::SAMPLER, 50, vkcv::ShaderStage::VERTEX);
vkcv::DescriptorSet set({uniformBufBinding, storageBufBinding, imageBinding, samplerBinding});
sets.push_back(set);
auto resourceHandle = core.createResourceDescription(sets);
std::cout << "Resource " << resourceHandle.id << " created." << std::endl;
}
/*
* BufferHandle triangleVertices = core.createBuffer(vertices);
* BufferHandle triangleIndices = core.createBuffer(indices);
......
......@@ -10,6 +10,7 @@
#include "PassManager.hpp"
#include "PipelineManager.hpp"
#include "vkcv/BufferManager.hpp"
#include "DescriptorManager.hpp"
#include "Surface.hpp"
#include "ImageLayoutTransitions.hpp"
#include "Framebuffer.hpp"
......@@ -92,6 +93,7 @@ namespace vkcv
m_swapchainImageViews(imageViews),
m_PassManager{std::make_unique<PassManager>(m_Context.m_Device)},
m_PipelineManager{std::make_unique<PipelineManager>(m_Context.m_Device)},
m_DescriptorManager(std::make_unique<DescriptorManager>(m_Context.m_Device)),
m_BufferManager{std::unique_ptr<BufferManager>(new BufferManager())},
m_CommandResources(commandResources),
m_SyncResources(syncResources)
......@@ -251,4 +253,9 @@ namespace vkcv
finish();
}
}
ResourcesHandle Core::createResourceDescription(const std::vector<DescriptorSet> &descriptorSets)
{
return m_DescriptorManager->createResourceDescription(descriptorSets);
}
}
#include "vkcv/DescriptorConfig.hpp"
#include <utility>
namespace vkcv {
DescriptorBinding::DescriptorBinding(
DescriptorType descriptorType,
uint32_t descriptorCount,
ShaderStage shaderStage
) noexcept :
descriptorType{descriptorType},
descriptorCount{descriptorCount},
shaderStage{shaderStage}
{};
DescriptorSet::DescriptorSet(std::vector<DescriptorBinding> bindings) noexcept :
bindings{std::move(bindings)}
{};
}
#include "DescriptorManager.hpp"
namespace vkcv
{
DescriptorManager::ResourceDescription::ResourceDescription(std::vector<vk::DescriptorSet> sets,
std::vector<vk::DescriptorSetLayout> layouts) noexcept :
descriptorSets{std::move(sets)},
descriptorSetLayouts{std::move(layouts)}
{}
DescriptorManager::DescriptorManager(vk::Device device) noexcept:
m_Device{ device }, m_NextResourceDescriptionID{ 1 }
{
/**
* Allocate a set size for the initial pool, namely 1000 units of each descriptor type below.
*/
const std::vector<vk::DescriptorPoolSize> poolSizes = {vk::DescriptorPoolSize(vk::DescriptorType::eSampler, 1000),
vk::DescriptorPoolSize(vk::DescriptorType::eSampledImage, 1000),
vk::DescriptorPoolSize(vk::DescriptorType::eUniformBuffer, 1000),
vk::DescriptorPoolSize(vk::DescriptorType::eStorageBuffer, 1000)};
vk::DescriptorPoolCreateInfo poolInfo({},
1000,
static_cast<uint32_t>(poolSizes.size()),
poolSizes.data());
if(m_Device.createDescriptorPool(&poolInfo, nullptr, &m_Pool) != vk::Result::eSuccess)
{
std::cout << "FAILED TO ALLOCATED DESCRIPTOR POOL." << std::endl;
m_Pool = nullptr;
};
}
DescriptorManager::~DescriptorManager() noexcept
{
for(const auto &resource : m_ResourceDescriptions)
{
for(const auto &layout : resource.descriptorSetLayouts)
m_Device.destroyDescriptorSetLayout(layout);
}
m_Device.destroy(m_Pool);
}
ResourcesHandle DescriptorManager::createResourceDescription(const std::vector<DescriptorSet> &descriptorSets)
{
std::vector<vk::DescriptorSet> vk_sets;
std::vector<vk::DescriptorSetLayout> vk_setLayouts;
for (const auto &set : descriptorSets) {
std::vector<vk::DescriptorSetLayoutBinding> setBindings = {};
//create each set's binding
for (uint32_t j = 0; j < set.bindings.size(); j++) {
vk::DescriptorSetLayoutBinding descriptorSetLayoutBinding(
j,
convertDescriptorTypeFlag(set.bindings[j].descriptorType),
set.bindings[j].descriptorCount,
convertShaderStageFlag(set.bindings[j].shaderStage));
setBindings.push_back(descriptorSetLayoutBinding);
}
//create the descriptor set's layout from the bindings gathered above
vk::DescriptorSetLayoutCreateInfo layoutInfo({}, setBindings);
vk::DescriptorSetLayout layout = nullptr;
if(m_Device.createDescriptorSetLayout(&layoutInfo, nullptr, &layout) != vk::Result::eSuccess)
{
std::cout << "FAILED TO CREATE DESCRIPTOR SET LAYOUT" << std::endl;
return ResourcesHandle{0};
};
vk_setLayouts.push_back(layout);
}
//create and allocate the set(s) based on the layouts that have been gathered above
vk_sets.resize(vk_setLayouts.size());
vk::DescriptorSetAllocateInfo allocInfo(m_Pool, vk_sets.size(), vk_setLayouts.data());
auto result = m_Device.allocateDescriptorSets(&allocInfo, vk_sets.data());
if(result != vk::Result::eSuccess)
{
std::cout << "FAILED TO ALLOCATE DESCRIPTOR SET" << std::endl;
std::cout << vk::to_string(result) << std::endl;
for(const auto &layout : vk_setLayouts)
m_Device.destroy(layout);
return ResourcesHandle{0};
};
m_ResourceDescriptions.emplace_back(vk_sets, vk_setLayouts);
return ResourcesHandle{m_NextResourceDescriptionID++};
}
vk::DescriptorType DescriptorManager::convertDescriptorTypeFlag(DescriptorType type) {
switch (type)
{
case DescriptorType::UNIFORM_BUFFER:
return vk::DescriptorType::eUniformBuffer;
case DescriptorType::STORAGE_BUFFER:
return vk::DescriptorType::eStorageBuffer;
case DescriptorType::SAMPLER:
return vk::DescriptorType::eSampler;
case DescriptorType::IMAGE:
return vk::DescriptorType::eSampledImage;
default:
return vk::DescriptorType::eUniformBuffer;
}
}
vk::ShaderStageFlagBits DescriptorManager::convertShaderStageFlag(ShaderStage stage) {
switch (stage)
{
case ShaderStage::VERTEX:
return vk::ShaderStageFlagBits::eVertex;
case ShaderStage::FRAGMENT:
return vk::ShaderStageFlagBits::eFragment;
case ShaderStage::TESS_CONTROL:
return vk::ShaderStageFlagBits::eTessellationControl;
case ShaderStage::TESS_EVAL:
return vk::ShaderStageFlagBits::eTessellationEvaluation;
case ShaderStage::GEOMETRY:
return vk::ShaderStageFlagBits::eGeometry;
case ShaderStage::COMPUTE:
return vk::ShaderStageFlagBits::eCompute;
default:
return vk::ShaderStageFlagBits::eAll;
}
}
}
\ No newline at end of file
#include <vulkan/vulkan.hpp>
#include "vkcv/Handles.hpp"
#include "vkcv/DescriptorConfig.hpp"
namespace vkcv
{
class DescriptorManager
{
public:
explicit DescriptorManager(vk::Device device) noexcept;
~DescriptorManager() noexcept;
/**
* Creates all vk::DescriptorSets and allocates them from the pool.
* DescriptorSets are put inside a ResourceDescription struct.
* Structs are then put into m_ResourceDescriptions.
* @param[in] vector of filled vkcv::DescriptorSet structs
* @return index into that objects a resource handle
*/
ResourcesHandle createResourceDescription(const std::vector<DescriptorSet> & descriptorSets);
private:
vk::Device m_Device;
vk::DescriptorPool m_Pool;
/**
* Container for all resources requested by the user in one call of createResourceDescription.
* Includes descriptor sets and the respective descriptor set layouts.
*/
struct ResourceDescription
{
ResourceDescription() = delete;
ResourceDescription(std::vector<vk::DescriptorSet> sets, std::vector<vk::DescriptorSetLayout> layouts) noexcept;
std::vector<vk::DescriptorSet> descriptorSets;
std::vector<vk::DescriptorSetLayout> descriptorSetLayouts;
};
/**
* Contains all the resource descriptions that were requested by the user in calls of createResourceDescription.
*/
std::vector<ResourceDescription> m_ResourceDescriptions;
// Counter for the vector above
uint64_t m_NextResourceDescriptionID;
/**
* Converts the flags of the descriptor types from VulkanCV (vkcv) to Vulkan (vk).
* @param[in] vkcv flag of the DescriptorType (see DescriptorConfig.hpp)
* @return vk flag of the DescriptorType
*/
static vk::DescriptorType convertDescriptorTypeFlag(DescriptorType type);
/**
* Converts the flags of the shader stages from VulkanCV (vkcv) to Vulkan (vk).
* @param[in] vkcv flag of the ShaderStage (see ShaderProgram.hpp)
* @return vk flag of the ShaderStage
*/
static vk::ShaderStageFlagBits convertShaderStageFlag(ShaderStage stage);
};
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment