From 1b4f8f42eadd4dd8e11de9cbf9fb0891c815567b Mon Sep 17 00:00:00 2001 From: kj16609 Date: Tue, 15 Apr 2025 00:57:54 -0400 Subject: [PATCH] Implement basic buffer resizing --- CMakeLists.txt | 10 +- fgl_cmake_modules | 2 +- src/editor/src/gui/drawStats.cpp | 14 +- src/engine/EngineContext.cpp | 12 +- src/engine/EngineContext.hpp | 2 +- src/engine/assets/MaterialManager.cpp | 3 +- src/engine/assets/MaterialManager.hpp | 2 +- src/engine/assets/model/Model.cpp | 2 +- src/engine/assets/model/Model.hpp | 2 +- .../assets/model/builders/ModelBuilder.hpp | 13 +- .../assets/model/builders/SceneBuilder.cpp | 3 +- .../assets/model/builders/SceneBuilder.hpp | 8 +- src/engine/assets/transfer/TransferData.cpp | 11 +- src/engine/assets/transfer/TransferData.hpp | 12 +- .../assets/transfer/TransferManager.cpp | 29 ++- .../assets/transfer/TransferManager.hpp | 25 +- src/engine/camera/Camera.hpp | 2 +- src/engine/camera/CameraManager.hpp | 2 +- src/engine/debug/Track.cpp | 3 +- src/engine/debug/Track.hpp | 9 +- src/engine/descriptors/Descriptor.hpp | 4 +- src/engine/memory/DefferedCleanup.hpp | 11 + .../buffers/{Buffer.cpp => BufferHandle.cpp} | 229 ++++++++++++------ .../buffers/{Buffer.hpp => BufferHandle.hpp} | 85 ++++--- .../memory/buffers/BufferSuballocation.cpp | 17 +- .../memory/buffers/BufferSuballocation.hpp | 6 +- .../buffers/BufferSuballocationHandle.cpp | 21 +- .../buffers/BufferSuballocationHandle.hpp | 28 +-- src/engine/memory/buffers/HostSingleT.hpp | 4 +- .../buffers/UniqueFrameSuballocation.hpp | 7 +- .../memory/buffers/vector/BufferVector.cpp | 9 +- .../memory/buffers/vector/BufferVector.hpp | 2 - .../memory/buffers/vector/DeviceVector.hpp | 6 +- src/engine/primitives/planes/PointPlane.hpp | 2 +- .../primitives/vectors/NormalVector.hpp | 7 +- .../systems/render/EntityRendererSystem.cpp | 5 +- .../systems/render/EntityRendererSystem.hpp | 2 +- 37 files changed, 371 insertions(+), 240 deletions(-) create mode 100644 src/engine/memory/DefferedCleanup.hpp rename src/engine/memory/buffers/{Buffer.cpp => BufferHandle.cpp} (54%) rename src/engine/memory/buffers/{Buffer.hpp => BufferHandle.hpp} (73%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0598029..2cd39f5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,8 @@ # /CMakeLists.txt - cmake_minimum_required(VERSION 3.25.0) -project(TitorGameEngine LANGUAGES CXX C) + +set(CMAKE_CXX_STANDARD 23) +set(CMAKE_CXX_STANDARD_REQUIRED ON) find_program(CCACHE_FOUND ccache) if (CCACHE_FOUND) @@ -10,10 +11,9 @@ else () message("ccache not found. Not using it") endif () -add_subdirectory(fgl_cmake_modules) +project(TitorGameEngine LANGUAGES CXX C) -set(CMAKE_CXX_STANDARD 23) -set(CMAKE_CXX_STANDARD_REQUIRED ON) +add_subdirectory(fgl_cmake_modules) PreSetup() diff --git a/fgl_cmake_modules b/fgl_cmake_modules index 1d3efaf..ecdcb16 160000 --- a/fgl_cmake_modules +++ b/fgl_cmake_modules @@ -1 +1 @@ -Subproject commit 1d3efaf2bcdcefd7ff312733e1eda7933e8c24d6 +Subproject commit ecdcb16f2e23cebc96341ff6f670409b447aa0c0 diff --git a/src/editor/src/gui/drawStats.cpp b/src/editor/src/gui/drawStats.cpp index 14798c2..64213a4 100644 --- a/src/editor/src/gui/drawStats.cpp +++ b/src/editor/src/gui/drawStats.cpp @@ -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(); } + */ } } diff --git a/src/engine/EngineContext.cpp b/src/engine/EngineContext.cpp index eae0ad6..9ab7899 100644 --- a/src/engine/EngineContext.cpp +++ b/src/engine/EngineContext.cpp @@ -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(); { diff --git a/src/engine/EngineContext.hpp b/src/engine/EngineContext.hpp index 0f36eef..1b54d48 100644 --- a/src/engine/EngineContext.hpp +++ b/src/engine/EngineContext.hpp @@ -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; diff --git a/src/engine/assets/MaterialManager.cpp b/src/engine/assets/MaterialManager.cpp index 6b8af75..96793b1 100644 --- a/src/engine/assets/MaterialManager.cpp +++ b/src/engine/assets/MaterialManager.cpp @@ -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() diff --git a/src/engine/assets/MaterialManager.hpp b/src/engine/assets/MaterialManager.hpp index 342aa56..762f052 100644 --- a/src/engine/assets/MaterialManager.hpp +++ b/src/engine/assets/MaterialManager.hpp @@ -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" diff --git a/src/engine/assets/model/Model.cpp b/src/engine/assets/model/Model.cpp index be6698b..66f37fb 100644 --- a/src/engine/assets/model/Model.cpp +++ b/src/engine/assets/model/Model.cpp @@ -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 ), diff --git a/src/engine/assets/model/Model.hpp b/src/engine/assets/model/Model.hpp index 8730a90..e89ecb2 100644 --- a/src/engine/assets/model/Model.hpp +++ b/src/engine/assets/model/Model.hpp @@ -36,7 +36,7 @@ namespace fgl::engine namespace memory { - class Buffer; + class BufferHandle; } struct ModelBuilder; diff --git a/src/engine/assets/model/builders/ModelBuilder.hpp b/src/engine/assets/model/builders/ModelBuilder.hpp index dd1361c..0a694b8 100644 --- a/src/engine/assets/model/builders/ModelBuilder.hpp +++ b/src/engine/assets/model/builders/ModelBuilder.hpp @@ -8,27 +8,24 @@ #include #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 ) {} diff --git a/src/engine/assets/model/builders/SceneBuilder.cpp b/src/engine/assets/model/builders/SceneBuilder.cpp index 8a5ecf4..4c3c2f0 100644 --- a/src/engine/assets/model/builders/SceneBuilder.cpp +++ b/src/engine/assets/model/builders/SceneBuilder.cpp @@ -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 ) {} diff --git a/src/engine/assets/model/builders/SceneBuilder.hpp b/src/engine/assets/model/builders/SceneBuilder.hpp index 6929fbd..35a2287 100644 --- a/src/engine/assets/model/builders/SceneBuilder.hpp +++ b/src/engine/assets/model/builders/SceneBuilder.hpp @@ -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 ); }; diff --git a/src/engine/assets/transfer/TransferData.cpp b/src/engine/assets/transfer/TransferData.cpp index 5384021..6eb3334 100644 --- a/src/engine/assets/transfer/TransferData.cpp +++ b/src/engine/assets/transfer/TransferData.cpp @@ -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 ) }; diff --git a/src/engine/assets/transfer/TransferData.hpp b/src/engine/assets/transfer/TransferData.hpp index 5d7da50..36a08f0 100644 --- a/src/engine/assets/transfer/TransferData.hpp +++ b/src/engine/assets/transfer/TransferData.hpp @@ -8,6 +8,8 @@ #include #include +#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( diff --git a/src/engine/assets/transfer/TransferManager.cpp b/src/engine/assets/transfer/TransferManager.cpp index 72dd3bd..993c1bb 100644 --- a/src/engine/assets/transfer/TransferManager.cpp +++ b/src/engine/assets/transfer/TransferManager.cpp @@ -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(); diff --git a/src/engine/assets/transfer/TransferManager.hpp b/src/engine/assets/transfer/TransferManager.hpp index a4755f4..d9a6524 100644 --- a/src/engine/assets/transfer/TransferManager.hpp +++ b/src/engine/assets/transfer/TransferManager.hpp @@ -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(); diff --git a/src/engine/camera/Camera.hpp b/src/engine/camera/Camera.hpp index 6cae17c..b223be6 100644 --- a/src/engine/camera/Camera.hpp +++ b/src/engine/camera/Camera.hpp @@ -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 ); diff --git a/src/engine/camera/CameraManager.hpp b/src/engine/camera/CameraManager.hpp index b5d16d5..8bd8ec8 100644 --- a/src/engine/camera/CameraManager.hpp +++ b/src/engine/camera/CameraManager.hpp @@ -6,7 +6,7 @@ #include #include "Camera.hpp" -#include "engine/memory/buffers/Buffer.hpp" +#include "engine/memory/buffers/BufferHandle.hpp" namespace fgl::engine { diff --git a/src/engine/debug/Track.cpp b/src/engine/debug/Track.cpp index 9d60d63..91c6d38 100644 --- a/src/engine/debug/Track.cpp +++ b/src/engine/debug/Track.cpp @@ -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 ) diff --git a/src/engine/debug/Track.hpp b/src/engine/debug/Track.hpp index 572c93f..3f07eef 100644 --- a/src/engine/debug/Track.hpp +++ b/src/engine/debug/Track.hpp @@ -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 ); } }; diff --git a/src/engine/descriptors/Descriptor.hpp b/src/engine/descriptors/Descriptor.hpp index 3caa568..86a7cf2 100644 --- a/src/engine/descriptors/Descriptor.hpp +++ b/src/engine/descriptors/Descriptor.hpp @@ -4,9 +4,9 @@ #pragma once -#include +#include -#include "engine/memory/buffers/Buffer.hpp" +#include namespace fgl::engine::descriptors { diff --git a/src/engine/memory/DefferedCleanup.hpp b/src/engine/memory/DefferedCleanup.hpp new file mode 100644 index 0000000..81c9a82 --- /dev/null +++ b/src/engine/memory/DefferedCleanup.hpp @@ -0,0 +1,11 @@ +// +// Created by kj16609 on 4/9/25. +// +#pragma once + +namespace fgl::engine::memory +{ + + void deferredDelete( auto&& item ) {} + +} diff --git a/src/engine/memory/buffers/Buffer.cpp b/src/engine/memory/buffers/BufferHandle.cpp similarity index 54% rename from src/engine/memory/buffers/Buffer.cpp rename to src/engine/memory/buffers/BufferHandle.cpp index 2b53206..90fb272 100644 --- a/src/engine/memory/buffers/Buffer.cpp +++ b/src/engine/memory/buffers/BufferHandle.cpp @@ -2,27 +2,39 @@ // Created by kj16609 on 12/30/23. // -#include "Buffer.hpp" +#include "BufferHandle.hpp" #include +#include #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 }; diff --git a/src/engine/memory/buffers/Buffer.hpp b/src/engine/memory/buffers/BufferHandle.hpp similarity index 73% rename from src/engine/memory/buffers/Buffer.hpp rename to src/engine/memory/buffers/BufferHandle.hpp index ae1786b..ca958d1 100644 --- a/src/engine/memory/buffers/Buffer.hpp +++ b/src/engine/memory/buffers/BufferHandle.hpp @@ -14,7 +14,9 @@ #include #include #include +#include +#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 + //! + using AllocationSize = vk::DeviceSize; + + //! @brief list of any free blocks + //! @note All blocks are amalgamated to the largest they can expand to. + //! + 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 - //! - 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. - //! - 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 \ No newline at end of file diff --git a/src/engine/memory/buffers/BufferSuballocation.cpp b/src/engine/memory/buffers/BufferSuballocation.cpp index a1da8bd..d3e6e1d 100644 --- a/src/engine/memory/buffers/BufferSuballocation.cpp +++ b/src/engine/memory/buffers/BufferSuballocation.cpp @@ -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 diff --git a/src/engine/memory/buffers/BufferSuballocation.hpp b/src/engine/memory/buffers/BufferSuballocation.hpp index ebcddd6..a1dbe80 100644 --- a/src/engine/memory/buffers/BufferSuballocation.hpp +++ b/src/engine/memory/buffers/BufferSuballocation.hpp @@ -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 ); diff --git a/src/engine/memory/buffers/BufferSuballocationHandle.cpp b/src/engine/memory/buffers/BufferSuballocationHandle.cpp index 987040a..ec30a6f 100644 --- a/src/engine/memory/buffers/BufferSuballocationHandle.cpp +++ b/src/engine/memory/buffers/BufferSuballocationHandle.cpp @@ -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:: diff --git a/src/engine/memory/buffers/BufferSuballocationHandle.hpp b/src/engine/memory/buffers/BufferSuballocationHandle.hpp index e3472c4..e2712d0 100644 --- a/src/engine/memory/buffers/BufferSuballocationHandle.hpp +++ b/src/engine/memory/buffers/BufferSuballocationHandle.hpp @@ -6,8 +6,7 @@ #include -#include - +#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, diff --git a/src/engine/memory/buffers/HostSingleT.hpp b/src/engine/memory/buffers/HostSingleT.hpp index 4c4c4cd..d401f81 100644 --- a/src/engine/memory/buffers/HostSingleT.hpp +++ b/src/engine/memory/buffers/HostSingleT.hpp @@ -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 ) { diff --git a/src/engine/memory/buffers/UniqueFrameSuballocation.hpp b/src/engine/memory/buffers/UniqueFrameSuballocation.hpp index 3f2054e..35e9408 100644 --- a/src/engine/memory/buffers/UniqueFrameSuballocation.hpp +++ b/src/engine/memory/buffers/UniqueFrameSuballocation.hpp @@ -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 ] ); diff --git a/src/engine/memory/buffers/vector/BufferVector.cpp b/src/engine/memory/buffers/vector/BufferVector.cpp index 1fb52c4..4d09abe 100644 --- a/src/engine/memory/buffers/vector/BufferVector.cpp +++ b/src/engine/memory/buffers/vector/BufferVector.cpp @@ -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( diff --git a/src/engine/memory/buffers/vector/BufferVector.hpp b/src/engine/memory/buffers/vector/BufferVector.hpp index bd90051..34bfede 100644 --- a/src/engine/memory/buffers/vector/BufferVector.hpp +++ b/src/engine/memory/buffers/vector/BufferVector.hpp @@ -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 }; diff --git a/src/engine/memory/buffers/vector/DeviceVector.hpp b/src/engine/memory/buffers/vector/DeviceVector.hpp index 25e88be..c5a8df8 100644 --- a/src/engine/memory/buffers/vector/DeviceVector.hpp +++ b/src/engine/memory/buffers/vector/DeviceVector.hpp @@ -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 ); } diff --git a/src/engine/primitives/planes/PointPlane.hpp b/src/engine/primitives/planes/PointPlane.hpp index 1379a80..45d9f93 100644 --- a/src/engine/primitives/planes/PointPlane.hpp +++ b/src/engine/primitives/planes/PointPlane.hpp @@ -19,7 +19,7 @@ namespace fgl::engine * @tparam CType */ template < CoordinateSpace CType > - class FGL_PACKED SimplePlane + class SimplePlane { NormalVector m_vector; float m_distance; diff --git a/src/engine/primitives/vectors/NormalVector.hpp b/src/engine/primitives/vectors/NormalVector.hpp index eae42d6..10a72b1 100644 --- a/src/engine/primitives/vectors/NormalVector.hpp +++ b/src/engine/primitives/vectors/NormalVector.hpp @@ -10,7 +10,6 @@ #include #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 diff --git a/src/engine/systems/render/EntityRendererSystem.cpp b/src/engine/systems/render/EntityRendererSystem.cpp index c721f05..c2c4d41 100644 --- a/src/engine/systems/render/EntityRendererSystem.cpp +++ b/src/engine/systems/render/EntityRendererSystem.cpp @@ -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(), diff --git a/src/engine/systems/render/EntityRendererSystem.hpp b/src/engine/systems/render/EntityRendererSystem.hpp index e5ec048..0b2cd1f 100644 --- a/src/engine/systems/render/EntityRendererSystem.hpp +++ b/src/engine/systems/render/EntityRendererSystem.hpp @@ -15,7 +15,7 @@ namespace fgl::engine namespace memory { - class Buffer; + class BufferHandle; } struct FrameInfo;