Finally gets the camera renderpass working

This commit is contained in:
2024-07-23 00:39:07 -04:00
parent c7c3e965b6
commit e89dc1261c
63 changed files with 1365 additions and 558 deletions

View File

@@ -8,21 +8,25 @@ file(GLOB_RECURSE CPP_SOURCES
add_library(FGLEngine STATIC ${CPP_SOURCES} ${HPP_SOURCES})
set(CMAKE_CXX_STANDARD 23)
target_precompile_headers(FGLEngine PRIVATE
if (DEFINED FGL_ENABLE_PCH)
<vulkan/vulkan.h>
target_precompile_headers(FGLEngine PRIVATE
<tracy/Tracy.hpp>
<vulkan/vulkan.h>
<vma/vma_impl.hpp>
<tracy/Tracy.hpp>
<glm/glm.hpp>
<glm/gtc/matrix_transform.hpp>
<glm/gtc/constants.hpp>
<glm/vec3.hpp>
<glm/vec2.hpp>
<glm/mat4x4.hpp>
)
<vma/vma_impl.hpp>
<glm/glm.hpp>
<glm/gtc/matrix_transform.hpp>
<glm/gtc/constants.hpp>
<glm/vec3.hpp>
<glm/vec2.hpp>
<glm/mat4x4.hpp>
)
endif ()
target_compile_definitions(FGLEngine PUBLIC VULKAN_HPP_FLAGS_MASK_TYPE_AS_PUBLIC)

View File

@@ -54,6 +54,9 @@ namespace fgl::engine
vk::BufferUsageFlagBits::eUniformBuffer,
vk::MemoryPropertyFlagBits::eHostVisible }; // 512 KB
//Camera prep
Camera::initCameraRenderer();
PerFrameSuballocation< HostSingleT< CameraInfo > > camera_info { global_ubo_buffer,
SwapChain::MAX_FRAMES_IN_FLIGHT };
@@ -117,6 +120,9 @@ namespace fgl::engine
TracyCZoneEnd( TRACY_PrepareEngine );
//TODO: Make a camera management object
std::vector< Camera* > cameras { &camera };
while ( !m_window.shouldClose() )
{
memory::TransferManager::getInstance().submitNow();
@@ -169,8 +175,7 @@ namespace fgl::engine
draw_parameter_buffers[ frame_index ],
*this->m_vertex_buffer,
*this->m_index_buffer,
m_renderer.getGBufferDescriptor( present_idx ),
m_renderer.getGBufferCompositeDescriptor( present_idx ),
m_renderer.getSwapChain().getInputDescriptor( present_idx ),
view_frustum,
this->m_renderer.getSwapChain() };
@@ -184,21 +189,23 @@ namespace fgl::engine
camera_info[ frame_index ] = current_camera_info;
m_culling_system.startPass( frame_info );
TracyVkCollect( frame_info.tracy_ctx, *command_buffer );
//TODO: Setup semaphores to make this pass not always required.
memory::TransferManager::getInstance().recordOwnershipTransferDst( command_buffer );
m_culling_system.wait();
for ( auto* current_camera : cameras )
{
current_camera->pass( frame_info );
}
auto* primary_camera { cameras[ 0 ] };
primary_camera
->copyOutput( command_buffer, frame_index, m_renderer.getSwapChain().getInputImage( present_idx ) );
m_renderer.beginSwapchainRendererPass( command_buffer );
m_terrain_system.pass( frame_info );
m_entity_renderer.pass( frame_info );
m_composition_system.pass( frame_info );
m_gui_system.pass( frame_info );
m_renderer.endSwapchainRendererPass( command_buffer );

View File

@@ -7,10 +7,7 @@
#include "Window.hpp"
#include "engine/literals/size.hpp"
#include "engine/rendering/Renderer.hpp"
#include "engine/systems/CullingSystem.hpp"
#include "engine/systems/EntityRendererSystem.hpp"
#include "engine/tree/octtree/OctTreeNode.hpp"
#include "systems/CompositionSystem.hpp"
#include "systems/GuiSystem.hpp"
#include "systems/TerrainSystem.hpp"
@@ -49,14 +46,6 @@ namespace fgl::engine
vk::MemoryPropertyFlagBits::eDeviceLocal ) };
// SubPass 0
CullingSystem m_culling_system {};
TerrainSystem m_terrain_system { Device::getInstance(), m_renderer.getSwapChainRenderPass() };
EntityRendererSystem m_entity_renderer { Device::getInstance(), m_renderer.getSwapChainRenderPass() };
// SubPass 1
CompositionSystem m_composition_system { Device::getInstance(), m_renderer.getSwapChainRenderPass() };
// SubPass 2
GuiSystem m_gui_system { Device::getInstance(), m_renderer.getSwapChainRenderPass() };
void loadGameObjects();

View File

@@ -14,7 +14,6 @@
#define FGL_DELETE_ALL_Ro5( ClassName ) \
FGL_DELETE_DEFAULT_CTOR( ClassName ) FGL_DELETE_COPY( ClassName ) FGL_DELETE_MOVE( ClassName )
//#define FGL_FLATTEN __attribute__( ( flatten ) )
#define FGL_FLATTEN [[gnu::flatten]]
#define FGL_ARTIFICIAL [[gnu::artificial]]
#define FGL_HOT [[gnu::hot]]
@@ -33,4 +32,14 @@
#define FGL_NONSTRING_DATA [[gnu::nonstring]]
//! Warns if the structure field is not alligned with a set number of bytes
#define FGL_STRICT_ALIGNMENT( bytesize ) [[gnu::warn_if_not_aligned( bytesize )]]
#define FGL_STRICT_ALIGNMENT( bytesize ) [[gnu::warn_if_not_aligned( bytesize )]]
#define FGL_ASSERT( ... ) assert( __VA_ARGS__ );
#ifndef NDEBUG
#define FGL_UNREACHABLE() \
FGL_ASSERT( false ); \
std::unreachable()
#else
#define FGL_UNREACHABLE() std::unreachable()
#endif

18
src/engine/FrameInfo.cpp Normal file
View File

@@ -0,0 +1,18 @@
//
// Created by kj16609 on 7/20/24.
//
#include "FrameInfo.hpp"
#include "camera/Camera.hpp"
#include "camera/CameraSwapchain.hpp"
namespace fgl::engine
{
descriptors::DescriptorSet& FrameInfo::getGBufferDescriptor()
{
return camera_data.camera.getSwapchain().getGBufferDescriptor( frame_idx );
}
} // namespace fgl::engine

View File

@@ -74,9 +74,9 @@ namespace fgl::engine
using GBufferDescriptorSet =
descriptors::DescriptorSetLayout< 0, PositionDescriptor, NormalDescriptor, AlbedoDescriptor >;
using CompositeDescriptor = descriptors::AttachmentDescriptor< 0, vk::ShaderStageFlagBits::eFragment >;
using InputDescriptor = descriptors::AttachmentDescriptor< 0, vk::ShaderStageFlagBits::eFragment >;
using GBufferCompositeDescriptorSet = descriptors::DescriptorSetLayout< 0, CompositeDescriptor >;
using GuiInputDescriptorSet = descriptors::DescriptorSetLayout< 0, InputDescriptor >;
class OctTreeNode;
@@ -105,8 +105,9 @@ namespace fgl::engine
memory::Buffer& model_vertex_buffer;
memory::Buffer& model_index_buffer;
descriptors::DescriptorSet& gbuffer_descriptor_set;
descriptors::DescriptorSet& gbuffer_composite_set;
descriptors::DescriptorSet& gui_input_descriptor;
descriptors::DescriptorSet& getGBufferDescriptor();
const Frustum< CoordinateSpace::World >& camera_frustum;
SwapChain& swap_chain;

View File

@@ -4,8 +4,8 @@
#include "KeyboardMovementController.hpp"
#include <chrono>
#include <functional>
#include <bits/chrono.h>
#include <iostream>
#include "engine/primitives/vectors/Vector.hpp"

View File

@@ -5,10 +5,11 @@
#include "Window.hpp"
#include <vulkan/vulkan.hpp>
#include <vulkan/vulkan_raii.hpp>
#include <stdexcept>
#include "engine/rendering/Device.hpp"
#include "engine/rendering/Instance.hpp"
namespace fgl::engine
{

View File

@@ -6,6 +6,7 @@
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
#include <vulkan/vulkan_core.h>
#include <cstdint>
#include <string>

View File

@@ -163,7 +163,7 @@ namespace fgl::engine::memory
return false;
}
std::unreachable();
FGL_UNREACHABLE();
}
bool TransferData::stage(
@@ -188,7 +188,7 @@ namespace fgl::engine::memory
return performBufferStage( copy_regions );
}
std::unreachable();
FGL_UNREACHABLE();
}
void TransferData::markBad()

View File

