Merge branch 'refs/heads/attempt2'

# Conflicts:
#	src/engine/concepts/is_attachment.hpp
#	src/engine/gui/preview.cpp
#	src/engine/rendering/Attachment.hpp
#	src/engine/rendering/RenderPassBuilder.hpp
#	src/engine/rendering/Renderer.cpp
#	src/engine/rendering/Renderer.hpp
#	src/engine/rendering/SwapChain.cpp
#	src/engine/rendering/SwapChain.hpp
#	src/engine/rendering/types.hpp
#	src/engine/systems/GuiSystem.cpp
This commit is contained in:
2024-07-11 03:58:44 -04:00
14 changed files with 350 additions and 457 deletions

View File

@@ -10,6 +10,4 @@ void main() {
vec4 composite = subpassLoad(i_composite).xyzw;
out_color = composite;
}
}

View File

@@ -151,12 +151,13 @@ namespace fgl::engine
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,
{ camera, viewer.getTransform() },
@@ -167,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() };

View File

@@ -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,7 +76,8 @@ namespace fgl::engine
struct FrameInfo
{
std::uint16_t frame_idx;
FrameIndex frame_idx;
PresentIndex present_idx;
float frame_time;
vk::raii::CommandBuffer& command_buffer;

View File

@@ -4,6 +4,8 @@
#pragma once
#include <memory>
namespace fgl::engine
{
class ImageView;
@@ -22,10 +24,13 @@ namespace fgl::engine
a.setIndex( std::declval< std::uint32_t >() )
};
{
a.linkImages( std::declval< std::vector< std::shared_ptr< Image > >& >() )
a.attachImageView( std::declval< std::uint16_t >(), std::declval< std::shared_ptr< ImageView > >() )
};
{
a.view( std::declval< std::uint32_t >() )
a.linkImage( std::declval< std::uint16_t >(), std::declval< Image& >() )
};
{
a.getView( std::declval< std::uint8_t >() )
} -> std::same_as< ImageView& >;
{
a.m_clear_value

View File

@@ -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,8 +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 ) )
{
@@ -148,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 ) )
{
@@ -156,37 +157,34 @@ 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 ) )
{
log::debug( "Changing output to Position" );
current = Position;
}
*/
ImGui::EndCombo();
}
/*
switch ( current )
{
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;
}*/
}
handleDragDrop( info );

View File

@@ -13,8 +13,7 @@
#include "engine/concepts/is_attachment.hpp"
#include "engine/image/Image.hpp"
#include "engine/image/ImageView.hpp"
#include "types.hpp"
#include "engine/rendering/Device.hpp"
namespace fgl::engine
{
@@ -34,7 +33,7 @@ namespace fgl::engine
class Attachment
{
vk::AttachmentDescription description {};
std::uint32_t m_index { std::numeric_limits< std::uint32_t >::max() };
std::uint32_t index { std::numeric_limits< std::uint32_t >::max() };
public:
@@ -44,22 +43,9 @@ 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 ) { m_index = idx; }
void setIndex( const std::uint32_t idx ) { index = idx; }
constexpr static vk::AttachmentLoadOp loadOp = load_op;
constexpr static vk::AttachmentStoreOp storeOp = store_op;
@@ -79,18 +65,21 @@ namespace fgl::engine
description.finalLayout = final_layout;
}
void linkImage( std::shared_ptr< Image > image )
void attachImageView( std::uint16_t frame_idx, std::shared_ptr< ImageView > image_view )
{
auto& itter { m_attachment_resources.m_images.emplace_back( std::move( image ) ) };
m_attachment_resources.m_image_views.emplace_back( itter->getView() );
auto& image_views = m_attachment_resources.m_image_views;
if ( image_views.size() <= frame_idx ) image_views.resize( frame_idx + 1 );
image_views[ frame_idx ] = std::move( image_view );
}
void linkImages( std::vector< std::shared_ptr< Image > >& images )
void linkImage( std::uint16_t frame_idx, Image& image ) { attachImageView( frame_idx, image.getView() ); }
void linkImages( std::vector< Image >& images )
{
for ( auto image : images )
assert( images.size() > 0 );
for ( std::uint16_t i = 0; i < images.size(); ++i )
{
auto& itter { m_attachment_resources.m_images.emplace_back( std::move( image ) ) };
m_attachment_resources.m_image_views.emplace_back( itter->getView() );
linkImage( i, images[ i ] );
}
}
@@ -110,59 +99,37 @@ namespace fgl::engine
}
}
//! Creates resources required for this attachment
//! Creates a resource that is used across all frames
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() );
}
}
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; }
std::uint32_t getIndex() const
{
assert(
m_index != std::numeric_limits< std::uint32_t >::max()
index != std::numeric_limits< std::uint32_t >::max()
&& "Attachment must be registered in RenderPass before use" );
return m_index;
}
ImageView& view( const FrameIndex index )
{
assert( index < m_attachment_resources.m_image_views.size() );
return *m_attachment_resources.m_image_views[ index ];
}
Image& image( const FrameIndex index )
{
assert( index < m_attachment_resources.m_images.size() );
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() );
assert( images.size() > 0 );
for ( std::size_t i = 0; i < images.size(); ++i )
{
images[ i ]->setName( str );
image_views[ i ]->setName( str );
}
return index;
}
friend class RenderPassBuilder;

