Gets dynamic rendering mostly working

This commit is contained in:
2025-01-17 21:17:07 -05:00
parent 615e994bd5
commit 83f12f8f7e
35 changed files with 966 additions and 719 deletions

View File

@@ -8,7 +8,7 @@
#include "engine/assets/model/Model.hpp"
#include "engine/assets/model/builders/SceneBuilder.hpp"
#include "engine/camera/Camera.hpp"
#include "engine/camera/CameraSwapchain.hpp"
#include "engine/camera/GBufferSwapchain.hpp"
#include "engine/filesystem/scanner/FileScanner.hpp"
#include "engine/filesystem/types.hpp"
#include "engine/gameobjects/components/ModelComponent.hpp"
@@ -53,9 +53,7 @@ namespace fgl::engine::gui
obj.addFlag( IsEntity | IsVisible );
auto component {
std::make_unique< ModelComponent >( std::move( model ) )
};
auto component { std::make_unique< ModelComponent >( std::move( model ) ) };
obj.addComponent( std::move( component ) );
@@ -208,16 +206,17 @@ namespace fgl::engine::gui
default:
[[fallthrough]];
case Composite:
camera.getSwapchain().m_g_buffer_composite_img[ frame_index ]->drawImGui( target_size );
camera.getCompositeSwapchain().m_gbuffer_target[ frame_index ]->drawImGui( target_size );
// camera.getSwapchain().m_g_buffer_composite_img[ frame_index ]->drawImGui( target_size );
break;
case Albedo:
camera.getSwapchain().m_g_buffer_color_img[ frame_index ]->drawImGui( target_size );
// camera.getSwapchain().m_g_buffer_color_img[ frame_index ]->drawImGui( target_size );
break;
case Normal:
camera.getSwapchain().m_g_buffer_normal_img[ frame_index ]->drawImGui( target_size );
// camera.getSwapchain().m_g_buffer_normal_img[ frame_index ]->drawImGui( target_size );
break;
case Position:
camera.getSwapchain().m_g_buffer_position_img[ frame_index ]->drawImGui( target_size );
// camera.getSwapchain().m_g_buffer_position_img[ frame_index ]->drawImGui( target_size );
break;
}

View File

@@ -35,46 +35,53 @@ int main()
log::debug( "Vulkan instance version: {}.{}.{}.{}", major, minor, patch, minor );
EngineContext engine_ctx {};
// We start by hooking into the imgui rendering.
engine_ctx.hookInitImGui( gui::initGui );
engine_ctx.hookPreFrame( gui::startDrawImGui );
engine_ctx.hookEarlyFrame( gui::drawImGui );
engine_ctx.hookLateFrame( gui::endDrawImGui );
engine_ctx.hookDestruction( gui::cleanupImGui );
// Now we need to create the camera for the editor.
CameraManager& camera_manager { engine_ctx.cameraManager() };
auto& editor_camera { camera_manager.getPrimary() };
editor_camera->setFOV( glm::radians( 90.0f ) );
//! Will be true until the window says it wants to close.
while ( engine_ctx.good() )
try
{
debug::timing::reset();
engine_ctx.tickDeltaTime();
EngineContext engine_ctx {};
engine_ctx.handleTransfers();
// We start by hooking into the imgui rendering.
engine_ctx.hookInitImGui( gui::initGui );
engine_ctx.hookPreFrame( gui::startDrawImGui );
engine_ctx.hookEarlyFrame( gui::drawImGui );
engine_ctx.hookLateFrame( gui::endDrawImGui );
engine_ctx.hookDestruction( gui::cleanupImGui );
// Process input
engine_ctx.processInput();
// Now we need to create the camera for the editor.
CameraManager& camera_manager { engine_ctx.cameraManager() };
// Here we can decide if we want to tick fully or not.
auto& editor_camera { camera_manager.getPrimary() };
// Simulate step
engine_ctx.tickSimulation();
editor_camera->setFOV( glm::radians( 90.0f ) );
// Update the viewer camera
//! Will be true until the window says it wants to close.
while ( engine_ctx.good() )
{
debug::timing::reset();
engine_ctx.tickDeltaTime();
// Render step
engine_ctx.renderFrame();
engine_ctx.handleTransfers();
engine_ctx.finishFrame();
// This will 'end' the root node, Which is created on 'reset'
debug::timing::internal::pop();
// Process input
engine_ctx.processInput();
// Here we can decide if we want to tick fully or not.
// Simulate step
engine_ctx.tickSimulation();
// Update the viewer camera
// Render step
engine_ctx.renderFrame();
engine_ctx.finishFrame();
// This will 'end' the root node, Which is created on 'reset'
debug::timing::internal::pop();
}
}
catch ( const vk::LayerNotPresentError& e )
{
log::info( "{}:{}", e.code().message(), e.what() );
}
return EXIT_SUCCESS;

View File

@@ -14,7 +14,7 @@
#include "assets/material/Material.hpp"
#include "camera/Camera.hpp"
#include "camera/CameraManager.hpp"
#include "camera/CameraRenderer.hpp"
#include "camera/GBufferRenderer.hpp"
#include "debug/timing/FlameGraph.hpp"
#include "engine/assets/model/builders/SceneBuilder.hpp"
#include "engine/assets/transfer/TransferManager.hpp"

View File

