Add in some buffer printouts

This commit is contained in:
2024-08-08 14:44:20 -04:00
parent 32d452a568
commit 8d0bfc1d12
9 changed files with 107 additions and 176 deletions

View File

@@ -3,6 +3,7 @@
#include "core.hpp"
#include "engine/buffers/Buffer.hpp"
#include "engine/literals/size.hpp"
#include "safe_include.hpp"
namespace fgl::engine::gui
@@ -17,38 +18,37 @@ namespace fgl::engine::gui
inline vk::DeviceSize free() const { return m_total - m_used; }
vk::DeviceSize m_largest_free_block;
vk::DeviceSize m_largest_free_block { std::numeric_limits< vk::DeviceSize >::max() };
};
AllocationInfo gpu {};
AllocationInfo host {};
};
const AllocationList getTotalAllocated()
AllocationList getTotalAllocated()
{
AllocationList info {};
auto& [ gpu_allocated, gpu_used, gpu_largest_free ] = info.gpu;
auto& [ host_allocated, host_used, host_largest_free ] = info.host;
for ( const std::weak_ptr< memory::BufferHandle >& buffer_weak :
fgl::engine::memory::Buffer::getActiveBufferHandles() )
for ( const auto* buffer : memory::getActiveBuffers() )
{
if ( auto locked = buffer_weak.lock(); locked )
// The buffer is still active.
if ( buffer->m_memory_properties & vk::MemoryPropertyFlagBits::eDeviceLocal )
{
// The buffer is still active.
if ( locked->m_memory_properties & vk::MemoryPropertyFlagBits::eDeviceLocal )
{
gpu_allocated += locked->size();
}
else if ( locked->m_memory_properties & vk::MemoryPropertyFlagBits::eHostVisible )
{
host_allocated += locked->size();
}
else
throw std::
runtime_error( "Unknown memory property flag choice. Could not determine host vs device" );
gpu_allocated += buffer->size();
gpu_used += buffer->used();
gpu_largest_free = std::min( buffer->largestBlock(), gpu_largest_free );
}
else if ( buffer->m_memory_properties & vk::MemoryPropertyFlagBits::eHostVisible )
{
host_allocated += buffer->size();
host_used += buffer->used();
host_largest_free = std::min( buffer->largestBlock(), host_largest_free );
}
else
throw std::runtime_error( "Unknown memory property flag choice. Could not determine host vs device" );
}
return info;
@@ -60,16 +60,20 @@ namespace fgl::engine::gui
const auto& [ gpu_allocated, gpu_used, gpu_largest_block ] = gpu;
const auto& [ host_allocated, host_used, host_largest_block ] = host;
using namespace literals::size_literals;
ImGui::Text( "Device" );
ImGui::Text( "|- %0.1f MB Allocated", static_cast< float >( gpu_allocated ) / 1000.0f / 1000.0f );
ImGui::Text( "|- %0.1f MB Used ", static_cast< float >( gpu_used ) / 1000.0f / 1000.0f );
ImGui::Text( "|- %0.1f MB Unused", static_cast< float >( gpu.free() ) / 1000.0f / 1000.0f );
ImGui::Text( "|- %s Allocated", to_string( gpu_allocated ).c_str() );
ImGui::Text( "|- %s Used ", to_string( gpu_used ).c_str() );
ImGui::Text( "|- %s Unused", to_string( gpu.free() ).c_str() );
ImGui::Text( "|- %s Available in most allocated buffer", to_string( gpu.m_largest_free_block ).c_str() );
ImGui::Separator();
ImGui::Text( "Host" );
ImGui::Text( "|- %0.1f MB Allocated", static_cast< float >( host_allocated ) / 1000.0f / 1000.0f );
ImGui::Text( "|- %0.1f MB Used ", static_cast< float >( host_used ) / 1000.0f / 1000.0f );
ImGui::Text( "|- %0.1f MB Unused", static_cast< float >( host.free() ) / 1000.0f / 1000.0f );
ImGui::Text( "|- %s Allocated", to_string( host_allocated ).c_str() );
ImGui::Text( "|- %s Used ", to_string( host_used ).c_str() );
ImGui::Text( "|- %s Unused", to_string( host.free() ).c_str() );
ImGui::Text( "|- %s Available in most allocated buffer", to_string( host.m_largest_free_block ).c_str() );
ImGui::Separator();
}

