diff --git a/src/engine/CMakeLists.txt b/src/engine/CMakeLists.txt index 15fe547..f631ce8 100644 --- a/src/engine/CMakeLists.txt +++ b/src/engine/CMakeLists.txt @@ -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) - + target_precompile_headers(FGLEngine PRIVATE - + - + - - - - - - -) + + + + + + + + + ) + +endif () target_compile_definitions(FGLEngine PUBLIC VULKAN_HPP_FLAGS_MASK_TYPE_AS_PUBLIC) diff --git a/src/engine/EngineContext.cpp b/src/engine/EngineContext.cpp index 513f8df..ca4f7b7 100644 --- a/src/engine/EngineContext.cpp +++ b/src/engine/EngineContext.cpp @@ -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 ); diff --git a/src/engine/EngineContext.hpp b/src/engine/EngineContext.hpp index 80a9400..32dfdf3 100644 --- a/src/engine/EngineContext.hpp +++ b/src/engine/EngineContext.hpp @@ -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(); diff --git a/src/engine/FGL_DEFINES.hpp b/src/engine/FGL_DEFINES.hpp index 4971fb0..3acae88 100644 --- a/src/engine/FGL_DEFINES.hpp +++ b/src/engine/FGL_DEFINES.hpp @@ -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 )]] \ No newline at end of file +#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 \ No newline at end of file diff --git a/src/engine/FrameInfo.cpp b/src/engine/FrameInfo.cpp new file mode 100644 index 0000000..c891b63 --- /dev/null +++ b/src/engine/FrameInfo.cpp @@ -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 diff --git a/src/engine/FrameInfo.hpp b/src/engine/FrameInfo.hpp index 89f9cde..c8dfbf1 100644 --- a/src/engine/FrameInfo.hpp +++ b/src/engine/FrameInfo.hpp @@ -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; diff --git a/src/engine/KeyboardMovementController.cpp b/src/engine/KeyboardMovementController.cpp index 3bb111c..825270c 100644 --- a/src/engine/KeyboardMovementController.cpp +++ b/src/engine/KeyboardMovementController.cpp @@ -4,8 +4,8 @@ #include "KeyboardMovementController.hpp" -#include -#include +#include + #include #include "engine/primitives/vectors/Vector.hpp" diff --git a/src/engine/Window.cpp b/src/engine/Window.cpp index fc3a62b..b11b1f2 100644 --- a/src/engine/Window.cpp +++ b/src/engine/Window.cpp @@ -5,10 +5,11 @@ #include "Window.hpp" #include +#include #include -#include "engine/rendering/Device.hpp" +#include "engine/rendering/Instance.hpp" namespace fgl::engine { diff --git a/src/engine/Window.hpp b/src/engine/Window.hpp index 028ec75..94c319f 100644 --- a/src/engine/Window.hpp +++ b/src/engine/Window.hpp @@ -6,6 +6,7 @@ #define GLFW_INCLUDE_VULKAN #include +#include #include #include diff --git a/src/engine/assets/TransferData.cpp b/src/engine/assets/TransferData.cpp index 0837a93..0280f97 100644 --- a/src/engine/assets/TransferData.cpp +++ b/src/engine/assets/TransferData.cpp @@ -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() diff --git a/src/engine/camera/Camera.cpp b/src/engine/camera/Camera.cpp index 35bc4e6..1328c74 100644 --- a/src/engine/camera/Camera.cpp +++ b/src/engine/camera/Camera.cpp @@ -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 > diff --git a/src/engine/camera/Camera.hpp b/src/engine/camera/Camera.hpp index fffd0f3..86490b2 100644 --- a/src/engine/camera/Camera.hpp +++ b/src/engine/camera/Camera.hpp @@ -12,6 +12,7 @@ #include #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 diff --git a/src/engine/camera/CameraRenderer.cpp b/src/engine/camera/CameraRenderer.cpp new file mode 100644 index 0000000..8cba055 --- /dev/null +++ b/src/engine/camera/CameraRenderer.cpp @@ -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 diff --git a/src/engine/camera/CameraRenderer.hpp b/src/engine/camera/CameraRenderer.hpp new file mode 100644 index 0000000..c1a5a65 --- /dev/null +++ b/src/engine/camera/CameraRenderer.hpp @@ -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 diff --git a/src/engine/camera/CameraSwapchain.cpp b/src/engine/camera/CameraSwapchain.cpp index 35d96e1..4a313ae 100644 --- a/src/engine/camera/CameraSwapchain.cpp +++ b/src/engine/camera/CameraSwapchain.cpp @@ -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 \ No newline at end of file diff --git a/src/engine/camera/CameraSwapchain.hpp b/src/engine/camera/CameraSwapchain.hpp index 6f8bf00..62d725c 100644 --- a/src/engine/camera/CameraSwapchain.hpp +++ b/src/engine/camera/CameraSwapchain.hpp @@ -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 \ No newline at end of file diff --git a/src/engine/constants.hpp b/src/engine/constants.hpp index eac3b5f..73d618e 100644 --- a/src/engine/constants.hpp +++ b/src/engine/constants.hpp @@ -4,8 +4,11 @@ #pragma once +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Weffc++" #include #include +#pragma GCC diagnostic pop namespace fgl::engine::constants { diff --git a/src/engine/debug/drawers.hpp b/src/engine/debug/drawers.hpp index 9919ca0..cfa0425 100644 --- a/src/engine/debug/drawers.hpp +++ b/src/engine/debug/drawers.hpp @@ -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 { diff --git a/src/engine/descriptors/DescriptorSet.hpp b/src/engine/descriptors/DescriptorSet.hpp index 33ce3ad..d0bb408 100644 --- a/src/engine/descriptors/DescriptorSet.hpp +++ b/src/engine/descriptors/DescriptorSet.hpp @@ -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 {}; diff --git a/src/engine/gameobjects/components/GameObjectComponentBase.hpp b/src/engine/gameobjects/components/GameObjectComponentBase.hpp index 47da177..d354a69 100644 --- a/src/engine/gameobjects/components/GameObjectComponentBase.hpp +++ b/src/engine/gameobjects/components/GameObjectComponentBase.hpp @@ -4,6 +4,9 @@ #pragma once +#include +#include + namespace fgl::engine { diff --git a/src/engine/gameobjects/components/ModelComponent.cpp b/src/engine/gameobjects/components/ModelComponent.cpp index 7d71e4d..86c98d1 100644 --- a/src/engine/gameobjects/components/ModelComponent.cpp +++ b/src/engine/gameobjects/components/ModelComponent.cpp @@ -4,7 +4,11 @@ #include "ModelComponent.hpp" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" +#pragma GCC diagnostic ignored "-Weffc++" #include +#pragma GCC diagnostic pop namespace fgl::engine { diff --git a/src/engine/gui/core.cpp b/src/engine/gui/core.cpp index 8a226a2..91941d9 100644 --- a/src/engine/gui/core.cpp +++ b/src/engine/gui/core.cpp @@ -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 = {}, diff --git a/src/engine/gui/preview.cpp b/src/engine/gui/preview.cpp index 4fa32ba..714e460 100644 --- a/src/engine/gui/preview.cpp +++ b/src/engine/gui/preview.cpp @@ -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; } diff --git a/src/engine/image/Image.cpp b/src/engine/image/Image.cpp index 31b1e27..ef91966 100644 --- a/src/engine/image/Image.cpp +++ b/src/engine/image/Image.cpp @@ -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 ); diff --git a/src/engine/image/Image.hpp b/src/engine/image/Image.hpp index ae059cc..933536a 100644 --- a/src/engine/image/Image.hpp +++ b/src/engine/image/Image.hpp @@ -7,7 +7,6 @@ #include #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(); }; diff --git a/src/engine/image/Sampler.cpp b/src/engine/image/Sampler.cpp index 66c813c..6acab85 100644 --- a/src/engine/image/Sampler.cpp +++ b/src/engine/image/Sampler.cpp @@ -64,7 +64,7 @@ namespace fgl::engine return vk::Filter::eLinear; } - std::unreachable(); + FGL_UNREACHABLE(); } vk::SamplerAddressMode wrappingToVk( const int val ) diff --git a/src/engine/math/noise/perlin/generator.cpp b/src/engine/math/noise/perlin/generator.cpp index 7c4a4b2..57b135a 100644 --- a/src/engine/math/noise/perlin/generator.cpp +++ b/src/engine/math/noise/perlin/generator.cpp @@ -4,7 +4,12 @@ #include "generator.hpp" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Weffc++" #include +#pragma GCC diagnostic pop + + #include #include diff --git a/src/engine/math/noise/perlin/generator.hpp b/src/engine/math/noise/perlin/generator.hpp index c8f25d7..b4ac981 100644 --- a/src/engine/math/noise/perlin/generator.hpp +++ b/src/engine/math/noise/perlin/generator.hpp @@ -4,7 +4,10 @@ #pragma once +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Weffc++" #include +#pragma GCC diagnostic pop #include diff --git a/src/engine/math/taitBryanMatrix.cpp b/src/engine/math/taitBryanMatrix.cpp index df7f443..61a054e 100644 --- a/src/engine/math/taitBryanMatrix.cpp +++ b/src/engine/math/taitBryanMatrix.cpp @@ -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 ) diff --git a/src/engine/math/taitBryanMatrix.hpp b/src/engine/math/taitBryanMatrix.hpp index 2086edd..8b93fe9 100644 --- a/src/engine/math/taitBryanMatrix.hpp +++ b/src/engine/math/taitBryanMatrix.hpp @@ -4,7 +4,10 @@ #pragma once +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Weffc++" #include +#pragma GCC diagnostic pop namespace fgl::engine { diff --git a/src/engine/model/Model.hpp b/src/engine/model/Model.hpp index 7f5f6d1..1029cdc 100644 --- a/src/engine/model/Model.hpp +++ b/src/engine/model/Model.hpp @@ -4,7 +4,11 @@ #pragma once +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Weffc++" +#pragma GCC diagnostic ignored "-Wduplicated-branches" #include +#pragma GCC diagnostic pop #include #include diff --git a/src/engine/model/Vertex.cpp b/src/engine/model/Vertex.cpp index 6023cca..747531c 100644 --- a/src/engine/model/Vertex.cpp +++ b/src/engine/model/Vertex.cpp @@ -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 #include +#pragma GCC diagnostic pop #include "Model.hpp" #include "engine/utils.hpp" diff --git a/src/engine/model/Vertex.hpp b/src/engine/model/Vertex.hpp index 5c44de3..859d4b2 100644 --- a/src/engine/model/Vertex.hpp +++ b/src/engine/model/Vertex.hpp @@ -4,8 +4,12 @@ #pragma once +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Weffc++" #include #include +#pragma GCC diagnostic pop + #include namespace fgl::engine diff --git a/src/engine/model/builders/SceneBuilder.cpp b/src/engine/model/builders/SceneBuilder.cpp index 314d7be..fdd3126 100644 --- a/src/engine/model/builders/SceneBuilder.cpp +++ b/src/engine/model/builders/SceneBuilder.cpp @@ -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; diff --git a/src/engine/model/builders/SceneBuilder.hpp b/src/engine/model/builders/SceneBuilder.hpp index 56e81b2..83a2ca9 100644 --- a/src/engine/model/builders/SceneBuilder.hpp +++ b/src/engine/model/builders/SceneBuilder.hpp @@ -4,8 +4,13 @@ #pragma once +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Weffc++" +#pragma GCC diagnostic ignored "-Wduplicated-branches" +#include #include #include +#pragma GCC diagnostic pop #include #include diff --git a/src/engine/model/builders/loadObj.cpp b/src/engine/model/builders/loadObj.cpp index 7226c79..d3a7bd3 100644 --- a/src/engine/model/builders/loadObj.cpp +++ b/src/engine/model/builders/loadObj.cpp @@ -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" ); diff --git a/src/engine/primitives/Frustum.hpp b/src/engine/primitives/Frustum.hpp index 5aeaa32..841a313 100644 --- a/src/engine/primitives/Frustum.hpp +++ b/src/engine/primitives/Frustum.hpp @@ -4,6 +4,8 @@ #pragma once +#include + #include "engine/primitives/lines/InfiniteLine.hpp" #include "engine/primitives/planes/OriginDistancePlane.hpp" #include "engine/primitives/planes/PointPlane.hpp" diff --git a/src/engine/primitives/Rotation.hpp b/src/engine/primitives/Rotation.hpp index fd6955a..e462ec2 100644 --- a/src/engine/primitives/Rotation.hpp +++ b/src/engine/primitives/Rotation.hpp @@ -6,6 +6,7 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Weffc++" +#pragma GCC diagnostic ignored "-Wduplicated-branches" #include #include #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 > diff --git a/src/engine/primitives/Scale.hpp b/src/engine/primitives/Scale.hpp index cc1b769..fab24ef 100644 --- a/src/engine/primitives/Scale.hpp +++ b/src/engine/primitives/Scale.hpp @@ -4,9 +4,25 @@ #pragma once +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Weffc++" +#include +#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 diff --git a/src/engine/primitives/lines/LineBase.cpp b/src/engine/primitives/lines/LineBase.cpp index b02ada0..89d64fe 100644 --- a/src/engine/primitives/lines/LineBase.cpp +++ b/src/engine/primitives/lines/LineBase.cpp @@ -4,7 +4,10 @@ #include "LineBase.hpp" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Weffc++" #include +#pragma GCC diagnostic push namespace fgl::engine { diff --git a/src/engine/primitives/lines/LineBase.hpp b/src/engine/primitives/lines/LineBase.hpp index ed6c195..b52e5bb 100644 --- a/src/engine/primitives/lines/LineBase.hpp +++ b/src/engine/primitives/lines/LineBase.hpp @@ -4,7 +4,10 @@ #pragma once +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Weffc++" #include +#pragma GCC diagnostic pop namespace fgl::engine { diff --git a/src/engine/primitives/matricies/RotationMatrix.hpp b/src/engine/primitives/matricies/RotationMatrix.hpp index 48bc117..90730ad 100644 --- a/src/engine/primitives/matricies/RotationMatrix.hpp +++ b/src/engine/primitives/matricies/RotationMatrix.hpp @@ -4,9 +4,10 @@ #pragma once -#include - -#include "MatrixEvolvedTypes.hpp" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Weffc++" +#include +#pragma GCC diagnostic pop namespace fgl::engine { diff --git a/src/engine/primitives/points/Coordinate.hpp b/src/engine/primitives/points/Coordinate.hpp index 6c58432..a713079 100644 --- a/src/engine/primitives/points/Coordinate.hpp +++ b/src/engine/primitives/points/Coordinate.hpp @@ -4,9 +4,11 @@ #pragma once +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Weffc++" +#pragma GCC diagnostic ignored "-Wduplicated-branches" #include - -#include +#pragma GCC diagnostic pop #include "engine/constants.hpp" #include "engine/primitives/CoordinateSpace.hpp" diff --git a/src/engine/primitives/vectors/NormalVector.hpp b/src/engine/primitives/vectors/NormalVector.hpp index 6f04233..0514ca8 100644 --- a/src/engine/primitives/vectors/NormalVector.hpp +++ b/src/engine/primitives/vectors/NormalVector.hpp @@ -4,8 +4,11 @@ #pragma once +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Weffc++" #include #include +#pragma GCC diagnostic pop #include "engine/primitives/CoordinateSpace.hpp" diff --git a/src/engine/primitives/vectors/Vector.hpp b/src/engine/primitives/vectors/Vector.hpp index d4d42c9..f47c2b5 100644 --- a/src/engine/primitives/vectors/Vector.hpp +++ b/src/engine/primitives/vectors/Vector.hpp @@ -4,7 +4,10 @@ #pragma once +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Weffc++" #include +#pragma GCC diagnostic pop #include "engine/FGL_DEFINES.hpp" #include "engine/constants.hpp" diff --git a/src/engine/rendering/Attachment.hpp b/src/engine/rendering/Attachment.hpp index e65d26d..43790b3 100644 --- a/src/engine/rendering/Attachment.hpp +++ b/src/engine/rendering/Attachment.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 diff --git a/src/engine/rendering/Device.cpp b/src/engine/rendering/Device.cpp index 70bb788..ddc771e 100644 --- a/src/engine/rendering/Device.cpp +++ b/src/engine/rendering/Device.cpp @@ -3,6 +3,8 @@ #include "engine/descriptors/DescriptorPool.hpp" // std headers +#include + #include #include #include diff --git a/src/engine/rendering/RenderPass.cpp b/src/engine/rendering/RenderPass.cpp new file mode 100644 index 0000000..a127539 --- /dev/null +++ b/src/engine/rendering/RenderPass.cpp @@ -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 diff --git a/src/engine/rendering/RenderPass.hpp b/src/engine/rendering/RenderPass.hpp new file mode 100644 index 0000000..67a56da --- /dev/null +++ b/src/engine/rendering/RenderPass.hpp @@ -0,0 +1,153 @@ +// +// Created by kj16609 on 7/21/24. +// + +#pragma once +#include +#include + +#include + +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 diff --git a/src/engine/rendering/RenderPassBuilder.cpp b/src/engine/rendering/RenderPassBuilder.cpp deleted file mode 100644 index f1cde4b..0000000 --- a/src/engine/rendering/RenderPassBuilder.cpp +++ /dev/null @@ -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 diff --git a/src/engine/rendering/RenderPassBuilder.hpp b/src/engine/rendering/RenderPassBuilder.hpp deleted file mode 100644 index 7e19299..0000000 --- a/src/engine/rendering/RenderPassBuilder.hpp +++ /dev/null @@ -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 \ No newline at end of file diff --git a/src/engine/rendering/Renderer.cpp b/src/engine/rendering/Renderer.cpp index 2ea778d..3380292 100644 --- a/src/engine/rendering/Renderer.cpp +++ b/src/engine/rendering/Renderer.cpp @@ -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 ); diff --git a/src/engine/rendering/Renderer.hpp b/src/engine/rendering/Renderer.hpp index 17c7217..3793d96 100644 --- a/src/engine/rendering/Renderer.hpp +++ b/src/engine/rendering/Renderer.hpp @@ -11,7 +11,6 @@ #include "Device.hpp" #include "SwapChain.hpp" -#include "engine/Window.hpp" //clang-format: off #include @@ -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" ); diff --git a/src/engine/rendering/SwapChain.cpp b/src/engine/rendering/SwapChain.cpp index 05ff5cf..b3296e9 100644 --- a/src/engine/rendering/SwapChain.cpp +++ b/src/engine/rendering/SwapChain.cpp @@ -8,14 +8,13 @@ #include #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() diff --git a/src/engine/rendering/SwapChain.hpp b/src/engine/rendering/SwapChain.hpp index 2004a2b..3ca2b28 100644 --- a/src/engine/rendering/SwapChain.hpp +++ b/src/engine/rendering/SwapChain.hpp @@ -3,8 +3,8 @@ #include #include +#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(); diff --git a/src/engine/systems/CompositionSystem.cpp b/src/engine/systems/CompositionSystem.cpp index 1ce34ed..34bb7fc 100644 --- a/src/engine/systems/CompositionSystem.cpp +++ b/src/engine/systems/CompositionSystem.cpp @@ -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; } diff --git a/src/engine/systems/CullingSystem.cpp b/src/engine/systems/CullingSystem.cpp index bd380bb..de80f7a 100644 --- a/src/engine/systems/CullingSystem.cpp +++ b/src/engine/systems/CullingSystem.cpp @@ -15,7 +15,7 @@ namespace fgl::engine { static bool enable_culling { true }; - static bool& isCullingEnabled() + [[maybe_unused]] static bool& isCullingEnabled() { return enable_culling; } diff --git a/src/engine/systems/GuiSystem.cpp b/src/engine/systems/GuiSystem.cpp index 256a6b0..0898d13 100644 --- a/src/engine/systems/GuiSystem.cpp +++ b/src/engine/systems/GuiSystem.cpp @@ -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; } diff --git a/src/engine/systems/GuiSystem.hpp b/src/engine/systems/GuiSystem.hpp index 1e0d1a3..e09c5ad 100644 --- a/src/engine/systems/GuiSystem.hpp +++ b/src/engine/systems/GuiSystem.hpp @@ -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" >; diff --git a/src/engine/texture/Texture.cpp b/src/engine/texture/Texture.cpp index 71d8614..babe74e 100644 --- a/src/engine/texture/Texture.cpp +++ b/src/engine/texture/Texture.cpp @@ -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() diff --git a/src/engine/texture/Texture.hpp b/src/engine/texture/Texture.hpp index ff6ea63..938ede6 100644 --- a/src/engine/texture/Texture.hpp +++ b/src/engine/texture/Texture.hpp @@ -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; } diff --git a/src/engine/tree/octtree/OctTreeNode.cpp b/src/engine/tree/octtree/OctTreeNode.cpp index 3f1c5ad..282ae5e 100644 --- a/src/engine/tree/octtree/OctTreeNode.cpp +++ b/src/engine/tree/octtree/OctTreeNode.cpp @@ -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 \ No newline at end of file diff --git a/src/engine/tree/quadtree/QuadTree.hpp b/src/engine/tree/quadtree/QuadTree.hpp index a9b0d05..03e030d 100644 --- a/src/engine/tree/quadtree/QuadTree.hpp +++ b/src/engine/tree/quadtree/QuadTree.hpp @@ -4,6 +4,7 @@ #pragma once +#include #include #include "engine/primitives/Scale.hpp"