diff --git a/src/engine/concepts/is_attachment.hpp b/src/engine/concepts/is_attachment.hpp index 0c0d998..1dd9f65 100644 --- a/src/engine/concepts/is_attachment.hpp +++ b/src/engine/concepts/is_attachment.hpp @@ -31,7 +31,7 @@ namespace fgl::engine }; { a.resources() - } -> std::same_as< AttachmentResources >; + } -> std::same_as< AttachmentResources& >; { a.m_clear_value } -> std::same_as< vk::ClearValue& >; diff --git a/src/engine/gameobjects/components/ModelComponent.hpp b/src/engine/gameobjects/components/ModelComponent.hpp index 85c3873..96e2775 100644 --- a/src/engine/gameobjects/components/ModelComponent.hpp +++ b/src/engine/gameobjects/components/ModelComponent.hpp @@ -24,7 +24,11 @@ namespace fgl::engine void drawImGui() override; - std::string_view name() const override {} + std::string_view name() const override + { + //TODO: Get name of component + return "TEST NAME"; + } virtual ~ModelComponent() override {} diff --git a/src/engine/gui/preview.cpp b/src/engine/gui/preview.cpp index 81eed25..4d3d60a 100644 --- a/src/engine/gui/preview.cpp +++ b/src/engine/gui/preview.cpp @@ -139,6 +139,7 @@ namespace fgl::engine::gui current = Composite; } + /* info.swap_chain.g_buffer_albedo_img->drawImGui( { v_size, h_size } ); ImGui::SameLine(); if ( ImGui::Selectable( options[ Albedo ], current == Albedo ) ) @@ -162,14 +163,17 @@ namespace fgl::engine::gui log::debug( "Changing output to Position" ); current = Position; } + */ ImGui::EndCombo(); } + /* switch ( current ) { default: [[fallthrough]]; + case Composite: info.swap_chain.g_buffer_composite_img->drawImGui(); break; @@ -182,7 +186,7 @@ namespace fgl::engine::gui case Position: info.swap_chain.g_buffer_position_img->drawImGui(); break; - } + }*/ handleDragDrop( info ); diff --git a/src/engine/image/ImageView.cpp b/src/engine/image/ImageView.cpp index f793cb5..7937dfa 100644 --- a/src/engine/image/ImageView.cpp +++ b/src/engine/image/ImageView.cpp @@ -52,9 +52,9 @@ namespace fgl::engine return info; } - vk::raii::ImageView& ImageView::getVkView() + vk::ImageView ImageView::getVkView() { - return m_image_view; + return *m_image_view; } vk::Extent2D ImageView::getExtent() const diff --git a/src/engine/image/ImageView.hpp b/src/engine/image/ImageView.hpp index 8912b9d..31a973f 100644 --- a/src/engine/image/ImageView.hpp +++ b/src/engine/image/ImageView.hpp @@ -31,34 +31,25 @@ namespace fgl::engine ImageView() = delete; + ImageView( std::shared_ptr< ImageHandle >& img ); + ImageView( const ImageView& ) = delete; ImageView& operator=( const ImageView& ) = delete; - ImageView( ImageView&& other ) noexcept : - m_resource( std::move( other.m_resource ) ), - m_descriptor_info( std::move( other.m_descriptor_info ) ), - m_image_view( std::move( other.m_image_view ) ), - m_sampler( - vk::Filter::eLinear, - vk::Filter::eLinear, - vk::SamplerMipmapMode::eLinear, - vk::SamplerAddressMode::eClampToEdge ) - { - other.m_image_view = VK_NULL_HANDLE; - } + ImageView( ImageView&& other ) = default; + ImageView& operator=( ImageView&& other ) = default; - vk::raii::ImageView createImageView( const std::shared_ptr< ImageHandle >& img ); - ImageView( std::shared_ptr< ImageHandle >& img ); + [[nodiscard]] static vk::raii::ImageView createImageView( const std::shared_ptr< ImageHandle >& img ); - vk::Extent2D getExtent() const; + [[nodiscard]] vk::Extent2D getExtent() const; - vk::raii::ImageView& getVkView(); + [[nodiscard]] vk::ImageView getVkView(); - VkImageView operator*() { return *m_image_view; } + [[nodiscard]] VkImageView operator*() { return *m_image_view; } - VkImage getVkImage() { return m_resource->getVkImage(); } + [[nodiscard]] VkImage getVkImage() { return m_resource->getVkImage(); } - Sampler& getSampler() { return m_sampler; }; + [[nodiscard]] Sampler& getSampler() { return m_sampler; }; vk::DescriptorImageInfo descriptorInfo( vk::Sampler sampler, vk::ImageLayout layout ) const; vk::DescriptorImageInfo descriptorInfo( vk::ImageLayout layout ) const; diff --git a/src/engine/image/Sampler.hpp b/src/engine/image/Sampler.hpp index bd60eb1..7c72375 100644 --- a/src/engine/image/Sampler.hpp +++ b/src/engine/image/Sampler.hpp @@ -61,10 +61,7 @@ namespace fgl::engine Sampler( Sampler&& other ); Sampler& operator=( Sampler&& ); - ~Sampler() - { - if ( *m_sampler != VK_NULL_HANDLE ) log::debug( "Sampler destroyed" ); - } + ~Sampler() {} vk::raii::Sampler& getVkSampler() { return m_sampler; } diff --git a/src/engine/model/Primitive.hpp b/src/engine/model/Primitive.hpp index 88263de..e9357df 100644 --- a/src/engine/model/Primitive.hpp +++ b/src/engine/model/Primitive.hpp @@ -66,7 +66,7 @@ namespace fgl::engine OrientedBoundingBox< CoordinateSpace::Model > m_bounding_box; PrimitiveMode m_mode; - PrimitiveTextures m_textures {}; + PrimitiveTextures m_textures; std::optional< TransformComponent > m_transform; @@ -81,7 +81,9 @@ namespace fgl::engine m_vertex_buffer( std::move( vertex_buffer ) ), m_index_buffer( std::move( index_buffer ) ), m_bounding_box( bounding_box ), - m_mode( mode ) + m_mode( mode ), + m_textures(), + m_transform() {} Primitive( @@ -94,7 +96,8 @@ namespace fgl::engine m_index_buffer( std::move( index_buffer ) ), m_bounding_box( bounding_box ), m_mode( mode ), - m_textures( std::forward< decltype( m_textures ) >( textures ) ) + m_textures( std::forward< decltype( m_textures ) >( textures ) ), + m_transform() {} Primitive() = delete; diff --git a/src/engine/rendering/Attachment.hpp b/src/engine/rendering/Attachment.hpp index 3588e94..675e939 100644 --- a/src/engine/rendering/Attachment.hpp +++ b/src/engine/rendering/Attachment.hpp @@ -13,7 +13,8 @@ #include "engine/concepts/is_attachment.hpp" #include "engine/image/Image.hpp" -#include "engine/rendering/Device.hpp" +#include "engine/image/ImageView.hpp" +#include "types.hpp" namespace fgl::engine { @@ -33,7 +34,7 @@ namespace fgl::engine class Attachment { vk::AttachmentDescription description {}; - std::uint32_t index { std::numeric_limits< std::uint32_t >::max() }; + std::uint32_t m_index { std::numeric_limits< std::uint32_t >::max() }; public: @@ -43,9 +44,22 @@ namespace fgl::engine void setClear( vk::ClearDepthStencilValue value ) { m_clear_value = value; } + //! Fills out with the resource image view for the given frame index + void fillVec( const std::uint16_t frame_idx, std::vector< vk::ImageView >& out ) + { + auto& resource { m_attachment_resources.m_image_views.at( frame_idx ) }; + assert( resource ); + + assert( out.size() > m_index ); + + vk::ImageView view { resource->getVkView() }; + + out.at( m_index ) = view; + } + AttachmentResources m_attachment_resources {}; - void setIndex( const std::uint32_t idx ) { index = idx; } + void setIndex( const std::uint32_t idx ) { m_index = idx; } constexpr static vk::AttachmentLoadOp loadOp = load_op; constexpr static vk::AttachmentStoreOp storeOp = store_op; @@ -80,6 +94,8 @@ namespace fgl::engine { linkImage( i, images[ i ] ); } + + log::info( "Linked {} images to the swapchain color", images.size() ); } void createResources( const std::uint32_t count, vk::Extent2D extent ) @@ -98,36 +114,55 @@ namespace fgl::engine } } - //! Creates a resource that is used across all frames + //! Creates resources required for this attachment void createResourceSpread( const std::uint32_t count, vk::Extent2D extent, vk::ImageUsageFlags extra_flags = vk::ImageUsageFlags( 0 ) ) { - auto image { std::make_shared< Image >( - extent, - description.format, - usage | vk::ImageUsageFlagBits::eInputAttachment | extra_flags, - inital_layout, - final_layout ) }; for ( std::uint32_t i = 0; i < count; ++i ) { + auto image { std::make_shared< Image >( + extent, + description.format, + usage | vk::ImageUsageFlagBits::eInputAttachment | extra_flags, + inital_layout, + final_layout ) }; + m_attachment_resources.m_images.emplace_back( image ); m_attachment_resources.m_image_views.emplace_back( image->getView() ); } } - AttachmentResources resources() { return m_attachment_resources; } + AttachmentResources& resources() { return m_attachment_resources; } vk::AttachmentDescription& desc() { return description; } std::uint32_t getIndex() const { assert( - index != std::numeric_limits< std::uint32_t >::max() + m_index != std::numeric_limits< std::uint32_t >::max() && "Attachment must be registered in RenderPass before use" ); - return index; + return m_index; } - friend class RenderPass; + ImageView& view( const FrameIndex index ) { return *m_attachment_resources.m_image_views[ index ]; } + + Image& image( const FrameIndex index ) { return *m_attachment_resources.m_images[ index ]; } + + void setName( const std::string str ) + { + auto& images { m_attachment_resources.m_images }; + auto& image_views { m_attachment_resources.m_image_views }; + + assert( images.size() == image_views.size() ); + + for ( std::size_t i = 0; i < images.size(); ++i ) + { + images[ i ]->setName( str ); + image_views[ i ]->setName( str ); + } + } + + friend class RenderPassBuilder; }; template < is_attachment AttachmentT, vk::ImageLayout layout > diff --git a/src/engine/rendering/CameraSwapchain.cpp b/src/engine/rendering/CameraSwapchain.cpp new file mode 100644 index 0000000..ba7faef --- /dev/null +++ b/src/engine/rendering/CameraSwapchain.cpp @@ -0,0 +1,107 @@ +// +// Created by kj16609 on 7/10/24. +// + +#include "CameraSwapchain.hpp" + +#include "Device.hpp" +#include "RenderPassBuilder.hpp" + +/* +namespace fgl::engine +{ + + vk::Format pickOptimalDepthFormat() + { + return Device::getInstance().findSupportedFormat( + { vk::Format::eD32Sfloat, vk::Format::eD32SfloatS8Uint, vk::Format::eD24UnormS8Uint }, + vk::ImageTiling::eOptimal, + vk::FormatFeatureFlagBits::eDepthStencilAttachment ); + } + + std::vector< vk::raii::Framebuffer > CameraSwapchain::createFramebuffers() + {} + + vk::raii::RenderPass CameraSwapchain::createRenderpass() + { + //In order to make the renderpass we need to know what we are doing. + RenderPassBuilder render_pass_builder; + + //We start by defining the various attachments used here. + + auto& [ color_attachment, depth_attachment, position_attachment, normal_attachment, albedo_attachment ] = + m_attachments; + + render_pass_builder.registerAttachments( + color_attachment, depth_attachment, position_attachment, normal_attachment, albedo_attachment ); + + //TODO: Pre depth pass in order to reduce the number of fragment invocations + + Subpass< + vk::PipelineBindPoint::eGraphics, + UsedAttachment< DepthAttachment, vk::ImageLayout::eDepthStencilAttachmentOptimal >, + UsedAttachment< ColorAttachment, vk::ImageLayout::eColorAttachmentOptimal >, + UsedAttachment< ColorAttachment, vk::ImageLayout::eColorAttachmentOptimal >, + UsedAttachment< ColorAttachment, vk::ImageLayout::eColorAttachmentOptimal > > + g_buffer_subpass { 0, depth_attachment, position_attachment, normal_attachment, albedo_attachment }; + + g_buffer_subpass.registerDependencyFromExternal( + vk::AccessFlagBits::eDepthStencilAttachmentWrite, + vk::PipelineStageFlagBits::eEarlyFragmentTests | vk::PipelineStageFlagBits::eLateFragmentTests ); + + g_buffer_subpass.registerDependencyFromExternal( + vk::AccessFlagBits::eColorAttachmentWrite, vk::PipelineStageFlagBits::eColorAttachmentOutput ); + + Subpass< + vk::PipelineBindPoint::eGraphics, + UsedAttachment< DepthAttachment, vk::ImageLayout::eDepthStencilAttachmentOptimal >, + UsedAttachment< ColorAttachment, vk::ImageLayout::eColorAttachmentOptimal >, + InputAttachment< ColorAttachment, vk::ImageLayout::eShaderReadOnlyOptimal >, + InputAttachment< ColorAttachment, vk::ImageLayout::eShaderReadOnlyOptimal >, + InputAttachment< ColorAttachment, vk::ImageLayout::eShaderReadOnlyOptimal > > + composite_subpass { + 1, depth_attachment, color_attachment, position_attachment, normal_attachment, albedo_attachment + }; + + // For color attachments + composite_subpass.registerDependencyFrom( + g_buffer_subpass, + vk::AccessFlagBits::eColorAttachmentWrite, + vk::PipelineStageFlagBits::eColorAttachmentOutput, + vk::AccessFlagBits::eInputAttachmentRead, + vk::PipelineStageFlagBits::eFragmentShader, + vk::DependencyFlagBits::eByRegion ); + + // For depth attachment + composite_subpass.registerDependencyFrom( + g_buffer_subpass, + vk::AccessFlagBits::eDepthStencilAttachmentWrite, + vk::PipelineStageFlagBits::eEarlyFragmentTests | vk::PipelineStageFlagBits::eLateFragmentTests, + vk::AccessFlagBits::eDepthStencilAttachmentRead | vk::AccessFlagBits::eDepthStencilAttachmentWrite, + vk::PipelineStageFlagBits::eEarlyFragmentTests | vk::PipelineStageFlagBits::eLateFragmentTests, + vk::DependencyFlagBits::eByRegion ); + + composite_subpass.registerDependencyToExternal( + vk::AccessFlagBits::eColorAttachmentWrite, + vk::PipelineStageFlagBits::eColorAttachmentOutput, + vk::AccessFlagBits::eInputAttachmentRead, + vk::PipelineStageFlagBits::eFragmentShader, + vk::DependencyFlagBits::eByRegion ); + + render_pass_builder.registerSubpass( g_buffer_subpass ); + render_pass_builder.registerSubpass( composite_subpass ); + + return render_pass_builder.create(); + } + + CameraSwapchain::CameraSwapchain( PhysicalDevice& physical_device, vk::Extent2D starting_extent ) : + m_physical_device( physical_device ), + m_final_render_info( vk::Format::eR8G8B8A8Unorm, pickOptimalDepthFormat() ), + m_attachments( m_final_render_info.m_color_format, m_final_render_info.m_depth_format ), + m_extent( starting_extent ), + m_renderpass( createRenderpass() ), + m_framebuffers( createFramebuffers() ) + {} + +} // namespace fgl::engine +*/ \ No newline at end of file diff --git a/src/engine/rendering/CameraSwapchain.hpp b/src/engine/rendering/CameraSwapchain.hpp new file mode 100644 index 0000000..4835bbb --- /dev/null +++ b/src/engine/rendering/CameraSwapchain.hpp @@ -0,0 +1,66 @@ +// +// Created by kj16609 on 7/10/24. +// + +#pragma once +#include +#include + +#include "Attachment.hpp" + +/* +namespace fgl::engine +{ + class PhysicalDevice; + + vk::Format pickOptimalDepthFormat(); + + class CameraSwapchain + { + PhysicalDevice& m_physical_device; + + //! Contains the information for the final color buffer + struct + { + vk::Format m_color_format; + vk::Format m_depth_format; + } m_final_render_info; + + struct + { + // Final output (composite) attachments + ColorAttachment color_attachment; + DepthAttachment depth_attachment; + + // GBuffer Attachments + ColorAttachment position_attachment { vk::Format::eR16G16B16A16Sfloat }; + ColorAttachment normal_attachment { vk::Format::eR16G16B16A16Sfloat }; + ColorAttachment albedo_attachment { vk::Format::eR8G8B8A8Unorm }; + } m_attachments; + + vk::Extent2D m_extent; + + vk::raii::RenderPass m_renderpass; + + //! Framebuffers used in each frame (index using frame_idx) + std::vector< vk::raii::Framebuffer > m_framebuffers; + + struct + { + //! Triggered when the image is ready to be used again + std::vector< vk::raii::Semaphore > image_available; + + //! Triggered when the frame is finished rendering + std::vector< vk::raii::Semaphore > render_finished; + } semaphores; + + std::vector< vk::raii::Framebuffer > createFramebuffers(); + + vk::raii::RenderPass createRenderpass(); + + public: + + CameraSwapchain( PhysicalDevice& physical_device, vk::Extent2D starting_extent ); + }; +} // namespace fgl::engine +*/ \ No newline at end of file diff --git a/src/engine/rendering/RenderPass.cpp b/src/engine/rendering/RenderPassBuilder.cpp similarity index 88% rename from src/engine/rendering/RenderPass.cpp rename to src/engine/rendering/RenderPassBuilder.cpp index 51bacb2..f1cde4b 100644 --- a/src/engine/rendering/RenderPass.cpp +++ b/src/engine/rendering/RenderPassBuilder.cpp @@ -2,14 +2,13 @@ // Created by kj16609 on 12/31/23. // -#include "RenderPass.hpp" - #include "Device.hpp" +#include "RenderPassBuilder.hpp" namespace fgl::engine { - vk::raii::RenderPass RenderPass::create() + vk::raii::RenderPass RenderPassBuilder::create() { auto& device { Device::getInstance() }; diff --git a/src/engine/rendering/RenderPass.hpp b/src/engine/rendering/RenderPassBuilder.hpp similarity index 94% rename from src/engine/rendering/RenderPass.hpp rename to src/engine/rendering/RenderPassBuilder.hpp index b60e802..4999dfd 100644 --- a/src/engine/rendering/RenderPass.hpp +++ b/src/engine/rendering/RenderPassBuilder.hpp @@ -31,7 +31,7 @@ namespace fgl::engine } }; - class RenderPass + class RenderPassBuilder { std::vector< vk::AttachmentDescription > attachment_descriptions {}; std::vector< vk::ClearValue > m_clear_values {}; @@ -67,10 +67,6 @@ namespace fgl::engine attachment_descriptions.push_back( attachments.desc() ), m_clear_values.push_back( attachments.m_clear_value ) ), ... ); - - m_attachment_resources.reserve( sizeof...( Attachments ) ); - - ( ( m_attachment_resources.emplace_back( attachments.m_attachment_resources ) ), ... ); } std::unique_ptr< RenderPassResources > resources( std::uint16_t frame_count ) diff --git a/src/engine/rendering/Renderer.cpp b/src/engine/rendering/Renderer.cpp index b782e44..6537a39 100644 --- a/src/engine/rendering/Renderer.cpp +++ b/src/engine/rendering/Renderer.cpp @@ -100,8 +100,8 @@ namespace fgl::engine std::pair< vk::raii::CommandBuffer&, vk::raii::CommandBuffer& > Renderer::beginFrame() { assert( !is_frame_started && "Cannot begin frame while frame is already in progress" ); - auto [ result, image_idx ] = m_swapchain->acquireNextImage(); - current_image_idx = image_idx; + auto [ result, present_index ] = m_swapchain->acquireNextImage(); + current_present_index = present_index; if ( result == vk::Result::eErrorOutOfDateKHR ) { @@ -123,7 +123,8 @@ namespace fgl::engine command_buffer.begin( begin_info ); vk::CommandBufferInheritanceInfo inheritance_info {}; - inheritance_info.framebuffer = this->getSwapChain().getFrameBuffer( current_image_idx ); + inheritance_info.framebuffer = + this->getSwapChain().getFrameBuffer( current_frame_index, current_present_index ); inheritance_info.renderPass = this->getSwapChainRenderPass(); inheritance_info.subpass = 2; @@ -148,7 +149,7 @@ namespace fgl::engine command_buffer.end(); - const auto result { m_swapchain->submitCommandBuffers( command_buffer, current_image_idx ) }; + const auto result { m_swapchain->submitCommandBuffers( command_buffer, current_present_index ) }; if ( result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR || m_window.wasWindowResized() ) @@ -160,7 +161,8 @@ 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 ) % SwapChain::MAX_FRAMES_IN_FLIGHT ); + current_frame_index = + static_cast< std::uint16_t >( ( current_frame_index + 1 ) % SwapChain::MAX_FRAMES_IN_FLIGHT ); } void Renderer::setViewport( const vk::raii::CommandBuffer& buffer ) @@ -196,7 +198,7 @@ namespace fgl::engine vk::RenderPassBeginInfo render_pass_info {}; render_pass_info.pNext = VK_NULL_HANDLE; render_pass_info.renderPass = m_swapchain->getRenderPass(); - render_pass_info.framebuffer = m_swapchain->getFrameBuffer( static_cast< int >( current_image_idx ) ); + render_pass_info.framebuffer = m_swapchain->getFrameBuffer( current_frame_index, current_present_index ); render_pass_info.renderArea = { .offset = { 0, 0 }, .extent = m_swapchain->getSwapChainExtent() }; render_pass_info.clearValueCount = static_cast< std::uint32_t >( clear_values.size() ); render_pass_info.pClearValues = clear_values.data(); diff --git a/src/engine/rendering/Renderer.hpp b/src/engine/rendering/Renderer.hpp index 995fcfb..222a895 100644 --- a/src/engine/rendering/Renderer.hpp +++ b/src/engine/rendering/Renderer.hpp @@ -32,8 +32,8 @@ namespace fgl::engine std::optional< TracyVkCtx > m_tracy_ctx { std::nullopt }; - uint32_t current_image_idx { std::numeric_limits< std::uint32_t >::max() }; - std::uint16_t current_frame_idx { 0 }; + PresentIndex current_present_index { std::numeric_limits< PresentIndex >::max() }; + FrameIndex current_frame_index { 0 }; bool is_frame_started { false }; void createCommandBuffers(); @@ -54,7 +54,7 @@ namespace fgl::engine std::uint16_t getFrameIndex() const { assert( is_frame_started && "Cannot get frame index while frame not in progress" ); - return current_frame_idx; + return current_frame_index; } bool isFrameInProgress() const { return is_frame_started; } @@ -62,10 +62,10 @@ namespace fgl::engine vk::raii::CommandBuffer& getCurrentCommandbuffer() { assert( is_frame_started && "Cannot get command buffer while frame not in progress" ); - return m_command_buffer[ current_frame_idx ]; + return m_command_buffer[ current_frame_index ]; } - vk::raii::CommandBuffer& getCurrentGuiCommandBuffer() { return m_gui_command_buffer[ current_frame_idx ]; } + vk::raii::CommandBuffer& getCurrentGuiCommandBuffer() { return m_gui_command_buffer[ current_frame_index ]; } TracyVkCtx getCurrentTracyCTX() const { diff --git a/src/engine/rendering/Subpass.hpp b/src/engine/rendering/Subpass.hpp index b0d6705..35c652e 100644 --- a/src/engine/rendering/Subpass.hpp +++ b/src/engine/rendering/Subpass.hpp @@ -109,7 +109,7 @@ namespace fgl::engine vk::SubpassDescription description() { return subpass_description; } - friend class RenderPass; + friend class RenderPassBuilder; void registerDependency( std::uint32_t src_subpass, @@ -142,8 +142,7 @@ namespace fgl::engine log::critical( "Rendering pass using a full dependency. THIS IS MOST LIKELY NOT WHAT YOU WANT UNLESS DEBUGGING" ); constexpr vk::AccessFlags all_access { vk::AccessFlagBits::eMemoryWrite | vk::AccessFlagBits::eMemoryRead }; - constexpr vk::PipelineStageFlags all_stages { vk::PipelineStageFlagBits::eAllCommands - | vk::PipelineStageFlagBits::eAllGraphics }; + constexpr vk::PipelineStageFlags all_stages { vk::PipelineStageFlagBits::eAllGraphics }; registerDependencyFrom( parent, all_access, all_stages, all_access, all_stages, vk::DependencyFlagBits::eByRegion ); diff --git a/src/engine/rendering/SwapChain.cpp b/src/engine/rendering/SwapChain.cpp index 638b6ca..826e728 100644 --- a/src/engine/rendering/SwapChain.cpp +++ b/src/engine/rendering/SwapChain.cpp @@ -8,29 +8,46 @@ #include #include "Attachment.hpp" -#include "RenderPass.hpp" +#include "RenderPassBuilder.hpp" #include "Subpass.hpp" #include "engine/assets/TransferManager.hpp" namespace fgl::engine { - SwapChain::SwapChain( vk::Extent2D extent, PhysicalDevice& phy_device ) : + SwapChain::SwapChain( const vk::Extent2D extent, PhysicalDevice& phy_device ) : m_phy_device( phy_device ), - windowExtent( extent ) + m_swapchain_support( Device::getInstance().getSwapChainSupport() ), + m_surface_format( chooseSwapSurfaceFormat( m_swapchain_support.formats ) ), + m_swap_chain_format( m_surface_format.format ), + m_swap_chain_extent( chooseSwapExtent( m_swapchain_support.capabilities ) ), + windowExtent( extent ), + m_render_attachments( getSwapChainImageFormat(), findDepthFormat() ) { init(); } - SwapChain::SwapChain( vk::Extent2D extent, std::shared_ptr< SwapChain > previous ) : + SwapChain::SwapChain( const vk::Extent2D extent, std::shared_ptr< SwapChain > previous ) : m_phy_device( previous->m_phy_device ), + old_swap_chain( previous ), + m_swapchain_support( Device::getInstance().getSwapChainSupport() ), + m_surface_format( chooseSwapSurfaceFormat( m_swapchain_support.formats ) ), + m_swap_chain_format( m_surface_format.format ), + m_swap_chain_extent( chooseSwapExtent( m_swapchain_support.capabilities ) ), windowExtent( extent ), - old_swap_chain( previous ) + m_render_attachments( getSwapChainImageFormat(), findDepthFormat() ) { init(); old_swap_chain.reset(); } + vk::raii::Framebuffer& SwapChain::getFrameBuffer( const FrameIndex frame_idx, const PresentIndex present_idx ) + { + assert( present_idx < m_swap_chain_buffers.size() ); + assert( frame_idx < SwapChain::MAX_FRAMES_IN_FLIGHT ); + return m_swap_chain_buffers[ present_idx ][ frame_idx ]; + } + void SwapChain::init() { createSwapChain(); @@ -43,7 +60,7 @@ namespace fgl::engine { ZoneScoped; - std::vector< vk::Fence > fences { inFlightFences[ currentFrame ] }; + std::vector< vk::Fence > fences { in_flight_fences[ current_frame_index ] }; if ( Device::getInstance().device().waitForFences( fences, VK_TRUE, std::numeric_limits< uint64_t >::max() ) != vk::Result::eSuccess ) @@ -51,19 +68,20 @@ namespace fgl::engine auto result { swapChain.acquireNextImage( std::numeric_limits< uint64_t >::max(), - imageAvailableSemaphores[ currentFrame ] // must be a not signaled semaphore + imageAvailableSemaphores[ current_frame_index ] // must be a not signaled semaphore ) }; return result; } - vk::Result SwapChain::submitCommandBuffers( const vk::raii::CommandBuffer& buffers, std::uint32_t imageIndex ) + vk::Result SwapChain:: + submitCommandBuffers( const vk::raii::CommandBuffer& buffers, const PresentIndex current_present_index ) { ZoneScoped; - imagesInFlight[ imageIndex ] = inFlightFences[ currentFrame ]; + images_in_flight[ current_present_index ] = in_flight_fences[ current_frame_index ]; - std::vector< vk::Fence > fences { imagesInFlight[ imageIndex ] }; + std::vector< vk::Fence > fences { images_in_flight[ current_present_index ] }; if ( Device::getInstance().device().waitForFences( fences, VK_TRUE, std::numeric_limits< uint64_t >::max() ) != vk::Result::eSuccess ) @@ -71,7 +89,7 @@ namespace fgl::engine vk::SubmitInfo submitInfo {}; - std::vector< vk::Semaphore > wait_sems { imageAvailableSemaphores[ currentFrame ], + std::vector< vk::Semaphore > wait_sems { imageAvailableSemaphores[ current_frame_index ], memory::TransferManager::getInstance().getFinishedSem() }; std::vector< vk::PipelineStageFlags > wait_stages { vk::PipelineStageFlagBits::eColorAttachmentOutput, @@ -83,14 +101,14 @@ namespace fgl::engine submitInfo.commandBufferCount = 1; submitInfo.pCommandBuffers = &( *buffers ); - std::vector< vk::Semaphore > signaled_semaphores { renderFinishedSemaphores[ currentFrame ] }; + std::vector< vk::Semaphore > signaled_semaphores { renderFinishedSemaphores[ current_frame_index ] }; submitInfo.setSignalSemaphores( signaled_semaphores ); Device::getInstance().device().resetFences( fences ); std::vector< vk::SubmitInfo > submit_infos { submitInfo }; - Device::getInstance().graphicsQueue().submit( submitInfo, inFlightFences[ currentFrame ] ); + Device::getInstance().graphicsQueue().submit( submitInfo, in_flight_fences[ current_frame_index ] ); vk::PresentInfoKHR presentInfo = {}; @@ -99,7 +117,7 @@ namespace fgl::engine std::vector< vk::SwapchainKHR > swapchains { swapChain }; presentInfo.setSwapchains( swapchains ); - std::array< std::uint32_t, 1 > indicies { { imageIndex } }; + std::array< std::uint32_t, 1 > indicies { { current_present_index } }; presentInfo.setImageIndices( indicies ); if ( auto present_result = Device::getInstance().presentQueue().presentKHR( presentInfo ); @@ -110,7 +128,7 @@ namespace fgl::engine throw std::runtime_error( "failed to present swap chain image!" ); } - currentFrame = ( currentFrame + 1 ) % MAX_FRAMES_IN_FLIGHT; + current_frame_index = ( current_frame_index + 1 ) % MAX_FRAMES_IN_FLIGHT; return vk::Result::eSuccess; } @@ -118,26 +136,23 @@ namespace fgl::engine void SwapChain::createSwapChain() { ZoneScoped; - SwapChainSupportDetails swapChainSupport { Device::getInstance().getSwapChainSupport() }; - vk::SurfaceFormatKHR surfaceFormat { chooseSwapSurfaceFormat( swapChainSupport.formats ) }; - vk::PresentModeKHR presentMode { chooseSwapPresentMode( swapChainSupport.presentModes ) }; - vk::Extent2D extent { chooseSwapExtent( swapChainSupport.capabilities ) }; + const vk::PresentModeKHR presentMode { chooseSwapPresentMode( m_swapchain_support.presentModes ) }; - uint32_t imageCount = swapChainSupport.capabilities.minImageCount + 1; - if ( swapChainSupport.capabilities.maxImageCount > 0 - && imageCount > swapChainSupport.capabilities.maxImageCount ) + uint32_t imageCount = m_swapchain_support.capabilities.minImageCount + 1; + if ( m_swapchain_support.capabilities.maxImageCount > 0 + && imageCount > m_swapchain_support.capabilities.maxImageCount ) { - imageCount = swapChainSupport.capabilities.maxImageCount; + imageCount = m_swapchain_support.capabilities.maxImageCount; } vk::SwapchainCreateInfoKHR createInfo = {}; createInfo.surface = Device::getInstance().surface(); createInfo.minImageCount = imageCount; - createInfo.imageFormat = surfaceFormat.format; - createInfo.imageColorSpace = surfaceFormat.colorSpace; - createInfo.imageExtent = extent; + createInfo.imageFormat = m_surface_format.format; + createInfo.imageColorSpace = m_surface_format.colorSpace; + createInfo.imageExtent = m_swap_chain_extent; createInfo.imageArrayLayers = 1; createInfo.imageUsage = vk::ImageUsageFlagBits::eColorAttachment; @@ -161,7 +176,7 @@ namespace fgl::engine createInfo.pQueueFamilyIndices = nullptr; // Optional } - createInfo.preTransform = swapChainSupport.capabilities.currentTransform; + createInfo.preTransform = m_swapchain_support.capabilities.currentTransform; createInfo.compositeAlpha = vk::CompositeAlphaFlagBitsKHR::eOpaque; createInfo.presentMode = presentMode; @@ -175,108 +190,25 @@ namespace fgl::engine for ( std::uint64_t i = 0; i < swap_chain_images.size(); i++ ) { - auto& itter = - m_swap_chain_images - .emplace_back( extent, surfaceFormat.format, swap_chain_images[ i ], createInfo.imageUsage ); + auto& itter = m_swap_chain_images.emplace_back( + m_swap_chain_extent, m_surface_format.format, swap_chain_images[ i ], createInfo.imageUsage ); itter.setName( "Swapchain image: " + std::to_string( i ) ); } - - m_swap_chain_format = surfaceFormat.format; - m_swap_chain_extent = extent; } void SwapChain::createRenderPass() { ZoneScoped; - //Present attachment - ColoredPresentAttachment colorAttachment { getSwapChainImageFormat() }; - for ( int i = 0; i < imageCount(); ++i ) - { - auto& image { m_swap_chain_images[ i ] }; + RenderPassBuilder render_pass_builder {}; - image.setName( "SwapChainImage: " + std::to_string( i ) ); - } - - colorAttachment.linkImages( m_swap_chain_images ); - - // G-Buffer - ColorAttachment g_buffer_position { vk::Format::eR16G16B16A16Sfloat }; - ColorAttachment g_buffer_normal { vk::Format::eR16G16B16A16Sfloat }; - ColorAttachment g_buffer_albedo { vk::Format::eR8G8B8A8Unorm }; - ColorAttachment g_buffer_composite { vk::Format::eR8G8B8A8Unorm }; - - g_buffer_position.createResourceSpread( imageCount(), getSwapChainExtent(), vk::ImageUsageFlagBits::eSampled ); - g_buffer_normal.createResourceSpread( imageCount(), getSwapChainExtent(), vk::ImageUsageFlagBits::eSampled ); - g_buffer_albedo.createResourceSpread( imageCount(), getSwapChainExtent(), vk::ImageUsageFlagBits::eSampled ); - g_buffer_composite.createResourceSpread( imageCount(), getSwapChainExtent(), vk::ImageUsageFlagBits::eSampled ); - - g_buffer_position.setClear( vk::ClearColorValue( std::array< float, 4 > { { 0.0f, 0.0f, 0.0f, 0.0f } } ) ); - g_buffer_normal.setClear( vk::ClearColorValue( std::array< float, 4 > { { 0.0f, 0.0f, 0.0f, 0.0f } } ) ); - g_buffer_albedo.setClear( vk::ClearColorValue( std::array< float, 4 > { { 0.0f, 0.0f, 0.0f, 0.0f } } ) ); - g_buffer_composite.setClear( vk::ClearColorValue( std::array< float, 4 > { { 0.0f, 0.0f, 0.0f, 0.0f } } ) ); - - g_buffer_position_img = std::make_unique< Texture >( g_buffer_position.m_attachment_resources.m_images[ 0 ] - ->setName( "GBufferPosition" ) ); - g_buffer_normal_img = std::make_unique< Texture >( g_buffer_normal.m_attachment_resources.m_images[ 0 ] - ->setName( "GBufferNormal" ) ); - g_buffer_albedo_img = std::make_unique< Texture >( g_buffer_albedo.m_attachment_resources.m_images[ 0 ] - ->setName( "GBufferAlbedo" ) ); - g_buffer_composite_img = std::make_unique< Texture >( g_buffer_composite.m_attachment_resources.m_images[ 0 ] - ->setName( "GBufferComposite" ) ); - - RenderPass render_pass {}; - - DepthAttachment depthAttachment { findDepthFormat() }; - depthAttachment.createResources( imageCount(), getSwapChainExtent() ); - depthAttachment.setClear( vk::ClearDepthStencilValue( 1.0f, 0 ) ); - - render_pass.registerAttachments( - colorAttachment, depthAttachment, g_buffer_position, g_buffer_normal, g_buffer_albedo, g_buffer_composite ); - - for ( int i = 0; i < SwapChain::MAX_FRAMES_IN_FLIGHT; ++i ) - { - { - auto set { std::make_unique< descriptors::DescriptorSet >( GBufferDescriptorSet::createLayout() ) }; - - set->setMaxIDX( 2 ); - - set->bindAttachment( - 0, - *( g_buffer_position.resources().m_image_views[ i ].get() ), - vk::ImageLayout::eShaderReadOnlyOptimal ); - - set->bindAttachment( - 1, - *( g_buffer_normal.resources().m_image_views[ i ].get() ), - vk::ImageLayout::eShaderReadOnlyOptimal ); - - set->bindAttachment( - 2, - *( g_buffer_albedo.resources().m_image_views[ i ].get() ), - vk::ImageLayout::eShaderReadOnlyOptimal ); - - set->update(); - - m_gbuffer_descriptor_set[ i ] = std::move( set ); - } - - { - auto composite_set { - std::make_unique< descriptors::DescriptorSet >( GBufferCompositeDescriptorSet::createLayout() ) - }; - - composite_set->setMaxIDX( 2 ); - composite_set->bindAttachment( - 0, - *( g_buffer_composite.resources().m_image_views[ 0 ].get() ), - vk::ImageLayout::eShaderReadOnlyOptimal ); - - composite_set->update(); - - m_gbuffer_composite_descriptor_set[ i ] = std::move( composite_set ); - } - } + render_pass_builder.registerAttachments( + m_render_attachments.color, + m_render_attachments.depth, + m_gbuffer_attachments.position, + m_gbuffer_attachments.normal, + m_gbuffer_attachments.albedo, + m_gbuffer_attachments.composite ); static_assert( is_attachment< ColoredPresentAttachment > ); static_assert( is_attachment< DepthAttachment > ); @@ -287,7 +219,11 @@ namespace fgl::engine UsedAttachment< ColorAttachment, vk::ImageLayout::eColorAttachmentOptimal >, UsedAttachment< ColorAttachment, vk::ImageLayout::eColorAttachmentOptimal >, UsedAttachment< ColorAttachment, vk::ImageLayout::eColorAttachmentOptimal > > - g_buffer_subpass { 0, depthAttachment, g_buffer_position, g_buffer_normal, g_buffer_albedo }; + g_buffer_subpass { 0, + m_render_attachments.depth, + m_gbuffer_attachments.position, + m_gbuffer_attachments.normal, + m_gbuffer_attachments.albedo }; g_buffer_subpass.registerDependencyFromExternal( vk::AccessFlagBits::eDepthStencilAttachmentWrite, @@ -299,17 +235,22 @@ namespace fgl::engine Subpass< vk::PipelineBindPoint::eGraphics, UsedAttachment< DepthAttachment, vk::ImageLayout::eDepthStencilAttachmentOptimal >, - UsedAttachment< ColorAttachment, vk::ImageLayout::eColorAttachmentOptimal >, + UsedAttachment< ColoredPresentAttachment, vk::ImageLayout::eColorAttachmentOptimal >, InputAttachment< ColorAttachment, vk::ImageLayout::eShaderReadOnlyOptimal >, InputAttachment< ColorAttachment, vk::ImageLayout::eShaderReadOnlyOptimal >, InputAttachment< ColorAttachment, vk::ImageLayout::eShaderReadOnlyOptimal > > - composite_subpass { - 1, depthAttachment, g_buffer_composite, g_buffer_position, g_buffer_normal, g_buffer_albedo - }; + composite_subpass { 1, + m_render_attachments.depth, + m_render_attachments.color, + m_gbuffer_attachments.position, + m_gbuffer_attachments.normal, + m_gbuffer_attachments.albedo }; composite_subpass.registerDependencyFromExternal( vk::AccessFlagBits::eColorAttachmentWrite, vk::PipelineStageFlagBits::eColorAttachmentOutput ); + composite_subpass.registerFullDependency( g_buffer_subpass ); + // For color attachments composite_subpass.registerDependencyFrom( g_buffer_subpass, @@ -328,23 +269,13 @@ namespace fgl::engine vk::PipelineStageFlagBits::eEarlyFragmentTests | vk::PipelineStageFlagBits::eLateFragmentTests, vk::DependencyFlagBits::eByRegion ); - /* - composite_subpass.registerDependencyFrom( - g_buffer_subpass, - vk::AccessFlagBits::eColorAttachmentWrite, - vk::PipelineStageFlagBits::eColorAttachmentOutput, - vk::AccessFlagBits::eTransferWrite, - vk::PipelineStageFlagBits::eTopOfPipe, - vk::DependencyFlagBits::eByRegion ); - */ - // To prevent the composite buffer from getting obliterated by the gui pass and so we can use it to render to the GUI in certian areas, We need to keep them seperate and the composite image to be unmodified. Subpass< vk::PipelineBindPoint::eGraphics, UsedAttachment< DepthAttachment, vk::ImageLayout::eDepthStencilAttachmentOptimal >, UsedAttachment< ColoredPresentAttachment, vk::ImageLayout::eColorAttachmentOptimal >, InputAttachment< ColorAttachment, vk::ImageLayout::eShaderReadOnlyOptimal > > - gui_subpass { 2, depthAttachment, colorAttachment, g_buffer_composite }; + gui_subpass { 2, m_render_attachments.depth, m_render_attachments.color, m_gbuffer_attachments.composite }; gui_subpass.registerDependencyFromExternal( vk::AccessFlagBits::eColorAttachmentWrite, vk::PipelineStageFlagBits::eColorAttachmentOutput ); @@ -361,9 +292,6 @@ namespace fgl::engine vk::PipelineStageFlagBits::eFragmentShader, vk::DependencyFlagBits::eByRegion ); - //composite_subpass.registerFullDependency( g_buffer_subpass ); - //gui_subpass.registerFullDependency( composite_subpass ); - gui_subpass.registerDependencyFrom( composite_subpass, vk::AccessFlagBits::eColorAttachmentWrite, @@ -379,36 +307,134 @@ namespace fgl::engine vk::PipelineStageFlagBits::eBottomOfPipe, vk::DependencyFlagBits::eByRegion ); - render_pass.registerSubpass( g_buffer_subpass ); - render_pass.registerSubpass( composite_subpass ); - render_pass.registerSubpass( gui_subpass ); + render_pass_builder.registerSubpass( g_buffer_subpass ); + render_pass_builder.registerSubpass( composite_subpass ); + render_pass_builder.registerSubpass( gui_subpass ); - m_render_pass = render_pass.create(); + m_render_pass = render_pass_builder.create(); + } - m_render_pass_resources = render_pass.resources( imageCount() ); - m_clear_values = render_pass.getClearValues(); + template < is_attachment... Attachments > + std::vector< vk::ImageView > fillViewsFromAttachments( uint8_t frame_idx, Attachments&&... attachments ) + { + std::vector< vk::ImageView > views {}; + + views.resize( sizeof...( Attachments ) ); + + ( ( attachments.fillVec( frame_idx, views ) ), ... ); + + return views; } void SwapChain::createFramebuffers() { ZoneScoped; + + // Render target resource management + for ( int i = 0; i < imageCount(); ++i ) + { + auto& image { m_swap_chain_images[ i ] }; + + image.setName( "SwapChainImage: " + std::to_string( i ) ); + } + + m_render_attachments.color.linkImages( m_swap_chain_images ); + + m_render_attachments.depth.createResources( imageCount(), getSwapChainExtent() ); + m_render_attachments.depth.setClear( vk::ClearDepthStencilValue( 1.0f, 0 ) ); + + // GBuffer resource management + m_gbuffer_attachments.position.createResourceSpread( + SwapChain::MAX_FRAMES_IN_FLIGHT, getSwapChainExtent(), vk::ImageUsageFlagBits::eSampled ); + m_gbuffer_attachments.normal.createResourceSpread( + SwapChain::MAX_FRAMES_IN_FLIGHT, getSwapChainExtent(), vk::ImageUsageFlagBits::eSampled ); + m_gbuffer_attachments.albedo.createResourceSpread( + SwapChain::MAX_FRAMES_IN_FLIGHT, getSwapChainExtent(), vk::ImageUsageFlagBits::eSampled ); + m_gbuffer_attachments.composite.createResourceSpread( + SwapChain::MAX_FRAMES_IN_FLIGHT, getSwapChainExtent(), vk::ImageUsageFlagBits::eSampled ); + + m_gbuffer_attachments.position.setClear( vk::ClearColorValue( std::array< float, 4 > { + { 0.0f, 0.0f, 0.0f, 0.0f } } ) ); + m_gbuffer_attachments.normal.setClear( vk::ClearColorValue( std::array< float, 4 > { + { 0.0f, 0.0f, 0.0f, 0.0f } } ) ); + m_gbuffer_attachments.albedo.setClear( vk::ClearColorValue( std::array< float, 4 > { + { 0.0f, 0.0f, 0.0f, 0.0f } } ) ); + m_gbuffer_attachments.composite.setClear( vk::ClearColorValue( std::array< float, 4 > { + { 0.0f, 0.0f, 0.0f, 0.0f } } ) ); + + populateAttachmentClearValues( + m_render_attachments.color, + m_render_attachments.depth, + m_gbuffer_attachments.position, + m_gbuffer_attachments.normal, + m_gbuffer_attachments.albedo, + m_gbuffer_attachments.composite ); + + for ( FrameIndex i = 0; i < SwapChain::MAX_FRAMES_IN_FLIGHT; ++i ) + { + auto gbuffer_set { std::make_unique< descriptors::DescriptorSet >( GBufferDescriptorSet::createLayout() ) }; + + gbuffer_set->setMaxIDX( 2 ); + + gbuffer_set->bindAttachment( + 0, m_gbuffer_attachments.position.view( i ), vk::ImageLayout::eShaderReadOnlyOptimal ); + + gbuffer_set + ->bindAttachment( 1, m_gbuffer_attachments.normal.view( i ), vk::ImageLayout::eShaderReadOnlyOptimal ); + + gbuffer_set + ->bindAttachment( 2, m_gbuffer_attachments.albedo.view( i ), vk::ImageLayout::eShaderReadOnlyOptimal ); + + gbuffer_set->update(); + + m_gbuffer_descriptor_set.at( i ) = std::move( gbuffer_set ); + + auto composite_set { + std::make_unique< descriptors::DescriptorSet >( GBufferCompositeDescriptorSet::createLayout() ) + }; + + composite_set->setMaxIDX( 0 ); + composite_set->bindAttachment( + 0, m_gbuffer_attachments.composite.view( i ), vk::ImageLayout::eShaderReadOnlyOptimal ); + + composite_set->update(); + + m_gbuffer_composite_descriptor_set.at( i ) = std::move( composite_set ); + } + m_swap_chain_buffers.clear(); m_swap_chain_buffers.reserve( imageCount() ); - for ( uint8_t i = 0; i < imageCount(); i++ ) + + for ( std::uint16_t present_idx = 0; present_idx < imageCount(); ++present_idx ) { - std::vector< vk::ImageView > attachments { m_render_pass_resources->forFrame( i ) }; + std::vector< vk::raii::Framebuffer > temp {}; + temp.reserve( SwapChain::MAX_FRAMES_IN_FLIGHT ); - //Fill attachments for this frame - const vk::Extent2D swapChainExtent { getSwapChainExtent() }; - vk::FramebufferCreateInfo framebufferInfo {}; - framebufferInfo.renderPass = m_render_pass; - framebufferInfo.attachmentCount = static_cast< uint32_t >( attachments.size() ); - framebufferInfo.pAttachments = attachments.data(); - framebufferInfo.width = swapChainExtent.width; - framebufferInfo.height = swapChainExtent.height; - framebufferInfo.layers = 1; + for ( FrameIndex frame_idx = 0; frame_idx < SwapChain::MAX_FRAMES_IN_FLIGHT; frame_idx++ ) + { + std::vector< vk::ImageView > attachments {}; - m_swap_chain_buffers.push_back( Device::getInstance()->createFramebuffer( framebufferInfo ) ); + attachments.emplace_back( *m_render_attachments.color.view( present_idx ) ); + attachments.emplace_back( *m_render_attachments.depth.view( present_idx ) ); + attachments.emplace_back( *m_gbuffer_attachments.position.view( frame_idx ) ); + attachments.emplace_back( *m_gbuffer_attachments.normal.view( frame_idx ) ); + attachments.emplace_back( *m_gbuffer_attachments.albedo.view( frame_idx ) ); + attachments.emplace_back( *m_gbuffer_attachments.composite.view( frame_idx ) ); + + //Fill attachments for this frame + const vk::Extent2D swapchain_extent { getSwapChainExtent() }; + vk::FramebufferCreateInfo framebufferInfo {}; + framebufferInfo.renderPass = m_render_pass; + framebufferInfo.attachmentCount = static_cast< uint32_t >( attachments.size() ); + framebufferInfo.pAttachments = attachments.data(); + framebufferInfo.width = swapchain_extent.width; + framebufferInfo.height = swapchain_extent.height; + framebufferInfo.layers = 1; + + temp.emplace_back( Device::getInstance()->createFramebuffer( framebufferInfo ) ); + } + + m_swap_chain_buffers.emplace_back( std::move( temp ) ); } } @@ -417,8 +443,8 @@ namespace fgl::engine ZoneScoped; imageAvailableSemaphores.reserve( MAX_FRAMES_IN_FLIGHT ); renderFinishedSemaphores.reserve( MAX_FRAMES_IN_FLIGHT ); - inFlightFences.reserve( MAX_FRAMES_IN_FLIGHT ); - imagesInFlight.resize( imageCount(), VK_NULL_HANDLE ); + in_flight_fences.reserve( MAX_FRAMES_IN_FLIGHT ); + images_in_flight.resize( imageCount(), VK_NULL_HANDLE ); vk::SemaphoreCreateInfo semaphoreInfo {}; @@ -431,31 +457,30 @@ namespace fgl::engine imageAvailableSemaphores.push_back( device->createSemaphore( semaphoreInfo ) ); renderFinishedSemaphores.push_back( device->createSemaphore( semaphoreInfo ) ); - inFlightFences.push_back( device->createFence( fenceInfo ) ); + in_flight_fences.push_back( device->createFence( fenceInfo ) ); } } vk::SurfaceFormatKHR SwapChain::chooseSwapSurfaceFormat( const std::vector< vk::SurfaceFormatKHR >& - availableFormats ) + available_formats ) { ZoneScoped; - for ( const auto& availableFormat : availableFormats ) + for ( const auto& format : available_formats ) { - if ( availableFormat.format == vk::Format::eB8G8R8A8Srgb - && availableFormat.colorSpace == vk::ColorSpaceKHR::eSrgbNonlinear ) + if ( format.format == vk::Format::eB8G8R8A8Srgb && format.colorSpace == vk::ColorSpaceKHR::eSrgbNonlinear ) { - return availableFormat; + return format; } } - return availableFormats[ 0 ]; + return available_formats[ 0 ]; } vk::PresentModeKHR SwapChain::chooseSwapPresentMode( const std::vector< vk::PresentModeKHR >& - availablePresentModes ) + available_present_modes ) { ZoneScoped; - for ( const auto& availablePresentMode : availablePresentModes ) + for ( const auto& availablePresentMode : available_present_modes ) { switch ( availablePresentMode ) { @@ -480,12 +505,12 @@ namespace fgl::engine } } - for ( const auto& availablePresentMode : availablePresentModes ) + for ( const auto& present_mode_khr : available_present_modes ) { - if ( availablePresentMode == vk::PresentModeKHR::eMailbox ) + if ( present_mode_khr == vk::PresentModeKHR::eMailbox ) { std::cout << "Present mode: Mailbox: ACTIVE" << std::endl; - return availablePresentMode; + return present_mode_khr; } } diff --git a/src/engine/rendering/SwapChain.hpp b/src/engine/rendering/SwapChain.hpp index 3740f27..e8a8e0b 100644 --- a/src/engine/rendering/SwapChain.hpp +++ b/src/engine/rendering/SwapChain.hpp @@ -6,8 +6,9 @@ #include #include "Device.hpp" -#include "RenderPass.hpp" +#include "RenderPassBuilder.hpp" #include "engine/FrameInfo.hpp" +#include "engine/rendering/types.hpp" #include "engine/texture/Texture.hpp" namespace fgl::engine @@ -16,43 +17,51 @@ namespace fgl::engine { public: - static constexpr std::uint16_t MAX_FRAMES_IN_FLIGHT = 2; + static constexpr FrameIndex MAX_FRAMES_IN_FLIGHT { 2 }; private: PhysicalDevice& m_phy_device; + std::shared_ptr< SwapChain > old_swap_chain {}; + + SwapChainSupportDetails m_swapchain_support; + vk::SurfaceFormatKHR m_surface_format; vk::Format m_swap_chain_format { vk::Format::eUndefined }; vk::Format m_swap_chain_depth_format { findDepthFormat() }; vk::Extent2D m_swap_chain_extent { 0, 0 }; - std::vector< vk::raii::Framebuffer > m_swap_chain_buffers {}; + std::vector< std::vector< vk::raii::Framebuffer > > m_swap_chain_buffers {}; vk::raii::RenderPass m_render_pass { VK_NULL_HANDLE }; - std::unique_ptr< RenderPassResources > m_render_pass_resources { nullptr }; std::vector< Image > m_swap_chain_images {}; vk::Extent2D windowExtent; vk::raii::SwapchainKHR swapChain { VK_NULL_HANDLE }; - std::shared_ptr< SwapChain > old_swap_chain {}; std::vector< vk::raii::Semaphore > imageAvailableSemaphores {}; std::vector< vk::raii::Semaphore > renderFinishedSemaphores {}; - std::vector< vk::raii::Fence > inFlightFences {}; - std::vector< vk::Fence > imagesInFlight {}; - size_t currentFrame { 0 }; + std::vector< vk::raii::Fence > in_flight_fences {}; + std::vector< vk::Fence > images_in_flight {}; + size_t current_frame_index { 0 }; std::vector< vk::ClearValue > m_clear_values {}; - public: + //! Attachments for the final render target + struct + { + ColoredPresentAttachment color; // Present attachment + DepthAttachment depth; + } m_render_attachments; - std::unique_ptr< Texture > g_buffer_position_img { nullptr }; - std::unique_ptr< Texture > g_buffer_normal_img { nullptr }; - std::unique_ptr< Texture > g_buffer_albedo_img { nullptr }; - std::unique_ptr< Texture > g_buffer_composite_img { nullptr }; - - private: + struct + { + ColorAttachment position { vk::Format::eR16G16B16A16Sfloat }; + ColorAttachment normal { vk::Format::eR16G16B16A16Sfloat }; + ColorAttachment albedo { vk::Format::eR8G8B8A8Unorm }; + ColorAttachment composite { vk::Format::eR8G8B8A8Unorm }; + } m_gbuffer_attachments {}; void init(); void createSwapChain(); @@ -60,9 +69,16 @@ namespace fgl::engine void createFramebuffers(); void createSyncObjects(); + template < is_attachment... Attachments > + void populateAttachmentClearValues( Attachments&... attachments ) + { + m_clear_values.resize( sizeof...( Attachments ) ); + ( ( m_clear_values[ attachments.getIndex() ] = attachments.m_clear_value ), ... ); + } + // Helper functions - vk::SurfaceFormatKHR chooseSwapSurfaceFormat( const std::vector< vk::SurfaceFormatKHR >& availableFormats ); - vk::PresentModeKHR chooseSwapPresentMode( const std::vector< vk::PresentModeKHR >& availablePresentModes ); + vk::SurfaceFormatKHR chooseSwapSurfaceFormat( const std::vector< vk::SurfaceFormatKHR >& available_formats ); + vk::PresentModeKHR chooseSwapPresentMode( const std::vector< vk::PresentModeKHR >& available_present_modes ); vk::Extent2D chooseSwapExtent( const vk::SurfaceCapabilitiesKHR& capabilities ); std::array< std::unique_ptr< descriptors::DescriptorSet >, SwapChain::MAX_FRAMES_IN_FLIGHT > @@ -97,16 +113,17 @@ namespace fgl::engine SwapChain( const SwapChain& ) = delete; SwapChain& operator=( const SwapChain& ) = delete; - vk::raii::Framebuffer& getFrameBuffer( std::uint32_t index ) - { - return m_swap_chain_buffers[ static_cast< std::size_t >( index ) ]; - } + vk::raii::Framebuffer& getFrameBuffer( const FrameIndex frame_index, const std::uint16_t present_idx ); vk::raii::RenderPass& getRenderPass() { return m_render_pass; } - std::uint16_t imageCount() const { return static_cast< std::uint16_t >( m_swap_chain_images.size() ); } + std::uint16_t imageCount() const { return m_swap_chain_images.size(); } - vk::Format getSwapChainImageFormat() const { return m_swap_chain_format; } + vk::Format getSwapChainImageFormat() const + { + assert( m_swap_chain_format != vk::Format::eUndefined ); + return m_swap_chain_format; + } vk::Extent2D getSwapChainExtent() const { return m_swap_chain_extent; } @@ -130,7 +147,7 @@ namespace fgl::engine [[nodiscard]] std::pair< vk::Result, std::uint32_t > acquireNextImage(); [[nodiscard]] vk::Result - submitCommandBuffers( const vk::raii::CommandBuffer& buffers, std::uint32_t imageIndex ); + submitCommandBuffers( const vk::raii::CommandBuffer& buffers, PresentIndex current_present_index ); }; } // namespace fgl::engine diff --git a/src/engine/rendering/types.hpp b/src/engine/rendering/types.hpp new file mode 100644 index 0000000..de13525 --- /dev/null +++ b/src/engine/rendering/types.hpp @@ -0,0 +1,11 @@ +// +// Created by kj16609 on 7/10/24. +// + +#pragma once + +namespace fgl::engine +{ + using FrameIndex = std::uint16_t; + using PresentIndex = std::uint16_t; +} // namespace fgl::engine