@@ -13,6 +13,12 @@
namespace fgl::engine
{
Matrix< MatrixType::WorldToScreen > Camera::getProjectionViewMatrix() const
{
assert( projection_matrix != constants::MAT4_IDENTITY );
return projection_matrix * view_matrix;
}
void Camera::setOrthographicProjection( float left, float right, float top, float bottom, float near, float far )
{
projection_matrix =
@@ -28,7 +34,184 @@ namespace fgl::engine
base_frustum = createFrustum( aspect, fovy, near, far );
}
FGL_FLATTEN_HOT void Camera::setView( WorldCoordinate pos, const Rotation rotation, const ViewMode mode )
Coordinate< CoordinateSpace::World > Camera::getPosition() const
{
//Should maybe store the inverse view matrix
return WorldCoordinate( inverse_view_matrix[ 3 ] );
}
void Camera::pass( FrameInfo& frame_info ) const
{
m_renderer->pass( frame_info, *m_swapchain );
}
vk::raii::RenderPass& Camera::getRenderpass()
{
return m_renderer->getRenderpass();
}
CameraSwapchain& Camera::getSwapchain() const
{
return *m_swapchain;
}
void Camera::setViewport( const vk::raii::CommandBuffer& command_buffer )
{
vk::Viewport viewport {};
viewport.x = 0.0f;
viewport.y = 0.0f;
const auto [ width, height ] = m_extent;
viewport.width = static_cast< float >( width );
viewport.height = static_cast< float >( height );
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
const std::vector< vk::Viewport > viewports { viewport };
command_buffer.setViewport( 0, viewports );
}
void Camera::setScissor( const vk::raii::CommandBuffer& command_buffer )
{
const vk::Rect2D scissor { { 0, 0 }, m_extent };
const std::vector< vk::Rect2D > scissors { scissor };
command_buffer.setScissor( 0, scissors );
}
void Camera::beginRenderpass( const vk::raii::CommandBuffer& command_buffer, const FrameInfo& info )
{
vk::RenderPassBeginInfo begin_info {};
begin_info.renderPass = getRenderpass();
begin_info.framebuffer = this->getSwapchain().getFramebuffer( info.frame_idx );
begin_info.renderArea = { .offset = { 0, 0 }, .extent = m_extent };
begin_info.setClearValues( this->getSwapchain().getClearValues() );
command_buffer.beginRenderPass( begin_info, vk::SubpassContents::eInline );
setViewport( command_buffer );
setScissor( command_buffer );
}
void Camera::endRenderpass( const vk::raii::CommandBuffer& command_buffer )
{
command_buffer.endRenderPass();
}
void Camera::
copyOutput( const vk::raii::CommandBuffer& command_buffer, const FrameIndex frame_index, Image& target )
{
assert( m_extent == target.getExtent() );
Image& source { this->getSwapchain().getOutput( frame_index ) };
vk::ImageSubresourceRange range {};
range.aspectMask = vk::ImageAspectFlagBits::eColor;
range.baseMipLevel = 0;
range.levelCount = 1;
range.baseArrayLayer = 0;
range.layerCount = 1;
vk::ImageMemoryBarrier barrier_to_target {};
barrier_to_target.oldLayout = vk::ImageLayout::eUndefined;
barrier_to_target.newLayout = vk::ImageLayout::eTransferDstOptimal;
barrier_to_target.image = target.getVkImage();
barrier_to_target.subresourceRange = range;
barrier_to_target.srcAccessMask = vk::AccessFlagBits::eMemoryWrite;
barrier_to_target.dstAccessMask =
vk::AccessFlagBits::eTransferWrite | vk::AccessFlagBits::eColorAttachmentWrite;
barrier_to_target.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier_to_target.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
command_buffer.pipelineBarrier(
vk::PipelineStageFlagBits::eTransfer | vk::PipelineStageFlagBits::eColorAttachmentOutput,
vk::PipelineStageFlagBits::eTransfer | vk::PipelineStageFlagBits::eColorAttachmentOutput,
{},
{},
{},
{ barrier_to_target } );
vk::ImageMemoryBarrier barrier_from_source {};
barrier_from_source.oldLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
barrier_from_source.newLayout = vk::ImageLayout::eTransferSrcOptimal;
barrier_from_source.image = source.getVkImage();
barrier_from_source.subresourceRange = range;
barrier_from_source.srcAccessMask = vk::AccessFlagBits::eColorAttachmentWrite;
barrier_from_source.dstAccessMask = vk::AccessFlagBits::eTransferRead | vk::AccessFlagBits::eTransferWrite;
barrier_from_source.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier_from_source.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
command_buffer.pipelineBarrier(
vk::PipelineStageFlagBits::eColorAttachmentOutput,
vk::PipelineStageFlagBits::eTransfer,
{},
{},
{},
{ barrier_from_source } );
vk::ImageCopy region {};
region.extent = vk::Extent3D( m_extent, 1 );
region.srcSubresource.aspectMask = vk::ImageAspectFlagBits::eColor;
region.srcSubresource.layerCount = 1;
region.srcSubresource.mipLevel = 0;
region.srcSubresource.baseArrayLayer = 0;
region.srcOffset = vk::Offset3D( 0, 0, 0 );
region.dstOffset = region.srcOffset;
region.dstSubresource = region.srcSubresource;
command_buffer.copyImage(
source.getVkImage(),
vk::ImageLayout::eTransferSrcOptimal,
target.getVkImage(),
vk::ImageLayout::eTransferDstOptimal,
{ region } );
vk::ImageMemoryBarrier barrier_from_target {};
barrier_from_target.oldLayout = barrier_to_target.newLayout;
barrier_from_target.newLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
barrier_from_target.image = target.getVkImage();
barrier_from_target.subresourceRange = range;
barrier_from_target.srcAccessMask = vk::AccessFlagBits::eTransferWrite;
barrier_from_target.dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eInputAttachmentRead
| vk::AccessFlagBits::eColorAttachmentRead;
barrier_from_target.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier_from_target.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
command_buffer.pipelineBarrier(
vk::PipelineStageFlagBits::eTransfer,
vk::PipelineStageFlagBits::eFragmentShader | vk::PipelineStageFlagBits::eColorAttachmentOutput,
{},
{},
{},
{ barrier_from_target } );
vk::ImageMemoryBarrier barrier_to_source {};
barrier_to_source.oldLayout = barrier_from_source.newLayout;
barrier_to_source.newLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
barrier_to_source.image = source.getVkImage();
barrier_to_source.subresourceRange = range;
barrier_to_source.srcAccessMask = vk::AccessFlagBits::eTransferWrite;
barrier_to_source.dstAccessMask = vk::AccessFlagBits::eShaderRead;
barrier_to_source.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier_to_source.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
command_buffer.pipelineBarrier(
vk::PipelineStageFlagBits::eTransfer,
vk::PipelineStageFlagBits::eFragmentShader,
{},
{},
{},
{ barrier_to_source } );
}
FGL_FLATTEN_HOT void Camera::setView( WorldCoordinate pos, const Rotation& rotation, const ViewMode mode )
{
switch ( mode )
{
@@ -73,9 +256,15 @@ namespace fgl::engine
frustum = translation_matrix * base_frustum;
}
void Camera::initCameraRenderer()
{
assert( !m_renderer );
m_renderer = std::make_unique< CameraRenderer >();
}
Camera::Camera( const vk::Extent2D extent ) :
m_extent( extent ),
m_swapchain( std::make_shared< CameraSwapchain >( m_extent ) )
m_swapchain( std::make_shared< CameraSwapchain >( m_renderer->getRenderpass(), m_extent ) )
{
this->setPerspectiveProjection( 90.0f, 16.0f / 9.0f, constants::NEAR_PLANE, constants::FAR_PLANE );
this->setView( WorldCoordinate( constants::CENTER ), Rotation( 0.0f, 0.0f, 0.0f ) );
@@ -84,7 +273,7 @@ namespace fgl::engine
void Camera::setExtent( const vk::Extent2D extent )
{
m_extent = extent;
m_swapchain = std::make_shared< CameraSwapchain >( m_extent );
m_swapchain = std::make_shared< CameraSwapchain >( m_renderer->getRenderpass(), m_extent );
}
Frustum< CoordinateSpace::Model >

View File

@@ -12,6 +12,7 @@
#include <glm/gtx/string_cast.hpp>
#pragma GCC diagnostic pop
#include "CameraRenderer.hpp"
#include "engine/constants.hpp"
#include "engine/primitives/Frustum.hpp"
#include "engine/primitives/TransformComponent.hpp"
@@ -26,8 +27,13 @@ namespace fgl::engine
Frustum< CoordinateSpace::Model > createFrustum( float aspect, float fovy, float near, float far );
using CameraIDX = std::uint8_t;
class Camera
{
inline static CameraIDX camera_counter { 0 };
CameraIDX camera_idx { camera_counter++ };
Matrix< MatrixType::CameraToScreen > projection_matrix { 1.0f };
Matrix< MatrixType::WorldToCamera > view_matrix { 1.0f };
@@ -43,6 +49,7 @@ namespace fgl::engine
vk::Extent2D m_extent;
inline static std::unique_ptr< CameraRenderer > m_renderer;
std::shared_ptr< CameraSwapchain > m_swapchain;
Matrix< MatrixType::ModelToWorld > frustumTranslationMatrix() const;
@@ -51,9 +58,11 @@ namespace fgl::engine
public:
Camera( const vk::Extent2D extent );
static void initCameraRenderer();
void setExtent( const vk::Extent2D extent );
Camera( vk::Extent2D extent );
void setExtent( vk::Extent2D extent );
Rotation getRotation() const { return current_rotation; }
@@ -68,22 +77,14 @@ namespace fgl::engine
const Matrix< MatrixType::WorldToCamera >& getViewMatrix() const { return view_matrix; }
Matrix< MatrixType::WorldToScreen > getProjectionViewMatrix() const
{
assert( projection_matrix != constants::MAT4_IDENTITY );
return projection_matrix * view_matrix;
}
Matrix< MatrixType::WorldToScreen > getProjectionViewMatrix() const;
glm::mat4 getInverseViewMatrix() const { return glm::inverse( view_matrix ); }
void setOrthographicProjection( float left, float right, float top, float bottom, float near, float far );
void setPerspectiveProjection( float fovy, float aspect, float near, float far );
Coordinate< CoordinateSpace::World > getPosition() const
{
//Should maybe store the inverse view matrix
return WorldCoordinate( inverse_view_matrix[ 3 ] );
}
Coordinate< CoordinateSpace::World > getPosition() const;
Vector getUp() const { return -getDown(); }
@@ -97,13 +98,26 @@ namespace fgl::engine
Vector getDown() const { return Vector( glm::normalize( glm::vec3( inverse_view_matrix[ 1 ] ) ) ); }
//! Performs the render pass for this camera
void pass( FrameInfo& frame_info ) const;
static vk::raii::RenderPass& getRenderpass();
CameraSwapchain& getSwapchain() const;
void setViewport( const vk::raii::CommandBuffer& command_buffer );
void setScissor( const vk::raii::CommandBuffer& command_buffer );
void beginRenderpass( const vk::raii::CommandBuffer& command_buffer, const FrameInfo& info );
void endRenderpass( const vk::raii::CommandBuffer& command_buffer );
void copyOutput( const vk::raii::CommandBuffer& command_buffer, FrameIndex frame_index, Image& target );
enum ViewMode
{
Euler,
TaitBryan
};
void setView( WorldCoordinate pos, const Rotation rotation, const ViewMode mode = TaitBryan );
void setView( WorldCoordinate pos, const Rotation& rotation, ViewMode mode = TaitBryan );
};
} // namespace fgl::engine

View File

@@ -0,0 +1,154 @@
//
// Created by kj16609 on 7/21/24.
//
#include "CameraRenderer.hpp"
#include "CameraSwapchain.hpp"
#include "engine/rendering/RenderPass.hpp"
namespace fgl::engine
{
class CameraSwapchain;
vk::raii::RenderPass CameraRenderer::createRenderPass()
{
rendering::RenderPassBuilder builder {};
constexpr std::size_t PositionIndex { 0 };
constexpr std::size_t NormalIndex { 1 };
constexpr std::size_t AlbedoIndex { 2 };
constexpr std::size_t CompositeIndex { 3 };
constexpr std::size_t DepthIndex { 4 };
builder.setAttachmentCount( 5 );
// Set formats for each item in the swapchain
auto position { builder.attachment( PositionIndex ) };
position.setFormat( vk::Format::eR16G16B16A16Sfloat ); // position
position.setLayouts( vk::ImageLayout::eUndefined, vk::ImageLayout::eShaderReadOnlyOptimal );
position.setOps( vk::AttachmentLoadOp::eClear, vk::AttachmentStoreOp::eStore );
auto normal { builder.attachment( NormalIndex ) };
normal.setFormat( vk::Format::eR16G16B16A16Sfloat ); // normal
normal.setLayouts( vk::ImageLayout::eUndefined, vk::ImageLayout::eShaderReadOnlyOptimal );
normal.setOps( vk::AttachmentLoadOp::eClear, vk::AttachmentStoreOp::eStore );
auto albedo { builder.attachment( AlbedoIndex ) };
albedo.setFormat( vk::Format::eR8G8B8A8Unorm ); // albedo
albedo.setLayouts( vk::ImageLayout::eUndefined, vk::ImageLayout::eShaderReadOnlyOptimal );
albedo.setOps( vk::AttachmentLoadOp::eClear, vk::AttachmentStoreOp::eStore );
auto composite { builder.attachment( CompositeIndex ) };
composite.setFormat( vk::Format::eR8G8B8A8Unorm ); // composite
composite.setLayouts( vk::ImageLayout::eUndefined, vk::ImageLayout::eShaderReadOnlyOptimal );
composite.setOps( vk::AttachmentLoadOp::eClear, vk::AttachmentStoreOp::eStore );
auto depth { builder.attachment( DepthIndex ) };
depth.setLayouts( vk::ImageLayout::eUndefined, vk::ImageLayout::eDepthStencilReadOnlyOptimal );
depth.setFormat( SwapChain::findDepthFormat() ); // depth
depth.setOps( vk::AttachmentLoadOp::eClear, vk::AttachmentStoreOp::eStore );
auto& g_buffer_subpass { builder.createSubpass( 0 ) };
g_buffer_subpass.setDepthLayout( DepthIndex, vk::ImageLayout::eDepthStencilAttachmentOptimal );
g_buffer_subpass.addRenderLayout( PositionIndex, vk::ImageLayout::eColorAttachmentOptimal );
g_buffer_subpass.addRenderLayout( NormalIndex, vk::ImageLayout::eColorAttachmentOptimal );
g_buffer_subpass.addRenderLayout( AlbedoIndex, 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( CompositeIndex, vk::ImageLayout::eColorAttachmentOptimal );
composite_subpass.addInputLayout( PositionIndex, vk::ImageLayout::eShaderReadOnlyOptimal );
composite_subpass.addInputLayout( NormalIndex, vk::ImageLayout::eShaderReadOnlyOptimal );
composite_subpass.addInputLayout( AlbedoIndex, 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 )
{
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.endRenderPass();
}
void CameraRenderer::pass( FrameInfo& frame_info, CameraSwapchain& camera_swapchain )
{
m_culling_system.startPass( frame_info );
auto& command_buffer { frame_info.command_buffer };
beginRenderPass( command_buffer, camera_swapchain, frame_info.frame_idx );
m_culling_system.wait();
m_terrain_system.pass( frame_info );
m_entity_renderer.pass( frame_info );
m_composition_system.pass( frame_info );
endRenderPass( command_buffer );
}
vk::raii::RenderPass& CameraRenderer::getRenderpass()
{
return m_renderpass;
}
} // namespace fgl::engine

View File

@@ -0,0 +1,48 @@
//
// Created by kj16609 on 7/21/24.
//
#pragma once
#include "CameraSwapchain.hpp"
#include "engine/rendering/SwapChain.hpp"
#include "engine/systems/CompositionSystem.hpp"
#include "engine/systems/CullingSystem.hpp"
#include "engine/systems/EntityRendererSystem.hpp"
#include "engine/systems/TerrainSystem.hpp"
namespace fgl::engine
{
class CameraRenderer
{
vk::raii::RenderPass m_renderpass;
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 );
CullingSystem m_culling_system {};
// SubPass 0
TerrainSystem m_terrain_system { Device::getInstance(), m_renderpass };
EntityRendererSystem m_entity_renderer { Device::getInstance(), m_renderpass };
// SubPass 1
CompositionSystem m_composition_system { Device::getInstance(), m_renderpass };
void beginRenderPass(
const vk::raii::CommandBuffer& command_buffer, CameraSwapchain& swapchain, const FrameIndex index );
void endRenderPass( const vk::raii::CommandBuffer& command_buffer );
public:
void pass( FrameInfo& frame_info, CameraSwapchain& camera_swapchain );
vk::raii::RenderPass& getRenderpass();
CameraRenderer() : m_renderpass( createRenderPass() ) {}
};
} // namespace fgl::engine

View File

@@ -4,81 +4,60 @@
#include "CameraSwapchain.hpp"
#include "engine/descriptors/DescriptorSet.hpp"
namespace fgl::engine
{
vk::raii::RenderPass CameraSwapchain::creaeteRenderpass()
std::vector< std::unique_ptr< descriptors::DescriptorSet > > CameraSwapchain::createGBufferDescriptors()
{
RenderPassBuilder builder;
std::vector< std::unique_ptr< descriptors::DescriptorSet > > data {};
data.resize( SwapChain::MAX_FRAMES_IN_FLIGHT );
builder.registerAttachments( output.composite, output.depth, gbuffer.position, gbuffer.normal, gbuffer.albedo );
for ( PresentIndex i = 0; i < SwapChain::MAX_FRAMES_IN_FLIGHT; ++i )
{
auto set { std::make_unique< descriptors::DescriptorSet >( GBufferDescriptorSet::createLayout() ) };
Subpass<
vk::PipelineBindPoint::eGraphics,
UsedAttachment< DepthAttachment< 4 >, vk::ImageLayout::eDepthStencilAttachmentOptimal >,
UsedAttachment< ColorAttachment< 0 >, vk::ImageLayout::eColorAttachmentOptimal >,
UsedAttachment< ColorAttachment< 1 >, vk::ImageLayout::eColorAttachmentOptimal >,
UsedAttachment< ColorAttachment< 2 >, vk::ImageLayout::eColorAttachmentOptimal > >
g_buffer_subpass { 0 };
set->setMaxIDX( 2 );
g_buffer_subpass.registerDependencyFromExternal(
vk::AccessFlagBits::eDepthStencilAttachmentWrite,
vk::PipelineStageFlagBits::eEarlyFragmentTests | vk::PipelineStageFlagBits::eLateFragmentTests );
set->bindAttachment( 0, gbuffer.position.getView( i ), vk::ImageLayout::eShaderReadOnlyOptimal );
g_buffer_subpass.registerDependencyFromExternal(
vk::AccessFlagBits::eColorAttachmentWrite, vk::PipelineStageFlagBits::eColorAttachmentOutput );
set->bindAttachment( 1, gbuffer.normal.getView( i ), vk::ImageLayout::eShaderReadOnlyOptimal );
Subpass<
vk::PipelineBindPoint::eGraphics,
UsedAttachment< ColorAttachment< 3 >, vk::ImageLayout::eColorAttachmentOptimal >,
InputAttachment< ColorAttachment< 0 >, vk::ImageLayout::eShaderReadOnlyOptimal >,
InputAttachment< ColorAttachment< 1 >, vk::ImageLayout::eShaderReadOnlyOptimal >,
InputAttachment< ColorAttachment< 2 >, vk::ImageLayout::eShaderReadOnlyOptimal > >
composite_subpass { 1 };
set->bindAttachment( 2, gbuffer.albedo.getView( i ), vk::ImageLayout::eShaderReadOnlyOptimal );
composite_subpass.registerDependencyFromExternal(
vk::AccessFlagBits::eColorAttachmentWrite, vk::PipelineStageFlagBits::eColorAttachmentOutput );
set->update();
// For color attachments
composite_subpass.registerDependencyFrom(
g_buffer_subpass,
vk::AccessFlagBits::eColorAttachmentWrite,
vk::PipelineStageFlagBits::eColorAttachmentOutput,
vk::AccessFlagBits::eInputAttachmentRead,
vk::PipelineStageFlagBits::eFragmentShader,
vk::DependencyFlagBits::eByRegion );
data[ i ] = std::move( set );
}
composite_subpass.registerDependencyToExternal(
vk::AccessFlagBits::eColorAttachmentWrite,
vk::PipelineStageFlagBits::eColorAttachmentOutput,
vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eInputAttachmentRead,
vk::PipelineStageFlagBits::eFragmentShader );
return data;
}
//Done
builder.registerSubpass( g_buffer_subpass );
builder.registerSubpass( composite_subpass );
return builder.create();
const std::vector< vk::ClearValue >& CameraSwapchain::getClearValues()
{
assert( !m_clear_values.empty() );
return m_clear_values;
}
std::vector< vk::raii::Framebuffer > CameraSwapchain::createFrambuffers()
{
const auto image_count { SwapChain::MAX_FRAMES_IN_FLIGHT };
gbuffer.position.createResourceSpread( image_count, m_extent );
gbuffer.normal.createResourceSpread( image_count, m_extent );
gbuffer.albedo.createResourceSpread( image_count, m_extent );
constexpr auto image_count { SwapChain::MAX_FRAMES_IN_FLIGHT };
gbuffer.position.createResources( image_count, m_extent );
gbuffer.normal.createResources( image_count, m_extent );
gbuffer.albedo.createResources( image_count, m_extent );
output.composite.createResourceSpread( image_count, m_extent, vk::ImageUsageFlagBits::eSampled );
output.depth.createResourceSpread( image_count, m_extent );
gbuffer.composite.createResources( image_count, m_extent, vk::ImageUsageFlagBits::eTransferSrc );
gbuffer.depth.createResources( image_count, m_extent );
gbuffer.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, gbuffer.position, gbuffer.normal, gbuffer.albedo, output.composite, output.depth )
};
std::vector< vk::ImageView > attachments { getViewsForFrame(
i, gbuffer.position, gbuffer.normal, gbuffer.albedo, gbuffer.composite, gbuffer.depth ) };
vk::FramebufferCreateInfo info {};
info.renderPass = m_renderpass;
@@ -88,15 +67,59 @@ namespace fgl::engine
info.layers = 1;
buffers.emplace_back( Device::getInstance()->createFramebuffer( info ) );
auto& position_resources { gbuffer.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 ) );
g_buffer_position_img.emplace_back( std::make_unique< Texture >( position_image ) );
g_buffer_normal_img.emplace_back( std::make_unique< Texture >( gbuffer.normal.m_attachment_resources
.m_images[ i ]
->setName( "GBufferNormal" ) ) );
g_buffer_albedo_img.emplace_back( std::make_unique< Texture >( gbuffer.albedo.m_attachment_resources
.m_images[ i ]
->setName( "GBufferAlbedo" ) ) );
g_buffer_composite_img.emplace_back( std::make_unique< Texture >( gbuffer.composite.m_attachment_resources
.m_images[ i ]
->setName( "GBufferComposite" ) ) );
}
return buffers;
}
CameraSwapchain::CameraSwapchain( const vk::Extent2D extent ) :
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->gbuffer.composite.m_attachment_resources.m_images.size() );
return *gbuffer.composite.m_attachment_resources.m_images[ index ];
}
CameraSwapchain::CameraSwapchain( vk::raii::RenderPass& renderpass, const vk::Extent2D extent ) :
m_extent( extent ),
m_renderpass( creaeteRenderpass() ),
m_framebuffers( createFrambuffers() )
{}
m_renderpass( renderpass ),
m_framebuffers( createFrambuffers() ),
m_clear_values(
gatherClearValues( gbuffer.albedo, gbuffer.composite, gbuffer.depth, gbuffer.normal, gbuffer.position ) ),
m_gbuffer_descriptor_set( createGBufferDescriptors() )
{
gbuffer.depth.setName( "Depth" );
}
} // namespace fgl::engine