@@ -5,7 +5,7 @@
#include "FrameInfo.hpp"
#include "camera/Camera.hpp"
#include "camera/CameraSwapchain.hpp"
#include "camera/GBufferSwapchain.hpp"
namespace fgl::engine
{

View File

@@ -5,6 +5,7 @@
#pragma once
//clang-format: off
#include <vulkan/vulkan.hpp>
#include <tracy/TracyVulkan.hpp>
//clang-format: on

View File

@@ -11,17 +11,188 @@ namespace fgl::engine
std::shared_ptr< ImageView > Image::getView()
{
if ( !view.expired() )
return view.lock();
if ( !m_view.expired() )
return m_view.lock();
else
{
assert( m_handle );
auto ptr { std::make_shared< ImageView >( m_handle ) };
view = ptr;
m_view = ptr;
return ptr;
}
}
constexpr vk::AccessFlags getAccessFlags( const vk::ImageLayout layout )
{
switch ( layout )
{
case vk::ImageLayout::eUndefined:
return vk::AccessFlags( 0 );
case vk::ImageLayout::eGeneral:
break;
case vk::ImageLayout::eColorAttachmentOptimal:
return vk::AccessFlagBits::eColorAttachmentRead | vk::AccessFlagBits::eColorAttachmentWrite;
case vk::ImageLayout::eDepthStencilAttachmentOptimal:
break;
case vk::ImageLayout::eDepthStencilReadOnlyOptimal:
break;
case vk::ImageLayout::eShaderReadOnlyOptimal:
return vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eInputAttachmentRead;
case vk::ImageLayout::eTransferSrcOptimal:
return vk::AccessFlagBits::eTransferRead;
case vk::ImageLayout::eTransferDstOptimal:
return vk::AccessFlagBits::eTransferWrite;
case vk::ImageLayout::ePreinitialized:
return vk::AccessFlagBits::eHostWrite;
case vk::ImageLayout::eDepthReadOnlyStencilAttachmentOptimal:
break;
case vk::ImageLayout::eDepthAttachmentStencilReadOnlyOptimal:
break;
case vk::ImageLayout::eDepthReadOnlyOptimal:
[[fallthrough]];
case vk::ImageLayout::eDepthAttachmentOptimal:
return vk::AccessFlagBits::eDepthStencilAttachmentRead
| vk::AccessFlagBits::eDepthStencilAttachmentWrite;
case vk::ImageLayout::eStencilAttachmentOptimal:
break;
case vk::ImageLayout::eStencilReadOnlyOptimal:
break;
case vk::ImageLayout::eReadOnlyOptimal:
break;
case vk::ImageLayout::eAttachmentOptimal:
break;
case vk::ImageLayout::ePresentSrcKHR:
return vk::AccessFlags( 0 );
case vk::ImageLayout::eVideoDecodeDstKHR:
break;
case vk::ImageLayout::eVideoDecodeSrcKHR:
break;
case vk::ImageLayout::eVideoDecodeDpbKHR:
break;
case vk::ImageLayout::eSharedPresentKHR:
break;
case vk::ImageLayout::eFragmentDensityMapOptimalEXT:
break;
case vk::ImageLayout::eFragmentShadingRateAttachmentOptimalKHR:
return vk::AccessFlagBits::eFragmentShadingRateAttachmentReadKHR;
case vk::ImageLayout::eRenderingLocalReadKHR:
return vk::AccessFlagBits::eColorAttachmentWrite;
case vk::ImageLayout::eVideoEncodeDstKHR:
break;
case vk::ImageLayout::eVideoEncodeSrcKHR:
break;
case vk::ImageLayout::eVideoEncodeDpbKHR:
break;
case vk::ImageLayout::eAttachmentFeedbackLoopOptimalEXT:
break;
default:
FGL_UNREACHABLE();
}
FGL_UNREACHABLE();
}
constexpr vk::PipelineStageFlags getPipelineStageFlags( const vk::ImageLayout layout )
{
switch ( layout )
{
default:
FGL_UNREACHABLE();
case vk::ImageLayout::eUndefined:
return vk::PipelineStageFlagBits::eTopOfPipe;
case vk::ImageLayout::eGeneral:
break;
case vk::ImageLayout::eColorAttachmentOptimal:
return vk::PipelineStageFlagBits::eColorAttachmentOutput;
case vk::ImageLayout::eDepthStencilAttachmentOptimal:
break;
case vk::ImageLayout::eDepthStencilReadOnlyOptimal:
break;
case vk::ImageLayout::eShaderReadOnlyOptimal:
return vk::PipelineStageFlagBits::eVertexShader | vk::PipelineStageFlagBits::eFragmentShader;
case vk::ImageLayout::eTransferSrcOptimal:
[[fallthrough]];
case vk::ImageLayout::eTransferDstOptimal:
return vk::PipelineStageFlagBits::eTransfer;
case vk::ImageLayout::ePreinitialized:
break;
case vk::ImageLayout::eDepthReadOnlyStencilAttachmentOptimal:
break;
case vk::ImageLayout::eDepthAttachmentStencilReadOnlyOptimal:
break;
case vk::ImageLayout::eDepthAttachmentOptimal:
break;
case vk::ImageLayout::eDepthReadOnlyOptimal:
break;
case vk::ImageLayout::eStencilAttachmentOptimal:
break;
case vk::ImageLayout::eStencilReadOnlyOptimal:
break;
case vk::ImageLayout::eReadOnlyOptimal:
break;
case vk::ImageLayout::eAttachmentOptimal:
break;
case vk::ImageLayout::ePresentSrcKHR:
return vk::PipelineStageFlagBits::eBottomOfPipe;
case vk::ImageLayout::eVideoDecodeDstKHR:
break;
case vk::ImageLayout::eVideoDecodeSrcKHR:
break;
case vk::ImageLayout::eVideoDecodeDpbKHR:
break;
case vk::ImageLayout::eSharedPresentKHR:
break;
case vk::ImageLayout::eFragmentDensityMapOptimalEXT:
break;
case vk::ImageLayout::eFragmentShadingRateAttachmentOptimalKHR:
break;
case vk::ImageLayout::eRenderingLocalReadKHR:
break;
case vk::ImageLayout::eVideoEncodeDstKHR:
break;
case vk::ImageLayout::eVideoEncodeSrcKHR:
break;
case vk::ImageLayout::eVideoEncodeDpbKHR:
break;
case vk::ImageLayout::eAttachmentFeedbackLoopOptimalEXT:
break;
}
FGL_UNREACHABLE();
}
vk::ImageMemoryBarrier Image::transitionTo(
const vk::ImageLayout old_layout,
const vk::ImageLayout new_layout,
const vk::ImageSubresourceRange& range ) const
{
vk::ImageMemoryBarrier barrier {};
barrier.srcAccessMask = getAccessFlags( old_layout );
barrier.dstAccessMask = getAccessFlags( new_layout );
barrier.oldLayout = old_layout;
barrier.newLayout = new_layout;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.subresourceRange = range;
barrier.setImage( this->getVkImage() );
return barrier;
}
vk::ImageMemoryBarrier Image::transitionTo(
const vk::ImageLayout old_layout, const vk::ImageLayout new_layout, const vk::ImageAspectFlags aspect )
{
const vk::ImageSubresourceRange subresource { aspect, 0, 1, 0, 1 };
const vk::ImageMemoryBarrier barrier { transitionTo( old_layout, new_layout, subresource ) };
return barrier;
}
Image::Image(
const vk::Extent2D extent,
const vk::Format format,
@@ -44,7 +215,7 @@ namespace fgl::engine
Image& Image::operator=( const Image& other )
{
m_handle = other.m_handle;
view = {};
m_view = {};
return *this;
}
@@ -56,7 +227,7 @@ namespace fgl::engine
Image& Image::operator=( Image&& other ) noexcept
{
m_handle = std::move( other.m_handle );
view = std::move( other.view );
m_view = std::move( other.m_view );
m_extent = other.m_extent;
return *this;
}

View File

@@ -20,7 +20,7 @@ namespace fgl::engine
class Image
{
std::shared_ptr< ImageHandle > m_handle;
std::weak_ptr< ImageView > view {};
std::weak_ptr< ImageView > m_view {};
vk::Extent2D m_extent;
friend class memory::TransferManager;
@@ -54,6 +54,16 @@ namespace fgl::engine
const vk::Extent2D& getExtent() const { return m_extent; }
[[nodiscard]] std::shared_ptr< ImageView > getView();
vk::ImageMemoryBarrier transitionTo(
vk::ImageLayout old_layout, vk::ImageLayout new_layout, const vk::ImageSubresourceRange& range ) const;
vk::ImageMemoryBarrier transitionTo( vk::ImageLayout old_layout, vk::ImageLayout new_layout, vk::ImageAspectFlags aspect );
inline vk::ImageMemoryBarrier transitionColorTo(vk::ImageLayout old_layout, vk::ImageLayout new_layout)
{
return transitionTo( old_layout, new_layout, vk::ImageAspectFlagBits::eColor );
}
};
} // namespace fgl::engine

View File

@@ -109,12 +109,13 @@ namespace fgl::engine
Texture::Texture( std::vector< std::byte >&& data, const vk::Extent2D extent, const vk::Format format ) :
m_texture_id( texture_id_pool.getID() ),
m_image( std::make_shared< Image >(
extent,
format,
vk::ImageUsageFlagBits::eTransferDst | vk::ImageUsageFlagBits::eSampled,
vk::ImageLayout::eUndefined,
vk::ImageLayout::eShaderReadOnlyOptimal ) ),
m_image(
std::make_shared< Image >(
extent,
format,
vk::ImageUsageFlagBits::eTransferDst | vk::ImageUsageFlagBits::eSampled,
vk::ImageLayout::eUndefined,
vk::ImageLayout::eShaderReadOnlyOptimal ) ),
m_image_view( m_image->getView() ),
m_extent( extent ),
m_name( "Default Texture Name" )
@@ -147,6 +148,11 @@ namespace fgl::engine
texture_id_pool.markUnused( m_texture_id );
}
Image& Texture::getImageRef()
{
return *m_image;
}
vk::DescriptorImageInfo Texture::getDescriptor() const
{
return m_image_view->descriptorInfo( vk::ImageLayout::eGeneral );

View File

@@ -89,6 +89,8 @@ namespace fgl::engine
~Texture();
Image& getImageRef();
Texture( const Texture& ) = delete;
Texture& operator=( const Texture& ) = delete;

View File

@@ -9,8 +9,8 @@
#include <tracy/Tracy.hpp>
#include "CameraInfo.hpp"
#include "CameraRenderer.hpp"
#include "CameraSwapchain.hpp"
#include "GBufferRenderer.hpp"
#include "GBufferSwapchain.hpp"
#include "engine/debug/timing/FlameGraph.hpp"
namespace fgl::engine
@@ -69,11 +69,11 @@ namespace fgl::engine
{
ZoneScopedN( "Camera::pass" );
auto timer = debug::timing::push( "Camera" );
if ( m_cold && m_swapchain )
if ( m_cold && m_gbuffer_swapchain )
{
//TODO: Make some way to destroy the swapchain in a deffered manner.
m_old_swapchain = m_swapchain;
m_swapchain = nullptr;
// m_old_swapchain = m_gbuffer_swapchain;
m_gbuffer_swapchain = nullptr;
m_active = false;
}
@@ -82,19 +82,25 @@ namespace fgl::engine
assert( frame_info.camera == nullptr );
frame_info.camera = this;
if ( m_swapchain->getExtent() != m_target_extent )
if ( m_gbuffer_swapchain->getExtent() != m_target_extent )
{
remakeSwapchain( m_target_extent );
}
updateInfo( frame_info.frame_idx );
m_camera_renderer->pass( frame_info, *m_swapchain );
FGL_ASSERT( m_camera_renderer, "Camera renderer should not be nullptr" );
m_camera_renderer->pass( frame_info, *m_gbuffer_swapchain );
frame_info.camera = nullptr;
}
CameraSwapchain& Camera::getSwapchain() const
GBufferSwapchain& Camera::getSwapchain() const
{
return *m_swapchain;
return *m_gbuffer_swapchain;
}
CompositeSwapchain& Camera::getCompositeSwapchain() const
{
return *m_composite_swapchain;
}
void Camera::setViewport( const vk::raii::CommandBuffer& command_buffer )
@@ -103,7 +109,7 @@ namespace fgl::engine
viewport.x = 0.0f;
viewport.y = 0.0f;
const auto& [ width, height ] = m_swapchain->getExtent();
const auto& [ width, height ] = m_gbuffer_swapchain->getExtent();
viewport.width = static_cast< float >( width );
viewport.height = static_cast< float >( height );
viewport.minDepth = 0.0f;
@@ -116,7 +122,7 @@ namespace fgl::engine
void Camera::setScissor( const vk::raii::CommandBuffer& command_buffer )
{
const vk::Rect2D scissor { { 0, 0 }, m_swapchain->getExtent() };
const vk::Rect2D scissor { { 0, 0 }, m_gbuffer_swapchain->getExtent() };
const std::vector< vk::Rect2D > scissors { scissor };
@@ -126,8 +132,9 @@ namespace fgl::engine
void Camera::remakeSwapchain( vk::Extent2D extent )
{
this->setPerspectiveProjection( m_fov_y, aspectRatio(), constants::NEAR_PLANE, constants::FAR_PLANE );
m_old_swapchain = m_swapchain;
m_swapchain = std::make_shared< CameraSwapchain >( m_camera_renderer->getRenderpass(), extent );
m_composite_swapchain = std::make_unique< CompositeSwapchain >( extent );
m_gbuffer_swapchain = std::make_unique< GBufferSwapchain >( extent );
}
void Camera::setName( const std::string_view str )
@@ -137,15 +144,16 @@ namespace fgl::engine
float Camera::aspectRatio() const
{
return m_swapchain->getAspectRatio();
return m_gbuffer_swapchain->getAspectRatio();
}
void Camera::
copyOutput( const vk::raii::CommandBuffer& command_buffer, const FrameIndex frame_index, Image& target )
{
assert( m_swapchain->getExtent() == target.getExtent() );
assert( m_gbuffer_swapchain->getExtent() == target.getExtent() );
Image& source { this->getSwapchain().getOutput( frame_index ) };
Texture& source_tex { *m_composite_swapchain->m_gbuffer_target[ frame_index ] };
Image& source { source_tex.getImageRef() };
vk::ImageSubresourceRange range {};
range.aspectMask = vk::ImageAspectFlagBits::eColor;
@@ -192,7 +200,7 @@ namespace fgl::engine
{ barrier_from_source } );
vk::ImageCopy region {};
region.extent = vk::Extent3D( m_swapchain->getExtent(), 1 );
region.extent = vk::Extent3D( m_gbuffer_swapchain->getExtent(), 1 );
region.srcSubresource.aspectMask = vk::ImageAspectFlagBits::eColor;
region.srcSubresource.layerCount = 1;
@@ -318,14 +326,14 @@ namespace fgl::engine
return camera_descriptor_set;
}
Camera::Camera( const vk::Extent2D extent, memory::Buffer& buffer, std::unique_ptr< CameraRenderer >& renderer ) :
m_camera_renderer( renderer ),
m_transform(),
Camera::Camera( const vk::Extent2D extent, memory::Buffer& buffer, const std::shared_ptr< GBufferRenderer >& renderer ) :
m_target_extent( extent ),
m_camera_frame_info( buffer, SwapChain::MAX_FRAMES_IN_FLIGHT ),
m_swapchain( std::make_shared< CameraSwapchain >( m_camera_renderer->getRenderpass(), m_target_extent ) ),
m_name()
m_composite_swapchain( std::make_unique< CompositeSwapchain >( m_target_extent ) ),
m_gbuffer_swapchain( std::make_unique< GBufferSwapchain >( m_target_extent ) ),
m_camera_renderer( renderer ),
m_camera_frame_info( buffer, SwapChain::MAX_FRAMES_IN_FLIGHT )
{
FGL_ASSERT( renderer, "Camera renderer is null" );
this->setPerspectiveProjection( m_fov_y, aspectRatio(), constants::NEAR_PLANE, constants::FAR_PLANE );
this->setView( WorldCoordinate( constants::CENTER ), Rotation( 0.0f, 0.0f, 0.0f ) );

View File

@@ -12,6 +12,7 @@
#include <glm/gtx/string_cast.hpp>
#pragma GCC diagnostic pop
#include "CompositeSwapchain.hpp"
#include "engine/descriptors/DescriptorSet.hpp"
#include "engine/memory/buffers/HostSingleT.hpp"
#include "engine/memory/buffers/UniqueFrameSuballocation.hpp"
@@ -34,10 +35,10 @@ namespace fgl::engine
}
class Image;
struct FrameInfo;
class CameraRenderer;
class GBufferRenderer;
struct CameraInfo;
class CameraSwapchain;
class GBufferSwapchain;
class Camera;
FrustumBase createFrustum( float aspect, float fovy, float near, float far );
@@ -48,7 +49,12 @@ namespace fgl::engine
{
inline static CameraIDX m_camera_counter { 0 };
std::unique_ptr< CameraRenderer >& m_camera_renderer;
vk::Extent2D m_target_extent;
std::unique_ptr< CompositeSwapchain > m_composite_swapchain;
std::unique_ptr< GBufferSwapchain > m_gbuffer_swapchain;
std::shared_ptr< GBufferRenderer > m_camera_renderer;
//! True if the camera is active and to be rendered
bool m_active { true };
@@ -73,7 +79,6 @@ namespace fgl::engine
WorldTransform m_transform;
vk::Extent2D m_target_extent;
float m_fov_y { glm::radians( 90.0f ) };
PerFrameSuballocation< HostSingleT< CameraInfo > > m_camera_frame_info;
@@ -81,10 +86,6 @@ namespace fgl::engine
// Camera info is expected at binding 0
std::vector< std::unique_ptr< descriptors::DescriptorSet > > m_camera_info_descriptors {};
// TODO: Remove this old swapchain and instead do a proper deffered cleanup of it.
std::shared_ptr< CameraSwapchain > m_old_swapchain { nullptr };
std::shared_ptr< CameraSwapchain > m_swapchain;
std::string m_name;
Matrix< MatrixType::ModelToWorld > frustumTranslationMatrix() const;
@@ -96,7 +97,7 @@ namespace fgl::engine
Camera( vk::Extent2D test_extent ) : m_target_extent( test_extent ) {}
#endif
Camera( vk::Extent2D extent, memory::Buffer& buffer, std::unique_ptr< CameraRenderer >& renderer );
Camera( vk::Extent2D extent, memory::Buffer& buffer, const std::shared_ptr< GBufferRenderer >& renderer );
friend class CameraManager;
@@ -114,8 +115,6 @@ namespace fgl::engine
const std::string& getName() const;
static void initCameraRenderer();
void setExtent( vk::Extent2D extent );
const Rotation& getRotation() const { return m_transform.rotation; }
@@ -171,7 +170,8 @@ namespace fgl::engine
FGL_FORCE_INLINE NormalVector getDown() const
{
return NormalVector( glm::vec3( m_inverse_view_matrix[ 1 ] ) ); }
return NormalVector( glm::vec3( m_inverse_view_matrix[ 1 ] ) );
}
//! Updates the required info for rendering
void updateInfo( FrameIndex frame_index );
@@ -182,7 +182,8 @@ namespace fgl::engine
//! Performs the render pass for this camera
void pass( FrameInfo& frame_info );
CameraSwapchain& getSwapchain() const;
GBufferSwapchain& getSwapchain() const;
CompositeSwapchain& getCompositeSwapchain() const;
void setViewport( const vk::raii::CommandBuffer& command_buffer );
void setScissor( const vk::raii::CommandBuffer& command_buffer );
@@ -204,6 +205,4 @@ namespace fgl::engine
#endif
};
descriptors::DescriptorSetLayout& getCameraDescriptorSet();
} // namespace fgl::engine

