Implement basic buffer resizing

This commit is contained in:
2025-04-15 00:57:54 -04:00
parent c0ec82fac1
commit 1b4f8f42ea
37 changed files with 371 additions and 240 deletions

View File

@@ -6,7 +6,8 @@
#include "engine/debug/timing/FlameGraph.hpp"
#include "engine/flags.hpp"
#include "engine/math/literals/size.hpp"
#include "engine/memory/buffers/Buffer.hpp"
#include "engine/memory/buffers/BufferHandle.hpp"
#include "memory/buffers/BufferHandle.hpp"
#include "safe_include.hpp"
namespace fgl::engine::gui
@@ -35,8 +36,11 @@ namespace fgl::engine::gui
auto& [ gpu_allocated, gpu_used, gpu_largest_free ] = info.m_gpu;
auto& [ host_allocated, host_used, host_largest_free ] = info.m_host;
for ( const auto* buffer : memory::getActiveBuffers() )
/*
for ( const std::weak_ptr< memory::BufferHandle > buffer_weak : memory::getActiveBuffers() )
{
const auto buffer { buffer_weak.lock() };
// The buffer is still active.
if ( buffer->m_memory_properties & vk::MemoryPropertyFlagBits::eDeviceLocal )
{
@@ -53,6 +57,7 @@ namespace fgl::engine::gui
else
throw std::runtime_error( "Unknown memory property flag choice. Could not determine host vs device" );
}
*/
return info;
}
@@ -88,8 +93,10 @@ namespace fgl::engine::gui
if ( ImGui::CollapsingHeader( "Buffers" ) )
{
for ( const auto* buffer : memory::getActiveBuffers() )
/*
for ( const std::weak_ptr< memory::BufferHandle > buffer_weak : memory::getActiveBuffers() )
{
const auto buffer { buffer_weak.lock() };
ImGui::Text( "Name: %s", buffer->m_debug_name.c_str() );
const double used_percent { static_cast< float >( buffer->used() )
@@ -104,6 +111,7 @@ namespace fgl::engine::gui
ImGui::Text( "Largest block: %s", toString( buffer->largestBlock() ).c_str() );
ImGui::Separator();
}
*/
}
}

View File

