180 lines
6.1 KiB
C++
180 lines
6.1 KiB
C++
// =============================================
|
|
// Aster: pipeline_utils.h
|
|
// Copyright (c) 2020-2024 Anish Bhobe
|
|
// =============================================
|
|
|
|
#include "render_resource_manager.h"
|
|
|
|
#include "buffer.h"
|
|
#include "device.h"
|
|
#include "helpers.h"
|
|
#include "image.h"
|
|
|
|
#include <EASTL/array.h>
|
|
|
|
RenderResourceManager::WriteInfo::WriteInfo(vk::DescriptorBufferInfo info)
|
|
: uBufferInfo(info)
|
|
{
|
|
}
|
|
|
|
RenderResourceManager::WriteInfo::WriteInfo(vk::DescriptorImageInfo info)
|
|
: uImageInfo(info)
|
|
{
|
|
}
|
|
|
|
RenderResourceManager::WriteInfo::WriteInfo(vk::BufferView info)
|
|
: uBufferView(info)
|
|
{
|
|
}
|
|
|
|
BufferHandle
|
|
RenderResourceManager::Commit(const UniformStorageBuffer *storageBuffer)
|
|
{
|
|
const u32 handle = m_BufferFreeList.Alloc();
|
|
|
|
m_WriteInfos.emplace_back(vk::DescriptorBufferInfo{
|
|
.buffer = storageBuffer->m_Buffer,
|
|
.offset = 0,
|
|
.range = storageBuffer->GetSize(),
|
|
});
|
|
|
|
m_Writes.push_back({
|
|
.dstSet = m_DescriptorSet,
|
|
.dstBinding = BUFFER_BINDING_INDEX,
|
|
.dstArrayElement = handle,
|
|
.descriptorCount = 1,
|
|
.descriptorType = vk::DescriptorType::eStorageBuffer,
|
|
.pBufferInfo = &m_WriteInfos.back().uBufferInfo,
|
|
});
|
|
|
|
return {handle};
|
|
}
|
|
|
|
TextureHandle
|
|
RenderResourceManager::Commit(const Texture *texture)
|
|
{
|
|
const u32 handle = m_TextureFreeList.Alloc();
|
|
|
|
m_WriteInfos.emplace_back(vk::DescriptorImageInfo{
|
|
.sampler = nullptr,
|
|
.imageView = texture->m_View,
|
|
.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal,
|
|
});
|
|
|
|
m_Writes.push_back({
|
|
.dstSet = m_DescriptorSet,
|
|
.dstBinding = TEXTURE_BINDING_INDEX,
|
|
.dstArrayElement = handle,
|
|
.descriptorCount = 1,
|
|
.descriptorType = vk::DescriptorType::eCombinedImageSampler,
|
|
.pImageInfo = &m_WriteInfos.back().uImageInfo,
|
|
});
|
|
|
|
return {handle};
|
|
}
|
|
|
|
void
|
|
RenderResourceManager::Update()
|
|
{
|
|
usize count = Cast<usize>(m_Writes.size());
|
|
vk::WriteDescriptorSet *pData = m_Writes.data();
|
|
if (count > 0)
|
|
{
|
|
m_Device->m_Device.updateDescriptorSets(count, pData, 0, nullptr);
|
|
}
|
|
|
|
m_Writes.clear();
|
|
m_WriteInfos.clear();
|
|
}
|
|
|
|
RenderResourceManager::RenderResourceManager(const Device *device, u16 maxSize)
|
|
: m_Device(device)
|
|
{
|
|
vk::PhysicalDeviceProperties properties;
|
|
m_Device->m_PhysicalDevice.getProperties(&properties);
|
|
|
|
u32 buffersCount = eastl::min(properties.limits.maxPerStageDescriptorStorageBuffers - 1024, Cast<u32>(maxSize));
|
|
u32 texturesCount = eastl::min(properties.limits.maxPerStageDescriptorSampledImages - 1024, Cast<u32>(maxSize));
|
|
|
|
vk::SamplerCreateInfo samplerCreateInfo = {
|
|
.magFilter = vk::Filter::eLinear,
|
|
.minFilter = vk::Filter::eLinear,
|
|
.mipmapMode = vk::SamplerMipmapMode::eLinear,
|
|
.addressModeU = vk::SamplerAddressMode::eClampToBorder,
|
|
.addressModeV = vk::SamplerAddressMode::eClampToBorder,
|
|
.addressModeW = vk::SamplerAddressMode::eClampToBorder,
|
|
.mipLodBias = 0.0f,
|
|
.anisotropyEnable = true,
|
|
.maxAnisotropy = properties.limits.maxSamplerAnisotropy,
|
|
.compareEnable = false,
|
|
.minLod = 0,
|
|
.maxLod = vk::LodClampNone,
|
|
.borderColor = vk::BorderColor::eFloatOpaqueBlack,
|
|
.unnormalizedCoordinates = false,
|
|
};
|
|
AbortIfFailed(device->m_Device.createSampler(&samplerCreateInfo, nullptr, &m_Sampler));
|
|
|
|
INFO("Max Buffer Count: {}", buffersCount);
|
|
INFO("Max Texture Count: {}", texturesCount);
|
|
|
|
m_BufferFreeList.Init(buffersCount);
|
|
m_TextureFreeList.Init(texturesCount);
|
|
|
|
eastl::array poolSizes = {
|
|
vk::DescriptorPoolSize{
|
|
.type = vk::DescriptorType::eStorageBuffer,
|
|
.descriptorCount = buffersCount,
|
|
},
|
|
vk::DescriptorPoolSize{
|
|
.type = vk::DescriptorType::eCombinedImageSampler,
|
|
.descriptorCount = texturesCount,
|
|
},
|
|
};
|
|
const vk::DescriptorPoolCreateInfo poolCreateInfo = {
|
|
.flags = vk::DescriptorPoolCreateFlagBits::eUpdateAfterBind,
|
|
.maxSets = 1,
|
|
.poolSizeCount = Cast<u32>(poolSizes.size()),
|
|
.pPoolSizes = poolSizes.data(),
|
|
};
|
|
AbortIfFailed(device->m_Device.createDescriptorPool(&poolCreateInfo, nullptr, &m_DescriptorPool));
|
|
|
|
eastl::vector immutableSamplers(texturesCount, m_Sampler);
|
|
eastl::array descriptorLayoutBindings = {
|
|
vk::DescriptorSetLayoutBinding{
|
|
.binding = BUFFER_BINDING_INDEX,
|
|
.descriptorType = vk::DescriptorType::eStorageBuffer,
|
|
.descriptorCount = Cast<u32>(buffersCount),
|
|
.stageFlags = vk::ShaderStageFlagBits::eAll,
|
|
},
|
|
vk::DescriptorSetLayoutBinding{
|
|
.binding = TEXTURE_BINDING_INDEX,
|
|
.descriptorType = vk::DescriptorType::eCombinedImageSampler,
|
|
.descriptorCount = Cast<u32>(texturesCount),
|
|
.stageFlags = vk::ShaderStageFlagBits::eAll,
|
|
.pImmutableSamplers = immutableSamplers.data(),
|
|
},
|
|
};
|
|
const vk::DescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
|
|
.flags = vk::DescriptorSetLayoutCreateFlagBits::eUpdateAfterBindPool,
|
|
.bindingCount = Cast<u32>(descriptorLayoutBindings.size()),
|
|
.pBindings = descriptorLayoutBindings.data(),
|
|
};
|
|
AbortIfFailed(device->m_Device.createDescriptorSetLayout(&descriptorSetLayoutCreateInfo, nullptr, &m_SetLayout));
|
|
|
|
// One descriptor is enough. Updating it at any time is safe. (Update until submit, data held when pending)
|
|
// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_EXT_descriptor_indexing.html
|
|
// https://github.com/KhronosGroup/Vulkan-Guide/blob/main/chapters/extensions/VK_EXT_descriptor_indexing.adoc
|
|
const vk::DescriptorSetAllocateInfo descriptorSetAllocateInfo = {
|
|
.descriptorPool = m_DescriptorPool,
|
|
.descriptorSetCount = 1,
|
|
.pSetLayouts = &m_SetLayout,
|
|
};
|
|
AbortIfFailed(device->m_Device.allocateDescriptorSets(&descriptorSetAllocateInfo, &m_DescriptorSet));
|
|
}
|
|
|
|
RenderResourceManager::~RenderResourceManager()
|
|
{
|
|
m_Device->m_Device.destroy(m_Sampler, nullptr);
|
|
m_Device->m_Device.destroy(m_DescriptorPool, nullptr);
|
|
m_Device->m_Device.destroy(m_SetLayout, nullptr);
|
|
} |