diff --git a/src/engine/EngineContext.cpp b/src/engine/EngineContext.cpp index fb5984b..2f7cbc2 100644 --- a/src/engine/EngineContext.cpp +++ b/src/engine/EngineContext.cpp @@ -22,6 +22,7 @@ #include "engine/math/Average.hpp" #include "engine/math/literals/size.hpp" #include "memory/buffers/BufferHandle.hpp" +#include "systems/RenderGraph.hpp" namespace fgl::engine { @@ -105,6 +106,9 @@ namespace fgl::engine void EngineContext::renderFrame() { ZoneScoped; + + RenderGraph graph {}; + if ( auto command_buffers_o = m_renderer.beginFrame(); command_buffers_o.has_value() ) { const auto timer = debug::timing::push( "Render Frame" ); @@ -119,6 +123,7 @@ namespace fgl::engine FrameInfo frame_info { in_flight_idx, present_idx, m_delta_time, + graph, command_buffers, nullptr, // Camera m_camera_manager.getCameras(), diff --git a/src/engine/FGL_DEFINES.hpp b/src/engine/FGL_DEFINES.hpp index 3eade49..b4439c7 100644 --- a/src/engine/FGL_DEFINES.hpp +++ b/src/engine/FGL_DEFINES.hpp @@ -4,25 +4,37 @@ #pragma once -#define FGL_DELETE_DEFAULT_CTOR( ClassName ) ClassName() = delete; -#define FGL_DELETE_COPY_ASSIGN( ClassName ) ClassName& operator=( const ClassName& ) = delete; -#define FGL_DELETE_COPY_CTOR( ClassName ) ClassName( const ClassName& ) = delete; -#define FGL_DELETE_MOVE_ASSIGN( ClassName ) ClassName& operator=( ClassName&& ) = delete; -#define FGL_DELETE_MOVE_CTOR( ClassName ) ClassName( ClassName&& ) = delete; -#define FGL_DELETE_COPY( ClassName ) FGL_DELETE_COPY_CTOR( ClassName ) FGL_DELETE_COPY_ASSIGN( ClassName ) -#define FGL_DELETE_MOVE( ClassName ) FGL_DELETE_MOVE_CTOR( ClassName ) FGL_DELETE_MOVE_ASSIGN( ClassName ) +#define FGL_DELETE_DEFAULT_CTOR( ClassName ) ClassName() = delete +#define FGL_DELETE_COPY_ASSIGN( ClassName ) ClassName& operator=( const ClassName& ) = delete +#define FGL_DELETE_COPY_CTOR( ClassName ) ClassName( const ClassName& ) = delete +#define FGL_DELETE_MOVE_ASSIGN( ClassName ) ClassName& operator=( ClassName&& ) = delete +#define FGL_DELETE_MOVE_CTOR( ClassName ) ClassName( ClassName&& ) = delete +#define FGL_DELETE_COPY( ClassName ) \ + FGL_DELETE_COPY_CTOR( ClassName ); \ + FGL_DELETE_COPY_ASSIGN( ClassName ) +#define FGL_DELETE_MOVE( ClassName ) \ + FGL_DELETE_MOVE_CTOR( ClassName ); \ + FGL_DELETE_MOVE_ASSIGN( ClassName ) #define FGL_DELETE_ALL_RO5( ClassName ) \ - FGL_DELETE_DEFAULT_CTOR( ClassName ) FGL_DELETE_COPY( ClassName ) FGL_DELETE_MOVE( ClassName ) + FGL_DELETE_DEFAULT_CTOR( ClassName ); \ + FGL_DELETE_COPY( ClassName ); \ + FGL_DELETE_MOVE( ClassName ) -#define FGL_DEFAULT_DEFAULT_CTOR( ClassName ) ClassName() = default; -#define FGL_DEFAULT_COPY_ASSIGN( ClassName ) ClassName& operator=( const ClassName& ) = default; -#define FGL_DEFAULT_COPY_CTOR( ClassName ) [[nodiscard]] ClassName( const ClassName& ) = default; -#define FGL_DEFAULT_MOVE_ASSIGN( ClassName ) ClassName& operator=( ClassName&& ) = default; -#define FGL_DEFAULT_MOVE_CTOR( ClassName ) [[nodiscard]] ClassName( ClassName&& ) = default; -#define FGL_DEFAULT_COPY( ClassName ) FGL_DEFAULT_COPY_CTOR( ClassName ) FGL_DEFAULT_COPY_ASSIGN( ClassName ) -#define FGL_DEFAULT_MOVE( ClassName ) FGL_DEFAULT_MOVE_CTOR( ClassName ) FGL_DEFAULT_MOVE_ASSIGN( ClassName ) +#define FGL_DEFAULT_DEFAULT_CTOR( ClassName ) ClassName() = default +#define FGL_DEFAULT_COPY_ASSIGN( ClassName ) ClassName& operator=( const ClassName& ) = default +#define FGL_DEFAULT_COPY_CTOR( ClassName ) [[nodiscard]] ClassName( const ClassName& ) = default +#define FGL_DEFAULT_MOVE_ASSIGN( ClassName ) ClassName& operator=( ClassName&& ) = default +#define FGL_DEFAULT_MOVE_CTOR( ClassName ) [[nodiscard]] ClassName( ClassName&& ) = default +#define FGL_DEFAULT_COPY( ClassName ) \ + FGL_DEFAULT_COPY_CTOR( ClassName ); \ + FGL_DEFAULT_COPY_ASSIGN( ClassName ) +#define FGL_DEFAULT_MOVE( ClassName ) \ + FGL_DEFAULT_MOVE_CTOR( ClassName ); \ + FGL_DEFAULT_MOVE_ASSIGN( ClassName ) #define FGL_DEFAULT_ALL_RO5( ClassName ) \ - FGL_DEFAULT_DEFAULT_CTOR( ClassName ) FGL_DEFAULT_COPY( ClassName ) FGL_DEFAULT_MOVE( ClassName ) + FGL_DEFAULT_DEFAULT_CTOR( ClassName ); \ + FGL_DEFAULT_COPY( ClassName ); \ + FGL_DEFAULT_MOVE( ClassName ) #define FGL_PACKED __attribute__( ( packed ) ) #define FGL_PACKED_ALIGNED( al ) __attribute__( ( packed, aligned( al ) ) ) diff --git a/src/engine/FrameInfo.hpp b/src/engine/FrameInfo.hpp index 2203702..66996e1 100644 --- a/src/engine/FrameInfo.hpp +++ b/src/engine/FrameInfo.hpp @@ -21,6 +21,7 @@ namespace fgl::engine { + class RenderGraph; class CameraViewpoint; struct PrimitiveRenderInfo; struct PrimitiveInstanceInfo; @@ -79,6 +80,7 @@ namespace fgl::engine FrameIndex in_flight_idx; PresentIndex present_idx; DeltaTime delta_time; + RenderGraph& graph; CommandBuffers& command_buffer; diff --git a/src/engine/assets/image/Sampler.cpp b/src/engine/assets/image/Sampler.cpp index 3708808..d0c8866 100644 --- a/src/engine/assets/image/Sampler.cpp +++ b/src/engine/assets/image/Sampler.cpp @@ -56,6 +56,23 @@ namespace fgl::engine m_sampler( createSampler( min_filter, mag_filter, mipmap_mode, sampler_wrap_u, sampler_wrap_v, sampler_wrap_w ) ) {} + Sampler::Sampler( + const vk::Filter min_filter, + const vk::Filter mag_filter, + const vk::SamplerMipmapMode mipmap_mode, + const vk::SamplerAddressMode sampler_wrap_u, + const vk::SamplerAddressMode sampler_wrap_v ) : + Sampler( min_filter, mag_filter, mipmap_mode, sampler_wrap_u, sampler_wrap_v, sampler_wrap_v ) + {} + + Sampler::Sampler( + const vk::Filter min_filter, + const vk::Filter mag_filter, + const vk::SamplerMipmapMode mipmap_mode, + const vk::SamplerAddressMode sampler_wrap_u ) : + Sampler( min_filter, mag_filter, mipmap_mode, sampler_wrap_u, sampler_wrap_u, sampler_wrap_u ) + {} + namespace gl { vk::Filter filterToVk( const int value ) diff --git a/src/engine/assets/image/Sampler.hpp b/src/engine/assets/image/Sampler.hpp index b5e7956..69df2e2 100644 --- a/src/engine/assets/image/Sampler.hpp +++ b/src/engine/assets/image/Sampler.hpp @@ -18,7 +18,7 @@ namespace fgl::engine public: - FGL_DELETE_COPY( Sampler ) + FGL_DELETE_COPY( Sampler ); Sampler() : Sampler( @@ -36,22 +36,18 @@ namespace fgl::engine vk::SamplerAddressMode sampler_wrap_v, vk::SamplerAddressMode sampler_wrap_w ); - FGL_FORCE_INLINE_FLATTEN Sampler( - const vk::Filter min_filter, - const vk::Filter mag_filter, - const vk::SamplerMipmapMode mipmap_mode, - const vk::SamplerAddressMode sampler_wrap_u, - const vk::SamplerAddressMode sampler_wrap_v ) : - Sampler( min_filter, mag_filter, mipmap_mode, sampler_wrap_u, sampler_wrap_v, sampler_wrap_v ) - {} + Sampler( + vk::Filter min_filter, + vk::Filter mag_filter, + vk::SamplerMipmapMode mipmap_mode, + vk::SamplerAddressMode sampler_wrap_u, + vk::SamplerAddressMode sampler_wrap_v ); - FGL_FORCE_INLINE_FLATTEN Sampler( - const vk::Filter min_filter, - const vk::Filter mag_filter, - const vk::SamplerMipmapMode mipmap_mode, - const vk::SamplerAddressMode sampler_wrap_u ) : - Sampler( min_filter, mag_filter, mipmap_mode, sampler_wrap_u, sampler_wrap_u, sampler_wrap_u ) - {} + Sampler( + vk::Filter min_filter, + vk::Filter mag_filter, + vk::SamplerMipmapMode mipmap_mode, + vk::SamplerAddressMode sampler_wrap_u ); //TODO: This should be moved to favor a single sampler when possible, Making a duplicate sampler is not required. //TODO: Singleton diff --git a/src/engine/assets/model/ModelInstanceInfo.hpp b/src/engine/assets/model/ModelInstanceInfo.hpp index b219a94..d9be334 100644 --- a/src/engine/assets/model/ModelInstanceInfo.hpp +++ b/src/engine/assets/model/ModelInstanceInfo.hpp @@ -2,6 +2,7 @@ // Created by kj16609 on 4/5/25. // #pragma once +#include "constants.hpp" #include "memory/buffers/vector/IndexedVector.hpp" namespace fgl::engine diff --git a/src/engine/assets/transfer/TransferManager.hpp b/src/engine/assets/transfer/TransferManager.hpp index 749b691..736df16 100644 --- a/src/engine/assets/transfer/TransferManager.hpp +++ b/src/engine/assets/transfer/TransferManager.hpp @@ -14,6 +14,7 @@ namespace fgl::engine { + class CommandBuffer; class Image; class Device; diff --git a/src/engine/descriptors/DescriptorSet.hpp b/src/engine/descriptors/DescriptorSet.hpp index 2cb17d2..80c7cbd 100644 --- a/src/engine/descriptors/DescriptorSet.hpp +++ b/src/engine/descriptors/DescriptorSet.hpp @@ -5,6 +5,7 @@ #pragma once #include +#include #include diff --git a/src/engine/descriptors/DescriptorSetLayout.cpp b/src/engine/descriptors/DescriptorSetLayout.cpp index 3bb6193..a30a605 100644 --- a/src/engine/descriptors/DescriptorSetLayout.cpp +++ b/src/engine/descriptors/DescriptorSetLayout.cpp @@ -6,6 +6,7 @@ #include "DescriptorSet.hpp" #include "engine/debug/logging/logging.hpp" +#include "rendering/devices/Device.hpp" namespace fgl::engine::descriptors { diff --git a/src/engine/memory/buffers/BufferSuballocation.cpp b/src/engine/memory/buffers/BufferSuballocation.cpp index 53cb9de..d6372f8 100644 --- a/src/engine/memory/buffers/BufferSuballocation.cpp +++ b/src/engine/memory/buffers/BufferSuballocation.cpp @@ -8,6 +8,7 @@ #include "SuballocationView.hpp" #include "align.hpp" #include "engine/debug/logging/logging.hpp" +#include "rendering/devices/Device.hpp" namespace fgl::engine::memory { diff --git a/src/engine/memory/buffers/BufferSuballocation.hpp b/src/engine/memory/buffers/BufferSuballocation.hpp index 1f85816..ee1b200 100644 --- a/src/engine/memory/buffers/BufferSuballocation.hpp +++ b/src/engine/memory/buffers/BufferSuballocation.hpp @@ -6,7 +6,6 @@ #include "BufferSuballocationHandle.hpp" #include "debug/Track.hpp" -#include "engine/rendering/devices/Device.hpp" namespace fgl::engine::memory { diff --git a/src/engine/memory/buffers/UniqueFrameSuballocation.hpp b/src/engine/memory/buffers/UniqueFrameSuballocation.hpp index 35e9408..2cb5fb7 100644 --- a/src/engine/memory/buffers/UniqueFrameSuballocation.hpp +++ b/src/engine/memory/buffers/UniqueFrameSuballocation.hpp @@ -4,6 +4,7 @@ #pragma once +#include "constants.hpp" #include "engine/concepts/is_suballocation.hpp" namespace fgl::engine diff --git a/src/engine/rendering/pipelines/v2/Pipeline.cpp b/src/engine/rendering/pipelines/v2/Pipeline.cpp index 0c2a692..7b18963 100644 --- a/src/engine/rendering/pipelines/v2/Pipeline.cpp +++ b/src/engine/rendering/pipelines/v2/Pipeline.cpp @@ -8,6 +8,8 @@ #include "engine/debug/logging/logging.hpp" #include "engine/descriptors/DescriptorSet.hpp" #include "engine/flags.hpp" +#include "rendering/CommandBufferPool.hpp" +#include "rendering/devices/Device.hpp" namespace fgl::engine { diff --git a/src/engine/rendering/pipelines/v2/Pipeline.hpp b/src/engine/rendering/pipelines/v2/Pipeline.hpp index 1fd4969..d4bfed9 100644 --- a/src/engine/rendering/pipelines/v2/Pipeline.hpp +++ b/src/engine/rendering/pipelines/v2/Pipeline.hpp @@ -6,9 +6,9 @@ #include "PipelineBuilder.hpp" #include "engine/descriptors/DescriptorSet.hpp" +#include "rendering/CommandBufferPool.hpp" namespace fgl::engine - { namespace descriptors { diff --git a/src/engine/systems/RenderGraph.cpp b/src/engine/systems/RenderGraph.cpp new file mode 100644 index 0000000..f951ca1 --- /dev/null +++ b/src/engine/systems/RenderGraph.cpp @@ -0,0 +1,92 @@ +// +// Created by kj16609 on 10/2/25. +// +#include "RenderGraph.hpp" + +namespace fgl::engine +{ + + void RenderGraph::submitInfo( AttachmentInfo&& attachment_info ) + { + m_queue.emplace( attachment_info ); + // m_current->m_infos.emplace_back( std::forward< AttachmentInfo >( attachment_info ) ); + } + + void RenderGraph::transformAttachment( const AttachmentInfo& value, CommandBuffer& command_buffer ) + { + const auto& itter { m_attachment_state.find( value.m_name ) }; + + if ( itter == m_attachment_state.end() ) + throw std:: + runtime_error( std::format( "Failed to find an attachment state for attachment {}", value.m_name ) ); + + AttachmentState& state { itter->second }; + + const bool needs_layout_change { state.current_layout != value.m_layout }; + const bool dont_care_load { + value.m_loadOp != vk::AttachmentLoadOp::eDontCare + }; // We don't care about anything that happens to this attachment before this point + const bool clear_load { value.m_loadOp + == vk::AttachmentLoadOp::eClear }; // We need to clear this attachment before we use it + + vk::ImageMemoryBarrier barrier { + state.m_image->transitionTo( state.current_layout, value.m_layout, state.aspect_flags ) + }; + + m_image_barriers.emplace_back( barrier ); + } + + void RenderGraph::push() + { + // auto new_node { std::make_unique< Node >() }; + // auto& itter { m_current->m_children.emplace_back( std::move( new_node ) ) }; + // m_current = itter.get(); + } + + void RenderGraph::pop() + { + // m_current = m_current->m_parent; + } + + void RenderGraph::addAttachmentInput( const std::string& image_name, const vk::ImageLayout desired_layout ) + { + AttachmentInfo attachment_info { .m_name = image_name, + .m_layout = desired_layout, + .m_loadOp = vk::AttachmentLoadOp::eLoad, + .m_storeOp = vk::AttachmentStoreOp::eDontCare }; + + submitInfo( std::move( attachment_info ) ); + } + + void RenderGraph::addAttachmentOutput( const std::string& image_name, const vk::ImageLayout desired_layout ) + { + AttachmentInfo attachment_info { .m_name = image_name, + .m_layout = desired_layout, + .m_loadOp = vk::AttachmentLoadOp::eDontCare, + .m_storeOp = vk::AttachmentStoreOp::eStore }; + + submitInfo( std::move( attachment_info ) ); + } + + void RenderGraph::addAttachmentMutable( const std::string& image_name, const vk::ImageLayout desired_layout ) + { + AttachmentInfo attachment_info { .m_name = image_name, + .m_layout = desired_layout, + .m_loadOp = vk::AttachmentLoadOp::eLoad, + .m_storeOp = vk::AttachmentStoreOp::eStore }; + + submitInfo( std::move( attachment_info ) ); + } + + void RenderGraph::flush( const CommandBuffer& command_buffer ) + { + while ( !m_queue.empty() ) + { + auto itter = m_queue.back(); + m_queue.pop(); + + transformAttachment( itter, command_buffer ); + } + } + +} // namespace fgl::engine \ No newline at end of file diff --git a/src/engine/systems/RenderGraph.hpp b/src/engine/systems/RenderGraph.hpp new file mode 100644 index 0000000..19a7ca1 --- /dev/null +++ b/src/engine/systems/RenderGraph.hpp @@ -0,0 +1,90 @@ +// +// Created by kj16609 on 10/2/25. +// +#pragma once + +#include +#include +#include +#include + +#include "assets/model/Model.hpp" + +namespace vk +{ + enum class AttachmentStoreOp; + enum class AttachmentLoadOp; + enum class Format; +} // namespace vk + +namespace fgl::engine +{ + + using AttachmentImage = std::shared_ptr< Image >; + using AttachmentImageView = std::shared_ptr< ImageView >; + + struct AttachmentInfo + { + std::string m_name; + + //! The format we want to be in for this moment + vk::ImageLayout m_layout; + vk::AttachmentLoadOp m_loadOp; + vk::AttachmentStoreOp m_storeOp; + }; + + struct AttachmentState : AttachmentInfo + { + AttachmentImage m_image; + AttachmentImageView m_view; + + vk::ImageLayout current_layout; + + vk::ImageAspectFlags aspect_flags; + }; + + class RenderGraph + { + struct Node + { + using Variant = std::variant< AttachmentInfo >; + Node* m_parent { nullptr }; + std::vector< std::unique_ptr< Node > > m_children {}; + + std::vector< Variant > m_infos {}; + }; + + std::unordered_map< std::string, AttachmentState > m_attachment_state {}; + + std::queue< AttachmentInfo > m_queue {}; + + std::vector< vk::ImageMemoryBarrier > m_image_barriers {}; + std::vector< vk::BufferMemoryBarrier > m_buffer_barriers {}; + + // //TODO: Allocator + // std::unique_ptr< Node > m_root {}; + // Node* m_current {}; + + void submitInfo( AttachmentInfo&& attachment_info ); + + void transformAttachment( const AttachmentInfo& value, CommandBuffer& command_buffer ); + + public: + + friend class RenderGraph; + + void push(); + void pop(); + + void addAttachmentInput( const std::string& image_name, vk::ImageLayout desired_layout ); + void addAttachmentOutput( const std::string& image_name, vk::ImageLayout desired_layout ); + + //! Adds an attachment that will be used as an input and output + void addAttachmentMutable( const std::string& image_name, vk::ImageLayout desired_layout ); + + void registerBuffer( const std::string& str, const memory::BufferSuballocation& value ); + void addBufferDependency( std::string buffer_name ); + void flush( const CommandBuffer& command_buffer ); + }; + +} // namespace fgl::engine \ No newline at end of file diff --git a/src/engine/systems/render/EntityRendererSystem.cpp b/src/engine/systems/render/EntityRendererSystem.cpp index 0f2d5bf..5887a6f 100644 --- a/src/engine/systems/render/EntityRendererSystem.cpp +++ b/src/engine/systems/render/EntityRendererSystem.cpp @@ -13,6 +13,7 @@ #include "debug/timing/FlameGraph.hpp" #include "rendering/pipelines/v2/Pipeline.hpp" #include "rendering/pipelines/v2/PipelineBuilder.hpp" +#include "systems/RenderGraph.hpp" namespace fgl::engine { @@ -78,8 +79,24 @@ namespace fgl::engine auto& command_buffer { info.command_buffer.render_cb }; TracyVkZone( info.tracy_ctx, **command_buffer, "Render textured entities" ); + info.graph.addAttachmentOutput( "G_DEPTH", vk::ImageLayout::eDepthAttachmentOptimal ); + info.graph.addAttachmentOutput( "G_COLOR", vk::ImageLayout::eAttachmentOptimal ); + info.graph.addAttachmentOutput( "G_NORMAL", vk::ImageLayout::eAttachmentOptimal ); + info.graph.addAttachmentOutput( "G_POSITION", vk::ImageLayout::eAttachmentOptimal ); + info.graph.addAttachmentOutput( "G_EMISSIVE", vk::ImageLayout::eAttachmentOptimal ); + info.graph.addAttachmentOutput( "G_METALLIC", vk::ImageLayout::eAttachmentOptimal ); + + // info.graph.addBufferDependency( "VERTEX_BUFFER" ); + // info.graph.addBufferDependency( "INDEX_BUFFER" ); + + // info.graph.registerBuffer( "MODEL_INSTANCES", info.camera->m_generated_instance_info[ info.in_flight_idx ] ); + + // info.graph.addBufferDependency( "MODEL_INSTANCES" ); + // compute shader + info.graph.flush( command_buffer ); + m_textured_pipeline->bind( command_buffer ); m_textured_pipeline->bindDescriptor( command_buffer, info.getCameraDescriptor() ); @@ -89,8 +106,8 @@ namespace fgl::engine auto& model_buffers { getModelBuffers() }; const std::vector< vk::Buffer > vert_buffers { - model_buffers.m_vertex_buffer->getVkBuffer(), - info.camera->m_generated_instance_info[ info.in_flight_idx ].getVkBuffer(), + model_buffers.m_vertex_buffer->getVkBuffer(), // VERTEX_BUFFER + info.camera->m_generated_instance_info[ info.in_flight_idx ].getVkBuffer(), // MODEL_INSTANCES }; command_buffer->bindVertexBuffers(