From 2fddf66153debd76e4e9238f445ad32999d5d4db Mon Sep 17 00:00:00 2001 From: kj16609 Date: Thu, 11 Jul 2024 00:55:22 -0400 Subject: [PATCH 1/5] Move swapchain init to ctor init --- src/engine/rendering/SwapChain.cpp | 179 ++++++++++++++++------------- src/engine/rendering/SwapChain.hpp | 54 ++++++--- 2 files changed, 131 insertions(+), 102 deletions(-) diff --git a/src/engine/rendering/SwapChain.cpp b/src/engine/rendering/SwapChain.cpp index 638b6ca..fdb285f 100644 --- a/src/engine/rendering/SwapChain.cpp +++ b/src/engine/rendering/SwapChain.cpp @@ -17,15 +17,32 @@ namespace fgl::engine SwapChain::SwapChain( vk::Extent2D extent, PhysicalDevice& phy_device ) : m_phy_device( phy_device ), - windowExtent( extent ) + m_swapchain_details( Device::getInstance().getSwapChainSupport() ), + m_surface_format( chooseSwapSurfaceFormat( m_swapchain_details.formats ) ), + m_present_mode( chooseSwapPresentMode( m_swapchain_details.presentModes ) ), + m_swapchain_extent( extent ), + m_swap_chain_format( m_surface_format.format ), + m_swap_chain_depth_format( findDepthFormat() ), + old_swap_chain( nullptr ), + m_swapchain( createSwapChain() ), + m_swap_chain_images( createSwapchainImages() ), + render_attachments( getSwapChainImageFormat(), findDepthFormat() ) { init(); } SwapChain::SwapChain( vk::Extent2D extent, std::shared_ptr< SwapChain > previous ) : m_phy_device( previous->m_phy_device ), - windowExtent( extent ), - old_swap_chain( previous ) + m_swapchain_details( Device::getInstance().getSwapChainSupport() ), + m_surface_format( chooseSwapSurfaceFormat( m_swapchain_details.formats ) ), + m_present_mode( chooseSwapPresentMode( m_swapchain_details.presentModes ) ), + m_swapchain_extent( extent ), + m_swap_chain_format( m_surface_format.format ), + m_swap_chain_depth_format( findDepthFormat() ), + old_swap_chain( previous ), + m_swapchain( createSwapChain() ), + m_swap_chain_images( createSwapchainImages() ), + render_attachments( getSwapChainImageFormat(), findDepthFormat() ) { init(); old_swap_chain.reset(); @@ -33,7 +50,6 @@ namespace fgl::engine void SwapChain::init() { - createSwapChain(); createRenderPass(); createFramebuffers(); createSyncObjects(); @@ -43,15 +59,15 @@ namespace fgl::engine { ZoneScoped; - std::vector< vk::Fence > fences { inFlightFences[ currentFrame ] }; + std::vector< vk::Fence > fences { in_flight_fence[ m_current_frame_index ] }; if ( Device::getInstance().device().waitForFences( fences, VK_TRUE, std::numeric_limits< uint64_t >::max() ) != vk::Result::eSuccess ) throw std::runtime_error( "failed to wait for fences!" ); - auto result { swapChain.acquireNextImage( + auto result { m_swapchain.acquireNextImage( std::numeric_limits< uint64_t >::max(), - imageAvailableSemaphores[ currentFrame ] // must be a not signaled semaphore + imageAvailableSemaphores[ m_current_frame_index ] // must be a not signaled semaphore ) }; return result; @@ -61,42 +77,42 @@ namespace fgl::engine { ZoneScoped; - imagesInFlight[ imageIndex ] = inFlightFences[ currentFrame ]; + images_in_flight[ imageIndex ] = in_flight_fence[ m_current_frame_index ]; - std::vector< vk::Fence > fences { imagesInFlight[ imageIndex ] }; + std::vector< vk::Fence > fences { images_in_flight[ imageIndex ] }; if ( Device::getInstance().device().waitForFences( fences, VK_TRUE, std::numeric_limits< uint64_t >::max() ) != vk::Result::eSuccess ) throw std::runtime_error( "failed to wait for fences!" ); - vk::SubmitInfo submitInfo {}; + vk::SubmitInfo m_submit_info {}; - std::vector< vk::Semaphore > wait_sems { imageAvailableSemaphores[ currentFrame ], + std::vector< vk::Semaphore > wait_sems { imageAvailableSemaphores[ m_current_frame_index ], memory::TransferManager::getInstance().getFinishedSem() }; std::vector< vk::PipelineStageFlags > wait_stages { vk::PipelineStageFlagBits::eColorAttachmentOutput, vk::PipelineStageFlagBits::eTopOfPipe }; - submitInfo.setWaitSemaphores( wait_sems ); - submitInfo.setWaitDstStageMask( wait_stages ); + m_submit_info.setWaitSemaphores( wait_sems ); + m_submit_info.setWaitDstStageMask( wait_stages ); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &( *buffers ); + m_submit_info.commandBufferCount = 1; + m_submit_info.pCommandBuffers = &( *buffers ); - std::vector< vk::Semaphore > signaled_semaphores { renderFinishedSemaphores[ currentFrame ] }; - submitInfo.setSignalSemaphores( signaled_semaphores ); + std::vector< vk::Semaphore > signaled_semaphores { renderFinishedSemaphores[ m_current_frame_index ] }; + m_submit_info.setSignalSemaphores( signaled_semaphores ); Device::getInstance().device().resetFences( fences ); - std::vector< vk::SubmitInfo > submit_infos { submitInfo }; + std::vector< vk::SubmitInfo > submit_infos { m_submit_info }; - Device::getInstance().graphicsQueue().submit( submitInfo, inFlightFences[ currentFrame ] ); + Device::getInstance().graphicsQueue().submit( m_submit_info, in_flight_fence[ m_current_frame_index ] ); vk::PresentInfoKHR presentInfo = {}; presentInfo.setWaitSemaphores( signaled_semaphores ); - std::vector< vk::SwapchainKHR > swapchains { swapChain }; + std::vector< vk::SwapchainKHR > swapchains { m_swapchain }; presentInfo.setSwapchains( swapchains ); std::array< std::uint32_t, 1 > indicies { { imageIndex } }; @@ -110,39 +126,34 @@ namespace fgl::engine throw std::runtime_error( "failed to present swap chain image!" ); } - currentFrame = ( currentFrame + 1 ) % MAX_FRAMES_IN_FLIGHT; + m_current_frame_index = ( m_current_frame_index + 1 ) % MAX_FRAMES_IN_FLIGHT; return vk::Result::eSuccess; } - void SwapChain::createSwapChain() + vk::raii::SwapchainKHR 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 ) }; - - uint32_t imageCount = swapChainSupport.capabilities.minImageCount + 1; - if ( swapChainSupport.capabilities.maxImageCount > 0 - && imageCount > swapChainSupport.capabilities.maxImageCount ) + std::uint32_t image_count { m_swapchain_details.capabilities.minImageCount + 1 }; + if ( m_swapchain_details.capabilities.maxImageCount > 0 + && image_count > m_swapchain_details.capabilities.maxImageCount ) { - imageCount = swapChainSupport.capabilities.maxImageCount; + image_count = m_swapchain_details.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.minImageCount = image_count; + createInfo.imageFormat = m_surface_format.format; + createInfo.imageColorSpace = m_surface_format.colorSpace; + createInfo.imageExtent = m_swapchain_extent; createInfo.imageArrayLayers = 1; createInfo.imageUsage = vk::ImageUsageFlagBits::eColorAttachment; - std::uint32_t graphics_family { m_phy_device.queueInfo().getIndex( vk::QueueFlagBits::eGraphics ) }; - std::uint32_t present_family { m_phy_device.queueInfo().getPresentIndex() }; + const std::uint32_t graphics_family { m_phy_device.queueInfo().getIndex( vk::QueueFlagBits::eGraphics ) }; + const std::uint32_t present_family { m_phy_device.queueInfo().getPresentIndex() }; const uint32_t queueFamilyIndices[] = { graphics_family, present_family }; @@ -161,35 +172,39 @@ namespace fgl::engine createInfo.pQueueFamilyIndices = nullptr; // Optional } - createInfo.preTransform = swapChainSupport.capabilities.currentTransform; + createInfo.preTransform = m_swapchain_details.capabilities.currentTransform; createInfo.compositeAlpha = vk::CompositeAlphaFlagBitsKHR::eOpaque; - createInfo.presentMode = presentMode; + createInfo.presentMode = m_present_mode; createInfo.clipped = VK_TRUE; - createInfo.oldSwapchain = old_swap_chain == nullptr ? VK_NULL_HANDLE : *old_swap_chain->swapChain; + createInfo.oldSwapchain = old_swap_chain == nullptr ? VK_NULL_HANDLE : *old_swap_chain->m_swapchain; - swapChain = Device::getInstance()->createSwapchainKHR( createInfo ); + return Device::getInstance()->createSwapchainKHR( createInfo ); + } - std::vector< vk::Image > swap_chain_images { swapChain.getImages() }; + std::vector< Image > SwapChain::createSwapchainImages() + { + std::vector< vk::Image > swap_chain_images { m_swapchain.getImages() }; + std::vector< Image > images {}; 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 = images.emplace_back( + m_swapchain_extent, + m_surface_format.format, + swap_chain_images[ i ], + vk::ImageUsageFlagBits::eColorAttachment ); itter.setName( "Swapchain image: " + std::to_string( i ) ); } - m_swap_chain_format = surfaceFormat.format; - m_swap_chain_extent = extent; + return images; } void SwapChain::createRenderPass() { ZoneScoped; //Present attachment - ColoredPresentAttachment colorAttachment { getSwapChainImageFormat() }; for ( int i = 0; i < imageCount(); ++i ) { @@ -198,41 +213,39 @@ namespace fgl::engine image.setName( "SwapChainImage: " + std::to_string( i ) ); } - colorAttachment.linkImages( m_swap_chain_images ); + render_attachments.color.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 }; + gbuffer.position.createResourceSpread( imageCount(), getSwapChainExtent(), vk::ImageUsageFlagBits::eSampled ); + gbuffer.normal.createResourceSpread( imageCount(), getSwapChainExtent(), vk::ImageUsageFlagBits::eSampled ); + gbuffer.albedo.createResourceSpread( imageCount(), getSwapChainExtent(), vk::ImageUsageFlagBits::eSampled ); + gbuffer.composite.createResourceSpread( imageCount(), getSwapChainExtent(), vk::ImageUsageFlagBits::eSampled ); - 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 ); + gbuffer.position.setClear( vk::ClearColorValue( std::array< float, 4 > { { 0.0f, 0.0f, 0.0f, 0.0f } } ) ); + gbuffer.normal.setClear( vk::ClearColorValue( std::array< float, 4 > { { 0.0f, 0.0f, 0.0f, 0.0f } } ) ); + gbuffer.albedo.setClear( vk::ClearColorValue( std::array< float, 4 > { { 0.0f, 0.0f, 0.0f, 0.0f } } ) ); + gbuffer.composite.setClear( vk::ClearColorValue( std::array< float, 4 > { { 0.0f, 0.0f, 0.0f, 0.0f } } ) ); - 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 ] + g_buffer_position_img = std::make_unique< Texture >( gbuffer.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 ] + g_buffer_normal_img = std::make_unique< Texture >( gbuffer.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 ] + g_buffer_albedo_img = std::make_unique< Texture >( gbuffer.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 ] + g_buffer_composite_img = std::make_unique< Texture >( gbuffer.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_attachments.depth.createResources( imageCount(), getSwapChainExtent() ); + render_attachments.depth.setClear( vk::ClearDepthStencilValue( 1.0f, 0 ) ); render_pass.registerAttachments( - colorAttachment, depthAttachment, g_buffer_position, g_buffer_normal, g_buffer_albedo, g_buffer_composite ); + render_attachments.color, + render_attachments.depth, + gbuffer.position, + gbuffer.normal, + gbuffer.albedo, + gbuffer.composite ); for ( int i = 0; i < SwapChain::MAX_FRAMES_IN_FLIGHT; ++i ) { @@ -243,17 +256,17 @@ namespace fgl::engine set->bindAttachment( 0, - *( g_buffer_position.resources().m_image_views[ i ].get() ), + *( gbuffer.position.resources().m_image_views[ i ].get() ), vk::ImageLayout::eShaderReadOnlyOptimal ); set->bindAttachment( 1, - *( g_buffer_normal.resources().m_image_views[ i ].get() ), + *( gbuffer.normal.resources().m_image_views[ i ].get() ), vk::ImageLayout::eShaderReadOnlyOptimal ); set->bindAttachment( 2, - *( g_buffer_albedo.resources().m_image_views[ i ].get() ), + *( gbuffer.albedo.resources().m_image_views[ i ].get() ), vk::ImageLayout::eShaderReadOnlyOptimal ); set->update(); @@ -266,10 +279,10 @@ namespace fgl::engine std::make_unique< descriptors::DescriptorSet >( GBufferCompositeDescriptorSet::createLayout() ) }; - composite_set->setMaxIDX( 2 ); + composite_set->setMaxIDX( 1 ); composite_set->bindAttachment( 0, - *( g_buffer_composite.resources().m_image_views[ 0 ].get() ), + *( gbuffer.composite.resources().m_image_views[ i ].get() ), vk::ImageLayout::eShaderReadOnlyOptimal ); composite_set->update(); @@ -287,7 +300,7 @@ 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, render_attachments.depth, gbuffer.position, gbuffer.normal, gbuffer.albedo }; g_buffer_subpass.registerDependencyFromExternal( vk::AccessFlagBits::eDepthStencilAttachmentWrite, @@ -304,7 +317,7 @@ namespace fgl::engine 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 + 1, render_attachments.depth, gbuffer.composite, gbuffer.position, gbuffer.normal, gbuffer.albedo }; composite_subpass.registerDependencyFromExternal( @@ -344,7 +357,7 @@ namespace fgl::engine 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, render_attachments.depth, render_attachments.color, gbuffer.composite }; gui_subpass.registerDependencyFromExternal( vk::AccessFlagBits::eColorAttachmentWrite, vk::PipelineStageFlagBits::eColorAttachmentOutput ); @@ -417,8 +430,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_fence.reserve( MAX_FRAMES_IN_FLIGHT ); + images_in_flight.resize( imageCount(), VK_NULL_HANDLE ); vk::SemaphoreCreateInfo semaphoreInfo {}; @@ -431,7 +444,7 @@ namespace fgl::engine imageAvailableSemaphores.push_back( device->createSemaphore( semaphoreInfo ) ); renderFinishedSemaphores.push_back( device->createSemaphore( semaphoreInfo ) ); - inFlightFences.push_back( device->createFence( fenceInfo ) ); + in_flight_fence.push_back( device->createFence( fenceInfo ) ); } } @@ -509,7 +522,7 @@ namespace fgl::engine } else { - vk::Extent2D actualExtent = windowExtent; + vk::Extent2D actualExtent = m_swapchain_extent; actualExtent.width = std:: max( capabilities.minImageExtent.width, std::min( capabilities.maxImageExtent.width, actualExtent.width ) ); diff --git a/src/engine/rendering/SwapChain.hpp b/src/engine/rendering/SwapChain.hpp index 3740f27..002d7c1 100644 --- a/src/engine/rendering/SwapChain.hpp +++ b/src/engine/rendering/SwapChain.hpp @@ -22,26 +22,42 @@ namespace fgl::engine PhysicalDevice& m_phy_device; - 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 }; + SwapChainSupportDetails m_swapchain_details; + vk::SurfaceFormatKHR m_surface_format; + vk::PresentModeKHR m_present_mode; + vk::Extent2D m_swapchain_extent; + + vk::Format m_swap_chain_format; + vk::Format m_swap_chain_depth_format; + + std::shared_ptr< SwapChain > old_swap_chain; + + vk::raii::SwapchainKHR m_swapchain; + std::vector< Image > m_swap_chain_images; + + struct + { + ColoredPresentAttachment color; + DepthAttachment depth; + } render_attachments; + + struct + { + ColorAttachment position { vk::Format::eR16G16B16A16Sfloat }; + ColorAttachment normal { vk::Format::eR16G16B16A16Sfloat }; + ColorAttachment albedo { vk::Format::eR8G8B8A8Unorm }; + ColorAttachment composite { vk::Format::eR8G8B8A8Unorm }; + } gbuffer {}; 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_fence {}; + std::vector< vk::Fence > images_in_flight {}; + size_t m_current_frame_index { 0 }; std::vector< vk::ClearValue > m_clear_values {}; @@ -55,7 +71,8 @@ namespace fgl::engine private: void init(); - void createSwapChain(); + [[nodiscard]] vk::raii::SwapchainKHR createSwapChain(); + [[nodiscard]] std::vector< Image > createSwapchainImages(); void createRenderPass(); void createFramebuffers(); void createSyncObjects(); @@ -108,11 +125,11 @@ namespace fgl::engine vk::Format getSwapChainImageFormat() const { return m_swap_chain_format; } - vk::Extent2D getSwapChainExtent() const { return m_swap_chain_extent; } + vk::Extent2D getSwapChainExtent() const { return m_swapchain_extent; } - uint32_t width() const { return m_swap_chain_extent.width; } + uint32_t width() const { return m_swapchain_extent.width; } - uint32_t height() const { return m_swap_chain_extent.height; } + uint32_t height() const { return m_swapchain_extent.height; } bool compareSwapFormats( const SwapChain& other ) const { @@ -122,8 +139,7 @@ namespace fgl::engine float extentAspectRatio() const { - return static_cast< float >( m_swap_chain_extent.width ) - / static_cast< float >( m_swap_chain_extent.height ); + return static_cast< float >( m_swapchain_extent.width ) / static_cast< float >( m_swapchain_extent.height ); } vk::Format findDepthFormat(); From 21268f2d4df605a6c75f5fa76785aaa787abb8a3 Mon Sep 17 00:00:00 2001 From: kj16609 Date: Thu, 11 Jul 2024 01:32:57 -0400 Subject: [PATCH 2/5] Rework swapchain to no longer init inside of ctor body --- src/engine/concepts/is_attachment.hpp | 4 +- src/engine/rendering/Attachment.hpp | 9 +- src/engine/rendering/RenderPass.hpp | 103 -------- .../{RenderPass.cpp => RenderPassBuilder.cpp} | 5 +- src/engine/rendering/RenderPassBuilder.hpp | 52 ++++ src/engine/rendering/Subpass.hpp | 2 +- src/engine/rendering/SwapChain.cpp | 236 +++++++++--------- src/engine/rendering/SwapChain.hpp | 65 +++-- 8 files changed, 233 insertions(+), 243 deletions(-) delete mode 100644 src/engine/rendering/RenderPass.hpp rename src/engine/rendering/{RenderPass.cpp => RenderPassBuilder.cpp} (88%) create mode 100644 src/engine/rendering/RenderPassBuilder.hpp diff --git a/src/engine/concepts/is_attachment.hpp b/src/engine/concepts/is_attachment.hpp index 0c0d998..a8edbe6 100644 --- a/src/engine/concepts/is_attachment.hpp +++ b/src/engine/concepts/is_attachment.hpp @@ -30,8 +30,8 @@ namespace fgl::engine a.linkImage( std::declval< std::uint16_t >(), std::declval< Image& >() ) }; { - a.resources() - } -> std::same_as< AttachmentResources >; + a.getView( std::declval< std::uint8_t >() ) + } -> std::same_as< ImageView& >; { a.m_clear_value } -> std::same_as< vk::ClearValue& >; diff --git a/src/engine/rendering/Attachment.hpp b/src/engine/rendering/Attachment.hpp index 3588e94..b145c31 100644 --- a/src/engine/rendering/Attachment.hpp +++ b/src/engine/rendering/Attachment.hpp @@ -76,6 +76,7 @@ namespace fgl::engine void linkImages( std::vector< Image >& images ) { + assert( images.size() > 0 ); for ( std::uint16_t i = 0; i < images.size(); ++i ) { linkImage( i, images[ i ] ); @@ -115,7 +116,11 @@ namespace fgl::engine } } - AttachmentResources resources() { return m_attachment_resources; } + ImageView& getView( std::uint8_t frame_idx ) + { + assert( frame_idx < m_attachment_resources.m_image_views.size() ); + return *m_attachment_resources.m_image_views[ frame_idx ]; + } vk::AttachmentDescription& desc() { return description; } @@ -127,7 +132,7 @@ namespace fgl::engine return index; } - friend class RenderPass; + friend class RenderPassBuilder; }; template < is_attachment AttachmentT, vk::ImageLayout layout > diff --git a/src/engine/rendering/RenderPass.hpp b/src/engine/rendering/RenderPass.hpp deleted file mode 100644 index b60e802..0000000 --- a/src/engine/rendering/RenderPass.hpp +++ /dev/null @@ -1,103 +0,0 @@ -// -// Created by kj16609 on 12/30/23. -// - -#pragma once - -#include "Subpass.hpp" -#include "engine/image/ImageView.hpp" - -namespace fgl::engine -{ - - struct RenderPassResources - { - std::vector< std::vector< std::shared_ptr< ImageView > > > m_image_views; - - RenderPassResources() = delete; - RenderPassResources( const RenderPassResources& ) = delete; - - RenderPassResources( std::vector< std::vector< std::shared_ptr< ImageView > > >&& image_views ) : - m_image_views( std::move( image_views ) ) - {} - - std::vector< vk::ImageView > forFrame( std::uint32_t frame ) const - { - std::vector< vk::ImageView > views; - - for ( auto& view : m_image_views.at( frame ) ) views.push_back( view->getVkView() ); - - return views; - } - }; - - class RenderPass - { - std::vector< vk::AttachmentDescription > attachment_descriptions {}; - std::vector< vk::ClearValue > m_clear_values {}; - - std::vector< vk::SubpassDescription > subpass_descriptions {}; - std::vector< vk::SubpassDependency > dependencies {}; - - std::vector< AttachmentResources > m_attachment_resources {}; - - public: - - std::vector< vk::ClearValue > getClearValues() const { return m_clear_values; } - - template < typename SubpassT > - requires is_subpass< SubpassT > - void registerSubpass( SubpassT& subpass ) - { - subpass_descriptions.emplace_back( subpass.description() ); - - for ( auto& dependency : subpass.dependencies ) - { - dependencies.push_back( dependency ); - } - } - - template < is_attachment... Attachments > - void registerAttachments( Attachments&... attachments ) - { - attachment_descriptions.reserve( sizeof...( Attachments ) ); - m_clear_values.reserve( sizeof...( Attachments ) ); - - ( ( attachments.setIndex( static_cast< std::uint32_t >( attachment_descriptions.size() ) ), - 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 ) - { - assert( m_attachment_resources.size() > 0 && "Must register attachments before getting resources" ); - - //Each attachment will have a vector of image views, one for each frame - // We need to seperate them out so that we have a vector of image views for each frame - std::vector< std::vector< std::shared_ptr< ImageView > > > views; - - views.resize( frame_count ); - - for ( auto& attachment : m_attachment_resources ) - { - assert( - attachment.m_image_views.size() == frame_count - && "Attachment image views must be equal to frame count" ); - for ( std::uint16_t frame_idx = 0; frame_idx < attachment.m_image_views.size(); ++frame_idx ) - { - views[ frame_idx ].emplace_back( attachment.m_image_views[ frame_idx ] ); - } - } - - return std::make_unique< RenderPassResources >( std::move( views ) ); - } - - vk::raii::RenderPass create(); - }; - -} // 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/RenderPassBuilder.hpp b/src/engine/rendering/RenderPassBuilder.hpp new file mode 100644 index 0000000..a8aa15b --- /dev/null +++ b/src/engine/rendering/RenderPassBuilder.hpp @@ -0,0 +1,52 @@ +// +// Created by kj16609 on 12/30/23. +// + +#pragma once + +#include "Subpass.hpp" +#include "engine/image/ImageView.hpp" + +namespace fgl::engine +{ + + class RenderPassBuilder + { + std::vector< vk::AttachmentDescription > attachment_descriptions {}; + std::vector< vk::ClearValue > m_clear_values {}; + + std::vector< vk::SubpassDescription > subpass_descriptions {}; + std::vector< vk::SubpassDependency > dependencies {}; + + public: + + std::vector< vk::ClearValue > getClearValues() const { return m_clear_values; } + + template < typename SubpassT > + requires is_subpass< SubpassT > + void registerSubpass( SubpassT& subpass ) + { + subpass_descriptions.emplace_back( subpass.description() ); + + for ( auto& dependency : subpass.dependencies ) + { + dependencies.push_back( dependency ); + } + } + + template < is_attachment... Attachments > + void registerAttachments( Attachments&... attachments ) + { + attachment_descriptions.reserve( sizeof...( Attachments ) ); + m_clear_values.reserve( sizeof...( Attachments ) ); + + ( ( attachments.setIndex( static_cast< std::uint32_t >( attachment_descriptions.size() ) ), + attachment_descriptions.push_back( attachments.desc() ), + m_clear_values.push_back( attachments.m_clear_value ) ), + ... ); + } + + vk::raii::RenderPass create(); + }; + +} // namespace fgl::engine \ No newline at end of file diff --git a/src/engine/rendering/Subpass.hpp b/src/engine/rendering/Subpass.hpp index b0d6705..5b0218f 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, diff --git a/src/engine/rendering/SwapChain.cpp b/src/engine/rendering/SwapChain.cpp index fdb285f..54dd65c 100644 --- a/src/engine/rendering/SwapChain.cpp +++ b/src/engine/rendering/SwapChain.cpp @@ -8,7 +8,7 @@ #include #include "Attachment.hpp" -#include "RenderPass.hpp" +#include "RenderPassBuilder.hpp" #include "Subpass.hpp" #include "engine/assets/TransferManager.hpp" @@ -26,7 +26,18 @@ namespace fgl::engine old_swap_chain( nullptr ), m_swapchain( createSwapChain() ), m_swap_chain_images( createSwapchainImages() ), - render_attachments( getSwapChainImageFormat(), findDepthFormat() ) + render_attachments( getSwapChainImageFormat(), findDepthFormat() ), + m_render_pass( createRenderPass() ), + m_swap_chain_buffers( createFramebuffers() ), + m_clear_values( gatherClearValues( + render_attachments.color, + render_attachments.depth, + gbuffer.position, + gbuffer.normal, + gbuffer.albedo, + gbuffer.composite ) ), + m_gbuffer_descriptor_set( createGBufferDescriptors() ), + m_gbuffer_composite_descriptor_set( createCompositeDescriptors() ) { init(); } @@ -42,7 +53,18 @@ namespace fgl::engine old_swap_chain( previous ), m_swapchain( createSwapChain() ), m_swap_chain_images( createSwapchainImages() ), - render_attachments( getSwapChainImageFormat(), findDepthFormat() ) + render_attachments( getSwapChainImageFormat(), findDepthFormat() ), + m_render_pass( createRenderPass() ), + m_swap_chain_buffers( createFramebuffers() ), + m_clear_values( gatherClearValues( + render_attachments.color, + render_attachments.depth, + gbuffer.position, + gbuffer.normal, + gbuffer.albedo, + gbuffer.composite ) ), + m_gbuffer_descriptor_set( createGBufferDescriptors() ), + m_gbuffer_composite_descriptor_set( createCompositeDescriptors() ) { init(); old_swap_chain.reset(); @@ -50,8 +72,6 @@ namespace fgl::engine void SwapChain::init() { - createRenderPass(); - createFramebuffers(); createSyncObjects(); } @@ -67,7 +87,7 @@ namespace fgl::engine auto result { m_swapchain.acquireNextImage( std::numeric_limits< uint64_t >::max(), - imageAvailableSemaphores[ m_current_frame_index ] // must be a not signaled semaphore + image_available_sem[ m_current_frame_index ] // must be a not signaled semaphore ) }; return result; @@ -87,7 +107,7 @@ namespace fgl::engine vk::SubmitInfo m_submit_info {}; - std::vector< vk::Semaphore > wait_sems { imageAvailableSemaphores[ m_current_frame_index ], + std::vector< vk::Semaphore > wait_sems { image_available_sem[ m_current_frame_index ], memory::TransferManager::getInstance().getFinishedSem() }; std::vector< vk::PipelineStageFlags > wait_stages { vk::PipelineStageFlagBits::eColorAttachmentOutput, @@ -99,7 +119,7 @@ namespace fgl::engine m_submit_info.commandBufferCount = 1; m_submit_info.pCommandBuffers = &( *buffers ); - std::vector< vk::Semaphore > signaled_semaphores { renderFinishedSemaphores[ m_current_frame_index ] }; + std::vector< vk::Semaphore > signaled_semaphores { render_finished_sem[ m_current_frame_index ] }; m_submit_info.setSignalSemaphores( signaled_semaphores ); Device::getInstance().device().resetFences( fences ); @@ -201,45 +221,18 @@ namespace fgl::engine return images; } - void SwapChain::createRenderPass() + vk::raii::RenderPass SwapChain::createRenderPass() { ZoneScoped; //Present attachment - for ( int i = 0; i < imageCount(); ++i ) - { - auto& image { m_swap_chain_images[ i ] }; - - image.setName( "SwapChainImage: " + std::to_string( i ) ); - } - - render_attachments.color.linkImages( m_swap_chain_images ); - - gbuffer.position.createResourceSpread( imageCount(), getSwapChainExtent(), vk::ImageUsageFlagBits::eSampled ); - gbuffer.normal.createResourceSpread( imageCount(), getSwapChainExtent(), vk::ImageUsageFlagBits::eSampled ); - gbuffer.albedo.createResourceSpread( imageCount(), getSwapChainExtent(), vk::ImageUsageFlagBits::eSampled ); - gbuffer.composite.createResourceSpread( imageCount(), getSwapChainExtent(), vk::ImageUsageFlagBits::eSampled ); - + render_attachments.depth.setClear( vk::ClearDepthStencilValue( 1.0f, 0 ) ); gbuffer.position.setClear( vk::ClearColorValue( std::array< float, 4 > { { 0.0f, 0.0f, 0.0f, 0.0f } } ) ); gbuffer.normal.setClear( vk::ClearColorValue( std::array< float, 4 > { { 0.0f, 0.0f, 0.0f, 0.0f } } ) ); gbuffer.albedo.setClear( vk::ClearColorValue( std::array< float, 4 > { { 0.0f, 0.0f, 0.0f, 0.0f } } ) ); gbuffer.composite.setClear( vk::ClearColorValue( std::array< float, 4 > { { 0.0f, 0.0f, 0.0f, 0.0f } } ) ); - g_buffer_position_img = std::make_unique< Texture >( gbuffer.position.m_attachment_resources.m_images[ 0 ] - ->setName( "GBufferPosition" ) ); - g_buffer_normal_img = std::make_unique< Texture >( gbuffer.normal.m_attachment_resources.m_images[ 0 ] - ->setName( "GBufferNormal" ) ); - g_buffer_albedo_img = std::make_unique< Texture >( gbuffer.albedo.m_attachment_resources.m_images[ 0 ] - ->setName( "GBufferAlbedo" ) ); - g_buffer_composite_img = std::make_unique< Texture >( gbuffer.composite.m_attachment_resources.m_images[ 0 ] - ->setName( "GBufferComposite" ) ); - - RenderPass render_pass {}; - - render_attachments.depth.createResources( imageCount(), getSwapChainExtent() ); - render_attachments.depth.setClear( vk::ClearDepthStencilValue( 1.0f, 0 ) ); - - render_pass.registerAttachments( + render_pass_builder.registerAttachments( render_attachments.color, render_attachments.depth, gbuffer.position, @@ -247,50 +240,6 @@ namespace fgl::engine gbuffer.albedo, gbuffer.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, - *( gbuffer.position.resources().m_image_views[ i ].get() ), - vk::ImageLayout::eShaderReadOnlyOptimal ); - - set->bindAttachment( - 1, - *( gbuffer.normal.resources().m_image_views[ i ].get() ), - vk::ImageLayout::eShaderReadOnlyOptimal ); - - set->bindAttachment( - 2, - *( gbuffer.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( 1 ); - composite_set->bindAttachment( - 0, - *( gbuffer.composite.resources().m_image_views[ i ].get() ), - vk::ImageLayout::eShaderReadOnlyOptimal ); - - composite_set->update(); - - m_gbuffer_composite_descriptor_set[ i ] = std::move( composite_set ); - } - } - static_assert( is_attachment< ColoredPresentAttachment > ); static_assert( is_attachment< DepthAttachment > ); @@ -341,16 +290,6 @@ 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, @@ -362,10 +301,6 @@ namespace fgl::engine gui_subpass.registerDependencyFromExternal( vk::AccessFlagBits::eColorAttachmentWrite, vk::PipelineStageFlagBits::eColorAttachmentOutput ); - /* - g_buffer_subpass -> composite_subpass -> gui_subpass - */ - gui_subpass.registerDependencyFrom( composite_subpass, vk::AccessFlagBits::eColorAttachmentWrite, @@ -374,9 +309,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, @@ -392,24 +324,51 @@ 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_clear_values = render_pass_builder.getClearValues(); - m_render_pass_resources = render_pass.resources( imageCount() ); - m_clear_values = render_pass.getClearValues(); + return render_pass_builder.create(); } - void SwapChain::createFramebuffers() + std::vector< vk::raii::Framebuffer > SwapChain::createFramebuffers() { ZoneScoped; - m_swap_chain_buffers.clear(); - m_swap_chain_buffers.reserve( imageCount() ); + + render_attachments.depth.createResources( imageCount(), getSwapChainExtent() ); + + render_attachments.color.linkImages( m_swap_chain_images ); + + gbuffer.position.createResourceSpread( imageCount(), getSwapChainExtent(), vk::ImageUsageFlagBits::eSampled ); + gbuffer.normal.createResourceSpread( imageCount(), getSwapChainExtent(), vk::ImageUsageFlagBits::eSampled ); + gbuffer.albedo.createResourceSpread( imageCount(), getSwapChainExtent(), vk::ImageUsageFlagBits::eSampled ); + gbuffer.composite.createResourceSpread( imageCount(), getSwapChainExtent(), vk::ImageUsageFlagBits::eSampled ); + + g_buffer_position_img = std::make_unique< Texture >( gbuffer.position.m_attachment_resources.m_images[ 0 ] + ->setName( "GBufferPosition" ) ); + g_buffer_normal_img = std::make_unique< Texture >( gbuffer.normal.m_attachment_resources.m_images[ 0 ] + ->setName( "GBufferNormal" ) ); + g_buffer_albedo_img = std::make_unique< Texture >( gbuffer.albedo.m_attachment_resources.m_images[ 0 ] + ->setName( "GBufferAlbedo" ) ); + g_buffer_composite_img = std::make_unique< Texture >( gbuffer.composite.m_attachment_resources.m_images[ 0 ] + ->setName( "GBufferComposite" ) ); + + std::vector< vk::raii::Framebuffer > framebuffers {}; + + framebuffers.reserve( imageCount() ); + for ( uint8_t i = 0; i < imageCount(); i++ ) { - std::vector< vk::ImageView > attachments { m_render_pass_resources->forFrame( i ) }; + std::vector< vk::ImageView > attachments { getViewsForFrame( + i, + render_attachments.color, + render_attachments.depth, + gbuffer.position, + gbuffer.normal, + gbuffer.albedo, + gbuffer.composite ) }; //Fill attachments for this frame const vk::Extent2D swapChainExtent { getSwapChainExtent() }; @@ -421,15 +380,17 @@ namespace fgl::engine framebufferInfo.height = swapChainExtent.height; framebufferInfo.layers = 1; - m_swap_chain_buffers.push_back( Device::getInstance()->createFramebuffer( framebufferInfo ) ); + framebuffers.push_back( Device::getInstance()->createFramebuffer( framebufferInfo ) ); } + + return framebuffers; } void SwapChain::createSyncObjects() { ZoneScoped; - imageAvailableSemaphores.reserve( MAX_FRAMES_IN_FLIGHT ); - renderFinishedSemaphores.reserve( MAX_FRAMES_IN_FLIGHT ); + image_available_sem.reserve( MAX_FRAMES_IN_FLIGHT ); + render_finished_sem.reserve( MAX_FRAMES_IN_FLIGHT ); in_flight_fence.reserve( MAX_FRAMES_IN_FLIGHT ); images_in_flight.resize( imageCount(), VK_NULL_HANDLE ); @@ -442,8 +403,8 @@ namespace fgl::engine { auto& device { Device::getInstance() }; - imageAvailableSemaphores.push_back( device->createSemaphore( semaphoreInfo ) ); - renderFinishedSemaphores.push_back( device->createSemaphore( semaphoreInfo ) ); + image_available_sem.push_back( device->createSemaphore( semaphoreInfo ) ); + render_finished_sem.push_back( device->createSemaphore( semaphoreInfo ) ); in_flight_fence.push_back( device->createFence( fenceInfo ) ); } } @@ -534,6 +495,53 @@ namespace fgl::engine } } + std::array< std::unique_ptr< descriptors::DescriptorSet >, SwapChain::MAX_FRAMES_IN_FLIGHT > SwapChain:: + createGBufferDescriptors() + { + std::array< std::unique_ptr< descriptors::DescriptorSet >, SwapChain::MAX_FRAMES_IN_FLIGHT > data; + + 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, gbuffer.position.getView( i ), vk::ImageLayout::eShaderReadOnlyOptimal ); + + set->bindAttachment( 1, gbuffer.normal.getView( i ), vk::ImageLayout::eShaderReadOnlyOptimal ); + + set->bindAttachment( 2, gbuffer.albedo.getView( i ), vk::ImageLayout::eShaderReadOnlyOptimal ); + + set->update(); + + data[ i ] = std::move( set ); + } + + return data; + } + + std::array< std::unique_ptr< descriptors::DescriptorSet >, SwapChain::MAX_FRAMES_IN_FLIGHT > SwapChain:: + createCompositeDescriptors() + { + std::array< std::unique_ptr< descriptors::DescriptorSet >, SwapChain::MAX_FRAMES_IN_FLIGHT > data; + + for ( int i = 0; i < SwapChain::MAX_FRAMES_IN_FLIGHT; ++i ) + { + auto composite_set { + std::make_unique< descriptors::DescriptorSet >( GBufferCompositeDescriptorSet::createLayout() ) + }; + + composite_set->setMaxIDX( 1 ); + composite_set->bindAttachment( 0, gbuffer.composite.getView( i ), vk::ImageLayout::eShaderReadOnlyOptimal ); + + composite_set->update(); + + data[ i ] = std::move( composite_set ); + } + + return data; + } + vk::Format SwapChain::findDepthFormat() { ZoneScoped; diff --git a/src/engine/rendering/SwapChain.hpp b/src/engine/rendering/SwapChain.hpp index 002d7c1..11d3653 100644 --- a/src/engine/rendering/SwapChain.hpp +++ b/src/engine/rendering/SwapChain.hpp @@ -6,7 +6,7 @@ #include #include "Device.hpp" -#include "RenderPass.hpp" +#include "RenderPassBuilder.hpp" #include "engine/FrameInfo.hpp" #include "engine/texture/Texture.hpp" @@ -49,18 +49,6 @@ namespace fgl::engine ColorAttachment composite { vk::Format::eR8G8B8A8Unorm }; } gbuffer {}; - 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< vk::raii::Semaphore > imageAvailableSemaphores {}; - std::vector< vk::raii::Semaphore > renderFinishedSemaphores {}; - std::vector< vk::raii::Fence > in_flight_fence {}; - std::vector< vk::Fence > images_in_flight {}; - size_t m_current_frame_index { 0 }; - - std::vector< vk::ClearValue > m_clear_values {}; - public: std::unique_ptr< Texture > g_buffer_position_img { nullptr }; @@ -70,11 +58,31 @@ namespace fgl::engine private: + RenderPassBuilder render_pass_builder {}; + + vk::raii::RenderPass m_render_pass; + + std::vector< vk::raii::Framebuffer > m_swap_chain_buffers; + + std::vector< vk::ClearValue > m_clear_values; + + std::array< std::unique_ptr< descriptors::DescriptorSet >, SwapChain::MAX_FRAMES_IN_FLIGHT > + m_gbuffer_descriptor_set; + + std::array< std::unique_ptr< descriptors::DescriptorSet >, SwapChain::MAX_FRAMES_IN_FLIGHT > + m_gbuffer_composite_descriptor_set; + + std::vector< vk::raii::Semaphore > image_available_sem {}; + std::vector< vk::raii::Semaphore > render_finished_sem {}; + std::vector< vk::raii::Fence > in_flight_fence {}; + std::vector< vk::Fence > images_in_flight {}; + size_t m_current_frame_index { 0 }; + void init(); [[nodiscard]] vk::raii::SwapchainKHR createSwapChain(); [[nodiscard]] std::vector< Image > createSwapchainImages(); - void createRenderPass(); - void createFramebuffers(); + [[nodiscard]] vk::raii::RenderPass createRenderPass(); + [[nodiscard]] std::vector< vk::raii::Framebuffer > createFramebuffers(); void createSyncObjects(); // Helper functions @@ -82,11 +90,32 @@ namespace fgl::engine vk::PresentModeKHR chooseSwapPresentMode( const std::vector< vk::PresentModeKHR >& availablePresentModes ); vk::Extent2D chooseSwapExtent( const vk::SurfaceCapabilitiesKHR& capabilities ); - std::array< std::unique_ptr< descriptors::DescriptorSet >, SwapChain::MAX_FRAMES_IN_FLIGHT > - m_gbuffer_descriptor_set {}; + template < is_attachment... Attachments > + static std::vector< vk::ImageView > getViewsForFrame( const std::uint8_t frame_idx, Attachments... attachments ) + { + std::vector< vk::ImageView > view {}; + view.resize( sizeof...( Attachments ) ); + + ( ( view[ attachments.getIndex() ] = *attachments.getView( frame_idx ) ), ... ); + + return view; + } + + template < is_attachment... Attachments > + static std::vector< vk::ClearValue > gatherClearValues( Attachments... attachments ) + { + std::vector< vk::ClearValue > clear_values {}; + clear_values.resize( sizeof...( Attachments ) ); + + ( ( clear_values[ attachments.getIndex() ] = attachments.m_clear_value ), ... ); + + return clear_values; + } std::array< std::unique_ptr< descriptors::DescriptorSet >, SwapChain::MAX_FRAMES_IN_FLIGHT > - m_gbuffer_composite_descriptor_set {}; + createGBufferDescriptors(); + std::array< std::unique_ptr< descriptors::DescriptorSet >, SwapChain::MAX_FRAMES_IN_FLIGHT > + createCompositeDescriptors(); public: From f1c31dbea7afd9c85deb61d1c10cbd579f92e899 Mon Sep 17 00:00:00 2001 From: kj16609 Date: Thu, 11 Jul 2024 01:41:48 -0400 Subject: [PATCH 3/5] More code cleanup --- src/engine/rendering/SwapChain.cpp | 75 ++++++++++++++---------------- src/engine/rendering/SwapChain.hpp | 8 ++-- 2 files changed, 38 insertions(+), 45 deletions(-) diff --git a/src/engine/rendering/SwapChain.cpp b/src/engine/rendering/SwapChain.cpp index 54dd65c..2907acc 100644 --- a/src/engine/rendering/SwapChain.cpp +++ b/src/engine/rendering/SwapChain.cpp @@ -226,12 +226,6 @@ namespace fgl::engine ZoneScoped; //Present attachment - render_attachments.depth.setClear( vk::ClearDepthStencilValue( 1.0f, 0 ) ); - gbuffer.position.setClear( vk::ClearColorValue( std::array< float, 4 > { { 0.0f, 0.0f, 0.0f, 0.0f } } ) ); - gbuffer.normal.setClear( vk::ClearColorValue( std::array< float, 4 > { { 0.0f, 0.0f, 0.0f, 0.0f } } ) ); - gbuffer.albedo.setClear( vk::ClearColorValue( std::array< float, 4 > { { 0.0f, 0.0f, 0.0f, 0.0f } } ) ); - gbuffer.composite.setClear( vk::ClearColorValue( std::array< float, 4 > { { 0.0f, 0.0f, 0.0f, 0.0f } } ) ); - render_pass_builder.registerAttachments( render_attachments.color, render_attachments.depth, @@ -337,21 +331,28 @@ namespace fgl::engine { ZoneScoped; - render_attachments.depth.createResources( imageCount(), getSwapChainExtent() ); - render_attachments.color.linkImages( m_swap_chain_images ); - gbuffer.position.createResourceSpread( imageCount(), getSwapChainExtent(), vk::ImageUsageFlagBits::eSampled ); - gbuffer.normal.createResourceSpread( imageCount(), getSwapChainExtent(), vk::ImageUsageFlagBits::eSampled ); - gbuffer.albedo.createResourceSpread( imageCount(), getSwapChainExtent(), vk::ImageUsageFlagBits::eSampled ); - gbuffer.composite.createResourceSpread( imageCount(), getSwapChainExtent(), vk::ImageUsageFlagBits::eSampled ); + render_attachments.depth.createResources( imageCount(), getSwapChainExtent() ); + render_attachments.depth.setClear( vk::ClearDepthStencilValue( 1.0f, 0 ) ); + gbuffer.position.createResourceSpread( imageCount(), getSwapChainExtent(), vk::ImageUsageFlagBits::eSampled ); + gbuffer.position.setClear( vk::ClearColorValue( std::array< float, 4 > { { 0.0f, 0.0f, 0.0f, 0.0f } } ) ); g_buffer_position_img = std::make_unique< Texture >( gbuffer.position.m_attachment_resources.m_images[ 0 ] ->setName( "GBufferPosition" ) ); + + gbuffer.normal.createResourceSpread( imageCount(), getSwapChainExtent(), vk::ImageUsageFlagBits::eSampled ); + gbuffer.normal.setClear( vk::ClearColorValue( std::array< float, 4 > { { 0.0f, 0.0f, 0.0f, 0.0f } } ) ); g_buffer_normal_img = std::make_unique< Texture >( gbuffer.normal.m_attachment_resources.m_images[ 0 ] ->setName( "GBufferNormal" ) ); + + gbuffer.albedo.createResourceSpread( imageCount(), getSwapChainExtent(), vk::ImageUsageFlagBits::eSampled ); + gbuffer.albedo.setClear( vk::ClearColorValue( std::array< float, 4 > { { 0.0f, 0.0f, 0.0f, 0.0f } } ) ); g_buffer_albedo_img = std::make_unique< Texture >( gbuffer.albedo.m_attachment_resources.m_images[ 0 ] ->setName( "GBufferAlbedo" ) ); + + gbuffer.composite.createResourceSpread( imageCount(), getSwapChainExtent(), vk::ImageUsageFlagBits::eSampled ); + gbuffer.composite.setClear( vk::ClearColorValue( std::array< float, 4 > { { 0.0f, 0.0f, 0.0f, 0.0f } } ) ); g_buffer_composite_img = std::make_unique< Texture >( gbuffer.composite.m_attachment_resources.m_images[ 0 ] ->setName( "GBufferComposite" ) ); @@ -410,28 +411,26 @@ namespace fgl::engine } 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 ) + vk::PresentModeKHR SwapChain::chooseSwapPresentMode( const std::vector< vk::PresentModeKHR >& present_modes ) { ZoneScoped; - for ( const auto& availablePresentMode : availablePresentModes ) + for ( const auto& mode : present_modes ) { - switch ( availablePresentMode ) + switch ( mode ) { case vk::PresentModeKHR::eImmediate: std::cout << "Present mode: Immediate" << std::endl; @@ -454,27 +453,20 @@ namespace fgl::engine } } - for ( const auto& availablePresentMode : availablePresentModes ) + for ( const auto& mode : present_modes ) { - if ( availablePresentMode == vk::PresentModeKHR::eMailbox ) + if ( mode == vk::PresentModeKHR::eMailbox ) { std::cout << "Present mode: Mailbox: ACTIVE" << std::endl; - return availablePresentMode; + return mode; } } - // for (const auto &availablePresentMode : availablePresentModes) { - // if (availablePresentMode == VK_PRESENT_MODE_IMMEDIATE_KHR) { - // std::cout << "Present mode: Immediate" << std::endl; - // return availablePresentMode; - // } - // } - std::cout << "Present mode: V-Sync: ACTIVE" << std::endl; return vk::PresentModeKHR::eFifo; } - vk::Extent2D SwapChain::chooseSwapExtent( const vk::SurfaceCapabilitiesKHR& capabilities ) + vk::Extent2D SwapChain::chooseSwapExtent( const vk::SurfaceCapabilitiesKHR& capabilities ) const { ZoneScoped; if ( capabilities.currentExtent.width != std::numeric_limits< uint32_t >::max() ) @@ -483,15 +475,16 @@ namespace fgl::engine } else { - vk::Extent2D actualExtent = m_swapchain_extent; - actualExtent.width = std:: - max( capabilities.minImageExtent.width, - std::min( capabilities.maxImageExtent.width, actualExtent.width ) ); - actualExtent.height = std:: - max( capabilities.minImageExtent.height, - std::min( capabilities.maxImageExtent.height, actualExtent.height ) ); + vk::Extent2D actual_extent { m_swapchain_extent }; - return actualExtent; + const auto [ min_height, min_width ] = capabilities.minImageExtent; + const auto [ max_height, max_width ] = capabilities.maxImageExtent; + + actual_extent.width = std::clamp( actual_extent.width, min_width, max_width ); + + actual_extent.height = std::clamp( actual_extent.height, min_height, max_height ); + + return actual_extent; } } diff --git a/src/engine/rendering/SwapChain.hpp b/src/engine/rendering/SwapChain.hpp index 11d3653..82ea65e 100644 --- a/src/engine/rendering/SwapChain.hpp +++ b/src/engine/rendering/SwapChain.hpp @@ -86,9 +86,9 @@ namespace fgl::engine void createSyncObjects(); // Helper functions - vk::SurfaceFormatKHR chooseSwapSurfaceFormat( const std::vector< vk::SurfaceFormatKHR >& availableFormats ); - vk::PresentModeKHR chooseSwapPresentMode( const std::vector< vk::PresentModeKHR >& availablePresentModes ); - vk::Extent2D chooseSwapExtent( const vk::SurfaceCapabilitiesKHR& capabilities ); + static vk::SurfaceFormatKHR chooseSwapSurfaceFormat( const std::vector< vk::SurfaceFormatKHR >& available_formats ); + static vk::PresentModeKHR chooseSwapPresentMode( const std::vector< vk::PresentModeKHR >& present_modes ); + vk::Extent2D chooseSwapExtent( const vk::SurfaceCapabilitiesKHR& capabilities ) const; template < is_attachment... Attachments > static std::vector< vk::ImageView > getViewsForFrame( const std::uint8_t frame_idx, Attachments... attachments ) @@ -171,7 +171,7 @@ namespace fgl::engine return static_cast< float >( m_swapchain_extent.width ) / static_cast< float >( m_swapchain_extent.height ); } - vk::Format findDepthFormat(); + static vk::Format findDepthFormat(); [[nodiscard]] std::pair< vk::Result, std::uint32_t > acquireNextImage(); [[nodiscard]] vk::Result From 2f7e3452ac11a5a4bb464ba380e3d1754f6a7bf2 Mon Sep 17 00:00:00 2001 From: kj16609 Date: Thu, 11 Jul 2024 01:42:02 -0400 Subject: [PATCH 4/5] More code cleanup - Formatting --- src/engine/rendering/SwapChain.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/engine/rendering/SwapChain.hpp b/src/engine/rendering/SwapChain.hpp index 82ea65e..fd5a068 100644 --- a/src/engine/rendering/SwapChain.hpp +++ b/src/engine/rendering/SwapChain.hpp @@ -86,7 +86,8 @@ namespace fgl::engine void createSyncObjects(); // Helper functions - static vk::SurfaceFormatKHR chooseSwapSurfaceFormat( const std::vector< vk::SurfaceFormatKHR >& available_formats ); + static vk::SurfaceFormatKHR chooseSwapSurfaceFormat( const std::vector< vk::SurfaceFormatKHR >& + available_formats ); static vk::PresentModeKHR chooseSwapPresentMode( const std::vector< vk::PresentModeKHR >& present_modes ); vk::Extent2D chooseSwapExtent( const vk::SurfaceCapabilitiesKHR& capabilities ) const; From f2bf5cad53a47afa4357e516d01d41d3eaca1c09 Mon Sep 17 00:00:00 2001 From: kj16609 Date: Thu, 11 Jul 2024 03:46:03 -0400 Subject: [PATCH 5/5] More cleanup --- shaders/gui-compose.frag | 4 +- src/engine/EngineContext.cpp | 12 ++-- src/engine/FrameInfo.hpp | 5 +- src/engine/gui/core.cpp | 3 +- src/engine/gui/preview.cpp | 16 +++-- src/engine/rendering/Renderer.cpp | 27 ++------ src/engine/rendering/Renderer.hpp | 14 ++-- src/engine/rendering/Subpass.hpp | 10 +-- src/engine/rendering/SwapChain.cpp | 104 ++++++++++++++++------------- src/engine/rendering/SwapChain.hpp | 51 ++++++-------- src/engine/rendering/types.hpp | 13 ++++ src/engine/systems/GuiSystem.cpp | 13 ++-- 12 files changed, 137 insertions(+), 135 deletions(-) create mode 100644 src/engine/rendering/types.hpp diff --git a/shaders/gui-compose.frag b/shaders/gui-compose.frag index 7eae4dc..d1ba96c 100644 --- a/shaders/gui-compose.frag +++ b/shaders/gui-compose.frag @@ -10,6 +10,4 @@ void main() { vec4 composite = subpassLoad(i_composite).xyzw; out_color = composite; -} - - +} \ No newline at end of file diff --git a/src/engine/EngineContext.cpp b/src/engine/EngineContext.cpp index 9c088c3..85c03a3 100644 --- a/src/engine/EngineContext.cpp +++ b/src/engine/EngineContext.cpp @@ -148,18 +148,18 @@ namespace fgl::engine camera_controller.moveInPlaneXZ( m_window.window(), delta_time, viewer ); camera.setView( viewer.getPosition(), viewer.getRotation() ); - if ( auto [ command_buffer, gui_command_buffer ] = m_renderer.beginFrame(); *command_buffer ) + if ( auto& command_buffer = m_renderer.beginFrame(); *command_buffer ) { ZoneScopedN( "Render" ); - //Update - const std::uint16_t frame_index { m_renderer.getFrameIndex() }; + const FrameIndex frame_index { m_renderer.getFrameIndex() }; + const PresentIndex present_idx { m_renderer.getPresentIndex() }; const auto view_frustum { camera.getFrustumBounds() }; FrameInfo frame_info { frame_index, + present_idx, delta_time, command_buffer, - gui_command_buffer, { camera, viewer.getTransform() }, global_descriptor_sets[ frame_index ], m_game_objects_root, @@ -168,8 +168,8 @@ namespace fgl::engine draw_parameter_buffers[ frame_index ], *this->m_vertex_buffer, *this->m_index_buffer, - m_renderer.getGBufferDescriptor( frame_index ), - m_renderer.getGBufferCompositeDescriptor( frame_index ), + m_renderer.getGBufferDescriptor( present_idx ), + m_renderer.getGBufferCompositeDescriptor( present_idx ), view_frustum, this->m_renderer.getSwapChain() }; diff --git a/src/engine/FrameInfo.hpp b/src/engine/FrameInfo.hpp index e042e49..214504c 100644 --- a/src/engine/FrameInfo.hpp +++ b/src/engine/FrameInfo.hpp @@ -15,6 +15,7 @@ #include "engine/descriptors/DescriptorSet.hpp" #include "engine/descriptors/DescriptorSetLayout.hpp" #include "engine/tree/octtree/OctTreeNode.hpp" +#include "rendering/types.hpp" #define MAX_LIGHTS 10 @@ -75,11 +76,11 @@ namespace fgl::engine struct FrameInfo { - std::uint16_t frame_idx; + FrameIndex frame_idx; + PresentIndex present_idx; float frame_time; vk::raii::CommandBuffer& command_buffer; - vk::raii::CommandBuffer& gui_command_buffer; struct { diff --git a/src/engine/gui/core.cpp b/src/engine/gui/core.cpp index 091e370..7bac810 100644 --- a/src/engine/gui/core.cpp +++ b/src/engine/gui/core.cpp @@ -136,7 +136,6 @@ namespace fgl::engine::gui void drawMainGUI( FrameInfo& info ) { ZoneScoped; - TracyVkZone( info.tracy_ctx, *info.gui_command_buffer, "ImGui Rendering" ); beginImGui(); // TODO: Maybe play with docks again some other time @@ -148,7 +147,7 @@ namespace fgl::engine::gui drawEntityInfo( info ); drawFilesystemGUI( info ); - endImGui( info.gui_command_buffer ); + endImGui( info.command_buffer ); } static GameObject* selected_object { nullptr }; diff --git a/src/engine/gui/preview.cpp b/src/engine/gui/preview.cpp index 81eed25..df06c90 100644 --- a/src/engine/gui/preview.cpp +++ b/src/engine/gui/preview.cpp @@ -98,6 +98,8 @@ namespace fgl::engine::gui void drawRenderingOutputs( FrameInfo& info ) { ZoneScoped; + const auto present_idx { info.present_idx }; + ImGui::Begin( "RenderOutputs" ); enum RenderingOutputSelection : std::uint_fast8_t @@ -139,7 +141,7 @@ namespace fgl::engine::gui current = Composite; } - info.swap_chain.g_buffer_albedo_img->drawImGui( { v_size, h_size } ); + info.swap_chain.g_buffer_albedo_img[ present_idx ]->drawImGui( { v_size, h_size } ); ImGui::SameLine(); if ( ImGui::Selectable( options[ Albedo ], current == Albedo ) ) { @@ -147,7 +149,7 @@ namespace fgl::engine::gui current = Albedo; } - info.swap_chain.g_buffer_normal_img->drawImGui( { v_size, h_size } ); + info.swap_chain.g_buffer_normal_img[ present_idx ]->drawImGui( { v_size, h_size } ); ImGui::SameLine(); if ( ImGui::Selectable( options[ Normal ], current == Normal ) ) { @@ -155,7 +157,7 @@ namespace fgl::engine::gui current = Normal; } - info.swap_chain.g_buffer_position_img->drawImGui( { v_size, h_size } ); + info.swap_chain.g_buffer_position_img[ present_idx ]->drawImGui( { v_size, h_size } ); ImGui::SameLine(); if ( ImGui::Selectable( options[ Position ], current == Position ) ) { @@ -171,16 +173,16 @@ namespace fgl::engine::gui default: [[fallthrough]]; case Composite: - info.swap_chain.g_buffer_composite_img->drawImGui(); + info.swap_chain.g_buffer_composite_img[ present_idx ]->drawImGui(); break; case Albedo: - info.swap_chain.g_buffer_albedo_img->drawImGui(); + info.swap_chain.g_buffer_albedo_img[ present_idx ]->drawImGui(); break; case Normal: - info.swap_chain.g_buffer_normal_img->drawImGui(); + info.swap_chain.g_buffer_normal_img[ present_idx ]->drawImGui(); break; case Position: - info.swap_chain.g_buffer_position_img->drawImGui(); + info.swap_chain.g_buffer_position_img[ present_idx ]->drawImGui(); break; } diff --git a/src/engine/rendering/Renderer.cpp b/src/engine/rendering/Renderer.cpp index b782e44..f0ae9d2 100644 --- a/src/engine/rendering/Renderer.cpp +++ b/src/engine/rendering/Renderer.cpp @@ -97,11 +97,11 @@ namespace fgl::engine } } - std::pair< vk::raii::CommandBuffer&, vk::raii::CommandBuffer& > Renderer::beginFrame() + 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 ) { @@ -113,7 +113,6 @@ namespace fgl::engine is_frame_started = true; auto& command_buffer { getCurrentCommandbuffer() }; - auto& gui_command_buffer { getCurrentGuiCommandBuffer() }; vk::CommandBufferBeginInfo begin_info {}; begin_info.pNext = VK_NULL_HANDLE; @@ -122,21 +121,7 @@ namespace fgl::engine command_buffer.begin( begin_info ); - vk::CommandBufferInheritanceInfo inheritance_info {}; - inheritance_info.framebuffer = this->getSwapChain().getFrameBuffer( current_image_idx ); - inheritance_info.renderPass = this->getSwapChainRenderPass(); - inheritance_info.subpass = 2; - - vk::CommandBufferBeginInfo gui_begin_info {}; - gui_begin_info.pInheritanceInfo = &inheritance_info; - gui_begin_info.flags = vk::CommandBufferUsageFlagBits::eRenderPassContinue; - - gui_command_buffer.begin( gui_begin_info ); - - setViewport( gui_command_buffer ); - setScissor( gui_command_buffer ); - - return { command_buffer, gui_command_buffer }; + return command_buffer; } void Renderer::endFrame() @@ -148,7 +133,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() ) @@ -196,7 +181,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_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..17c7217 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_idx { 0 }; bool is_frame_started { false }; void createCommandBuffers(); @@ -51,12 +51,18 @@ namespace fgl::engine return m_swapchain->getGBufferCompositeDescriptor( frame_idx ); } - std::uint16_t getFrameIndex() const + FrameIndex getFrameIndex() const { assert( is_frame_started && "Cannot get frame index while frame not in progress" ); return current_frame_idx; } + PresentIndex getPresentIndex() const + { + assert( current_present_index != std::numeric_limits< PresentIndex >::max() ); + return current_present_index; + } + bool isFrameInProgress() const { return is_frame_started; } vk::raii::CommandBuffer& getCurrentCommandbuffer() @@ -81,7 +87,7 @@ namespace fgl::engine float getAspectRatio() const { return m_swapchain->extentAspectRatio(); } - std::pair< vk::raii::CommandBuffer&, vk::raii::CommandBuffer& > beginFrame(); + vk::raii::CommandBuffer& beginFrame(); void endFrame(); void setViewport( const vk::raii::CommandBuffer& buffer ); diff --git a/src/engine/rendering/Subpass.hpp b/src/engine/rendering/Subpass.hpp index 5b0218f..9df1cfc 100644 --- a/src/engine/rendering/Subpass.hpp +++ b/src/engine/rendering/Subpass.hpp @@ -199,17 +199,17 @@ namespace fgl::engine void registerDependencyToExternal( const vk::AccessFlags src_access_flags, const vk::PipelineStageFlags src_stage_flags, - const vk::AccessFlags dst_access_flags, - const vk::PipelineStageFlags dst_stage_flags, - const vk::DependencyFlags dependency_flags ) + const vk::AccessFlags dst_access_flags = vk::AccessFlagBits::eNone, + const vk::PipelineStageFlags dst_stage_flags = vk::PipelineStageFlagBits::eNone, + const vk::DependencyFlags dependency_flags = {} ) { registerDependency( this->getIndex(), VK_SUBPASS_EXTERNAL, src_access_flags, src_stage_flags, - dst_access_flags, - dst_stage_flags, + dst_access_flags == vk::AccessFlagBits::eNone ? src_access_flags : dst_access_flags, + dst_stage_flags == vk::PipelineStageFlagBits::eNone ? src_stage_flags : dst_stage_flags, dependency_flags ); } }; diff --git a/src/engine/rendering/SwapChain.cpp b/src/engine/rendering/SwapChain.cpp index 2907acc..8fb5411 100644 --- a/src/engine/rendering/SwapChain.cpp +++ b/src/engine/rendering/SwapChain.cpp @@ -15,7 +15,7 @@ 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 ), m_swapchain_details( Device::getInstance().getSwapChainSupport() ), m_surface_format( chooseSwapSurfaceFormat( m_swapchain_details.formats ) ), @@ -37,12 +37,12 @@ namespace fgl::engine gbuffer.albedo, gbuffer.composite ) ), m_gbuffer_descriptor_set( createGBufferDescriptors() ), - m_gbuffer_composite_descriptor_set( createCompositeDescriptors() ) + m_composite_descriptor_set( createCompositeDescriptors() ) { 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 ), m_swapchain_details( Device::getInstance().getSwapChainSupport() ), m_surface_format( chooseSwapSurfaceFormat( m_swapchain_details.formats ) ), @@ -64,7 +64,7 @@ namespace fgl::engine gbuffer.albedo, gbuffer.composite ) ), m_gbuffer_descriptor_set( createGBufferDescriptors() ), - m_gbuffer_composite_descriptor_set( createCompositeDescriptors() ) + m_composite_descriptor_set( createCompositeDescriptors() ) { init(); old_swap_chain.reset(); @@ -75,7 +75,7 @@ namespace fgl::engine createSyncObjects(); } - std::pair< vk::Result, std::uint32_t > SwapChain::acquireNextImage() + std::pair< vk::Result, PresentIndex > SwapChain::acquireNextImage() { ZoneScoped; @@ -93,13 +93,14 @@ namespace fgl::engine 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 present_index ) { ZoneScoped; - images_in_flight[ imageIndex ] = in_flight_fence[ m_current_frame_index ]; + images_in_flight[ present_index ] = in_flight_fence[ m_current_frame_index ]; - std::vector< vk::Fence > fences { images_in_flight[ imageIndex ] }; + std::vector< vk::Fence > fences { images_in_flight[ present_index ] }; if ( Device::getInstance().device().waitForFences( fences, VK_TRUE, std::numeric_limits< uint64_t >::max() ) != vk::Result::eSuccess ) @@ -135,7 +136,7 @@ namespace fgl::engine std::vector< vk::SwapchainKHR > swapchains { m_swapchain }; presentInfo.setSwapchains( swapchains ); - std::array< std::uint32_t, 1 > indicies { { imageIndex } }; + std::array< std::uint32_t, 1 > indicies { { present_index } }; presentInfo.setImageIndices( indicies ); if ( auto present_result = Device::getInstance().presentQueue().presentKHR( presentInfo ); @@ -254,14 +255,11 @@ namespace fgl::engine 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, render_attachments.depth, gbuffer.composite, gbuffer.position, gbuffer.normal, gbuffer.albedo - }; + composite_subpass { 1, gbuffer.composite, gbuffer.position, gbuffer.normal, gbuffer.albedo }; composite_subpass.registerDependencyFromExternal( vk::AccessFlagBits::eColorAttachmentWrite, vk::PipelineStageFlagBits::eColorAttachmentOutput ); @@ -275,14 +273,11 @@ namespace fgl::engine 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::eShaderRead | vk::AccessFlagBits::eInputAttachmentRead, + vk::PipelineStageFlagBits::eFragmentShader ); // 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< @@ -292,6 +287,17 @@ namespace fgl::engine InputAttachment< ColorAttachment, vk::ImageLayout::eShaderReadOnlyOptimal > > gui_subpass { 2, render_attachments.depth, render_attachments.color, gbuffer.composite }; + gui_subpass.registerFullDependency( composite_subpass ); + + // For depth attachment + gui_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 ); + gui_subpass.registerDependencyFromExternal( vk::AccessFlagBits::eColorAttachmentWrite, vk::PipelineStageFlagBits::eColorAttachmentOutput ); @@ -299,7 +305,7 @@ namespace fgl::engine composite_subpass, vk::AccessFlagBits::eColorAttachmentWrite, vk::PipelineStageFlagBits::eColorAttachmentOutput, - vk::AccessFlagBits::eShaderRead, + vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eInputAttachmentRead, vk::PipelineStageFlagBits::eFragmentShader, vk::DependencyFlagBits::eByRegion ); @@ -312,18 +318,12 @@ namespace fgl::engine vk::DependencyFlagBits::eByRegion ); gui_subpass.registerDependencyToExternal( - vk::AccessFlagBits::eColorAttachmentWrite, - vk::PipelineStageFlagBits::eColorAttachmentOutput, - vk::AccessFlagBits::eMemoryRead, - vk::PipelineStageFlagBits::eBottomOfPipe, - vk::DependencyFlagBits::eByRegion ); + vk::AccessFlagBits::eColorAttachmentWrite, vk::PipelineStageFlagBits::eColorAttachmentOutput ); render_pass_builder.registerSubpass( g_buffer_subpass ); render_pass_builder.registerSubpass( composite_subpass ); render_pass_builder.registerSubpass( gui_subpass ); - m_clear_values = render_pass_builder.getClearValues(); - return render_pass_builder.create(); } @@ -338,23 +338,31 @@ namespace fgl::engine gbuffer.position.createResourceSpread( imageCount(), getSwapChainExtent(), vk::ImageUsageFlagBits::eSampled ); gbuffer.position.setClear( vk::ClearColorValue( std::array< float, 4 > { { 0.0f, 0.0f, 0.0f, 0.0f } } ) ); - g_buffer_position_img = std::make_unique< Texture >( gbuffer.position.m_attachment_resources.m_images[ 0 ] - ->setName( "GBufferPosition" ) ); gbuffer.normal.createResourceSpread( imageCount(), getSwapChainExtent(), vk::ImageUsageFlagBits::eSampled ); gbuffer.normal.setClear( vk::ClearColorValue( std::array< float, 4 > { { 0.0f, 0.0f, 0.0f, 0.0f } } ) ); - g_buffer_normal_img = std::make_unique< Texture >( gbuffer.normal.m_attachment_resources.m_images[ 0 ] - ->setName( "GBufferNormal" ) ); gbuffer.albedo.createResourceSpread( imageCount(), getSwapChainExtent(), vk::ImageUsageFlagBits::eSampled ); gbuffer.albedo.setClear( vk::ClearColorValue( std::array< float, 4 > { { 0.0f, 0.0f, 0.0f, 0.0f } } ) ); - g_buffer_albedo_img = std::make_unique< Texture >( gbuffer.albedo.m_attachment_resources.m_images[ 0 ] - ->setName( "GBufferAlbedo" ) ); gbuffer.composite.createResourceSpread( imageCount(), getSwapChainExtent(), vk::ImageUsageFlagBits::eSampled ); gbuffer.composite.setClear( vk::ClearColorValue( std::array< float, 4 > { { 0.0f, 0.0f, 0.0f, 0.0f } } ) ); - g_buffer_composite_img = std::make_unique< Texture >( gbuffer.composite.m_attachment_resources.m_images[ 0 ] - ->setName( "GBufferComposite" ) ); + + for ( PresentIndex i = 0; i < imageCount(); ++i ) + { + g_buffer_position_img.emplace_back( std::make_unique< Texture >( gbuffer.position.m_attachment_resources + .m_images[ i ] + ->setName( "GBufferPosition" ) ) ); + g_buffer_normal_img.emplace_back( std::make_unique< Texture >( gbuffer.normal.m_attachment_resources + .m_images[ i ] + ->setName( "GBufferNormal" ) ) ); + g_buffer_albedo_img.emplace_back( std::make_unique< Texture >( gbuffer.albedo.m_attachment_resources + .m_images[ i ] + ->setName( "GBufferAlbedo" ) ) ); + g_buffer_composite_img.emplace_back( std::make_unique< Texture >( gbuffer.composite.m_attachment_resources + .m_images[ i ] + ->setName( "GBufferComposite" ) ) ); + } std::vector< vk::raii::Framebuffer > framebuffers {}; @@ -390,9 +398,9 @@ namespace fgl::engine void SwapChain::createSyncObjects() { ZoneScoped; - image_available_sem.reserve( MAX_FRAMES_IN_FLIGHT ); - render_finished_sem.reserve( MAX_FRAMES_IN_FLIGHT ); - in_flight_fence.reserve( MAX_FRAMES_IN_FLIGHT ); + image_available_sem.reserve( imageCount() ); + render_finished_sem.reserve( imageCount() ); + in_flight_fence.reserve( imageCount() ); images_in_flight.resize( imageCount(), VK_NULL_HANDLE ); vk::SemaphoreCreateInfo semaphoreInfo {}; @@ -488,12 +496,12 @@ namespace fgl::engine } } - std::array< std::unique_ptr< descriptors::DescriptorSet >, SwapChain::MAX_FRAMES_IN_FLIGHT > SwapChain:: - createGBufferDescriptors() + std::vector< std::unique_ptr< descriptors::DescriptorSet > > SwapChain::createGBufferDescriptors() { - std::array< std::unique_ptr< descriptors::DescriptorSet >, SwapChain::MAX_FRAMES_IN_FLIGHT > data; + std::vector< std::unique_ptr< descriptors::DescriptorSet > > data; + data.resize( imageCount() ); - for ( int i = 0; i < SwapChain::MAX_FRAMES_IN_FLIGHT; ++i ) + for ( PresentIndex i = 0; i < imageCount(); ++i ) { auto set { std::make_unique< descriptors::DescriptorSet >( GBufferDescriptorSet::createLayout() ) }; @@ -513,12 +521,12 @@ namespace fgl::engine return data; } - std::array< std::unique_ptr< descriptors::DescriptorSet >, SwapChain::MAX_FRAMES_IN_FLIGHT > SwapChain:: - createCompositeDescriptors() + std::vector< std::unique_ptr< descriptors::DescriptorSet > > SwapChain::createCompositeDescriptors() { - std::array< std::unique_ptr< descriptors::DescriptorSet >, SwapChain::MAX_FRAMES_IN_FLIGHT > data; + std::vector< std::unique_ptr< descriptors::DescriptorSet > > data; + data.resize( imageCount() ); - for ( int i = 0; i < SwapChain::MAX_FRAMES_IN_FLIGHT; ++i ) + for ( PresentIndex i = 0; i < imageCount(); ++i ) { auto composite_set { std::make_unique< descriptors::DescriptorSet >( GBufferCompositeDescriptorSet::createLayout() ) diff --git a/src/engine/rendering/SwapChain.hpp b/src/engine/rendering/SwapChain.hpp index fd5a068..1f7149a 100644 --- a/src/engine/rendering/SwapChain.hpp +++ b/src/engine/rendering/SwapChain.hpp @@ -1,7 +1,5 @@ #pragma once -#include - #include #include @@ -9,6 +7,7 @@ #include "RenderPassBuilder.hpp" #include "engine/FrameInfo.hpp" #include "engine/texture/Texture.hpp" +#include "types.hpp" namespace fgl::engine { @@ -16,7 +15,7 @@ namespace fgl::engine { public: - static constexpr std::uint16_t MAX_FRAMES_IN_FLIGHT = 2; + static constexpr std::uint16_t MAX_FRAMES_IN_FLIGHT { 2 }; private: @@ -51,10 +50,10 @@ namespace fgl::engine public: - 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 }; + std::vector< std::unique_ptr< Texture > > g_buffer_position_img {}; + std::vector< std::unique_ptr< Texture > > g_buffer_normal_img {}; + std::vector< std::unique_ptr< Texture > > g_buffer_albedo_img {}; + std::vector< std::unique_ptr< Texture > > g_buffer_composite_img {}; private: @@ -66,11 +65,9 @@ namespace fgl::engine std::vector< vk::ClearValue > m_clear_values; - std::array< std::unique_ptr< descriptors::DescriptorSet >, SwapChain::MAX_FRAMES_IN_FLIGHT > - m_gbuffer_descriptor_set; + std::vector< std::unique_ptr< descriptors::DescriptorSet > > m_gbuffer_descriptor_set; - std::array< std::unique_ptr< descriptors::DescriptorSet >, SwapChain::MAX_FRAMES_IN_FLIGHT > - m_gbuffer_composite_descriptor_set; + std::vector< std::unique_ptr< descriptors::DescriptorSet > > m_composite_descriptor_set; std::vector< vk::raii::Semaphore > image_available_sem {}; std::vector< vk::raii::Semaphore > render_finished_sem {}; @@ -113,29 +110,25 @@ namespace fgl::engine return clear_values; } - std::array< std::unique_ptr< descriptors::DescriptorSet >, SwapChain::MAX_FRAMES_IN_FLIGHT > - createGBufferDescriptors(); - std::array< std::unique_ptr< descriptors::DescriptorSet >, SwapChain::MAX_FRAMES_IN_FLIGHT > - createCompositeDescriptors(); + std::vector< std::unique_ptr< descriptors::DescriptorSet > > createGBufferDescriptors(); + std::vector< std::unique_ptr< descriptors::DescriptorSet > > createCompositeDescriptors(); public: std::vector< vk::ClearValue > getClearValues() const { return m_clear_values; } - descriptors::DescriptorSet& getGBufferDescriptor( std::uint16_t frame_idx ) const + descriptors::DescriptorSet& getGBufferDescriptor( PresentIndex frame_idx ) const { - assert( frame_idx < SwapChain::MAX_FRAMES_IN_FLIGHT && "Frame index out of range" ); - assert( - m_gbuffer_descriptor_set.size() == SwapChain::MAX_FRAMES_IN_FLIGHT - && "GBuffer descriptor set not initialized" ); + assert( frame_idx < imageCount() && "Frame index out of range" ); + assert( m_gbuffer_descriptor_set.size() > 0 && "GBuffer descriptor set not initialized" ); return *m_gbuffer_descriptor_set[ frame_idx ]; } - descriptors::DescriptorSet& getGBufferCompositeDescriptor( uint16_t frame_idx ) const + descriptors::DescriptorSet& getGBufferCompositeDescriptor( PresentIndex frame_idx ) const { - assert( frame_idx < SwapChain::MAX_FRAMES_IN_FLIGHT && "Frame index out of range" ); - - return *m_gbuffer_composite_descriptor_set[ frame_idx ]; + assert( frame_idx < imageCount() && "Frame index out of range" ); + assert( m_composite_descriptor_set.size() > 0 && "GBuffer descriptor set not initialized" ); + return *m_composite_descriptor_set[ frame_idx ]; } SwapChain( vk::Extent2D windowExtent, PhysicalDevice& phy_dev ); @@ -144,14 +137,14 @@ namespace fgl::engine SwapChain( const SwapChain& ) = delete; SwapChain& operator=( const SwapChain& ) = delete; - vk::raii::Framebuffer& getFrameBuffer( std::uint32_t index ) + vk::raii::Framebuffer& getFrameBuffer( const PresentIndex present_index ) { - return m_swap_chain_buffers[ static_cast< std::size_t >( index ) ]; + return m_swap_chain_buffers[ static_cast< std::size_t >( present_index ) ]; } vk::raii::RenderPass& getRenderPass() { return m_render_pass; } - std::uint16_t imageCount() const { return static_cast< std::uint16_t >( m_swap_chain_images.size() ); } + PresentIndex imageCount() const { return static_cast< std::uint16_t >( m_swap_chain_images.size() ); } vk::Format getSwapChainImageFormat() const { return m_swap_chain_format; } @@ -174,9 +167,9 @@ namespace fgl::engine static vk::Format findDepthFormat(); - [[nodiscard]] std::pair< vk::Result, std::uint32_t > acquireNextImage(); + [[nodiscard]] std::pair< vk::Result, PresentIndex > acquireNextImage(); [[nodiscard]] vk::Result - submitCommandBuffers( const vk::raii::CommandBuffer& buffers, std::uint32_t imageIndex ); + submitCommandBuffers( const vk::raii::CommandBuffer& buffers, PresentIndex 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..5f919dc --- /dev/null +++ b/src/engine/rendering/types.hpp @@ -0,0 +1,13 @@ +// +// Created by kj16609 on 7/11/24. +// + +#pragma once + +#include + +namespace fgl::engine +{ + using PresentIndex = std::uint16_t; + using FrameIndex = std::uint16_t; +} diff --git a/src/engine/systems/GuiSystem.cpp b/src/engine/systems/GuiSystem.cpp index 42d9399..256a6b0 100644 --- a/src/engine/systems/GuiSystem.cpp +++ b/src/engine/systems/GuiSystem.cpp @@ -24,13 +24,15 @@ namespace fgl::engine vk::raii::CommandBuffer& GuiSystem::setupSystem( FrameInfo& info ) { - auto& command_buffer { info.gui_command_buffer }; + auto& command_buffer { info.command_buffer }; + + command_buffer.nextSubpass( vk::SubpassContents::eInline ); + + m_pipeline->bind( command_buffer ); m_pipeline ->bindDescriptor( command_buffer, GBufferCompositeDescriptorSet::m_set_idx, info.gbuffer_composite_set ); - m_pipeline->bind( command_buffer ); - return command_buffer; } @@ -42,11 +44,6 @@ namespace fgl::engine //Handle GUI gui::drawMainGUI( info ); - - command_buffer.end(); - - info.command_buffer.nextSubpass( vk::SubpassContents::eSecondaryCommandBuffers ); - info.command_buffer.executeCommands( { info.gui_command_buffer } ); } } // namespace fgl::engine