2023-11-15 17:42:57 +01:00
|
|
|
#include "Descriptor.h"
|
|
|
|
|
#include "Buffer.h"
|
2024-06-09 12:20:04 +02:00
|
|
|
#include "CRC.h"
|
2023-12-02 10:55:00 +01:00
|
|
|
#include "Command.h"
|
2025-08-10 19:16:55 +02:00
|
|
|
#include "Enums.h"
|
2024-04-13 23:51:38 +02:00
|
|
|
#include "Graphics.h"
|
2025-02-28 16:56:51 +09:00
|
|
|
#include "Graphics/Buffer.h"
|
|
|
|
|
#include "Graphics/Descriptor.h"
|
|
|
|
|
#include "Graphics/Enums.h"
|
|
|
|
|
#include "Graphics/Initializer.h"
|
2025-08-10 19:16:55 +02:00
|
|
|
#include "Graphics/Vulkan/Resources.h"
|
2024-07-10 21:07:10 +02:00
|
|
|
#include "RayTracing.h"
|
2024-08-13 22:44:04 +02:00
|
|
|
#include "Texture.h"
|
2025-02-28 16:56:51 +09:00
|
|
|
#include "vulkan/vulkan_core.h"
|
|
|
|
|
#include <algorithm>
|
2025-08-10 19:16:55 +02:00
|
|
|
#include <iostream>
|
2025-05-16 13:04:43 +02:00
|
|
|
#include <mutex>
|
2020-03-09 12:30:07 +01:00
|
|
|
|
2020-03-20 01:27:40 +01:00
|
|
|
using namespace Seele;
|
|
|
|
|
using namespace Seele::Vulkan;
|
|
|
|
|
|
2021-05-06 17:02:10 +02:00
|
|
|
DescriptorLayout::DescriptorLayout(PGraphics graphics, const std::string& name)
|
2024-04-13 23:51:38 +02:00
|
|
|
: Gfx::DescriptorLayout(name), graphics(graphics), layoutHandle(VK_NULL_HANDLE) {}
|
|
|
|
|
|
|
|
|
|
DescriptorLayout::~DescriptorLayout() {
|
2024-05-15 15:27:13 +02:00
|
|
|
graphics->getDestructionManager()->queueResourceForDestruction(std::move(pool));
|
2024-05-29 10:40:35 +02:00
|
|
|
if (layoutHandle != VK_NULL_HANDLE) {
|
|
|
|
|
vkDestroyDescriptorSetLayout(graphics->getDevice(), layoutHandle, nullptr);
|
|
|
|
|
}
|
2020-03-09 12:30:07 +01:00
|
|
|
}
|
|
|
|
|
|
2024-04-13 23:51:38 +02:00
|
|
|
void DescriptorLayout::create() {
|
2024-05-29 10:40:35 +02:00
|
|
|
if (layoutHandle != VK_NULL_HANDLE) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2025-02-28 16:56:51 +09:00
|
|
|
Array<VkDescriptorBindingFlags> bindingFlags;
|
2025-08-08 22:29:54 +02:00
|
|
|
if (std::ranges::contains(descriptorBindings, Gfx::SE_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK, &Gfx::DescriptorBinding::descriptorType)) {
|
2025-02-28 16:56:51 +09:00
|
|
|
bindings.add({
|
|
|
|
|
.binding = 0,
|
2025-08-10 19:16:55 +02:00
|
|
|
.descriptorType =
|
|
|
|
|
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, // although we can pretend that we support inline uniforms, slang does not generate them
|
2025-02-28 16:56:51 +09:00
|
|
|
.descriptorCount = 1,
|
|
|
|
|
.stageFlags = VK_SHADER_STAGE_ALL, // todo
|
2024-05-29 10:40:35 +02:00
|
|
|
.pImmutableSamplers = nullptr,
|
2025-02-28 16:56:51 +09:00
|
|
|
});
|
|
|
|
|
bindingFlags.add(0);
|
|
|
|
|
}
|
|
|
|
|
for (const auto& gfxBinding : descriptorBindings) {
|
2025-08-08 22:29:54 +02:00
|
|
|
if (gfxBinding.descriptorType == Gfx::SE_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK) {
|
2025-02-28 16:56:51 +09:00
|
|
|
mappings[gfxBinding.name] = {
|
|
|
|
|
.binding = 0,
|
|
|
|
|
.constantOffset = constantsSize,
|
|
|
|
|
.constantSize = gfxBinding.uniformLength,
|
2025-08-08 22:29:54 +02:00
|
|
|
.type = cast(gfxBinding.descriptorType),
|
2025-02-28 16:56:51 +09:00
|
|
|
};
|
|
|
|
|
constantsSize += gfxBinding.uniformLength;
|
|
|
|
|
constantsStages |= gfxBinding.shaderStages;
|
|
|
|
|
} else {
|
2025-03-20 20:15:38 +01:00
|
|
|
mappings[gfxBinding.name] = DescriptorMapping{
|
2025-02-28 16:56:51 +09:00
|
|
|
.binding = (uint32)bindings.size(),
|
2025-03-07 21:48:27 +01:00
|
|
|
.type = cast(gfxBinding.descriptorType),
|
2025-02-28 16:56:51 +09:00
|
|
|
};
|
2025-03-20 20:15:38 +01:00
|
|
|
bindings.add(VkDescriptorSetLayoutBinding{
|
2025-02-28 16:56:51 +09:00
|
|
|
.binding = (uint32)bindings.size(),
|
|
|
|
|
.descriptorType = cast(gfxBinding.descriptorType),
|
|
|
|
|
.descriptorCount = gfxBinding.descriptorCount,
|
|
|
|
|
.stageFlags = gfxBinding.shaderStages,
|
|
|
|
|
.pImmutableSamplers = nullptr,
|
|
|
|
|
});
|
|
|
|
|
bindingFlags.add(gfxBinding.bindingFlags);
|
|
|
|
|
}
|
2024-05-29 10:40:35 +02:00
|
|
|
}
|
|
|
|
|
VkDescriptorSetLayoutBindingFlagsCreateInfo bindingFlagsInfo = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO,
|
|
|
|
|
.pNext = nullptr,
|
|
|
|
|
.bindingCount = static_cast<uint32>(bindingFlags.size()),
|
|
|
|
|
.pBindingFlags = bindingFlags.data(),
|
2023-11-10 22:26:47 +01:00
|
|
|
};
|
2024-05-29 10:40:35 +02:00
|
|
|
VkDescriptorSetLayoutCreateInfo createInfo = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
|
|
|
|
.pNext = &bindingFlagsInfo,
|
2024-06-19 10:44:11 +02:00
|
|
|
.flags = 0,
|
2024-05-29 10:40:35 +02:00
|
|
|
.bindingCount = (uint32)bindings.size(),
|
|
|
|
|
.pBindings = bindings.data(),
|
|
|
|
|
};
|
|
|
|
|
VK_CHECK(vkCreateDescriptorSetLayout(graphics->getDevice(), &createInfo, nullptr, &layoutHandle));
|
2020-03-09 12:30:07 +01:00
|
|
|
|
2024-05-29 10:40:35 +02:00
|
|
|
pool = new DescriptorPool(graphics, this);
|
2020-10-03 11:00:10 +02:00
|
|
|
|
2024-05-29 10:40:35 +02:00
|
|
|
hash = CRC::Calculate(bindings.data(), sizeof(VkDescriptorSetLayoutBinding) * bindings.size(), CRC::CRC_32());
|
2020-03-09 12:30:07 +01:00
|
|
|
}
|
|
|
|
|
|
2024-05-29 10:40:35 +02:00
|
|
|
DescriptorPool::DescriptorPool(PGraphics graphics, PDescriptorLayout layout)
|
2024-08-07 21:19:33 +02:00
|
|
|
: CommandBoundResource(graphics, layout->getName()), graphics(graphics), layout(layout) {
|
2024-05-29 10:40:35 +02:00
|
|
|
for (uint32 i = 0; i < cachedHandles.size(); ++i) {
|
|
|
|
|
cachedHandles[i] = nullptr;
|
2021-12-27 15:04:53 +01:00
|
|
|
}
|
2024-05-29 10:40:35 +02:00
|
|
|
|
2025-08-08 22:29:54 +02:00
|
|
|
Map<VkDescriptorType, uint32> perTypeSizes;
|
|
|
|
|
for (uint32 i = 0; i < layout->bindings.size(); ++i) {
|
|
|
|
|
auto& binding = layout->bindings[i];
|
2024-07-10 21:07:10 +02:00
|
|
|
perTypeSizes[binding.descriptorType] += 512;
|
2024-05-29 10:40:35 +02:00
|
|
|
}
|
|
|
|
|
Array<VkDescriptorPoolSize> poolSizes;
|
2025-03-26 13:38:48 +01:00
|
|
|
for (const auto& [type, num] : perTypeSizes) {
|
|
|
|
|
poolSizes.add(VkDescriptorPoolSize{
|
2025-08-08 22:29:54 +02:00
|
|
|
.type = type,
|
2025-03-26 13:38:48 +01:00
|
|
|
.descriptorCount = num,
|
|
|
|
|
});
|
2024-05-29 10:40:35 +02:00
|
|
|
}
|
|
|
|
|
VkDescriptorPoolCreateInfo createInfo = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
|
|
|
|
|
.pNext = nullptr,
|
2024-06-19 10:44:11 +02:00
|
|
|
.flags = 0,
|
2024-05-29 10:40:35 +02:00
|
|
|
.maxSets = maxSets * Gfx::numFramesBuffered,
|
|
|
|
|
.poolSizeCount = (uint32)poolSizes.size(),
|
|
|
|
|
.pPoolSizes = poolSizes.data(),
|
|
|
|
|
};
|
|
|
|
|
VK_CHECK(vkCreateDescriptorPool(graphics->getDevice(), &createInfo, nullptr, &poolHandle));
|
2020-03-13 12:44:33 +01:00
|
|
|
}
|
|
|
|
|
|
2024-04-13 23:51:38 +02:00
|
|
|
DescriptorPool::~DescriptorPool() {
|
2024-06-09 12:20:04 +02:00
|
|
|
for (size_t i = 0; i < maxSets; ++i) {
|
|
|
|
|
if (cachedHandles[i] != nullptr) {
|
2024-10-14 18:14:08 +02:00
|
|
|
graphics->getDestructionManager()->queueResourceForDestruction(std::move(cachedHandles[i]));
|
2024-05-15 15:27:13 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
vkDestroyDescriptorPool(graphics->getDevice(), poolHandle, nullptr);
|
|
|
|
|
if (nextAlloc) {
|
|
|
|
|
delete nextAlloc;
|
|
|
|
|
}
|
2020-06-02 11:46:18 +02:00
|
|
|
}
|
|
|
|
|
|
2025-08-10 19:16:55 +02:00
|
|
|
Gfx::ODescriptorSet DescriptorPool::allocateDescriptorSet() {
|
2024-05-29 10:40:35 +02:00
|
|
|
VkDescriptorSetLayout layoutHandle = layout->getHandle();
|
|
|
|
|
VkDescriptorSetVariableDescriptorCountAllocateInfo setCounts = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO,
|
|
|
|
|
.pNext = nullptr,
|
|
|
|
|
.descriptorSetCount = 1,
|
|
|
|
|
};
|
|
|
|
|
VkDescriptorSetAllocateInfo allocInfo = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
|
|
|
|
|
.pNext = nullptr,
|
|
|
|
|
.descriptorPool = poolHandle,
|
|
|
|
|
.descriptorSetCount = 1,
|
|
|
|
|
.pSetLayouts = &layoutHandle,
|
|
|
|
|
};
|
|
|
|
|
uint32 counts = 0;
|
|
|
|
|
for (const auto& binding : layout->bindings) {
|
|
|
|
|
if (binding.descriptorCount > 0) {
|
|
|
|
|
counts = binding.descriptorCount;
|
|
|
|
|
}
|
2021-12-27 15:04:53 +01:00
|
|
|
}
|
2024-05-29 10:40:35 +02:00
|
|
|
if (layout->bindings.size() > 0) {
|
|
|
|
|
setCounts.pDescriptorCounts = &counts;
|
|
|
|
|
allocInfo.pNext = &setCounts;
|
2024-04-13 23:51:38 +02:00
|
|
|
}
|
2024-05-29 10:40:35 +02:00
|
|
|
for (uint32 setIndex = 0; setIndex < cachedHandles.size(); ++setIndex) {
|
|
|
|
|
if (cachedHandles[setIndex] == nullptr) {
|
2025-08-10 19:16:55 +02:00
|
|
|
cachedHandles[setIndex] = new DescriptorSetHandle(graphics, layout->getName());
|
2024-05-29 10:40:35 +02:00
|
|
|
}
|
2025-08-14 11:06:43 +02:00
|
|
|
if (cachedHandles[setIndex]->isCurrentlyBound() || cachedHandles[setIndex]->isUsed) {
|
2024-05-29 10:40:35 +02:00
|
|
|
// Currently in use, skip
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (cachedHandles[setIndex]->getHandle() == VK_NULL_HANDLE) {
|
|
|
|
|
// If it hasnt been initialized, allocate it
|
2025-08-10 19:16:55 +02:00
|
|
|
VK_CHECK(vkAllocateDescriptorSets(graphics->getDevice(), &allocInfo, &cachedHandles[setIndex]->handle));
|
2025-04-13 14:41:42 +02:00
|
|
|
VkDebugUtilsObjectNameInfoEXT nameInfo = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT,
|
|
|
|
|
.pNext = nullptr,
|
|
|
|
|
.objectType = VK_OBJECT_TYPE_DESCRIPTOR_SET,
|
2025-08-10 19:16:55 +02:00
|
|
|
.objectHandle = (uint64)cachedHandles[setIndex]->getHandle(),
|
2025-04-13 14:41:42 +02:00
|
|
|
.pObjectName = name.c_str(),
|
|
|
|
|
};
|
|
|
|
|
vkSetDebugUtilsObjectNameEXT(graphics->getDevice(), &nameInfo);
|
2024-05-29 10:40:35 +02:00
|
|
|
}
|
2025-08-14 11:06:43 +02:00
|
|
|
cachedHandles[setIndex]->isUsed = true;
|
2024-05-29 10:40:35 +02:00
|
|
|
// Found set, stop searching
|
2025-08-10 19:16:55 +02:00
|
|
|
return new DescriptorSet(graphics, this, cachedHandles[setIndex]);
|
2024-05-29 10:40:35 +02:00
|
|
|
}
|
|
|
|
|
if (nextAlloc == nullptr) {
|
|
|
|
|
nextAlloc = new DescriptorPool(graphics, layout);
|
|
|
|
|
}
|
|
|
|
|
// std::cout << "Out of descriptors, forwarding" << std::endl;
|
|
|
|
|
return nextAlloc->allocateDescriptorSet();
|
|
|
|
|
// throw std::logic_error("Out of descriptor sets");
|
2020-03-13 12:44:33 +01:00
|
|
|
}
|
|
|
|
|
|
2025-08-14 11:06:43 +02:00
|
|
|
void DescriptorPool::reset() {}
|
2020-03-13 12:44:33 +01:00
|
|
|
|
2025-08-10 19:16:55 +02:00
|
|
|
DescriptorSetHandle::DescriptorSetHandle(PGraphics graphics, const std::string& name) : CommandBoundResource(graphics, name) {}
|
|
|
|
|
|
2025-08-14 11:06:43 +02:00
|
|
|
DescriptorSetHandle::~DescriptorSetHandle() {
|
|
|
|
|
graphics->getDestructionManager()->queueResourceForDestruction(std::move(constantsBuffer));
|
|
|
|
|
}
|
2025-08-10 19:16:55 +02:00
|
|
|
|
|
|
|
|
DescriptorSet::DescriptorSet(PGraphics graphics, PDescriptorPool owner, PDescriptorSetHandle setHandle)
|
|
|
|
|
: Gfx::DescriptorSet(owner->getLayout()), setHandle(setHandle),
|
2024-08-13 22:44:04 +02:00
|
|
|
graphics(graphics), owner(owner) {
|
2025-08-08 22:29:54 +02:00
|
|
|
boundResources.resize(owner->getLayout()->bindings.size());
|
2024-08-13 22:44:04 +02:00
|
|
|
for (uint32 i = 0; i < boundResources.size(); ++i) {
|
2025-08-08 22:29:54 +02:00
|
|
|
boundResources[i].resize(owner->getLayout()->bindings[i].descriptorCount);
|
2025-05-16 13:04:43 +02:00
|
|
|
for (size_t x = 0; x < boundResources[i].size(); ++x) {
|
|
|
|
|
boundResources[i][x] = nullptr;
|
|
|
|
|
}
|
2024-06-20 21:57:26 +02:00
|
|
|
}
|
2025-02-28 16:56:51 +09:00
|
|
|
constantData.resize(owner->getLayout()->constantsSize);
|
2024-05-18 21:23:59 +02:00
|
|
|
}
|
2024-04-23 08:11:44 +02:00
|
|
|
|
2025-08-14 11:06:43 +02:00
|
|
|
DescriptorSet::~DescriptorSet() {
|
|
|
|
|
setHandle->isUsed = false;
|
|
|
|
|
}
|
2024-04-13 23:51:38 +02:00
|
|
|
|
2026-04-11 10:15:35 +02:00
|
|
|
void DescriptorSet::updateConstants(const std::string& mappingName, uint32 offset, const void* data) {
|
|
|
|
|
std::memcpy(constantData.data() + owner->getLayout()->mappings[mappingName].constantOffset, (const char*)data + offset,
|
2025-03-25 18:10:32 +01:00
|
|
|
owner->getLayout()->mappings[mappingName].constantSize);
|
2024-04-13 23:51:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-03-25 09:17:08 +01:00
|
|
|
void DescriptorSet::updateBuffer(const std::string& mappingName, uint32 index, Gfx::PShaderBuffer shaderBuffer) {
|
2024-05-29 10:40:35 +02:00
|
|
|
PShaderBuffer vulkanBuffer = shaderBuffer.cast<ShaderBuffer>();
|
2025-03-25 09:17:08 +01:00
|
|
|
const auto& map = owner->getLayout()->mappings[mappingName];
|
2025-03-07 21:48:27 +01:00
|
|
|
uint32 binding = map.binding;
|
2025-04-13 14:41:42 +02:00
|
|
|
// if the buffer is empty
|
|
|
|
|
if (vulkanBuffer->getAlloc() == nullptr)
|
2024-05-29 10:40:35 +02:00
|
|
|
return;
|
2025-05-16 13:04:43 +02:00
|
|
|
|
2024-05-29 10:40:35 +02:00
|
|
|
bufferInfos.add(VkDescriptorBufferInfo{
|
|
|
|
|
.buffer = vulkanBuffer->getHandle(),
|
|
|
|
|
.offset = 0,
|
|
|
|
|
.range = vulkanBuffer->getSize(),
|
2024-06-09 12:20:04 +02:00
|
|
|
});
|
2024-05-29 10:40:35 +02:00
|
|
|
writeDescriptors.add(VkWriteDescriptorSet{
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
|
|
|
|
.pNext = nullptr,
|
2025-08-10 19:16:55 +02:00
|
|
|
.dstSet = setHandle->getHandle(),
|
2024-05-29 10:40:35 +02:00
|
|
|
.dstBinding = binding,
|
2024-09-27 15:57:37 +02:00
|
|
|
.dstArrayElement = index,
|
2024-05-29 10:40:35 +02:00
|
|
|
.descriptorCount = 1,
|
2025-03-07 21:48:27 +01:00
|
|
|
.descriptorType = map.type,
|
2024-10-07 20:14:00 +02:00
|
|
|
.pBufferInfo = &bufferInfos.back(),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
boundResources[binding][index] = vulkanBuffer->getAlloc();
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-08 22:29:54 +02:00
|
|
|
void DescriptorSet::updateBuffer(const std::string& mappingName, uint32 index, Gfx::PVertexBuffer vertexBuffer) {
|
|
|
|
|
PVertexBuffer vulkanBuffer = vertexBuffer.cast<VertexBuffer>();
|
2025-03-25 09:17:08 +01:00
|
|
|
const auto& map = owner->getLayout()->mappings[mappingName];
|
2025-03-07 21:48:27 +01:00
|
|
|
uint32 binding = map.binding;
|
2025-04-13 14:41:42 +02:00
|
|
|
// if the buffer is empty
|
|
|
|
|
if (vulkanBuffer->getAlloc() == nullptr)
|
2024-10-07 20:14:00 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
bufferInfos.add(VkDescriptorBufferInfo{
|
|
|
|
|
.buffer = vulkanBuffer->getHandle(),
|
|
|
|
|
.offset = 0,
|
|
|
|
|
.range = vulkanBuffer->getSize(),
|
|
|
|
|
});
|
|
|
|
|
writeDescriptors.add(VkWriteDescriptorSet{
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
|
|
|
|
.pNext = nullptr,
|
2025-08-10 19:16:55 +02:00
|
|
|
.dstSet = setHandle->getHandle(),
|
2024-10-07 20:14:00 +02:00
|
|
|
.dstBinding = binding,
|
|
|
|
|
.dstArrayElement = index,
|
|
|
|
|
.descriptorCount = 1,
|
2025-03-07 21:48:27 +01:00
|
|
|
.descriptorType = map.type,
|
2024-05-29 10:40:35 +02:00
|
|
|
.pBufferInfo = &bufferInfos.back(),
|
2024-06-09 12:20:04 +02:00
|
|
|
});
|
2024-04-13 23:51:38 +02:00
|
|
|
|
2024-09-27 15:57:37 +02:00
|
|
|
boundResources[binding][index] = vulkanBuffer->getAlloc();
|
2024-04-13 23:51:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-03-25 09:17:08 +01:00
|
|
|
void DescriptorSet::updateBuffer(const std::string& mappingName, uint32 index, Gfx::PIndexBuffer indexBuffer) {
|
2024-07-10 21:07:10 +02:00
|
|
|
PIndexBuffer vulkanBuffer = indexBuffer.cast<IndexBuffer>();
|
2025-03-25 09:17:08 +01:00
|
|
|
const auto& map = owner->getLayout()->mappings[mappingName];
|
2025-08-08 22:29:54 +02:00
|
|
|
uint32 binding = map.binding;
|
|
|
|
|
// if the buffer is empty
|
|
|
|
|
if (vulkanBuffer->getAlloc() == nullptr)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
bufferInfos.add(VkDescriptorBufferInfo{
|
|
|
|
|
.buffer = vulkanBuffer->getHandle(),
|
|
|
|
|
.offset = 0,
|
|
|
|
|
.range = vulkanBuffer->getSize(),
|
|
|
|
|
});
|
|
|
|
|
writeDescriptors.add(VkWriteDescriptorSet{
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
|
|
|
|
.pNext = nullptr,
|
2025-08-10 19:16:55 +02:00
|
|
|
.dstSet = setHandle->getHandle(),
|
2025-08-08 22:29:54 +02:00
|
|
|
.dstBinding = binding,
|
|
|
|
|
.dstArrayElement = index,
|
|
|
|
|
.descriptorCount = 1,
|
|
|
|
|
.descriptorType = map.type,
|
|
|
|
|
.pBufferInfo = &bufferInfos.back(),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
boundResources[binding][index] = vulkanBuffer->getAlloc();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DescriptorSet::updateBuffer(const std::string& mappingName, uint32 index, Gfx::PUniformBuffer uniformBuffer) {
|
|
|
|
|
PUniformBuffer vulkanBuffer = uniformBuffer.cast<UniformBuffer>();
|
|
|
|
|
const auto& map = owner->getLayout()->mappings[mappingName];
|
2025-03-07 21:48:27 +01:00
|
|
|
uint32 binding = map.binding;
|
2025-04-13 14:41:42 +02:00
|
|
|
// if the buffer is empty
|
|
|
|
|
if (vulkanBuffer->getAlloc() == nullptr)
|
2024-07-10 21:07:10 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
bufferInfos.add(VkDescriptorBufferInfo{
|
|
|
|
|
.buffer = vulkanBuffer->getHandle(),
|
|
|
|
|
.offset = 0,
|
|
|
|
|
.range = vulkanBuffer->getSize(),
|
|
|
|
|
});
|
|
|
|
|
writeDescriptors.add(VkWriteDescriptorSet{
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
|
|
|
|
.pNext = nullptr,
|
2025-08-10 19:16:55 +02:00
|
|
|
.dstSet = setHandle->getHandle(),
|
2024-07-10 21:07:10 +02:00
|
|
|
.dstBinding = binding,
|
2024-09-27 15:57:37 +02:00
|
|
|
.dstArrayElement = index,
|
2024-07-10 21:07:10 +02:00
|
|
|
.descriptorCount = 1,
|
2025-03-07 21:48:27 +01:00
|
|
|
.descriptorType = map.type,
|
2024-07-10 21:07:10 +02:00
|
|
|
.pBufferInfo = &bufferInfos.back(),
|
|
|
|
|
});
|
|
|
|
|
|
2024-09-27 15:57:37 +02:00
|
|
|
boundResources[binding][index] = vulkanBuffer->getAlloc();
|
2024-05-06 18:36:16 +02:00
|
|
|
}
|
|
|
|
|
|
2025-03-25 09:17:08 +01:00
|
|
|
void DescriptorSet::updateSampler(const std::string& mappingName, uint32 index, Gfx::PSampler samplerState) {
|
2024-05-29 10:40:35 +02:00
|
|
|
PSampler vulkanSampler = samplerState.cast<Sampler>();
|
2025-03-25 09:17:08 +01:00
|
|
|
const auto& map = owner->getLayout()->mappings[mappingName];
|
2025-03-07 21:48:27 +01:00
|
|
|
uint32 binding = map.binding;
|
2024-09-27 15:57:37 +02:00
|
|
|
if (boundResources[binding][index] == vulkanSampler->getHandle()) {
|
2024-05-29 10:40:35 +02:00
|
|
|
return;
|
2022-04-15 11:19:30 +02:00
|
|
|
}
|
2024-05-29 10:40:35 +02:00
|
|
|
|
|
|
|
|
imageInfos.add(VkDescriptorImageInfo{
|
|
|
|
|
.sampler = vulkanSampler->getSampler(),
|
|
|
|
|
.imageView = VK_NULL_HANDLE,
|
|
|
|
|
.imageLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
2024-06-09 12:20:04 +02:00
|
|
|
});
|
2024-05-29 10:40:35 +02:00
|
|
|
|
2023-11-15 17:42:57 +01:00
|
|
|
writeDescriptors.add(VkWriteDescriptorSet{
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
|
|
|
|
.pNext = nullptr,
|
2025-08-10 19:16:55 +02:00
|
|
|
.dstSet = setHandle->getHandle(),
|
2023-11-15 17:42:57 +01:00
|
|
|
.dstBinding = binding,
|
2024-09-27 15:57:37 +02:00
|
|
|
.dstArrayElement = index,
|
2024-05-29 10:40:35 +02:00
|
|
|
.descriptorCount = 1,
|
2025-03-07 21:48:27 +01:00
|
|
|
.descriptorType = map.type,
|
2024-05-29 10:40:35 +02:00
|
|
|
.pImageInfo = &imageInfos.back(),
|
2024-06-09 12:20:04 +02:00
|
|
|
});
|
2024-05-29 10:40:35 +02:00
|
|
|
|
2024-09-27 15:57:37 +02:00
|
|
|
boundResources[binding][index] = vulkanSampler->getHandle();
|
2024-06-18 19:19:05 +02:00
|
|
|
}
|
|
|
|
|
|
2025-07-04 17:36:40 +02:00
|
|
|
void DescriptorSet::updateTexture(const std::string& mappingName, uint32 index, Gfx::PTextureView texture) {
|
|
|
|
|
PTextureView vulkanTexture = texture.cast<TextureView>();
|
2025-03-25 09:17:08 +01:00
|
|
|
const auto& map = owner->getLayout()->mappings[mappingName];
|
2025-03-07 21:48:27 +01:00
|
|
|
uint32 binding = map.binding;
|
2025-07-04 17:36:40 +02:00
|
|
|
if (boundResources[binding][index] == vulkanTexture->getSource()) {
|
2024-09-27 15:57:37 +02:00
|
|
|
return;
|
2024-06-20 21:57:26 +02:00
|
|
|
}
|
2024-09-27 15:57:37 +02:00
|
|
|
|
|
|
|
|
// It is assumed that the image is in the correct layout
|
|
|
|
|
imageInfos.add(VkDescriptorImageInfo{
|
|
|
|
|
.sampler = VK_NULL_HANDLE,
|
|
|
|
|
.imageView = vulkanTexture->getView(),
|
|
|
|
|
.imageLayout = cast(vulkanTexture->getLayout()),
|
|
|
|
|
});
|
|
|
|
|
writeDescriptors.add(VkWriteDescriptorSet{
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
|
|
|
|
.pNext = nullptr,
|
2025-08-10 19:16:55 +02:00
|
|
|
.dstSet = setHandle->getHandle(),
|
2024-09-27 15:57:37 +02:00
|
|
|
.dstBinding = binding,
|
|
|
|
|
.dstArrayElement = index,
|
|
|
|
|
.descriptorCount = 1,
|
2025-03-07 21:48:27 +01:00
|
|
|
.descriptorType = map.type,
|
2024-09-27 15:57:37 +02:00
|
|
|
.pImageInfo = &imageInfos.back(),
|
|
|
|
|
});
|
|
|
|
|
|
2025-07-04 17:36:40 +02:00
|
|
|
boundResources[binding][index] = vulkanTexture->getSource();
|
2024-06-20 21:57:26 +02:00
|
|
|
}
|
|
|
|
|
|
2025-03-25 09:17:08 +01:00
|
|
|
void DescriptorSet::updateAccelerationStructure(const std::string& mappingName, uint32 index, Gfx::PTopLevelAS as) {
|
2024-07-10 21:07:10 +02:00
|
|
|
auto tlas = as.cast<TopLevelAS>();
|
2025-03-25 09:17:08 +01:00
|
|
|
uint32 binding = owner->getLayout()->mappings[mappingName].binding;
|
2024-07-10 21:07:10 +02:00
|
|
|
accelerationInfos.add(VkWriteDescriptorSetAccelerationStructureKHR{
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR,
|
|
|
|
|
.pNext = nullptr,
|
|
|
|
|
.accelerationStructureCount = 1,
|
2024-07-12 13:33:52 +02:00
|
|
|
.pAccelerationStructures = &tlas->handle,
|
2024-07-10 21:07:10 +02:00
|
|
|
});
|
|
|
|
|
writeDescriptors.add(VkWriteDescriptorSet{
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
|
|
|
|
.pNext = &accelerationInfos.back(),
|
2025-08-10 19:16:55 +02:00
|
|
|
.dstSet = setHandle->getHandle(),
|
2024-07-10 21:07:10 +02:00
|
|
|
.dstBinding = binding,
|
2024-09-27 15:57:37 +02:00
|
|
|
.dstArrayElement = index,
|
2024-07-10 21:07:10 +02:00
|
|
|
.descriptorCount = 1,
|
|
|
|
|
.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR,
|
|
|
|
|
});
|
|
|
|
|
}
|
2024-06-20 21:57:26 +02:00
|
|
|
|
2024-04-13 23:51:38 +02:00
|
|
|
void DescriptorSet::writeChanges() {
|
2025-03-07 21:48:27 +01:00
|
|
|
if (constantData.size() > 0) {
|
2025-08-14 11:06:43 +02:00
|
|
|
if (setHandle->constantsBuffer != nullptr) {
|
|
|
|
|
graphics->getDestructionManager()->queueResourceForDestruction(std::move(setHandle->constantsBuffer));
|
2025-03-07 21:48:27 +01:00
|
|
|
}
|
2025-08-14 11:06:43 +02:00
|
|
|
setHandle->constantsBuffer = new BufferAllocation(graphics, owner->getLayout()->getName(),
|
2025-03-07 21:48:27 +01:00
|
|
|
VkBufferCreateInfo{
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
|
|
|
|
.pNext = nullptr,
|
|
|
|
|
.size = constantData.size(),
|
|
|
|
|
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
|
|
|
|
|
},
|
|
|
|
|
VmaAllocationCreateInfo{
|
|
|
|
|
.usage = VMA_MEMORY_USAGE_AUTO,
|
|
|
|
|
},
|
|
|
|
|
Gfx::QueueType::GRAPHICS);
|
2025-08-14 11:06:43 +02:00
|
|
|
setHandle->constantsBuffer->updateContents(0, constantData.size(), constantData.data());
|
|
|
|
|
setHandle->constantsBuffer->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
|
2025-03-07 21:48:27 +01:00
|
|
|
Gfx::SE_ACCESS_UNIFORM_READ_BIT, Gfx::SE_PIPELINE_STAGE_ALL_COMMANDS_BIT);
|
|
|
|
|
bufferInfos.add(VkDescriptorBufferInfo{
|
2025-08-14 11:06:43 +02:00
|
|
|
.buffer = setHandle->constantsBuffer->buffer,
|
2025-03-07 21:48:27 +01:00
|
|
|
.offset = 0,
|
2025-08-14 11:06:43 +02:00
|
|
|
.range = setHandle->constantsBuffer->size,
|
2025-03-07 21:48:27 +01:00
|
|
|
});
|
|
|
|
|
writeDescriptors.add(VkWriteDescriptorSet{
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
|
|
|
|
.pNext = nullptr,
|
2025-08-10 19:16:55 +02:00
|
|
|
.dstSet = setHandle->getHandle(),
|
2025-03-07 21:48:27 +01:00
|
|
|
.dstBinding = 0,
|
|
|
|
|
.dstArrayElement = 0,
|
|
|
|
|
.descriptorCount = 1,
|
|
|
|
|
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
|
|
|
|
.pBufferInfo = &bufferInfos.back(),
|
|
|
|
|
});
|
|
|
|
|
}
|
2025-03-25 18:10:32 +01:00
|
|
|
|
2024-05-29 10:40:35 +02:00
|
|
|
if (writeDescriptors.size() > 0) {
|
2025-08-10 19:16:55 +02:00
|
|
|
if (setHandle->isCurrentlyBound()) {
|
2024-05-29 10:40:35 +02:00
|
|
|
std::cout << "Descriptor currently bound, allocate a new one instead" << std::endl;
|
2025-08-10 19:16:55 +02:00
|
|
|
assert(!setHandle->isCurrentlyBound());
|
2024-05-29 10:40:35 +02:00
|
|
|
}
|
|
|
|
|
vkUpdateDescriptorSets(graphics->getDevice(), (uint32)writeDescriptors.size(), writeDescriptors.data(), 0, nullptr);
|
|
|
|
|
writeDescriptors.clear();
|
|
|
|
|
imageInfos.clear();
|
|
|
|
|
bufferInfos.clear();
|
2024-04-13 23:51:38 +02:00
|
|
|
}
|
2020-03-13 12:44:33 +01:00
|
|
|
}
|
|
|
|
|
|
2024-04-23 08:11:44 +02:00
|
|
|
PipelineLayout::PipelineLayout(PGraphics graphics, const std::string& name, Gfx::PPipelineLayout baseLayout)
|
|
|
|
|
: Gfx::PipelineLayout(name, baseLayout), graphics(graphics), layoutHandle(VK_NULL_HANDLE) {}
|
2021-04-13 23:09:16 +02:00
|
|
|
|
2024-04-13 23:51:38 +02:00
|
|
|
PipelineLayout::~PipelineLayout() {}
|
2020-03-13 12:44:33 +01:00
|
|
|
|
2024-05-01 19:39:57 +02:00
|
|
|
std::mutex layoutLock;
|
2024-04-13 23:51:38 +02:00
|
|
|
Map<uint32, VkPipelineLayout> cachedLayouts;
|
2020-10-03 11:00:10 +02:00
|
|
|
|
2024-04-13 23:51:38 +02:00
|
|
|
void PipelineLayout::create() {
|
2025-03-26 13:38:48 +01:00
|
|
|
for (const auto& [_, desc] : descriptorSetLayouts) {
|
2024-05-29 10:40:35 +02:00
|
|
|
PDescriptorLayout layout = desc.cast<DescriptorLayout>();
|
|
|
|
|
layout->create();
|
|
|
|
|
uint32 parameterIndex = parameterMapping[layout->getName()];
|
2024-06-09 12:20:04 +02:00
|
|
|
if (parameterIndex >= vulkanDescriptorLayouts.size()) {
|
2024-05-29 10:40:35 +02:00
|
|
|
vulkanDescriptorLayouts.resize(parameterIndex + 1);
|
|
|
|
|
}
|
|
|
|
|
vulkanDescriptorLayouts[parameterIndex] = layout->getHandle();
|
2024-04-23 23:21:30 +02:00
|
|
|
}
|
2020-03-13 12:44:33 +01:00
|
|
|
|
2024-05-29 10:40:35 +02:00
|
|
|
Array<VkPushConstantRange> vkPushConstants(pushConstants.size());
|
|
|
|
|
for (size_t i = 0; i < pushConstants.size(); i++) {
|
|
|
|
|
vkPushConstants[i].offset = pushConstants[i].offset;
|
|
|
|
|
vkPushConstants[i].size = pushConstants[i].size;
|
|
|
|
|
vkPushConstants[i].stageFlags = pushConstants[i].stageFlags;
|
|
|
|
|
}
|
2020-03-13 12:44:33 +01:00
|
|
|
|
2024-05-29 10:40:35 +02:00
|
|
|
VkPipelineLayoutCreateInfo createInfo = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
|
|
|
|
.pNext = nullptr,
|
|
|
|
|
.flags = 0,
|
|
|
|
|
.setLayoutCount = (uint32)vulkanDescriptorLayouts.size(),
|
|
|
|
|
.pSetLayouts = vulkanDescriptorLayouts.data(),
|
|
|
|
|
.pushConstantRangeCount = (uint32)vkPushConstants.size(),
|
|
|
|
|
.pPushConstantRanges = vkPushConstants.data(),
|
|
|
|
|
};
|
2020-10-03 11:00:10 +02:00
|
|
|
|
2024-06-09 12:20:04 +02:00
|
|
|
layoutHash =
|
|
|
|
|
CRC::Calculate(createInfo.pPushConstantRanges, sizeof(VkPushConstantRange) * createInfo.pushConstantRangeCount, CRC::CRC_32());
|
|
|
|
|
layoutHash =
|
|
|
|
|
CRC::Calculate(createInfo.pSetLayouts, sizeof(VkDescriptorSetLayout) * createInfo.setLayoutCount, CRC::CRC_32(), layoutHash);
|
2024-04-13 23:51:38 +02:00
|
|
|
|
2024-05-29 10:40:35 +02:00
|
|
|
std::unique_lock l(layoutLock);
|
|
|
|
|
if (cachedLayouts.contains(layoutHash)) {
|
|
|
|
|
// std::cout << "New Layout" << std::endl;
|
|
|
|
|
layoutHandle = cachedLayouts[layoutHash];
|
|
|
|
|
return;
|
|
|
|
|
}
|
2024-04-13 23:51:38 +02:00
|
|
|
|
2024-05-29 10:40:35 +02:00
|
|
|
VK_CHECK(vkCreatePipelineLayout(graphics->getDevice(), &createInfo, nullptr, &layoutHandle));
|
|
|
|
|
cachedLayouts[layoutHash] = layoutHandle;
|
2020-10-03 11:00:10 +02:00
|
|
|
}
|