#include "xe_descriptors.hpp" #include #include 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::Builder::build() const { return std::make_unique(xeDevice, bindings); } XeDescriptorSetLayout::XeDescriptorSetLayout( XeDevice &xeDevice, std::unordered_map bindings) : xeDevice{xeDevice}, bindings{bindings} { std::vector 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(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::Builder::build() const { return std::make_unique(xeDevice, maxSets, poolFlags, poolSizes); } XeDescriptorPool::XeDescriptorPool( XeDevice &xeDevice, uint32_t maxSets, VkDescriptorPoolCreateFlags poolFlags, const std::vector &poolSizes) : xeDevice{xeDevice} { VkDescriptorPoolCreateInfo descriptorPoolInfo{}; descriptorPoolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; descriptorPoolInfo.poolSizeCount = static_cast(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 &descriptors) const { vkFreeDescriptorSets( xeDevice.device(), descriptorPool, static_cast(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); } }