View File

@@ -0,0 +1,46 @@
@startuml
'https://plantuml.com/component-diagram
package "Some Group" {
HTTP - [First Component]
[Another Component]
}
node "Other Groups" {
FTP - [Second Component]
[First Component] --> FTP
}
cloud {
[Example 1]
}
database "MySql" {
folder "This is my folder" {
[Folder 3]
}
frame "Foo" {
[Frame 4]
}
}
[Another Component] --> [Example 1]
[Example 1] --> [Folder 3]
[Folder 3] --> [Frame 4]
node "GBufferSwapchain" {
node "Albedo"
node "Metallic"
node "Position & Depth 16F4"
}
@enduml

View File

@@ -5,7 +5,7 @@
#include "CameraManager.hpp"
#include "Camera.hpp"
#include "CameraRenderer.hpp"
#include "GBufferRenderer.hpp"
#include "engine/debug/DEBUG_NAMES.hpp"
#include "engine/math/literals/size.hpp"
@@ -25,7 +25,7 @@ namespace fgl::engine
}
CameraManager::CameraManager() :
m_renderer( std::make_unique< CameraRenderer >() ),
m_renderer( std::make_shared< GBufferRenderer >() ),
m_data_buffer( 4_KiB, vk::BufferUsageFlagBits::eUniformBuffer, vk::MemoryPropertyFlagBits::eHostVisible )
{
m_primary_camera = createCamera( { 1920, 1080 } );

View File

@@ -17,7 +17,7 @@ namespace fgl::engine
class CameraManager
{
std::unique_ptr< CameraRenderer > m_renderer;
std::shared_ptr< GBufferRenderer > m_renderer;
memory::Buffer m_data_buffer;
std::shared_ptr< Camera > m_primary_camera { nullptr };

View File

@@ -1,182 +0,0 @@
//
// Created by kj16609 on 7/21/24.
//
#include "CameraRenderer.hpp"
#include "CameraSwapchain.hpp"
#include "engine/rendering/renderpass/RenderPass.hpp"
namespace fgl::engine
{
class CameraSwapchain;
vk::raii::RenderPass CameraRenderer::createRenderPass()
{
rendering::RenderPassBuilder builder {};
builder.setAttachmentCount( 7 );
// Set formats for each item in the swapchain
//XYZ in world space
auto position { builder.attachment( POSITION_INDEX ) };
position.setFormat( pickPositionFormat() ); // position
position.setLayouts( vk::ImageLayout::eUndefined, vk::ImageLayout::eShaderReadOnlyOptimal );
position.setOps( vk::AttachmentLoadOp::eClear, vk::AttachmentStoreOp::eStore );
//RGBA
auto normal { builder.attachment( NORMAL_INDEX ) };
normal.setFormat( pickNormalFormat() ); // normal
normal.setLayouts( vk::ImageLayout::eUndefined, vk::ImageLayout::eShaderReadOnlyOptimal );
normal.setOps( vk::AttachmentLoadOp::eClear, vk::AttachmentStoreOp::eStore );
// RGBA
auto color { builder.attachment( COLOR_INDEX ) };
color.setFormat( pickColorFormat() ); // color
color.setLayouts( vk::ImageLayout::eUndefined, vk::ImageLayout::eShaderReadOnlyOptimal );
color.setOps( vk::AttachmentLoadOp::eClear, vk::AttachmentStoreOp::eStore );
// Metallic, Roughness, Occlusion
auto metallic_roughness { builder.attachment( METALLIC_INDEX ) };
metallic_roughness.setFormat( pickMetallicFormat() );
metallic_roughness.setLayouts( vk::ImageLayout::eUndefined, vk::ImageLayout::eShaderReadOnlyOptimal );
metallic_roughness.setOps( vk::AttachmentLoadOp::eClear, vk::AttachmentStoreOp::eStore );
// RGB
auto emissive { builder.attachment( EMISSIVE_INDEX ) };
emissive.setFormat( pickEmissiveFormat() );
emissive.setLayouts( vk::ImageLayout::eUndefined, vk::ImageLayout::eShaderReadOnlyOptimal );
emissive.setOps( vk::AttachmentLoadOp::eClear, vk::AttachmentStoreOp::eStore );
auto composite { builder.attachment( COMPOSITE_INDEX ) };
//TODO: For HDR I think this needs to be a bigger range then 8bits per channel.
composite.setFormat( pickCompositeFormat() ); // composite
composite.setLayouts( vk::ImageLayout::eUndefined, vk::ImageLayout::eShaderReadOnlyOptimal );
composite.setOps( vk::AttachmentLoadOp::eClear, vk::AttachmentStoreOp::eStore );
auto depth { builder.attachment( DEPTH_INDEX ) };
depth.setLayouts( vk::ImageLayout::eUndefined, vk::ImageLayout::eDepthStencilReadOnlyOptimal );
depth.setFormat( pickDepthFormat() ); // depth
depth.setOps( vk::AttachmentLoadOp::eClear, vk::AttachmentStoreOp::eStore );
auto& g_buffer_subpass { builder.createSubpass( 0 ) };
g_buffer_subpass.setDepthLayout( DEPTH_INDEX, vk::ImageLayout::eDepthStencilAttachmentOptimal );
g_buffer_subpass.addRenderLayout( COLOR_INDEX, vk::ImageLayout::eColorAttachmentOptimal );
g_buffer_subpass.addRenderLayout( POSITION_INDEX, vk::ImageLayout::eColorAttachmentOptimal );
g_buffer_subpass.addRenderLayout( NORMAL_INDEX, vk::ImageLayout::eColorAttachmentOptimal );
g_buffer_subpass.addRenderLayout( METALLIC_INDEX, vk::ImageLayout::eColorAttachmentOptimal );
g_buffer_subpass.addRenderLayout( EMISSIVE_INDEX, vk::ImageLayout::eColorAttachmentOptimal );
g_buffer_subpass.addDependencyFromExternal(
vk::AccessFlagBits::eDepthStencilAttachmentWrite,
vk::PipelineStageFlagBits::eEarlyFragmentTests | vk::PipelineStageFlagBits::eLateFragmentTests );
g_buffer_subpass.addDependencyFromExternal(
vk::AccessFlagBits::eColorAttachmentWrite, vk::PipelineStageFlagBits::eColorAttachmentOutput );
auto& composite_subpass { builder.createSubpass( 1 ) };
composite_subpass.addRenderLayout( COMPOSITE_INDEX, vk::ImageLayout::eColorAttachmentOptimal );
composite_subpass.addInputLayout( COLOR_INDEX, vk::ImageLayout::eShaderReadOnlyOptimal );
composite_subpass.addInputLayout( POSITION_INDEX, vk::ImageLayout::eShaderReadOnlyOptimal );
composite_subpass.addInputLayout( NORMAL_INDEX, vk::ImageLayout::eShaderReadOnlyOptimal );
composite_subpass.addInputLayout( METALLIC_INDEX, vk::ImageLayout::eShaderReadOnlyOptimal );
composite_subpass.addInputLayout( EMISSIVE_INDEX, vk::ImageLayout::eShaderReadOnlyOptimal );
composite_subpass.addDependency(
g_buffer_subpass,
vk::AccessFlagBits::eColorAttachmentWrite,
vk::PipelineStageFlagBits::eColorAttachmentOutput,
vk::AccessFlagBits::eInputAttachmentRead,
vk::PipelineStageFlagBits::eFragmentShader );
composite_subpass.addDependencyFromExternal(
vk::AccessFlagBits::eColorAttachmentWrite, vk::PipelineStageFlagBits::eColorAttachmentOutput );
return builder.create();
}
void CameraRenderer::setViewport( const vk::raii::CommandBuffer& command_buffer, const vk::Extent2D extent )
{
vk::Viewport viewport {};
viewport.x = 0.0f;
viewport.y = 0.0f;
viewport.width = static_cast< float >( extent.width );
viewport.height = static_cast< float >( extent.height );
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
const std::vector< vk::Viewport > viewports { viewport };
command_buffer.setViewport( 0, viewports );
}
void CameraRenderer::setScissor( const vk::raii::CommandBuffer& command_buffer, const vk::Extent2D extent )
{
const vk::Rect2D scissor { { 0, 0 }, extent };
const std::vector< vk::Rect2D > scissors { scissor };
command_buffer.setScissor( 0, scissors );
}
void CameraRenderer::beginRenderPass(
const vk::raii::CommandBuffer& command_buffer, CameraSwapchain& swapchain, const FrameIndex index )
{
const vk::RenderingInfo info { swapchain.getRenderingInfo( index ) };
command_buffer.beginRendering( info );
/*
vk::RenderPassBeginInfo info {};
info.renderPass = m_renderpass;
info.framebuffer = swapchain.getFramebuffer( index );
info.renderArea = { .offset = { 0, 0 }, .extent = swapchain.getExtent() };
info.setClearValues( swapchain.getClearValues() );
*/
// command_buffer.beginRenderPass( info, vk::SubpassContents::eInline );
setViewport( command_buffer, swapchain.getExtent() );
setScissor( command_buffer, swapchain.getExtent() );
}
void CameraRenderer::endRenderPass( const vk::raii::CommandBuffer& command_buffer )
{
command_buffer.endRendering();
// command_buffer.endRenderPass();
}
void CameraRenderer::pass( FrameInfo& frame_info, CameraSwapchain& camera_swapchain )
{
ZoneScopedN( "CameraRenderer::pass" );
m_culling_system.startPass( frame_info );
auto& command_buffer { frame_info.command_buffer };
camera_swapchain.transitionImages( command_buffer, CameraSwapchain::INITAL, frame_info.frame_idx );
beginRenderPass( command_buffer, camera_swapchain, frame_info.frame_idx );
// Transition the gbuffer to it's inital state
m_culling_system.wait();
//m_terrain_system.pass( frame_info );
m_entity_renderer.pass( frame_info );
m_line_drawer.pass( frame_info );
endRenderPass( command_buffer );
m_composition_system.pass( frame_info );
}
vk::raii::RenderPass& CameraRenderer::getRenderpass()
{
return m_renderpass;
}
} // namespace fgl::engine

View File

@@ -1,284 +0,0 @@
//
// Created by kj16609 on 7/11/24.
//
#include "CameraSwapchain.hpp"
#include "engine/descriptors/DescriptorSet.hpp"
namespace fgl::engine
{
std::vector< std::unique_ptr< descriptors::DescriptorSet > > CameraSwapchain::createGBufferDescriptors()
{
std::vector< std::unique_ptr< descriptors::DescriptorSet > > data {};
data.resize( SwapChain::MAX_FRAMES_IN_FLIGHT );
for ( PresentIndex i = 0; i < SwapChain::MAX_FRAMES_IN_FLIGHT; ++i )
{
//auto set { std::make_unique< descriptors::DescriptorSet >( GBufferDescriptorSet::createLayout() ) };
auto set { gbuffer_set.create() };
set->bindAttachment( 0, m_gbuffer.m_color.getView( i ), vk::ImageLayout::eShaderReadOnlyOptimal );
set->bindAttachment( 1, m_gbuffer.m_position.getView( i ), vk::ImageLayout::eShaderReadOnlyOptimal );
set->bindAttachment( 2, m_gbuffer.m_normal.getView( i ), vk::ImageLayout::eShaderReadOnlyOptimal );
set->bindAttachment( 3, m_gbuffer.m_metallic.getView( i ), vk::ImageLayout::eShaderReadOnlyOptimal );
set->bindAttachment( 4, m_gbuffer.m_emissive.getView( i ), vk::ImageLayout::eShaderReadOnlyOptimal );
set->update();
data[ i ] = std::move( set );
}
return data;
}
vk::ImageMemoryBarrier createColorImageBarrier(
const Image& image,
const vk::ImageLayout old_layout,
const vk::ImageLayout new_layout,
const vk::AccessFlags flags )
{
vk::ImageMemoryBarrier barrier {};
barrier.setImage( image.getVkImage() );
barrier.setOldLayout( old_layout );
barrier.setNewLayout( new_layout );
barrier.setSrcAccessMask( flags );
constexpr vk::ImageSubresourceRange subresource { vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1 };
barrier.setSubresourceRange( subresource );
return barrier;
}
vk::ImageMemoryBarrier createDepthImageBarrier(
const Image& image, const vk::ImageLayout old_layout, const vk::ImageLayout new_layout )
{
vk::ImageMemoryBarrier barrier {};
barrier.setImage( image.getVkImage() );
barrier.setOldLayout( old_layout );
barrier.setNewLayout( new_layout );
constexpr vk::ImageSubresourceRange subresource {
vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1,
};
barrier.setSubresourceRange( subresource );
return barrier;
}
void CameraSwapchain::transitionImages(
vk::raii::CommandBuffer& command_buffer, const std::uint16_t stage_id, const FrameIndex index )
{
switch ( stage_id )
{
default:
throw std::invalid_argument( "Invalid Stage ID" );
case INITAL:
{
const std::vector< vk::ImageMemoryBarrier > barriers {
createColorImageBarrier(
m_gbuffer.m_color.getImage( index ),
vk::ImageLayout::eUndefined,
vk::ImageLayout::eColorAttachmentOptimal,
vk::AccessFlagBits::eColorAttachmentWrite | vk::AccessFlagBits::eColorAttachmentRead ),
createColorImageBarrier(
m_gbuffer.m_emissive.getImage( index ),
vk::ImageLayout::eUndefined,
vk::ImageLayout::eColorAttachmentOptimal,
vk::AccessFlagBits::eColorAttachmentWrite | vk::AccessFlagBits::eColorAttachmentRead ),
createColorImageBarrier(
m_gbuffer.m_metallic.getImage( index ),
vk::ImageLayout::eUndefined,
vk::ImageLayout::eColorAttachmentOptimal,
vk::AccessFlagBits::eColorAttachmentWrite | vk::AccessFlagBits::eColorAttachmentRead ),
createColorImageBarrier(
m_gbuffer.m_position.getImage( index ),
vk::ImageLayout::eUndefined,
vk::ImageLayout::eColorAttachmentOptimal,
vk::AccessFlagBits::eColorAttachmentWrite | vk::AccessFlagBits::eColorAttachmentRead ),
createDepthImageBarrier(
m_gbuffer.m_depth.getImage( index ),
vk::ImageLayout::eUndefined,
vk::ImageLayout::eDepthStencilAttachmentOptimal )
};
command_buffer.pipelineBarrier(
vk::PipelineStageFlagBits::eColorAttachmentOutput,
vk::PipelineStageFlagBits::eBottomOfPipe,
vk::DependencyFlags( 0 ),
{},
{},
barriers );
return;
}
case FINAL:
{
return;
}
}
}
vk::RenderingInfo CameraSwapchain::getRenderingInfo( const FrameIndex frame_index )
{
// This should be safe to have as static as the information used here will only capable of being used in a single frame.
static thread_local std::vector< vk::RenderingAttachmentInfo > color_attachment_infos {};
static thread_local vk::RenderingAttachmentInfo depth_attachment_infos {};
depth_attachment_infos = m_gbuffer.m_depth.renderInfo( frame_index, vk::ImageLayout::eDepthAttachmentOptimal );
color_attachment_infos.clear();
color_attachment_infos = {
m_gbuffer.m_color.renderInfo( frame_index, vk::ImageLayout::eColorAttachmentOptimal ),
m_gbuffer.m_position.renderInfo( frame_index, vk::ImageLayout::eColorAttachmentOptimal ),
m_gbuffer.m_normal.renderInfo( frame_index, vk::ImageLayout::eColorAttachmentOptimal ),
m_gbuffer.m_metallic.renderInfo( frame_index, vk::ImageLayout::eColorAttachmentOptimal ),
m_gbuffer.m_emissive.renderInfo( frame_index, vk::ImageLayout::eColorAttachmentOptimal )
};
vk::RenderingInfo rendering_info {};
rendering_info.setRenderArea( { { 0, 0 }, m_extent } );
rendering_info.setLayerCount( 1 );
rendering_info.setColorAttachments( color_attachment_infos );
rendering_info.setPDepthAttachment( &depth_attachment_infos );
// rendering_info.setPStencilAttachment( &depth_attachment_infos );
return rendering_info;
}
const std::vector< vk::ClearValue >& CameraSwapchain::getClearValues()
{
assert( !m_clear_values.empty() );
return m_clear_values;
}
std::vector< vk::raii::Framebuffer > CameraSwapchain::createFrambuffers()
{
constexpr auto image_count { SwapChain::MAX_FRAMES_IN_FLIGHT };
m_gbuffer.m_color.createResources( image_count, m_extent );
m_gbuffer.m_position.createResources( image_count, m_extent );
m_gbuffer.m_normal.createResources( image_count, m_extent );
m_gbuffer.m_metallic.createResources( image_count, m_extent );
m_gbuffer.m_emissive.createResources( image_count, m_extent );
m_gbuffer.m_composite.createResources( image_count, m_extent, vk::ImageUsageFlagBits::eTransferSrc );
m_gbuffer.m_depth.createResources( image_count, m_extent );
m_gbuffer.m_depth.setClear( vk::ClearDepthStencilValue( 1.0f, 0 ) );
std::vector< vk::raii::Framebuffer > buffers {};
buffers.reserve( image_count );
for ( FrameIndex i = 0; i < image_count; ++i )
{
std::vector< vk::ImageView > attachments { getViewsForFrame(
i,
m_gbuffer.m_color,
m_gbuffer.m_position,
m_gbuffer.m_normal,
m_gbuffer.m_metallic,
m_gbuffer.m_emissive,
m_gbuffer.m_composite,
m_gbuffer.m_depth ) };
vk::FramebufferCreateInfo info {};
info.renderPass = m_renderpass;
info.setAttachments( attachments );
info.width = m_extent.width;
info.height = m_extent.height;
info.layers = 1;
buffers.emplace_back( Device::getInstance()->createFramebuffer( info ) );
m_g_buffer_color_img.emplace_back(
std::make_unique< Texture >( m_gbuffer.m_color.m_attachment_resources.m_images[ i ]
->setName( "GBufferColor" ) ) );
auto& position_resources { m_gbuffer.m_position.m_attachment_resources };
assert( position_resources.m_images[ i ] );
assert( position_resources.m_image_views[ i ] );
auto& position_image { *position_resources.m_images[ i ] };
position_image.setName( format_ns::format( "GBufferPosition: {}", i ) );
m_g_buffer_position_img.emplace_back( std::make_unique< Texture >( position_image ) );
m_g_buffer_normal_img.emplace_back(
std::make_unique< Texture >( m_gbuffer.m_normal.m_attachment_resources.m_images[ i ]
->setName( "GBufferNormal" ) ) );
m_g_buffer_metallic_img.emplace_back(
std::make_unique< Texture >( m_gbuffer.m_metallic.m_attachment_resources.m_images[ i ]
->setName( "GBufferMetallic" ) ) );
m_g_buffer_emissive_img.emplace_back(
std::make_unique< Texture >( m_gbuffer.m_emissive.m_attachment_resources.m_images[ i ]
->setName( "GBufferEmissive" ) ) );
m_g_buffer_composite_img.emplace_back(
std::make_unique< Texture >( m_gbuffer.m_composite.m_attachment_resources.m_images[ i ]
->setName( "GBufferComposite" ) ) );
}
return buffers;
}
descriptors::DescriptorSet& CameraSwapchain::getGBufferDescriptor( const FrameIndex frame_index )
{
return *m_gbuffer_descriptor_set[ frame_index ];
}
vk::raii::Framebuffer& CameraSwapchain::getFramebuffer( const FrameIndex frame_index )
{
return m_framebuffers[ frame_index ];
}
vk::Extent2D CameraSwapchain::getExtent() const
{
return m_extent;
}
Image& CameraSwapchain::getOutput( const FrameIndex index )
{
assert( index <= this->m_gbuffer.m_composite.m_attachment_resources.m_images.size() );
return *m_gbuffer.m_composite.m_attachment_resources.m_images[ index ];
}
float CameraSwapchain::getAspectRatio()
{
return static_cast< float >( m_extent.width ) / static_cast< float >( m_extent.height );
}
CameraSwapchain::CameraSwapchain( vk::raii::RenderPass& renderpass, const vk::Extent2D extent ) :
m_extent( extent ),
m_renderpass( renderpass ),
m_framebuffers( createFrambuffers() ),
m_clear_values( gatherClearValues(
m_gbuffer.m_color,
m_gbuffer.m_position,
m_gbuffer.m_normal,
m_gbuffer.m_metallic,
m_gbuffer.m_emissive,
m_gbuffer.m_composite,
m_gbuffer.m_depth ) ),
m_gbuffer_descriptor_set( createGBufferDescriptors() )
{
m_gbuffer.m_depth.setName( "Depth" );
}
CameraSwapchain::~CameraSwapchain()
{
for ( auto& descriptor : m_gbuffer_descriptor_set )
{
descriptors::queueDescriptorDeletion( std::move( descriptor ) );
}
}
} // namespace fgl::engine

View File

@@ -0,0 +1,91 @@
//
// Created by kj16609 on 1/13/25.
//
#include "CompositeSwapchain.hpp"
#include "engine/rendering/SwapChain.hpp"
#include "engine/rendering/pipelines/Attachment.hpp"
namespace fgl::engine
{
class Texture;
void CompositeSwapchain::
transitionImages( vk::raii::CommandBuffer& command_buffer, StageID stage_id, FrameIndex index )
{
switch ( stage_id )
{
default:
throw std::runtime_error( "Invalid StageID" );
case INITAL:
{
const std::vector< vk::ImageMemoryBarrier > barriers {
m_buffer.m_target.getImage( index )
.transitionColorTo( vk::ImageLayout::eUndefined, vk::ImageLayout::eColorAttachmentOptimal ),
};
command_buffer.pipelineBarrier(
vk::PipelineStageFlagBits::eTopOfPipe,
vk::PipelineStageFlagBits::eColorAttachmentOutput,
vk::DependencyFlags( 0 ),
{},
{},
barriers );
return;
}
case FINAL:
{
const std::vector< vk::ImageMemoryBarrier > barriers {
m_buffer.m_target.getImage( index ).transitionColorTo(
vk::ImageLayout::eColorAttachmentOptimal, vk::ImageLayout::ePresentSrcKHR ),
};
command_buffer.pipelineBarrier(
vk::PipelineStageFlagBits::eColorAttachmentOutput,
vk::PipelineStageFlagBits::eBottomOfPipe,
vk::DependencyFlags( 0 ),
{},
{},
barriers );
return;
}
}
}
vk::RenderingInfo CompositeSwapchain::getRenderingInfo( const FrameIndex index )
{
static thread_local std::vector< vk::RenderingAttachmentInfo > infos {};
infos.clear();
infos = { m_buffer.m_target.renderInfo( index, vk::ImageLayout::eColorAttachmentOptimal ) };
vk::RenderingInfo rendering_info {};
rendering_info.setRenderArea( { { 0, 0 }, m_extent } );
rendering_info.setLayerCount( 1 );
rendering_info.setColorAttachments( infos );
return rendering_info;
}
CompositeSwapchain::CompositeSwapchain( vk::Extent2D extent ) : m_extent( extent )
{
constexpr auto image_count { SwapChain::MAX_FRAMES_IN_FLIGHT };
m_buffer.m_target.createResources( image_count, m_extent, vk::ImageUsageFlagBits::eTransferSrc );
for ( const auto& image : m_buffer.m_target.m_attachment_resources.m_images )
{
m_gbuffer_target.emplace_back( std::make_unique< Texture >( *image ) );
}
}
CompositeSwapchain::~CompositeSwapchain()
{}
} // namespace fgl::engine

View File

@@ -0,0 +1,44 @@
//
// Created by kj16609 on 1/13/25.
//
#pragma once
#include "engine/rendering/RenderingFormats.hpp"
#include "engine/rendering/pipelines/Attachment.hpp"
namespace fgl::engine
{
class Texture;
class CompositeSwapchain
{
vk::Extent2D m_extent;
struct
{
ColorAttachment< 0 > m_target { pickCompositeFormat() };
} m_buffer {};
public:
FGL_DELETE_COPY( CompositeSwapchain );
FGL_DELETE_MOVE( CompositeSwapchain );
std::vector< std::unique_ptr< Texture > > m_gbuffer_target {};
enum StageID : std::uint16_t
{
INITAL,
FINAL,
};
void transitionImages( vk::raii::CommandBuffer& command_buffer, StageID stage_id, FrameIndex index );
vk::RenderingInfo getRenderingInfo( FrameIndex index );
vk::Extent2D getExtent() const { return m_extent; }
CompositeSwapchain( vk::Extent2D extent );
~CompositeSwapchain();
};
} // namespace fgl::engine

View File

@@ -0,0 +1,99 @@
//
// Created by kj16609 on 1/13/25.
//
#include "GBufferCompositor.hpp"
#include "Camera.hpp"
#include "CompositeSwapchain.hpp"
#include "GBufferSwapchain.hpp"
#include "engine/rendering/pipelines/v2/AttachmentBuilder.hpp"
namespace fgl::engine
{
void GBufferCompositor::setViewport( const vk::raii::CommandBuffer& command_buffer, const vk::Extent2D extent )
{
vk::Viewport viewport {};
viewport.x = 0.0f;
viewport.y = 0.0f;
viewport.width = static_cast< float >( extent.width );
viewport.height = static_cast< float >( extent.height );
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
const std::vector< vk::Viewport > viewports { viewport };
command_buffer.setViewport( 0, viewports );
}
void GBufferCompositor::setScissor( const vk::raii::CommandBuffer& command_buffer, const vk::Extent2D extent )
{
const vk::Rect2D scissor { { 0, 0 }, extent };
const std::vector< vk::Rect2D > scissors { scissor };
command_buffer.setScissor( 0, scissors );
}
void GBufferCompositor::
beginPass( vk::raii::CommandBuffer& cmd, CompositeSwapchain& swapchain, const FrameIndex& index )
{
const vk::RenderingInfo info { swapchain.getRenderingInfo( index ) };
cmd.beginRendering( info );
setViewport( cmd, swapchain.getExtent() );
setScissor( cmd, swapchain.getExtent() );
}
void GBufferCompositor::endPass( vk::raii::CommandBuffer& cmd )
{
cmd.endRendering();
}
GBufferCompositor::GBufferCompositor( const CompositeFlags flags ) : m_flags( flags )
{
PipelineBuilder builder { 0 };
builder.addDescriptorSet( gbuffer_set );
builder.addDescriptorSet( Camera::getDescriptorLayout() );
builder.addColorAttachment().setFormat( pickColorFormat() ).finish();
builder.setPushConstant( vk::ShaderStageFlagBits::eFragment, sizeof( CompositionControl ) );
builder.setVertexShader( Shader::loadVertex( "shaders/fullscreen.vert" ) );
builder.setFragmentShader( Shader::loadFragment( "shaders/composition.frag" ) );
builder.disableCulling();
builder.disableVertexInput();
m_pipeline = builder.create();
m_pipeline->setDebugName( "Composition pipeline" );
}
void GBufferCompositor::
composite( vk::raii::CommandBuffer& command_buffer, Camera& camera, const FrameIndex frame_index )
{
auto& gbuffer_swapchain { camera.getSwapchain() };
auto& composite_swapchain { camera.getCompositeSwapchain() };
composite_swapchain.transitionImages( command_buffer, CompositeSwapchain::INITAL, frame_index );
beginPass( command_buffer, composite_swapchain, frame_index );
m_pipeline->bind( command_buffer );
m_pipeline->bindDescriptor( command_buffer, gbuffer_swapchain.getGBufferDescriptor( frame_index ) );
m_pipeline->bindDescriptor( command_buffer, camera.getDescriptor( frame_index ) );
m_pipeline->pushConstant( command_buffer, vk::ShaderStageFlagBits::eFragment, m_control );
command_buffer.draw( 3, 1, 0, 0 );
endPass( command_buffer );
}
} // namespace fgl::engine

View File

@@ -0,0 +1,56 @@
//
// Created by kj16609 on 1/13/25.
//
#pragma once
#include <vulkan/vulkan_raii.hpp>
#include "Camera.hpp"
#include "engine/rendering/pipelines/v2/Pipeline.hpp"
#include "engine/rendering/types.hpp"
#include "engine/systems/composition/Control.hpp"
namespace fgl::engine
{
class CompositeSwapchain;
class Image;
class GBufferSwapchain;
using CompositeFlags = std::uint16_t;
enum CompositeFlagBits : CompositeFlags
{
CompositeFlagBits_None = 0,
CompositeFlagBits_NormalOnly = 1 << 0,
//! The final output should be transformed into a presenting valid format.
CompositeFlagBits_PresentTarget = 1 << 1,
CompositeFlagBits_Standard = CompositeFlagBits_None,
};
/**
* @brief Composites a GBuffer input
*/
class GBufferCompositor
{
CompositeFlags m_flags;
std::unique_ptr< Pipeline > m_pipeline { nullptr };
void setViewport( const vk::raii::CommandBuffer& cmd, vk::Extent2D extent_2d );
void setScissor( const vk::raii::CommandBuffer& cmd, vk::Extent2D extent_2d );
void beginPass( vk::raii::CommandBuffer& cmd, CompositeSwapchain& swapchain, const FrameIndex& index );
void endPass( vk::raii::CommandBuffer& cmd );
CompositionControl m_control {};
public:
GBufferCompositor( CompositeFlags flags = CompositeFlagBits_Standard );
void composite( vk::raii::CommandBuffer& command_buffer, Camera& camera, FrameIndex frame_index );
inline void switchMode( const CompositeFlags flags ) { m_flags = flags; }
};
} // namespace fgl::engine

View File

@@ -0,0 +1,82 @@
//
// Created by kj16609 on 7/21/24.
//
#include "GBufferRenderer.hpp"
#include "Camera.hpp"
#include "engine/rendering/renderpass/RenderPass.hpp"
namespace fgl::engine
{
class GBufferSwapchain;
void GBufferRenderer::setViewport( const vk::raii::CommandBuffer& command_buffer, const vk::Extent2D extent )
{
vk::Viewport viewport {};
viewport.x = 0.0f;
viewport.y = 0.0f;
viewport.width = static_cast< float >( extent.width );
viewport.height = static_cast< float >( extent.height );
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
const std::vector< vk::Viewport > viewports { viewport };
command_buffer.setViewport( 0, viewports );
}
void GBufferRenderer::setScissor( const vk::raii::CommandBuffer& command_buffer, const vk::Extent2D extent )
{
const vk::Rect2D scissor { { 0, 0 }, extent };
const std::vector< vk::Rect2D > scissors { scissor };
command_buffer.setScissor( 0, scissors );
}
void GBufferRenderer::beginRenderPass(
const vk::raii::CommandBuffer& command_buffer, GBufferSwapchain& swapchain, const FrameIndex index )
{
const vk::RenderingInfo info { swapchain.getRenderingInfo( index ) };
command_buffer.beginRendering( info );
setViewport( command_buffer, swapchain.getExtent() );
setScissor( command_buffer, swapchain.getExtent() );
}
void GBufferRenderer::endRenderPass( const vk::raii::CommandBuffer& command_buffer )
{
command_buffer.endRendering();
}
void GBufferRenderer::pass( FrameInfo& frame_info, GBufferSwapchain& camera_swapchain )
{
ZoneScopedN( "CameraRenderer::pass" );
m_culling_system.startPass( frame_info );
auto& command_buffer { frame_info.command_buffer };
camera_swapchain.transitionImages( command_buffer, GBufferSwapchain::INITAL, frame_info.frame_idx );
beginRenderPass( command_buffer, camera_swapchain, frame_info.frame_idx );
// Transition the gbuffer to it's inital state
m_culling_system.wait();
//m_terrain_system.pass( frame_info );
m_entity_renderer.pass( frame_info );
m_line_drawer.pass( frame_info );
endRenderPass( command_buffer );
camera_swapchain.transitionImages( command_buffer, GBufferSwapchain::FINAL, frame_info.frame_idx );
m_compositor.composite( command_buffer, *frame_info.camera, frame_info.frame_idx );
}
} // namespace fgl::engine

View File

@@ -4,8 +4,8 @@
#pragma once
#include "CameraSwapchain.hpp"
#include "engine/systems/composition/CompositionSystem.hpp"
#include "GBufferCompositor.hpp"
#include "GBufferSwapchain.hpp"
#include "engine/systems/prerender/CullingSystem.hpp"
#include "engine/systems/render/EntityRendererSystem.hpp"
#include "engine/systems/render/LineDrawer.hpp"
@@ -13,11 +13,10 @@
namespace fgl::engine
{
class CameraRenderer
class GBufferRenderer
{
vk::raii::RenderPass m_renderpass;
GBufferCompositor m_compositor;
static vk::raii::RenderPass createRenderPass();
void setViewport( const vk::raii::CommandBuffer& command_buffer, vk::Extent2D extent );
void setScissor( const vk::raii::CommandBuffer& command_buffer, vk::Extent2D extent );
@@ -25,24 +24,22 @@ namespace fgl::engine
// SubPass 0
//TerrainSystem m_terrain_system { Device::getInstance(), m_renderpass };
EntityRendererSystem m_entity_renderer { m_renderpass };
LineDrawer m_line_drawer { m_renderpass };
EntityRendererSystem m_entity_renderer {};
LineDrawer m_line_drawer {};
// SubPass 1
CompositionSystem m_composition_system { m_renderpass };
// CompositionSystem m_composition_system {};
void beginRenderPass(
const vk::raii::CommandBuffer& command_buffer, CameraSwapchain& swapchain, const FrameIndex index );
const vk::raii::CommandBuffer& command_buffer, GBufferSwapchain& swapchain, FrameIndex index );
void endRenderPass( const vk::raii::CommandBuffer& command_buffer );
public:
void pass( FrameInfo& frame_info, CameraSwapchain& camera_swapchain );
void pass( FrameInfo& frame_info, GBufferSwapchain& camera_swapchain );
vk::raii::RenderPass& getRenderpass();
CameraRenderer() : m_renderpass( createRenderPass() ) {}
GBufferRenderer() = default;
};
} // namespace fgl::engine

View File

@@ -0,0 +1,189 @@
//
// Created by kj16609 on 7/11/24.
//
#include "GBufferSwapchain.hpp"
#include "engine/descriptors/DescriptorSet.hpp"
namespace fgl::engine
{
std::vector< std::unique_ptr< descriptors::DescriptorSet > > GBufferSwapchain::createGBufferDescriptors()
{
std::vector< std::unique_ptr< descriptors::DescriptorSet > > data {};
data.resize( SwapChain::MAX_FRAMES_IN_FLIGHT );
for ( PresentIndex i = 0; i < SwapChain::MAX_FRAMES_IN_FLIGHT; ++i )
{
//auto set { std::make_unique< descriptors::DescriptorSet >( GBufferDescriptorSet::createLayout() ) };
auto set { gbuffer_set.create() };
set->bindAttachment( 0, m_gbuffer.m_color.getView( i ), vk::ImageLayout::eRenderingLocalReadKHR );
set->bindAttachment( 1, m_gbuffer.m_position.getView( i ), vk::ImageLayout::eRenderingLocalReadKHR );
set->bindAttachment( 2, m_gbuffer.m_normal.getView( i ), vk::ImageLayout::eRenderingLocalReadKHR );
set->bindAttachment( 3, m_gbuffer.m_metallic.getView( i ), vk::ImageLayout::eRenderingLocalReadKHR );
set->bindAttachment( 4, m_gbuffer.m_emissive.getView( i ), vk::ImageLayout::eRenderingLocalReadKHR );
set->update();
data[ i ] = std::move( set );
}
return data;
}
void GBufferSwapchain::transitionImages(
vk::raii::CommandBuffer& command_buffer, const std::uint16_t stage_id, const FrameIndex index )
{
switch ( stage_id )
{
default:
throw std::invalid_argument( "Invalid Stage ID" );
case INITAL:
{
const std::vector< vk::ImageMemoryBarrier > barriers {
m_gbuffer.m_color.getImage( index )
.transitionColorTo( vk::ImageLayout::eUndefined, vk::ImageLayout::eColorAttachmentOptimal ),
m_gbuffer.m_emissive.getImage( index )
.transitionColorTo( vk::ImageLayout::eUndefined, vk::ImageLayout::eColorAttachmentOptimal ),
m_gbuffer.m_metallic.getImage( index )
.transitionColorTo( vk::ImageLayout::eUndefined, vk::ImageLayout::eColorAttachmentOptimal ),
m_gbuffer.m_position.getImage( index )
.transitionColorTo( vk::ImageLayout::eUndefined, vk::ImageLayout::eColorAttachmentOptimal ),
m_gbuffer.m_normal.getImage( index )
.transitionColorTo( vk::ImageLayout::eUndefined, vk::ImageLayout::eColorAttachmentOptimal ),
m_gbuffer.m_depth.getImage( index ).transitionTo(
vk::ImageLayout::eUndefined,
vk::ImageLayout::eDepthAttachmentOptimal,
vk::ImageAspectFlagBits::eDepth ),
};
command_buffer.pipelineBarrier(
vk::PipelineStageFlagBits::eTopOfPipe,
vk::PipelineStageFlagBits::eColorAttachmentOutput
| vk::PipelineStageFlagBits::eEarlyFragmentTests
| vk::PipelineStageFlagBits::eLateFragmentTests,
vk::DependencyFlags( 0 ),
{},
{},
barriers );
return;
}
case FINAL:
{
// Final should turn all of these into readonly in order to be used for other render targets.
const std::vector< vk::ImageMemoryBarrier > barriers {
m_gbuffer.m_color.getImage( index ).transitionColorTo(
vk::ImageLayout::eColorAttachmentOptimal, vk::ImageLayout::eShaderReadOnlyOptimal ),
m_gbuffer.m_emissive.getImage( index ).transitionColorTo(
vk::ImageLayout::eColorAttachmentOptimal, vk::ImageLayout::eShaderReadOnlyOptimal ),
m_gbuffer.m_metallic.getImage( index ).transitionColorTo(
vk::ImageLayout::eColorAttachmentOptimal, vk::ImageLayout::eShaderReadOnlyOptimal ),
m_gbuffer.m_position.getImage( index ).transitionColorTo(
vk::ImageLayout::eColorAttachmentOptimal, vk::ImageLayout::eShaderReadOnlyOptimal ),
m_gbuffer.m_normal.getImage( index ).transitionColorTo(
vk::ImageLayout::eColorAttachmentOptimal, vk::ImageLayout::eShaderReadOnlyOptimal )
// It might be useful to properly transition this for other post processing effects later
// m_gbuffer.m_depth.getImage( index ).transitionTo(
// vk::ImageLayout::eDepthAttachmentOptimal,
// vk::ImageLayout::eDepthReadOnlyOptimal,
// vk::ImageAspectFlagBits::eDepth ),
};
command_buffer.pipelineBarrier(
vk::PipelineStageFlagBits::eColorAttachmentOutput,
vk::PipelineStageFlagBits::eFragmentShader,
vk::DependencyFlags( 0 ),
{},
{},
barriers );
return;
}
}
}
vk::RenderingInfo GBufferSwapchain::getRenderingInfo( const FrameIndex frame_index )
{
// This should be safe to have as static as the information used here will only capable of being used in a single frame.
static thread_local std::vector< vk::RenderingAttachmentInfo > color_attachment_infos {};
static thread_local vk::RenderingAttachmentInfo depth_attachment_infos {};
depth_attachment_infos = m_gbuffer.m_depth.renderInfo( frame_index, vk::ImageLayout::eDepthAttachmentOptimal );
color_attachment_infos.clear();
color_attachment_infos = {
m_gbuffer.m_color.renderInfo( frame_index, vk::ImageLayout::eColorAttachmentOptimal ),
m_gbuffer.m_position.renderInfo( frame_index, vk::ImageLayout::eColorAttachmentOptimal ),
m_gbuffer.m_normal.renderInfo( frame_index, vk::ImageLayout::eColorAttachmentOptimal ),
m_gbuffer.m_metallic.renderInfo( frame_index, vk::ImageLayout::eColorAttachmentOptimal ),
m_gbuffer.m_emissive.renderInfo( frame_index, vk::ImageLayout::eColorAttachmentOptimal )
};
vk::RenderingInfo rendering_info {};
rendering_info.setRenderArea( { { 0, 0 }, m_extent } );
rendering_info.setLayerCount( 1 );
rendering_info.setColorAttachments( color_attachment_infos );
rendering_info.setPDepthAttachment( &depth_attachment_infos );
// rendering_info.setPStencilAttachment( &depth_attachment_infos );
return rendering_info;
}
descriptors::DescriptorSet& GBufferSwapchain::getGBufferDescriptor( const FrameIndex frame_index )
{
return *m_gbuffer_descriptor_set[ frame_index ];
}
vk::Extent2D GBufferSwapchain::getExtent() const
{
return m_extent;
}
float GBufferSwapchain::getAspectRatio()
{
return static_cast< float >( m_extent.width ) / static_cast< float >( m_extent.height );
}
GBufferSwapchain::GBufferSwapchain( const vk::Extent2D extent ) : m_extent( extent )
// m_gbuffer_descriptor_set( createGBufferDescriptors() )
{
constexpr auto image_count { SwapChain::MAX_FRAMES_IN_FLIGHT };
m_gbuffer.m_color.createResources( image_count, m_extent );
m_gbuffer.m_position.createResources( image_count, m_extent );
m_gbuffer.m_normal.createResources( image_count, m_extent );
m_gbuffer.m_metallic.createResources( image_count, m_extent );
m_gbuffer.m_emissive.createResources( image_count, m_extent );
m_gbuffer.m_depth.createResources( image_count, m_extent );
m_gbuffer.m_depth.setClear( vk::ClearDepthStencilValue( 1.0f, 0 ) );
m_gbuffer.m_color.setName( "Color" );
m_gbuffer.m_position.setName( "Position" );
m_gbuffer.m_normal.setName( "Normal" );
m_gbuffer.m_metallic.setName( "Metallic" );
m_gbuffer.m_emissive.setName( "Emissive" );
m_gbuffer.m_depth.setName( "Depth" );
m_gbuffer_descriptor_set = createGBufferDescriptors();
}
GBufferSwapchain::~GBufferSwapchain()
{
for ( auto& descriptor : m_gbuffer_descriptor_set )
{
descriptors::queueDescriptorDeletion( std::move( descriptor ) );
}
}
} // namespace fgl::engine

View File

@@ -21,7 +21,7 @@ namespace fgl::engine
constexpr std::size_t COMPOSITE_INDEX { 5 };
constexpr std::size_t DEPTH_INDEX { 6 };
class CameraSwapchain
class GBufferSwapchain
{
struct
{
@@ -30,31 +30,16 @@ namespace fgl::engine
ColorAttachment< NORMAL_INDEX > m_normal { pickNormalFormat() };
ColorAttachment< METALLIC_INDEX > m_metallic { pickMetallicFormat() };
ColorAttachment< EMISSIVE_INDEX > m_emissive { pickEmissiveFormat() };
ColorAttachment< COMPOSITE_INDEX > m_composite { pickCompositeFormat() };
//TODO: Move depth into m_position A channel
DepthAttachment< DEPTH_INDEX > m_depth { pickDepthFormat() };
// ColorAttachment< COMPOSITE_INDEX > m_composite { pickCompositeFormat() };
} m_gbuffer {};
public:
std::vector< std::unique_ptr< Texture > > m_g_buffer_color_img {};
std::vector< std::unique_ptr< Texture > > m_g_buffer_position_img {};
std::vector< std::unique_ptr< Texture > > m_g_buffer_normal_img {};
std::vector< std::unique_ptr< Texture > > m_g_buffer_metallic_img {};
std::vector< std::unique_ptr< Texture > > m_g_buffer_emissive_img {};
std::vector< std::unique_ptr< Texture > > m_g_buffer_composite_img {};
private:
vk::Extent2D m_extent;
vk::raii::RenderPass& m_renderpass;
std::vector< vk::raii::Framebuffer > m_framebuffers;
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 > > createGBufferDescriptors();
@@ -63,28 +48,21 @@ namespace fgl::engine
enum StageID : std::uint16_t
{
INITAL = 0,
FINAL = std::numeric_limits< std::uint16_t >::max()
INITAL,
COMPOSITE,
FINAL
};
void transitionImages( vk::raii::CommandBuffer& command_buffer, std::uint16_t stage_id, FrameIndex index );
vk::RenderingInfo getRenderingInfo( const FrameIndex frame_index );
CameraSwapchain( vk::raii::RenderPass& renderpass, vk::Extent2D extent );
~CameraSwapchain();
const std::vector< vk::ClearValue >& getClearValues();
std::vector< vk::raii::Framebuffer > createFrambuffers();
GBufferSwapchain( vk::Extent2D extent );
~GBufferSwapchain();
descriptors::DescriptorSet& getGBufferDescriptor( FrameIndex frame_index );
vk::raii::Framebuffer& getFramebuffer( FrameIndex frame_index );
vk::Extent2D getExtent() const;
Image& getOutput( const FrameIndex index );
float getAspectRatio();
};

View File

@@ -99,7 +99,7 @@ namespace fgl::engine
info.pEngineName = "titor";
info.engineVersion = VK_MAKE_VERSION( 1, 0, 0 );
info.apiVersion = VK_API_VERSION_1_4;
info.apiVersion = VK_API_VERSION_1_3;
return info;
}