View File

@@ -12,34 +12,49 @@
namespace fgl::engine::memory
{
BufferHandle::BufferHandle(
vk::DeviceSize memory_size, vk::BufferUsageFlags usage, vk::MemoryPropertyFlags memory_properties ) :
inline static std::vector< Buffer* > active_buffers {};
std::vector< Buffer* > getActiveBuffers()
{
return active_buffers;
}
Buffer::
Buffer( vk::DeviceSize memory_size, vk::BufferUsageFlags usage, vk::MemoryPropertyFlags memory_properties ) :
m_memory_size( memory_size ),
m_usage( usage ),
m_memory_properties( memory_properties )
{
alloc( memory_size );
active_buffers.emplace_back( this );
m_free_blocks.push_back( { 0, memory_size } );
}
BufferHandle::~BufferHandle()
Buffer::~Buffer()
{
assert( this->m_allocations.size() == 0 );
dealloc();
if ( auto itter = std::find( active_buffers.begin(), active_buffers.end(), this );
itter != active_buffers.end() )
active_buffers.erase( itter );
}
void* BufferHandle::map( BufferSuballocationHandle& handle )
void* Buffer::map( BufferSuballocationHandle& handle )
{
if ( m_alloc_info.pMappedData == nullptr ) return nullptr;
return static_cast< std::byte* >( m_alloc_info.pMappedData ) + handle.m_offset;
}
void BufferHandle::dealloc()
void Buffer::dealloc()
{
vmaDestroyBuffer( Device::getInstance().allocator(), m_buffer, m_allocation );
}
void BufferHandle::alloc( vk::DeviceSize memory_size )
void Buffer::alloc( vk::DeviceSize memory_size )
{
assert( memory_size > 0 );
m_memory_size = memory_size;
vk::BufferCreateInfo buffer_info {};
buffer_info.pNext = VK_NULL_HANDLE;
@@ -79,25 +94,6 @@ namespace fgl::engine::memory
vmaGetAllocationInfo( Device::getInstance().allocator(), m_allocation, &m_alloc_info );
}
#ifdef TRACK_BUFFERS
std::vector< std::weak_ptr< BufferHandle > > Buffer::getActiveBufferHandles()
{
std::vector< std::weak_ptr< BufferHandle > > handles;
handles.reserve( m_buffer_handles.size() );
for ( auto& handle : m_buffer_handles )
{
if ( auto ptr = handle.lock() )
{
handles.push_back( ptr );
}
}
m_buffer_handles = handles;
return handles;
}
#endif
vk::DeviceSize Buffer::alignment()
{
vk::DeviceSize size { 0 };
@@ -194,10 +190,9 @@ namespace fgl::engine::memory
std::cout << "Total memory free: " << fgl::literals::size_literals::to_string( free_memory_counter )
<< std::endl;
std::cout << "Total memory: " << fgl::literals::size_literals::to_string( m_handle->m_memory_size )
<< std::endl;
std::cout << "Total memory: " << fgl::literals::size_literals::to_string( m_memory_size ) << std::endl;
if ( allocated_memory_counter + free_memory_counter != m_handle->m_memory_size )
if ( allocated_memory_counter + free_memory_counter != m_memory_size )
{
std::cout << "Memory size mismatch detected! Difference of: "
<< ( allocated_memory_counter + free_memory_counter - memory_size ) << std::endl;
@@ -303,7 +298,7 @@ namespace fgl::engine::memory
vk::DebugUtilsObjectNameInfoEXT info {};
info.objectType = vk::ObjectType::eBuffer;
info.pObjectName = str.c_str();
info.objectHandle = reinterpret_cast< std::uint64_t >( static_cast< VkBuffer >( this->m_handle->m_buffer ) );
info.objectHandle = reinterpret_cast< std::uint64_t >( static_cast< VkBuffer >( this->m_buffer ) );
Device::getInstance().setDebugUtilsObjectName( info );
}
@@ -342,26 +337,27 @@ namespace fgl::engine::memory
#endif
}
void* Buffer::map( BufferSuballocationHandle& handle )
vk::DeviceSize Buffer::used() const
{
return this->m_handle->map( handle );
vk::DeviceSize total_size { 0 };
if ( m_allocations.size() == 0 ) return total_size;
for ( const auto& [ offset, size ] : m_allocations ) total_size += size;
return total_size;
}
Buffer::
Buffer( vk::DeviceSize memory_size, vk::BufferUsageFlags usage, vk::MemoryPropertyFlags memory_properties ) :
m_handle( std::make_shared< BufferHandle >( memory_size, usage, memory_properties ) ),
m_usage( usage ),
m_memory_properties( memory_properties )
vk::DeviceSize Buffer::largestBlock() const
{
m_free_blocks.insert( m_free_blocks.begin(), { 0, memory_size } );
#ifdef TRACK_BUFFERS
m_buffer_handles.emplace_back( m_handle );
#endif
}
vk::DeviceSize largest { 0 };
Buffer::~Buffer()
{
assert( m_allocations.size() == 0 && "Buffer destructed while allocations still present" );
for ( const auto& blocks : m_free_blocks )
{
largest = std::max( largest, blocks.second );
}
return largest;
}
} // namespace fgl::engine::memory

