#include "xe_descriptors.hpp" #include #include #include namespace xe { DescriptorSetLayout::Builder &DescriptorSetLayout::Builder::addBinding( uint32_t binding, VkDescriptorType descriptorType, VkShaderStageFlags stageFlags, VkSampler *sampler, 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; layoutBinding.pImmutableSamplers = sampler; bindings[binding] = layoutBinding; return *this; } std::unique_ptr DescriptorSetLayout::Builder::build() const { return std::make_unique(xeDevice, bindings); } DescriptorSetLayout::DescriptorSetLayout( Device &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!"); } } DescriptorSetLayout::~DescriptorSetLayout() { vkDestroyDescriptorSetLayout(xeDevice.device(), descriptorSetLayout, nullptr); } DescriptorPool::Builder &DescriptorPool::Builder::addPoolSize( VkDescriptorType descriptorType, uint32_t count) { poolSizes.push_back({descriptorType, count}); return *this; } DescriptorPool::Builder &DescriptorPool::Builder::setPoolFlags( VkDescriptorPoolCreateFlags flags) { poolFlags = flags; return *this; } DescriptorPool::Builder &DescriptorPool::Builder::setMaxSets(uint32_t count) { maxSets = count; return *this; } std::unique_ptr DescriptorPool::Builder::build() const { return std::make_unique(xeDevice, maxSets, poolFlags, poolSizes); } DescriptorPool::DescriptorPool( Device &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!"); } } DescriptorPool::~DescriptorPool() { vkDestroyDescriptorPool(xeDevice.device(), descriptorPool, nullptr); } bool DescriptorPool::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 DescriptorPool::freeDescriptors(std::vector &descriptors) const { vkFreeDescriptorSets( xeDevice.device(), descriptorPool, static_cast(descriptors.size()), descriptors.data()); } void DescriptorPool::resetPool() { vkResetDescriptorPool(xeDevice.device(), descriptorPool, 0); } DescriptorWriter::DescriptorWriter(DescriptorSetLayout &setLayout, DescriptorPool &pool) : setLayout{setLayout}, pool{pool} {} DescriptorWriter &DescriptorWriter::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; } DescriptorWriter &DescriptorWriter::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; } DescriptorWriter &DescriptorWriter::writeImageArray( uint32_t binding, std::vector *imageInfos) { assert(setLayout.bindings.count(binding) == 1 && "Layout does not contain specified binding"); auto &bindingDescription = setLayout.bindings[binding]; VkWriteDescriptorSet write{}; write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; write.descriptorType = bindingDescription.descriptorType; write.dstBinding = binding; write.dstArrayElement = 0; write.pImageInfo = imageInfos->data(); write.descriptorCount = imageInfos->size(); writes.push_back(write); return *this; } bool DescriptorWriter::build(VkDescriptorSet &set) { bool success = pool.allocateDescriptor(setLayout.getDescriptorSetLayout(), set); if (!success) { return false; } overwrite(set); return true; } void DescriptorWriter::overwrite(VkDescriptorSet &set) { for (auto &write : writes) { write.dstSet = set; } vkUpdateDescriptorSets(pool.xeDevice.device(), writes.size(), writes.data(), 0, nullptr); } }