View File

@@ -10,27 +10,6 @@
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 RenderPassBuilder
{
std::vector< vk::AttachmentDescription > attachment_descriptions {};
@@ -39,8 +18,6 @@ namespace fgl::engine
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; }
@@ -69,30 +46,6 @@ namespace fgl::engine
... );
}
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();
};

View File

@@ -74,7 +74,7 @@ namespace fgl::engine
void Renderer::recreateSwapchain()
{
ZoneScoped;
log::info( "Rebuilding swapchain" );
std::cout << "Rebuilding swap chain" << std::endl;
auto extent { m_window.getExtent() };
while ( extent.width == 0 || extent.height == 0 )
@@ -145,8 +145,7 @@ namespace fgl::engine
throw std::runtime_error( "Failed to submit commmand buffer" );
is_frame_started = false;
current_frame_index =
static_cast< std::uint16_t >( ( current_frame_index + 1 ) % SwapChain::MAX_FRAMES_IN_FLIGHT );
current_frame_idx = static_cast< std::uint16_t >( ( current_frame_idx + 1 ) % SwapChain::MAX_FRAMES_IN_FLIGHT );
}
void Renderer::setViewport( const vk::raii::CommandBuffer& buffer )
@@ -182,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( current_frame_index, current_present_index );
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();

View File

@@ -11,6 +11,7 @@
#include "Device.hpp"
#include "SwapChain.hpp"
#include "engine/Window.hpp"
//clang-format: off
#include <tracy/TracyVulkan.hpp>
@@ -32,7 +33,7 @@ namespace fgl::engine
std::optional< TracyVkCtx > m_tracy_ctx { std::nullopt };
PresentIndex current_present_index { std::numeric_limits< PresentIndex >::max() };
FrameIndex current_frame_index { 0 };
FrameIndex current_frame_idx { 0 };
bool is_frame_started { false };
void createCommandBuffers();
@@ -50,10 +51,16 @@ 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_index;
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; }
@@ -61,10 +68,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_index ];
return m_command_buffer[ current_frame_idx ];
}
vk::raii::CommandBuffer& getCurrentGuiCommandBuffer() { return m_gui_command_buffer[ current_frame_index ]; }
vk::raii::CommandBuffer& getCurrentGuiCommandBuffer() { return m_gui_command_buffer[ current_frame_idx ]; }
TracyVkCtx getCurrentTracyCTX() const
{

View File

@@ -198,17 +198,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 );
}
};

View File