View File

@@ -0,0 +1,24 @@
@startuml
'https://plantuml.com/sequence-diagram
autonumber
box "GBuffer" #LightBlue
participant Depth
participant Albedo
participant Depth
end box
Alice -> Bob: Authentication Request
Bob --> Alice: Authentication Response
Alice -> Bob: Another authentication Request
Alice <-- Bob: another authentication Response
@enduml

View File

@@ -75,6 +75,8 @@ namespace fgl::engine
{
m_dynamic_rendering_features.setDynamicRendering( VK_TRUE );
m_dynamic_rendering_local_read_features.setDynamicRenderingLocalRead( VK_TRUE );
m_dynamic_rendering_unused_features.setDynamicRenderingUnusedAttachments( VK_TRUE );
m_info_chain.unlink< vk::PhysicalDeviceDynamicRenderingUnusedAttachmentsFeaturesEXT >();
}
std::vector< vk::DeviceQueueCreateInfo > Device::DeviceCreateInfo::

View File

@@ -51,7 +51,8 @@ namespace fgl::engine
using InfoChain = vk::StructureChain<
vk::DeviceCreateInfo,
vk::PhysicalDeviceDynamicRenderingFeatures,
vk::PhysicalDeviceDynamicRenderingLocalReadFeatures,
vk::PhysicalDeviceDynamicRenderingLocalReadFeaturesKHR,
vk::PhysicalDeviceDynamicRenderingUnusedAttachmentsFeaturesEXT,
vk::PhysicalDeviceDescriptorIndexingFeatures >;
InfoChain m_info_chain;
@@ -70,14 +71,18 @@ namespace fgl::engine
m_info_chain.get< vk::PhysicalDeviceDescriptorIndexingFeatures >()
};
vk::PhysicalDeviceDynamicRenderingLocalReadFeatures& m_dynamic_rendering_local_read_features {
m_info_chain.get< vk::PhysicalDeviceDynamicRenderingLocalReadFeatures >()
vk::PhysicalDeviceDynamicRenderingLocalReadFeaturesKHR& m_dynamic_rendering_local_read_features {
m_info_chain.get< vk::PhysicalDeviceDynamicRenderingLocalReadFeaturesKHR >()
};
vk::PhysicalDeviceDynamicRenderingFeatures& m_dynamic_rendering_features {
m_info_chain.get< vk::PhysicalDeviceDynamicRenderingFeatures >()
};
vk::PhysicalDeviceDynamicRenderingUnusedAttachmentsFeaturesEXT& m_dynamic_rendering_unused_features {
m_info_chain.get< vk::PhysicalDeviceDynamicRenderingUnusedAttachmentsFeaturesEXT >()
};
DeviceCreateInfo( PhysicalDevice& );
} device_creation_info;

