Files
FGL-Engine/src/engine/descriptors/DescriptorSet.cpp

225 lines
6.7 KiB
C++

//
// Created by kj16609 on 1/5/24.
//
#include "DescriptorSet.hpp"
#include <vulkan/vulkan.hpp>
#include <iostream>
#include <queue>
#include "DescriptorPool.hpp"
#include "engine/assets/image/ImageView.hpp"
#include "engine/assets/texture/Texture.hpp"
#include "engine/memory/buffers/BufferSuballocation.hpp"
#include "engine/rendering/SwapChain.hpp"
namespace fgl::engine::descriptors
{
DescriptorSet::DescriptorSet(
const vk::raii::DescriptorSetLayout& layout, const DescriptorIDX idx, const std::size_t binding_count ) :
m_set_idx( idx ),
m_set( DescriptorPool::getInstance().allocateSet( layout ) ),
m_binding_count( binding_count )
{
m_infos.resize( m_binding_count );
}
DescriptorSet::DescriptorSet( DescriptorSet&& other ) noexcept :
m_set_idx( other.m_set_idx ),
m_infos( std::move( other.m_infos ) ),
descriptor_writes( std::move( other.descriptor_writes ) ),
m_resources( std::move( other.m_resources ) ),
m_set( std::move( other.m_set ) ),
m_binding_count( other.m_binding_count )
{
other.m_set = VK_NULL_HANDLE;
other.m_binding_count = 0;
}
DescriptorSet& DescriptorSet::operator=( DescriptorSet&& other ) noexcept
{
m_set_idx = other.m_set_idx;
m_infos = std::move( other.m_infos );
descriptor_writes = std::move( other.descriptor_writes );
m_resources = std::move( other.m_resources );
m_set = std::move( other.m_set );
other.m_set = VK_NULL_HANDLE;
m_binding_count = other.m_binding_count;
other.m_binding_count = 0;
return *this;
}
void DescriptorSet::bindUniformBuffer( const std::uint32_t binding_idx, memory::BufferSuballocation& buffer )
{
assert( binding_idx < m_infos.size() && "Binding index out of range" );
m_infos[ binding_idx ] = buffer.descriptorInfo();
vk::WriteDescriptorSet write {};
write.dstSet = m_set;
write.dstBinding = binding_idx;
write.dstArrayElement = 0;
write.descriptorCount = 1;
write.descriptorType = vk::DescriptorType::eUniformBuffer;
write.pBufferInfo = &( std::get< vk::DescriptorBufferInfo >( m_infos.data()[ binding_idx ] ) );
write.pImageInfo = VK_NULL_HANDLE;
write.pTexelBufferView = VK_NULL_HANDLE;
descriptor_writes.push_back( write );
}
void DescriptorSet::bindArray(
const std::uint32_t binding_idx,
const memory::BufferSuballocation& buffer,
const std::size_t array_idx,
const std::size_t item_size )
{
assert( binding_idx < m_infos.size() && "Binding index out of range" );
m_infos[ binding_idx ] = buffer.descriptorInfo( array_idx * item_size );
//HACK: We set the range to something else after getting it
std::get< vk::DescriptorBufferInfo >( m_infos[ binding_idx ] ).range = item_size;
vk::WriteDescriptorSet write {};
write.dstSet = m_set;
write.dstBinding = binding_idx;
write.dstArrayElement = array_idx;
write.descriptorCount = 1;
write.descriptorType = vk::DescriptorType::eUniformBuffer;
write.pBufferInfo = &( std::get< vk::DescriptorBufferInfo >( m_infos.data()[ binding_idx ] ) );
write.pImageInfo = VK_NULL_HANDLE;
write.pTexelBufferView = VK_NULL_HANDLE;
log::info( "Bound idx {} to data", array_idx );
descriptor_writes.push_back( write );
}
void DescriptorSet::
bindImage( std::uint32_t binding_idx, ImageView& view, vk::ImageLayout layout, vk::raii::Sampler sampler )
{
assert( binding_idx < m_infos.size() && "Binding index out of range" );
//Store info
m_infos[ binding_idx ] = view.descriptorInfo( sampler, layout );
vk::WriteDescriptorSet write {};
write.dstSet = m_set;
write.dstBinding = binding_idx;
write.dstArrayElement = 0;
write.descriptorCount = 1;
write.descriptorType = vk::DescriptorType::eSampledImage;
write.pBufferInfo = VK_NULL_HANDLE;
write.pImageInfo = &( std::get< vk::DescriptorImageInfo >( m_infos.data()[ binding_idx ] ) );
write.pTexelBufferView = VK_NULL_HANDLE;
descriptor_writes.push_back( write );
}
void DescriptorSet::bindTexture( std::uint32_t binding_idx, std::shared_ptr< Texture >& tex_ptr )
{
assert( binding_idx < m_infos.size() && "Binding index out of range" );
assert(
std::holds_alternative< std::monostate >( m_infos[ binding_idx ] )
&& "Update must be called between each array bind" );
assert( tex_ptr );
//TODO: Bind temporary texture if tex_ptr is not ready.
Texture& tex { *tex_ptr };
m_infos[ binding_idx ] = tex.getImageView().descriptorInfo(
tex.getImageView().getSampler().getVkSampler(), vk::ImageLayout::eShaderReadOnlyOptimal );
vk::WriteDescriptorSet write {};
write.dstSet = m_set;
write.dstBinding = binding_idx;
write.dstArrayElement = tex.getID();
write.descriptorCount = 1;
write.descriptorType = vk::DescriptorType::eCombinedImageSampler;
write.pImageInfo = &( std::get< vk::DescriptorImageInfo >( m_infos.data()[ binding_idx ] ) );
descriptor_writes.push_back( write );
}
void DescriptorSet::update()
{
Device::getInstance().device().updateDescriptorSets( descriptor_writes, {} );
reset();
}
DescriptorSet::~DescriptorSet()
{}
void DescriptorSet::reset()
{
m_infos.clear();
//Clear all writes
descriptor_writes.clear();
m_infos.resize( m_binding_count );
}
void DescriptorSet::bindAttachment(
const std::uint32_t binding_idx,
const ImageView& view,
const vk::ImageLayout layout,
const vk::raii::Sampler& sampler )
{
assert( binding_idx < m_infos.size() && "Binding index out of range" );
//Store info
m_infos[ binding_idx ] = view.descriptorInfo( sampler, layout );
vk::WriteDescriptorSet write {};
write.dstSet = m_set;
write.dstBinding = binding_idx;
write.dstArrayElement = 0;
write.descriptorCount = 1;
write.descriptorType = vk::DescriptorType::eInputAttachment;
write.pBufferInfo = VK_NULL_HANDLE;
write.pImageInfo = &( std::get< vk::DescriptorImageInfo >( m_infos.data()[ binding_idx ] ) );
write.pTexelBufferView = VK_NULL_HANDLE;
descriptor_writes.push_back( write );
}
void DescriptorSet::setName( const std::string& str )
{
vk::DebugUtilsObjectNameInfoEXT info {};
info.objectType = vk::ObjectType::eDescriptorSet;
info.pObjectName = str.c_str();
info.setObjectHandle( reinterpret_cast< std::uint64_t >( getVkDescriptorSet() ) );
Device::getInstance().setDebugUtilsObjectName( info );
}
inline static std::vector< std::pair< std::uint_fast8_t, std::unique_ptr< DescriptorSet > > > queue {};
void queueDescriptorDeletion( std::unique_ptr< DescriptorSet > set )
{
queue.emplace_back( std::make_pair( 0, std::move( set ) ) );
}
void deleteQueuedDescriptors()
{
for ( auto itter = queue.begin(); itter != queue.end(); itter = itter++ )
{
auto& [ counter, set ] = *itter;
// Prevent deleting a descriptor until we are sure it's been here long enough
if ( counter > SwapChain::MAX_FRAMES_IN_FLIGHT + 1 )
{
itter = queue.erase( itter );
}
else
++counter;
}
}
} // namespace fgl::engine::descriptors