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