2020-08-11 21:23:20 +02:00
|
|
|
#include "VulkanDescriptorSets.h"
|
2020-03-09 12:30:07 +01:00
|
|
|
#include "VulkanGraphicsResources.h"
|
|
|
|
|
#include "VulkanGraphicsEnums.h"
|
|
|
|
|
#include "VulkanGraphics.h"
|
|
|
|
|
#include "VulkanInitializer.h"
|
|
|
|
|
|
2020-03-20 01:27:40 +01:00
|
|
|
using namespace Seele;
|
|
|
|
|
using namespace Seele::Vulkan;
|
|
|
|
|
|
2020-10-03 11:00:10 +02:00
|
|
|
DescriptorLayout::DescriptorLayout(PGraphics graphics)
|
|
|
|
|
: graphics(graphics)
|
|
|
|
|
, layoutHandle(VK_NULL_HANDLE)
|
|
|
|
|
{
|
|
|
|
|
}
|
2020-03-20 01:27:40 +01:00
|
|
|
DescriptorLayout::~DescriptorLayout()
|
2020-03-09 12:30:07 +01:00
|
|
|
{
|
|
|
|
|
if (layoutHandle != VK_NULL_HANDLE)
|
|
|
|
|
{
|
|
|
|
|
vkDestroyDescriptorSetLayout(graphics->getDevice(), layoutHandle, nullptr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-20 01:27:40 +01:00
|
|
|
void DescriptorLayout::create()
|
2020-03-09 12:30:07 +01:00
|
|
|
{
|
|
|
|
|
if (layoutHandle != VK_NULL_HANDLE)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
bindings.resize(descriptorBindings.size());
|
|
|
|
|
for (size_t i = 0; i < descriptorBindings.size(); ++i)
|
|
|
|
|
{
|
2020-04-12 15:47:19 +02:00
|
|
|
VkDescriptorSetLayoutBinding &binding = bindings[i];
|
|
|
|
|
const Gfx::DescriptorBinding &rhiBinding = descriptorBindings[i];
|
2020-03-09 12:30:07 +01:00
|
|
|
binding.binding = rhiBinding.binding;
|
|
|
|
|
binding.descriptorCount = rhiBinding.descriptorCount;
|
|
|
|
|
binding.descriptorType = cast(rhiBinding.descriptorType);
|
|
|
|
|
binding.stageFlags = rhiBinding.shaderStages;
|
|
|
|
|
binding.pImmutableSamplers = nullptr;
|
|
|
|
|
}
|
|
|
|
|
VkDescriptorSetLayoutCreateInfo createInfo =
|
|
|
|
|
init::DescriptorSetLayoutCreateInfo(bindings.data(), bindings.size());
|
|
|
|
|
VK_CHECK(vkCreateDescriptorSetLayout(graphics->getDevice(), &createInfo, nullptr, &layoutHandle));
|
|
|
|
|
|
2020-03-20 01:27:40 +01:00
|
|
|
allocator = new DescriptorAllocator(graphics, *this);
|
2020-10-03 11:00:10 +02:00
|
|
|
|
|
|
|
|
boost::crc_32_type result;
|
|
|
|
|
result.process_bytes(bindings.data(), sizeof(VkDescriptorSetLayoutBinding) * bindings.size());
|
|
|
|
|
hash = result.checksum();
|
2020-03-09 12:30:07 +01:00
|
|
|
}
|
|
|
|
|
|
2020-03-20 01:27:40 +01:00
|
|
|
PipelineLayout::~PipelineLayout()
|
2020-03-13 12:44:33 +01:00
|
|
|
{
|
|
|
|
|
if (layoutHandle != VK_NULL_HANDLE)
|
|
|
|
|
{
|
|
|
|
|
vkDestroyPipelineLayout(graphics->getDevice(), layoutHandle, nullptr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-03 11:00:10 +02:00
|
|
|
static Map<uint32, VkPipelineLayout> layoutCache;
|
|
|
|
|
|
2020-03-20 01:27:40 +01:00
|
|
|
void PipelineLayout::create()
|
2020-03-09 12:30:07 +01:00
|
|
|
{
|
|
|
|
|
vulkanDescriptorLayouts.resize(descriptorSetLayouts.size());
|
|
|
|
|
for (size_t i = 0; i < descriptorSetLayouts.size(); ++i)
|
|
|
|
|
{
|
2020-10-03 11:00:10 +02:00
|
|
|
// There could be unused descriptor set indices
|
|
|
|
|
if(descriptorSetLayouts[i] == nullptr)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2020-03-20 01:27:40 +01:00
|
|
|
PDescriptorLayout layout = descriptorSetLayouts[i].cast<DescriptorLayout>();
|
2020-03-09 19:22:21 +01:00
|
|
|
layout->create();
|
|
|
|
|
vulkanDescriptorLayouts[i] = layout->getHandle();
|
2020-03-09 12:30:07 +01:00
|
|
|
}
|
2020-10-03 11:00:10 +02:00
|
|
|
|
2020-03-09 19:22:21 +01:00
|
|
|
VkPipelineLayoutCreateInfo createInfo =
|
|
|
|
|
init::PipelineLayoutCreateInfo(vulkanDescriptorLayouts.data(), vulkanDescriptorLayouts.size());
|
|
|
|
|
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;
|
2020-03-13 12:44:33 +01:00
|
|
|
vkPushConstants[i].stageFlags = cast((VkShaderStageFlagBits)pushConstants[i].stageFlags);
|
2020-03-09 19:22:21 +01:00
|
|
|
}
|
|
|
|
|
createInfo.pushConstantRangeCount = vkPushConstants.size();
|
|
|
|
|
createInfo.pPushConstantRanges = vkPushConstants.data();
|
2020-03-13 12:44:33 +01:00
|
|
|
|
2020-08-06 00:54:43 +02:00
|
|
|
boost::crc_32_type result;
|
2020-10-03 11:00:10 +02:00
|
|
|
result.process_bytes(createInfo.pPushConstantRanges, sizeof(VkPushConstantRange) * createInfo.pushConstantRangeCount);
|
|
|
|
|
result.process_bytes(createInfo.pSetLayouts, sizeof(VkDescriptorSetLayout) * createInfo.setLayoutCount);
|
2020-08-06 00:54:43 +02:00
|
|
|
layoutHash = result.checksum();
|
2020-10-03 11:00:10 +02:00
|
|
|
|
|
|
|
|
if(layoutCache[layoutHash] != VK_NULL_HANDLE)
|
|
|
|
|
{
|
|
|
|
|
layoutHandle = layoutCache[layoutHash];
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VK_CHECK(vkCreatePipelineLayout(graphics->getDevice(), &createInfo, nullptr, &layoutHandle));
|
|
|
|
|
layoutCache[layoutHash] = layoutHandle;
|
2020-03-13 12:44:33 +01:00
|
|
|
}
|
|
|
|
|
|
2020-06-02 11:46:18 +02:00
|
|
|
void PipelineLayout::reset()
|
|
|
|
|
{
|
|
|
|
|
vkDestroyPipelineLayout(graphics->getDevice(), layoutHandle, nullptr);
|
|
|
|
|
descriptorSetLayouts.clear();
|
|
|
|
|
pushConstants.clear();
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-20 01:27:40 +01:00
|
|
|
DescriptorSet::~DescriptorSet()
|
2020-03-13 12:44:33 +01:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-20 01:27:40 +01:00
|
|
|
void DescriptorSet::updateBuffer(uint32_t binding, Gfx::PUniformBuffer uniformBuffer)
|
2020-03-13 12:44:33 +01:00
|
|
|
{
|
2020-03-20 01:27:40 +01:00
|
|
|
PUniformBuffer vulkanBuffer = uniformBuffer.cast<UniformBuffer>();
|
2020-10-14 01:49:43 +02:00
|
|
|
UniformBuffer* cachedBuffer = reinterpret_cast<UniformBuffer*>(cachedData[Gfx::currentFrameIndex][binding]);
|
2020-10-03 11:00:10 +02:00
|
|
|
if(vulkanBuffer->isDataEquals(cachedBuffer))
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
2020-10-14 01:49:43 +02:00
|
|
|
bufferInfos.add(init::DescriptorBufferInfo(vulkanBuffer->getHandle(), 0, vulkanBuffer->getSize()));
|
2020-03-13 12:44:33 +01:00
|
|
|
|
2020-10-14 01:49:43 +02:00
|
|
|
VkWriteDescriptorSet writeDescriptor = init::WriteDescriptorSet(setHandle[Gfx::currentFrameIndex], VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, binding, &bufferInfos.back());
|
2020-03-13 12:44:33 +01:00
|
|
|
writeDescriptors.add(writeDescriptor);
|
2020-10-03 11:00:10 +02:00
|
|
|
|
2020-10-14 01:49:43 +02:00
|
|
|
cachedData[Gfx::currentFrameIndex][binding] = vulkanBuffer.getHandle();
|
2020-03-13 12:44:33 +01:00
|
|
|
}
|
|
|
|
|
|
2020-03-20 01:27:40 +01:00
|
|
|
void DescriptorSet::updateBuffer(uint32_t binding, Gfx::PStructuredBuffer uniformBuffer)
|
2020-03-13 12:44:33 +01:00
|
|
|
{
|
2020-03-20 01:27:40 +01:00
|
|
|
PStructuredBuffer vulkanBuffer = uniformBuffer.cast<StructuredBuffer>();
|
2020-10-14 01:49:43 +02:00
|
|
|
StructuredBuffer* cachedBuffer = reinterpret_cast<StructuredBuffer*>(cachedData[Gfx::currentFrameIndex][binding]);
|
2020-10-03 11:00:10 +02:00
|
|
|
if(vulkanBuffer.getHandle() == cachedBuffer)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
2020-10-14 01:49:43 +02:00
|
|
|
bufferInfos.add(init::DescriptorBufferInfo(vulkanBuffer->getHandle(), 0, vulkanBuffer->getSize()));
|
2020-03-13 12:44:33 +01:00
|
|
|
|
2020-10-14 01:49:43 +02:00
|
|
|
VkWriteDescriptorSet writeDescriptor = init::WriteDescriptorSet(setHandle[Gfx::currentFrameIndex], VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, binding, &bufferInfos.back());
|
2020-03-13 12:44:33 +01:00
|
|
|
writeDescriptors.add(writeDescriptor);
|
2020-10-03 11:00:10 +02:00
|
|
|
|
2020-10-14 01:49:43 +02:00
|
|
|
cachedData[Gfx::currentFrameIndex][binding] = vulkanBuffer.getHandle();
|
2020-03-13 12:44:33 +01:00
|
|
|
}
|
|
|
|
|
|
2020-03-20 01:27:40 +01:00
|
|
|
void DescriptorSet::updateSampler(uint32_t binding, Gfx::PSamplerState samplerState)
|
2020-03-13 12:44:33 +01:00
|
|
|
{
|
2020-03-20 01:27:40 +01:00
|
|
|
PSamplerState vulkanSampler = samplerState.cast<SamplerState>();
|
2020-10-14 01:49:43 +02:00
|
|
|
SamplerState* cachedSampler = reinterpret_cast<SamplerState*>(cachedData[Gfx::currentFrameIndex][binding]);
|
2020-10-03 11:00:10 +02:00
|
|
|
if(vulkanSampler.getHandle() == cachedSampler)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
2020-03-13 12:44:33 +01:00
|
|
|
VkDescriptorImageInfo imageInfo =
|
|
|
|
|
init::DescriptorImageInfo(
|
|
|
|
|
vulkanSampler->sampler,
|
|
|
|
|
VK_NULL_HANDLE,
|
2020-08-11 22:38:19 +02:00
|
|
|
VK_IMAGE_LAYOUT_UNDEFINED);
|
2020-03-13 12:44:33 +01:00
|
|
|
imageInfos.add(imageInfo);
|
|
|
|
|
|
2020-10-14 01:49:43 +02:00
|
|
|
VkWriteDescriptorSet writeDescriptor = init::WriteDescriptorSet(setHandle[Gfx::currentFrameIndex], VK_DESCRIPTOR_TYPE_SAMPLER, binding, &imageInfos.back());
|
2020-03-13 12:44:33 +01:00
|
|
|
writeDescriptors.add(writeDescriptor);
|
2020-10-03 11:00:10 +02:00
|
|
|
|
2020-10-14 01:49:43 +02:00
|
|
|
cachedData[Gfx::currentFrameIndex][binding] = vulkanSampler.getHandle();
|
2020-03-13 12:44:33 +01:00
|
|
|
}
|
|
|
|
|
|
2020-03-20 01:27:40 +01:00
|
|
|
void DescriptorSet::updateTexture(uint32_t binding, Gfx::PTexture texture, Gfx::PSamplerState samplerState)
|
2020-03-13 12:44:33 +01:00
|
|
|
{
|
2020-10-03 11:00:10 +02:00
|
|
|
TextureHandle* vulkanTexture = TextureBase::cast(texture);
|
2020-10-14 01:49:43 +02:00
|
|
|
TextureHandle* cachedTexture = reinterpret_cast<TextureHandle*>(cachedData[Gfx::currentFrameIndex][binding]);
|
2020-10-03 11:00:10 +02:00
|
|
|
if(vulkanTexture == cachedTexture)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
2020-03-13 12:44:33 +01:00
|
|
|
//It is assumed that the image is in the correct layout
|
2020-04-12 15:47:19 +02:00
|
|
|
VkDescriptorImageInfo imageInfo =
|
|
|
|
|
init::DescriptorImageInfo(
|
|
|
|
|
VK_NULL_HANDLE,
|
|
|
|
|
vulkanTexture->getView(),
|
|
|
|
|
vulkanTexture->getLayout());
|
2020-03-13 12:44:33 +01:00
|
|
|
if (samplerState != nullptr)
|
|
|
|
|
{
|
2020-04-12 15:47:19 +02:00
|
|
|
PSamplerState vulkanSampler = samplerState.cast<SamplerState>();
|
|
|
|
|
imageInfo.sampler = vulkanSampler->sampler;
|
2020-03-13 12:44:33 +01:00
|
|
|
}
|
2020-04-12 15:47:19 +02:00
|
|
|
imageInfos.add(imageInfo);
|
2020-10-14 01:49:43 +02:00
|
|
|
VkWriteDescriptorSet writeDescriptor = init::WriteDescriptorSet(setHandle[Gfx::currentFrameIndex], samplerState != nullptr ? VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER : VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, binding, &imageInfos.back());
|
2020-04-12 15:47:19 +02:00
|
|
|
if (vulkanTexture->getUsage() & VK_IMAGE_USAGE_STORAGE_BIT)
|
2020-03-13 12:44:33 +01:00
|
|
|
{
|
2020-04-12 15:47:19 +02:00
|
|
|
writeDescriptor.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
2020-03-13 12:44:33 +01:00
|
|
|
}
|
|
|
|
|
writeDescriptors.add(writeDescriptor);
|
2020-10-03 11:00:10 +02:00
|
|
|
|
2020-10-14 01:49:43 +02:00
|
|
|
cachedData[Gfx::currentFrameIndex][binding] = vulkanTexture;
|
2020-03-13 12:44:33 +01:00
|
|
|
}
|
|
|
|
|
|
2020-03-20 01:27:40 +01:00
|
|
|
bool DescriptorSet::operator<(Gfx::PDescriptorSet other)
|
2020-03-13 12:44:33 +01:00
|
|
|
{
|
2020-03-20 01:27:40 +01:00
|
|
|
PDescriptorSet otherSet = other.cast<DescriptorSet>();
|
2020-03-13 12:44:33 +01:00
|
|
|
return setHandle < otherSet->setHandle;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-20 01:27:40 +01:00
|
|
|
void DescriptorSet::writeChanges()
|
2020-03-13 12:44:33 +01:00
|
|
|
{
|
|
|
|
|
if (writeDescriptors.size() > 0)
|
|
|
|
|
{
|
|
|
|
|
vkUpdateDescriptorSets(graphics->getDevice(), writeDescriptors.size(), writeDescriptors.data(), 0, nullptr);
|
|
|
|
|
writeDescriptors.clear();
|
|
|
|
|
imageInfos.clear();
|
|
|
|
|
bufferInfos.clear();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-12 15:47:19 +02:00
|
|
|
DescriptorAllocator::DescriptorAllocator(PGraphics graphics, DescriptorLayout &layout)
|
2020-10-03 11:00:10 +02:00
|
|
|
: layout(layout), graphics(graphics), currentCachedIndex(0)
|
2020-03-13 12:44:33 +01:00
|
|
|
{
|
2020-10-03 11:00:10 +02:00
|
|
|
std::memset(&cachedHandles, 0, sizeof(cachedHandles));
|
|
|
|
|
|
2020-08-11 22:38:19 +02:00
|
|
|
uint32 perTypeSizes[VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT]; // TODO: FIX ENUM
|
2020-03-13 12:44:33 +01:00
|
|
|
std::memset(perTypeSizes, 0, sizeof(perTypeSizes));
|
2020-04-12 15:47:19 +02:00
|
|
|
for (uint32 i = 0; i < layout.getBindings().size(); ++i)
|
2020-03-13 12:44:33 +01:00
|
|
|
{
|
2020-04-12 15:47:19 +02:00
|
|
|
auto &binding = layout.getBindings()[i];
|
2020-03-13 12:44:33 +01:00
|
|
|
int typeIndex = binding.descriptorType;
|
|
|
|
|
perTypeSizes[typeIndex] += 256;
|
|
|
|
|
}
|
|
|
|
|
Array<VkDescriptorPoolSize> poolSizes;
|
2020-08-11 22:38:19 +02:00
|
|
|
for (uint32 i = 0; i < VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; ++i)
|
2020-03-13 12:44:33 +01:00
|
|
|
{
|
|
|
|
|
if (perTypeSizes[i] > 0)
|
|
|
|
|
{
|
|
|
|
|
VkDescriptorPoolSize size;
|
|
|
|
|
size.descriptorCount = perTypeSizes[i];
|
|
|
|
|
size.type = (VkDescriptorType)i;
|
|
|
|
|
poolSizes.add(size);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
VkDescriptorPoolCreateInfo createInfo = init::DescriptorPoolCreateInfo(poolSizes.size(), poolSizes.data(), maxSets);
|
|
|
|
|
VK_CHECK(vkCreateDescriptorPool(graphics->getDevice(), &createInfo, nullptr, &poolHandle));
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-20 01:27:40 +01:00
|
|
|
DescriptorAllocator::~DescriptorAllocator()
|
2020-03-13 12:44:33 +01:00
|
|
|
{
|
|
|
|
|
vkDestroyDescriptorPool(graphics->getDevice(), poolHandle, nullptr);
|
2020-04-12 15:47:19 +02:00
|
|
|
graphics = nullptr;
|
2020-03-13 12:44:33 +01:00
|
|
|
}
|
|
|
|
|
|
2020-04-12 15:47:19 +02:00
|
|
|
void DescriptorAllocator::allocateDescriptorSet(Gfx::PDescriptorSet &descriptorSet)
|
2020-03-13 12:44:33 +01:00
|
|
|
{
|
2020-03-20 01:27:40 +01:00
|
|
|
descriptorSet = new DescriptorSet(graphics, this);
|
|
|
|
|
PDescriptorSet vulkanSet = descriptorSet.cast<DescriptorSet>();
|
2020-03-13 12:44:33 +01:00
|
|
|
VkDescriptorSetLayout layoutHandle = layout.getHandle();
|
|
|
|
|
VkDescriptorSetAllocateInfo allocInfo =
|
|
|
|
|
init::DescriptorSetAllocateInfo(poolHandle, &layoutHandle, 1);
|
2020-10-03 11:00:10 +02:00
|
|
|
for(uint32 i = 0; i < Gfx::numFramesBuffered; ++i)
|
|
|
|
|
{
|
|
|
|
|
if(cachedHandles[currentCachedIndex] != VK_NULL_HANDLE)
|
|
|
|
|
{
|
|
|
|
|
vulkanSet->setHandle[i] = cachedHandles[currentCachedIndex++];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
VK_CHECK(vkAllocateDescriptorSets(graphics->getDevice(), &allocInfo, &vulkanSet->setHandle[i]));
|
|
|
|
|
cachedHandles[currentCachedIndex++] = vulkanSet->setHandle[i];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vulkanSet->cachedData[i].resize(layout.bindings.size());
|
|
|
|
|
// Not really pretty, but this way the set knows which ones are valid
|
|
|
|
|
std::memset(vulkanSet->cachedData[i].data(), 0, sizeof(void*) * vulkanSet->cachedData[i].size());
|
|
|
|
|
}
|
2020-03-13 12:44:33 +01:00
|
|
|
}
|
2020-10-03 11:00:10 +02:00
|
|
|
|
|
|
|
|
void DescriptorAllocator::reset()
|
|
|
|
|
{
|
|
|
|
|
currentCachedIndex = 0;
|
|
|
|
|
}
|