diff --git a/src/editor/src/gui/EditorGuiContext.cpp b/src/editor/src/gui/EditorGuiContext.cpp index d464bad..84930da 100644 --- a/src/editor/src/gui/EditorGuiContext.cpp +++ b/src/editor/src/gui/EditorGuiContext.cpp @@ -117,13 +117,22 @@ namespace fgl::editor gui::drawStats( info ); } - void EditorGuiContext::endDraw( vk::raii::CommandBuffer& command_buffer ) + void EditorGuiContext::endDraw( CommandBuffer& command_buffer ) { ZoneScoped; ImGui::Render(); + constexpr static std::string_view label { "IMGUI Rendering" }; + + vk::DebugUtilsLabelEXT debug_label; + debug_label.pLabelName = label.data(); + + command_buffer->beginDebugUtilsLabelEXT( debug_label ); + ImDrawData* data { ImGui::GetDrawData() }; - ImGui_ImplVulkan_RenderDrawData( data, *command_buffer ); + ImGui_ImplVulkan_RenderDrawData( data, **command_buffer ); + + command_buffer->endDebugUtilsLabelEXT(); //ImGui::UpdatePlatformWindows(); //ImGui::RenderPlatformWindowsDefault(); @@ -131,6 +140,6 @@ namespace fgl::editor void EditorGuiContext::endDraw( FrameInfo& info ) { - return endDraw( info.command_buffer ); + return endDraw( info.command_buffer.imgui_cb ); } } // 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 index a9e151a..7404eb8 100644 --- a/src/editor/src/gui/EditorGuiContext.hpp +++ b/src/editor/src/gui/EditorGuiContext.hpp @@ -17,7 +17,7 @@ namespace fgl::editor void beginDraw(); void draw( engine::FrameInfo& info ); - void endDraw( vk::raii::CommandBuffer& command_buffer ); + void endDraw( engine::CommandBuffer& command_buffer ); void endDraw( engine::FrameInfo& info ); }; } // namespace fgl::editor \ No newline at end of file diff --git a/src/engine/EngineContext.cpp b/src/engine/EngineContext.cpp index 7de97e1..cea22a9 100644 --- a/src/engine/EngineContext.cpp +++ b/src/engine/EngineContext.cpp @@ -145,16 +145,18 @@ namespace fgl::engine void EngineContext::renderFrame() { ZoneScoped; - if ( auto& command_buffer = m_renderer.beginFrame(); *command_buffer ) + if ( auto command_buffers_o = m_renderer.beginFrame(); command_buffers_o.has_value() ) { const auto timer = debug::timing::push( "Render Frame" ); const FrameIndex frame_index { m_renderer.getFrameIndex() }; const PresentIndex present_idx { m_renderer.getPresentIndex() }; + auto& command_buffers { command_buffers_o.value() }; + FrameInfo frame_info { frame_index, present_idx, m_delta_time, - command_buffer, + command_buffers, nullptr, // Camera m_camera_manager.getCameras(), // global_descriptor_sets[ frame_index ], @@ -172,25 +174,25 @@ namespace fgl::engine for ( const auto& hook : m_pre_frame_hooks ) hook( frame_info ); } - TracyVkCollect( frame_info.tracy_ctx, *command_buffer ); + TracyVkCollect( frame_info.tracy_ctx, *command_buffers.transfer_cb ); //TODO: Setup semaphores to make this pass not always required. - m_transfer_manager.recordOwnershipTransferDst( command_buffer ); + 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 ); for ( const auto& hook : m_render_hooks ) hook( frame_info ); - m_renderer.beginSwapchainRendererPass( command_buffer ); + m_renderer.beginSwapchainRendererPass( command_buffers.imgui_cb ); m_gui_system.pass( frame_info ); for ( const auto& hook : m_late_render_hooks ) hook( frame_info ); - m_renderer.endSwapchainRendererPass( command_buffer ); + m_renderer.endSwapchainRendererPass( command_buffers.imgui_cb ); - m_renderer.endFrame(); + m_renderer.endFrame( command_buffers ); m_transfer_manager.dump(); diff --git a/src/engine/FrameInfo.hpp b/src/engine/FrameInfo.hpp index 73b305d..5911933 100644 --- a/src/engine/FrameInfo.hpp +++ b/src/engine/FrameInfo.hpp @@ -12,6 +12,7 @@ #include "descriptors/Descriptor.hpp" #include "descriptors/DescriptorSetLayout.hpp" #include "primitives/Frustum.hpp" +#include "rendering/CommandBuffers.hpp" #include "rendering/types.hpp" #define MAX_LIGHTS 10 @@ -75,7 +76,7 @@ namespace fgl::engine PresentIndex present_idx; double delta_time; - vk::raii::CommandBuffer& command_buffer; + CommandBuffers& command_buffer; Camera* camera { nullptr }; diff --git a/src/engine/assets/transfer/TransferManager.cpp b/src/engine/assets/transfer/TransferManager.cpp index 45182b5..72dd3bd 100644 --- a/src/engine/assets/transfer/TransferManager.cpp +++ b/src/engine/assets/transfer/TransferManager.cpp @@ -54,6 +54,11 @@ namespace fgl::engine::memory const std::vector< vk::BufferMemoryBarrier > from_memory_barriers { createFromGraphicsBarriers() }; + vk::DebugUtilsLabelEXT debug_label {}; + debug_label.pLabelName = "Transfer"; + + command_buffer.beginDebugUtilsLabelEXT( debug_label ); + // Acquire the buffer from the queue family command_buffer.pipelineBarrier( vk::PipelineStageFlagBits::eBottomOfPipe, @@ -66,7 +71,7 @@ namespace fgl::engine::memory //Record all the buffer copies for ( auto& [ key, regions ] : m_copy_regions ) { - auto& [ source, target ] = key; + const auto& [ source, target ] = key; command_buffer.copyBuffer( source, target, regions ); } @@ -81,6 +86,8 @@ namespace fgl::engine::memory {}, to_buffer_memory_barriers, {} ); + + command_buffer.endDebugUtilsLabelEXT(); } void TransferManager::resizeBuffer( const std::uint64_t size ) @@ -218,21 +225,21 @@ namespace fgl::engine::memory inline static TransferManager* GLOBAL_TRANSFER_MANAGER {}; - void TransferManager::takeOwnership( vk::raii::CommandBuffer& command_buffer ) + void TransferManager::takeOwnership( CommandBuffer& command_buffer ) { std::vector< vk::BufferMemoryBarrier > barriers { createToTransferBarriers() }; - command_buffer.pipelineBarrier( + command_buffer->pipelineBarrier( vk::PipelineStageFlagBits::eNone, vk::PipelineStageFlagBits::eTransfer, {}, {}, barriers, {} ); } - void TransferManager::recordOwnershipTransferDst( vk::raii::CommandBuffer& command_buffer ) + void TransferManager::recordOwnershipTransferDst( CommandBuffer& command_buffer ) { ZoneScoped; std::vector< vk::BufferMemoryBarrier > barriers { createToGraphicsBarriers() }; - command_buffer.pipelineBarrier( + command_buffer->pipelineBarrier( vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eVertexInput | vk::PipelineStageFlagBits::eVertexShader, {}, diff --git a/src/engine/assets/transfer/TransferManager.hpp b/src/engine/assets/transfer/TransferManager.hpp index 4c6a77d..a4755f4 100644 --- a/src/engine/assets/transfer/TransferManager.hpp +++ b/src/engine/assets/transfer/TransferManager.hpp @@ -84,10 +84,10 @@ namespace fgl::engine::memory 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 ); + void takeOwnership( CommandBuffer& command_buffer ); //! Records the barriers required for transfering queue ownership - void recordOwnershipTransferDst( vk::raii::CommandBuffer& command_buffer ); + void recordOwnershipTransferDst( CommandBuffer& command_buffer ); //! Drops the processed items void dump(); diff --git a/src/engine/camera/Camera.cpp b/src/engine/camera/Camera.cpp index 98d2b37..c417dfc 100644 --- a/src/engine/camera/Camera.cpp +++ b/src/engine/camera/Camera.cpp @@ -133,6 +133,8 @@ namespace fgl::engine { this->setPerspectiveProjection( m_fov_y, aspectRatio(), constants::NEAR_PLANE, constants::FAR_PLANE ); + log::debug( "Camera swapchain recreated" ); + m_old_composite_swapchain = std::move( m_composite_swapchain ); m_old_gbuffer_swapchain = std::move( m_gbuffer_swapchain ); @@ -335,13 +337,13 @@ namespace fgl::engine m_composite_swapchain( std::make_unique< CompositeSwapchain >( m_target_extent ) ), m_gbuffer_swapchain( std::make_unique< GBufferSwapchain >( m_target_extent ) ), m_camera_renderer( renderer ), - m_camera_frame_info( buffer, PresentSwapChain::MAX_FRAMES_IN_FLIGHT ) + m_camera_frame_info( buffer, constants::MAX_FRAMES_IN_FLIGHT ) { FGL_ASSERT( renderer, "Camera renderer is null" ); this->setPerspectiveProjection( m_fov_y, aspectRatio(), constants::NEAR_PLANE, constants::FAR_PLANE ); this->setView( WorldCoordinate( constants::CENTER ), Rotation( 0.0f, 0.0f, 0.0f ) ); - for ( std::uint8_t i = 0; i < PresentSwapChain::MAX_FRAMES_IN_FLIGHT; ++i ) + for ( std::uint8_t i = 0; i < constants::MAX_FRAMES_IN_FLIGHT; ++i ) { auto set { camera_descriptor_set.create() }; set->bindUniformBuffer( 0, m_camera_frame_info[ i ] ); diff --git a/src/engine/camera/CompositeSwapchain.cpp b/src/engine/camera/CompositeSwapchain.cpp index 74aa859..cbd12e6 100644 --- a/src/engine/camera/CompositeSwapchain.cpp +++ b/src/engine/camera/CompositeSwapchain.cpp @@ -10,8 +10,7 @@ namespace fgl::engine { class Texture; - void CompositeSwapchain:: - transitionImages( vk::raii::CommandBuffer& command_buffer, StageID stage_id, FrameIndex index ) + void CompositeSwapchain::transitionImages( CommandBuffer& command_buffer, StageID stage_id, FrameIndex index ) { switch ( stage_id ) { @@ -24,7 +23,7 @@ namespace fgl::engine .transitionColorTo( vk::ImageLayout::eUndefined, vk::ImageLayout::eColorAttachmentOptimal ), }; - command_buffer.pipelineBarrier( + command_buffer->pipelineBarrier( vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eColorAttachmentOutput, vk::DependencyFlags( 0 ), @@ -41,7 +40,7 @@ namespace fgl::engine vk::ImageLayout::eColorAttachmentOptimal, vk::ImageLayout::eShaderReadOnlyOptimal ), }; - command_buffer.pipelineBarrier( + command_buffer->pipelineBarrier( vk::PipelineStageFlagBits::eColorAttachmentOutput, vk::PipelineStageFlagBits::eFragmentShader, vk::DependencyFlags( 0 ), @@ -58,7 +57,7 @@ namespace fgl::engine vk::ImageLayout::eColorAttachmentOptimal, vk::ImageLayout::ePresentSrcKHR ), }; - command_buffer.pipelineBarrier( + command_buffer->pipelineBarrier( vk::PipelineStageFlagBits::eColorAttachmentOutput, vk::PipelineStageFlagBits::eBottomOfPipe, vk::DependencyFlags( 0 ), @@ -94,7 +93,7 @@ namespace fgl::engine CompositeSwapchain::CompositeSwapchain( vk::Extent2D extent ) : m_extent( extent ) { - constexpr auto image_count { PresentSwapChain::MAX_FRAMES_IN_FLIGHT }; + constexpr auto image_count { constants::MAX_FRAMES_IN_FLIGHT }; m_buffer.m_target.createResources( image_count, m_extent, vk::ImageUsageFlagBits::eTransferSrc ); m_buffer.m_target.setName( "CompositeSwapchain::m_target" ); diff --git a/src/engine/camera/CompositeSwapchain.hpp b/src/engine/camera/CompositeSwapchain.hpp index 662044b..c01c6ad 100644 --- a/src/engine/camera/CompositeSwapchain.hpp +++ b/src/engine/camera/CompositeSwapchain.hpp @@ -7,6 +7,7 @@ #include "FGL_DEFINES.hpp" #include "engine/rendering/RenderingFormats.hpp" #include "engine/rendering/pipelines/Attachment.hpp" +#include "rendering/CommandBufferPool.hpp" namespace fgl::engine { @@ -35,7 +36,7 @@ namespace fgl::engine FINAL_PRESENT, }; - void transitionImages( vk::raii::CommandBuffer& command_buffer, StageID stage_id, FrameIndex index ); + void transitionImages( CommandBuffer& command_buffer, StageID stage_id, FrameIndex index ); vk::RenderingInfo getRenderingInfo( FrameIndex index ); diff --git a/src/engine/camera/GBufferCompositor.cpp b/src/engine/camera/GBufferCompositor.cpp index 5b36fba..1005621 100644 --- a/src/engine/camera/GBufferCompositor.cpp +++ b/src/engine/camera/GBufferCompositor.cpp @@ -36,20 +36,19 @@ namespace fgl::engine command_buffer.setScissor( 0, scissors ); } - void GBufferCompositor:: - beginPass( vk::raii::CommandBuffer& cmd, CompositeSwapchain& swapchain, const FrameIndex& index ) + void GBufferCompositor::beginPass( CommandBuffer& cmd, CompositeSwapchain& swapchain, const FrameIndex& index ) { const vk::RenderingInfo info { swapchain.getRenderingInfo( index ) }; - cmd.beginRendering( info ); + cmd->beginRendering( info ); - setViewport( cmd, swapchain.getExtent() ); - setScissor( cmd, swapchain.getExtent() ); + setViewport( *cmd, swapchain.getExtent() ); + setScissor( *cmd, swapchain.getExtent() ); } - void GBufferCompositor::endPass( vk::raii::CommandBuffer& cmd ) + void GBufferCompositor::endPass( CommandBuffer& cmd ) { - cmd.endRendering(); + cmd->endRendering(); } GBufferCompositor::GBufferCompositor( const CompositeFlags flags ) : m_flags( flags ) @@ -74,8 +73,7 @@ namespace fgl::engine m_pipeline->setDebugName( "Composition pipeline" ); } - void GBufferCompositor:: - composite( vk::raii::CommandBuffer& command_buffer, Camera& camera, const FrameIndex frame_index ) + void GBufferCompositor::composite( CommandBuffer& command_buffer, Camera& camera, const FrameIndex frame_index ) { auto& gbuffer_swapchain { camera.getSwapchain() }; auto& composite_swapchain { camera.getCompositeSwapchain() }; @@ -91,7 +89,7 @@ namespace fgl::engine m_pipeline->pushConstant( command_buffer, vk::ShaderStageFlagBits::eFragment, m_control ); - command_buffer.draw( 3, 1, 0, 0 ); + command_buffer->draw( 3, 1, 0, 0 ); endPass( command_buffer ); diff --git a/src/engine/camera/GBufferCompositor.hpp b/src/engine/camera/GBufferCompositor.hpp index 31e8b90..6b08027 100644 --- a/src/engine/camera/GBufferCompositor.hpp +++ b/src/engine/camera/GBufferCompositor.hpp @@ -39,8 +39,8 @@ namespace fgl::engine void setViewport( const vk::raii::CommandBuffer& cmd, vk::Extent2D extent_2d ); void setScissor( const vk::raii::CommandBuffer& cmd, vk::Extent2D extent_2d ); - void beginPass( vk::raii::CommandBuffer& cmd, CompositeSwapchain& swapchain, const FrameIndex& index ); - void endPass( vk::raii::CommandBuffer& cmd ); + void beginPass( CommandBuffer& cmd, CompositeSwapchain& swapchain, const FrameIndex& index ); + void endPass( CommandBuffer& cmd ); CompositionControl m_control {}; @@ -48,7 +48,7 @@ namespace fgl::engine GBufferCompositor( CompositeFlags flags = CompositeFlagBits_Standard ); - void composite( vk::raii::CommandBuffer& command_buffer, Camera& camera, FrameIndex frame_index ); + void composite( CommandBuffer& command_buffer, Camera& camera, FrameIndex frame_index ); inline void switchMode( const CompositeFlags flags ) { m_flags = flags; } }; diff --git a/src/engine/camera/GBufferRenderer.cpp b/src/engine/camera/GBufferRenderer.cpp index ad5d09c..365501e 100644 --- a/src/engine/camera/GBufferRenderer.cpp +++ b/src/engine/camera/GBufferRenderer.cpp @@ -5,13 +5,14 @@ #include "GBufferRenderer.hpp" #include "Camera.hpp" +#include "GBufferSwapchain.hpp" #include "engine/rendering/renderpass/RenderPass.hpp" namespace fgl::engine { class GBufferSwapchain; - void GBufferRenderer::setViewport( const vk::raii::CommandBuffer& command_buffer, const vk::Extent2D extent ) + void GBufferRenderer::setViewport( const CommandBuffer& command_buffer, const vk::Extent2D extent ) { vk::Viewport viewport {}; viewport.x = 0.0f; @@ -24,32 +25,32 @@ namespace fgl::engine const std::vector< vk::Viewport > viewports { viewport }; - command_buffer.setViewport( 0, viewports ); + command_buffer->setViewport( 0, viewports ); } - void GBufferRenderer::setScissor( const vk::raii::CommandBuffer& command_buffer, const vk::Extent2D extent ) + void GBufferRenderer::setScissor( const CommandBuffer& command_buffer, const vk::Extent2D extent ) { const vk::Rect2D scissor { { 0, 0 }, extent }; const std::vector< vk::Rect2D > scissors { scissor }; - command_buffer.setScissor( 0, scissors ); + command_buffer->setScissor( 0, scissors ); } - void GBufferRenderer::beginRenderPass( - const vk::raii::CommandBuffer& command_buffer, GBufferSwapchain& swapchain, const FrameIndex index ) + void GBufferRenderer:: + beginRenderPass( const CommandBuffer& command_buffer, GBufferSwapchain& swapchain, const FrameIndex index ) { const vk::RenderingInfo info { swapchain.getRenderingInfo( index ) }; - command_buffer.beginRendering( info ); + command_buffer->beginRendering( info ); setViewport( command_buffer, swapchain.getExtent() ); setScissor( command_buffer, swapchain.getExtent() ); } - void GBufferRenderer::endRenderPass( const vk::raii::CommandBuffer& command_buffer ) + void GBufferRenderer::endRenderPass( const CommandBuffer& command_buffer ) { - command_buffer.endRendering(); + command_buffer->endRendering(); } void GBufferRenderer::pass( FrameInfo& frame_info, GBufferSwapchain& camera_swapchain ) @@ -57,7 +58,7 @@ namespace fgl::engine ZoneScopedN( "CameraRenderer::pass" ); m_culling_system.startPass( frame_info ); - auto& command_buffer { frame_info.command_buffer }; + auto& command_buffer { frame_info.command_buffer.render_cb }; camera_swapchain.transitionImages( command_buffer, GBufferSwapchain::INITAL, frame_info.frame_idx ); diff --git a/src/engine/camera/GBufferRenderer.hpp b/src/engine/camera/GBufferRenderer.hpp index 74a983d..7e91989 100644 --- a/src/engine/camera/GBufferRenderer.hpp +++ b/src/engine/camera/GBufferRenderer.hpp @@ -5,7 +5,6 @@ #pragma once #include "GBufferCompositor.hpp" -#include "GBufferSwapchain.hpp" #include "engine/systems/prerender/CullingSystem.hpp" #include "engine/systems/render/EntityRendererSystem.hpp" #include "engine/systems/render/LineDrawer.hpp" @@ -17,8 +16,8 @@ namespace fgl::engine { GBufferCompositor m_compositor; - void setViewport( const vk::raii::CommandBuffer& command_buffer, vk::Extent2D extent ); - void setScissor( const vk::raii::CommandBuffer& command_buffer, vk::Extent2D extent ); + void setViewport( const CommandBuffer& command_buffer, vk::Extent2D extent ); + void setScissor( const CommandBuffer& command_buffer, vk::Extent2D extent ); CullingSystem m_culling_system {}; @@ -30,10 +29,9 @@ namespace fgl::engine // SubPass 1 // CompositionSystem m_composition_system {}; - void beginRenderPass( - const vk::raii::CommandBuffer& command_buffer, GBufferSwapchain& swapchain, FrameIndex index ); + void beginRenderPass( const CommandBuffer& command_buffer, GBufferSwapchain& swapchain, FrameIndex index ); - void endRenderPass( const vk::raii::CommandBuffer& command_buffer ); + void endRenderPass( const CommandBuffer& command_buffer ); public: diff --git a/src/engine/camera/GBufferSwapchain.cpp b/src/engine/camera/GBufferSwapchain.cpp index 5dffa81..bb5a8ca 100644 --- a/src/engine/camera/GBufferSwapchain.cpp +++ b/src/engine/camera/GBufferSwapchain.cpp @@ -12,9 +12,9 @@ namespace fgl::engine std::vector< std::unique_ptr< descriptors::DescriptorSet > > GBufferSwapchain::createGBufferDescriptors() { std::vector< std::unique_ptr< descriptors::DescriptorSet > > data {}; - data.resize( PresentSwapChain::MAX_FRAMES_IN_FLIGHT ); + data.resize( constants::MAX_FRAMES_IN_FLIGHT ); - for ( PresentIndex i = 0; i < PresentSwapChain::MAX_FRAMES_IN_FLIGHT; ++i ) + for ( PresentIndex i = 0; i < constants::MAX_FRAMES_IN_FLIGHT; ++i ) { //auto set { std::make_unique< descriptors::DescriptorSet >( GBufferDescriptorSet::createLayout() ) }; auto set { gbuffer_set.create() }; @@ -37,8 +37,8 @@ namespace fgl::engine return data; } - void GBufferSwapchain::transitionImages( - vk::raii::CommandBuffer& command_buffer, const std::uint16_t stage_id, const FrameIndex index ) + void GBufferSwapchain:: + transitionImages( CommandBuffer& command_buffer, const std::uint16_t stage_id, const FrameIndex index ) { switch ( stage_id ) { @@ -63,7 +63,7 @@ namespace fgl::engine vk::ImageAspectFlagBits::eDepth ), }; - command_buffer.pipelineBarrier( + command_buffer->pipelineBarrier( vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eColorAttachmentOutput | vk::PipelineStageFlagBits::eEarlyFragmentTests @@ -96,7 +96,7 @@ namespace fgl::engine // vk::ImageAspectFlagBits::eDepth ), }; - command_buffer.pipelineBarrier( + command_buffer->pipelineBarrier( vk::PipelineStageFlagBits::eColorAttachmentOutput, vk::PipelineStageFlagBits::eFragmentShader, vk::DependencyFlags( 0 ), @@ -157,7 +157,7 @@ namespace fgl::engine GBufferSwapchain::GBufferSwapchain( const vk::Extent2D extent ) : m_extent( extent ) // m_gbuffer_descriptor_set( createGBufferDescriptors() ) { - constexpr auto image_count { PresentSwapChain::MAX_FRAMES_IN_FLIGHT }; + constexpr auto image_count { constants::MAX_FRAMES_IN_FLIGHT }; m_gbuffer.m_color.createResources( image_count, m_extent ); m_gbuffer.m_position.createResources( image_count, m_extent ); diff --git a/src/engine/camera/GBufferSwapchain.hpp b/src/engine/camera/GBufferSwapchain.hpp index 957f802..6ac6fbd 100644 --- a/src/engine/camera/GBufferSwapchain.hpp +++ b/src/engine/camera/GBufferSwapchain.hpp @@ -53,7 +53,7 @@ namespace fgl::engine FINAL }; - void transitionImages( vk::raii::CommandBuffer& command_buffer, std::uint16_t stage_id, FrameIndex index ); + void transitionImages( CommandBuffer& command_buffer, std::uint16_t stage_id, FrameIndex index ); vk::RenderingInfo getRenderingInfo( const FrameIndex frame_index ); GBufferSwapchain( vk::Extent2D extent ); diff --git a/src/engine/constants.hpp b/src/engine/constants.hpp index 4394f8a..c470127 100644 --- a/src/engine/constants.hpp +++ b/src/engine/constants.hpp @@ -49,4 +49,6 @@ namespace fgl::engine::constants constexpr TextureID INVALID_TEXTURE_ID { 0 }; + constexpr std::uint8_t MAX_FRAMES_IN_FLIGHT { 2 }; + } // namespace fgl::engine::constants diff --git a/src/engine/descriptors/DescriptorSet.cpp b/src/engine/descriptors/DescriptorSet.cpp index a3013ed..1288373 100644 --- a/src/engine/descriptors/DescriptorSet.cpp +++ b/src/engine/descriptors/DescriptorSet.cpp @@ -214,7 +214,7 @@ namespace fgl::engine::descriptors { auto& [ counter, set ] = *itter; // Prevent deleting a descriptor until we are sure it's been here long enough - if ( counter > PresentSwapChain::MAX_FRAMES_IN_FLIGHT + 1 ) + if ( counter > constants::MAX_FRAMES_IN_FLIGHT + 1 ) { itter = QUEUE.erase( itter ); } diff --git a/src/engine/rendering/CommandBuffer.cpp b/src/engine/rendering/CommandBuffer.cpp new file mode 100644 index 0000000..709bcb7 --- /dev/null +++ b/src/engine/rendering/CommandBuffer.cpp @@ -0,0 +1,25 @@ +// +// Created by kj16609 on 2/14/25. +// +#include "CommandBuffer.hpp" + +#include "CommandBufferPool.hpp" +#include "debug/logging/logging.hpp" + +namespace fgl::engine +{ + CommandBufferHandle::CommandBufferHandle( vk::raii::CommandBuffer&& buffer, const CommandType type ) : + m_cmd_buffer( std::move( buffer ) ), + m_type( type ) + {} + + CommandBufferHandle::~CommandBufferHandle() + { + log::warn( "Command buffer handle destroyed!" ); + } + + vk::raii::CommandBuffer& CommandBufferHandle::cmd() + { + return m_cmd_buffer; + } +} // namespace fgl::engine \ No newline at end of file diff --git a/src/engine/rendering/CommandBuffer.hpp b/src/engine/rendering/CommandBuffer.hpp new file mode 100644 index 0000000..b350e3e --- /dev/null +++ b/src/engine/rendering/CommandBuffer.hpp @@ -0,0 +1,53 @@ +// +// Created by kj16609 on 2/14/25. +// +#pragma once +#include + +#include "FGL_DEFINES.hpp" + +namespace fgl::engine +{ + class CommandBufferPool; + + /** + * @brief Contains a vk::raii::CommandBuffer to be used for recording, and a list of all assets to be appended too for each asset used. + */ + class CommandBufferHandle + { + public: + + enum CommandType : std::uint8_t + { + Invalid = 0, + Primary = 1, + Secondary = 2 + } m_type; + + private: + + /* + * Later on we'll want to append to this list in order to keep various assets alive + * that need to persist for this command buffer. Once this command buffer is reset, + * we can then drop all the assets kept in this list if they are ready to be deleted + */ + // std::vector< std::shared_ptr< AssetHandle > > m_asset_handles {}; + + vk::raii::CommandBuffer m_cmd_buffer; + + friend class CommandBufferPool; + + explicit CommandBufferHandle( vk::raii::CommandBuffer&& buffer, CommandType type ); + + public: + + FGL_DELETE_COPY( CommandBufferHandle ); + FGL_DELETE_MOVE( CommandBufferHandle ); + CommandBufferHandle() = delete; + + ~CommandBufferHandle(); + + vk::raii::CommandBuffer& cmd(); + }; + +} // namespace fgl::engine \ No newline at end of file diff --git a/src/engine/rendering/CommandBufferPool.cpp b/src/engine/rendering/CommandBufferPool.cpp new file mode 100644 index 0000000..fc11d35 --- /dev/null +++ b/src/engine/rendering/CommandBufferPool.cpp @@ -0,0 +1,199 @@ +// +// Created by kj16609 on 2/14/25. +// +#include "CommandBufferPool.hpp" + +#include "devices/Device.hpp" + +namespace fgl::engine +{ + /* + std::shared_ptr< CommandBufferHandle > CommandBufferPool::createBuffer() + { + CommandBufferHandle* handle_ptr { nullptr }; + + vk::CommandBufferAllocateInfo allocate_info {}; + + allocate_info.commandBufferCount = 1; + + return std::shared_ptr< CommandBufferHandle >( handle_ptr ); + } + */ + + // No longer need eTransient as these will persist from start until destruction of the engine. + // eResetCommandBuffer indicates that we'll be the ones resetting the command buffer. + constexpr vk::CommandPoolCreateFlags CREATE_FLAGS { vk::CommandPoolCreateFlagBits::eResetCommandBuffer }; + + CommandBuffer::CommandBuffer( std::shared_ptr< CommandBufferHandle >&& handle, CommandBufferPool* pool ) : + m_handle( std::move( handle ) ), + m_pool( pool ) + {} + + vk::raii::CommandBuffer* CommandBuffer::operator->() const + { + return &m_handle->cmd(); + } + + vk::raii::CommandBuffer& CommandBuffer::operator*() const + { + return m_handle->cmd(); + } + + void CommandBuffer::setName( const char* name ) + { + vk::DebugUtilsObjectNameInfoEXT info {}; + info.setObjectType( vk::ObjectType::eCommandBuffer ); + info.setPObjectName( name ); + info.setObjectHandle( + reinterpret_cast< std::uint64_t >( static_cast< VkCommandBuffer >( *( m_handle->cmd() ) ) ) ); + + Device::getInstance().setDebugUtilsObjectName( info ); + } + + CommandBuffer::CommandBuffer( CommandBuffer&& other ) noexcept : + m_handle( std::move( other.m_handle ) ), + m_pool( other.m_pool ) + { + FGL_ASSERT( m_handle, "Invalid handle when moving" ); + other.m_handle = nullptr; + other.m_pool = nullptr; + } + + CommandBuffer::~CommandBuffer() + { + if ( m_handle ) m_pool->markInFlight( std::move( m_handle ) ); + } + + void CommandBufferPool::advanceInFlight() + { + std::lock_guard guard { m_queue_mtx }; + + in_flight_idx += 1; + if ( in_flight_idx >= constants::MAX_FRAMES_IN_FLIGHT ) in_flight_idx = 0; + + std::vector< std::shared_ptr< CommandBufferHandle > >& vec { m_in_flight[ in_flight_idx ] }; + + // return all command buffers back to the pool to prepare for new insertions + for ( std::shared_ptr< CommandBufferHandle >& buffer : vec ) + { + // Reset command buffer before returning it back to the pool + buffer->cmd().reset(); + + FGL_ASSERT( buffer->m_type != CommandBufferHandle::Invalid, "Command buffer type invalid" ); + + auto& target { buffer->m_type == CommandBufferHandle::Primary ? m_available_p_buffers : + m_available_s_buffers }; + + target.push( std::move( buffer ) ); + } + + vec.clear(); + } + + void CommandBufferPool::markInFlight( std::shared_ptr< CommandBufferHandle >&& buffer ) + { + FGL_ASSERT( buffer, "Buffer was not valid!" ); + m_in_flight[ in_flight_idx ].emplace_back( std::move( buffer ) ); + } + + CommandBufferPool createGraphicsPool( vk::raii::Device& device, PhysicalDevice& physical_device ) + { + const auto graphics_index { physical_device.queueInfo().getIndex( vk::QueueFlagBits::eGraphics ) }; + + return { device, graphics_index }; + } + + CommandBufferPool createTransferPool( vk::raii::Device& device, PhysicalDevice& physical_device ) + { + const auto transfer_index { physical_device.queueInfo().getIndex( vk::QueueFlagBits::eTransfer ) }; + + return { device, transfer_index }; + } + + CommandBufferPool::CommandBufferPool( vk::raii::Device& device, const std::uint32_t queue_index ) : + m_pool_info( CREATE_FLAGS, queue_index ), + m_pool( device.createCommandPool( m_pool_info ) ), + in_flight_idx( 0 ) + { + constexpr std::size_t command_buffer_target { 8 }; + constexpr std::size_t secondary_multip { 16 }; + + vk::CommandBufferAllocateInfo info {}; + + info.setCommandPool( m_pool ); + + { + info.setCommandBufferCount( command_buffer_target ); + info.setLevel( vk::CommandBufferLevel::ePrimary ); + + std::vector< vk::raii::CommandBuffer > command_buffers { device.allocateCommandBuffers( info ) }; + + std::lock_guard guard { m_queue_mtx }; + + for ( auto& command_buffer : command_buffers ) + { + auto* ptr { new CommandBufferHandle( std::move( command_buffer ), CommandBufferHandle::Primary ) }; + + m_available_p_buffers.push( std::shared_ptr< CommandBufferHandle >( ptr ) ); + } + } + + { + info.setLevel( vk::CommandBufferLevel::eSecondary ); + info.setCommandBufferCount( command_buffer_target * secondary_multip ); + + std::vector< vk::raii::CommandBuffer > command_buffers { device.allocateCommandBuffers( info ) }; + + std::lock_guard guard { m_queue_mtx }; + + for ( auto& command_buffer : command_buffers ) + { + auto* ptr { new CommandBufferHandle( std::move( command_buffer ), CommandBufferHandle::Secondary ) }; + + m_available_s_buffers.push( std::shared_ptr< CommandBufferHandle >( ptr ) ); + } + } + } + + CommandBufferPool::~CommandBufferPool() + {} + + [[nodiscard]] CommandBuffer CommandBufferPool::getCommandBuffer( const CommandBufferHandle::CommandType type ) + { + std::lock_guard guard { m_queue_mtx }; + + auto& source { type == CommandBufferHandle::Primary ? m_available_p_buffers : m_available_s_buffers }; + + FGL_ASSERT( source.size() > 0, "No available command buffers!" ); + + auto buffer = source.front(); + source.pop(); + + return { std::move( buffer ), this }; + } + + std::vector< CommandBuffer > CommandBufferPool:: + getCommandBuffers( const std::size_t count, const CommandBufferHandle::CommandType type ) + { + std::lock_guard guard { m_queue_mtx }; + + std::vector< CommandBuffer > command_buffers {}; + command_buffers.reserve( count ); + + auto& source { type == CommandBufferHandle::Primary ? m_available_p_buffers : m_available_s_buffers }; + + for ( std::size_t i = 0; i < count; ++i ) + { + FGL_ASSERT( source.size() > 0, "No available command buffers!" ); + + CommandBuffer buffer { std::move( source.front() ), this }; + + command_buffers.emplace_back( std::move( buffer ) ); + + source.pop(); + } + + return command_buffers; + } + +} // namespace fgl::engine diff --git a/src/engine/rendering/CommandBufferPool.hpp b/src/engine/rendering/CommandBufferPool.hpp new file mode 100644 index 0000000..0db2a94 --- /dev/null +++ b/src/engine/rendering/CommandBufferPool.hpp @@ -0,0 +1,89 @@ +// +// Created by kj16609 on 2/14/25. +// +#pragma once +#include +#include + +#include "CommandBuffer.hpp" +#include "FGL_DEFINES.hpp" +#include "constants.hpp" +#include "devices/PhysicalDevice.hpp" +#include "types.hpp" + +namespace fgl::engine +{ + class Device; + + class CommandBuffer + { + std::shared_ptr< CommandBufferHandle > m_handle; + CommandBufferPool* m_pool; + + CommandBuffer( std::shared_ptr< CommandBufferHandle >&& handle, CommandBufferPool* pool ); + + friend class CommandBufferPool; + + public: + + vk::raii::CommandBuffer* operator->() const; + + vk::raii::CommandBuffer& operator*() const; + + void setName( const char* name ); + + FGL_DELETE_COPY( CommandBuffer ); + FGL_DELETE_MOVE_ASSIGN( CommandBuffer ); + + CommandBuffer( CommandBuffer&& other ) noexcept; + + ~CommandBuffer(); + }; + + class CommandBufferPool + { + vk::CommandPoolCreateInfo m_pool_info; + vk::raii::CommandPool m_pool; + + std::mutex m_queue_mtx {}; + //! Available primary command buffers + std::queue< std::shared_ptr< CommandBufferHandle > > m_available_s_buffers {}; + + //! Available secondary command buffers + std::queue< std::shared_ptr< CommandBufferHandle > > m_available_p_buffers {}; + + // std::shared_ptr< CommandBufferHandle > createBuffer(); + + //! Command pools that might still be in flight. + FrameIndex in_flight_idx; + std::array< std::vector< std::shared_ptr< CommandBufferHandle > >, constants::MAX_FRAMES_IN_FLIGHT > + m_in_flight {}; + + void markInFlight( std::shared_ptr< CommandBufferHandle >&& buffer ); + + friend class CommandBuffer; + + public: + + CommandBufferPool() = delete; + CommandBufferPool( vk::raii::Device& device, std::uint32_t queue_index ); + // CommandBufferPool( PhysicalDevice& phy_device, vk::raii::Device& device ); + ~CommandBufferPool(); + + FGL_DELETE_COPY( CommandBufferPool ); + FGL_DELETE_MOVE( CommandBufferPool ); + + //! Gets an available and empty command buffer + //TODO: According to vulkan it's recomended to have a entire command pool per thread, + // However because we are going to re-use as many of these buffers, I'm unsure if it's needed? + CommandBuffer getCommandBuffer( CommandBufferHandle::CommandType type ); + std::vector< CommandBuffer > getCommandBuffers( std::size_t count, CommandBufferHandle::CommandType type ); + + //! Moves the in-flight tracking number to the next index + void advanceInFlight(); + }; + + CommandBufferPool createGraphicsPool( vk::raii::Device& device, PhysicalDevice& physical_device ); + CommandBufferPool createTransferPool( vk::raii::Device& device, PhysicalDevice& physical_device ); + +} // namespace fgl::engine \ No newline at end of file diff --git a/src/engine/rendering/CommandBuffers.cpp b/src/engine/rendering/CommandBuffers.cpp new file mode 100644 index 0000000..7cdabe4 --- /dev/null +++ b/src/engine/rendering/CommandBuffers.cpp @@ -0,0 +1,21 @@ +// +// Created by kj16609 on 2/14/25. +// + +#include "CommandBuffers.hpp" + +namespace fgl::engine +{ + + CommandBuffers::CommandBuffers( std::vector< CommandBuffer >&& buffers ) : + imgui_cb( std::move( buffers[ 0 ] ) ), + transfer_cb( std::move( buffers[ 1 ] ) ), + render_cb( std::move( buffers[ 2 ] ) ), + composition_cb( std::move( buffers[ 3 ] ) ) + { + imgui_cb.setName( "ImGui CB" ); + transfer_cb.setName( "Transfer CB" ); + render_cb.setName( "Render CB" ); + composition_cb.setName( "Composition CB" ); + } +} // namespace fgl::engine diff --git a/src/engine/rendering/CommandBuffers.hpp b/src/engine/rendering/CommandBuffers.hpp new file mode 100644 index 0000000..6a64494 --- /dev/null +++ b/src/engine/rendering/CommandBuffers.hpp @@ -0,0 +1,24 @@ +// +// Created by kj16609 on 2/14/25. +// +#pragma once + +#include + +#include "CommandBufferPool.hpp" + +namespace fgl::engine +{ + struct CommandBuffers + { + CommandBuffer imgui_cb; + CommandBuffer transfer_cb; + CommandBuffer render_cb; + CommandBuffer composition_cb; + + CommandBuffers() = delete; + + CommandBuffers( std::vector< CommandBuffer >&& buffers ); + }; + +} // namespace fgl::engine diff --git a/src/engine/rendering/PresentSwapChain.cpp b/src/engine/rendering/PresentSwapChain.cpp index 012ac23..d59fca2 100644 --- a/src/engine/rendering/PresentSwapChain.cpp +++ b/src/engine/rendering/PresentSwapChain.cpp @@ -117,8 +117,7 @@ namespace fgl::engine return result; } - vk::Result PresentSwapChain:: - submitCommandBuffers( const vk::raii::CommandBuffer& buffers, const PresentIndex present_index ) + vk::Result PresentSwapChain::submitCommandBuffers( const CommandBuffer& buffers, const PresentIndex present_index ) { ZoneScoped; @@ -142,7 +141,7 @@ namespace fgl::engine m_submit_info.setWaitDstStageMask( wait_stages ); m_submit_info.commandBufferCount = 1; - m_submit_info.pCommandBuffers = &( *buffers ); + m_submit_info.pCommandBuffers = &( **buffers ); std::vector< vk::Semaphore > signaled_semaphores { m_render_finished_sem[ m_current_frame_index ] }; m_submit_info.setSignalSemaphores( signaled_semaphores ); @@ -171,14 +170,14 @@ namespace fgl::engine throw std::runtime_error( "failed to present swap chain image!" ); } - m_current_frame_index = static_cast< - FrameIndex >( ( m_current_frame_index + static_cast< FrameIndex >( 1 ) ) % MAX_FRAMES_IN_FLIGHT ); + m_current_frame_index = static_cast< FrameIndex >( + ( m_current_frame_index + static_cast< FrameIndex >( 1 ) ) % constants::MAX_FRAMES_IN_FLIGHT ); return vk::Result::eSuccess; } void PresentSwapChain:: - transitionImages( const vk::raii::CommandBuffer& command_buffer, StageID stage_id, FrameIndex frame_index ) + transitionImages( const CommandBuffer& command_buffer, const StageID stage_id, const FrameIndex frame_index ) { switch ( stage_id ) { @@ -196,7 +195,7 @@ namespace fgl::engine vk::ImageAspectFlagBits::eDepth ) }; - command_buffer.pipelineBarrier( + command_buffer->pipelineBarrier( vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eColorAttachmentOutput | vk::PipelineStageFlagBits::eEarlyFragmentTests @@ -216,7 +215,7 @@ namespace fgl::engine vk::ImageLayout::eColorAttachmentOptimal, vk::ImageLayout::ePresentSrcKHR ), }; - command_buffer.pipelineBarrier( + command_buffer->pipelineBarrier( vk::PipelineStageFlagBits::eColorAttachmentOutput, vk::PipelineStageFlagBits::eBottomOfPipe, vk::DependencyFlags( 0 ), @@ -315,7 +314,7 @@ namespace fgl::engine vk::FenceCreateInfo fenceInfo {}; fenceInfo.flags = vk::FenceCreateFlagBits::eSignaled; - for ( size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++ ) + for ( size_t i = 0; i < constants::MAX_FRAMES_IN_FLIGHT; i++ ) { auto& device { Device::getInstance() }; diff --git a/src/engine/rendering/PresentSwapChain.hpp b/src/engine/rendering/PresentSwapChain.hpp index 057a3a5..30dfed7 100644 --- a/src/engine/rendering/PresentSwapChain.hpp +++ b/src/engine/rendering/PresentSwapChain.hpp @@ -15,8 +15,6 @@ namespace fgl::engine { public: - static constexpr FrameIndex MAX_FRAMES_IN_FLIGHT { 2 }; - enum StageID { INITAL, @@ -105,12 +103,12 @@ namespace fgl::engine [[nodiscard]] std::pair< vk::Result, PresentIndex > acquireNextImage(); [[nodiscard]] vk::Result - submitCommandBuffers( const vk::raii::CommandBuffer& buffers, PresentIndex present_index ); + submitCommandBuffers( const CommandBuffer& buffers, PresentIndex present_index ); - void transitionImages( const vk::raii::CommandBuffer& command_buffer, StageID inital, FrameIndex frame_index ); + void transitionImages( const CommandBuffer& command_buffer, StageID stage_id, FrameIndex frame_index ); }; template < typename T > - using PerFrameArray = std::array< T, PresentSwapChain::MAX_FRAMES_IN_FLIGHT >; + using PerFrameArray = std::array< T, constants::MAX_FRAMES_IN_FLIGHT >; } // namespace fgl::engine diff --git a/src/engine/rendering/Renderer.cpp b/src/engine/rendering/Renderer.cpp index 3165e79..eb55206 100644 --- a/src/engine/rendering/Renderer.cpp +++ b/src/engine/rendering/Renderer.cpp @@ -122,11 +122,11 @@ namespace fgl::engine alloc_info.pNext = VK_NULL_HANDLE; alloc_info.commandPool = Device::getInstance().getCommandPool(); alloc_info.level = vk::CommandBufferLevel::ePrimary; - alloc_info.commandBufferCount = PresentSwapChain::MAX_FRAMES_IN_FLIGHT; + alloc_info.commandBufferCount = constants::MAX_FRAMES_IN_FLIGHT; - m_command_buffer = Device::getInstance().device().allocateCommandBuffers( alloc_info ); - - m_tracy_ctx = createContext( m_phy_device, Device::getInstance(), m_command_buffer[ 0 ] ); + //TODO: Restore tracy functionality, It's wanting a command buffer. + //TODO: Figure out if the command buffer it wants is just for setup or needs to be ran occasionally + // m_tracy_ctx = createContext( m_phy_device, Device::getInstance(), m_command_buffer[ 0 ] ); /* m_tracy_ctx = TracyVkContextCalibrated( @@ -139,8 +139,6 @@ namespace fgl::engine */ alloc_info.level = vk::CommandBufferLevel::eSecondary; - - m_gui_command_buffer = Device::getInstance()->allocateCommandBuffers( alloc_info ); } void Renderer::recreateSwapchain() @@ -169,7 +167,7 @@ namespace fgl::engine } } - vk::raii::CommandBuffer& Renderer::beginFrame() + std::optional< CommandBuffers > Renderer::beginFrame() { assert( !is_frame_started && "Cannot begin frame while frame is already in progress" ); auto [ result, present_index ] = m_swapchain->acquireNextImage(); @@ -184,28 +182,60 @@ namespace fgl::engine throw std::runtime_error( "Failed to acquire swap chain image" ); is_frame_started = true; - auto& command_buffer { getCurrentCommandbuffer() }; - vk::CommandBufferBeginInfo begin_info {}; - begin_info.pNext = VK_NULL_HANDLE; - //begin_info.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit; - begin_info.pInheritanceInfo = VK_NULL_HANDLE; + auto command_buffers { + Device::getInstance().getCmdBufferPool().getCommandBuffers( 4, CommandBufferHandle::Secondary ) + }; - command_buffer.begin( begin_info ); + vk::CommandBufferBeginInfo info {}; + info.pNext = VK_NULL_HANDLE; - return command_buffer; + vk::CommandBufferInheritanceInfo inheritance_info {}; + inheritance_info.framebuffer = VK_NULL_HANDLE; + inheritance_info.renderPass = VK_NULL_HANDLE; + inheritance_info.subpass = 0; + + info.pInheritanceInfo = &inheritance_info; + + for ( auto& command_buffer : command_buffers ) + { + command_buffer->begin( info ); + } + + CommandBuffers buffers { std::move( command_buffers ) }; + + return buffers; } - void Renderer::endFrame() + void Renderer::endFrame( CommandBuffers& buffers ) { ZoneScopedN( "Ending frame" ); assert( is_frame_started && "Cannot call end frame while frame is not in progress" ); - auto& command_buffer { getCurrentCommandbuffer() }; + // auto& command_buffer { getCurrentCommandbuffer() }; - command_buffer.end(); + // Get a primary command buffer + const auto primary_cmd { + Device::getInstance().getCmdBufferPool().getCommandBuffer( CommandBufferHandle::Primary ) + }; - const auto result { m_swapchain->submitCommandBuffers( command_buffer, current_present_index ) }; + vk::CommandBufferBeginInfo begin_info {}; + begin_info.pNext = VK_NULL_HANDLE; + begin_info.pInheritanceInfo = VK_NULL_HANDLE; + primary_cmd->begin( begin_info ); + + buffers.transfer_cb->end(); + buffers.render_cb->end(); + buffers.composition_cb->end(); + buffers.imgui_cb->end(); + + // run all secondary command buffers + primary_cmd->executeCommands( + { *buffers.transfer_cb, *buffers.render_cb, *buffers.composition_cb, *buffers.imgui_cb } ); + + primary_cmd->end(); + + const auto result { m_swapchain->submitCommandBuffers( primary_cmd, current_present_index ) }; if ( result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR || m_window.wasWindowResized() ) @@ -217,11 +247,10 @@ namespace fgl::engine throw std::runtime_error( "Failed to submit commmand buffer" ); is_frame_started = false; - current_frame_idx = - static_cast< std::uint16_t >( ( current_frame_idx + 1 ) % PresentSwapChain::MAX_FRAMES_IN_FLIGHT ); + current_frame_idx = static_cast< std::uint16_t >( ( current_frame_idx + 1 ) % constants::MAX_FRAMES_IN_FLIGHT ); } - void Renderer::setViewport( const vk::raii::CommandBuffer& buffer ) + void Renderer::setViewport( const CommandBuffer& buffer ) { vk::Viewport viewport {}; viewport.x = 0.0f; @@ -233,19 +262,19 @@ namespace fgl::engine const std::vector< vk::Viewport > viewports { viewport }; - buffer.setViewport( 0, viewports ); + buffer->setViewport( 0, viewports ); } - void Renderer::setScissor( const vk::raii::CommandBuffer& buffer ) + void Renderer::setScissor( const CommandBuffer& buffer ) { const vk::Rect2D scissor { { 0, 0 }, m_swapchain->getSwapChainExtent() }; const std::vector< vk::Rect2D > scissors { scissor }; - buffer.setScissor( 0, scissors ); + buffer->setScissor( 0, scissors ); } - void Renderer::beginSwapchainRendererPass( vk::raii::CommandBuffer& buffer ) + void Renderer::beginSwapchainRendererPass( CommandBuffer& buffer ) { assert( is_frame_started && "Cannot call beginSwapChainRenderPass if frame is not in progress" ); @@ -253,17 +282,17 @@ namespace fgl::engine m_swapchain->transitionImages( buffer, PresentSwapChain::INITAL, current_present_index ); - buffer.beginRendering( info ); + buffer->beginRendering( info ); setViewport( buffer ); setScissor( buffer ); } - void Renderer::endSwapchainRendererPass( vk::raii::CommandBuffer& buffer ) + void Renderer::endSwapchainRendererPass( CommandBuffer& buffer ) { assert( is_frame_started && "Cannot call endSwapChainRenderPass if frame is not in progress" ); - buffer.endRendering(); + buffer->endRendering(); m_swapchain->transitionImages( buffer, PresentSwapChain::FINAL, current_present_index ); } diff --git a/src/engine/rendering/Renderer.hpp b/src/engine/rendering/Renderer.hpp index 7cf6d9b..63c3e0a 100644 --- a/src/engine/rendering/Renderer.hpp +++ b/src/engine/rendering/Renderer.hpp @@ -4,18 +4,17 @@ #pragma once +// clang-format off #include +#include +// clang-format on #include #include +#include "CommandBuffers.hpp" #include "PresentSwapChain.hpp" -//clang-format: off -#include - -//clang-format: on - namespace fgl::engine { @@ -25,9 +24,6 @@ namespace fgl::engine PhysicalDevice& m_phy_device; std::unique_ptr< PresentSwapChain > m_swapchain; - std::vector< vk::raii::CommandBuffer > m_command_buffer {}; - std::vector< vk::raii::CommandBuffer > m_gui_command_buffer {}; - TracyVkCtx m_tracy_ctx { nullptr }; PresentIndex current_present_index { std::numeric_limits< PresentIndex >::max() }; @@ -53,26 +49,20 @@ namespace fgl::engine bool isFrameInProgress() const { return is_frame_started; } - vk::raii::CommandBuffer& getCurrentCommandbuffer() - { - assert( is_frame_started && "Cannot get command buffer while frame not in progress" ); - return m_command_buffer[ current_frame_idx ]; - } - - vk::raii::CommandBuffer& getCurrentGuiCommandBuffer() { return m_gui_command_buffer[ current_frame_idx ]; } - TracyVkCtx getCurrentTracyCTX() const { return m_tracy_ctx; } float getAspectRatio() const { return m_swapchain->extentAspectRatio(); } - vk::raii::CommandBuffer& beginFrame(); - void endFrame(); + // vk::raii::CommandBuffer& beginFrame(); + std::optional< CommandBuffers > beginFrame(); - void setViewport( const vk::raii::CommandBuffer& buffer ); - void setScissor( const vk::raii::CommandBuffer& buffer ); + void endFrame( CommandBuffers& buffers ); - void beginSwapchainRendererPass( vk::raii::CommandBuffer& buffer ); - void endSwapchainRendererPass( vk::raii::CommandBuffer& buffer ); + void setViewport( const CommandBuffer& buffer ); + void setScissor( const CommandBuffer& buffer ); + + void beginSwapchainRendererPass( CommandBuffer& buffer ); + void endSwapchainRendererPass( CommandBuffer& buffer ); PresentSwapChain& getSwapChain() { return *m_swapchain; } diff --git a/src/engine/rendering/devices/Device.cpp b/src/engine/rendering/devices/Device.cpp index f007c9e..9a02206 100644 --- a/src/engine/rendering/devices/Device.cpp +++ b/src/engine/rendering/devices/Device.cpp @@ -167,6 +167,7 @@ namespace fgl::engine m_physical_device( m_instance, m_surface_khr ), device_creation_info( m_physical_device ), m_device( m_physical_device, device_creation_info.m_create_info ), + m_command_pool( createGraphicsPool( m_device, m_physical_device ) ), m_commandPool( m_device.createCommandPool( commandPoolInfo() ) ), m_graphics_queue( m_device .getQueue( m_physical_device.queueInfo().getIndex( vk::QueueFlagBits::eGraphics ), 0 ) ), diff --git a/src/engine/rendering/devices/Device.hpp b/src/engine/rendering/devices/Device.hpp index 01157de..aa17bb6 100644 --- a/src/engine/rendering/devices/Device.hpp +++ b/src/engine/rendering/devices/Device.hpp @@ -10,6 +10,7 @@ #include "engine/rendering/Instance.hpp" #include "engine/rendering/Surface.hpp" #include "extensions.hpp" +#include "rendering/CommandBufferPool.hpp" #include "vma/vma_impl.hpp" namespace fgl::engine @@ -89,6 +90,8 @@ namespace fgl::engine vk::raii::Device m_device; + CommandBufferPool m_command_pool; + vk::raii::CommandPool m_commandPool; vk::raii::Queue m_graphics_queue; @@ -101,6 +104,7 @@ namespace fgl::engine vk::PhysicalDeviceProperties m_properties; vk::CommandPoolCreateInfo commandPoolInfo(); + CommandBufferPool& getCmdBufferPool() { return m_command_pool; } Device( Window&, Instance& ); ~Device(); diff --git a/src/engine/rendering/pipelines/v2/Pipeline.cpp b/src/engine/rendering/pipelines/v2/Pipeline.cpp index 6cdfe83..4233c32 100644 --- a/src/engine/rendering/pipelines/v2/Pipeline.cpp +++ b/src/engine/rendering/pipelines/v2/Pipeline.cpp @@ -26,7 +26,7 @@ namespace fgl::engine m_builder_state( std::forward< std::unique_ptr< PipelineBuilder::BuilderState > >( builder_state ) ) {} - void Pipeline::bind( vk::raii::CommandBuffer& cmd_buffer ) + void Pipeline::bind( CommandBuffer& cmd_buffer ) { if ( flags::shouldReloadShaders() ) { @@ -40,21 +40,21 @@ namespace fgl::engine } } - cmd_buffer.bindPipeline( vk::PipelineBindPoint::eGraphics, m_pipeline ); + cmd_buffer->bindPipeline( vk::PipelineBindPoint::eGraphics, m_pipeline ); } void Pipeline::bindDescriptor( - vk::raii::CommandBuffer& command_buffer, + CommandBuffer& command_buffer, const descriptors::DescriptorIDX descriptor_idx, descriptors::DescriptorSet& set ) { const std::vector< vk::DescriptorSet > sets { *set }; constexpr std::vector< std::uint32_t > offsets {}; - command_buffer.bindDescriptorSets( vk::PipelineBindPoint::eGraphics, m_layout, descriptor_idx, sets, offsets ); + command_buffer->bindDescriptorSets( vk::PipelineBindPoint::eGraphics, m_layout, descriptor_idx, sets, offsets ); } - void Pipeline::bindDescriptor( vk::raii::CommandBuffer& comd_buffer, descriptors::DescriptorSet& set ) + void Pipeline::bindDescriptor( CommandBuffer& comd_buffer, descriptors::DescriptorSet& set ) { bindDescriptor( comd_buffer, set.setIDX(), set ); } diff --git a/src/engine/rendering/pipelines/v2/Pipeline.hpp b/src/engine/rendering/pipelines/v2/Pipeline.hpp index bfbb266..5bc51a4 100644 --- a/src/engine/rendering/pipelines/v2/Pipeline.hpp +++ b/src/engine/rendering/pipelines/v2/Pipeline.hpp @@ -31,19 +31,19 @@ namespace fgl::engine vk::raii::PipelineLayout&& layout, std::unique_ptr< PipelineBuilder::BuilderState >&& builder_state ); - void bind( vk::raii::CommandBuffer& ); + void bind( CommandBuffer& cmd_buffer ); void bindDescriptor( - vk::raii::CommandBuffer&, descriptors::DescriptorIDX descriptor_idx, descriptors::DescriptorSet& set ); - void bindDescriptor( vk::raii::CommandBuffer& comd_buffer, descriptors::DescriptorSet& set ); + CommandBuffer&, descriptors::DescriptorIDX descriptor_idx, descriptors::DescriptorSet& set ); + void bindDescriptor( CommandBuffer& comd_buffer, descriptors::DescriptorSet& set ); void setDebugName( const char* str ); template < typename T > requires std::is_trivially_copyable_v< T > - void pushConstant( vk::raii::CommandBuffer& command_buffer, vk::ShaderStageFlags stage, const T& t ) + void pushConstant( CommandBuffer& command_buffer, vk::ShaderStageFlags stage, const T& t ) { - command_buffer.pushConstants< T >( m_layout, stage, 0, { t } ); + command_buffer->pushConstants< T >( m_layout, stage, 0, { t } ); } }; diff --git a/src/engine/systems/composition/GuiSystem.cpp b/src/engine/systems/composition/GuiSystem.cpp index c0b7ab4..1912871 100644 --- a/src/engine/systems/composition/GuiSystem.cpp +++ b/src/engine/systems/composition/GuiSystem.cpp @@ -5,7 +5,6 @@ #include "GuiSystem.hpp" #include "engine/FrameInfo.hpp" -#include "engine/assets/model/SimpleVertex.hpp" #include "engine/rendering/pipelines/v2/AttachmentBuilder.hpp" #include "engine/rendering/pipelines/v2/Pipeline.hpp" #include "engine/rendering/pipelines/v2/PipelineBuilder.hpp" @@ -22,8 +21,10 @@ namespace fgl::engine builder.addDescriptorSet( gui_descriptor_set ); - builder.setAttributeDescriptions( SimpleVertex::getAttributeDescriptions() ); - builder.setBindingDescriptions( SimpleVertex::getBindingDescriptions() ); + // VUID-vkCmdDraw-None-04008: States that vertex binding 0 is null handle, and must be bound. + // Not entirely sure why we had added vertex bindings to this in the first place? + // builder.setAttributeDescriptions( SimpleVertex::getAttributeDescriptions() ); + // builder.setBindingDescriptions( SimpleVertex::getBindingDescriptions() ); builder.setVertexShader( Shader::loadVertex( "shaders/gui-compose.slang" ) ); builder.setFragmentShader( Shader::loadFragment( "shaders/gui-compose.slang" ) ); @@ -34,9 +35,9 @@ namespace fgl::engine m_pipeline->setDebugName( "Gui Pipeline" ); } - vk::raii::CommandBuffer& GuiSystem::setupSystem( FrameInfo& info ) + CommandBuffer& GuiSystem::setupSystem( FrameInfo& info ) { - auto& command_buffer { info.command_buffer }; + auto& command_buffer { info.command_buffer.imgui_cb }; m_pipeline->bind( command_buffer ); @@ -50,7 +51,7 @@ namespace fgl::engine ZoneScopedN( "GuiSystem::pass" ); auto& command_buffer { setupSystem( info ) }; - command_buffer.draw( 3, 1, 0, 0 ); + command_buffer->draw( 3, 1, 0, 0 ); } } // namespace fgl::engine diff --git a/src/engine/systems/composition/GuiSystem.hpp b/src/engine/systems/composition/GuiSystem.hpp index 2a32f80..83160c7 100644 --- a/src/engine/systems/composition/GuiSystem.hpp +++ b/src/engine/systems/composition/GuiSystem.hpp @@ -20,7 +20,7 @@ namespace fgl::engine std::unique_ptr< Pipeline > m_pipeline {}; //Setup isn't needed for this. So we can just never define this safely. - [[maybe_unused]] vk::raii::CommandBuffer& setupSystem( FrameInfo& info ); + [[maybe_unused]] CommandBuffer& setupSystem( FrameInfo& info ); public: diff --git a/src/engine/systems/render/EntityRendererSystem.cpp b/src/engine/systems/render/EntityRendererSystem.cpp index 7e1c94a..1ffe240 100644 --- a/src/engine/systems/render/EntityRendererSystem.cpp +++ b/src/engine/systems/render/EntityRendererSystem.cpp @@ -18,7 +18,7 @@ namespace fgl::engine { - EntityRendererSystem::EntityRendererSystem( ) + EntityRendererSystem::EntityRendererSystem() { ZoneScoped; @@ -71,9 +71,9 @@ namespace fgl::engine EntityRendererSystem::~EntityRendererSystem() {} - vk::raii::CommandBuffer& EntityRendererSystem::setupSystem( const FrameInfo& info ) + CommandBuffer& EntityRendererSystem::setupSystem( const FrameInfo& info ) { - auto& command_buffer { info.command_buffer }; + auto& command_buffer { info.command_buffer.render_cb }; //This function becomes a dummy since we have multiple pipelines. //We will instead bind the pipeline and descriptors for each stage of this pass. @@ -144,7 +144,7 @@ namespace fgl::engine void EntityRendererSystem::texturedPass( const FrameInfo& info ) { ZoneScopedN( "Textured pass" ); - auto& command_buffer { info.command_buffer }; + auto& command_buffer { info.command_buffer.render_cb }; TracyVkZone( info.tracy_ctx, *command_buffer, "Render textured entities" ); auto [ draw_commands, model_matricies ] = @@ -172,10 +172,10 @@ namespace fgl::engine const std::vector< vk::Buffer > vert_buffers { info.model_vertex_buffer.getVkBuffer(), model_matrix_info_buffer->getVkBuffer() }; - command_buffer.bindVertexBuffers( 0, vert_buffers, { 0, model_matrix_info_buffer->getOffset() } ); - command_buffer.bindIndexBuffer( info.model_index_buffer.getVkBuffer(), 0, vk::IndexType::eUint32 ); + command_buffer->bindVertexBuffers( 0, vert_buffers, { 0, model_matrix_info_buffer->getOffset() } ); + command_buffer->bindIndexBuffer( info.model_index_buffer.getVkBuffer(), 0, vk::IndexType::eUint32 ); - command_buffer.drawIndexedIndirect( + command_buffer->drawIndexedIndirect( draw_parameter_buffer->getVkBuffer(), draw_parameter_buffer->getOffset(), draw_parameter_buffer->size(), diff --git a/src/engine/systems/render/EntityRendererSystem.hpp b/src/engine/systems/render/EntityRendererSystem.hpp index 7eb66c0..f05bfd1 100644 --- a/src/engine/systems/render/EntityRendererSystem.hpp +++ b/src/engine/systems/render/EntityRendererSystem.hpp @@ -42,7 +42,7 @@ namespace fgl::engine PerFrameArray< std::unique_ptr< DrawParameterBufferSuballocation > > m_draw_textured_parameter_buffers {}; PerFrameArray< std::unique_ptr< ModelMatrixInfoBufferSuballocation > > m_textured_model_matrix_info_buffers {}; - vk::raii::CommandBuffer& setupSystem( const FrameInfo& ); + CommandBuffer& setupSystem( const FrameInfo& ); public: diff --git a/src/engine/systems/render/LineDrawer.cpp b/src/engine/systems/render/LineDrawer.cpp index 1d36723..22a1e54 100644 --- a/src/engine/systems/render/LineDrawer.cpp +++ b/src/engine/systems/render/LineDrawer.cpp @@ -24,7 +24,7 @@ namespace fgl::engine inline static std::vector< VertexLine > m_lines {}; - LineDrawer::LineDrawer( ) + LineDrawer::LineDrawer() { PipelineBuilder builder { 0 }; @@ -48,9 +48,9 @@ namespace fgl::engine LineDrawer::~LineDrawer() {} - vk::raii::CommandBuffer& LineDrawer::setupSystem( FrameInfo& info ) + CommandBuffer& LineDrawer::setupSystem( FrameInfo& info ) { - auto& command_buffer { info.command_buffer }; + auto& command_buffer { info.command_buffer.render_cb }; m_pipeline->bind( command_buffer ); m_pipeline->bindDescriptor( command_buffer, info.getCameraDescriptor() ); @@ -72,11 +72,11 @@ namespace fgl::engine line_vertex_buffer = std::make_unique< HostVector< VertexLine > >( info.model_matrix_info_buffer, m_lines ); - command_buffer.bindVertexBuffers( 0, line_vertex_buffer->getVkBuffer(), { line_vertex_buffer->getOffset() } ); + command_buffer->bindVertexBuffers( 0, line_vertex_buffer->getVkBuffer(), { line_vertex_buffer->getOffset() } ); - command_buffer.setLineWidth( 5.0f ); + command_buffer->setLineWidth( 5.0f ); - command_buffer.draw( + command_buffer->draw( static_cast< std::uint32_t >( m_lines.size() * 2 ), static_cast< std::uint32_t >( m_lines.size() ), 0, 0 ); m_lines.clear(); diff --git a/src/engine/systems/render/LineDrawer.hpp b/src/engine/systems/render/LineDrawer.hpp index 7c62c12..8da5128 100644 --- a/src/engine/systems/render/LineDrawer.hpp +++ b/src/engine/systems/render/LineDrawer.hpp @@ -25,7 +25,7 @@ namespace fgl::engine FGL_DELETE_COPY( LineDrawer ); FGL_DELETE_MOVE( LineDrawer ); - vk::raii::CommandBuffer& setupSystem( FrameInfo& info ); + CommandBuffer& setupSystem( FrameInfo& info ); void pass( FrameInfo& info ); LineDrawer();