2022-09-19 01:20:51 +00:00
|
|
|
#include "xe_descriptors.hpp"
|
|
|
|
|
|
|
|
#include <cassert>
|
|
|
|
#include <stdexcept>
|
|
|
|
|
|
|
|
namespace xe {
|
|
|
|
|
|
|
|
XeDescriptorSetLayout::Builder &XeDescriptorSetLayout::Builder::addBinding(
|
|
|
|
uint32_t binding,
|
|
|
|
VkDescriptorType descriptorType,
|
|
|
|
VkShaderStageFlags stageFlags,
|
2022-09-21 02:02:58 +00:00
|
|
|
VkSampler *sampler) {
|
2022-09-19 01:20:51 +00:00
|
|
|
assert(bindings.count(binding) == 0 && "Binding already in use");
|
2022-09-21 02:02:58 +00:00
|
|
|
uint32_t count = 1;
|
2022-09-19 01:20:51 +00:00
|
|
|
VkDescriptorSetLayoutBinding layoutBinding{};
|
|
|
|
layoutBinding.binding = binding;
|
|
|
|
layoutBinding.descriptorType = descriptorType;
|
|
|
|
layoutBinding.descriptorCount = count;
|
|
|
|
layoutBinding.stageFlags = stageFlags;
|
2022-09-21 02:02:58 +00:00
|
|
|
layoutBinding.pImmutableSamplers = sampler;
|
2022-09-19 01:20:51 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|