View File

@@ -20,12 +20,16 @@
namespace fgl::engine
{
class Device;
}
namespace gui
{
struct AllocationList;
AllocationList getTotalAllocated();
} // namespace gui
} // namespace fgl::engine
namespace fgl::engine::memory
{
class BufferHandle;
class BufferSuballocation;
struct BufferSuballocationHandle;
@@ -34,7 +38,7 @@ namespace fgl::engine::memory
//TODO: Ensure this class can't be directly accessed from within Buffer unless we are trying
// to access it in a debug manner (IE the drawStats menu)
struct BufferHandle
class Buffer
{
vk::Buffer m_buffer { VK_NULL_HANDLE };
VmaAllocation m_allocation {};
@@ -48,71 +52,33 @@ namespace fgl::engine::memory
void alloc( vk::DeviceSize memory_size );
void dealloc();
BufferHandle() = delete;
BufferHandle( const BufferHandle& other ) = delete;
BufferHandle& operator=( const BufferHandle& other ) = delete;
BufferHandle( BufferHandle&& other ) = delete;
BufferHandle& operator=( BufferHandle&& other ) = delete;
Buffer() = delete;
Buffer( const Buffer& other ) = delete;
Buffer& operator=( const Buffer& other ) = delete;
Buffer( Buffer&& other ) = delete;
Buffer& operator=( Buffer&& other ) = delete;
friend class Buffer;
public:
BufferHandle(
vk::DeviceSize memory_size, vk::BufferUsageFlags usage, vk::MemoryPropertyFlags memory_properties );
Buffer( vk::DeviceSize memory_size, vk::BufferUsageFlags usage, vk::MemoryPropertyFlags memory_properties );
~BufferHandle();
~Buffer();
auto address() const { return m_alloc_info.deviceMemory; }
auto size() const { return m_alloc_info.size; }
void* map( BufferSuballocationHandle& handle );
};
vk::DeviceSize largestBlock() const;
class Buffer
{
#ifdef TRACK_BUFFERS
//! Tracking pointer for all buffers
inline static std::vector< std::weak_ptr< BufferHandle > > m_buffer_handles {};
public:
static std::vector< std::weak_ptr< BufferHandle > > getActiveBufferHandles();
vk::DeviceSize used() const;
private:
#endif
//TODO: Switch this to being a non pointer if we aren't tracking
// Since we don't need this to be a pointer at all if we don't need to track anything
// It'll just be wasted pointer dereferencing
std::shared_ptr< BufferHandle > m_handle;
public:
vk::BufferUsageFlags m_usage;
vk::MemoryPropertyFlags m_memory_properties;
Buffer() = delete;
Buffer( vk::DeviceSize memory_size, vk::BufferUsageFlags usage, vk::MemoryPropertyFlags memory_properties );
~Buffer();
Buffer( const Buffer& other ) = delete;
Buffer& operator=( const Buffer& other ) = delete;
Buffer( Buffer&& other ) = default;
Buffer& operator=( Buffer&& other ) = default;
inline vk::Buffer& getVkBuffer() noexcept { return m_handle->m_buffer; }
void* map( BufferSuballocationHandle& handle );
//! Returns the required alignment for this buffer.
vk::DeviceSize alignment();
std::shared_ptr< BufferHandle >& getHandle() { return m_handle; }
private:
//! @brief List of all active suballocations
//! <offset, size>
std::map< vk::DeviceSize, vk::DeviceSize > m_allocations {};
@@ -125,40 +91,24 @@ namespace fgl::engine::memory
public:
//! Returns the vulkan buffer handle for this buffer
vk::Buffer getBuffer() const
{
assert( m_handle );
assert( m_handle->m_buffer != VK_NULL_HANDLE );
return m_handle->m_buffer;
}
vk::Buffer getVkBuffer() const { return m_buffer; }
//! Returns the vulkan memory handle for this buffer
vk::DeviceMemory getMemory() const
{
assert( m_handle );
assert( m_handle->m_alloc_info.deviceMemory != VK_NULL_HANDLE );
assert( m_alloc_info.deviceMemory != VK_NULL_HANDLE );
return m_handle->m_alloc_info.deviceMemory;
return m_alloc_info.deviceMemory;
}
//! Total memory size of the buffer
vk::DeviceSize size() const
{
assert( m_handle );
assert( !std::isnan( m_handle->m_memory_size ) );
friend struct BufferSuballocationHandle;
friend class BufferSuballocation; //TODO: Remove this
return m_handle->m_memory_size;
}
friend gui::AllocationList gui::getTotalAllocated();
void* map( BufferSuballocationHandle& info );
public:
bool isMappable() const
{
assert( m_handle );
return m_handle->m_alloc_info.pMappedData != nullptr;
}
bool isMappable() const { return m_alloc_info.pMappedData != nullptr; }
//! Returns a allocation block from this buffer. Block will be aligned with nonUniformBufferOffsetAlignment
//! and nonCoherentAtomSize if required (is_uniform_buffer and is_host_visible respectively)
@@ -185,4 +135,5 @@ namespace fgl::engine::memory
void setDebugName( const std::string str );
};
std::vector< Buffer* > getActiveBuffers();
} // namespace fgl::engine::memory