View File

@@ -4,6 +4,7 @@
#pragma once
#include "engine/descriptors/DescriptorSet.hpp"
#include "engine/rendering/Attachment.hpp"
#include "engine/rendering/SwapChain.hpp"
@@ -17,27 +18,46 @@ namespace fgl::engine
ColorAttachment< 0 > position { vk::Format::eR16G16B16A16Sfloat };
ColorAttachment< 1 > normal { vk::Format::eR16G16B16A16Sfloat };
ColorAttachment< 2 > albedo { vk::Format::eR8G8B8A8Unorm };
} gbuffer {};
struct
{
//Final attachments
ColorAttachment< 3 > composite { vk::Format::eR8G8B8A8Unorm };
DepthAttachment< 4 > depth { SwapChain::findDepthFormat() };
} output {};
vk::Extent2D m_extent;
vk::raii::RenderPass m_renderpass;
std::vector< vk::raii::Framebuffer > m_framebuffers;
} gbuffer {};
public:
vk::raii::RenderPass creaeteRenderpass();
std::vector< std::unique_ptr< Texture > > g_buffer_position_img {};
std::vector< std::unique_ptr< Texture > > g_buffer_normal_img {};
std::vector< std::unique_ptr< Texture > > g_buffer_albedo_img {};
std::vector< std::unique_ptr< Texture > > g_buffer_composite_img {};
private:
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();
public:
CameraSwapchain( vk::raii::RenderPass& renderpass, vk::Extent2D extent );
const std::vector< vk::ClearValue >& getClearValues();
std::vector< vk::raii::Framebuffer > createFrambuffers();
CameraSwapchain( const vk::Extent2D extent );
descriptors::DescriptorSet& getGBufferDescriptor( FrameIndex frame_index );
vk::raii::Framebuffer& getFramebuffer( FrameIndex frame_index );
vk::Extent2D getExtent() const;
Image& getOutput( const FrameIndex index );
};
} // namespace fgl::engine

View File

