Setup command pools for primary and secondary command buffers, Split recording into multiple secondary buffers

This commit is contained in:
2025-02-14 17:20:57 -05:00
parent 129524f8ca
commit bc326e2c79
37 changed files with 615 additions and 162 deletions

View File

@@ -117,13 +117,22 @@ namespace fgl::editor
gui::drawStats( info ); gui::drawStats( info );
} }
void EditorGuiContext::endDraw( vk::raii::CommandBuffer& command_buffer ) void EditorGuiContext::endDraw( CommandBuffer& command_buffer )
{ {
ZoneScoped; ZoneScoped;
ImGui::Render(); 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() }; ImDrawData* data { ImGui::GetDrawData() };
ImGui_ImplVulkan_RenderDrawData( data, *command_buffer ); ImGui_ImplVulkan_RenderDrawData( data, **command_buffer );
command_buffer->endDebugUtilsLabelEXT();
//ImGui::UpdatePlatformWindows(); //ImGui::UpdatePlatformWindows();
//ImGui::RenderPlatformWindowsDefault(); //ImGui::RenderPlatformWindowsDefault();
@@ -131,6 +140,6 @@ namespace fgl::editor
void EditorGuiContext::endDraw( FrameInfo& info ) void EditorGuiContext::endDraw( FrameInfo& info )
{ {
return endDraw( info.command_buffer ); return endDraw( info.command_buffer.imgui_cb );
} }
} // namespace fgl::editor } // namespace fgl::editor

View File

@@ -17,7 +17,7 @@ namespace fgl::editor
void beginDraw(); void beginDraw();
void draw( engine::FrameInfo& info ); void draw( engine::FrameInfo& info );
void endDraw( vk::raii::CommandBuffer& command_buffer ); void endDraw( engine::CommandBuffer& command_buffer );
void endDraw( engine::FrameInfo& info ); void endDraw( engine::FrameInfo& info );
}; };
} // namespace fgl::editor } // namespace fgl::editor

View File