View File

@@ -10,7 +10,6 @@
namespace fgl::engine::memory
{
class Buffer;
class BufferHandle;
class SuballocationView;
struct BufferSuballocationHandle;

View File

@@ -12,7 +12,7 @@ namespace fgl::engine::memory
{
vk::Buffer BufferSuballocationHandle::getBuffer()
{
return buffer.getBuffer();
return buffer.getVkBuffer();
}
BufferSuballocationHandle::

View File

@@ -6,6 +6,8 @@
#include <vulkan/vulkan.hpp>
#include <memory>
namespace vk::raii
{
class CommandBuffer;

View File

@@ -4,11 +4,14 @@
#pragma once
#include "Buffer.hpp"
#include "BufferSuballocation.hpp"
namespace fgl::engine
{
namespace memory
{
class Buffer;
}
//! Single element allocation of T
template < typename T >

View File

@@ -2,17 +2,4 @@
// Created by kj16609 on 12/29/23.
//
#pragma once
#include <type_traits>
#include "engine/buffers/Buffer.hpp"
namespace fgl::engine::memory
{
template < typename T > concept is_buffer = std::same_as< T, Buffer >;
template < typename T >
concept is_buffer_ref = std::is_reference_v< T > && is_buffer< std::remove_reference_t< T > >;
} // namespace fgl::engine::memory
#pragma once

View File

@@ -4,29 +4,18 @@
#pragma once
#include "is_buffer.hpp"
namespace fgl::engine::memory
{
template < typename T >
concept is_suballocation = requires( T t ) {
{
t.getBuffer()
} -> is_buffer_ref;
{
t.getVkBuffer()
} -> std::same_as< vk::Buffer >;
{
t.getOffset()
} -> std::same_as< vk::DeviceSize >;
concept is_suballocation = requires( const T t ) {
{ t.getVkBuffer() } -> std::same_as< vk::Buffer >;
{ t.getOffset() } -> std::same_as< vk::DeviceSize >;
/*
{
t.size()
} -> std::same_as< vk::DeviceSize >;
*/
{
t.descriptorInfo()
} -> std::same_as< vk::DescriptorBufferInfo >;
{ t.descriptorInfo() } -> std::same_as< vk::DescriptorBufferInfo >;
};
} // namespace fgl::engine::memory