@@ -4,8 +4,11 @@
#pragma once
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#include <glm/mat4x4.hpp>
#include <glm/vec3.hpp>
#pragma GCC diagnostic pop
namespace fgl::engine::constants
{

View File

@@ -34,6 +34,10 @@ namespace fgl::engine
#define ENABLE_IMGUI_DRAWERS 0
#endif
#ifndef ENABLE_IMGUI
#define ENABLE_IMGUI 0
#endif
#if ENABLE_IMGUI_DRAWERS
namespace fgl::engine::debug
{

View File

@@ -27,6 +27,7 @@ namespace fgl::engine::descriptors
class DescriptorSet
{
//TODO: Maybe redo this to not be a monostate variant?
std::vector< std::variant< std::monostate, vk::DescriptorImageInfo, vk::DescriptorBufferInfo > > m_infos {};
std::vector< vk::WriteDescriptorSet > descriptor_writes {};

View File

@@ -4,6 +4,9 @@
#pragma once
#include <cstdint>
#include <string_view>
namespace fgl::engine
{

View File

@@ -4,7 +4,11 @@
#include "ModelComponent.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wold-style-cast"
#pragma GCC diagnostic ignored "-Weffc++"
#include <imgui.h>
#pragma GCC diagnostic pop
namespace fgl::engine
{

View File

@@ -54,7 +54,7 @@ namespace fgl::engine::gui
.MSAASamples = VK_SAMPLE_COUNT_1_BIT,
.PipelineCache = VK_NULL_HANDLE,
.Subpass = 2,
.Subpass = 0,
.UseDynamicRendering = VK_FALSE,
.PipelineRenderingCreateInfo = {},

View File

@@ -15,6 +15,8 @@
// clang-format on
#include "engine/FrameInfo.hpp"
#include "engine/camera/Camera.hpp"
#include "engine/camera/CameraSwapchain.hpp"
#include "engine/filesystem/scanner/FileScanner.hpp"
#include "engine/filesystem/types.hpp"
#include "engine/gameobjects/components/ModelComponent.hpp"
@@ -99,7 +101,7 @@ namespace fgl::engine::gui
void drawRenderingOutputs( FrameInfo& info )
{
ZoneScoped;
const auto present_idx { info.present_idx };
const auto frame_index { info.frame_idx };
ImGui::Begin( "RenderOutputs" );
@@ -142,7 +144,7 @@ namespace fgl::engine::gui
current = Composite;
}
info.swap_chain.g_buffer_albedo_img[ present_idx ]->drawImGui( { v_size, h_size } );
info.camera_data.camera.getSwapchain().g_buffer_albedo_img[ frame_index ]->drawImGui( { v_size, h_size } );
ImGui::SameLine();
if ( ImGui::Selectable( options[ Albedo ], current == Albedo ) )
{
@@ -150,7 +152,7 @@ namespace fgl::engine::gui
current = Albedo;
}
info.swap_chain.g_buffer_normal_img[ present_idx ]->drawImGui( { v_size, h_size } );
info.camera_data.camera.getSwapchain().g_buffer_normal_img[ frame_index ]->drawImGui( { v_size, h_size } );
ImGui::SameLine();
if ( ImGui::Selectable( options[ Normal ], current == Normal ) )
{
@@ -158,7 +160,8 @@ namespace fgl::engine::gui
current = Normal;
}
info.swap_chain.g_buffer_position_img[ present_idx ]->drawImGui( { v_size, h_size } );
info.camera_data.camera.getSwapchain().g_buffer_position_img[ frame_index ]->drawImGui( { v_size,
h_size } );
ImGui::SameLine();
if ( ImGui::Selectable( options[ Position ], current == Position ) )
{
@@ -174,16 +177,16 @@ namespace fgl::engine::gui
default:
[[fallthrough]];
case Composite:
info.swap_chain.g_buffer_composite_img[ present_idx ]->drawImGui();
info.camera_data.camera.getSwapchain().g_buffer_composite_img[ frame_index ]->drawImGui();
break;
case Albedo:
info.swap_chain.g_buffer_albedo_img[ present_idx ]->drawImGui();
info.camera_data.camera.getSwapchain().g_buffer_albedo_img[ frame_index ]->drawImGui();
break;
case Normal:
info.swap_chain.g_buffer_normal_img[ present_idx ]->drawImGui();
info.camera_data.camera.getSwapchain().g_buffer_normal_img[ frame_index ]->drawImGui();
break;
case Position:
info.swap_chain.g_buffer_position_img[ present_idx ]->drawImGui();
info.camera_data.camera.getSwapchain().g_buffer_position_img[ frame_index ]->drawImGui();
break;
}

View File

@@ -22,6 +22,45 @@ namespace fgl::engine
}
}
Image::Image(
const vk::Extent2D extent,
const vk::Format format,
const vk::Image image,
const vk::ImageUsageFlags usage ) noexcept :
m_handle( std::make_shared< ImageHandle >( extent, format, image, usage ) ),
m_extent( extent )
{}
Image::Image(
const vk::Extent2D extent,
const vk::Format format,
const vk::ImageUsageFlags usage,
const vk::ImageLayout inital_layout,
const vk::ImageLayout final_layout ) :
m_handle( std::make_shared< ImageHandle >( extent, format, usage, inital_layout, final_layout ) ),
m_extent( extent )
{}
Image& Image::operator=( const Image& other )
{
m_handle = other.m_handle;
view = {};
return *this;
}
VkImage Image::getVkImage() const
{
return m_handle->getVkImage();
}
Image& Image::operator=( Image&& other ) noexcept
{
m_handle = std::move( other.m_handle );
view = std::move( other.view );
m_extent = other.m_extent;
return *this;
}
Image& Image::setName( const std::string& str )
{
m_handle->setName( str );

View File

@@ -7,7 +7,6 @@
#include <memory>
#include "engine/image/ImageHandle.hpp"
#include "engine/rendering/Device.hpp"
namespace fgl::engine
{
@@ -22,6 +21,7 @@ namespace fgl::engine
{
std::shared_ptr< ImageHandle > m_handle;
std::weak_ptr< ImageView > view {};
vk::Extent2D m_extent;
friend class memory::TransferManager;
@@ -29,42 +29,29 @@ namespace fgl::engine
Image() = delete;
[[nodiscard]]
Image( vk::Extent2D extent, vk::Format format, vk::Image image, vk::ImageUsageFlags usage ) noexcept;
[[nodiscard]] Image(
const vk::Extent2D extent,
const vk::Format format,
const vk::Image image,
const vk::ImageUsageFlags usage ) noexcept :
m_handle( std::make_shared< ImageHandle >( extent, format, image, usage ) )
{}
vk::Extent2D extent,
vk::Format format,
vk::ImageUsageFlags usage,
vk::ImageLayout inital_layout,
vk::ImageLayout final_layout );
Image& setName( const std::string& str );
Image( const Image& other ) : m_handle( other.m_handle ), m_extent( other.m_extent ) {}
Image(
const vk::Extent2D extent,
const vk::Format format,
const vk::ImageUsageFlags usage,
const vk::ImageLayout inital_layout,
const vk::ImageLayout final_layout ) :
m_handle( std::make_shared< ImageHandle >( extent, format, usage, inital_layout, final_layout ) )
{}
[[nodiscard]] Image& operator=( const Image& other );
Image( const Image& other ) : m_handle( other.m_handle ) {}
[[nodiscard]] Image& operator=( const Image& other )
{
m_handle = other.m_handle;
view = {};
return *this;
}
VkImage getVkImage() const;
[[nodiscard]] Image( Image&& other ) = default;
[[nodiscard]] Image& operator=( Image&& other ) noexcept
{
m_handle = std::move( other.m_handle );
view = std::move( other.view );
return *this;
}
[[nodiscard]] Image& operator=( Image&& other ) noexcept;
Image& setName( const std::string& str );
const vk::Extent2D& getExtent() const { return m_extent; }
[[nodiscard]] std::shared_ptr< ImageView > getView();
};

View File

@@ -64,7 +64,7 @@ namespace fgl::engine
return vk::Filter::eLinear;
}
std::unreachable();
FGL_UNREACHABLE();
}
vk::SamplerAddressMode wrappingToVk( const int val )

View File

@@ -4,7 +4,12 @@
#include "generator.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#include <glm/geometric.hpp>
#pragma GCC diagnostic pop
#include <tracy/Tracy.hpp>
#include <algorithm>

View File

@@ -4,7 +4,10 @@
#pragma once
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#include <glm/vec2.hpp>
#pragma GCC diagnostic pop
#include <vector>

View File

@@ -49,7 +49,7 @@ namespace fgl::engine
throw std::runtime_error( "Unimplemented rotation order" );
}
std::unreachable();
FGL_UNREACHABLE();
}
glm::mat3 taitBryanMatrix( const glm::vec3 rotation, const RotationOrder order )

View File

@@ -4,7 +4,10 @@
#pragma once
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#include <glm/mat4x4.hpp>
#pragma GCC diagnostic pop
namespace fgl::engine
{

View File

@@ -4,7 +4,11 @@
#pragma once
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wduplicated-branches"
#include <glm/glm.hpp>
#pragma GCC diagnostic pop
#include <filesystem>
#include <memory>

View File

@@ -5,7 +5,12 @@
#include "Vertex.hpp"
#define GLM_ENABLE_EXPERIMENTAL
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wduplicated-branches"
#include <glm/vec2.hpp>
#include <glm/gtx/hash.hpp>
#pragma GCC diagnostic pop
#include "Model.hpp"
#include "engine/utils.hpp"

View File

@@ -4,8 +4,12 @@
#pragma once
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#include <glm/vec2.hpp>
#include <glm/vec3.hpp>
#pragma GCC diagnostic pop
#include <vulkan/vulkan.hpp>
namespace fgl::engine

View File

@@ -308,10 +308,11 @@ namespace fgl::engine
}
log::debug( "Attributes for primitive:\n{}", att_str );
const bool has_normal { hasAttribute( prim, "NORMAL" ) };
//TODO: Get normal colors from texture
[[maybe_unused]] const bool has_normal { hasAttribute( prim, "NORMAL" ) };
const bool has_position { hasAttribute( prim, "POSITION" ) };
const bool has_texcoord { hasAttribute( prim, "TEXCOORD_0" ) };
const int texcoord_count { has_texcoord ? getTexcoordCount( prim ) : 0 };
[[maybe_unused]] const int texcoord_count { has_texcoord ? getTexcoordCount( prim ) : 0 };
if ( !has_position ) throw std::runtime_error( "Failed to load model. Missing expected POSITION attribute" );
@@ -355,7 +356,7 @@ namespace fgl::engine
}
}
std::unreachable();
FGL_UNREACHABLE();
}
OrientedBoundingBox< CoordinateSpace::Model > createModelBoundingBox( const std::vector< Primitive >& primitives )
@@ -448,12 +449,23 @@ namespace fgl::engine
const std::vector< double > scale { node.scale };
if ( rotation.size() == 4 )
obj.getTransform().rotation = glm::quat( rotation[ 0 ], rotation[ 1 ], rotation[ 2 ], rotation[ 3 ] );
obj.getTransform().rotation = glm::quat(
static_cast< float >( rotation[ 0 ] ),
static_cast< float >( rotation[ 1 ] ),
static_cast< float >( rotation[ 2 ] ),
static_cast< float >( rotation[ 3 ] ) );
if ( scale.size() == 3 ) obj.getTransform().scale = glm::vec3( scale[ 0 ], scale[ 1 ], scale[ 2 ] );
if ( scale.size() == 3 )
obj.getTransform().scale = glm::vec3(
static_cast< float >( scale[ 0 ] ),
static_cast< float >( scale[ 1 ] ),
static_cast< float >( scale[ 2 ] ) );
if ( translation.size() == 3 )
obj.getTransform().translation = WorldCoordinate( translation[ 0 ], translation[ 1 ], translation[ 2 ] );
obj.getTransform().translation = WorldCoordinate(
static_cast< float >( translation[ 0 ] ),
static_cast< float >( translation[ 1 ] ),
static_cast< float >( translation[ 2 ] ) );
obj.getName() = node.name;

View File

@@ -4,8 +4,13 @@
#pragma once
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wduplicated-branches"
#include <glm/gtx/hash.hpp>
#include <glm/vec2.hpp>
#include <glm/vec3.hpp>
#pragma GCC diagnostic pop
#include <filesystem>
#include <vector>

View File

@@ -30,7 +30,7 @@ namespace fgl::engine
const tinyobj::attrib_t& attrib { reader.GetAttrib() };
const std::vector< tinyobj::shape_t >& shapes { reader.GetShapes() };
const std::vector< tinyobj::material_t >& materials { reader.GetMaterials() };
[[maybe_unused]] const std::vector< tinyobj::material_t >& materials { reader.GetMaterials() };
if ( shapes.size() == 0 ) throw std::runtime_error( "Failed to get shapes from OBJ" );

View File

@@ -4,6 +4,8 @@
#pragma once
#include <ostream>
#include "engine/primitives/lines/InfiniteLine.hpp"
#include "engine/primitives/planes/OriginDistancePlane.hpp"
#include "engine/primitives/planes/PointPlane.hpp"

View File

@@ -6,6 +6,7 @@
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wduplicated-branches"
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
#pragma GCC diagnostic pop
@@ -131,7 +132,7 @@ namespace fgl::engine
case RotationModifierType::Yaw:
return const_cast< const Rotation& >( rot ).yaw();
}
std::unreachable();
FGL_UNREACHABLE();
}
namespace constants
@@ -151,6 +152,8 @@ namespace fgl::engine
case RotationModifierType::Yaw:
return constants::WORLD_DOWN;
}
FGL_UNREACHABLE();
}
template < RotationModifierType ModifierType >

View File

@@ -4,9 +4,25 @@
#pragma once
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#include <glm/vec3.hpp>
#pragma GCC diagnostic pop
namespace fgl::engine
{
using Scale = glm::vec3;
struct Scale : public glm::vec3
{
using glm::vec3::x;
using glm::vec3::y;
using glm::vec3::z;
Scale( const glm::vec3 value ) : glm::vec3( value ) {}
Scale( const float value ) : glm::vec3( value ) {}
Scale( const float x_i, const float y_i, const float z_i ) : glm::vec3( x_i, y_i, z_i ) {}
};
} // namespace fgl::engine

View File