@@ -17,63 +17,69 @@ namespace fgl::engine
SwapChain::SwapChain( const vk::Extent2D extent, PhysicalDevice& phy_device ) :
m_phy_device( phy_device ),
m_swapchain_support( Device::getInstance().getSwapChainSupport() ),
m_surface_format( chooseSwapSurfaceFormat( m_swapchain_support.formats ) ),
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() ),
m_swap_chain_extent( chooseSwapExtent( m_swapchain_support.capabilities ) ),
m_swapchain_extent( extent ),
old_swap_chain( nullptr ),
m_swapchain( createSwapChain() ),
m_swap_chain_images( createSwapchainImages() ),
m_render_attachments( getSwapChainImageFormat(), findDepthFormat() ),
render_attachments( getSwapChainImageFormat(), findDepthFormat() ),
m_render_pass( createRenderPass() ),
m_swap_chain_buffers( createFramebuffers() ),
m_clear_values( populateAttachmentClearValues() ),
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( createGBufferCompositeDescriptors() )
m_composite_descriptor_set( createCompositeDescriptors() )
{
init();
}
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_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() ),
m_swap_chain_extent( chooseSwapExtent( m_swapchain_support.capabilities ) ),
m_swapchain_extent( extent ),
old_swap_chain( previous ),
m_swapchain( createSwapChain() ),
m_swap_chain_images( createSwapchainImages() ),
m_render_attachments( getSwapChainImageFormat(), findDepthFormat() ),
render_attachments( getSwapChainImageFormat(), findDepthFormat() ),
m_render_pass( createRenderPass() ),
m_swap_chain_buffers( createFramebuffers() ),
m_clear_values( populateAttachmentClearValues() ),
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( createGBufferCompositeDescriptors() )
m_composite_descriptor_set( createCompositeDescriptors() )
{
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()
{
createSyncObjects();
}
std::pair< vk::Result, std::uint32_t > SwapChain::acquireNextImage()
std::pair< vk::Result, PresentIndex > SwapChain::acquireNextImage()
{
ZoneScoped;
std::vector< vk::Fence > fences { in_flight_fences[ current_frame_index ] };
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 )
@@ -81,47 +87,47 @@ namespace fgl::engine
auto result { m_swapchain.acquireNextImage(
std::numeric_limits< uint64_t >::max(),
imageAvailableSemaphores[ current_frame_index ] // must be a not signaled semaphore
image_available_sem[ m_current_frame_index ] // must be a not signaled semaphore
) };
return result;
}
vk::Result SwapChain::
submitCommandBuffers( const vk::raii::CommandBuffer& buffers, const PresentIndex current_present_index )
submitCommandBuffers( const vk::raii::CommandBuffer& buffers, const PresentIndex present_index )
{
ZoneScoped;
images_in_flight[ current_present_index ] = in_flight_fences[ current_frame_index ];
images_in_flight[ present_index ] = in_flight_fence[ m_current_frame_index ];
std::vector< vk::Fence > fences { images_in_flight[ current_present_index ] };
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 )
throw std::runtime_error( "failed to wait for fences!" );
vk::SubmitInfo submitInfo {};
vk::SubmitInfo m_submit_info {};
std::vector< vk::Semaphore > wait_sems { imageAvailableSemaphores[ 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,
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[ current_frame_index ] };
submitInfo.setSignalSemaphores( signaled_semaphores );
std::vector< vk::Semaphore > signaled_semaphores { render_finished_sem[ 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, in_flight_fences[ current_frame_index ] );
Device::getInstance().graphicsQueue().submit( m_submit_info, in_flight_fence[ m_current_frame_index ] );
vk::PresentInfoKHR presentInfo = {};
@@ -130,7 +136,7 @@ namespace fgl::engine
std::vector< vk::SwapchainKHR > swapchains { m_swapchain };
presentInfo.setSwapchains( swapchains );
std::array< std::uint32_t, 1 > indicies { { current_present_index } };
std::array< std::uint32_t, 1 > indicies { { present_index } };
presentInfo.setImageIndices( indicies );
if ( auto present_result = Device::getInstance().presentQueue().presentKHR( presentInfo );
@@ -141,7 +147,7 @@ namespace fgl::engine
throw std::runtime_error( "failed to present swap chain image!" );
}
current_frame_index = ( current_frame_index + 1 ) % MAX_FRAMES_IN_FLIGHT;
m_current_frame_index = ( m_current_frame_index + 1 ) % MAX_FRAMES_IN_FLIGHT;
return vk::Result::eSuccess;
}
@@ -150,24 +156,22 @@ namespace fgl::engine
{
ZoneScoped;
const vk::PresentModeKHR present_mode { chooseSwapPresentMode( m_swapchain_support.presentModes ) };
uint32_t image_count = m_swapchain_support.capabilities.minImageCount + 1;
if ( m_swapchain_support.capabilities.maxImageCount > 0
&& image_count > m_swapchain_support.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 )
{
image_count = m_swapchain_support.capabilities.maxImageCount;
image_count = m_swapchain_details.capabilities.maxImageCount;
}
vk::SwapchainCreateInfoKHR create_info = {};
create_info.surface = Device::getInstance().surface();
vk::SwapchainCreateInfoKHR createInfo = {};
createInfo.surface = Device::getInstance().surface();
create_info.minImageCount = image_count;
create_info.imageFormat = m_surface_format.format;
create_info.imageColorSpace = m_surface_format.colorSpace;
create_info.imageExtent = m_swap_chain_extent;
create_info.imageArrayLayers = 1;
create_info.imageUsage = vk::ImageUsageFlagBits::eColorAttachment;
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;
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() };
@@ -178,61 +182,58 @@ namespace fgl::engine
{
// If the familys are not the same then the swapchain must be shared between
// both queues.
create_info.imageSharingMode = vk::SharingMode::eConcurrent;
create_info.queueFamilyIndexCount = 2;
create_info.pQueueFamilyIndices = queueFamilyIndices;
createInfo.imageSharingMode = vk::SharingMode::eConcurrent;
createInfo.queueFamilyIndexCount = 2;
createInfo.pQueueFamilyIndices = queueFamilyIndices;
}
else
{
create_info.imageSharingMode = vk::SharingMode::eExclusive;
create_info.queueFamilyIndexCount = 0; // Optional
create_info.pQueueFamilyIndices = nullptr; // Optional
createInfo.imageSharingMode = vk::SharingMode::eExclusive;
createInfo.queueFamilyIndexCount = 0; // Optional
createInfo.pQueueFamilyIndices = nullptr; // Optional
}
create_info.preTransform = m_swapchain_support.capabilities.currentTransform;
create_info.compositeAlpha = vk::CompositeAlphaFlagBitsKHR::eOpaque;
createInfo.preTransform = m_swapchain_details.capabilities.currentTransform;
createInfo.compositeAlpha = vk::CompositeAlphaFlagBitsKHR::eOpaque;
create_info.presentMode = present_mode;
create_info.clipped = VK_TRUE;
createInfo.presentMode = m_present_mode;
createInfo.clipped = VK_TRUE;
create_info.oldSwapchain = ( old_swap_chain == nullptr ? VK_NULL_HANDLE : *old_swap_chain->m_swapchain );
createInfo.oldSwapchain = old_swap_chain == nullptr ? VK_NULL_HANDLE : *old_swap_chain->m_swapchain;
return Device::getInstance()->createSwapchainKHR( create_info );
return Device::getInstance()->createSwapchainKHR( createInfo );
}
std::vector< std::shared_ptr< Image > > SwapChain::createSwapchainImages()
std::vector< Image > SwapChain::createSwapchainImages()
{
std::vector< vk::Image > swap_chain_images { m_swapchain.getImages() };
std::vector< std::shared_ptr< Image > > images {};
images.reserve( swap_chain_images.size() );
std::vector< Image > images {};
for ( std::uint64_t i = 0; i < swap_chain_images.size(); ++i )
for ( std::uint64_t i = 0; i < swap_chain_images.size(); i++ )
{
images.emplace_back( std::make_shared< Image >(
m_swap_chain_extent,
auto& itter = images.emplace_back(
m_swapchain_extent,
m_surface_format.format,
swap_chain_images[ i ],
vk::ImageUsageFlagBits::eColorAttachment ) );
vk::ImageUsageFlagBits::eColorAttachment );
itter.setName( "Swapchain image: " + std::to_string( i ) );
}
assert( swap_chain_images.size() == images.size() );
return images;
}
vk::raii::RenderPass SwapChain::createRenderPass()
{
ZoneScoped;
RenderPassBuilder render_pass_builder {};
//Present attachment
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 );
render_attachments.color,
render_attachments.depth,
gbuffer.position,
gbuffer.normal,
gbuffer.albedo,
gbuffer.composite );
static_assert( is_attachment< ColoredPresentAttachment > );
static_assert( is_attachment< DepthAttachment > );
@@ -243,11 +244,7 @@ namespace fgl::engine
UsedAttachment< ColorAttachment, vk::ImageLayout::eColorAttachmentOptimal >,
UsedAttachment< ColorAttachment, vk::ImageLayout::eColorAttachmentOptimal >,
UsedAttachment< ColorAttachment, vk::ImageLayout::eColorAttachmentOptimal > >
g_buffer_subpass { 0,
m_render_attachments.depth,
m_gbuffer_attachments.position,
m_gbuffer_attachments.normal,
m_gbuffer_attachments.albedo };
g_buffer_subpass { 0, render_attachments.depth, gbuffer.position, gbuffer.normal, gbuffer.albedo };
g_buffer_subpass.registerDependencyFromExternal(
vk::AccessFlagBits::eDepthStencilAttachmentWrite,
@@ -258,17 +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,
m_render_attachments.depth,
m_gbuffer_attachments.composite,
m_gbuffer_attachments.position,
m_gbuffer_attachments.normal,
m_gbuffer_attachments.albedo };
composite_subpass { 1, gbuffer.composite, gbuffer.position, gbuffer.normal, gbuffer.albedo };
composite_subpass.registerDependencyFromExternal(
vk::AccessFlagBits::eColorAttachmentWrite, vk::PipelineStageFlagBits::eColorAttachmentOutput );
@@ -282,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<
@@ -297,15 +285,22 @@ namespace fgl::engine
UsedAttachment< DepthAttachment, vk::ImageLayout::eDepthStencilAttachmentOptimal >,
UsedAttachment< ColoredPresentAttachment, vk::ImageLayout::eColorAttachmentOptimal >,
InputAttachment< ColorAttachment, vk::ImageLayout::eShaderReadOnlyOptimal > >
gui_subpass { 2, m_render_attachments.depth, m_render_attachments.color, m_gbuffer_attachments.composite };
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 );
/*
g_buffer_subpass -> composite_subpass -> gui_subpass
*/
gui_subpass.registerDependencyFrom(
composite_subpass,
vk::AccessFlagBits::eColorAttachmentWrite,
@@ -323,11 +318,7 @@ 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 );
@@ -336,81 +327,69 @@ namespace fgl::engine
return render_pass_builder.create();
}
template < is_attachment... Attachments >
std::vector< std::shared_ptr< ImageView > >
fillViewsFromAttachments( uint8_t frame_idx, Attachments&&... attachments )
{
std::vector< std::shared_ptr< ImageView > > views {};
views.resize( sizeof...( Attachments ) );
( ( attachments.fillVec( frame_idx, views ) ), ... );
return views;
}
std::vector< std::vector< vk::raii::Framebuffer > > SwapChain::createFramebuffers()
std::vector< vk::raii::Framebuffer > SwapChain::createFramebuffers()
{
ZoneScoped;
assert( imageCount() > 0 );
render_attachments.color.linkImages( m_swap_chain_images );
m_render_attachments.color.linkImages( m_swap_chain_images );
render_attachments.depth.createResources( imageCount(), getSwapChainExtent() );
render_attachments.depth.setClear( vk::ClearDepthStencilValue( 1.0f, 0 ) );
m_render_attachments.depth.createResources( imageCount(), getSwapChainExtent() );
m_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 } } ) );
// 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 );
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 } } ) );
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 } } ) );
;
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 } } ) );
std::vector< std::vector< vk::raii::Framebuffer > > framebuffers {};
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 } } ) );
for ( std::uint16_t present_idx = 0; present_idx < imageCount(); ++present_idx )
for ( PresentIndex i = 0; i < imageCount(); ++i )
{
std::vector< vk::raii::Framebuffer > temp {};
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" ) ) );
}
for ( FrameIndex frame_idx = 0; frame_idx < SwapChain::MAX_FRAMES_IN_FLIGHT; frame_idx++ )
{
std::vector< vk::ImageView > attachments {};
std::vector< vk::raii::Framebuffer > framebuffers {};
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 ) );
framebuffers.reserve( imageCount() );
//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;
for ( uint8_t i = 0; i < imageCount(); i++ )
{
std::vector< vk::ImageView > attachments { getViewsForFrame(
i,
render_attachments.color,
render_attachments.depth,
gbuffer.position,
gbuffer.normal,
gbuffer.albedo,
gbuffer.composite ) };
temp.emplace_back( Device::getInstance()->createFramebuffer( framebufferInfo ) );
}
//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;
framebuffers.emplace_back( std::move( temp ) );
framebuffers.push_back( Device::getInstance()->createFramebuffer( framebufferInfo ) );
}
return framebuffers;
@@ -419,9 +398,9 @@ namespace fgl::engine
void SwapChain::createSyncObjects()
{
ZoneScoped;
imageAvailableSemaphores.reserve( MAX_FRAMES_IN_FLIGHT );
renderFinishedSemaphores.reserve( MAX_FRAMES_IN_FLIGHT );
in_flight_fences.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 {};
@@ -433,9 +412,9 @@ namespace fgl::engine
{
auto& device { Device::getInstance() };
imageAvailableSemaphores.push_back( device->createSemaphore( semaphoreInfo ) );
renderFinishedSemaphores.push_back( device->createSemaphore( semaphoreInfo ) );
in_flight_fences.push_back( device->createFence( fenceInfo ) );
image_available_sem.push_back( device->createSemaphore( semaphoreInfo ) );
render_finished_sem.push_back( device->createSemaphore( semaphoreInfo ) );
in_flight_fence.push_back( device->createFence( fenceInfo ) );
}
}
@@ -454,13 +433,12 @@ namespace fgl::engine
return available_formats[ 0 ];
}
vk::PresentModeKHR SwapChain::chooseSwapPresentMode( const std::vector< vk::PresentModeKHR >&
available_present_modes )
vk::PresentModeKHR SwapChain::chooseSwapPresentMode( const std::vector< vk::PresentModeKHR >& present_modes )
{
ZoneScoped;
for ( const auto& availablePresentMode : available_present_modes )
for ( const auto& mode : present_modes )
{
switch ( availablePresentMode )
switch ( mode )
{
case vk::PresentModeKHR::eImmediate:
std::cout << "Present mode: Immediate" << std::endl;
@@ -483,27 +461,20 @@ namespace fgl::engine
}
}
for ( const auto& present_mode_khr : available_present_modes )
for ( const auto& mode : present_modes )
{
if ( present_mode_khr == vk::PresentModeKHR::eMailbox )
if ( mode == vk::PresentModeKHR::eMailbox )
{
std::cout << "Present mode: Mailbox: ACTIVE" << std::endl;
return present_mode_khr;
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() )
@@ -512,67 +483,64 @@ 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;
}
}
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 > descriptors {};
std::vector< std::unique_ptr< descriptors::DescriptorSet > > data;
data.resize( imageCount() );
for ( FrameIndex frame_idx = 0; frame_idx < SwapChain::MAX_FRAMES_IN_FLIGHT; ++frame_idx )
for ( PresentIndex i = 0; i < imageCount(); ++i )
{
auto gbuffer_set { std::make_unique< descriptors::DescriptorSet >( GBufferDescriptorSet::createLayout() ) };
auto set { std::make_unique< descriptors::DescriptorSet >( GBufferDescriptorSet::createLayout() ) };
gbuffer_set->setMaxIDX( 2 );
set->setMaxIDX( 2 );
gbuffer_set->bindAttachment(
0, m_gbuffer_attachments.position.view( frame_idx ), vk::ImageLayout::eShaderReadOnlyOptimal );
set->bindAttachment( 0, gbuffer.position.getView( i ), vk::ImageLayout::eShaderReadOnlyOptimal );
gbuffer_set->bindAttachment(
1, m_gbuffer_attachments.normal.view( frame_idx ), vk::ImageLayout::eShaderReadOnlyOptimal );
set->bindAttachment( 1, gbuffer.normal.getView( i ), vk::ImageLayout::eShaderReadOnlyOptimal );
gbuffer_set->bindAttachment(
2, m_gbuffer_attachments.albedo.view( frame_idx ), vk::ImageLayout::eShaderReadOnlyOptimal );
set->bindAttachment( 2, gbuffer.albedo.getView( i ), vk::ImageLayout::eShaderReadOnlyOptimal );
gbuffer_set->update();
set->update();
descriptors.at( frame_idx ) = std::move( gbuffer_set );
data[ i ] = std::move( set );
}
return descriptors;
return data;
}
std::array< std::unique_ptr< descriptors::DescriptorSet >, SwapChain::MAX_FRAMES_IN_FLIGHT > SwapChain::
createGBufferCompositeDescriptors()
std::vector< std::unique_ptr< descriptors::DescriptorSet > > SwapChain::createCompositeDescriptors()
{
std::array< std::unique_ptr< descriptors::DescriptorSet >, SwapChain::MAX_FRAMES_IN_FLIGHT > descriptors {};
std::vector< std::unique_ptr< descriptors::DescriptorSet > > data;
data.resize( imageCount() );
for ( FrameIndex frame_idx = 0; frame_idx < SwapChain::MAX_FRAMES_IN_FLIGHT; ++frame_idx )
for ( PresentIndex i = 0; i < imageCount(); ++i )
{
auto composite_set {
std::make_unique< descriptors::DescriptorSet >( GBufferCompositeDescriptorSet::createLayout() )
};
composite_set->setMaxIDX( 0 );
composite_set->bindAttachment(
0, m_gbuffer_attachments.composite.view( frame_idx ), vk::ImageLayout::eShaderReadOnlyOptimal );
composite_set->setMaxIDX( 1 );
composite_set->bindAttachment( 0, gbuffer.composite.getView( i ), vk::ImageLayout::eShaderReadOnlyOptimal );
composite_set->update();
m_gbuffer_composite_descriptor_set.at( frame_idx ) = std::move( composite_set );
data[ i ] = std::move( composite_set );
}
return descriptors;
return data;
}
vk::Format SwapChain::findDepthFormat()

