descriptor set stuff from old engine
This commit is contained in:
@@ -0,0 +1,89 @@
|
|||||||
|
#include "descriptor_pool.hpp"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace sophia {
|
||||||
|
|
||||||
|
DescriptorPool::Builder& DescriptorPool::Builder::addPoolSize(
|
||||||
|
vk::DescriptorType descriptorType, u32 count) {
|
||||||
|
this->poolSizes.push_back({descriptorType, count});
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
DescriptorPool::Builder& DescriptorPool::Builder::setPoolFlags(
|
||||||
|
vk::DescriptorPoolCreateFlags flags) {
|
||||||
|
this->poolFlags = flags;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
DescriptorPool::Builder& DescriptorPool::Builder::setMaxSets(u32 count) {
|
||||||
|
this->maxSets = count;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<DescriptorPool> DescriptorPool::Builder::build() const {
|
||||||
|
return std::make_unique<DescriptorPool>(this->device, this->maxSets,
|
||||||
|
this->poolFlags, this->poolSizes);
|
||||||
|
}
|
||||||
|
|
||||||
|
DescriptorPool::DescriptorPool(
|
||||||
|
Device& device, u32 maxSets, vk::DescriptorPoolCreateFlags poolFlags,
|
||||||
|
const std::vector<vk::DescriptorPoolSize>& poolSizes)
|
||||||
|
: device{device} {
|
||||||
|
vk::DescriptorPoolCreateInfo descriptorPoolInfo{};
|
||||||
|
descriptorPoolInfo.poolSizeCount = static_cast<uint32_t>(poolSizes.size());
|
||||||
|
descriptorPoolInfo.pPoolSizes = poolSizes.data();
|
||||||
|
descriptorPoolInfo.maxSets = maxSets;
|
||||||
|
descriptorPoolInfo.flags = poolFlags;
|
||||||
|
|
||||||
|
vk::Result result = this->device.get()->createDescriptorPool(
|
||||||
|
&descriptorPoolInfo, nullptr, &this->descriptorPool);
|
||||||
|
|
||||||
|
if (result != vk::Result::eSuccess) {
|
||||||
|
log::fatal("failed to create descriptor pool");
|
||||||
|
throw std::runtime_error("failed to create descriptor pool");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DescriptorPool::~DescriptorPool() {
|
||||||
|
this->device.get()->destroyDescriptorPool(this->descriptorPool);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DescriptorPool::allocateDescriptorSet(
|
||||||
|
const vk::DescriptorSetLayout descriptorSetLayout,
|
||||||
|
vk::DescriptorSet& descriptor) const {
|
||||||
|
vk::DescriptorSetAllocateInfo allocInfo{};
|
||||||
|
allocInfo.descriptorPool = descriptorPool;
|
||||||
|
allocInfo.pSetLayouts = &descriptorSetLayout;
|
||||||
|
allocInfo.descriptorSetCount = 1;
|
||||||
|
|
||||||
|
// Might want to create a "DescriptorPoolManager" class that handles this
|
||||||
|
// case, and builds a new pool whenever an old pool fills up. But this is
|
||||||
|
// beyond our current scope
|
||||||
|
vk::Result result =
|
||||||
|
this->device.get()->allocateDescriptorSets(&allocInfo, &descriptor);
|
||||||
|
|
||||||
|
if (result == vk::Result::eSuccess) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DescriptorPool::freeDescriptors(
|
||||||
|
std::vector<vk::DescriptorSet>& descriptors) const {
|
||||||
|
vk::Result result = this->device.get()->freeDescriptorSets(
|
||||||
|
this->descriptorPool, static_cast<u32>(descriptors.size()),
|
||||||
|
descriptors.data());
|
||||||
|
|
||||||
|
if (result != vk::Result::eSuccess) {
|
||||||
|
log::fatal("failed to free descriptor sets");
|
||||||
|
throw std::runtime_error("failed to free descriptor sets");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DescriptorPool::resetPool() {
|
||||||
|
this->device.get()->resetDescriptorPool(this->descriptorPool);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace sophia
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "device.hpp"
|
||||||
|
|
||||||
|
namespace sophia {
|
||||||
|
|
||||||
|
class DescriptorPool {
|
||||||
|
public:
|
||||||
|
DescriptorPool(const DescriptorPool&) = delete;
|
||||||
|
DescriptorPool& operator=(const DescriptorPool&) = delete;
|
||||||
|
|
||||||
|
class Builder {
|
||||||
|
public:
|
||||||
|
Builder(Device& device) : device{device} {}
|
||||||
|
|
||||||
|
Builder& addPoolSize(vk::DescriptorType descriptorType, u32 count);
|
||||||
|
Builder& setPoolFlags(vk::DescriptorPoolCreateFlags flags);
|
||||||
|
Builder& setMaxSets(u32 count);
|
||||||
|
std::unique_ptr<DescriptorPool> build() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Device& device;
|
||||||
|
std::vector<vk::DescriptorPoolSize> poolSizes{};
|
||||||
|
u32 maxSets = 1000;
|
||||||
|
vk::DescriptorPoolCreateFlags poolFlags{};
|
||||||
|
};
|
||||||
|
|
||||||
|
DescriptorPool(Device& device, u32 maxSets,
|
||||||
|
vk::DescriptorPoolCreateFlags poolFlags,
|
||||||
|
const std::vector<vk::DescriptorPoolSize>& poolSizes);
|
||||||
|
~DescriptorPool();
|
||||||
|
|
||||||
|
bool allocateDescriptorSet(const vk::DescriptorSetLayout descriptorSetLayout,
|
||||||
|
vk::DescriptorSet& descriptor) const;
|
||||||
|
|
||||||
|
void freeDescriptors(std::vector<vk::DescriptorSet>& descriptors) const;
|
||||||
|
|
||||||
|
void resetPool();
|
||||||
|
|
||||||
|
const vk::DescriptorPool& get() { return this->descriptorPool; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Device& device;
|
||||||
|
vk::DescriptorPool descriptorPool;
|
||||||
|
|
||||||
|
friend class DescriptorWriter;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace sophia
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
#include "descriptor_set_layout.hpp"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace sophia {
|
||||||
|
|
||||||
|
DescriptorSetLayout::Builder& DescriptorSetLayout::Builder::addBinding(
|
||||||
|
u32 binding, vk::DescriptorType descriptorType,
|
||||||
|
vk::ShaderStageFlags stageFlags, u32 count) {
|
||||||
|
assert(this->bindings.count(binding) == 0 && "binding already in use");
|
||||||
|
|
||||||
|
vk::DescriptorSetLayoutBinding layoutBinding{binding, descriptorType, count,
|
||||||
|
stageFlags};
|
||||||
|
this->bindings[binding] = layoutBinding;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<DescriptorSetLayout> DescriptorSetLayout::Builder::build()
|
||||||
|
const {
|
||||||
|
return std::make_unique<DescriptorSetLayout>(this->device, this->bindings);
|
||||||
|
}
|
||||||
|
|
||||||
|
DescriptorSetLayout::DescriptorSetLayout(
|
||||||
|
Device& device,
|
||||||
|
std::unordered_map<u32, vk::DescriptorSetLayoutBinding> bindings)
|
||||||
|
: device{device}, bindings{bindings} {
|
||||||
|
std::vector<vk::DescriptorSetLayoutBinding> setLayoutBindings{};
|
||||||
|
|
||||||
|
for (auto binding : bindings) {
|
||||||
|
setLayoutBindings.push_back(binding.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
vk::DescriptorSetLayoutCreateInfo layoutCreateInfo{};
|
||||||
|
layoutCreateInfo.bindingCount =
|
||||||
|
static_cast<uint32_t>(setLayoutBindings.size());
|
||||||
|
layoutCreateInfo.pBindings = setLayoutBindings.data();
|
||||||
|
|
||||||
|
vk::Result result = this->device.get()->createDescriptorSetLayout(
|
||||||
|
&layoutCreateInfo, nullptr, &this->layout);
|
||||||
|
|
||||||
|
if (result != vk::Result::eSuccess) {
|
||||||
|
log::fatal("failed to create descriptor pool");
|
||||||
|
throw std::runtime_error("failed to create descriptor set layout");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DescriptorSetLayout::~DescriptorSetLayout() {
|
||||||
|
this->device.get()->destroyDescriptorSetLayout(this->layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace sophia
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "device.hpp"
|
||||||
|
|
||||||
|
namespace sophia {
|
||||||
|
|
||||||
|
class DescriptorSetLayout {
|
||||||
|
public:
|
||||||
|
DescriptorSetLayout(const DescriptorSetLayout&) = delete;
|
||||||
|
DescriptorSetLayout& operator=(const DescriptorSetLayout&) = delete;
|
||||||
|
|
||||||
|
class Builder {
|
||||||
|
public:
|
||||||
|
Builder(Device& device) : device{device} {}
|
||||||
|
|
||||||
|
Builder& addBinding(u32 binding, vk::DescriptorType descriptorType,
|
||||||
|
vk::ShaderStageFlags stageFlags, u32 count = 1);
|
||||||
|
|
||||||
|
std::unique_ptr<DescriptorSetLayout> build() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Device& device;
|
||||||
|
std::unordered_map<u32, vk::DescriptorSetLayoutBinding> bindings{};
|
||||||
|
};
|
||||||
|
|
||||||
|
DescriptorSetLayout(
|
||||||
|
Device& device,
|
||||||
|
std::unordered_map<u32, vk::DescriptorSetLayoutBinding> bindings);
|
||||||
|
~DescriptorSetLayout();
|
||||||
|
|
||||||
|
vk::DescriptorSetLayout getDescriptorSetLayout() const {
|
||||||
|
return this->layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Device& device;
|
||||||
|
vk::DescriptorSetLayout layout;
|
||||||
|
std::unordered_map<u32, vk::DescriptorSetLayoutBinding> bindings;
|
||||||
|
|
||||||
|
friend class DescriptorWriter;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace sophia
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
#include "descriptor_writer.hpp"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace sophia {
|
||||||
|
|
||||||
|
DescriptorWriter::DescriptorWriter(DescriptorSetLayout& setLayout,
|
||||||
|
DescriptorPool& pool)
|
||||||
|
: setLayout{setLayout}, pool{pool} {}
|
||||||
|
|
||||||
|
DescriptorWriter& DescriptorWriter::writeBuffer(
|
||||||
|
u32 binding, vk::DescriptorBufferInfo* bufferInfo) {
|
||||||
|
assert(this->setLayout.bindings.count(binding) == 1 &&
|
||||||
|
"setLayout does not contain specified binding");
|
||||||
|
|
||||||
|
auto& bindingDescription = this->setLayout.bindings[binding];
|
||||||
|
|
||||||
|
assert(bindingDescription.descriptorCount == 1 &&
|
||||||
|
"binding single descriptor info, but binding expects multiple");
|
||||||
|
|
||||||
|
vk::WriteDescriptorSet write{};
|
||||||
|
write.descriptorType = bindingDescription.descriptorType;
|
||||||
|
write.dstBinding = binding;
|
||||||
|
write.pBufferInfo = bufferInfo;
|
||||||
|
write.descriptorCount = 1;
|
||||||
|
|
||||||
|
writes.push_back(write);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
DescriptorWriter& DescriptorWriter::writeImage(
|
||||||
|
u32 binding, vk::DescriptorImageInfo* imageInfo) {
|
||||||
|
assert(this->setLayout.bindings.count(binding) == 1 &&
|
||||||
|
"setLayout does not contain specified binding");
|
||||||
|
|
||||||
|
auto& bindingDescription = this->setLayout.bindings[binding];
|
||||||
|
|
||||||
|
assert(bindingDescription.descriptorCount == 1 &&
|
||||||
|
"binding single descriptor info, but binding expects multiple");
|
||||||
|
|
||||||
|
vk::WriteDescriptorSet write{};
|
||||||
|
write.descriptorType = bindingDescription.descriptorType;
|
||||||
|
write.dstBinding = binding;
|
||||||
|
write.pImageInfo = imageInfo;
|
||||||
|
write.descriptorCount = 1;
|
||||||
|
|
||||||
|
writes.push_back(write);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DescriptorWriter::build(vk::DescriptorSet& set) {
|
||||||
|
bool success =
|
||||||
|
this->pool.allocateDescriptorSet(setLayout.getDescriptorSetLayout(), set);
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
overwrite(set);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DescriptorWriter::overwrite(vk::DescriptorSet& set) {
|
||||||
|
for (auto& write : writes) {
|
||||||
|
write.dstSet = set;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->pool.device.get()->updateDescriptorSets(writes.size(), writes.data(), 0,
|
||||||
|
nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace sophia
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "descriptor_pool.hpp"
|
||||||
|
#include "descriptor_set_layout.hpp"
|
||||||
|
#include "device.hpp"
|
||||||
|
|
||||||
|
namespace sophia {
|
||||||
|
|
||||||
|
class DescriptorWriter {
|
||||||
|
public:
|
||||||
|
DescriptorWriter(DescriptorSetLayout& setLayout, DescriptorPool& pool);
|
||||||
|
|
||||||
|
DescriptorWriter& writeBuffer(u32 binding,
|
||||||
|
vk::DescriptorBufferInfo* bufferInfo);
|
||||||
|
DescriptorWriter& writeImage(u32 binding, vk::DescriptorImageInfo* imageInfo);
|
||||||
|
|
||||||
|
bool build(vk::DescriptorSet& set);
|
||||||
|
void overwrite(vk::DescriptorSet& set);
|
||||||
|
|
||||||
|
private:
|
||||||
|
DescriptorSetLayout& setLayout;
|
||||||
|
DescriptorPool& pool;
|
||||||
|
std::vector<vk::WriteDescriptorSet> writes;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace sophia
|
||||||
Reference in New Issue
Block a user