@@ -4,7 +4,10 @@
#include "LineBase.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#include <glm/geometric.hpp>
#pragma GCC diagnostic push
namespace fgl::engine
{

View File

@@ -4,7 +4,10 @@
#pragma once
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#include <glm/vec3.hpp>
#pragma GCC diagnostic pop
namespace fgl::engine
{

View File

@@ -4,9 +4,10 @@
#pragma once
#include <glm/mat4x4.hpp>
#include "MatrixEvolvedTypes.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#include <glm/mat3x3.hpp>
#pragma GCC diagnostic pop
namespace fgl::engine
{

View File

@@ -4,9 +4,11 @@
#pragma once
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wduplicated-branches"
#include <glm/glm.hpp>
#include <ostream>
#pragma GCC diagnostic pop
#include "engine/constants.hpp"
#include "engine/primitives/CoordinateSpace.hpp"

View File

@@ -4,8 +4,11 @@
#pragma once
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#include <glm/geometric.hpp>
#include <glm/vec3.hpp>
#pragma GCC diagnostic pop
#include "engine/primitives/CoordinateSpace.hpp"

View File

@@ -4,7 +4,10 @@
#pragma once
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#include <glm/vec3.hpp>
#pragma GCC diagnostic pop
#include "engine/FGL_DEFINES.hpp"
#include "engine/constants.hpp"

View File

@@ -13,6 +13,7 @@
#include "engine/concepts/is_attachment.hpp"
#include "engine/image/Image.hpp"
#include "types.hpp"
namespace fgl::engine
{
@@ -42,6 +43,14 @@ namespace fgl::engine
void setClear( vk::ClearDepthStencilValue value ) { m_clear_value = value; }
void setName( const char* str )
{
for ( const auto& image : m_attachment_resources.m_images )
{
image->setName( str );
}
}
AttachmentResources m_attachment_resources {};
constexpr static vk::AttachmentLoadOp loadOp { load_op };
@@ -50,7 +59,7 @@ namespace fgl::engine
constexpr static vk::ImageLayout FinalLayout { final_layout };
constexpr static std::uint32_t m_index { Index };
Attachment( const vk::Format format )
constexpr Attachment( const vk::Format format )
{
assert( format != vk::Format::eUndefined && "Attachment format must not be undefined" );
description.format = format;
@@ -81,7 +90,8 @@ namespace fgl::engine
}
}
void createResources( const std::uint32_t count, vk::Extent2D extent )
void createResources(
const std::uint32_t count, vk::Extent2D extent, vk::ImageUsageFlags extra_flags = vk::ImageUsageFlags( 0 ) )
{
for ( std::uint16_t i = 0; i < count; ++i )
{
@@ -90,8 +100,8 @@ namespace fgl::engine
auto& itter { images.emplace_back( std::make_shared< Image >(
extent,
description.format,
usage | vk::ImageUsageFlagBits::eInputAttachment,
inital_layout,
usage | vk::ImageUsageFlagBits::eInputAttachment | extra_flags,
vk::ImageLayout::eUndefined,
final_layout ) ) };
image_views.emplace_back( itter->getView() );
}
@@ -105,7 +115,7 @@ namespace fgl::engine
extent,
description.format,
usage | vk::ImageUsageFlagBits::eInputAttachment | extra_flags,
inital_layout,
vk::ImageLayout::eUndefined,
final_layout ) };
for ( std::uint32_t i = 0; i < count; ++i )
{
@@ -114,33 +124,31 @@ namespace fgl::engine
}
}
ImageView& getView( std::uint8_t frame_idx )
ImageView& getView( const FrameIndex frame_idx )
{
assert( frame_idx < m_attachment_resources.m_image_views.size() );
return *m_attachment_resources.m_image_views[ frame_idx ];
}
vk::AttachmentDescription& desc() { return description; }
constexpr vk::AttachmentDescription& desc() { return description; }
friend class RenderPassBuilder;
};
template < is_attachment AttachmentT, vk::ImageLayout layout >
template < std::size_t index, vk::ImageLayout layout >
struct InputAttachment
{
static constexpr bool is_input { true };
static constexpr vk::ImageLayout m_layout { layout };
using Attachment = AttachmentT;
static constexpr std::size_t m_index { index };
};
template < is_attachment AttachmentT, vk::ImageLayout layout >
template < std::size_t index, vk::ImageLayout layout >
struct UsedAttachment
{
static constexpr bool is_input { false };
static constexpr vk::ImageLayout m_layout { layout };
using Attachment = AttachmentT;
static constexpr std::size_t m_index { index };
static constexpr bool is_input { false };
};
template < typename T >
@@ -189,7 +197,7 @@ namespace fgl::engine
}
template < is_attachment... Attachments >
static std::vector< vk::ImageView > getViewsForFrame( const std::uint8_t frame_idx, Attachments... attachments )
static std::vector< vk::ImageView > getViewsForFrame( const FrameIndex frame_idx, Attachments... attachments )
{
std::vector< vk::ImageView > view {};
view.resize( sizeof...( Attachments ) );
@@ -230,13 +238,28 @@ namespace fgl::engine
vk::ImageLayout::eDepthStencilAttachmentOptimal,
vk::ImageUsageFlagBits::eDepthStencilAttachment >;
#if ENABLE_IMGUI
constexpr vk::ImageUsageFlags IMGUI_ATTACHMENT_FLAGS { vk::ImageUsageFlagBits::eSampled };
#else
constexpr vk::ImageUsageFlags IMGUI_ATTACHMENT_FLAGS { 0 };
#endif
template < std::uint32_t Index >
using ColorAttachment = Attachment<
Index,
vk::AttachmentLoadOp::eClear,
vk::AttachmentStoreOp::eDontCare,
vk::AttachmentStoreOp::eStore,
vk::ImageLayout::eUndefined,
vk::ImageLayout::eShaderReadOnlyOptimal,
vk::ImageUsageFlagBits::eColorAttachment >;
vk::ImageUsageFlagBits::eColorAttachment | IMGUI_ATTACHMENT_FLAGS >;
template < std::uint32_t Index >
using InputColorAttachment = Attachment<
Index,
vk::AttachmentLoadOp::eLoad,
vk::AttachmentStoreOp::eDontCare,
vk::ImageLayout::eShaderReadOnlyOptimal,
vk::ImageLayout::eShaderReadOnlyOptimal,
vk::ImageUsageFlagBits::eColorAttachment | IMGUI_ATTACHMENT_FLAGS >;
} // namespace fgl::engine

View File

@@ -3,6 +3,8 @@
#include "engine/descriptors/DescriptorPool.hpp"
// std headers
#include <tracy/Tracy.hpp>
#include <cstring>
#include <iostream>
#include <set>

View File

@@ -0,0 +1,257 @@
//
// Created by kj16609 on 7/21/24.
//
#include "RenderPass.hpp"
#include "Device.hpp"
namespace fgl::engine::rendering
{
SubpassBuilder::SubpassBuilder( RenderPassBuilder& builder, const std::uint32_t index ) :
m_builder( builder ),
m_subpass_idx( index )
{}
//! Sets the layout the attachment is expected to and should be in during this subpass
void SubpassBuilder::addRenderLayout( const std::uint32_t index, const vk::ImageLayout layout )
{
// Check that the layout hasn't already been set
assert(
std::find_if(
m_attachment_references.begin(),
m_attachment_references.end(),
[ index ]( const vk::AttachmentReference& attachment_ref )
{ return attachment_ref.attachment == index; } )
== m_attachment_references.end() );
assert( layout != vk::ImageLayout::eShaderReadOnlyOptimal );
assert( layout != vk::ImageLayout::ePreinitialized );
assert( layout != vk::ImageLayout::eDepthStencilAttachmentOptimal );
m_attachment_references.emplace_back( vk::AttachmentReference( index, layout ) );
}
void SubpassBuilder::addInputLayout( const std::uint32_t index, const vk::ImageLayout layout )
{
// Check that the layout hasn't already been set
assert(
std::find_if(
m_input_attachment_references.begin(),
m_input_attachment_references.end(),
[ index ]( const vk::AttachmentReference& attachment_ref )
{ return attachment_ref.attachment == index; } )
== m_input_attachment_references.end() );
m_input_attachment_references.emplace_back( vk::AttachmentReference( index, layout ) );
}
void SubpassBuilder::setDepthLayout( const std::uint32_t index, const vk::ImageLayout layout )
{
m_depth_reference = vk::AttachmentReference( index, layout );
}
void SubpassBuilder::addDependency(
const std::uint32_t src_idx,
const std::uint32_t dst_idx,
const vk::AccessFlags src_access,
const vk::PipelineStageFlags src_stage,
const vk::AccessFlags dst_access,
const vk::PipelineStageFlags dst_stage,
const vk::DependencyFlags extra_flags )
{
vk::SubpassDependency info {};
info.srcSubpass = src_idx;
info.dstSubpass = dst_idx;
info.srcAccessMask = src_access;
info.srcStageMask = src_stage;
assert( dst_stage != vk::PipelineStageFlags( 0 ) );
info.dstAccessMask = dst_access;
info.dstStageMask = dst_stage;
info.dependencyFlags = extra_flags;
m_dependencies.emplace_back( info );
}
void SubpassBuilder::addDependency(
const SubpassBuilder& source,
const vk::AccessFlags src_access,
const vk::PipelineStageFlags src_stage,
const vk::AccessFlags dst_access,
const vk::PipelineStageFlags dst_stage,
const vk::DependencyFlags extra_flags )
{
return addDependency(
source.m_subpass_idx, m_subpass_idx, src_access, src_stage, dst_access, dst_stage, extra_flags );
}
void SubpassBuilder::addDependencyToExternal(
const vk::AccessFlags src_access,
const vk::PipelineStageFlags src_stage,
const vk::AccessFlags dst_access,
const vk::PipelineStageFlags dst_stage,
const vk::DependencyFlags extra_flags )
{
return addDependency(
m_subpass_idx,
VK_SUBPASS_EXTERNAL,
src_access,
src_stage,
( dst_access == vk::AccessFlagBits::eNone ) ? src_access : dst_access,
( dst_stage == vk::PipelineStageFlagBits::eNone ) ? src_stage : dst_stage,
extra_flags );
}
void SubpassBuilder::addDependencyFromExternal(
const vk::AccessFlags src_access,
const vk::PipelineStageFlags src_stage,
const vk::AccessFlags dst_access,
const vk::PipelineStageFlags dst_stage,
const vk::DependencyFlags extra_flags )
{
return addDependency(
VK_SUBPASS_EXTERNAL,
m_subpass_idx,
src_access,
src_stage,
( dst_access == vk::AccessFlagBits::eNone ) ? src_access : dst_access,
( dst_stage == vk::PipelineStageFlagBits::eNone ) ? src_stage : dst_stage,
extra_flags );
}
vk::SubpassDescription SubpassBuilder::description() const
{
vk::SubpassDescription description {};
description.setInputAttachments( m_input_attachment_references );
description.setColorAttachments( m_attachment_references );
description.setPDepthStencilAttachment( &m_depth_reference );
// We'll need to allow this to be changed if we are gonna use compute alongside graphics during a render pass
description.setPipelineBindPoint( vk::PipelineBindPoint::eGraphics );
// Apparently this can be used to preserve an attachment from a previous subpass.
// This might be helpful to ensure we have set if we aren't using an attachment in a certian subpass
// But use it later in the subpass.
description.setPreserveAttachments( m_preserved_attachment_references );
//todo: Figure out what resolve attachments are for.
// Flags aren't needed unless we are doing something with a specific device.
description.flags = vk::SubpassDescriptionFlags( 0 );
return description;
}
AttachmentInfo::AttachmentInfo( RenderPassBuilder& builder, std::size_t index ) :
m_index( index ),
m_builder( builder )
{}
void AttachmentInfo::setFormat( vk::Format format )
{
m_builder.setFormat( m_index, format );
#ifndef NDEBUG
set_format = true;
#endif
}
void AttachmentInfo::setLayouts( vk::ImageLayout image_layout, vk::ImageLayout final_layout )
{
m_builder.setLayouts( m_index, image_layout, final_layout );
#ifndef NDEBUG
set_layout = true;
#endif
}
void AttachmentInfo::setOps( vk::AttachmentLoadOp load_op, vk::AttachmentStoreOp store_op )
{
m_builder.setOps( m_index, load_op, store_op );
#ifndef NDEBUG
set_ops = true;
#endif
}
SubpassBuilder& RenderPassBuilder::createSubpass( const std::uint32_t index )
{
m_subpasses.emplace_back( new SubpassBuilder( *this, index ) );
return *m_subpasses.back();
}
SubpassBuilder& RenderPassBuilder::subpass( const std::size_t index ) const
{
return *m_subpasses[ index ];
}
void RenderPassBuilder::setAttachmentCount( const std::size_t count )
{
m_attachment_descriptions.resize( count );
}
void RenderPassBuilder::setFormat( const std::size_t index, const vk::Format format )
{
assert( index < m_attachment_descriptions.size() && "Maybe forgot call setAttachmentCount()?" );
m_attachment_descriptions[ index ].format = format;
}
void RenderPassBuilder::setInitalLayout( const std::size_t index, const vk::ImageLayout layout )
{
assert( index < m_attachment_descriptions.size() && "Maybe forgot call setAttachmentCount()?" );
m_attachment_descriptions[ index ].initialLayout = layout;
}
void RenderPassBuilder::setFinalLayout( const std::size_t index, const vk::ImageLayout layout )
{
assert( index < m_attachment_descriptions.size() && "Maybe forgot call setAttachmentCount()?" );
m_attachment_descriptions[ index ].finalLayout = layout;
}
void RenderPassBuilder::
setOps( const std::size_t index, const vk::AttachmentLoadOp load_op, const vk::AttachmentStoreOp store_op )
{
m_attachment_descriptions[ index ].loadOp = load_op;
m_attachment_descriptions[ index ].storeOp = store_op;
}
void RenderPassBuilder::
setLayouts( const std::size_t index, const vk::ImageLayout inital_layout, const vk::ImageLayout final_layout )
{
setInitalLayout( index, inital_layout );
setFinalLayout( index, final_layout );
}
vk::raii::RenderPass RenderPassBuilder::create()
{
vk::RenderPassCreateInfo info {};
std::vector< vk::SubpassDescription > subpass_descriptions {};
std::vector< vk::SubpassDependency > subpass_dependencies {};
for ( const auto& subpass : m_subpasses )
{
subpass_descriptions.emplace_back( subpass->description() );
for ( const auto& dependency : subpass->dependencies() )
{
subpass_dependencies.emplace_back( dependency );
}
}
info.setSubpasses( subpass_descriptions );
info.setSubpassCount( subpass_descriptions.size() );
info.setDependencies( subpass_dependencies );
info.setAttachments( m_attachment_descriptions );
return Device::getInstance()->createRenderPass( info );
}
AttachmentInfo RenderPassBuilder::attachment( const std::size_t index )
{
return AttachmentInfo( *this, index );
}
} // namespace fgl::engine::rendering

