diff --git a/src/editor/src/gui/EditorGuiContext.cpp b/src/editor/src/gui/EditorGuiContext.cpp new file mode 100644 index 0000000..97e8454 --- /dev/null +++ b/src/editor/src/gui/EditorGuiContext.cpp @@ -0,0 +1,131 @@ +// +// Created by kj16609 on 1/21/25. +// +#include "EditorGuiContext.hpp" + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Weffc++" +#pragma GCC diagnostic ignored "-Wold-style-cast" +#pragma GCC diagnostic ignored "-Wconversion" +#include +#include + +#include // Included for DockBuilder since it's not exposed yet +#pragma GCC diagnostic pop + +#include "FrameInfo.hpp" +#include "core.hpp" +#include "debug/timing/FlameGraph.hpp" +#include "descriptors/DescriptorPool.hpp" +#include "gui_window_names.hpp" +#include "rendering/RenderingFormats.hpp" + +namespace fgl::editor +{ + + using namespace fgl::engine; + + EditorGuiContext::EditorGuiContext( const Window& window ) + { + ZoneScoped; + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + [[maybe_unused]] ImGuiIO& io { ImGui::GetIO() }; + //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; + io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; + // io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; + io.ConfigWindowsResizeFromEdges = true; + + ImGui::StyleColorsDark(); + + Device& device { Device::getInstance() }; + + vk::PipelineRenderingCreateInfo pipeline_info {}; + + //TODO: Remove the ability for pickPresentFormat to be used here. Instead this should be hidden from the end user in roder to prevent shittery. This should be applied to everything else here too within reason. + const std::vector< vk::Format > color_formats { pickPresentFormat() }; + + pipeline_info.setColorAttachmentFormats( color_formats ); + pipeline_info.setDepthAttachmentFormat( pickDepthFormat() ); + + ImGui_ImplGlfw_InitForVulkan( window.window(), true ); + ImGui_ImplVulkan_InitInfo init_info { + .Instance = device.instance(), + .PhysicalDevice = *device.phyDevice().handle(), + .Device = *device, + .QueueFamily = device.phyDevice().queueInfo().getIndex( vk::QueueFlagBits::eGraphics ), + .Queue = *device.graphicsQueue(), + .DescriptorPool = *DescriptorPool::getInstance().getPool(), + .RenderPass = VK_NULL_HANDLE, + .MinImageCount = 2, + .ImageCount = 2, + .MSAASamples = VK_SAMPLE_COUNT_1_BIT, + + .PipelineCache = VK_NULL_HANDLE, + .Subpass = 0, + + .UseDynamicRendering = VK_TRUE, + .PipelineRenderingCreateInfo = pipeline_info, + + .Allocator = VK_NULL_HANDLE, + .CheckVkResultFn = VK_NULL_HANDLE, + .MinAllocationSize = 1024 * 1024 + }; + + ImGui_ImplVulkan_Init( &init_info ); + } + + EditorGuiContext::~EditorGuiContext() + { + ZoneScoped; + ImGui_ImplVulkan_Shutdown(); + ImGui_ImplGlfw_Shutdown(); + ImGui::DestroyContext(); + } + + void EditorGuiContext::beginDraw() + { + ZoneScoped; + ImGui_ImplVulkan_NewFrame(); + ImGui_ImplGlfw_NewFrame(); + ImGui::NewFrame(); + } + + void EditorGuiContext::draw( FrameInfo& info ) + { + ZoneScoped; + auto timer = debug::timing::push( "Draw ImGui" ); + ImGui::ShowDemoWindow(); + + gui::drawDock(); + + gui::drawCameraOutputs( info ); + gui::drawEntityGUI( info ); + gui::drawEntityInfo( info ); + + ImGui::Begin( FILE_PICKER_NAME.data(), nullptr, ImGuiWindowFlags_MenuBar ); + + m_file_browser.drawGui( info ); + + ImGui::End(); + + gui::drawStats( info ); + } + + void EditorGuiContext::endDraw( vk::raii::CommandBuffer& command_buffer ) + { + ZoneScoped; + ImGui::Render(); + + ImDrawData* data { ImGui::GetDrawData() }; + ImGui_ImplVulkan_RenderDrawData( data, *command_buffer ); + + //ImGui::UpdatePlatformWindows(); + //ImGui::RenderPlatformWindowsDefault(); + } + + void EditorGuiContext::endDraw( FrameInfo& info ) + { + return endDraw( info.command_buffer ); + } +} // namespace fgl::editor \ No newline at end of file diff --git a/src/editor/src/gui/EditorGuiContext.hpp b/src/editor/src/gui/EditorGuiContext.hpp new file mode 100644 index 0000000..a9e151a --- /dev/null +++ b/src/editor/src/gui/EditorGuiContext.hpp @@ -0,0 +1,23 @@ +// +// Created by kj16609 on 1/21/25. +// +#pragma once +#include "FileBrowser.hpp" + +namespace fgl::editor +{ + class EditorGuiContext + { + engine::filesystem::FileBrowser m_file_browser {}; + + public: + + EditorGuiContext( const engine::Window& window ); + ~EditorGuiContext(); + + void beginDraw(); + void draw( engine::FrameInfo& info ); + void endDraw( vk::raii::CommandBuffer& command_buffer ); + void endDraw( engine::FrameInfo& info ); + }; +} // namespace fgl::editor \ No newline at end of file diff --git a/src/editor/src/gui/FileBrowser.cpp b/src/editor/src/gui/FileBrowser.cpp index 4c54f03..baf1ff6 100644 --- a/src/editor/src/gui/FileBrowser.cpp +++ b/src/editor/src/gui/FileBrowser.cpp @@ -18,41 +18,15 @@ namespace fgl::engine::filesystem { //! Textures for files (pre-rendered image, images, ect) - inline static std::unordered_map< std::filesystem::path, std::shared_ptr< Texture > > file_textures {}; - inline static std::unique_ptr< DirInfo > current { nullptr }; + constexpr std::uint32_t DESIRED_SIZE { 128 }; + constexpr std::uint32_t PADDING { 2 }; - inline static std::once_flag flag {}; - inline static std::shared_ptr< Texture > folder_texture { nullptr }; - inline static std::shared_ptr< Texture > file_texture { nullptr }; - inline static std::shared_ptr< Texture > up_texture { nullptr }; - constexpr std::uint32_t desired_size { 128 }; - constexpr std::uint32_t padding { 2 }; - - const std::filesystem::path test_path { std::filesystem::current_path() / "assets" }; - - void prepareFileGUI() - { - //Prepare textures needed. - folder_texture = getTextureStore().load( "./assets/folder.png", vk::Format::eR8G8B8A8Unorm ); - file_texture = getTextureStore().load( "./assets/file.png", vk::Format::eR8G8B8A8Unorm ); - up_texture = getTextureStore().load( "./assets/up.png", vk::Format::eR8G8B8A8Unorm ); - - current = std::make_unique< DirInfo >( test_path ); - } - - void destroyFileGui() - { - folder_texture.reset(); - file_texture.reset(); - up_texture.reset(); - file_textures.clear(); - } + const std::filesystem::path TEST_PATH { std::filesystem::current_path() / "assets" }; void FileBrowser::drawGui( [[maybe_unused]] FrameInfo& info ) { ZoneScoped; - std::call_once( flag, prepareFileGUI ); /* if ( ImGui::BeginMenuBar() ) @@ -72,19 +46,20 @@ namespace fgl::engine::filesystem } */ - if ( !current ) + if ( !m_current_dir ) { - log::critical( "Current has no value!" ); - std::abort(); + m_current_dir = std::make_unique< DirInfo >( std::filesystem::current_path() ); + log::warn( + "Current directory was not set, Defaulting to current directory: {}", std::filesystem::current_path() ); } auto size { ImGui::GetWindowSize() }; //TODO: Probably a cleaner way to do this. size.x -= 12; // Remove scrollbar pixels - const float extra { std::fmod( size.x, static_cast< float >( desired_size + ( padding * 2 ) ) ) }; + const float extra { std::fmod( size.x, static_cast< float >( DESIRED_SIZE + ( PADDING * 2 ) ) ) }; const auto cols { - static_cast< int >( ( size.x - extra ) / static_cast< float >( desired_size + ( padding * 2 ) ) ) + static_cast< int >( ( size.x - extra ) / static_cast< float >( DESIRED_SIZE + ( PADDING * 2 ) ) ) }; if ( cols == 0 ) @@ -93,33 +68,33 @@ namespace fgl::engine::filesystem return; } - ImGui::PushStyleVar( ImGuiStyleVar_CellPadding, { padding, padding } ); + ImGui::PushStyleVar( ImGuiStyleVar_CellPadding, { PADDING, PADDING } ); - if ( current && ImGui::BeginTable( "Files", cols ) ) + if ( m_current_dir && ImGui::BeginTable( "Files", cols ) ) { for ( int i = 0; i < cols; ++i ) - ImGui::TableSetupColumn( "", ImGuiTableColumnFlags_WidthFixed, desired_size ); + ImGui::TableSetupColumn( "", ImGuiTableColumnFlags_WidthFixed, DESIRED_SIZE ); //List up if we can go up - if ( current->hasParent() ) + if ( m_current_dir->hasParent() ) { ImGui::TableNextColumn(); - drawUp( current ); + drawUp( m_current_dir ); } - assert( current ); + assert( m_current_dir ); //List folders first - for ( std::size_t i = 0; i < current->folderCount(); ++i ) + for ( std::size_t i = 0; i < m_current_dir->folderCount(); ++i ) { ImGui::TableNextColumn(); - drawFolder( current->dir( i ) ); + drawFolder( m_current_dir->dir( i ) ); } - for ( std::size_t i = 0; i < current->fileCount(); ++i ) + for ( std::size_t i = 0; i < m_current_dir->fileCount(); ++i ) { ImGui::TableNextColumn(); - drawFile( current->file( i ) ); + drawFile( m_current_dir->file( i ) ); } ImGui::EndTable(); @@ -148,22 +123,22 @@ namespace fgl::engine::filesystem return format_ns::format( "{:0.2f} GB", static_cast< float >( size ) / 1000.0f / 1000.0f / 1000.0f ); } - void drawTexture( const FileInfo& info ) + void FileBrowser::drawTexture( const FileInfo& info ) { - if ( auto itter = file_textures.find( info.path ); itter != file_textures.end() ) + if ( auto itter = m_file_textures.find( info.path ); itter != m_file_textures.end() ) { auto& [ path, texture ] = *itter; - texture->drawImGuiButton( { desired_size, desired_size } ); + texture->drawImGuiButton( { DESIRED_SIZE, DESIRED_SIZE } ); } else { - file_texture->drawImGuiButton( { desired_size, desired_size } ); + m_file_texture->drawImGuiButton( { DESIRED_SIZE, DESIRED_SIZE } ); auto tex { getTextureStore().load( info.path ) }; // Add the texture - file_textures.insert( std::make_pair( info.path, std::move( tex ) ) ); + m_file_textures.insert( std::make_pair( info.path, std::move( tex ) ) ); } if ( ImGui::BeginDragDropSource() ) @@ -176,15 +151,15 @@ namespace fgl::engine::filesystem } } - void drawBinary( [[maybe_unused]] const FileInfo& info ) + void FileBrowser::drawBinary( [[maybe_unused]] const FileInfo& info ) { // file_texture->drawImGui( { 128, 128 } ); - file_texture->drawImGuiButton( { desired_size, desired_size } ); + m_file_texture->drawImGuiButton( { DESIRED_SIZE, DESIRED_SIZE } ); //Unable to drag/drop because we have no idea what this is supposed to be for. } - void drawModel( const FileInfo& info ) + void FileBrowser::drawModel( const FileInfo& info ) { //TODO: Pre-render preview image for models drawBinary( info ); @@ -234,7 +209,7 @@ namespace fgl::engine::filesystem { ImGui::PushID( data.m_path.c_str() ); - if ( folder_texture->drawImGuiButton( { desired_size, desired_size } ) ) + if ( m_folder_texture->drawImGuiButton( { DESIRED_SIZE, DESIRED_SIZE } ) ) { openFolder( data ); ImGui::PopID(); @@ -247,15 +222,22 @@ namespace fgl::engine::filesystem ImGui::PopID(); } + FileBrowser::FileBrowser() + { + m_folder_texture = getTextureStore().load( "./assets/folder.png", vk::Format::eR8G8B8A8Unorm ); + m_file_texture = getTextureStore().load( "./assets/file.png", vk::Format::eR8G8B8A8Unorm ); + m_up_texture = getTextureStore().load( "./assets/up.png", vk::Format::eR8G8B8A8Unorm ); + } + void FileBrowser::goUp() { - current = current->up(); + m_current_dir = m_current_dir->up(); } void FileBrowser::openFolder( const DirInfo& dir ) { - file_textures.clear(); - current = std::make_unique< DirInfo >( dir.m_path ); + m_file_textures.clear(); + m_current_dir = std::make_unique< DirInfo >( dir.m_path ); } void FileBrowser::drawUp( const std::unique_ptr< DirInfo >& current_dir ) @@ -264,7 +246,7 @@ namespace fgl::engine::filesystem ImGui::PushID( up->m_path.c_str() ); - if ( up_texture->drawImGuiButton( { desired_size, desired_size } ) ) + if ( m_up_texture->drawImGuiButton( { DESIRED_SIZE, DESIRED_SIZE } ) ) { openFolder( *up ); } diff --git a/src/editor/src/gui/FileBrowser.hpp b/src/editor/src/gui/FileBrowser.hpp index eed030d..1ecc32a 100644 --- a/src/editor/src/gui/FileBrowser.hpp +++ b/src/editor/src/gui/FileBrowser.hpp @@ -3,7 +3,11 @@ // #pragma once +#include +#include + #include "../../../engine/filesystem/scanner/FileScanner.hpp" +#include "assets/texture/Texture.hpp" namespace fgl::engine { @@ -16,14 +20,29 @@ namespace fgl::engine::filesystem struct FileBrowser { - static void goUp(); + std::unordered_map< std::filesystem::path, std::shared_ptr< Texture > > m_file_textures {}; - static void openFolder( const DirInfo& dir ); + std::unique_ptr< DirInfo > m_current_dir { nullptr }; - static void drawUp( const std::unique_ptr< DirInfo >& current_dir ); - static void drawGui( FrameInfo& info ); - static void drawFile( const FileInfo& data ); - static void drawFolder( const DirInfo& data ); + std::shared_ptr< Texture > m_folder_texture { nullptr }; + std::shared_ptr< Texture > m_file_texture { nullptr }; + std::shared_ptr< Texture > m_up_texture { nullptr }; + + FileBrowser(); + + void goUp(); + + void openFolder( const DirInfo& dir ); + + void drawUp( const std::unique_ptr< DirInfo >& current_dir ); + void drawGui( FrameInfo& info ); + void drawFile( const FileInfo& data ); + void drawFolder( const DirInfo& data ); + + // drawers + void drawBinary( const FileInfo& info ); + void drawModel( const FileInfo& info ); + void drawTexture( const FileInfo& info ); }; void destroyFileGui(); diff --git a/src/editor/src/gui/core.cpp b/src/editor/src/gui/core.cpp index a7cc603..7bdffc4 100644 --- a/src/editor/src/gui/core.cpp +++ b/src/editor/src/gui/core.cpp @@ -8,102 +8,21 @@ #pragma GCC diagnostic ignored "-Weffc++" #pragma GCC diagnostic ignored "-Wold-style-cast" #pragma GCC diagnostic ignored "-Wconversion" -#include -#include - #include // Included for DockBuilder since it's not exposed yet #pragma GCC diagnostic pop #include "FileBrowser.hpp" #include "engine/assets/model/Model.hpp" #include "engine/debug/DEBUG_NAMES.hpp" -#include "engine/debug/drawers.hpp" -#include "engine/debug/profiling/counters.hpp" -#include "engine/debug/timing/FlameGraph.hpp" #include "engine/descriptors/DescriptorPool.hpp" #include "engine/rendering/Renderer.hpp" #include "engine/tree/octtree/OctTreeNode.hpp" #include "gui_window_names.hpp" -#include "rendering/RenderingFormats.hpp" #include "safe_include.hpp" namespace fgl::engine::gui { - void initGui( const Window& window, const Renderer& renderer ) - { - ZoneScoped; - IMGUI_CHECKVERSION(); - ImGui::CreateContext(); - [[maybe_unused]] ImGuiIO& io { ImGui::GetIO() }; - //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; - io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; - // io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; - io.ConfigWindowsResizeFromEdges = true; - - ImGui::StyleColorsDark(); - - Device& device { Device::getInstance() }; - - vk::PipelineRenderingCreateInfo pipeline_info {}; - - const std::vector< vk::Format > color_formats { pickPresentFormat() }; - - pipeline_info.setColorAttachmentFormats( color_formats ); - pipeline_info.setDepthAttachmentFormat( pickDepthFormat() ); - - ImGui_ImplGlfw_InitForVulkan( window.window(), true ); - ImGui_ImplVulkan_InitInfo init_info { - .Instance = device.instance(), - .PhysicalDevice = *device.phyDevice().handle(), - .Device = *device, - .QueueFamily = device.phyDevice().queueInfo().getIndex( vk::QueueFlagBits::eGraphics ), - .Queue = *device.graphicsQueue(), - .DescriptorPool = *DescriptorPool::getInstance().getPool(), - .RenderPass = VK_NULL_HANDLE, - .MinImageCount = 2, - .ImageCount = 2, - .MSAASamples = VK_SAMPLE_COUNT_1_BIT, - - .PipelineCache = VK_NULL_HANDLE, - .Subpass = 0, - - .UseDynamicRendering = VK_TRUE, - .PipelineRenderingCreateInfo = pipeline_info, - - .Allocator = VK_NULL_HANDLE, - .CheckVkResultFn = VK_NULL_HANDLE, - .MinAllocationSize = 1024 * 1024 - }; - - ImGui_ImplVulkan_Init( &init_info ); - } - - void beginImGui() - { - ZoneScoped; - ImGui_ImplVulkan_NewFrame(); - ImGui_ImplGlfw_NewFrame(); - ImGui::NewFrame(); - } - - void endImGui( vk::raii::CommandBuffer& command_buffer ) - { - ZoneScoped; - ImGui::Render(); - - ImDrawData* data { ImGui::GetDrawData() }; - ImGui_ImplVulkan_RenderDrawData( data, *command_buffer ); - - //ImGui::UpdatePlatformWindows(); - //ImGui::RenderPlatformWindowsDefault(); - } - - void endDrawImGui( FrameInfo& info ) - { - endImGui( info.command_buffer ); - } - inline void prepareDock( ImGuiID& primary_id ) { ImGui::DockBuilderRemoveNode( primary_id ); @@ -177,29 +96,6 @@ namespace fgl::engine::gui // ImGui::PopStyleVar(); } - void startDrawImGui( [[maybe_unused]] FrameInfo& info ) - { - beginImGui(); - - profiling::resetCounters(); - } - - void drawImGui( FrameInfo& info ) - { - ZoneScoped; - auto timer = debug::timing::push( "Draw ImGui" ); - ImGui::ShowDemoWindow(); - - drawDock(); - - drawCameraOutputs( info ); - drawEntityGUI( info ); - drawEntityInfo( info ); - drawFilesystemGUI( info ); - - drawStats( info ); - } - static GameObject* selected_object { nullptr }; void itterateGameObjectNode( FrameInfo& info, OctTreeNode& node ) @@ -294,23 +190,4 @@ namespace fgl::engine::gui ImGui::End(); } - void drawFilesystemGUI( FrameInfo& info ) - { - ZoneScoped; - ImGui::Begin( FILE_PICKER_NAME, nullptr, ImGuiWindowFlags_MenuBar ); - - filesystem::FileBrowser::drawGui( info ); - - ImGui::End(); - } - - void cleanupImGui() - { - ZoneScoped; - filesystem::destroyFileGui(); - ImGui_ImplVulkan_Shutdown(); - ImGui_ImplGlfw_Shutdown(); - ImGui::DestroyContext(); - } - } // namespace fgl::engine::gui diff --git a/src/editor/src/gui/core.hpp b/src/editor/src/gui/core.hpp index d2a183a..dab0fd3 100644 --- a/src/editor/src/gui/core.hpp +++ b/src/editor/src/gui/core.hpp @@ -16,17 +16,14 @@ namespace fgl::engine namespace fgl::engine::gui { // Setup/Destruction - void initGui( const Window& window, const Renderer& renderer ); void cleanupImGui(); - // Draws - void startDrawImGui( FrameInfo& info ); + void drawDock(); void drawImGui( FrameInfo& ); void drawEntityGUI( FrameInfo& ); void drawEntityInfo( FrameInfo& ); - void drawFilesystemGUI( FrameInfo& info ); void drawObject( GameObject& game_object ); void drawComponentsList( GameObject& game_object ); @@ -36,6 +33,4 @@ namespace fgl::engine::gui void drawStats( const FrameInfo& info ); - void endDrawImGui( FrameInfo& info ); - } // namespace fgl::engine::gui diff --git a/src/editor/src/main.cpp b/src/editor/src/main.cpp index f74722f..197f968 100644 --- a/src/editor/src/main.cpp +++ b/src/editor/src/main.cpp @@ -3,15 +3,18 @@ // #include +#include "debug/profiling/counters.hpp" #include "engine/EngineContext.hpp" #include "engine/camera/CameraManager.hpp" #include "engine/debug/timing/FlameGraph.hpp" #include "engine/gameobjects/components/CameraComponent.hpp" +#include "gui/EditorGuiContext.hpp" #include "gui/core.hpp" int main() { using namespace fgl::engine; + using namespace fgl::editor; log::set_level( spdlog::level::debug ); @@ -38,13 +41,18 @@ int main() try { EngineContext engine_ctx {}; + EditorGuiContext editor_ctx { engine_ctx.getWindow() }; // We start by hooking into the imgui rendering. - engine_ctx.hookInitImGui( gui::initGui ); - engine_ctx.hookPreFrame( gui::startDrawImGui ); - engine_ctx.hookEarlyFrame( gui::drawImGui ); - engine_ctx.hookLateFrame( gui::endDrawImGui ); - engine_ctx.hookDestruction( gui::cleanupImGui ); + engine_ctx.hookPreFrame( + [ & ]( [[maybe_unused]] FrameInfo& info ) + { + editor_ctx.beginDraw(); + + profiling::resetCounters(); + } ); + engine_ctx.hookEarlyFrame( [ & ]( [[maybe_unused]] FrameInfo& info ) { editor_ctx.draw( info ); } ); + engine_ctx.hookLateFrame( [ & ]( FrameInfo& info ) { editor_ctx.endDraw( info ); } ); // Now we need to create the camera for the editor. CameraManager& camera_manager { engine_ctx.cameraManager() }; @@ -78,6 +86,8 @@ int main() // This will 'end' the root node, Which is created on 'reset' debug::timing::internal::pop(); } + + engine_ctx.waitIdle(); } catch ( const vk::LayerNotPresentError& e ) { diff --git a/src/engine/CMakeLists.txt b/src/engine/CMakeLists.txt index 261172a..e402b2e 100644 --- a/src/engine/CMakeLists.txt +++ b/src/engine/CMakeLists.txt @@ -10,6 +10,8 @@ AddFGLLibrary(FGLEngine STATIC ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURC target_compile_definitions(FGLEngine PUBLIC VULKAN_HPP_FLAGS_MASK_TYPE_AS_PUBLIC) +target_link_libraries(FGLEngine PUBLIC stdc++exp) + include(dependencies/spdlog) include(dependencies/imgui) diff --git a/src/engine/EngineContext.cpp b/src/engine/EngineContext.cpp index 0cababd..ddaafde 100644 --- a/src/engine/EngineContext.cpp +++ b/src/engine/EngineContext.cpp @@ -45,7 +45,7 @@ namespace fgl::engine ZoneScoped; using namespace fgl::literals::size_literals; - memory::TransferManager::createInstance( device, 128_MiB ); + // memory::TransferManager::createInstance( device, 128_MiB ); m_matrix_info_pool.setDebugName( "Matrix info pool" ); m_draw_parameter_pool.setDebugName( "Draw parameter pool" ); @@ -216,6 +216,11 @@ namespace fgl::engine void EngineContext::finishFrame() {} + void EngineContext::waitIdle() + { + device->waitIdle(); + } + Window& EngineContext::getWindow() { return m_window; diff --git a/src/engine/EngineContext.hpp b/src/engine/EngineContext.hpp index 228775f..2c9fe98 100644 --- a/src/engine/EngineContext.hpp +++ b/src/engine/EngineContext.hpp @@ -7,6 +7,7 @@ #include "Window.hpp" #include "camera/CameraManager.hpp" #include "clock.hpp" +#include "engine/assets/transfer/TransferManager.hpp" #include "engine/math/literals/size.hpp" #include "engine/rendering/Renderer.hpp" #include "engine/tree/octtree/OctTreeNode.hpp" @@ -43,9 +44,6 @@ namespace fgl::engine Renderer m_renderer { m_window, device.phyDevice() }; - //GameObject::Map game_objects {}; - OctTreeNode m_game_objects_root { WorldCoordinate( constants::WORLD_CENTER ) }; - std::unique_ptr< memory::Buffer > m_vertex_buffer { std::make_unique< memory::Buffer >( 1_GiB, vk::BufferUsageFlagBits::eVertexBuffer | vk::BufferUsageFlagBits::eTransferDst, @@ -55,6 +53,11 @@ namespace fgl::engine vk::BufferUsageFlagBits::eIndexBuffer | vk::BufferUsageFlagBits::eTransferDst, vk::MemoryPropertyFlagBits::eDeviceLocal ) }; + memory::TransferManager m_transfer_manager { device, 128_MiB }; + + //GameObject::Map game_objects {}; + OctTreeNode m_game_objects_root { WorldCoordinate( constants::WORLD_CENTER ) }; + // SubPass 0 GuiSystem m_gui_system {}; @@ -130,6 +133,9 @@ namespace fgl::engine //! Runs any post-frame processes void finishFrame(); + //! Waits for all frames to be completed + void waitIdle(); + Window& getWindow(); float getWindowAspectRatio(); diff --git a/src/engine/assets/transfer/TransferManager.cpp b/src/engine/assets/transfer/TransferManager.cpp index 66b8e52..b1d096f 100644 --- a/src/engine/assets/transfer/TransferManager.cpp +++ b/src/engine/assets/transfer/TransferManager.cpp @@ -19,29 +19,29 @@ namespace fgl::engine::memory ZoneScoped; //Keep inserting new commands until we fill up the staging buffer - if ( queue.size() > 0 ) log::info( "[TransferManager]: Queue size: {}", queue.size() ); + if ( m_queue.size() > 0 ) log::info( "[TransferManager]: Queue size: {}", m_queue.size() ); std::size_t counter { 0 }; constexpr std::size_t counter_max { 256 }; - while ( queue.size() > 0 ) + while ( m_queue.size() > 0 ) { ++counter; if ( counter > counter_max ) break; - TransferData data { std::move( queue.front() ) }; - queue.pop(); + TransferData data { std::move( m_queue.front() ) }; + m_queue.pop(); if ( data.stage( - command_buffer, *staging_buffer, copy_regions, transfer_queue_index, graphics_queue_index ) ) + command_buffer, *m_staging_buffer, m_copy_regions, m_transfer_queue_index, m_graphics_queue_index ) ) { - processing.emplace_back( std::move( data ) ); + m_processing.emplace_back( std::move( data ) ); } else { // We were unable to stage for a reason log::info( "Unable to stage object. Breaking out of loop" ); - queue.push( data ); + m_queue.push( data ); break; } } @@ -60,7 +60,7 @@ namespace fgl::engine::memory {} ); //Record all the buffer copies - for ( auto& [ key, regions ] : copy_regions ) + for ( auto& [ key, regions ] : m_copy_regions ) { auto& [ source, target ] = key; @@ -81,7 +81,7 @@ namespace fgl::engine::memory void TransferManager::resizeBuffer( const std::uint64_t size ) { - staging_buffer = std::make_unique< Buffer >( + m_staging_buffer = std::make_unique< Buffer >( size, vk::BufferUsageFlagBits::eTransferSrc, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent ); @@ -91,7 +91,7 @@ namespace fgl::engine::memory { ZoneScoped; - std::vector< vk::Fence > fences { completion_fence }; + std::vector< vk::Fence > fences { m_completion_fence }; Device::getInstance()->resetFences( fences ); @@ -101,18 +101,18 @@ namespace fgl::engine::memory std::vector< vk::CommandBuffer > buffers { *command_buffer }; - std::vector< vk::Semaphore > sems { transfer_semaphore }; + std::vector< vk::Semaphore > sems { m_transfer_semaphore }; info.setSignalSemaphores( sems ); info.setCommandBuffers( buffers ); - transfer_queue.submit( info, completion_fence ); + m_transfer_queue.submit( info, m_completion_fence ); } std::vector< vk::BufferMemoryBarrier > TransferManager::createFromGraphicsBarriers() { std::vector< vk::BufferMemoryBarrier > barriers {}; - for ( auto& [ key, regions ] : copy_regions ) + for ( auto& [ key, regions ] : m_copy_regions ) { auto& [ source, target ] = key; @@ -124,8 +124,8 @@ namespace fgl::engine::memory barrier.size = region.size; barrier.srcAccessMask = vk::AccessFlagBits::eNone; barrier.dstAccessMask = vk::AccessFlagBits::eTransferWrite; - barrier.srcQueueFamilyIndex = graphics_queue_index; - barrier.dstQueueFamilyIndex = transfer_queue_index; + barrier.srcQueueFamilyIndex = m_graphics_queue_index; + barrier.dstQueueFamilyIndex = m_transfer_queue_index; barriers.emplace_back( barrier ); } @@ -138,7 +138,7 @@ namespace fgl::engine::memory { std::vector< vk::BufferMemoryBarrier > barriers {}; - for ( auto& [ key, regions ] : copy_regions ) + for ( auto& [ key, regions ] : m_copy_regions ) { auto& [ source, target ] = key; @@ -150,8 +150,8 @@ namespace fgl::engine::memory barrier.size = region.size; barrier.srcAccessMask = vk::AccessFlagBits::eNone; barrier.dstAccessMask = vk::AccessFlagBits::eTransferWrite; - barrier.srcQueueFamilyIndex = graphics_queue_index; - barrier.dstQueueFamilyIndex = transfer_queue_index; + barrier.srcQueueFamilyIndex = m_graphics_queue_index; + barrier.dstQueueFamilyIndex = m_transfer_queue_index; barriers.emplace_back( barrier ); } @@ -164,7 +164,7 @@ namespace fgl::engine::memory { std::vector< vk::BufferMemoryBarrier > barriers {}; - for ( auto& [ key, regions ] : copy_regions ) + for ( auto& [ key, regions ] : m_copy_regions ) { auto& [ source, target ] = key; @@ -176,8 +176,8 @@ namespace fgl::engine::memory barrier.size = region.size; barrier.srcAccessMask = vk::AccessFlagBits::eTransferWrite; barrier.dstAccessMask = vk::AccessFlagBits::eVertexAttributeRead | vk::AccessFlagBits::eIndexRead; - barrier.srcQueueFamilyIndex = transfer_queue_index; - barrier.dstQueueFamilyIndex = graphics_queue_index; + barrier.srcQueueFamilyIndex = m_transfer_queue_index; + barrier.dstQueueFamilyIndex = m_graphics_queue_index; barriers.emplace_back( barrier ); } @@ -190,7 +190,7 @@ namespace fgl::engine::memory { std::vector< vk::BufferMemoryBarrier > barriers {}; - for ( const auto& [ key, regions ] : copy_regions ) + for ( const auto& [ key, regions ] : m_copy_regions ) { const auto& [ src, dst ] = key; for ( const auto& region : regions ) @@ -202,8 +202,8 @@ namespace fgl::engine::memory barrier.size = region.size; barrier.srcAccessMask = vk::AccessFlagBits::eTransferWrite, barrier.dstAccessMask = vk::AccessFlagBits::eIndexRead | vk::AccessFlagBits::eVertexAttributeRead; - barrier.srcQueueFamilyIndex = transfer_queue_index; - barrier.dstQueueFamilyIndex = graphics_queue_index; + barrier.srcQueueFamilyIndex = m_transfer_queue_index; + barrier.dstQueueFamilyIndex = m_graphics_queue_index; barriers.emplace_back( barrier ); } @@ -212,7 +212,7 @@ namespace fgl::engine::memory return barriers; } - inline static std::unique_ptr< TransferManager > global_transfer_manager {}; + inline static TransferManager* GLOBAL_TRANSFER_MANAGER {}; void TransferManager::takeOwnership( vk::raii::CommandBuffer& command_buffer ) { @@ -241,33 +241,25 @@ namespace fgl::engine::memory { //Block on fence - std::vector< vk::Fence > fences { completion_fence }; + std::vector< vk::Fence > fences { m_completion_fence }; (void)Device::getInstance()->waitForFences( fences, VK_TRUE, std::numeric_limits< std::size_t >::max() ); - processing.clear(); - copy_regions.clear(); - } - - void TransferManager::createInstance( Device& device, std::uint64_t buffer_size ) - { - log::info( - "Transfer manager created with a buffer size of {}", - fgl::literals::size_literals::toString( buffer_size ) ); - global_transfer_manager = std::make_unique< TransferManager >( device, buffer_size ); + m_processing.clear(); + m_copy_regions.clear(); } TransferManager& TransferManager::getInstance() { - assert( global_transfer_manager ); - return *global_transfer_manager; + assert( GLOBAL_TRANSFER_MANAGER ); + return *GLOBAL_TRANSFER_MANAGER; } void TransferManager::copyToVector( BufferVector& source, BufferVector& target, const std::size_t target_offset ) { TransferData transfer_data { source.getHandle(), target.getHandle(), target_offset }; - queue.emplace( std::move( transfer_data ) ); + m_queue.emplace( std::move( transfer_data ) ); } void TransferManager::copyToImage( std::vector< std::byte >&& data, Image& image ) @@ -277,28 +269,32 @@ namespace fgl::engine::memory assert( std::get< TransferData::RawData >( transfer_data.m_source ).size() > 0 ); - queue.emplace( std::move( transfer_data ) ); + m_queue.emplace( std::move( transfer_data ) ); } TransferManager::TransferManager( Device& device, std::uint64_t buffer_size ) : - transfer_queue_index( device.phyDevice() + m_transfer_queue_index( device.phyDevice() .queueInfo() .getIndex( vk::QueueFlagBits::eTransfer, vk::QueueFlagBits::eGraphics ) ), - graphics_queue_index( device.phyDevice().queueInfo().getIndex( vk::QueueFlagBits::eGraphics ) ), - transfer_queue( device->getQueue( transfer_queue_index, 0 ) ), - transfer_semaphore( device->createSemaphore( {} ) ), - cmd_buffer_allocinfo( Device::getInstance().getCommandPool(), vk::CommandBufferLevel::ePrimary, 1 ), - transfer_buffers( Device::getInstance().device().allocateCommandBuffers( cmd_buffer_allocinfo ) ), - completion_fence( device->createFence( {} ) ) + m_graphics_queue_index( device.phyDevice().queueInfo().getIndex( vk::QueueFlagBits::eGraphics ) ), + m_transfer_queue( device->getQueue( m_transfer_queue_index, 0 ) ), + m_transfer_semaphore( device->createSemaphore( {} ) ), + m_cmd_buffer_allocinfo( Device::getInstance().getCommandPool(), vk::CommandBufferLevel::ePrimary, 1 ), + m_transfer_buffers( Device::getInstance().device().allocateCommandBuffers( m_cmd_buffer_allocinfo ) ), + m_completion_fence( device->createFence( {} ) ) { resizeBuffer( buffer_size ); + + log::info( "Transfer manager created with size {}", literals::size_literals::toString( buffer_size ) ); + + GLOBAL_TRANSFER_MANAGER = this; } void TransferManager::submitNow() { ZoneScoped; - auto& transfer_buffer { transfer_buffers[ 0 ] }; + auto& transfer_buffer { m_transfer_buffers[ 0 ] }; transfer_buffer.reset(); vk::CommandBufferBeginInfo info {}; @@ -309,15 +305,15 @@ namespace fgl::engine::memory submitBuffer( transfer_buffer ); - if ( processing.size() > 0 ) log::debug( "Submitted {} objects to be transfered", processing.size() ); + if ( m_processing.size() > 0 ) log::debug( "Submitted {} objects to be transfered", m_processing.size() ); - for ( auto& processed : processing ) + for ( auto& processed : m_processing ) { processed.markGood(); } //Drop the data - processing.clear(); + m_processing.clear(); } } // namespace fgl::engine::memory diff --git a/src/engine/assets/transfer/TransferManager.hpp b/src/engine/assets/transfer/TransferManager.hpp index 4c497ee..78050e7 100644 --- a/src/engine/assets/transfer/TransferManager.hpp +++ b/src/engine/assets/transfer/TransferManager.hpp @@ -34,31 +34,29 @@ namespace fgl::engine::memory { //TODO: Ring Buffer //! Queue of data needing to be transfered and submitted. - std::queue< TransferData > queue {}; + std::queue< TransferData > m_queue {}; //! Data actively in flight (Submitted to the DEVICE transfer queue) - std::vector< TransferData > processing {}; + std::vector< TransferData > m_processing {}; //! Buffer used for any raw -> buffer transfers - std::unique_ptr< Buffer > staging_buffer {}; - - private: + std::unique_ptr< Buffer > m_staging_buffer {}; //! Map to store copy regions for processing vectors - CopyRegionMap copy_regions {}; + CopyRegionMap m_copy_regions {}; - std::uint32_t transfer_queue_index; - std::uint32_t graphics_queue_index; - vk::raii::Queue transfer_queue; + std::uint32_t m_transfer_queue_index; + std::uint32_t m_graphics_queue_index; + vk::raii::Queue m_transfer_queue; //! Signaled once a transfer completes - vk::raii::Semaphore transfer_semaphore; + vk::raii::Semaphore m_transfer_semaphore; - vk::CommandBufferAllocateInfo cmd_buffer_allocinfo; + vk::CommandBufferAllocateInfo m_cmd_buffer_allocinfo; - std::vector< vk::raii::CommandBuffer > transfer_buffers; + std::vector< vk::raii::CommandBuffer > m_transfer_buffers; - vk::raii::Fence completion_fence; + vk::raii::Fence m_completion_fence; void recordCommands( vk::raii::CommandBuffer& command_buffer ); @@ -82,7 +80,7 @@ namespace fgl::engine::memory FGL_DELETE_ALL_RO5( TransferManager ); - vk::raii::Semaphore& getFinishedSem() { return transfer_semaphore; } + vk::raii::Semaphore& getFinishedSem() { return m_transfer_semaphore; } //! Takes ownership of memory regions from the graphics queue via memory barriers. void takeOwnership( vk::raii::CommandBuffer& buffer ); @@ -93,7 +91,6 @@ namespace fgl::engine::memory //! Drops the processed items void dump(); - static void createInstance( Device& device, std::uint64_t buffer_size ); static TransferManager& getInstance(); //! Resizes the staging buffer. @@ -109,7 +106,7 @@ namespace fgl::engine::memory device_vector.m_handle, byte_offset }; - queue.emplace( std::move( transfer_data ) ); + m_queue.emplace( std::move( transfer_data ) ); } template < typename T, typename DeviceVectorT > diff --git a/src/engine/gameobjects/GameObject.cpp b/src/engine/gameobjects/GameObject.cpp index 82f0091..ceba9bb 100644 --- a/src/engine/gameobjects/GameObject.cpp +++ b/src/engine/gameobjects/GameObject.cpp @@ -7,6 +7,11 @@ namespace fgl::engine { + GameObject::~GameObject() + { + for ( const auto& component : components ) delete component; + } + GameObject GameObject::createGameObject() { static GameObjectID current_id { 0 }; diff --git a/src/engine/gameobjects/GameObject.hpp b/src/engine/gameobjects/GameObject.hpp index 1ace9d7..1ee3bd6 100644 --- a/src/engine/gameobjects/GameObject.hpp +++ b/src/engine/gameobjects/GameObject.hpp @@ -58,6 +58,8 @@ namespace fgl::engine public: + ~GameObject(); + GameObject& operator=( GameObject&& other ) = default; template < typename T > diff --git a/src/engine/memory/buffers/Buffer.cpp b/src/engine/memory/buffers/Buffer.cpp index 1d9a872..fd305ba 100644 --- a/src/engine/memory/buffers/Buffer.cpp +++ b/src/engine/memory/buffers/Buffer.cpp @@ -4,8 +4,11 @@ #include "Buffer.hpp" +#include + #include "BufferSuballocationHandle.hpp" #include "align.hpp" +#include "engine/debug/logging/logging.hpp" #include "engine/memory/buffers/exceptions.hpp" #include "engine/rendering/devices/Device.hpp" @@ -19,20 +22,43 @@ namespace fgl::engine::memory return active_buffers; } - Buffer:: - Buffer( vk::DeviceSize memory_size, vk::BufferUsageFlags usage, vk::MemoryPropertyFlags memory_properties ) : + inline static std::uint16_t counter { 0 }; + + Buffer::Buffer( + vk::DeviceSize memory_size, + const vk::BufferUsageFlags usage, + const vk::MemoryPropertyFlags memory_properties ) : m_memory_size( memory_size ), m_usage( usage ), m_memory_properties( memory_properties ) { alloc( memory_size ); active_buffers.emplace_back( this ); - m_free_blocks.push_back( { 0, memory_size } ); + m_free_blocks.emplace_back( 0, memory_size ); } Buffer::~Buffer() { - assert( this->m_allocations.size() == 0 ); + if ( !m_allocations.empty() ) + { + log::critical( "Buffer allocations not empty. {} allocations left", m_allocations.size() ); + + for ( const auto& [ offset, size ] : m_allocations ) + { + log::info( "Stacktrace: Offset at {}", offset ); + + const auto itter = this->m_allocation_traces.find( offset ); + + if ( itter == this->m_allocation_traces.end() ) continue; + + std::stacktrace trace { itter->second }; + + std::cout << trace << std::endl; + } + + 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 ); @@ -50,8 +76,9 @@ namespace fgl::engine::memory vmaDestroyBuffer( Device::getInstance().allocator(), m_buffer, m_allocation ); } - void Buffer::alloc( vk::DeviceSize memory_size ) + void Buffer::alloc( const vk::DeviceSize memory_size ) { + assert( !m_debug_name.empty() ); assert( memory_size > 0 ); m_memory_size = memory_size; vk::BufferCreateInfo buffer_info {}; @@ -180,6 +207,8 @@ namespace fgl::engine::memory //Add the suballocation m_allocations.insert_or_assign( offset, memory_size ); + m_allocation_traces.insert_or_assign( offset, std::stacktrace::current() ); + //If there is any memory left over, Then add it back into the free blocks if ( size - memory_size > 0 ) m_free_blocks.emplace_back( std::make_pair( offset + memory_size, size - memory_size ) ); diff --git a/src/engine/memory/buffers/Buffer.hpp b/src/engine/memory/buffers/Buffer.hpp index 68c54ea..9318edc 100644 --- a/src/engine/memory/buffers/Buffer.hpp +++ b/src/engine/memory/buffers/Buffer.hpp @@ -90,6 +90,7 @@ namespace fgl::engine::memory 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. diff --git a/src/engine/rendering/PresentSwapChain.cpp b/src/engine/rendering/PresentSwapChain.cpp index 82618d5..012ac23 100644 --- a/src/engine/rendering/PresentSwapChain.cpp +++ b/src/engine/rendering/PresentSwapChain.cpp @@ -403,6 +403,11 @@ namespace fgl::engine } } + std::vector< vk::raii::Fence >& PresentSwapChain::getFrameFences() + { + return m_in_flight_fence; + } + PresentSwapChain::~PresentSwapChain() {} diff --git a/src/engine/rendering/PresentSwapChain.hpp b/src/engine/rendering/PresentSwapChain.hpp index 727978c..057a3a5 100644 --- a/src/engine/rendering/PresentSwapChain.hpp +++ b/src/engine/rendering/PresentSwapChain.hpp @@ -72,6 +72,8 @@ namespace fgl::engine public: + std::vector< vk::raii::Fence >& getFrameFences(); + PresentSwapChain( vk::Extent2D windowExtent, PhysicalDevice& phy_dev ); PresentSwapChain( vk::Extent2D windowExtent, std::shared_ptr< PresentSwapChain > previous ); diff --git a/src/engine/tree/octtree/OctTreeNode.cpp b/src/engine/tree/octtree/OctTreeNode.cpp index 62c37a8..caa9876 100644 --- a/src/engine/tree/octtree/OctTreeNode.cpp +++ b/src/engine/tree/octtree/OctTreeNode.cpp @@ -157,6 +157,9 @@ namespace fgl::engine std::get< OctTreeNodeLeaf >( m_node_data ).reserve( MAX_NODES_IN_LEAF ); } + OctTreeNode::~OctTreeNode() + {} + void OctTreeNode::split( const int depth ) { ZoneScoped; diff --git a/src/engine/tree/octtree/OctTreeNode.hpp b/src/engine/tree/octtree/OctTreeNode.hpp index e6dae00..68000b6 100644 --- a/src/engine/tree/octtree/OctTreeNode.hpp +++ b/src/engine/tree/octtree/OctTreeNode.hpp @@ -4,8 +4,8 @@ #pragma once -#include "engine/gameobjects/GameObject.hpp" #include "engine/primitives/boxes/AxisAlignedBoundingCube.hpp" +#include "gameobjects/GameObject.hpp" namespace fgl::engine { @@ -60,6 +60,8 @@ namespace fgl::engine OctTreeNode( const OctTreeNode& other ) = delete; OctTreeNode( OctTreeNode&& other ) = delete; + ~OctTreeNode(); + OctTreeNode& operator=( const OctTreeNode& ) = delete; OctTreeNode& operator=( OctTreeNode&& ) = delete; void clear();