Add in some buffer printouts
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -10,7 +10,6 @@
|
||||
namespace fgl::engine::memory
|
||||
{
|
||||
class Buffer;
|
||||
class BufferHandle;
|
||||
class SuballocationView;
|
||||
|
||||
struct BufferSuballocationHandle;
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace fgl::engine::memory
|
||||
{
|
||||
vk::Buffer BufferSuballocationHandle::getBuffer()
|
||||
{
|
||||
return buffer.getBuffer();
|
||||
return buffer.getVkBuffer();
|
||||
}
|
||||
|
||||
BufferSuballocationHandle::
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
|
||||
#include <vulkan/vulkan.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace vk::raii
|
||||
{
|
||||
class CommandBuffer;
|
||||
|
||||
@@ -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 >
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user