Finally gets the camera renderpass working
This commit is contained in:
@@ -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)
|
||||
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
18
src/engine/FrameInfo.cpp
Normal 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
|
||||
@@ -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;
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
|
||||
#include "KeyboardMovementController.hpp"
|
||||
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <bits/chrono.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "engine/primitives/vectors/Vector.hpp"
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#define GLFW_INCLUDE_VULKAN
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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 >
|
||||
|
||||
@@ -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
|
||||
|
||||
154
src/engine/camera/CameraRenderer.cpp
Normal file
154
src/engine/camera/CameraRenderer.cpp
Normal 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
|
||||
48
src/engine/camera/CameraRenderer.hpp
Normal file
48
src/engine/camera/CameraRenderer.hpp
Normal 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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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 {};
|
||||
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string_view>
|
||||
|
||||
namespace fgl::engine
|
||||
{
|
||||
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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 = {},
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
@@ -64,7 +64,7 @@ namespace fgl::engine
|
||||
return vk::Filter::eLinear;
|
||||
}
|
||||
|
||||
std::unreachable();
|
||||
FGL_UNREACHABLE();
|
||||
}
|
||||
|
||||
vk::SamplerAddressMode wrappingToVk( const int val )
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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 )
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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" );
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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 >
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
#include "engine/descriptors/DescriptorPool.hpp"
|
||||
|
||||
// std headers
|
||||
#include <tracy/Tracy.hpp>
|
||||
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <set>
|
||||
|
||||
257
src/engine/rendering/RenderPass.cpp
Normal file
257
src/engine/rendering/RenderPass.cpp
Normal 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
|
||||
153
src/engine/rendering/RenderPass.hpp
Normal file
153
src/engine/rendering/RenderPass.hpp
Normal 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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 );
|
||||
|
||||
|
||||
@@ -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" );
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace fgl::engine
|
||||
{
|
||||
static bool enable_culling { true };
|
||||
|
||||
static bool& isCullingEnabled()
|
||||
[[maybe_unused]] static bool& isCullingEnabled()
|
||||
{
|
||||
return enable_culling;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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" >;
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "engine/primitives/Scale.hpp"
|
||||
|
||||
Reference in New Issue
Block a user