View File

@@ -0,0 +1,153 @@
//
// Created by kj16609 on 7/21/24.
//
#pragma once
#include <vulkan/vulkan.hpp>
#include <vulkan/vulkan_raii.hpp>
#include <vector>
namespace fgl::engine::rendering
{
class RenderPassBuilder;
class SubpassBuilder
{
RenderPassBuilder& m_builder;
std::uint32_t m_subpass_idx;
std::vector< vk::AttachmentReference > m_attachment_references {};
std::vector< vk::AttachmentReference > m_input_attachment_references {};
std::vector< std::uint32_t > m_preserved_attachment_references {};
vk::AttachmentReference m_depth_reference { VK_ATTACHMENT_UNUSED, vk::ImageLayout::eUndefined };
std::vector< vk::SubpassDependency > m_dependencies {};
SubpassBuilder( RenderPassBuilder& builder, std::uint32_t index );
public:
// BEGIN Attachments
//! Sets the expected attachment layout for this subpass at the index given.
void addRenderLayout( std::uint32_t index, vk::ImageLayout layout );
void addInputLayout( std::uint32_t index, vk::ImageLayout layout );
void setDepthLayout( std::uint32_t index, vk::ImageLayout layout );
//TODO: This
//void setPreserved( const std::uint32_t index, SubpassBuilder& subpass ) {}
// END Attachments
void addDependency(
std::uint32_t src_idx,
std::uint32_t dst_idx,
vk::AccessFlags src_access,
vk::PipelineStageFlags src_stage,
vk::AccessFlags dst_access,
vk::PipelineStageFlags dst_stage,
vk::DependencyFlags extra_flags );
void addDependency(
const SubpassBuilder& source,
vk::AccessFlags src_access,
vk::PipelineStageFlags src_stage,
vk::AccessFlags dst_access,
vk::PipelineStageFlags dst_stage,
vk::DependencyFlags extra_flags = vk::DependencyFlags( 0 ) );
void addDependencyToExternal(
vk::AccessFlags src_access,
vk::PipelineStageFlags src_stage,
vk::AccessFlags dst_access,
vk::PipelineStageFlags dst_stage,
vk::DependencyFlags extra_flags = vk::DependencyFlags( 0 ) );
void addDependencyFromExternal(
vk::AccessFlags src_access,
vk::PipelineStageFlags src_stage,
vk::AccessFlags dst_access = vk::AccessFlagBits::eNone,
vk::PipelineStageFlags dst_stage = vk::PipelineStageFlagBits::eNone,
vk::DependencyFlags extra_flags = vk::DependencyFlags( 0 ) );
friend class RenderPassBuilder;
private:
vk::SubpassDescription description() const;
std::vector< vk::SubpassDependency > dependencies() { return m_dependencies; }
};
struct AttachmentInfo
{
std::size_t m_index;
RenderPassBuilder& m_builder;
#ifndef NDEBUG
bool set_ops { false };
bool set_layout { false };
bool set_format { false };
#endif
AttachmentInfo( RenderPassBuilder& builder, std::size_t index );
void setFormat( vk::Format format );
void setLayouts( vk::ImageLayout image_layout, vk::ImageLayout final_layout );
void setOps( vk::AttachmentLoadOp load_op, vk::AttachmentStoreOp store_op );
#ifndef NDEBUG
~AttachmentInfo()
{
assert( set_ops );
assert( set_layout );
assert( set_format );
}
#endif
};
class RenderPassBuilder
{
std::vector< std::unique_ptr< SubpassBuilder > > m_subpasses {};
std::vector< vk::AttachmentDescription > m_attachment_descriptions {};
public:
SubpassBuilder& createSubpass( std::uint32_t index );
SubpassBuilder& subpass( std::size_t index ) const;
void setAttachmentCount( std::size_t count );
void setFormat( std::size_t index, vk::Format format );
void setInitalLayout( std::size_t index, vk::ImageLayout layout );
void setFinalLayout( std::size_t index, vk::ImageLayout layout );
void setOps( std::size_t index, vk::AttachmentLoadOp load_op, vk::AttachmentStoreOp store_op );
void setLayouts( std::size_t index, vk::ImageLayout inital_layout, vk::ImageLayout final_layout );
vk::raii::RenderPass create();
AttachmentInfo attachment( std::size_t index );
};
class RenderPass
{
vk::raii::RenderPass m_renderpass;
std::vector< vk::AttachmentDescription >& getAttachmentDescriptions();
std::vector< vk::SubpassDescription >& getSubpassDescriptions();
std::vector< vk::SubpassDependency >& getSubpassDependencies();
vk::raii::RenderPass createRenderpass();
public:
RenderPass();
};
} // namespace fgl::engine::rendering

View File

@@ -1,27 +0,0 @@
//
// Created by kj16609 on 12/31/23.
//
#include "Device.hpp"
#include "RenderPassBuilder.hpp"
namespace fgl::engine
{
vk::raii::RenderPass RenderPassBuilder::create()
{
auto& device { Device::getInstance() };
vk::RenderPassCreateInfo info;
info.attachmentCount = static_cast< std::uint32_t >( attachment_descriptions.size() );
info.pAttachments = attachment_descriptions.data();
info.subpassCount = static_cast< std::uint32_t >( subpass_descriptions.size() );
info.pSubpasses = subpass_descriptions.data();
info.dependencyCount = static_cast< std::uint32_t >( dependencies.size() );
info.pDependencies = dependencies.data();
return device->createRenderPass( info );
}
} // namespace fgl::engine

View File

@@ -1,52 +0,0 @@
//
// Created by kj16609 on 12/30/23.
//
#pragma once
#include "Subpass.hpp"
#include "engine/image/ImageView.hpp"
namespace fgl::engine
{
class RenderPassBuilder
{
std::vector< vk::AttachmentDescription > attachment_descriptions {};
std::vector< vk::ClearValue > m_clear_values {};
std::vector< vk::SubpassDescription > subpass_descriptions {};
std::vector< vk::SubpassDependency > dependencies {};
public:
template < typename SubpassT >
requires is_subpass< SubpassT >
void registerSubpass( SubpassT& subpass )
{
subpass_descriptions.emplace_back( subpass.description() );
for ( auto& dependency : subpass.dependencies )
{
dependencies.push_back( dependency );
}
}
template < is_attachment... Attachments >
void registerAttachments( Attachments&... attachments )
{
static_assert(
sizeof...( Attachments ) == maxIndex< Attachments... >() + 1,
"There must be no empty attachment indicies when creating a render pass" );
attachment_descriptions.resize( sizeof...( Attachments ) );
m_clear_values.resize( sizeof...( Attachments ) );
( ( attachment_descriptions[ attachments.m_index ] = attachments.desc() ), ... );
( ( m_clear_values[ attachments.m_index ] = attachments.m_clear_value ), ... );
}
vk::raii::RenderPass create();
};
} // namespace fgl::engine

View File