@@ -145,16 +145,18 @@ namespace fgl::engine
void EngineContext::renderFrame() void EngineContext::renderFrame()
{ {
ZoneScoped; 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 auto timer = debug::timing::push( "Render Frame" );
const FrameIndex frame_index { m_renderer.getFrameIndex() }; const FrameIndex frame_index { m_renderer.getFrameIndex() };
const PresentIndex present_idx { m_renderer.getPresentIndex() }; const PresentIndex present_idx { m_renderer.getPresentIndex() };
auto& command_buffers { command_buffers_o.value() };
FrameInfo frame_info { frame_index, FrameInfo frame_info { frame_index,
present_idx, present_idx,
m_delta_time, m_delta_time,
command_buffer, command_buffers,
nullptr, // Camera nullptr, // Camera
m_camera_manager.getCameras(), m_camera_manager.getCameras(),
// global_descriptor_sets[ frame_index ], // global_descriptor_sets[ frame_index ],
@@ -172,25 +174,25 @@ namespace fgl::engine
for ( const auto& hook : m_pre_frame_hooks ) hook( frame_info ); 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. //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 ); 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. //TODO: Add some way of 'activating' cameras. We don't need to render cameras that aren't active.
renderCameras( frame_info ); renderCameras( frame_info );
for ( const auto& hook : m_render_hooks ) hook( 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 ); m_gui_system.pass( frame_info );
for ( const auto& hook : m_late_render_hooks ) hook( 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(); m_transfer_manager.dump();

View File

@@ -12,6 +12,7 @@
#include "descriptors/Descriptor.hpp" #include "descriptors/Descriptor.hpp"
#include "descriptors/DescriptorSetLayout.hpp" #include "descriptors/DescriptorSetLayout.hpp"
#include "primitives/Frustum.hpp" #include "primitives/Frustum.hpp"
#include "rendering/CommandBuffers.hpp"
#include "rendering/types.hpp" #include "rendering/types.hpp"
#define MAX_LIGHTS 10 #define MAX_LIGHTS 10
@@ -75,7 +76,7 @@ namespace fgl::engine
PresentIndex present_idx; PresentIndex present_idx;
double delta_time; double delta_time;
vk::raii::CommandBuffer& command_buffer; CommandBuffers& command_buffer;
Camera* camera { nullptr }; Camera* camera { nullptr };

View File

@@ -54,6 +54,11 @@ namespace fgl::engine::memory
const std::vector< vk::BufferMemoryBarrier > from_memory_barriers { createFromGraphicsBarriers() }; 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 // Acquire the buffer from the queue family
command_buffer.pipelineBarrier( command_buffer.pipelineBarrier(
vk::PipelineStageFlagBits::eBottomOfPipe, vk::PipelineStageFlagBits::eBottomOfPipe,
@@ -66,7 +71,7 @@ namespace fgl::engine::memory
//Record all the buffer copies //Record all the buffer copies
for ( auto& [ key, regions ] : m_copy_regions ) for ( auto& [ key, regions ] : m_copy_regions )
{ {
auto& [ source, target ] = key; const auto& [ source, target ] = key;
command_buffer.copyBuffer( source, target, regions ); command_buffer.copyBuffer( source, target, regions );
} }
@@ -81,6 +86,8 @@ namespace fgl::engine::memory
{}, {},
to_buffer_memory_barriers, to_buffer_memory_barriers,
{} ); {} );
command_buffer.endDebugUtilsLabelEXT();
} }
void TransferManager::resizeBuffer( const std::uint64_t size ) void TransferManager::resizeBuffer( const std::uint64_t size )
@@ -218,21 +225,21 @@ namespace fgl::engine::memory
inline static TransferManager* GLOBAL_TRANSFER_MANAGER {}; 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() }; std::vector< vk::BufferMemoryBarrier > barriers { createToTransferBarriers() };
command_buffer.pipelineBarrier( command_buffer->pipelineBarrier(
vk::PipelineStageFlagBits::eNone, vk::PipelineStageFlagBits::eTransfer, {}, {}, barriers, {} ); vk::PipelineStageFlagBits::eNone, vk::PipelineStageFlagBits::eTransfer, {}, {}, barriers, {} );
} }
void TransferManager::recordOwnershipTransferDst( vk::raii::CommandBuffer& command_buffer ) void TransferManager::recordOwnershipTransferDst( CommandBuffer& command_buffer )
{ {
ZoneScoped; ZoneScoped;
std::vector< vk::BufferMemoryBarrier > barriers { createToGraphicsBarriers() }; std::vector< vk::BufferMemoryBarrier > barriers { createToGraphicsBarriers() };
command_buffer.pipelineBarrier( command_buffer->pipelineBarrier(
vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eTransfer,
vk::PipelineStageFlagBits::eVertexInput | vk::PipelineStageFlagBits::eVertexShader, vk::PipelineStageFlagBits::eVertexInput | vk::PipelineStageFlagBits::eVertexShader,
{}, {},

View File

@@ -84,10 +84,10 @@ namespace fgl::engine::memory
vk::raii::Semaphore& getFinishedSem() { return m_transfer_semaphore; } vk::raii::Semaphore& getFinishedSem() { return m_transfer_semaphore; }
//! Takes ownership of memory regions from the graphics queue via memory barriers. //! 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 //! Records the barriers required for transfering queue ownership
void recordOwnershipTransferDst( vk::raii::CommandBuffer& command_buffer ); void recordOwnershipTransferDst( CommandBuffer& command_buffer );
//! Drops the processed items //! Drops the processed items
void dump(); void dump();

View File

@@ -133,6 +133,8 @@ namespace fgl::engine
{ {
this->setPerspectiveProjection( m_fov_y, aspectRatio(), constants::NEAR_PLANE, constants::FAR_PLANE ); 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_composite_swapchain = std::move( m_composite_swapchain );
m_old_gbuffer_swapchain = std::move( m_gbuffer_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_composite_swapchain( std::make_unique< CompositeSwapchain >( m_target_extent ) ),
m_gbuffer_swapchain( std::make_unique< GBufferSwapchain >( m_target_extent ) ), m_gbuffer_swapchain( std::make_unique< GBufferSwapchain >( m_target_extent ) ),
m_camera_renderer( renderer ), 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" ); FGL_ASSERT( renderer, "Camera renderer is null" );
this->setPerspectiveProjection( m_fov_y, aspectRatio(), constants::NEAR_PLANE, constants::FAR_PLANE ); this->setPerspectiveProjection( m_fov_y, aspectRatio(), constants::NEAR_PLANE, constants::FAR_PLANE );
this->setView( WorldCoordinate( constants::CENTER ), Rotation( 0.0f, 0.0f, 0.0f ) ); 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() }; auto set { camera_descriptor_set.create() };
set->bindUniformBuffer( 0, m_camera_frame_info[ i ] ); set->bindUniformBuffer( 0, m_camera_frame_info[ i ] );

View File

@@ -10,8 +10,7 @@ namespace fgl::engine
{ {
class Texture; class Texture;
void CompositeSwapchain:: void CompositeSwapchain::transitionImages( CommandBuffer& command_buffer, StageID stage_id, FrameIndex index )
transitionImages( vk::raii::CommandBuffer& command_buffer, StageID stage_id, FrameIndex index )
{ {
switch ( stage_id ) switch ( stage_id )
{ {
@@ -24,7 +23,7 @@ namespace fgl::engine
.transitionColorTo( vk::ImageLayout::eUndefined, vk::ImageLayout::eColorAttachmentOptimal ), .transitionColorTo( vk::ImageLayout::eUndefined, vk::ImageLayout::eColorAttachmentOptimal ),
}; };
command_buffer.pipelineBarrier( command_buffer->pipelineBarrier(
vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTopOfPipe,
vk::PipelineStageFlagBits::eColorAttachmentOutput, vk::PipelineStageFlagBits::eColorAttachmentOutput,
vk::DependencyFlags( 0 ), vk::DependencyFlags( 0 ),
@@ -41,7 +40,7 @@ namespace fgl::engine
vk::ImageLayout::eColorAttachmentOptimal, vk::ImageLayout::eShaderReadOnlyOptimal ), vk::ImageLayout::eColorAttachmentOptimal, vk::ImageLayout::eShaderReadOnlyOptimal ),
}; };
command_buffer.pipelineBarrier( command_buffer->pipelineBarrier(
vk::PipelineStageFlagBits::eColorAttachmentOutput, vk::PipelineStageFlagBits::eColorAttachmentOutput,
vk::PipelineStageFlagBits::eFragmentShader, vk::PipelineStageFlagBits::eFragmentShader,
vk::DependencyFlags( 0 ), vk::DependencyFlags( 0 ),
@@ -58,7 +57,7 @@ namespace fgl::engine
vk::ImageLayout::eColorAttachmentOptimal, vk::ImageLayout::ePresentSrcKHR ), vk::ImageLayout::eColorAttachmentOptimal, vk::ImageLayout::ePresentSrcKHR ),
}; };
command_buffer.pipelineBarrier( command_buffer->pipelineBarrier(
vk::PipelineStageFlagBits::eColorAttachmentOutput, vk::PipelineStageFlagBits::eColorAttachmentOutput,
vk::PipelineStageFlagBits::eBottomOfPipe, vk::PipelineStageFlagBits::eBottomOfPipe,
vk::DependencyFlags( 0 ), vk::DependencyFlags( 0 ),
@@ -94,7 +93,7 @@ namespace fgl::engine
CompositeSwapchain::CompositeSwapchain( vk::Extent2D extent ) : m_extent( extent ) 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.createResources( image_count, m_extent, vk::ImageUsageFlagBits::eTransferSrc );
m_buffer.m_target.setName( "CompositeSwapchain::m_target" ); m_buffer.m_target.setName( "CompositeSwapchain::m_target" );

View File

@@ -7,6 +7,7 @@
#include "FGL_DEFINES.hpp" #include "FGL_DEFINES.hpp"
#include "engine/rendering/RenderingFormats.hpp" #include "engine/rendering/RenderingFormats.hpp"
#include "engine/rendering/pipelines/Attachment.hpp" #include "engine/rendering/pipelines/Attachment.hpp"
#include "rendering/CommandBufferPool.hpp"
namespace fgl::engine namespace fgl::engine
{ {
@@ -35,7 +36,7 @@ namespace fgl::engine
FINAL_PRESENT, 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 ); vk::RenderingInfo getRenderingInfo( FrameIndex index );

View File

@@ -36,20 +36,19 @@ namespace fgl::engine
command_buffer.setScissor( 0, scissors ); command_buffer.setScissor( 0, scissors );
} }
void GBufferCompositor:: void GBufferCompositor::beginPass( CommandBuffer& cmd, CompositeSwapchain& swapchain, const FrameIndex& index )
beginPass( vk::raii::CommandBuffer& cmd, CompositeSwapchain& swapchain, const FrameIndex& index )
{ {
const vk::RenderingInfo info { swapchain.getRenderingInfo( index ) }; const vk::RenderingInfo info { swapchain.getRenderingInfo( index ) };
cmd.beginRendering( info ); cmd->beginRendering( info );
setViewport( cmd, swapchain.getExtent() ); setViewport( *cmd, swapchain.getExtent() );
setScissor( 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 ) GBufferCompositor::GBufferCompositor( const CompositeFlags flags ) : m_flags( flags )
@@ -74,8 +73,7 @@ namespace fgl::engine
m_pipeline->setDebugName( "Composition pipeline" ); m_pipeline->setDebugName( "Composition pipeline" );
} }
void GBufferCompositor:: void GBufferCompositor::composite( CommandBuffer& command_buffer, Camera& camera, const FrameIndex frame_index )
composite( vk::raii::CommandBuffer& command_buffer, Camera& camera, const FrameIndex frame_index )
{ {
auto& gbuffer_swapchain { camera.getSwapchain() }; auto& gbuffer_swapchain { camera.getSwapchain() };
auto& composite_swapchain { camera.getCompositeSwapchain() }; auto& composite_swapchain { camera.getCompositeSwapchain() };
@@ -91,7 +89,7 @@ namespace fgl::engine
m_pipeline->pushConstant( command_buffer, vk::ShaderStageFlagBits::eFragment, m_control ); 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 ); endPass( command_buffer );

View File

@@ -39,8 +39,8 @@ namespace fgl::engine
void setViewport( const vk::raii::CommandBuffer& cmd, vk::Extent2D extent_2d ); void setViewport( const vk::raii::CommandBuffer& cmd, vk::Extent2D extent_2d );
void setScissor( 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 beginPass( CommandBuffer& cmd, CompositeSwapchain& swapchain, const FrameIndex& index );
void endPass( vk::raii::CommandBuffer& cmd ); void endPass( CommandBuffer& cmd );
CompositionControl m_control {}; CompositionControl m_control {};
@@ -48,7 +48,7 @@ namespace fgl::engine
GBufferCompositor( CompositeFlags flags = CompositeFlagBits_Standard ); 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; } inline void switchMode( const CompositeFlags flags ) { m_flags = flags; }
}; };

View File

@@ -5,13 +5,14 @@
#include "GBufferRenderer.hpp" #include "GBufferRenderer.hpp"
#include "Camera.hpp" #include "Camera.hpp"
#include "GBufferSwapchain.hpp"
#include "engine/rendering/renderpass/RenderPass.hpp" #include "engine/rendering/renderpass/RenderPass.hpp"
namespace fgl::engine namespace fgl::engine
{ {
class GBufferSwapchain; 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 {}; vk::Viewport viewport {};
viewport.x = 0.0f; viewport.x = 0.0f;
@@ -24,32 +25,32 @@ namespace fgl::engine
const std::vector< vk::Viewport > viewports { viewport }; 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 vk::Rect2D scissor { { 0, 0 }, extent };
const std::vector< vk::Rect2D > scissors { scissor }; const std::vector< vk::Rect2D > scissors { scissor };
command_buffer.setScissor( 0, scissors ); command_buffer->setScissor( 0, scissors );
} }
void GBufferRenderer::beginRenderPass( void GBufferRenderer::
const vk::raii::CommandBuffer& command_buffer, GBufferSwapchain& swapchain, const FrameIndex index ) beginRenderPass( const CommandBuffer& command_buffer, GBufferSwapchain& swapchain, const FrameIndex index )
{ {
const vk::RenderingInfo info { swapchain.getRenderingInfo( index ) }; const vk::RenderingInfo info { swapchain.getRenderingInfo( index ) };
command_buffer.beginRendering( info ); command_buffer->beginRendering( info );
setViewport( command_buffer, swapchain.getExtent() ); setViewport( command_buffer, swapchain.getExtent() );
setScissor( 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 ) void GBufferRenderer::pass( FrameInfo& frame_info, GBufferSwapchain& camera_swapchain )
@@ -57,7 +58,7 @@ namespace fgl::engine
ZoneScopedN( "CameraRenderer::pass" ); ZoneScopedN( "CameraRenderer::pass" );
m_culling_system.startPass( frame_info ); 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 ); camera_swapchain.transitionImages( command_buffer, GBufferSwapchain::INITAL, frame_info.frame_idx );

View File

@@ -5,7 +5,6 @@
#pragma once #pragma once
#include "GBufferCompositor.hpp" #include "GBufferCompositor.hpp"
#include "GBufferSwapchain.hpp"
#include "engine/systems/prerender/CullingSystem.hpp" #include "engine/systems/prerender/CullingSystem.hpp"
#include "engine/systems/render/EntityRendererSystem.hpp" #include "engine/systems/render/EntityRendererSystem.hpp"
#include "engine/systems/render/LineDrawer.hpp" #include "engine/systems/render/LineDrawer.hpp"
@@ -17,8 +16,8 @@ namespace fgl::engine
{ {
GBufferCompositor m_compositor; GBufferCompositor m_compositor;
void setViewport( const vk::raii::CommandBuffer& command_buffer, vk::Extent2D extent ); void setViewport( const CommandBuffer& command_buffer, vk::Extent2D extent );
void setScissor( const vk::raii::CommandBuffer& command_buffer, vk::Extent2D extent ); void setScissor( const CommandBuffer& command_buffer, vk::Extent2D extent );
CullingSystem m_culling_system {}; CullingSystem m_culling_system {};
@@ -30,10 +29,9 @@ namespace fgl::engine
// SubPass 1 // SubPass 1
// CompositionSystem m_composition_system {}; // CompositionSystem m_composition_system {};
void beginRenderPass( void beginRenderPass( const CommandBuffer& command_buffer, GBufferSwapchain& swapchain, FrameIndex index );
const vk::raii::CommandBuffer& command_buffer, GBufferSwapchain& swapchain, FrameIndex index );
void endRenderPass( const vk::raii::CommandBuffer& command_buffer ); void endRenderPass( const CommandBuffer& command_buffer );
public: public:

View File

@@ -12,9 +12,9 @@ namespace fgl::engine
std::vector< std::unique_ptr< descriptors::DescriptorSet > > GBufferSwapchain::createGBufferDescriptors() std::vector< std::unique_ptr< descriptors::DescriptorSet > > GBufferSwapchain::createGBufferDescriptors()
{ {
std::vector< std::unique_ptr< descriptors::DescriptorSet > > data {}; 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 { std::make_unique< descriptors::DescriptorSet >( GBufferDescriptorSet::createLayout() ) };
auto set { gbuffer_set.create() }; auto set { gbuffer_set.create() };
@@ -37,8 +37,8 @@ namespace fgl::engine
return data; return data;
} }
void GBufferSwapchain::transitionImages( void GBufferSwapchain::
vk::raii::CommandBuffer& command_buffer, const std::uint16_t stage_id, const FrameIndex index ) transitionImages( CommandBuffer& command_buffer, const std::uint16_t stage_id, const FrameIndex index )
{ {
switch ( stage_id ) switch ( stage_id )
{ {
@@ -63,7 +63,7 @@ namespace fgl::engine
vk::ImageAspectFlagBits::eDepth ), vk::ImageAspectFlagBits::eDepth ),
}; };
command_buffer.pipelineBarrier( command_buffer->pipelineBarrier(
vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTopOfPipe,
vk::PipelineStageFlagBits::eColorAttachmentOutput vk::PipelineStageFlagBits::eColorAttachmentOutput
| vk::PipelineStageFlagBits::eEarlyFragmentTests | vk::PipelineStageFlagBits::eEarlyFragmentTests
@@ -96,7 +96,7 @@ namespace fgl::engine
// vk::ImageAspectFlagBits::eDepth ), // vk::ImageAspectFlagBits::eDepth ),
}; };
command_buffer.pipelineBarrier( command_buffer->pipelineBarrier(
vk::PipelineStageFlagBits::eColorAttachmentOutput, vk::PipelineStageFlagBits::eColorAttachmentOutput,
vk::PipelineStageFlagBits::eFragmentShader, vk::PipelineStageFlagBits::eFragmentShader,
vk::DependencyFlags( 0 ), vk::DependencyFlags( 0 ),
@@ -157,7 +157,7 @@ namespace fgl::engine
GBufferSwapchain::GBufferSwapchain( const vk::Extent2D extent ) : m_extent( extent ) GBufferSwapchain::GBufferSwapchain( const vk::Extent2D extent ) : m_extent( extent )
// m_gbuffer_descriptor_set( createGBufferDescriptors() ) // 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_color.createResources( image_count, m_extent );
m_gbuffer.m_position.createResources( image_count, m_extent ); m_gbuffer.m_position.createResources( image_count, m_extent );

View File

@@ -53,7 +53,7 @@ namespace fgl::engine
FINAL 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 ); vk::RenderingInfo getRenderingInfo( const FrameIndex frame_index );
GBufferSwapchain( vk::Extent2D extent ); GBufferSwapchain( vk::Extent2D extent );

View File

@@ -49,4 +49,6 @@ namespace fgl::engine::constants
constexpr TextureID INVALID_TEXTURE_ID { 0 }; constexpr TextureID INVALID_TEXTURE_ID { 0 };
constexpr std::uint8_t MAX_FRAMES_IN_FLIGHT { 2 };
} // namespace fgl::engine::constants } // namespace fgl::engine::constants

View File

@@ -214,7 +214,7 @@ namespace fgl::engine::descriptors
{ {
auto& [ counter, set ] = *itter; auto& [ counter, set ] = *itter;
// Prevent deleting a descriptor until we are sure it's been here long enough // 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 ); itter = QUEUE.erase( itter );
} }

View File

@@ -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

View File

@@ -0,0 +1,53 @@
//
// Created by kj16609 on 2/14/25.
//
#pragma once
#include <vulkan/vulkan_raii.hpp>
#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

View File

@@ -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

View File

@@ -0,0 +1,89 @@
//
// Created by kj16609 on 2/14/25.
//
#pragma once
#include <memory>
#include <queue>
#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

View File

@@ -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

View File

@@ -0,0 +1,24 @@
//
// Created by kj16609 on 2/14/25.
//
#pragma once
#include <vulkan/vulkan_raii.hpp>
#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

View File

@@ -117,8 +117,7 @@ namespace fgl::engine
return result; return result;
} }
vk::Result PresentSwapChain:: vk::Result PresentSwapChain::submitCommandBuffers( const CommandBuffer& buffers, const PresentIndex present_index )
submitCommandBuffers( const vk::raii::CommandBuffer& buffers, const PresentIndex present_index )
{ {
ZoneScoped; ZoneScoped;
@@ -142,7 +141,7 @@ namespace fgl::engine
m_submit_info.setWaitDstStageMask( wait_stages ); m_submit_info.setWaitDstStageMask( wait_stages );
m_submit_info.commandBufferCount = 1; 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 ] }; std::vector< vk::Semaphore > signaled_semaphores { m_render_finished_sem[ m_current_frame_index ] };
m_submit_info.setSignalSemaphores( signaled_semaphores ); m_submit_info.setSignalSemaphores( signaled_semaphores );
@@ -171,14 +170,14 @@ namespace fgl::engine
throw std::runtime_error( "failed to present swap chain image!" ); throw std::runtime_error( "failed to present swap chain image!" );
} }
m_current_frame_index = static_cast< m_current_frame_index = static_cast< FrameIndex >(
FrameIndex >( ( m_current_frame_index + static_cast< FrameIndex >( 1 ) ) % MAX_FRAMES_IN_FLIGHT ); ( m_current_frame_index + static_cast< FrameIndex >( 1 ) ) % constants::MAX_FRAMES_IN_FLIGHT );
return vk::Result::eSuccess; return vk::Result::eSuccess;
} }
void PresentSwapChain:: 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 ) switch ( stage_id )
{ {
@@ -196,7 +195,7 @@ namespace fgl::engine
vk::ImageAspectFlagBits::eDepth ) vk::ImageAspectFlagBits::eDepth )
}; };
command_buffer.pipelineBarrier( command_buffer->pipelineBarrier(
vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTopOfPipe,
vk::PipelineStageFlagBits::eColorAttachmentOutput vk::PipelineStageFlagBits::eColorAttachmentOutput
| vk::PipelineStageFlagBits::eEarlyFragmentTests | vk::PipelineStageFlagBits::eEarlyFragmentTests
@@ -216,7 +215,7 @@ namespace fgl::engine
vk::ImageLayout::eColorAttachmentOptimal, vk::ImageLayout::ePresentSrcKHR ), vk::ImageLayout::eColorAttachmentOptimal, vk::ImageLayout::ePresentSrcKHR ),
}; };
command_buffer.pipelineBarrier( command_buffer->pipelineBarrier(
vk::PipelineStageFlagBits::eColorAttachmentOutput, vk::PipelineStageFlagBits::eColorAttachmentOutput,
vk::PipelineStageFlagBits::eBottomOfPipe, vk::PipelineStageFlagBits::eBottomOfPipe,
vk::DependencyFlags( 0 ), vk::DependencyFlags( 0 ),
@@ -315,7 +314,7 @@ namespace fgl::engine
vk::FenceCreateInfo fenceInfo {}; vk::FenceCreateInfo fenceInfo {};
fenceInfo.flags = vk::FenceCreateFlagBits::eSignaled; 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() }; auto& device { Device::getInstance() };

View File

@@ -15,8 +15,6 @@ namespace fgl::engine
{ {
public: public:
static constexpr FrameIndex MAX_FRAMES_IN_FLIGHT { 2 };
enum StageID enum StageID
{ {
INITAL, INITAL,
@@ -105,12 +103,12 @@ namespace fgl::engine
[[nodiscard]] std::pair< vk::Result, PresentIndex > acquireNextImage(); [[nodiscard]] std::pair< vk::Result, PresentIndex > acquireNextImage();
[[nodiscard]] vk::Result [[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 > 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 } // namespace fgl::engine

View File

@@ -122,11 +122,11 @@ namespace fgl::engine
alloc_info.pNext = VK_NULL_HANDLE; alloc_info.pNext = VK_NULL_HANDLE;
alloc_info.commandPool = Device::getInstance().getCommandPool(); alloc_info.commandPool = Device::getInstance().getCommandPool();
alloc_info.level = vk::CommandBufferLevel::ePrimary; 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 ); //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 = createContext( m_phy_device, Device::getInstance(), m_command_buffer[ 0 ] );
/* /*
m_tracy_ctx = TracyVkContextCalibrated( m_tracy_ctx = TracyVkContextCalibrated(
@@ -139,8 +139,6 @@ namespace fgl::engine
*/ */
alloc_info.level = vk::CommandBufferLevel::eSecondary; alloc_info.level = vk::CommandBufferLevel::eSecondary;
m_gui_command_buffer = Device::getInstance()->allocateCommandBuffers( alloc_info );
} }
void Renderer::recreateSwapchain() 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" ); assert( !is_frame_started && "Cannot begin frame while frame is already in progress" );
auto [ result, present_index ] = m_swapchain->acquireNextImage(); auto [ result, present_index ] = m_swapchain->acquireNextImage();
@@ -184,28 +182,60 @@ namespace fgl::engine
throw std::runtime_error( "Failed to acquire swap chain image" ); throw std::runtime_error( "Failed to acquire swap chain image" );
is_frame_started = true; is_frame_started = true;
auto& command_buffer { getCurrentCommandbuffer() };
vk::CommandBufferBeginInfo begin_info {}; auto command_buffers {
begin_info.pNext = VK_NULL_HANDLE; Device::getInstance().getCmdBufferPool().getCommandBuffers( 4, CommandBufferHandle::Secondary )
//begin_info.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit; };
begin_info.pInheritanceInfo = VK_NULL_HANDLE;
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" ); ZoneScopedN( "Ending frame" );
assert( is_frame_started && "Cannot call end frame while frame is not in progress" ); 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 if ( result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR
|| m_window.wasWindowResized() ) || m_window.wasWindowResized() )
@@ -217,11 +247,10 @@ namespace fgl::engine
throw std::runtime_error( "Failed to submit commmand buffer" ); throw std::runtime_error( "Failed to submit commmand buffer" );
is_frame_started = false; is_frame_started = false;
current_frame_idx = current_frame_idx = static_cast< std::uint16_t >( ( current_frame_idx + 1 ) % constants::MAX_FRAMES_IN_FLIGHT );
static_cast< std::uint16_t >( ( current_frame_idx + 1 ) % PresentSwapChain::MAX_FRAMES_IN_FLIGHT );
} }
void Renderer::setViewport( const vk::raii::CommandBuffer& buffer ) void Renderer::setViewport( const CommandBuffer& buffer )
{ {
vk::Viewport viewport {}; vk::Viewport viewport {};
viewport.x = 0.0f; viewport.x = 0.0f;
@@ -233,19 +262,19 @@ namespace fgl::engine
const std::vector< vk::Viewport > viewports { viewport }; 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 vk::Rect2D scissor { { 0, 0 }, m_swapchain->getSwapChainExtent() };
const std::vector< vk::Rect2D > scissors { scissor }; 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" ); 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 ); m_swapchain->transitionImages( buffer, PresentSwapChain::INITAL, current_present_index );
buffer.beginRendering( info ); buffer->beginRendering( info );
setViewport( buffer ); setViewport( buffer );
setScissor( 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" ); 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 ); m_swapchain->transitionImages( buffer, PresentSwapChain::FINAL, current_present_index );
} }

View File

@@ -4,18 +4,17 @@
#pragma once #pragma once
// clang-format off
#include <vulkan/vulkan.hpp> #include <vulkan/vulkan.hpp>
#include <tracy/TracyVulkan.hpp>
// clang-format on
#include <cassert> #include <cassert>
#include <memory> #include <memory>
#include "CommandBuffers.hpp"
#include "PresentSwapChain.hpp" #include "PresentSwapChain.hpp"
//clang-format: off
#include <tracy/TracyVulkan.hpp>
//clang-format: on
namespace fgl::engine namespace fgl::engine
{ {
@@ -25,9 +24,6 @@ namespace fgl::engine
PhysicalDevice& m_phy_device; PhysicalDevice& m_phy_device;
std::unique_ptr< PresentSwapChain > m_swapchain; 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 }; TracyVkCtx m_tracy_ctx { nullptr };
PresentIndex current_present_index { std::numeric_limits< PresentIndex >::max() }; PresentIndex current_present_index { std::numeric_limits< PresentIndex >::max() };
@@ -53,26 +49,20 @@ namespace fgl::engine
bool isFrameInProgress() const { return is_frame_started; } 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; } TracyVkCtx getCurrentTracyCTX() const { return m_tracy_ctx; }
float getAspectRatio() const { return m_swapchain->extentAspectRatio(); } float getAspectRatio() const { return m_swapchain->extentAspectRatio(); }
vk::raii::CommandBuffer& beginFrame(); // vk::raii::CommandBuffer& beginFrame();
void endFrame(); std::optional< CommandBuffers > beginFrame();
void setViewport( const vk::raii::CommandBuffer& buffer ); void endFrame( CommandBuffers& buffers );
void setScissor( const vk::raii::CommandBuffer& buffer );
void beginSwapchainRendererPass( vk::raii::CommandBuffer& buffer ); void setViewport( const CommandBuffer& buffer );
void endSwapchainRendererPass( vk::raii::CommandBuffer& buffer ); void setScissor( const CommandBuffer& buffer );
void beginSwapchainRendererPass( CommandBuffer& buffer );
void endSwapchainRendererPass( CommandBuffer& buffer );
PresentSwapChain& getSwapChain() { return *m_swapchain; } PresentSwapChain& getSwapChain() { return *m_swapchain; }

View File

@@ -167,6 +167,7 @@ namespace fgl::engine
m_physical_device( m_instance, m_surface_khr ), m_physical_device( m_instance, m_surface_khr ),
device_creation_info( m_physical_device ), device_creation_info( m_physical_device ),
m_device( m_physical_device, device_creation_info.m_create_info ), 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_commandPool( m_device.createCommandPool( commandPoolInfo() ) ),
m_graphics_queue( m_device m_graphics_queue( m_device
.getQueue( m_physical_device.queueInfo().getIndex( vk::QueueFlagBits::eGraphics ), 0 ) ), .getQueue( m_physical_device.queueInfo().getIndex( vk::QueueFlagBits::eGraphics ), 0 ) ),

View File

@@ -10,6 +10,7 @@
#include "engine/rendering/Instance.hpp" #include "engine/rendering/Instance.hpp"
#include "engine/rendering/Surface.hpp" #include "engine/rendering/Surface.hpp"
#include "extensions.hpp" #include "extensions.hpp"
#include "rendering/CommandBufferPool.hpp"
#include "vma/vma_impl.hpp" #include "vma/vma_impl.hpp"
namespace fgl::engine namespace fgl::engine
@@ -89,6 +90,8 @@ namespace fgl::engine
vk::raii::Device m_device; vk::raii::Device m_device;
CommandBufferPool m_command_pool;
vk::raii::CommandPool m_commandPool; vk::raii::CommandPool m_commandPool;
vk::raii::Queue m_graphics_queue; vk::raii::Queue m_graphics_queue;
@@ -101,6 +104,7 @@ namespace fgl::engine
vk::PhysicalDeviceProperties m_properties; vk::PhysicalDeviceProperties m_properties;
vk::CommandPoolCreateInfo commandPoolInfo(); vk::CommandPoolCreateInfo commandPoolInfo();
CommandBufferPool& getCmdBufferPool() { return m_command_pool; }
Device( Window&, Instance& ); Device( Window&, Instance& );
~Device(); ~Device();

View File

@@ -26,7 +26,7 @@ namespace fgl::engine
m_builder_state( std::forward< std::unique_ptr< PipelineBuilder::BuilderState > >( builder_state ) ) 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() ) 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( void Pipeline::bindDescriptor(
vk::raii::CommandBuffer& command_buffer, CommandBuffer& command_buffer,
const descriptors::DescriptorIDX descriptor_idx, const descriptors::DescriptorIDX descriptor_idx,
descriptors::DescriptorSet& set ) descriptors::DescriptorSet& set )
{ {
const std::vector< vk::DescriptorSet > sets { *set }; const std::vector< vk::DescriptorSet > sets { *set };
constexpr std::vector< std::uint32_t > offsets {}; 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 ); bindDescriptor( comd_buffer, set.setIDX(), set );
} }