@@ -20,6 +20,7 @@
#include "engine/flags.hpp"
#include "engine/math/Average.hpp"
#include "engine/math/literals/size.hpp"
#include "memory/buffers/BufferHandle.hpp"
namespace fgl::engine
{
@@ -52,7 +53,7 @@ namespace fgl::engine
EngineContext::EngineContext() :
m_ubo_buffer_pool( 1_MiB, vk::BufferUsageFlagBits::eUniformBuffer, vk::MemoryPropertyFlagBits::eHostVisible ),
m_draw_parameter_pool(
128_MiB,
4_MiB,
vk::BufferUsageFlagBits::eIndirectBuffer | vk::BufferUsageFlagBits::eStorageBuffer,
vk::MemoryPropertyFlagBits::eDeviceLocal | vk::MemoryPropertyFlagBits::eHostVisible ),
m_gpu_draw_commands(
@@ -68,7 +69,7 @@ namespace fgl::engine
// memory::TransferManager::createInstance( device, 128_MiB );
m_draw_parameter_pool.setDebugName( "Draw parameter pool" );
m_draw_parameter_pool->setDebugName( "Draw parameter pool" );
}
static Average< float, 60 * 15 > rolling_ms_average;
@@ -159,9 +160,6 @@ namespace fgl::engine
TracyVkCollect( frame_info.tracy_ctx, **command_buffers.transfer_cb );
//TODO: Setup semaphores to make this pass not always required.
m_transfer_manager.recordOwnershipTransferDst( command_buffers.transfer_cb );
for ( const auto& hook : m_early_render_hooks ) hook( frame_info );
//TODO: Add some way of 'activating' cameras. We don't need to render cameras that aren't active.
renderCameras( frame_info );
@@ -175,9 +173,13 @@ namespace fgl::engine
m_renderer.endSwapchainRendererPass( command_buffers.imgui_cb );
m_transfer_manager.recordOwnershipTransferDst( command_buffers.transfer_cb );
m_renderer.endFrame( command_buffers );
//TODO: Setup semaphores to make this pass not always required.
m_transfer_manager.dump();
m_device.getCmdBufferPool().advanceInFlight();
{

View File

@@ -87,7 +87,7 @@ namespace fgl::engine
CameraManager m_camera_manager {};
memory::TransferManager m_transfer_manager { m_device, 128_MiB };
memory::TransferManager m_transfer_manager { m_device, 32_MiB };
std::chrono::time_point< Clock > m_last_tick { Clock::now() };
DeltaTime m_delta_time;

View File

@@ -6,6 +6,7 @@
#include "engine/debug/logging/logging.hpp"
#include "engine/math/literals/size.hpp"
#include "material/Material.hpp"
#include "memory/buffers/BufferHandle.hpp"
namespace fgl::engine
{
@@ -24,7 +25,7 @@ namespace fgl::engine
vk::MemoryPropertyFlagBits::eDeviceLocal | vk::MemoryPropertyFlagBits::eHostVisible ),
m_material_data( m_material_data_pool, MAX_MATERIAL_COUNT )
{
m_material_data_pool.setDebugName( "Material data pool" );
m_material_data_pool->setDebugName( "Material data pool" );
}
MaterialManager::~MaterialManager()

View File

@@ -3,7 +3,7 @@
//
#pragma once
#include "engine/memory/buffers/Buffer.hpp"
#include "engine/memory/buffers/BufferHandle.hpp"
#include "material/Material.hpp"
#include "memory/buffers/vector/DeviceVector.hpp"

View File

@@ -30,7 +30,7 @@ namespace fgl::engine
vk::BufferUsageFlagBits::eStorageBuffer | vk::BufferUsageFlagBits::eTransferDst,
vk::MemoryPropertyFlagBits::eDeviceLocal | vk::MemoryPropertyFlagBits::eHostVisible ),
m_vertex_buffer(
256_MiB,
2_MiB,
vk::BufferUsageFlagBits::eVertexBuffer | vk::BufferUsageFlagBits::eStorageBuffer
| vk::BufferUsageFlagBits::eTransferDst,
vk::MemoryPropertyFlagBits::eDeviceLocal ),

View File

@@ -36,7 +36,7 @@ namespace fgl::engine
namespace memory
{
class Buffer;
class BufferHandle;
}
struct ModelBuilder;

View File

@@ -8,27 +8,24 @@
#include <vector>
#include "engine/primitives/Transform.hpp"
#include "memory/buffers/BufferHandle.hpp"
namespace fgl::engine
{
struct ModelVertex;
struct Primitive;
namespace memory
{
class Buffer;
}
struct ModelBuilder
{
memory::Buffer& m_vertex_buffer;
memory::Buffer& m_index_buffer;
memory::Buffer m_vertex_buffer;
memory::Buffer m_index_buffer;
std::vector< Primitive > m_primitives {};
ModelBuilder() = delete;
ModelBuilder( memory::Buffer& parent_vertex_buffer, memory::Buffer& parent_index_buffer ) :
ModelBuilder(
const memory::Buffer& parent_vertex_buffer, const memory::Buffer& parent_index_buffer ) :
m_vertex_buffer( parent_vertex_buffer ),
m_index_buffer( parent_index_buffer )
{}

View File

@@ -13,7 +13,6 @@
#pragma GCC diagnostic pop
#include "assets/model/ModelVertex.hpp"
#include "engine/assets/image/ImageView.hpp"
#include "engine/assets/stores.hpp"
#include "engine/camera/Camera.hpp"
#include "engine/debug/logging/logging.hpp"
@@ -23,7 +22,7 @@
namespace fgl::engine
{
SceneBuilder::SceneBuilder( memory::Buffer& vertex_buffer, memory::Buffer& index_buffer ) :
SceneBuilder::SceneBuilder( const memory::Buffer& vertex_buffer, const memory::Buffer& index_buffer ) :
m_vertex_buffer( vertex_buffer ),
m_index_buffer( index_buffer )
{}

View File

@@ -30,7 +30,7 @@ namespace fgl::engine
namespace memory
{
class Buffer;
class BufferHandle;
}
} // namespace fgl::engine
@@ -50,8 +50,8 @@ namespace fgl::engine
{
//! Root path. Set by 'load' functions
std::filesystem::path m_root {};
memory::Buffer& m_vertex_buffer;
memory::Buffer& m_index_buffer;
memory::Buffer m_vertex_buffer;
memory::Buffer m_index_buffer;
std::vector< GameObject > game_objects {};
@@ -92,7 +92,7 @@ namespace fgl::engine
SceneBuilder() = delete;
SceneBuilder( memory::Buffer& vertex_buffer, memory::Buffer& index_buffer );
SceneBuilder( const memory::Buffer& vertex_buffer, const memory::Buffer& index_buffer );
void loadScene( const std::filesystem::path& path );
};

View File

@@ -6,8 +6,7 @@
#include "engine/assets/image/ImageHandle.hpp"
#include "engine/debug/logging/logging.hpp"
#include "engine/math/literals/size.hpp"
#include "engine/memory/buffers/Buffer.hpp"
#include "engine/memory/buffers/BufferHandle.hpp"
#include "engine/memory/buffers/exceptions.hpp"
#include "engine/memory/buffers/vector/HostVector.hpp"
#include "engine/utils.hpp"
@@ -107,8 +106,8 @@ namespace fgl::engine::memory
bool TransferData::performRawImageStage(
vk::raii::CommandBuffer& buffer,
Buffer& staging_buffer,
std::uint32_t transfer_idx,
std::uint32_t graphics_idx )
const std::uint32_t transfer_idx,
const std::uint32_t graphics_idx )
{
if ( !convertRawToBuffer( staging_buffer ) ) return false;
return performImageStage( buffer, transfer_idx, graphics_idx );
@@ -147,10 +146,10 @@ namespace fgl::engine::memory
{
// Prepare the staging buffer first.
assert( std::holds_alternative< RawData >( m_source ) );
assert( std::get< RawData >( m_source ).size() > 0 );
assert( !std::get< RawData >( m_source ).empty() );
// Check if we are capable of allocating into the staging buffer
if ( !staging_buffer.canAllocate( std::get< RawData >( m_source ).size(), 1 ) ) return false;
if ( !staging_buffer->canAllocate( std::get< RawData >( m_source ).size(), 1 ) ) return false;
HostVector< std::byte > vector { staging_buffer, std::get< RawData >( m_source ) };

View File

@@ -8,6 +8,8 @@
#include <unordered_map>
#include <vector>
#include "engine/memory/buffers/BufferHandle.hpp"
namespace vk
{
namespace raii
@@ -27,7 +29,7 @@ namespace fgl::engine
namespace memory
{
struct BufferSuballocationHandle;
class Buffer;
class BufferHandle;
} // namespace memory
} // namespace fgl::engine
@@ -87,8 +89,8 @@ namespace fgl::engine::memory
bool performRawImageStage(
vk::raii::CommandBuffer& buffer,
Buffer& staging_buffer,
std::uint32_t graphics_idx,
std::uint32_t transfer_idx );
std::uint32_t transfer_idx,
std::uint32_t graphics_idx );
bool performBufferStage( CopyRegionMap& copy_regions );
@@ -126,12 +128,12 @@ namespace fgl::engine::memory
TransferData(
const std::shared_ptr< BufferSuballocationHandle >& source,
const std::shared_ptr< BufferSuballocationHandle >& target,
const std::size_t offset );
std::size_t offset );
TransferData(
std::vector< std::byte >&& source,
const std::shared_ptr< BufferSuballocationHandle >& target,
const std::size_t offset );
std::size_t offset );
//IMAGE_FROM_X
TransferData(

View File

@@ -8,7 +8,7 @@
#include "engine/assets/image/ImageHandle.hpp"
#include "engine/assets/texture/Texture.hpp"
#include "engine/math/literals/size.hpp"
#include "engine/memory/buffers/Buffer.hpp"
#include "engine/memory/buffers/BufferHandle.hpp"
#include "engine/memory/buffers/BufferSuballocation.hpp"
#include "engine/memory/buffers/vector/HostVector.hpp"
@@ -19,12 +19,12 @@ namespace fgl::engine::memory
ZoneScoped;
//Keep inserting new commands until we fill up the staging buffer
if ( m_queue.size() > 0 ) log::info( "[TransferManager]: Queue size: {}", m_queue.size() );
if ( !m_queue.empty() ) log::info( "[TransferManager]: Queue size: {}", m_queue.size() );
std::size_t counter { 0 };
constexpr std::size_t counter_max { 256 };
while ( m_queue.size() > 0 )
while ( !m_queue.empty() )
{
++counter;
if ( counter > counter_max ) break;
@@ -34,7 +34,7 @@ namespace fgl::engine::memory
if ( data.stage(
command_buffer,
*m_staging_buffer,
m_staging_buffer,
m_copy_regions,
m_transfer_queue_index,
m_graphics_queue_index ) )
@@ -44,7 +44,7 @@ namespace fgl::engine::memory
else
{
// We were unable to stage for a reason
log::info( "Unable to stage object. Breaking out of loop" );
log::debug( "Unable to stage object. Breaking out of loop, Objects will be staged next pass" );
m_queue.push( data );
break;
}
@@ -92,10 +92,7 @@ namespace fgl::engine::memory
void TransferManager::resizeBuffer( const std::uint64_t size )
{
m_staging_buffer = std::make_unique< Buffer >(
size,
vk::BufferUsageFlagBits::eTransferSrc,
vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent );
m_staging_buffer->resize( size );
}
void TransferManager::submitBuffer( vk::raii::CommandBuffer& command_buffer )
@@ -258,6 +255,7 @@ namespace fgl::engine::memory
m_processing.clear();
m_copy_regions.clear();
m_allow_transfers = true;
}
TransferManager& TransferManager::getInstance()
@@ -273,7 +271,7 @@ namespace fgl::engine::memory
m_queue.emplace( std::move( transfer_data ) );
}
void TransferManager::copyToImage( std::vector< std::byte >&& data, Image& image )
void TransferManager::copyToImage( std::vector< std::byte >&& data, const Image& image )
{
assert( data.size() > 0 );
TransferData transfer_data { std::forward< std::vector< std::byte > >( data ), image.m_handle };
@@ -283,12 +281,11 @@ namespace fgl::engine::memory
m_queue.emplace( std::move( transfer_data ) );
}
TransferManager::TransferManager( Device& device, std::uint64_t buffer_size ) :
TransferManager::TransferManager( Device& device, const vk::DeviceSize buffer_size ) :
m_staging_buffer(
std::make_unique< Buffer >(
buffer_size,
vk::BufferUsageFlagBits::eTransferSrc,
vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent ) ),
buffer_size,
vk::BufferUsageFlagBits::eTransferSrc,
vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent ),
m_transfer_queue_index( device.phyDevice()
.queueInfo()
.getIndex( vk::QueueFlagBits::eTransfer, vk::QueueFlagBits::eGraphics ) ),
@@ -308,6 +305,8 @@ namespace fgl::engine::memory
{
ZoneScoped;
m_allow_transfers = false;
auto& transfer_buffer { m_transfer_buffers[ 0 ] };
transfer_buffer.reset();

View File

@@ -35,7 +35,7 @@ namespace fgl::engine::memory
//TODO: Ring Buffer
//! Buffer used for any raw -> buffer transfers
std::unique_ptr< Buffer > m_staging_buffer {};
Buffer m_staging_buffer;
//! Queue of data needing to be transfered and submitted.
std::queue< TransferData > m_queue {};
@@ -59,6 +59,9 @@ namespace fgl::engine::memory
vk::raii::Fence m_completion_fence;
//! True if transfers would be performed before the start of the next frame
bool m_allow_transfers { true };
void recordCommands( vk::raii::CommandBuffer& command_buffer );
void submitBuffer( vk::raii::CommandBuffer& command_buffer );
@@ -77,7 +80,7 @@ namespace fgl::engine::memory
public:
TransferManager( Device& device, std::uint64_t buffer_size );
TransferManager( Device& device, vk::DeviceSize buffer_size );
FGL_DELETE_ALL_RO5( TransferManager );
@@ -97,6 +100,22 @@ namespace fgl::engine::memory
//! Resizes the staging buffer.
void resizeBuffer( std::uint64_t size );
void copySuballocationRegion(
const std::shared_ptr< BufferSuballocationHandle >& src,
const std::shared_ptr< BufferSuballocationHandle >& dst,
const std::size_t offset = 0 )
{
FGL_ASSERT( src->m_size == dst->m_size, "Source and destination suballocations must be the same size" );
TransferData transfer_data {
src,
dst,
offset,
};
m_queue.emplace( std::move( transfer_data ) );
}
//! Queues a buffer to be transfered
template < typename DeviceVectorT >
requires is_device_vector< DeviceVectorT >
@@ -140,7 +159,7 @@ namespace fgl::engine::memory
void copyToVector( BufferVector& source, BufferVector& target, std::size_t target_offset );
void copyToImage( std::vector< std::byte >&& data, Image& image );
void copyToImage( std::vector< std::byte >&& data, const Image& image );
//! Forces the queue to be submitted now before the buffer is filled.
void submitNow();

View File

@@ -186,7 +186,7 @@ namespace fgl::engine
void updateInfo( FrameIndex frame_index );
descriptors::DescriptorSet& getDescriptor( FrameIndex index );
void setFOV( const float fov_y );
void setFOV( float fov_y );
//! Performs the render pass for this camera
void pass( FrameInfo& frame_info );

View File

@@ -6,7 +6,7 @@
#include <vector>
#include "Camera.hpp"
#include "engine/memory/buffers/Buffer.hpp"
#include "engine/memory/buffers/BufferHandle.hpp"
namespace fgl::engine
{

View File

@@ -35,7 +35,8 @@ namespace fgl::engine::debug
void deregisterTrack( const std::size_t UID )
{
assert( track_info.erase( UID ) > 0 && "Unable to find UID" );
track_info.erase( UID );
// assert( track_info.erase( UID ) > 0 && "Unable to find UID" );
}
std::vector< TrackInfo > getTracks( const std::string_view group, const std::string_view name )

View File

@@ -28,10 +28,12 @@ namespace fgl::engine::debug
std::vector< TrackInfo > getTracks( std::string_view group, std::string_view name );
std::vector< TrackInfo > getAllTracks();
constexpr TrackUID INVALID_TRACK_ID { std::numeric_limits< TrackUID >::max() };
template < TString Group, TString Name >
class Track
{
TrackUID UID;
TrackUID UID { INVALID_TRACK_ID };
public:
@@ -39,6 +41,11 @@ namespace fgl::engine::debug
UID( registerTrack( Group, Name, size, trace ) )
{}
Track( Track&& other ) = default;
Track( const Track& other ) = default;
Track& operator=( Track&& other ) = default;
Track& operator=( const Track& other ) = default;
~Track() { deregisterTrack( UID ); }
};

View File

@@ -4,9 +4,9 @@
#pragma once
#include <cstdint>
#include <vulkan/vulkan_raii.hpp>
#include "engine/memory/buffers/Buffer.hpp"
#include <cstdint>
namespace fgl::engine::descriptors
{

View File

@@ -0,0 +1,11 @@
//
// Created by kj16609 on 4/9/25.
//
#pragma once
namespace fgl::engine::memory
{
void deferredDelete( auto&& item ) {}
}

View File

@@ -2,27 +2,39 @@
// Created by kj16609 on 12/30/23.
//
#include "Buffer.hpp"
#include "BufferHandle.hpp"
#include <iostream>
#include <tuple>
#include "BufferSuballocationHandle.hpp"
#include "align.hpp"
#include "assets/transfer/TransferManager.hpp"
#include "engine/debug/logging/logging.hpp"
#include "engine/memory/buffers/BufferHandle.hpp"
#include "engine/memory/buffers/exceptions.hpp"
#include "engine/rendering/devices/Device.hpp"
#include "memory/DefferedCleanup.hpp"
namespace fgl::engine::memory
{
inline static std::vector< Buffer* > active_buffers {};
std::vector< Buffer* > getActiveBuffers()
void BufferHandle::swap( BufferHandle& other ) noexcept
{
return active_buffers;
std::swap( m_buffer, other.m_buffer );
std::swap( m_allocation, other.m_allocation );
std::swap( m_alloc_info, other.m_alloc_info );
std::swap( m_memory_size, other.m_memory_size );
std::swap( m_usage, other.m_usage );
std::swap( m_memory_properties, other.m_memory_properties );
std::swap( m_track, other.m_track );
std::swap( m_debug_name, other.m_debug_name );
std::swap( m_active_suballocations, other.m_active_suballocations );
std::swap( m_allocation_traces, other.m_allocation_traces );
std::swap( m_free_blocks, other.m_free_blocks );
}
Buffer::Buffer(
BufferHandle::BufferHandle(
vk::DeviceSize memory_size,
const vk::BufferUsageFlags usage,
const vk::MemoryPropertyFlags memory_properties ) :
@@ -30,19 +42,27 @@ namespace fgl::engine::memory
m_usage( usage ),
m_memory_properties( memory_properties )
{
alloc( memory_size );
active_buffers.emplace_back( this );
auto [ buffer, vma_alloc_info, vma_allocation ] = allocBuffer( memory_size, m_usage, m_memory_properties );
m_buffer = buffer;
m_alloc_info = vma_alloc_info;
m_allocation = vma_allocation;
m_free_blocks.emplace_back( 0, memory_size );
}
Buffer::~Buffer()
BufferHandle::~BufferHandle()
{
if ( !m_allocations.empty() )
if ( !m_active_suballocations.empty() )
{
log::critical( "Buffer allocations not empty. {} allocations left", m_allocations.size() );
log::critical( "Buffer allocations not empty. {} allocations left", m_active_suballocations.size() );
for ( const auto& [ offset, size ] : m_allocations )
for ( const auto& suballocation : m_active_suballocations )
{
if ( suballocation.expired() ) continue;
auto suballoc_ptr { suballocation.lock() };
const auto offset { suballoc_ptr->m_offset };
const auto size { suballoc_ptr->m_size };
log::info( "Stacktrace: Offset at {} with a size of {}", offset, size );
const auto itter = this->m_allocation_traces.find( offset );
@@ -56,71 +76,78 @@ namespace fgl::engine::memory
log::critical( "Buffer allocations were not empty!" );
// Call will always terminate
// throw std::runtime_error( "Buffer allocations not empty" );
throw std::runtime_error( "Buffer allocations not empty" );
}
dealloc();
if ( const auto itter = std::ranges::find( active_buffers, this ); itter != active_buffers.end() )
active_buffers.erase( itter );
deallocBuffer( m_buffer, m_allocation );
}
void* Buffer::map( const BufferSuballocationHandle& handle ) const
void* BufferHandle::map( const BufferSuballocationHandle& handle ) const
{
if ( m_alloc_info.pMappedData == nullptr ) return nullptr;
return static_cast< std::byte* >( m_alloc_info.pMappedData ) + handle.m_offset;
}
void Buffer::dealloc() const
void BufferHandle::deallocBuffer( vk::Buffer& buffer, VmaAllocation& allocation )
{
vmaDestroyBuffer( Device::getInstance().allocator(), m_buffer, m_allocation );
vmaDestroyBuffer( Device::getInstance().allocator(), buffer, allocation );
}
void Buffer::alloc( const vk::DeviceSize memory_size )
std::tuple< vk::Buffer, VmaAllocationInfo, VmaAllocation > BufferHandle::allocBuffer(
const vk::DeviceSize memory_size, vk::BufferUsageFlags usage, const vk::MemoryPropertyFlags property_flags )
{
assert( !m_debug_name.empty() );
// Used for resizing.
//TODO: Make this only available if resize is desired. Otherwise do not have it.
usage |= vk::BufferUsageFlagBits::eTransferDst;
usage |= vk::BufferUsageFlagBits::eTransferSrc;
assert( memory_size > 0 );
m_memory_size = memory_size;
vk::BufferCreateInfo buffer_info {};
buffer_info.pNext = VK_NULL_HANDLE;
buffer_info.flags = {};
buffer_info.size = m_memory_size;
buffer_info.usage = m_usage;
buffer_info.size = memory_size;
buffer_info.usage = usage;
buffer_info.sharingMode = vk::SharingMode::eExclusive;
buffer_info.queueFamilyIndexCount = 0;
buffer_info.pQueueFamilyIndices = VK_NULL_HANDLE;
VmaAllocationCreateInfo alloc_info {};
VmaAllocationCreateInfo create_info {};
alloc_info.usage = VMA_MEMORY_USAGE_AUTO;
create_info.usage = VMA_MEMORY_USAGE_AUTO;
if ( m_memory_properties & vk::MemoryPropertyFlagBits::eHostVisible )
alloc_info.flags |= VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT;
if ( property_flags & vk::MemoryPropertyFlagBits::eHostVisible )
create_info.flags |= VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT;
if ( m_usage & vk::BufferUsageFlagBits::eTransferSrc )
if ( usage & vk::BufferUsageFlagBits::eTransferSrc )
{
//Remove VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM BIT if we are transfer src
alloc_info.flags &= ~VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT;
create_info.flags &= ~VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT;
alloc_info.flags |= VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;
create_info.flags |= VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;
}
VmaAllocationInfo alloc_info {};
VmaAllocation allocation {};
const VkBufferCreateInfo& vk_buffer_info = buffer_info;
VkBuffer buffer { VK_NULL_HANDLE };
if ( vmaCreateBuffer(
Device::getInstance().allocator(), &vk_buffer_info, &alloc_info, &buffer, &m_allocation, nullptr )
Device::getInstance().allocator(), &vk_buffer_info, &create_info, &buffer, &allocation, nullptr )
!= VK_SUCCESS )
{
throw BufferException( "Unable to allocate memory in VMA" );
}
m_buffer = buffer;
vmaGetAllocationInfo( Device::getInstance().allocator(), allocation, &alloc_info );
vmaGetAllocationInfo( Device::getInstance().allocator(), m_allocation, &m_alloc_info );
return std::make_tuple<
vk::Buffer,
VmaAllocationInfo,
VmaAllocation >( std::move( buffer ), std::move( alloc_info ), std::move( allocation ) );
}
vk::DeviceSize Buffer::alignment() const
vk::DeviceSize BufferHandle::alignment() const
{
vk::DeviceSize size { 1 };
@@ -142,7 +169,7 @@ namespace fgl::engine::memory
return size;
}
decltype( Buffer::m_free_blocks )::iterator Buffer::
decltype( BufferHandle::m_free_blocks )::iterator BufferHandle::
findAvailableBlock( vk::DeviceSize memory_size, std::uint32_t t_alignment )
{
//Find a free space.
@@ -160,7 +187,63 @@ namespace fgl::engine::memory
} );
}
std::shared_ptr< BufferSuballocationHandle > Buffer::
void BufferHandle::resize( const vk::DeviceSize new_size )
{
log::warn( "Resizing buffer from {} to {}", size(), new_size );
std::shared_ptr< BufferHandle > new_handle { new BufferHandle( new_size, m_usage, m_memory_properties ) };
//Now we need to re-create all the current live allocations and transfer/replace them using the new buffer
std::vector<
std::pair< std::shared_ptr< BufferSuballocationHandle >, std::shared_ptr< BufferSuballocationHandle > > >
allocations {};
allocations.reserve( m_active_suballocations.size() );
for ( auto& suballocation_weak : m_active_suballocations )
{
if ( suballocation_weak.expired() ) continue;
try
{
auto suballocation { suballocation_weak.lock() };
auto new_suballocation { new_handle->allocate( suballocation->m_size, suballocation->m_alignment ) };
allocations.emplace_back( std::make_pair( suballocation, new_suballocation ) );
}
catch ( std::bad_weak_ptr& e )
{
// noop
void();
}
}
std::swap( m_buffer, new_handle->m_buffer );
std::swap( m_alloc_info, new_handle->m_alloc_info );
std::swap( m_allocation, new_handle->m_allocation );
std::swap( m_free_blocks, new_handle->m_free_blocks );
std::swap( m_active_suballocations, new_handle->m_active_suballocations );
std::swap( m_allocation_traces, new_handle->m_allocation_traces );
// This transforms any memory::Buffer to be the `new_handle` we allocated above.
const auto old_handle { new_handle };
FGL_ASSERT( old_handle.get() != this, "Old handle should not be the current buffer anymore!" );
new_handle = this->shared_from_this();
for ( auto& [ old_allocation, new_allocation ] : allocations )
{
old_allocation->m_parent_buffer = old_handle;
new_allocation->m_parent_buffer = new_handle;
}
//Now we need to transfer the data from the old buffer to the new buffer
for ( const auto& allocation : allocations )
{
const auto& [ old_suballocation, new_suballocation ] = allocation;
TransferManager::getInstance().copySuballocationRegion( old_suballocation, new_suballocation );
}
}
std::shared_ptr< BufferSuballocationHandle > BufferHandle::
allocate( vk::DeviceSize desired_memory_size, const std::uint32_t t_alignment )
{
ZoneScoped;
@@ -173,8 +256,14 @@ namespace fgl::engine::memory
if ( !canAllocate( desired_memory_size, t_alignment ) )
{
//TODO: Write more detailed error message
throw BufferOOM();
// Resize to x1.5 the size, or the size plus the desired size x1.5, Whichever is bigger
const auto optimal_size { std::
max( static_cast< vk::DeviceSize >( this->size() * 2 ),
this->size()
+ static_cast< vk::DeviceSize >( desired_memory_size * 2 ) ) };
this->resize( optimal_size );
FGL_ASSERT( optimal_size == this->size(), "Optimal size not met!" );
}
auto itter { findAvailableBlock( desired_memory_size, t_alignment ) };
@@ -209,9 +298,8 @@ namespace fgl::engine::memory
selected_block_size -= leftover_start_size;
}
//Add the suballocation
m_allocations.insert_or_assign( selected_block_offset, desired_memory_size );
// Add the suballocation
// m_allocations.insert_or_assign( selected_block_offset, desired_memory_size );
m_allocation_traces.insert_or_assign( selected_block_offset, std::stacktrace::current() );
assert( selected_block_size >= desired_memory_size );
@@ -226,26 +314,18 @@ namespace fgl::engine::memory
.emplace_back( selected_block_offset + desired_memory_size, selected_block_size - desired_memory_size );
}
#ifndef NDEBUG
//Check that we haven't lost any memory
std::size_t sum { 0 };
for ( const auto& [ _, free_size ] : this->m_free_blocks )
{
sum += free_size;
}
std::ranges::
remove_if( m_active_suballocations, []( auto& suballocation ) -> bool { return suballocation.expired(); } );
for ( const auto& [ _, allocated_size ] : this->m_allocations )
{
sum += allocated_size;
}
auto suballocation_handle { std::make_shared< BufferSuballocationHandle >(
Buffer( this->shared_from_this() ), selected_block_offset, desired_memory_size, t_alignment ) };
assert( sum == this->size() );
#endif
m_active_suballocations.push_back( suballocation_handle );
return std::make_shared< BufferSuballocationHandle >( *this, selected_block_offset, desired_memory_size );
return suballocation_handle;
}
bool Buffer::canAllocate( const vk::DeviceSize memory_size, const std::uint32_t alignment )
bool BufferHandle::canAllocate( const vk::DeviceSize memory_size, const std::uint32_t alignment )
{
// TODO: This check can be optimized by itterating through and virtually combining blocks that would be combined.
// If the combined block is large enough then we should consider it being capable of allocation.
@@ -256,11 +336,11 @@ namespace fgl::engine::memory
mergeFreeBlocks();
return findAvailableBlock( memory_size, alignment ) != m_free_blocks.end();
}
else
return true;
return true;
}
void Buffer::mergeFreeBlocks()
void BufferHandle::mergeFreeBlocks()
{
ZoneScoped;
//Can't combine blocks if there is only 1
@@ -304,7 +384,7 @@ namespace fgl::engine::memory
}
}
void Buffer::setDebugName( const std::string& str )
void BufferHandle::setDebugName( const std::string& str )
{
vk::DebugUtilsObjectNameInfoEXT info {};
info.objectType = vk::ObjectType::eBuffer;
@@ -316,18 +396,10 @@ namespace fgl::engine::memory
Device::getInstance().setDebugUtilsObjectName( info );
}
void Buffer::free( BufferSuballocationHandle& info )
void BufferHandle::free( BufferSuballocationHandle& info )
{
ZoneScoped;
//Find the suballocation
auto itter = m_allocations.find( info.m_offset );
if ( itter == m_allocations.end() ) throw std::runtime_error( "Failed to find suballocation" );
//Remove the suballocation
m_allocations.erase( itter );
if ( info.m_offset >= this->size() ) throw std::runtime_error( "Offset was outside of bounds of buffer" );
if ( info.m_offset + info.m_size > this->size() )
throw std::runtime_error(
@@ -351,9 +423,10 @@ namespace fgl::engine::memory
sum += free_blocks.second;
}
for ( const auto& allocated : this->m_allocations )
for ( auto& suballocation : m_active_suballocations )
{
sum += allocated.second;
if ( suballocation.expired() ) continue;
sum += suballocation.lock()->m_size;
}
if ( sum != this->size() )
@@ -362,21 +435,19 @@ namespace fgl::engine::memory
#endif
}
vk::DeviceSize Buffer::used() const
vk::DeviceSize BufferHandle::used() const
{
vk::DeviceSize total_size { 0 };
if ( m_allocations.size() == 0 ) return total_size;
for ( const auto& [ offset, size ] : m_allocations )
for ( auto& suballocation : m_active_suballocations )
{
total_size += size;
total_size += suballocation.lock()->m_size;
}
return total_size;
}
vk::DeviceSize Buffer::largestBlock() const
vk::DeviceSize BufferHandle::largestBlock() const
{
vk::DeviceSize largest { 0 };

View File

@@ -14,7 +14,9 @@
#include <memory>
#include <stacktrace>
#include <unordered_map>
#include <utility>
#include "FGL_DEFINES.hpp"
#include "engine/debug/Track.hpp"
#include "vma/vma_impl.hpp"
@@ -39,7 +41,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)
class Buffer
class BufferHandle : public std::enable_shared_from_this< BufferHandle >
{
vk::Buffer m_buffer { VK_NULL_HANDLE };
VmaAllocation m_allocation {};
@@ -52,26 +54,42 @@ namespace fgl::engine::memory
vk::BufferUsageFlags m_usage;
vk::MemoryPropertyFlags m_memory_properties;
std::vector< std::weak_ptr< BufferSuballocationHandle > > m_active_suballocations {};
std::unordered_map< vk::DeviceSize, std::stacktrace > m_allocation_traces {};
//! @brief List of all active suballocations
//! <offset, size>
using AllocationSize = vk::DeviceSize;
//! @brief list of any free blocks
//! @note All blocks are amalgamated to the largest they can expand to.
//! <offset, size>
std::vector< std::pair< vk::DeviceSize, vk::DeviceSize > > m_free_blocks {};
public:
std::string m_debug_name { "Debug name" };
private:
void alloc( vk::DeviceSize memory_size );
void dealloc() const;
static std::tuple< vk::Buffer, VmaAllocationInfo, VmaAllocation > allocBuffer(
vk::DeviceSize memory_size, vk::BufferUsageFlags usage, vk::MemoryPropertyFlags property_flags );
static void deallocBuffer( vk::Buffer&, VmaAllocation& );
Buffer() = delete;
Buffer( const Buffer& other ) = delete;
Buffer& operator=( const Buffer& other ) = delete;
Buffer( Buffer&& other ) = delete;
Buffer& operator=( Buffer&& other ) = delete;
BufferHandle() = delete;
BufferHandle( const BufferHandle& other ) = delete;
BufferHandle& operator=( const BufferHandle& other ) = delete;
BufferHandle( BufferHandle&& other ) = delete;
BufferHandle& operator=( BufferHandle&& other ) = delete;
void swap( BufferHandle& other ) noexcept;
public:
Buffer( vk::DeviceSize memory_size, vk::BufferUsageFlags usage, vk::MemoryPropertyFlags memory_properties );
BufferHandle(
vk::DeviceSize memory_size, vk::BufferUsageFlags usage, vk::MemoryPropertyFlags memory_properties );
~Buffer();
~BufferHandle();
auto address() const { return m_alloc_info.deviceMemory; }
@@ -81,27 +99,6 @@ namespace fgl::engine::memory
vk::DeviceSize used() const;
private:
void* map( const BufferSuballocationHandle& handle ) const;
//! Returns the required alignment for this buffer.
vk::DeviceSize alignment() const;
//! @brief List of all active suballocations
//! <offset, size>
using AllocationSize = vk::DeviceSize;
std::map< vk::DeviceSize, AllocationSize > m_allocations {};
std::unordered_map< vk::DeviceSize, std::stacktrace > m_allocation_traces {};
//! @brief list of any free blocks
//! @note All blocks are amalgamated to the largest they can expand to.
//! <offset, size>
std::vector< std::pair< vk::DeviceSize, vk::DeviceSize > > m_free_blocks {};
decltype( m_free_blocks )::iterator findAvailableBlock( vk::DeviceSize memory_size, std::uint32_t t_alignment );
public:
//! Returns the vulkan buffer handle for this buffer
@@ -120,12 +117,12 @@ namespace fgl::engine::memory
friend gui::AllocationList gui::getTotalAllocated();
public:
bool isMappable() const { return m_alloc_info.pMappedData != nullptr; }
void resize( vk::DeviceSize new_size );
//! 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)
/**
* @param desired_memory_size Size of each N
* @param alignment The alignment to use.
@@ -150,7 +147,27 @@ namespace fgl::engine::memory
void mergeFreeBlocks();
void setDebugName( const std::string& str );
private:
void* map( const BufferSuballocationHandle& handle ) const;
//! Returns the required alignment for this buffer.
vk::DeviceSize alignment() const;
decltype( m_free_blocks )::iterator findAvailableBlock( vk::DeviceSize memory_size, std::uint32_t t_alignment );
};
std::vector< Buffer* > getActiveBuffers();
struct Buffer final : public std::shared_ptr< BufferHandle >
{
Buffer( vk::DeviceSize memory_size, vk::BufferUsageFlags usage, vk::MemoryPropertyFlags memory_properties ) :
std::shared_ptr< BufferHandle >( std::make_shared< BufferHandle >( memory_size, usage, memory_properties ) )
{}
Buffer( const std::shared_ptr< BufferHandle >& buffer ) : std::shared_ptr< BufferHandle >( buffer ) {}
~Buffer() = default;
};
std::vector< std::weak_ptr< Buffer > > getActiveBuffers();
} // namespace fgl::engine::memory

View File

@@ -4,7 +4,6 @@
#include "BufferSuballocation.hpp"
#include "Buffer.hpp"
#include "BufferSuballocationHandle.hpp"
#include "SuballocationView.hpp"
#include "align.hpp"
@@ -62,7 +61,7 @@ namespace fgl::engine::memory
assert( end <= this->m_byte_size );
vk::MappedMemoryRange range {};
range.memory = m_handle->m_buffer.getMemory();
range.memory = m_handle->m_parent_buffer->getMemory();
range.offset = m_offset + beg;
const vk::DeviceSize min_atom_size { Device::getInstance().m_properties.limits.nonCoherentAtomSize };
@@ -85,14 +84,14 @@ namespace fgl::engine::memory
{
assert( m_handle != nullptr );
return m_handle->m_buffer;
return m_handle->m_parent_buffer;
}
vk::Buffer BufferSuballocation::getVkBuffer() const
{
assert( m_handle != nullptr );
return m_handle->m_buffer.getVkBuffer();
return m_handle->m_parent_buffer->getVkBuffer();
}
vk::DescriptorBufferInfo BufferSuballocation::descriptorInfo( const std::size_t byte_offset ) const
@@ -102,7 +101,7 @@ namespace fgl::engine::memory
FGL_ASSERT( byte_offset < m_byte_size, "Byte offset was greater then byte size!" );
FGL_ASSERT(
m_offset + byte_offset < this->getBuffer().size(),
m_offset + byte_offset < this->getBuffer()->size(),
"Byte offset + buffer offset was greater then parent buffer size" );
return { getVkBuffer(), m_offset + byte_offset, m_byte_size };
@@ -118,12 +117,12 @@ namespace fgl::engine::memory
return { m_handle, offset, size };
}
BufferSuballocation::BufferSuballocation( Buffer& buffer, const vk::DeviceSize size ) :
BufferSuballocation( buffer.allocate( size ) )
BufferSuballocation::BufferSuballocation( const Buffer& buffer, const vk::DeviceSize size ) :
BufferSuballocation( buffer->allocate( size ) )
{}
BufferSuballocation::BufferSuballocation( Buffer& buffer, const std::size_t t_size, const std::uint32_t t_align ) :
BufferSuballocation( buffer.allocate( t_size, t_align ) )
BufferSuballocation::BufferSuballocation( const Buffer& buffer, const std::size_t t_size, const std::uint32_t t_align ) :
BufferSuballocation( buffer->allocate( t_size, t_align ) )
{}
} // namespace fgl::engine::memory

View File

@@ -10,7 +10,7 @@
namespace fgl::engine::memory
{
class Buffer;
class BufferHandle;
class SuballocationView;
struct BufferSuballocationHandle;
@@ -30,7 +30,7 @@ namespace fgl::engine::memory
void flush( vk::DeviceSize beg, vk::DeviceSize end ) const;
explicit BufferSuballocation( Buffer& buffer, std::size_t t_size, std::uint32_t t_align );
explicit BufferSuballocation( const Buffer& buffer, std::size_t t_size, std::uint32_t t_align );
public:
@@ -39,7 +39,7 @@ namespace fgl::engine::memory
BufferSuballocation() = delete;
BufferSuballocation( std::shared_ptr< BufferSuballocationHandle > handle );
BufferSuballocation( Buffer& buffer, vk::DeviceSize size );
BufferSuballocation( const Buffer& buffer, vk::DeviceSize size );
FGL_DELETE_COPY( BufferSuballocation );

View File

@@ -4,35 +4,40 @@
#include "BufferSuballocationHandle.hpp"
#include "Buffer.hpp"
#include "BufferHandle.hpp"
#include "BufferSuballocation.hpp"
#include "assets/transfer/TransferManager.hpp"
#include "engine/debug/logging/logging.hpp"
namespace fgl::engine::memory
{
vk::Buffer BufferSuballocationHandle::getBuffer() const
{
return m_buffer.getVkBuffer();
return m_parent_buffer->getVkBuffer();
}
BufferSuballocationHandle::
BufferSuballocationHandle( Buffer& p_buffer, const vk::DeviceSize offset, const vk::DeviceSize memory_size ) :
m_buffer( p_buffer ),
BufferSuballocationHandle::BufferSuballocationHandle(
const Buffer& p_buffer,
const vk::DeviceSize offset,
const vk::DeviceSize memory_size,
const vk::DeviceSize alignment ) :
m_parent_buffer( p_buffer ),
m_size( memory_size ),
m_offset( offset ),
m_ptr( m_buffer.map( *this ) )
m_alignment( alignment ),
m_ptr( m_parent_buffer->map( *this ) )
{
// assert( memory_size != 0 && "BufferSuballocation::BufferSuballocation() called with memory_size == 0" );
}
vk::Buffer BufferSuballocationHandle::getVkBuffer() const
{
return m_buffer.getVkBuffer();
return m_parent_buffer->getVkBuffer();
}
BufferSuballocationHandle::~BufferSuballocationHandle()
{
m_buffer.free( *this );
m_parent_buffer->free( *this );
}
vk::BufferCopy BufferSuballocationHandle::

View File

@@ -6,8 +6,7 @@
#include <vulkan/vulkan.hpp>
#include <memory>
#include "BufferHandle.hpp"
#include "engine/debug/Track.hpp"
namespace vk::raii
@@ -17,11 +16,11 @@ namespace vk::raii
namespace fgl::engine::memory
{
class Buffer;
class BufferHandle;
struct BufferSuballocationHandle
struct BufferSuballocationHandle : public std::enable_shared_from_this< BufferSuballocationHandle >
{
Buffer& m_buffer;
Buffer m_parent_buffer;
debug::Track< "GPU", "BufferSuballocationHandle" > m_track {};
@@ -31,27 +30,28 @@ namespace fgl::engine::memory
//! Offset within buffer
vk::DeviceSize m_offset;
//! Alignment used when allocating
vk::DeviceSize m_alignment;
void* m_ptr { nullptr };
bool m_staged { false };
BufferSuballocationHandle() = delete;
BufferSuballocationHandle(
const Buffer& p_buffer, vk::DeviceSize offset, vk::DeviceSize memory_size, vk::DeviceSize alignment );
FGL_DELETE_DEFAULT_CTOR( BufferSuballocationHandle );
FGL_DELETE_MOVE( BufferSuballocationHandle );
FGL_DELETE_COPY( BufferSuballocationHandle );
BufferSuballocationHandle( Buffer& p_buffer, vk::DeviceSize offset, vk::DeviceSize memory_size );
~BufferSuballocationHandle();
BufferSuballocationHandle( const BufferSuballocationHandle& ) = delete;
BufferSuballocationHandle& operator=( const BufferSuballocationHandle& ) = delete;
BufferSuballocationHandle( BufferSuballocationHandle&& ) = delete;
BufferSuballocationHandle& operator=( BufferSuballocationHandle&& ) = delete;
[[nodiscard]] vk::Buffer getBuffer() const;
[[nodiscard]] vk::Buffer getVkBuffer() const;
[[nodiscard]] vk::BufferCopy copyRegion( const BufferSuballocationHandle& target, std::size_t offset ) const;
vk::DeviceSize getOffset() const { return m_offset; }
[[nodiscard]] vk::DeviceSize getOffset() const { return m_offset; }
void copyTo(
const vk::raii::CommandBuffer& cmd_buffer,

View File

@@ -10,7 +10,7 @@ namespace fgl::engine
{
namespace memory
{
class Buffer;
struct Buffer;
}
//! Single element allocation of T
@@ -26,7 +26,7 @@ namespace fgl::engine
HostSingleT( HostSingleT&& ) = delete;
HostSingleT& operator=( const HostSingleT& ) = delete;
HostSingleT( memory::Buffer& buffer ) : memory::BufferSuballocation( buffer, sizeof( T ), alignof( T ) ) {}
HostSingleT( const memory::Buffer& buffer ) : memory::BufferSuballocation( buffer, sizeof( T ), alignof( T ) ) {}
HostSingleT& operator=( T& t )
{

View File

@@ -13,12 +13,11 @@ namespace fgl::engine
template < memory::is_suballocation Suballocation >
class PerFrameSuballocation
{
memory::Buffer& m_buffer;
std::vector< std::unique_ptr< Suballocation > > m_suballocations {};
public:
explicit PerFrameSuballocation( memory::Buffer& buffer ) : m_buffer( buffer )
explicit PerFrameSuballocation( memory::Buffer& buffer )
{
m_suballocations.reserve( constants::MAX_FRAMES_IN_FLIGHT );
@@ -31,9 +30,9 @@ namespace fgl::engine
}
}
void setMaxFramesInFlight( std::uint16_t max ) { m_suballocations.resize( max ); }
// void setMaxFramesInFlight( std::uint16_t max ) { m_suballocations.resize( max ); }
Suballocation& operator[]( std::uint16_t index )
Suballocation& operator[]( std::size_t index )
{
assert( m_suballocations.size() >= index );
assert( m_suballocations[ index ] );

View File

@@ -5,7 +5,8 @@
#include "BufferVector.hpp"
#include "engine/assets/transfer/TransferManager.hpp"
#include "engine/memory/buffers/Buffer.hpp"
#include "engine/memory/buffers/BufferHandle.hpp"
#include "memory/buffers/BufferHandle.hpp"
namespace fgl::engine::memory
{
@@ -13,10 +14,10 @@ namespace fgl::engine::memory
constexpr std::uint32_t min_capacity { 1024 };
[[nodiscard]] BufferVector::BufferVector( Buffer& buffer, std::uint32_t count, std::uint32_t stride ) :
BufferSuballocation( buffer.allocate( std::max( count, min_capacity ) * stride, stride ) ),
BufferSuballocation( buffer->allocate( std::max( count, min_capacity ) * stride, stride ) ),
m_count( count ),
m_stride( stride ),
m_capacity( std::max( count, min_capacity ) )
m_capacity( std::max( count, min_capacity ) ),
m_stride( stride )
{
FGL_ASSERT( m_stride > 0, "Stride was not greater then zero" );
FGL_ASSERT(

View File

@@ -8,8 +8,6 @@
namespace fgl::engine::memory
{
class Buffer;
//! Number of spares to allocate when resizing beyond the current capacity + current spare
constexpr std::uint32_t SPARE_ALLOCATION_COUNT { 16 };

View File

@@ -11,7 +11,7 @@
namespace fgl::engine::memory
{
class Buffer;
struct Buffer;
}
namespace fgl::engine
@@ -31,6 +31,7 @@ namespace fgl::engine
// assert( count != 0 && "BufferSuballocationVector::BufferSuballocationVector() called with count == 0" );
}
FGL_DELETE_DEFAULT_CTOR( DeviceVector );
FGL_DELETE_COPY( DeviceVector );
FGL_DEFAULT_MOVE( DeviceVector );
@@ -43,9 +44,6 @@ namespace fgl::engine
DeviceVector( buffer, static_cast< std::uint32_t >( data.size() ) )
{
memory::TransferManager::getInstance().copyToVector< T, DeviceVector< T > >( data, *this );
log::debug(
"Allocated device vector of size: {}, With stride: {} at offset {}", size(), stride(), m_offset );
}
// void resize( const std::size_t new_size ) { BufferVector::resize( new_size ); }

View File

@@ -19,7 +19,7 @@ namespace fgl::engine
* @tparam CType
*/
template < CoordinateSpace CType >
class FGL_PACKED SimplePlane
class SimplePlane
{
NormalVector m_vector;
float m_distance;

View File

@@ -10,7 +10,6 @@
#include <glm/vec3.hpp>
#pragma GCC diagnostic pop
#include "../rotation/QuatRotation.hpp"
#include "engine/primitives/CoordinateSpace.hpp"
namespace fgl::engine
@@ -52,15 +51,13 @@ namespace fgl::engine
NormalVector( const NormalVector& other ) = default;
NormalVector& operator=( const NormalVector& other ) = default;
const glm::vec3& vec() const { return static_cast< const glm::vec3& >( *this ); }
[[nodiscard]] const glm::vec3& vec() const { return static_cast< const glm::vec3& >( *this ); }
glm::vec3& vec() { return static_cast< glm::vec3& >( *this ); }
Vector operator*( const float scalar ) const;
Vector operator*( float scalar ) const;
NormalVector operator-() const { return NormalVector( -static_cast< glm::vec3 >( *this ) ); }
explicit operator glm::vec3() const { return static_cast< glm::vec3 >( *this ); }
};
} // namespace fgl::engine