View File

@@ -1,15 +1,13 @@
#pragma once
#include <vulkan/vulkan.h>
#include <memory>
#include <vector>
#include "Device.hpp"
#include "RenderPassBuilder.hpp"
#include "engine/FrameInfo.hpp"
#include "engine/rendering/types.hpp"
#include "engine/texture/Texture.hpp"
#include "types.hpp"
namespace fgl::engine
{
@@ -17,31 +15,30 @@ namespace fgl::engine
{
public:
static constexpr FrameIndex MAX_FRAMES_IN_FLIGHT { 2 };
static constexpr std::uint16_t MAX_FRAMES_IN_FLIGHT { 2 };
private:
PhysicalDevice& m_phy_device;
std::shared_ptr< SwapChain > old_swap_chain {};
SwapChainSupportDetails m_swapchain_support;
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;
vk::Extent2D m_swap_chain_extent;
vk::Extent2D m_swapchain_extent;
std::shared_ptr< SwapChain > old_swap_chain;
vk::raii::SwapchainKHR m_swapchain;
std::vector< std::shared_ptr< Image > > m_swap_chain_images;
std::vector< Image > m_swap_chain_images;
//! Attachments for the final render target
struct
{
ColoredPresentAttachment color; // Present attachment
ColoredPresentAttachment color;
DepthAttachment depth;
} m_render_attachments;
} render_attachments;
struct
{
@@ -49,80 +46,89 @@ namespace fgl::engine
ColorAttachment normal { vk::Format::eR16G16B16A16Sfloat };
ColorAttachment albedo { vk::Format::eR8G8B8A8Unorm };
ColorAttachment composite { vk::Format::eR8G8B8A8Unorm };
} m_gbuffer_attachments {};
} gbuffer {};
public:
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:
RenderPassBuilder render_pass_builder {};
vk::raii::RenderPass m_render_pass;
std::vector< std::vector< vk::raii::Framebuffer > > m_swap_chain_buffers;
std::vector< vk::raii::Framebuffer > m_swap_chain_buffers;
std::vector< vk::raii::Semaphore > imageAvailableSemaphores {};
std::vector< vk::raii::Semaphore > renderFinishedSemaphores {};
std::vector< vk::raii::Fence > in_flight_fences {};
std::vector< vk::ClearValue > m_clear_values;
std::vector< std::unique_ptr< descriptors::DescriptorSet > > m_gbuffer_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 {};
std::vector< vk::raii::Fence > in_flight_fence {};
std::vector< vk::Fence > images_in_flight {};
FrameIndex current_frame_index { 0 };
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;
size_t m_current_frame_index { 0 };
void init();
[[nodiscard]] vk::raii::SwapchainKHR createSwapChain();
[[nodiscard]] std::vector< std::shared_ptr< Image > > createSwapchainImages();
[[nodiscard]] std::vector< Image > createSwapchainImages();
[[nodiscard]] vk::raii::RenderPass createRenderPass();
[[nodiscard]] std::vector< std::vector< vk::raii::Framebuffer > > createFramebuffers();
[[nodiscard]] std::vector< vk::raii::Framebuffer > createFramebuffers();
void createSyncObjects();
std::vector< vk::ClearValue > populateAttachmentClearValues()
// Helper functions
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 )
{
return 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 );
std::vector< vk::ImageView > view {};
view.resize( sizeof...( Attachments ) );
( ( view[ attachments.getIndex() ] = *attachments.getView( frame_idx ) ), ... );
return view;
}
template < is_attachment... Attachments >
std::vector< vk::ClearValue > populateAttachmentClearValues( Attachments&... attachments )
static std::vector< vk::ClearValue > gatherClearValues( Attachments... attachments )
{
std::vector< vk::ClearValue > values {};
std::vector< vk::ClearValue > clear_values {};
clear_values.resize( sizeof...( Attachments ) );
values.resize( sizeof...( Attachments ) );
( ( values[ attachments.getIndex() ] = attachments.m_clear_value ), ... );
( ( clear_values[ attachments.getIndex() ] = attachments.m_clear_value ), ... );
return values;
return clear_values;
}
// Helper functions
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 >
createGBufferDescriptors();
std::array< std::unique_ptr< descriptors::DescriptorSet >, SwapChain::MAX_FRAMES_IN_FLIGHT >
createGBufferCompositeDescriptors();
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( 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 );
@@ -131,33 +137,22 @@ namespace fgl::engine
SwapChain( const SwapChain& ) = delete;
SwapChain& operator=( const SwapChain& ) = delete;
vk::raii::Framebuffer& getFrameBuffer( const FrameIndex frame_index, const std::uint16_t present_idx );
vk::raii::Framebuffer& getFrameBuffer( const PresentIndex present_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
{
assert( m_swap_chain_images.size() > 0 );
return m_swap_chain_images.size();
}
PresentIndex imageCount() const { return static_cast< std::uint16_t >( m_swap_chain_images.size() ); }
vk::Format getSwapChainImageFormat() const
{
assert( m_swap_chain_format != vk::Format::eUndefined );
return m_swap_chain_format;
}
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
{
@@ -167,15 +162,14 @@ 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();
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, PresentIndex current_present_index );
submitCommandBuffers( const vk::raii::CommandBuffer& buffers, PresentIndex present_index );
};
} // namespace fgl::engine

View File

@@ -1,11 +1,13 @@
//
// Created by kj16609 on 7/10/24.
// Created by kj16609 on 7/11/24.
//
#pragma once
#include <cstdint>
namespace fgl::engine
{
using FrameIndex = std::uint16_t;
using PresentIndex = std::uint16_t;
} // namespace fgl::engine
using FrameIndex = std::uint16_t;
}

View File

@@ -28,18 +28,17 @@ namespace fgl::engine
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;
}
void GuiSystem::pass( FrameInfo& info )
{
auto& command_buffer { setupSystem( info ) };
TracyVkZone( info.tracy_ctx, *command_buffer, "Debug GUI Pass" );
command_buffer.draw( 3, 1, 0, 0 );