View File

@@ -109,7 +109,7 @@ namespace fgl::engine
}
//! Creates a resource that is used across all frames
void createResourceSpread(
void createSharedResources(
const std::uint32_t count, vk::Extent2D extent, vk::ImageUsageFlags extra_flags = vk::ImageUsageFlags( 0 ) )
{
auto image { std::make_shared< Image >(

View File

@@ -1,71 +0,0 @@
//
// Created by kj16609 on 3/11/24.
//
#include "CompositionSystem.hpp"
#include "Control.hpp"
#include "editor/src/gui/safe_include.hpp"
#include "engine/camera/Camera.hpp"
#include "engine/rendering/RenderingFormats.hpp"
#include "engine/rendering/pipelines/v2/AttachmentBuilder.hpp"
#include "engine/rendering/pipelines/v2/Pipeline.hpp"
#include "engine/rendering/pipelines/v2/PipelineBuilder.hpp"
namespace fgl::engine
{
CompositionSystem::CompositionSystem( vk::raii::RenderPass& render_pass )
{
PipelineBuilder builder { 0 };
builder.addDescriptorSet( gbuffer_set );
builder.addDescriptorSet( Camera::getDescriptorLayout() );
builder.addColorAttachment().setFormat( pickColorFormat() ).finish();
builder.setPushConstant( vk::ShaderStageFlagBits::eFragment, sizeof( CompositionControl ) );
builder.setVertexShader( Shader::loadVertex( "shaders/fullscreen.vert" ) );
builder.setFragmentShader( Shader::loadFragment( "shaders/composition.frag" ) );
builder.disableCulling();
builder.disableVertexInput();
m_composite_pipeline = builder.create();
m_composite_pipeline->setDebugName( "Composition pipeline" );
}
CompositionSystem::~CompositionSystem()
{}
vk::raii::CommandBuffer& CompositionSystem::setupSystem( FrameInfo& info )
{
auto& command_buffer { info.command_buffer };
m_composite_pipeline->bind( command_buffer );
m_composite_pipeline->bindDescriptor( command_buffer, info.getGBufferDescriptor() );
m_composite_pipeline->bindDescriptor( command_buffer, info.getCameraDescriptor() );
ImGui::Begin( "Composition" );
ImGui::InputInt( "Selection", &m_control.m_flags );
ImGui::End();
m_composite_pipeline->pushConstant( command_buffer, vk::ShaderStageFlagBits::eFragment, m_control );
return info.command_buffer;
}
void CompositionSystem::pass( FrameInfo& info )
{
auto& command_buffer { setupSystem( info ) };
TracyVkZone( info.tracy_ctx, *command_buffer, "Composition Pass" );
command_buffer.draw( 3, 1, 0, 0 );
}
} // namespace fgl::engine

View File

@@ -1,33 +0,0 @@
//
// Created by kj16609 on 3/11/24.
//
#pragma once
#include "Control.hpp"
#include "engine/FrameInfo.hpp"
#include "engine/systems/concepts.hpp"
namespace fgl::engine
{
class Pipeline;
class CompositionSystem
{
std::unique_ptr< Pipeline > m_composite_pipeline { nullptr };
vk::raii::CommandBuffer& setupSystem( FrameInfo& info );
CompositionControl m_control {};
public:
CompositionSystem( vk::raii::RenderPass& render_pass );
~CompositionSystem();
void pass( FrameInfo& info );
};
static_assert( is_system< CompositionSystem > );
} // namespace fgl::engine

View File

@@ -18,7 +18,7 @@
namespace fgl::engine
{
EntityRendererSystem::EntityRendererSystem( vk::raii::RenderPass& render_pass )
EntityRendererSystem::EntityRendererSystem( )
{
ZoneScoped;

View File

@@ -50,7 +50,7 @@ namespace fgl::engine
void texturelessPass( const FrameInfo& info );
void texturedPass( const FrameInfo& info );
EntityRendererSystem( vk::raii::RenderPass& render_pass );
EntityRendererSystem();
~EntityRendererSystem();
EntityRendererSystem( EntityRendererSystem&& other ) = delete;
EntityRendererSystem( const EntityRendererSystem& other ) = delete;

View File

@@ -24,7 +24,7 @@ namespace fgl::engine
inline static std::vector< VertexLine > m_lines {};
LineDrawer::LineDrawer( vk::raii::RenderPass& render_pass )
LineDrawer::LineDrawer( )
{
PipelineBuilder builder { 0 };

View File

@@ -22,12 +22,13 @@ namespace fgl::engine
public:
FGL_DELETE_ALL_RO5( LineDrawer );
FGL_DELETE_COPY( LineDrawer );
FGL_DELETE_MOVE( LineDrawer );
vk::raii::CommandBuffer& setupSystem( FrameInfo& info );
void pass( FrameInfo& info );
LineDrawer( vk::raii::RenderPass& render_pass );
LineDrawer();
~LineDrawer();
};