View File

@@ -14,6 +14,7 @@
#include "engine/debug/timing/FlameGraph.hpp"
#include "engine/rendering/pipelines/v2/Pipeline.hpp"
#include "engine/rendering/pipelines/v2/PipelineBuilder.hpp"
#include "memory/buffers/BufferHandle.hpp"
namespace fgl::engine
{
@@ -90,13 +91,13 @@ namespace fgl::engine
auto& model_buffers { getModelBuffers() };
const std::vector< vk::Buffer > vert_buffers {
model_buffers.m_vertex_buffer.getVkBuffer(),
model_buffers.m_vertex_buffer->getVkBuffer(),
model_buffers.m_generated_instance_info[ info.in_flight_idx ].getVkBuffer()
};
command_buffer->bindVertexBuffers(
0, vert_buffers, { 0, model_buffers.m_generated_instance_info[ info.in_flight_idx ].getOffset() } );
command_buffer->bindIndexBuffer( model_buffers.m_index_buffer.getVkBuffer(), 0, vk::IndexType::eUint32 );
command_buffer->bindIndexBuffer( model_buffers.m_index_buffer->getVkBuffer(), 0, vk::IndexType::eUint32 );
command_buffer->drawIndexedIndirect(
info.m_commands.getVkBuffer(),

View File

@@ -15,7 +15,7 @@ namespace fgl::engine
namespace memory
{
class Buffer;
class BufferHandle;
}
struct FrameInfo;