summaryrefslogtreecommitdiff
path: root/engine/xe_descriptors.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engine/xe_descriptors.cpp')
-rw-r--r--engine/xe_descriptors.cpp183
1 files changed, 183 insertions, 0 deletions
diff --git a/engine/xe_descriptors.cpp b/engine/xe_descriptors.cpp
new file mode 100644
index 0000000..ef6dc2c
--- /dev/null
+++ b/engine/xe_descriptors.cpp
@@ -0,0 +1,183 @@
+#include "xe_descriptors.hpp"
+
+#include <cassert>
+#include <stdexcept>
+
+namespace xe {
+
+XeDescriptorSetLayout::Builder &XeDescriptorSetLayout::Builder::addBinding(
+ uint32_t binding,
+ VkDescriptorType descriptorType,
+ VkShaderStageFlags stageFlags,
+ uint32_t count) {
+ assert(bindings.count(binding) == 0 && "Binding already in use");
+ VkDescriptorSetLayoutBinding layoutBinding{};
+ layoutBinding.binding = binding;
+ layoutBinding.descriptorType = descriptorType;
+ layoutBinding.descriptorCount = count;
+ layoutBinding.stageFlags = stageFlags;
+ bindings[binding] = layoutBinding;
+ return *this;
+}
+
+std::unique_ptr<XeDescriptorSetLayout> XeDescriptorSetLayout::Builder::build() const {
+ return std::make_unique<XeDescriptorSetLayout>(xeDevice, bindings);
+}
+
+XeDescriptorSetLayout::XeDescriptorSetLayout(
+ XeDevice &xeDevice, std::unordered_map<uint32_t, VkDescriptorSetLayoutBinding> bindings)
+ : xeDevice{xeDevice}, bindings{bindings} {
+ std::vector<VkDescriptorSetLayoutBinding> setLayoutBindings{};
+ for (auto kv : bindings) {
+ setLayoutBindings.push_back(kv.second);
+ }
+
+ VkDescriptorSetLayoutCreateInfo descriptorSetLayoutInfo{};
+ descriptorSetLayoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
+ descriptorSetLayoutInfo.bindingCount = static_cast<uint32_t>(setLayoutBindings.size());
+ descriptorSetLayoutInfo.pBindings = setLayoutBindings.data();
+
+ if (vkCreateDescriptorSetLayout(
+ xeDevice.device(),
+ &descriptorSetLayoutInfo,
+ nullptr,
+ &descriptorSetLayout) != VK_SUCCESS) {
+ throw std::runtime_error("failed to create descriptor set layout!");
+ }
+}
+
+XeDescriptorSetLayout::~XeDescriptorSetLayout() {
+ vkDestroyDescriptorSetLayout(xeDevice.device(), descriptorSetLayout, nullptr);
+}
+
+XeDescriptorPool::Builder &XeDescriptorPool::Builder::addPoolSize(
+ VkDescriptorType descriptorType, uint32_t count) {
+ poolSizes.push_back({descriptorType, count});
+ return *this;
+}
+
+XeDescriptorPool::Builder &XeDescriptorPool::Builder::setPoolFlags(
+ VkDescriptorPoolCreateFlags flags) {
+ poolFlags = flags;
+ return *this;
+}
+XeDescriptorPool::Builder &XeDescriptorPool::Builder::setMaxSets(uint32_t count) {
+ maxSets = count;
+ return *this;
+}
+
+std::unique_ptr<XeDescriptorPool> XeDescriptorPool::Builder::build() const {
+ return std::make_unique<XeDescriptorPool>(xeDevice, maxSets, poolFlags, poolSizes);
+}
+
+XeDescriptorPool::XeDescriptorPool(
+ XeDevice &xeDevice,
+ uint32_t maxSets,
+ VkDescriptorPoolCreateFlags poolFlags,
+ const std::vector<VkDescriptorPoolSize> &poolSizes)
+ : xeDevice{xeDevice} {
+ VkDescriptorPoolCreateInfo descriptorPoolInfo{};
+ descriptorPoolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
+ descriptorPoolInfo.poolSizeCount = static_cast<uint32_t>(poolSizes.size());
+ descriptorPoolInfo.pPoolSizes = poolSizes.data();
+ descriptorPoolInfo.maxSets = maxSets;
+ descriptorPoolInfo.flags = poolFlags;
+
+ if (vkCreateDescriptorPool(xeDevice.device(), &descriptorPoolInfo, nullptr, &descriptorPool) !=
+ VK_SUCCESS) {
+ throw std::runtime_error("failed to create descriptor pool!");
+ }
+}
+
+XeDescriptorPool::~XeDescriptorPool() {
+ vkDestroyDescriptorPool(xeDevice.device(), descriptorPool, nullptr);
+}
+
+bool XeDescriptorPool::allocateDescriptor(
+ const VkDescriptorSetLayout descriptorSetLayout, VkDescriptorSet &descriptor) const {
+ VkDescriptorSetAllocateInfo allocInfo{};
+ allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
+ allocInfo.descriptorPool = descriptorPool;
+ allocInfo.pSetLayouts = &descriptorSetLayout;
+ allocInfo.descriptorSetCount = 1;
+
+ if (vkAllocateDescriptorSets(xeDevice.device(), &allocInfo, &descriptor) != VK_SUCCESS) {
+ return false;
+ }
+ return true;
+}
+
+void XeDescriptorPool::freeDescriptors(std::vector<VkDescriptorSet> &descriptors) const {
+ vkFreeDescriptorSets(
+ xeDevice.device(),
+ descriptorPool,
+ static_cast<uint32_t>(descriptors.size()),
+ descriptors.data());
+}
+
+void XeDescriptorPool::resetPool() {
+ vkResetDescriptorPool(xeDevice.device(), descriptorPool, 0);
+}
+
+XeDescriptorWriter::XeDescriptorWriter(XeDescriptorSetLayout &setLayout, XeDescriptorPool &pool)
+ : setLayout{setLayout}, pool{pool} {}
+
+XeDescriptorWriter &XeDescriptorWriter::writeBuffer(
+ uint32_t binding, VkDescriptorBufferInfo *bufferInfo) {
+ assert(setLayout.bindings.count(binding) == 1 && "Layout does not contain specified binding");
+
+ auto &bindingDescription = setLayout.bindings[binding];
+
+ assert(
+ bindingDescription.descriptorCount == 1 &&
+ "Binding single descriptor info, but binding expects multiple");
+
+ VkWriteDescriptorSet write{};
+ write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+ write.descriptorType = bindingDescription.descriptorType;
+ write.dstBinding = binding;
+ write.pBufferInfo = bufferInfo;
+ write.descriptorCount = 1;
+
+ writes.push_back(write);
+ return *this;
+}
+
+XeDescriptorWriter &XeDescriptorWriter::writeImage(
+ uint32_t binding, VkDescriptorImageInfo *imageInfo) {
+ assert(setLayout.bindings.count(binding) == 1 && "Layout does not contain specified binding");
+
+ auto &bindingDescription = setLayout.bindings[binding];
+
+ assert(
+ bindingDescription.descriptorCount == 1 &&
+ "Binding single descriptor info, but binding expects multiple");
+
+ VkWriteDescriptorSet write{};
+ write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+ write.descriptorType = bindingDescription.descriptorType;
+ write.dstBinding = binding;
+ write.pImageInfo = imageInfo;
+ write.descriptorCount = 1;
+
+ writes.push_back(write);
+ return *this;
+}
+
+bool XeDescriptorWriter::build(VkDescriptorSet &set) {
+ bool success = pool.allocateDescriptor(setLayout.getDescriptorSetLayout(), set);
+ if (!success) {
+ return false;
+ }
+ overwrite(set);
+ return true;
+}
+
+void XeDescriptorWriter::overwrite(VkDescriptorSet &set) {
+ for (auto &write : writes) {
+ write.dstSet = set;
+ }
+ vkUpdateDescriptorSets(pool.xeDevice.device(), writes.size(), writes.data(), 0, nullptr);
+}
+
+} \ No newline at end of file