@@ -159,16 +159,16 @@ namespace fgl::engine
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
std::vector< vk::Viewport > viewports { viewport };
const std::vector< vk::Viewport > viewports { viewport };
buffer.setViewport( 0, viewports );
}
void Renderer::setScissor( const vk::raii::CommandBuffer& buffer )
{
vk::Rect2D scissor { { 0, 0 }, m_swapchain->getSwapChainExtent() };
const vk::Rect2D scissor { { 0, 0 }, m_swapchain->getSwapChainExtent() };
std::vector< vk::Rect2D > scissors { scissor };
const std::vector< vk::Rect2D > scissors { scissor };
buffer.setScissor( 0, scissors );
}
@@ -177,15 +177,13 @@ namespace fgl::engine
{
assert( is_frame_started && "Cannot call beginSwapChainRenderPass if frame is not in progress" );
std::vector< vk::ClearValue > clear_values { m_swapchain->getClearValues() };
vk::RenderPassBeginInfo render_pass_info {};
render_pass_info.pNext = VK_NULL_HANDLE;
render_pass_info.renderPass = m_swapchain->getRenderPass();
render_pass_info.framebuffer = m_swapchain->getFrameBuffer( current_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();
render_pass_info.setClearValues( m_swapchain->getClearValues() );
buffer.beginRenderPass( render_pass_info, vk::SubpassContents::eInline );

View File

@@ -11,7 +11,6 @@
#include "Device.hpp"
#include "SwapChain.hpp"
#include "engine/Window.hpp"
//clang-format: off
#include <tracy/TracyVulkan.hpp>
@@ -41,16 +40,6 @@ namespace fgl::engine
public:
descriptors::DescriptorSet& getGBufferDescriptor( std::uint16_t frame_idx ) const
{
return m_swapchain->getGBufferDescriptor( frame_idx );
}
descriptors::DescriptorSet& getGBufferCompositeDescriptor( std::uint16_t frame_idx ) const
{
return m_swapchain->getGBufferCompositeDescriptor( frame_idx );
}
FrameIndex getFrameIndex() const
{
assert( is_frame_started && "Cannot get frame index while frame not in progress" );

View File

@@ -8,14 +8,13 @@
#include <stdexcept>
#include "Attachment.hpp"
#include "RenderPassBuilder.hpp"
#include "RenderPass.hpp"
#include "Subpass.hpp"
#include "engine/assets/TransferManager.hpp"
#include "engine/descriptors/DescriptorSet.hpp"
namespace fgl::engine
{
SwapChain::SwapChain( const vk::Extent2D extent, PhysicalDevice& phy_device ) :
m_phy_device( phy_device ),
m_swapchain_details( Device::getInstance().getSwapChainSupport() ),
@@ -30,15 +29,9 @@ namespace fgl::engine
render_attachments( getSwapChainImageFormat(), findDepthFormat() ),
m_render_pass( createRenderPass() ),
m_swap_chain_buffers( createFramebuffers() ),
m_clear_values( gatherClearValues(
render_attachments.color,
render_attachments.depth,
gbuffer.position,
gbuffer.normal,
gbuffer.albedo,
gbuffer.composite ) ),
m_gbuffer_descriptor_set( createGBufferDescriptors() ),
m_composite_descriptor_set( createCompositeDescriptors() )
m_input_descriptors( createInputDescriptors() ),
m_clear_values(
gatherClearValues( render_attachments.color, render_attachments.depth, render_attachments.input_color ) )
{
init();
}
@@ -57,23 +50,41 @@ namespace fgl::engine
render_attachments( getSwapChainImageFormat(), findDepthFormat() ),
m_render_pass( createRenderPass() ),
m_swap_chain_buffers( createFramebuffers() ),
m_clear_values( gatherClearValues(
render_attachments.color,
render_attachments.depth,
gbuffer.position,
gbuffer.normal,
gbuffer.albedo,
gbuffer.composite ) ),
m_gbuffer_descriptor_set( createGBufferDescriptors() ),
m_composite_descriptor_set( createCompositeDescriptors() )
m_input_descriptors( createInputDescriptors() ),
m_clear_values(
gatherClearValues( render_attachments.color, render_attachments.depth, render_attachments.input_color ) )
{
init();
old_swap_chain.reset();
}
std::vector< std::unique_ptr< descriptors::DescriptorSet > > SwapChain::createInputDescriptors()
{
std::vector< std::unique_ptr< descriptors::DescriptorSet > > data {};
data.resize( imageCount() );
for ( PresentIndex i = 0; i < imageCount(); ++i )
{
auto set { std::make_unique< descriptors::DescriptorSet >( GuiInputDescriptorSet::createLayout() ) };
set->setMaxIDX( 0 );
set->bindAttachment(
0, render_attachments.input_color.getView( i ), vk::ImageLayout::eShaderReadOnlyOptimal );
set->update();
data[ i ] = std::move( set );
}
return data;
}
void SwapChain::init()
{
createSyncObjects();
render_attachments.input_color.setName( "Input Color" );
}
std::pair< vk::Result, PresentIndex > SwapChain::acquireNextImage()
@@ -228,101 +239,45 @@ namespace fgl::engine
ZoneScoped;
//Present attachment
render_pass_builder.registerAttachments(
render_attachments.color,
render_attachments.depth,
gbuffer.position,
gbuffer.normal,
gbuffer.albedo,
gbuffer.composite );
rendering::RenderPassBuilder builder;
Subpass<
vk::PipelineBindPoint::eGraphics,
UsedAttachment< DepthAttachment< 1 >, vk::ImageLayout::eDepthStencilAttachmentOptimal >,
UsedAttachment< ColorAttachment< 2 >, vk::ImageLayout::eColorAttachmentOptimal >,
UsedAttachment< ColorAttachment< 3 >, vk::ImageLayout::eColorAttachmentOptimal >,
UsedAttachment< ColorAttachment< 4 >, vk::ImageLayout::eColorAttachmentOptimal > >
g_buffer_subpass { 0 };
constexpr std::size_t ColorIndex { 0 };
constexpr std::size_t DepthIndex { 1 };
constexpr std::size_t InputColorIndex { 2 };
g_buffer_subpass.registerDependencyFromExternal(
builder.setAttachmentCount( 3 );
auto color { builder.attachment( ColorIndex ) };
color.setFormat( SwapChain::getSwapChainImageFormat() );
color.setLayouts( vk::ImageLayout::eUndefined, vk::ImageLayout::ePresentSrcKHR );
color.setOps( vk::AttachmentLoadOp::eClear, vk::AttachmentStoreOp::eStore );
auto depth { builder.attachment( DepthIndex ) };
depth.setFormat( SwapChain::findDepthFormat() );
depth.setLayouts( vk::ImageLayout::eUndefined, vk::ImageLayout::eDepthStencilAttachmentOptimal );
depth.setOps( vk::AttachmentLoadOp::eClear, vk::AttachmentStoreOp::eDontCare );
auto color_input { builder.attachment( InputColorIndex ) };
color_input.setFormat( vk::Format::eR8G8B8A8Unorm );
color_input.setLayouts( vk::ImageLayout::eShaderReadOnlyOptimal, vk::ImageLayout::eShaderReadOnlyOptimal );
color_input.setOps( vk::AttachmentLoadOp::eLoad, vk::AttachmentStoreOp::eDontCare );
auto& gui_subpass { builder.createSubpass( 0 ) };
gui_subpass.addInputLayout( InputColorIndex, vk::ImageLayout::eShaderReadOnlyOptimal );
gui_subpass.setDepthLayout( DepthIndex, vk::ImageLayout::eDepthStencilAttachmentOptimal );
gui_subpass.addRenderLayout( ColorIndex, vk::ImageLayout::eColorAttachmentOptimal );
gui_subpass.addDependencyFromExternal(
vk::AccessFlagBits::eDepthStencilAttachmentWrite,
vk::PipelineStageFlagBits::eEarlyFragmentTests | vk::PipelineStageFlagBits::eLateFragmentTests );
g_buffer_subpass.registerDependencyFromExternal(
gui_subpass.addDependencyFromExternal(
vk::AccessFlagBits::eColorAttachmentWrite, vk::PipelineStageFlagBits::eColorAttachmentOutput );
Subpass<
vk::PipelineBindPoint::eGraphics,
UsedAttachment< ColorAttachment< 5 >, vk::ImageLayout::eColorAttachmentOptimal >,
InputAttachment< ColorAttachment< 2 >, vk::ImageLayout::eShaderReadOnlyOptimal >,
InputAttachment< ColorAttachment< 3 >, vk::ImageLayout::eShaderReadOnlyOptimal >,
InputAttachment< ColorAttachment< 4 >, vk::ImageLayout::eShaderReadOnlyOptimal > >
composite_subpass { 1 };
composite_subpass.registerDependencyFromExternal(
vk::AccessFlagBits::eColorAttachmentWrite, vk::PipelineStageFlagBits::eColorAttachmentOutput );
// For color attachments
composite_subpass.registerDependencyFrom(
g_buffer_subpass,
vk::AccessFlagBits::eColorAttachmentWrite,
vk::PipelineStageFlagBits::eColorAttachmentOutput,
vk::AccessFlagBits::eInputAttachmentRead,
vk::PipelineStageFlagBits::eFragmentShader,
vk::DependencyFlagBits::eByRegion );
composite_subpass.registerDependencyToExternal(
vk::AccessFlagBits::eColorAttachmentWrite,
vk::PipelineStageFlagBits::eColorAttachmentOutput,
vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eInputAttachmentRead,
vk::PipelineStageFlagBits::eFragmentShader );
// To prevent the composite buffer from getting obliterated by the gui pass and so we can use it to render to the GUI in certian areas, We need to keep them seperate and the composite image to be unmodified.
Subpass<
vk::PipelineBindPoint::eGraphics,
UsedAttachment< DepthAttachment< 1 >, vk::ImageLayout::eDepthStencilAttachmentOptimal >,
UsedAttachment< ColoredPresentAttachment< 0 >, vk::ImageLayout::eColorAttachmentOptimal >,
InputAttachment< ColorAttachment< 5 >, vk::ImageLayout::eShaderReadOnlyOptimal > >
gui_subpass { 2 };
gui_subpass.registerFullDependency( composite_subpass );
// For depth attachment
gui_subpass.registerDependencyFrom(
g_buffer_subpass,
vk::AccessFlagBits::eDepthStencilAttachmentWrite,
vk::PipelineStageFlagBits::eEarlyFragmentTests | vk::PipelineStageFlagBits::eLateFragmentTests,
vk::AccessFlagBits::eDepthStencilAttachmentRead | vk::AccessFlagBits::eDepthStencilAttachmentWrite,
vk::PipelineStageFlagBits::eEarlyFragmentTests | vk::PipelineStageFlagBits::eLateFragmentTests,
vk::DependencyFlagBits::eByRegion );
gui_subpass.registerDependencyFromExternal(
vk::AccessFlagBits::eColorAttachmentWrite, vk::PipelineStageFlagBits::eColorAttachmentOutput );
gui_subpass.registerDependencyFrom(
composite_subpass,
vk::AccessFlagBits::eColorAttachmentWrite,
vk::PipelineStageFlagBits::eColorAttachmentOutput,
vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eInputAttachmentRead,
vk::PipelineStageFlagBits::eFragmentShader,
vk::DependencyFlagBits::eByRegion );
gui_subpass.registerDependencyFrom(
composite_subpass,
vk::AccessFlagBits::eColorAttachmentWrite,
vk::PipelineStageFlagBits::eColorAttachmentOutput,
vk::AccessFlagBits::eColorAttachmentWrite | vk::AccessFlagBits::eColorAttachmentRead,
vk::PipelineStageFlagBits::eColorAttachmentOutput,
vk::DependencyFlagBits::eByRegion );
gui_subpass.registerDependencyToExternal(
vk::AccessFlagBits::eColorAttachmentWrite, vk::PipelineStageFlagBits::eColorAttachmentOutput );
render_pass_builder.registerSubpass( g_buffer_subpass );
render_pass_builder.registerSubpass( composite_subpass );
render_pass_builder.registerSubpass( gui_subpass );
return render_pass_builder.create();
return builder.create();
}
std::vector< vk::raii::Framebuffer > SwapChain::createFramebuffers()
@@ -334,33 +289,8 @@ namespace fgl::engine
render_attachments.depth.createResources( imageCount(), getSwapChainExtent() );
render_attachments.depth.setClear( vk::ClearDepthStencilValue( 1.0f, 0 ) );
gbuffer.position.createResourceSpread( imageCount(), getSwapChainExtent(), vk::ImageUsageFlagBits::eSampled );
gbuffer.position.setClear( vk::ClearColorValue( std::array< float, 4 > { { 0.0f, 0.0f, 0.0f, 0.0f } } ) );
gbuffer.normal.createResourceSpread( imageCount(), getSwapChainExtent(), vk::ImageUsageFlagBits::eSampled );
gbuffer.normal.setClear( vk::ClearColorValue( std::array< float, 4 > { { 0.0f, 0.0f, 0.0f, 0.0f } } ) );
gbuffer.albedo.createResourceSpread( imageCount(), getSwapChainExtent(), vk::ImageUsageFlagBits::eSampled );
gbuffer.albedo.setClear( vk::ClearColorValue( std::array< float, 4 > { { 0.0f, 0.0f, 0.0f, 0.0f } } ) );
gbuffer.composite.createResourceSpread( imageCount(), getSwapChainExtent(), vk::ImageUsageFlagBits::eSampled );
gbuffer.composite.setClear( vk::ClearColorValue( std::array< float, 4 > { { 0.0f, 0.0f, 0.0f, 0.0f } } ) );
for ( PresentIndex i = 0; i < imageCount(); ++i )
{
g_buffer_position_img.emplace_back( std::make_unique< Texture >( gbuffer.position.m_attachment_resources
.m_images[ i ]
->setName( "GBufferPosition" ) ) );
g_buffer_normal_img.emplace_back( std::make_unique< Texture >( gbuffer.normal.m_attachment_resources
.m_images[ i ]
->setName( "GBufferNormal" ) ) );
g_buffer_albedo_img.emplace_back( std::make_unique< Texture >( gbuffer.albedo.m_attachment_resources
.m_images[ i ]
->setName( "GBufferAlbedo" ) ) );
g_buffer_composite_img.emplace_back( std::make_unique< Texture >( gbuffer.composite.m_attachment_resources
.m_images[ i ]
->setName( "GBufferComposite" ) ) );
}
render_attachments.input_color
.createResources( imageCount(), getSwapChainExtent(), vk::ImageUsageFlagBits::eTransferDst );
std::vector< vk::raii::Framebuffer > framebuffers {};
@@ -369,13 +299,7 @@ namespace fgl::engine
for ( uint8_t i = 0; i < imageCount(); i++ )
{
std::vector< vk::ImageView > attachments { getViewsForFrame(
i,
render_attachments.color,
render_attachments.depth,
gbuffer.position,
gbuffer.normal,
gbuffer.albedo,
gbuffer.composite ) };
i, render_attachments.color, render_attachments.depth, render_attachments.input_color ) };
//Fill attachments for this frame
const vk::Extent2D swapChainExtent { getSwapChainExtent() };
@@ -494,51 +418,31 @@ namespace fgl::engine
}
}
std::vector< std::unique_ptr< descriptors::DescriptorSet > > SwapChain::createGBufferDescriptors()
descriptors::DescriptorSet& SwapChain::getInputDescriptor( const PresentIndex present_index )
{
std::vector< std::unique_ptr< descriptors::DescriptorSet > > data;
data.resize( imageCount() );
for ( PresentIndex i = 0; i < imageCount(); ++i )
{
auto set { std::make_unique< descriptors::DescriptorSet >( GBufferDescriptorSet::createLayout() ) };
set->setMaxIDX( 2 );
set->bindAttachment( 0, gbuffer.position.getView( i ), vk::ImageLayout::eShaderReadOnlyOptimal );
set->bindAttachment( 1, gbuffer.normal.getView( i ), vk::ImageLayout::eShaderReadOnlyOptimal );
set->bindAttachment( 2, gbuffer.albedo.getView( i ), vk::ImageLayout::eShaderReadOnlyOptimal );
set->update();
data[ i ] = std::move( set );
}
return data;
assert( present_index < m_input_descriptors.size() );
return *m_input_descriptors[ present_index ];
}
std::vector< std::unique_ptr< descriptors::DescriptorSet > > SwapChain::createCompositeDescriptors()
Image& SwapChain::getInputImage( const PresentIndex present_index ) const
{
std::vector< std::unique_ptr< descriptors::DescriptorSet > > data;
data.resize( imageCount() );
return *render_attachments.input_color.m_attachment_resources.m_images[ present_index ];
}
for ( PresentIndex i = 0; i < imageCount(); ++i )
{
auto composite_set {
std::make_unique< descriptors::DescriptorSet >( GBufferCompositeDescriptorSet::createLayout() )
};
vk::raii::Framebuffer& SwapChain::getFrameBuffer( const PresentIndex present_index )
{
return m_swap_chain_buffers[ static_cast< std::size_t >( present_index ) ];
}
composite_set->setMaxIDX( 1 );
composite_set->bindAttachment( 0, gbuffer.composite.getView( i ), vk::ImageLayout::eShaderReadOnlyOptimal );
bool SwapChain::compareSwapFormats( const SwapChain& other ) const
{
return m_swap_chain_depth_format == other.m_swap_chain_depth_format
&& m_swap_chain_format == other.m_swap_chain_format;
}
composite_set->update();
data[ i ] = std::move( composite_set );
}
return data;
float SwapChain::extentAspectRatio() const
{
return static_cast< float >( m_swapchain_extent.width ) / static_cast< float >( m_swapchain_extent.height );
}
vk::Format SwapChain::findDepthFormat()

View File

@@ -3,8 +3,8 @@
#include <memory>
#include <vector>
#include "Attachment.hpp"
#include "Device.hpp"
#include "RenderPassBuilder.hpp"
#include "engine/FrameInfo.hpp"
#include "engine/texture/Texture.hpp"
#include "types.hpp"
@@ -15,7 +15,7 @@ namespace fgl::engine
{
public:
static constexpr std::uint16_t MAX_FRAMES_IN_FLIGHT { 2 };
static constexpr FrameIndex MAX_FRAMES_IN_FLIGHT { 2 };
private:
@@ -38,48 +38,30 @@ namespace fgl::engine
{
ColoredPresentAttachment< 0 > color;
DepthAttachment< 1 > depth;
InputColorAttachment< 2 > input_color { vk::Format::eR8G8B8A8Unorm };
} render_attachments;
struct
{
ColorAttachment< 2 > position { vk::Format::eR16G16B16A16Sfloat };
ColorAttachment< 3 > normal { vk::Format::eR16G16B16A16Sfloat };
ColorAttachment< 4 > albedo { vk::Format::eR8G8B8A8Unorm };
ColorAttachment< 5 > composite { vk::Format::eR8G8B8A8Unorm };
} gbuffer {};
public:
std::vector< std::unique_ptr< Texture > > g_buffer_position_img {};
std::vector< std::unique_ptr< Texture > > g_buffer_normal_img {};
std::vector< std::unique_ptr< Texture > > g_buffer_albedo_img {};
std::vector< std::unique_ptr< Texture > > g_buffer_composite_img {};
private:
RenderPassBuilder render_pass_builder {};
vk::raii::RenderPass m_render_pass;
std::vector< vk::raii::Framebuffer > m_swap_chain_buffers;
std::vector< std::unique_ptr< descriptors::DescriptorSet > > m_input_descriptors {};
std::vector< vk::ClearValue > m_clear_values;
std::vector< std::unique_ptr< descriptors::DescriptorSet > > m_gbuffer_descriptor_set;
std::vector< std::unique_ptr< descriptors::DescriptorSet > > m_composite_descriptor_set;
std::vector< vk::raii::Semaphore > image_available_sem {};
std::vector< vk::raii::Semaphore > render_finished_sem {};
std::vector< vk::raii::Fence > in_flight_fence {};
std::vector< vk::Fence > images_in_flight {};
size_t m_current_frame_index { 0 };
FrameIndex m_current_frame_index { 0 };
void init();
[[nodiscard]] vk::raii::SwapchainKHR createSwapChain();
[[nodiscard]] std::vector< Image > createSwapchainImages();
[[nodiscard]] vk::raii::RenderPass createRenderPass();
[[nodiscard]] std::vector< vk::raii::Framebuffer > createFramebuffers();
[[nodiscard]] std::vector< std::unique_ptr< descriptors::DescriptorSet > > createInputDescriptors();
void createSyncObjects();
// Helper functions
@@ -88,37 +70,21 @@ namespace fgl::engine
static vk::PresentModeKHR chooseSwapPresentMode( const std::vector< vk::PresentModeKHR >& present_modes );
vk::Extent2D chooseSwapExtent( const vk::SurfaceCapabilitiesKHR& capabilities ) const;
std::vector< std::unique_ptr< descriptors::DescriptorSet > > createGBufferDescriptors();
std::vector< std::unique_ptr< descriptors::DescriptorSet > > createCompositeDescriptors();
public:
std::vector< vk::ClearValue > getClearValues() const { return m_clear_values; }
descriptors::DescriptorSet& getGBufferDescriptor( PresentIndex frame_idx ) const
{
assert( frame_idx < imageCount() && "Frame index out of range" );
assert( m_gbuffer_descriptor_set.size() > 0 && "GBuffer descriptor set not initialized" );
return *m_gbuffer_descriptor_set[ frame_idx ];
}
descriptors::DescriptorSet& getGBufferCompositeDescriptor( PresentIndex frame_idx ) const
{
assert( frame_idx < imageCount() && "Frame index out of range" );
assert( m_composite_descriptor_set.size() > 0 && "GBuffer descriptor set not initialized" );
return *m_composite_descriptor_set[ frame_idx ];
}
SwapChain( vk::Extent2D windowExtent, PhysicalDevice& phy_dev );
SwapChain( vk::Extent2D windowExtent, std::shared_ptr< SwapChain > previous );
SwapChain( const SwapChain& ) = delete;
SwapChain& operator=( const SwapChain& ) = delete;
vk::raii::Framebuffer& getFrameBuffer( const PresentIndex present_index )
{
return m_swap_chain_buffers[ static_cast< std::size_t >( present_index ) ];
}
descriptors::DescriptorSet& getInputDescriptor( const PresentIndex present_index );
Image& getInputImage( PresentIndex present_index ) const;
const std::vector< vk::ClearValue >& getClearValues() const { return m_clear_values; }
vk::raii::Framebuffer& getFrameBuffer( PresentIndex present_index );
vk::raii::RenderPass& getRenderPass() { return m_render_pass; }
@@ -132,16 +98,9 @@ namespace fgl::engine
uint32_t height() const { return m_swapchain_extent.height; }
bool compareSwapFormats( const SwapChain& other ) const
{
return m_swap_chain_depth_format == other.m_swap_chain_depth_format
&& m_swap_chain_format == other.m_swap_chain_format;
}
bool compareSwapFormats( const SwapChain& other ) const;
float extentAspectRatio() const
{
return static_cast< float >( m_swapchain_extent.width ) / static_cast< float >( m_swapchain_extent.height );
}
float extentAspectRatio() const;
static vk::Format findDepthFormat();

View File

@@ -31,7 +31,7 @@ namespace fgl::engine
m_composite_pipeline->bind( command_buffer );
m_composite_pipeline
->bindDescriptor( command_buffer, GBufferDescriptorSet::m_set_idx, info.gbuffer_descriptor_set );
->bindDescriptor( command_buffer, GBufferDescriptorSet::m_set_idx, info.getGBufferDescriptor() );
return info.command_buffer;
}

View File

@@ -15,7 +15,7 @@ namespace fgl::engine
{
static bool enable_culling { true };
static bool& isCullingEnabled()
[[maybe_unused]] static bool& isCullingEnabled()
{
return enable_culling;
}

View File

@@ -16,7 +16,7 @@ namespace fgl::engine
PipelineConfigInfo::addColorAttachmentConfig( info );
PipelineConfigInfo::disableVertexInput( info );
PipelineConfigInfo::disableCulling( info );
info.subpass = 2;
info.subpass = 0;
m_pipeline = std::make_unique< Pipeline >( device, std::move( info ) );
m_pipeline->setDebugName( "Gui Pipeline" );
@@ -26,12 +26,9 @@ namespace fgl::engine
{
auto& command_buffer { info.command_buffer };
command_buffer.nextSubpass( vk::SubpassContents::eInline );
m_pipeline->bind( command_buffer );
m_pipeline
->bindDescriptor( command_buffer, GBufferCompositeDescriptorSet::m_set_idx, info.gbuffer_composite_set );
m_pipeline->bindDescriptor( command_buffer, 0, info.gui_input_descriptor );
return command_buffer;
}

View File

@@ -19,7 +19,7 @@ namespace fgl::engine
class GuiSystem
{
// Attachment 0 will be the composited image
using CompositeDescriptorSets = descriptors::DescriptorSetCollection< GBufferCompositeDescriptorSet >;
using CompositeDescriptorSets = descriptors::DescriptorSetCollection< GuiInputDescriptorSet >;
using VertexShader = VertexShaderT< "shaders/fullscreen.vert.spv" >;
using FragmentShader = FragmentShaderT< "shaders/gui-compose.frag.spv" >;

View File

@@ -114,17 +114,21 @@ namespace fgl::engine
Texture::Texture( std::vector< std::byte >&& data, const vk::Extent2D extent, const vk::Format format ) :
m_texture_id( getNextID() ),
m_extent( extent ),
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_image_view( m_image->getView() ),
m_extent( extent )
{
memory::TransferManager::getInstance()
.copyToImage( std::forward< std::vector< std::byte > >( data ), *m_image );
#if ENABLE_IMGUI
createImGuiSet();
#endif
}
Texture::Texture( const std::filesystem::path& path, const vk::Format format ) :
@@ -161,13 +165,13 @@ namespace fgl::engine
void Texture::createImGuiSet()
{
#if ENABLE_IMGUI
if ( !this->ready() )
{
log::debug( "Unable to create ImGui set. Texture was not ready" );
return;
}
#if ENABLE_IMGUI
log::debug( "Created ImGui set for image ID {}", this->getID() );
if ( m_imgui_set != VK_NULL_HANDLE ) return;
@@ -181,6 +185,8 @@ namespace fgl::engine
VkSampler vk_sampler { *( view->getSampler() ) };
m_imgui_set = ImGui_ImplVulkan_AddTexture( vk_sampler, vk_view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL );
#else
FGL_UNREACHABLE();
#endif
}
@@ -193,6 +199,7 @@ namespace fgl::engine
Texture::Texture( Image& image, Sampler sampler ) :
m_texture_id( getNextID() ),
m_image(),
m_image_view( image.getView() ),
//TODO: Figure out how to get extents from images.
m_extent()

View File

@@ -62,24 +62,22 @@ namespace fgl::engine
[[nodiscard]] Texture( std::tuple< std::vector< std::byte >, int, int, vk::Format > );
//! Construct texture with a specific extent and data
[[nodiscard]]
Texture( std::vector< std::byte >&& data, const int x, const int y, const vk::Format texture_format );
[[nodiscard]] Texture( std::vector< std::byte >&& data, int x, int y, vk::Format texture_format );
//! Construct texture with a specific extent and data
[[nodiscard]]
Texture( std::vector< std::byte >&& data, const vk::Extent2D extent, const vk::Format texture_format );
[[nodiscard]] Texture( std::vector< std::byte >&& data, vk::Extent2D extent, vk::Format texture_format );
//! Construct with a specific format
[[nodiscard]] Texture( const std::filesystem::path& path, const vk::Format format );
[[nodiscard]] Texture( const std::filesystem::path& path, vk::Format format );
//! Construct with no format
[[nodiscard]] Texture( const std::filesystem::path& path );
public:
inline static UIDKeyT extractKey( const std::filesystem::path& path ) { return path; }
static UIDKeyT extractKey( const std::filesystem::path& path ) { return path; }
inline static UIDKeyT extractKey( const std::filesystem::path& path, [[maybe_unused]] const vk::Format format )
static UIDKeyT extractKey( const std::filesystem::path& path, [[maybe_unused]] const vk::Format format )
{
return path;
}

View File

@@ -11,7 +11,6 @@
#include "engine/debug/drawers.hpp"
#include "engine/model/Model.hpp"
#include "engine/primitives/Frustum.hpp"
#include "engine/tree/quadtree/QuadTree.hpp"
namespace fgl::engine
{
@@ -92,10 +91,10 @@ namespace fgl::engine
return;
}
default:
std::unreachable();
FGL_UNREACHABLE();
}
std::unreachable();
FGL_UNREACHABLE();
}
bool OctTreeNode::contains( const WorldCoordinate coord ) const
@@ -276,7 +275,7 @@ namespace fgl::engine
return nullptr;
}
std::unreachable();
FGL_UNREACHABLE();
}
auto OctTreeNode::getGameObjectItter( const GameObject::GameObjectID id )
@@ -416,7 +415,7 @@ namespace fgl::engine
}
}
std::unreachable();
FGL_UNREACHABLE();
}
*/
@@ -462,7 +461,7 @@ namespace fgl::engine
return counter;
}
std::unreachable();
FGL_UNREACHABLE();
}
} // namespace fgl::engine

View File

@@ -4,6 +4,7 @@
#pragma once
#include <memory>
#include <vector>
#include "engine/primitives/Scale.hpp"