View File

@@ -31,19 +31,19 @@ namespace fgl::engine
vk::raii::PipelineLayout&& layout, vk::raii::PipelineLayout&& layout,
std::unique_ptr< PipelineBuilder::BuilderState >&& builder_state ); std::unique_ptr< PipelineBuilder::BuilderState >&& builder_state );
void bind( vk::raii::CommandBuffer& ); void bind( CommandBuffer& cmd_buffer );
void bindDescriptor( void bindDescriptor(
vk::raii::CommandBuffer&, descriptors::DescriptorIDX descriptor_idx, descriptors::DescriptorSet& set ); CommandBuffer&, descriptors::DescriptorIDX descriptor_idx, descriptors::DescriptorSet& set );
void bindDescriptor( vk::raii::CommandBuffer& comd_buffer, descriptors::DescriptorSet& set ); void bindDescriptor( CommandBuffer& comd_buffer, descriptors::DescriptorSet& set );
void setDebugName( const char* str ); void setDebugName( const char* str );
template < typename T > template < typename T >
requires std::is_trivially_copyable_v< 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 } );
} }
}; };

View File

@@ -5,7 +5,6 @@
#include "GuiSystem.hpp" #include "GuiSystem.hpp"
#include "engine/FrameInfo.hpp" #include "engine/FrameInfo.hpp"
#include "engine/assets/model/SimpleVertex.hpp"
#include "engine/rendering/pipelines/v2/AttachmentBuilder.hpp" #include "engine/rendering/pipelines/v2/AttachmentBuilder.hpp"
#include "engine/rendering/pipelines/v2/Pipeline.hpp" #include "engine/rendering/pipelines/v2/Pipeline.hpp"
#include "engine/rendering/pipelines/v2/PipelineBuilder.hpp" #include "engine/rendering/pipelines/v2/PipelineBuilder.hpp"
@@ -22,8 +21,10 @@ namespace fgl::engine
builder.addDescriptorSet( gui_descriptor_set ); builder.addDescriptorSet( gui_descriptor_set );
builder.setAttributeDescriptions( SimpleVertex::getAttributeDescriptions() ); // VUID-vkCmdDraw-None-04008: States that vertex binding 0 is null handle, and must be bound.
builder.setBindingDescriptions( SimpleVertex::getBindingDescriptions() ); // 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.setVertexShader( Shader::loadVertex( "shaders/gui-compose.slang" ) );
builder.setFragmentShader( Shader::loadFragment( "shaders/gui-compose.slang" ) ); builder.setFragmentShader( Shader::loadFragment( "shaders/gui-compose.slang" ) );
@@ -34,9 +35,9 @@ namespace fgl::engine
m_pipeline->setDebugName( "Gui Pipeline" ); 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 ); m_pipeline->bind( command_buffer );
@@ -50,7 +51,7 @@ namespace fgl::engine
ZoneScopedN( "GuiSystem::pass" ); ZoneScopedN( "GuiSystem::pass" );
auto& command_buffer { setupSystem( info ) }; auto& command_buffer { setupSystem( info ) };
command_buffer.draw( 3, 1, 0, 0 ); command_buffer->draw( 3, 1, 0, 0 );
} }
} // namespace fgl::engine } // namespace fgl::engine

View File

@@ -20,7 +20,7 @@ namespace fgl::engine
std::unique_ptr< Pipeline > m_pipeline {}; std::unique_ptr< Pipeline > m_pipeline {};
//Setup isn't needed for this. So we can just never define this safely. //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: public:

View File

@@ -18,7 +18,7 @@
namespace fgl::engine namespace fgl::engine
{ {
EntityRendererSystem::EntityRendererSystem( ) EntityRendererSystem::EntityRendererSystem()
{ {
ZoneScoped; ZoneScoped;
@@ -71,9 +71,9 @@ namespace fgl::engine
EntityRendererSystem::~EntityRendererSystem() 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. //This function becomes a dummy since we have multiple pipelines.
//We will instead bind the pipeline and descriptors for each stage of this pass. //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 ) void EntityRendererSystem::texturedPass( const FrameInfo& info )
{ {
ZoneScopedN( "Textured pass" ); 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" ); TracyVkZone( info.tracy_ctx, *command_buffer, "Render textured entities" );
auto [ draw_commands, model_matricies ] = auto [ draw_commands, model_matricies ] =
@@ -172,10 +172,10 @@ namespace fgl::engine
const std::vector< vk::Buffer > vert_buffers { info.model_vertex_buffer.getVkBuffer(), const std::vector< vk::Buffer > vert_buffers { info.model_vertex_buffer.getVkBuffer(),
model_matrix_info_buffer->getVkBuffer() }; model_matrix_info_buffer->getVkBuffer() };
command_buffer.bindVertexBuffers( 0, vert_buffers, { 0, model_matrix_info_buffer->getOffset() } ); 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->bindIndexBuffer( info.model_index_buffer.getVkBuffer(), 0, vk::IndexType::eUint32 );
command_buffer.drawIndexedIndirect( command_buffer->drawIndexedIndirect(
draw_parameter_buffer->getVkBuffer(), draw_parameter_buffer->getVkBuffer(),
draw_parameter_buffer->getOffset(), draw_parameter_buffer->getOffset(),
draw_parameter_buffer->size(), draw_parameter_buffer->size(),

View File

@@ -42,7 +42,7 @@ namespace fgl::engine
PerFrameArray< std::unique_ptr< DrawParameterBufferSuballocation > > m_draw_textured_parameter_buffers {}; PerFrameArray< std::unique_ptr< DrawParameterBufferSuballocation > > m_draw_textured_parameter_buffers {};
PerFrameArray< std::unique_ptr< ModelMatrixInfoBufferSuballocation > > m_textured_model_matrix_info_buffers {}; PerFrameArray< std::unique_ptr< ModelMatrixInfoBufferSuballocation > > m_textured_model_matrix_info_buffers {};
vk::raii::CommandBuffer& setupSystem( const FrameInfo& ); CommandBuffer& setupSystem( const FrameInfo& );
public: public:

View File

@@ -24,7 +24,7 @@ namespace fgl::engine
inline static std::vector< VertexLine > m_lines {}; inline static std::vector< VertexLine > m_lines {};
LineDrawer::LineDrawer( ) LineDrawer::LineDrawer()
{ {
PipelineBuilder builder { 0 }; PipelineBuilder builder { 0 };
@@ -48,9 +48,9 @@ namespace fgl::engine
LineDrawer::~LineDrawer() 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->bind( command_buffer );
m_pipeline->bindDescriptor( command_buffer, info.getCameraDescriptor() ); 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 ); 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 ); static_cast< std::uint32_t >( m_lines.size() * 2 ), static_cast< std::uint32_t >( m_lines.size() ), 0, 0 );
m_lines.clear(); m_lines.clear();

View File

@@ -25,7 +25,7 @@ namespace fgl::engine
FGL_DELETE_COPY( LineDrawer ); FGL_DELETE_COPY( LineDrawer );
FGL_DELETE_MOVE( LineDrawer ); FGL_DELETE_MOVE( LineDrawer );
vk::raii::CommandBuffer& setupSystem( FrameInfo& info ); CommandBuffer& setupSystem( FrameInfo& info );
void pass( FrameInfo& info ); void pass( FrameInfo& info );
LineDrawer(); LineDrawer();