From 5295d9a1f36568f94d74c3ee361f28508b1919e1 Mon Sep 17 00:00:00 2001 From: kj16609 Date: Tue, 12 Mar 2024 22:10:02 -0400 Subject: [PATCH] Optimization --- CMakeLists.txt | 8 +- cmake_modules/dependencies/tracy.cmake | 1 + src/engine/EngineContext.cpp | 2 +- src/engine/FrameInfo.hpp | 2 + src/engine/primitives/Frustum.hpp | 9 +++ .../boxes/AxisAlignedBoundingBox.cpp | 35 +++++---- .../boxes/AxisAlignedBoundingBox.hpp | 4 +- src/engine/primitives/boxes/BoundingBox.hpp | 6 +- .../primitives/boxes/OrientedBoundingBox.cpp | 72 ++++++++++++----- .../primitives/boxes/OrientedBoundingBox.hpp | 4 +- src/engine/primitives/lines/LineSegment.hpp | 16 ++-- src/engine/rendering/Renderer.cpp | 20 +++-- src/engine/rendering/Renderer.hpp | 5 +- src/engine/systems/CullingSystem.cpp | 16 +++- src/engine/systems/CullingSystem.hpp | 5 ++ src/engine/systems/EntityRendererSystem.cpp | 4 +- src/engine/systems/concepts.hpp | 33 ++++++++ src/engine/tree/octtree/OctTreeNode.cpp | 77 ++++++------------- src/engine/tree/octtree/OctTreeNode.hpp | 61 ++++++++++++++- 19 files changed, 256 insertions(+), 124 deletions(-) create mode 100644 src/engine/systems/concepts.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d4268a1..0415223 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,22 +28,19 @@ message("-- FGL_FLAGS: ${FGL_FLAGS}") add_subdirectory(dependencies/vma) include(dependencies/glfw) include(dependencies/glm) -include(dependencies/tracy) +include(cmake_modules/dependencies/tracy.cmake) include(dependencies/vulkan) include(dependencies/catch2) add_subdirectory(src) add_subdirectory(tests) -file(GLOB FRAG_SHADERS "${CMAKE_CURRENT_SOURCE_DIR}/shaders/*.frag") -file(GLOB VERT_SHADERS "${CMAKE_CURRENT_SOURCE_DIR}/shaders/*.vert") file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/bin/shaders") file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/bin/models") file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/models" DESTINATION "${CMAKE_BINARY_DIR}/bin") - string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_UPPER_BUILD_TYPE) if (CMAKE_UPPER_BUILD_TYPE STREQUAL "DEBUG" OR CMAKE_UPPER_BUILD_TYPE STREQUAL "RELWITHDEBINFO") @@ -60,6 +57,9 @@ foreach (MODEL IN LISTS MODELS) list(APPEND OBJ_MODELS ${CMAKE_BINARY_DIR}/bin/models/${FILENAME}) endforeach () +file(GLOB FRAG_SHADERS "${CMAKE_CURRENT_SOURCE_DIR}/shaders/*.frag") +file(GLOB VERT_SHADERS "${CMAKE_CURRENT_SOURCE_DIR}/shaders/*.vert") + foreach (SHADER IN LISTS FRAG_SHADERS) get_filename_component(FILENAME ${SHADER} NAME) add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/bin/shaders/${FILENAME}.spv diff --git a/cmake_modules/dependencies/tracy.cmake b/cmake_modules/dependencies/tracy.cmake index f9e4473..cb27724 100644 --- a/cmake_modules/dependencies/tracy.cmake +++ b/cmake_modules/dependencies/tracy.cmake @@ -7,6 +7,7 @@ message("-- Cmake upper: ${CMAKE_UPPER_BUILD_TYPE}") if (CMAKE_UPPER_BUILD_TYPE STREQUAL "DEBUG" OR CMAKE_UPPER_BUILD_TYPE STREQUAL "RELWITHDEBINFO") set(TRACY_ENABLE ON) set(TRACY_ON_DEMAND ON) + set(TRACY_NO_EXIT ON) endif () add_subdirectory(${CMAKE_SOURCE_DIR}/dependencies/tracy) diff --git a/src/engine/EngineContext.cpp b/src/engine/EngineContext.cpp index 70769fe..f076212 100644 --- a/src/engine/EngineContext.cpp +++ b/src/engine/EngineContext.cpp @@ -505,7 +505,7 @@ namespace fgl::engine model->syncBuffers( command_buffer ); - constexpr int val { 4 }; + constexpr int val { 32 }; constexpr float x_offset { -( static_cast< float >( val ) * 30.0f ) / 2.0f }; constexpr float y_offset { -( static_cast< float >( val ) * 20.0f ) / 2.0f }; diff --git a/src/engine/FrameInfo.hpp b/src/engine/FrameInfo.hpp index d51c724..09938fa 100644 --- a/src/engine/FrameInfo.hpp +++ b/src/engine/FrameInfo.hpp @@ -83,6 +83,8 @@ namespace fgl::engine DescriptorSet& gbuffer_descriptor_set; const Frustum< CoordinateSpace::World >& camera_frustum; + + std::vector< std::vector< GameObject >* > in_view_leafs {}; }; } // namespace fgl::engine diff --git a/src/engine/primitives/Frustum.hpp b/src/engine/primitives/Frustum.hpp index 5f9a23d..9838eb5 100644 --- a/src/engine/primitives/Frustum.hpp +++ b/src/engine/primitives/Frustum.hpp @@ -81,6 +81,15 @@ namespace fgl::engine template < typename T > bool intersects( const T& t ) const; + template < typename T, std::size_t TSize > + inline bool intersects( const std::array< T, TSize >& t ) const + { + for ( std::size_t i = 0; i < TSize; ++i ) + if ( intersects( t[ i ] ) ) return true; + + return false; + } + template < typename T > Coordinate< CType > intersection( const T& t ) const; diff --git a/src/engine/primitives/boxes/AxisAlignedBoundingBox.cpp b/src/engine/primitives/boxes/AxisAlignedBoundingBox.cpp index 8becb4a..813b4f6 100644 --- a/src/engine/primitives/boxes/AxisAlignedBoundingBox.cpp +++ b/src/engine/primitives/boxes/AxisAlignedBoundingBox.cpp @@ -17,9 +17,10 @@ namespace fgl::engine } template < CoordinateSpace CType > - std::vector< Coordinate< CType > > AxisAlignedBoundingBox< CType >::points() const + std::array< Coordinate< CType >, interface::BoundingBox::POINT_COUNT > AxisAlignedBoundingBox< CType >::points() + const { - std::vector< Coordinate< CType > > points; + std::array< Coordinate< CType >, POINT_COUNT > points {}; // xp == x positive (Highest x point) // xn == x negative (Lowest x point) @@ -40,7 +41,6 @@ namespace fgl::engine const glm::vec3 xn_yp_zn { xn, yp, zn }; // (- + -) const glm::vec3 xp_yp_zn { xp, yp, zn }; // (+ + -) - points.resize( 8 ); points[ 0 ] = Coordinate< CType >( xp_yp_zp ); points[ 1 ] = Coordinate< CType >( xn_yp_zp ); points[ 2 ] = Coordinate< CType >( xn_yp_zn ); @@ -62,29 +62,30 @@ namespace fgl::engine } template < CoordinateSpace CType > - std::vector< LineSegment< CType > > AxisAlignedBoundingBox< CType >::lines() const + std::array< LineSegment< CType >, interface::BoundingBox::LINE_COUNT > AxisAlignedBoundingBox< CType >::lines() + const { const auto points { this->points() }; - std::vector< LineSegment< CType > > lines; + std::array< LineSegment< CType >, LINE_COUNT > lines {}; //Top - lines.emplace_back( points[ 0 ], points[ 1 ] ); - lines.emplace_back( points[ 1 ], points[ 2 ] ); - lines.emplace_back( points[ 2 ], points[ 3 ] ); - lines.emplace_back( points[ 3 ], points[ 0 ] ); + lines[ 0 ] = LineSegment< CType >( points[ 0 ], points[ 1 ] ); + lines[ 1 ] = LineSegment< CType >( points[ 1 ], points[ 2 ] ); + lines[ 2 ] = LineSegment< CType >( points[ 2 ], points[ 3 ] ); + lines[ 3 ] = LineSegment< CType >( points[ 3 ], points[ 0 ] ); //Bottom - lines.emplace_back( points[ 4 ], points[ 5 ] ); - lines.emplace_back( points[ 5 ], points[ 6 ] ); - lines.emplace_back( points[ 6 ], points[ 7 ] ); - lines.emplace_back( points[ 7 ], points[ 4 ] ); + lines[ 4 ] = LineSegment< CType >( points[ 4 ], points[ 5 ] ); + lines[ 5 ] = LineSegment< CType >( points[ 5 ], points[ 6 ] ); + lines[ 6 ] = LineSegment< CType >( points[ 6 ], points[ 7 ] ); + lines[ 7 ] = LineSegment< CType >( points[ 7 ], points[ 4 ] ); //Sides - lines.emplace_back( points[ 0 ], points[ 4 ] ); - lines.emplace_back( points[ 1 ], points[ 5 ] ); - lines.emplace_back( points[ 2 ], points[ 6 ] ); - lines.emplace_back( points[ 3 ], points[ 7 ] ); + lines[ 8 ] = LineSegment< CType >( points[ 0 ], points[ 4 ] ); + lines[ 9 ] = LineSegment< CType >( points[ 1 ], points[ 5 ] ); + lines[ 10 ] = LineSegment< CType >( points[ 2 ], points[ 6 ] ); + lines[ 11 ] = LineSegment< CType >( points[ 3 ], points[ 7 ] ); return lines; } diff --git a/src/engine/primitives/boxes/AxisAlignedBoundingBox.hpp b/src/engine/primitives/boxes/AxisAlignedBoundingBox.hpp index 73d1ad4..4f70e37 100644 --- a/src/engine/primitives/boxes/AxisAlignedBoundingBox.hpp +++ b/src/engine/primitives/boxes/AxisAlignedBoundingBox.hpp @@ -56,8 +56,8 @@ namespace fgl::engine virtual Scale scale() const; - std::vector< Coordinate< CType > > points() const; - std::vector< LineSegment< CType > > lines() const; + std::array< Coordinate< CType >, POINT_COUNT > points() const; + std::array< LineSegment< CType >, LINE_COUNT > lines() const; constexpr NormalVector right() const { return NormalVector::bypass( constants::WORLD_RIGHT ); } diff --git a/src/engine/primitives/boxes/BoundingBox.hpp b/src/engine/primitives/boxes/BoundingBox.hpp index 9517a13..675ff0e 100644 --- a/src/engine/primitives/boxes/BoundingBox.hpp +++ b/src/engine/primitives/boxes/BoundingBox.hpp @@ -12,10 +12,14 @@ namespace fgl::engine::interface class NormalVector; //! Dummy class to allow for inheriting to pass 'is_bounding_box[ - class BoundingBox + struct BoundingBox { public: + constexpr static std::size_t POINT_COUNT { 8 }; + constexpr static std::size_t LINE_COUNT { ( POINT_COUNT / 2 ) * 3 }; + // Each point has 3 lines (Divide by 2 since we only need 1 line per direction) + virtual ~BoundingBox() {}; }; diff --git a/src/engine/primitives/boxes/OrientedBoundingBox.cpp b/src/engine/primitives/boxes/OrientedBoundingBox.cpp index 8980bfd..f307a12 100644 --- a/src/engine/primitives/boxes/OrientedBoundingBox.cpp +++ b/src/engine/primitives/boxes/OrientedBoundingBox.cpp @@ -84,11 +84,11 @@ namespace fgl::engine } template < CoordinateSpace CType > - std::vector< Coordinate< CType > > OrientedBoundingBox< CType >::points() const + std::array< Coordinate< CType >, interface::BoundingBox::POINT_COUNT > OrientedBoundingBox< CType >::points() const { assert( middle.vec() != constants::DEFAULT_VEC3 ); assert( scale != glm::vec3( 0.0f ) ); - std::vector< Coordinate< CType > > points; + std::array< Coordinate< CType >, POINT_COUNT > points {}; // xp == x positive (Highest x point) // xn == x negative (Lowest x point) @@ -129,7 +129,6 @@ namespace fgl::engine * 6 =========== 7 */ - points.resize( 8 ); points[ 0 ] = Coordinate< CType >( xp_yp_zp ); points[ 1 ] = Coordinate< CType >( xn_yp_zp ); points[ 2 ] = Coordinate< CType >( xn_yp_zn ); @@ -170,41 +169,72 @@ namespace fgl::engine ZoneScoped; const auto& other_points { other.points() }; - std::vector< Coordinate< CType > > points { this->points() }; - points.insert( points.end(), other_points.begin(), other_points.end() ); + const auto points { this->points() }; + std::array< Coordinate< CType >, interface::BoundingBox::POINT_COUNT * 2 > combined_points {}; + std::copy( other_points.begin(), other_points.end(), combined_points.begin() ); + std::copy( points.begin(), points.end(), combined_points.begin() + POINT_COUNT ); //TODO: There might be a way to do this without needing to do yet another point calculation. return generateBoundingFromPoints< CType >( points ); } template < CoordinateSpace CType > - std::vector< LineSegment< CType > > OrientedBoundingBox< CType >::lines() const + std::array< LineSegment< CType >, interface::BoundingBox::LINE_COUNT > OrientedBoundingBox< CType >::lines() const { const auto points { this->points() }; - std::vector< LineSegment< CType > > lines; + std::array< LineSegment< CType >, LINE_COUNT > lines; //Top - lines.emplace_back( points[ 0 ], points[ 1 ] ); - lines.emplace_back( points[ 1 ], points[ 2 ] ); - lines.emplace_back( points[ 2 ], points[ 3 ] ); - lines.emplace_back( points[ 3 ], points[ 0 ] ); + lines[ 0 ] = LineSegment< CType >( points[ 0 ], points[ 1 ] ); + lines[ 1 ] = LineSegment< CType >( points[ 1 ], points[ 2 ] ); + lines[ 2 ] = LineSegment< CType >( points[ 2 ], points[ 3 ] ); + lines[ 3 ] = LineSegment< CType >( points[ 3 ], points[ 0 ] ); //Bottom - lines.emplace_back( points[ 4 ], points[ 5 ] ); - lines.emplace_back( points[ 5 ], points[ 6 ] ); - lines.emplace_back( points[ 6 ], points[ 7 ] ); - lines.emplace_back( points[ 7 ], points[ 4 ] ); + lines[ 4 ] = LineSegment< CType >( points[ 4 ], points[ 5 ] ); + lines[ 5 ] = LineSegment< CType >( points[ 5 ], points[ 6 ] ); + lines[ 6 ] = LineSegment< CType >( points[ 6 ], points[ 7 ] ); + lines[ 7 ] = LineSegment< CType >( points[ 7 ], points[ 4 ] ); //Sides - lines.emplace_back( points[ 0 ], points[ 4 ] ); - lines.emplace_back( points[ 1 ], points[ 5 ] ); - lines.emplace_back( points[ 2 ], points[ 6 ] ); - lines.emplace_back( points[ 3 ], points[ 7 ] ); + lines[ 8 ] = LineSegment< CType >( points[ 0 ], points[ 4 ] ); + lines[ 9 ] = LineSegment< CType >( points[ 1 ], points[ 5 ] ); + lines[ 10 ] = LineSegment< CType >( points[ 2 ], points[ 6 ] ); + lines[ 11 ] = LineSegment< CType >( points[ 3 ], points[ 7 ] ); return lines; } + template < CoordinateSpace CType, std::size_t TCount > + OrientedBoundingBox< CType > generateBoundingFromPoints( const std::array< Coordinate< CType >, TCount >& points ) + { + ZoneScoped; + assert( points.size() > 0 ); + + // neg (min) + glm::vec3 top_left_front { points[ 0 ].vec() }; + // pos (max) + glm::vec3 bottom_right_back { points[ 0 ].vec() }; + + for ( const auto& pos : points ) + { + top_left_front.x = std::min( pos.vec().x, top_left_front.x ); + top_left_front.y = std::min( pos.vec().y, top_left_front.y ); + top_left_front.z = std::min( pos.vec().z, top_left_front.z ); + + bottom_right_back.x = std::max( pos.vec().x, bottom_right_back.x ); + bottom_right_back.y = std::max( pos.vec().y, bottom_right_back.y ); + bottom_right_back.z = std::max( pos.vec().z, bottom_right_back.z ); + } + + //Calculate midpoint + const glm::vec3 midpoint { ( top_left_front + bottom_right_back ) / glm::vec3( 2.0f ) }; + const glm::vec3 scale { bottom_right_back - midpoint }; + + return { Coordinate< CType >( midpoint ), scale }; + } + template < CoordinateSpace CType > OrientedBoundingBox< CType > generateBoundingFromPoints( const std::vector< Coordinate< CType > >& points ) { @@ -234,6 +264,10 @@ namespace fgl::engine return { Coordinate< CType >( midpoint ), scale }; } + template OrientedBoundingBox< CoordinateSpace::Model > generateBoundingFromPoints( const std::vector< Coordinate< + CoordinateSpace::Model > >& + points ); + OrientedBoundingBox< CoordinateSpace::Model > generateBoundingFromVerts( const std::vector< Vertex >& verts ) { // neg (min) diff --git a/src/engine/primitives/boxes/OrientedBoundingBox.hpp b/src/engine/primitives/boxes/OrientedBoundingBox.hpp index 3b4a646..966801b 100644 --- a/src/engine/primitives/boxes/OrientedBoundingBox.hpp +++ b/src/engine/primitives/boxes/OrientedBoundingBox.hpp @@ -56,8 +56,8 @@ namespace fgl::engine consteval static std::array< std::uint32_t, indicies_count > triangleIndicies(); - std::vector< Coordinate< CType > > points() const; - std::vector< LineSegment< CType > > lines() const; + std::array< Coordinate< CType >, POINT_COUNT > points() const; + std::array< LineSegment< CType >, LINE_COUNT > lines() const; NormalVector forward() const { return rotation.forward(); } diff --git a/src/engine/primitives/lines/LineSegment.hpp b/src/engine/primitives/lines/LineSegment.hpp index fd995a5..7797fbe 100644 --- a/src/engine/primitives/lines/LineSegment.hpp +++ b/src/engine/primitives/lines/LineSegment.hpp @@ -16,8 +16,8 @@ namespace fgl::engine template < CoordinateSpace CType > class LineSegment final : public LineBase { - Coordinate< CType > start; - Coordinate< CType > end; + Coordinate< CType > start { -constants::DEFAULT_VEC3 }; + Coordinate< CType > end { constants::DEFAULT_VEC3 }; glm::vec3 getVec3Position() const override { return getPosition().vec(); } @@ -25,11 +25,7 @@ namespace fgl::engine public: - NormalVector getDirection() const { return NormalVector( end - start ); } - - Coordinate< CType > getPosition() const { return start; } - - Coordinate< CType > getEnd() const { return end; } + LineSegment() = default; explicit LineSegment( const Coordinate< CType > i_start, const Coordinate< CType > i_end ) noexcept : start( i_start ), @@ -38,6 +34,12 @@ namespace fgl::engine explicit LineSegment( const glm::vec3 i_start, glm::vec3 i_end ) : start( i_start ), end( i_end ) {} + NormalVector getDirection() const { return NormalVector( end - start ); } + + Coordinate< CType > getPosition() const { return start; } + + Coordinate< CType > getEnd() const { return end; } + inline LineSegment flip() const { return LineSegment( end, start ); } template < typename T > diff --git a/src/engine/rendering/Renderer.cpp b/src/engine/rendering/Renderer.cpp index 2326cc9..d760b6e 100644 --- a/src/engine/rendering/Renderer.cpp +++ b/src/engine/rendering/Renderer.cpp @@ -51,16 +51,20 @@ namespace fgl::engine throw std::runtime_error( "Failed to allocate command buffers" ); #if TRACY_ENABLE - m_tracy_ctx.resize( SwapChain::MAX_FRAMES_IN_FLIGHT ); + VkPhysicalDevice phy_dev { Device::getInstance().phyDevice() }; + VkDevice dev { Device::getInstance().device() }; - for ( int i = 0; i < SwapChain::MAX_FRAMES_IN_FLIGHT; ++i ) - { - VkPhysicalDevice phy_dev { Device::getInstance().phyDevice() }; - VkDevice dev { Device::getInstance().device() }; + m_tracy_ctx = TracyVkContext( phy_dev, dev, Device::getInstance().graphicsQueue(), m_command_buffer[ 0 ] ); - m_tracy_ctx[ i ] = - TracyVkContext( phy_dev, dev, Device::getInstance().graphicsQueue(), m_command_buffer[ i ] ); - } + /* + m_tracy_ctx = TracyVkContextCalibrated( + phy_dev, + dev, + Device::getInstance().graphicsQueue(), + m_command_buffer[ 0 ], + VULKAN_HPP_DEFAULT_DISPATCHER.vkGetPhysicalDeviceCalibrateableTimeDomainsEXT, + VULKAN_HPP_DEFAULT_DISPATCHER.vkGetCalibratedTimestampsEXT ); + */ #endif } diff --git a/src/engine/rendering/Renderer.hpp b/src/engine/rendering/Renderer.hpp index e0f6d30..abf4466 100644 --- a/src/engine/rendering/Renderer.hpp +++ b/src/engine/rendering/Renderer.hpp @@ -29,7 +29,7 @@ namespace fgl::engine std::vector< vk::CommandBuffer > m_command_buffer {}; - std::vector< TracyVkCtx > m_tracy_ctx {}; + std::optional< TracyVkCtx > m_tracy_ctx { std::nullopt }; void createCommandBuffers(); void freeCommandBuffers(); @@ -63,7 +63,8 @@ namespace fgl::engine TracyVkCtx getCurrentTracyCTX() const { #if TRACY_ENABLE - return m_tracy_ctx[ current_frame_idx ]; + assert( m_tracy_ctx.has_value() ); + return m_tracy_ctx.value(); #else return nullptr; #endif diff --git a/src/engine/systems/CullingSystem.cpp b/src/engine/systems/CullingSystem.cpp index 6df0d36..f7e0b6e 100644 --- a/src/engine/systems/CullingSystem.cpp +++ b/src/engine/systems/CullingSystem.cpp @@ -13,15 +13,27 @@ namespace fgl::engine { + static bool enable_culling { true }; + void CullingSystem::pass( FrameInfo& info ) { ZoneScopedN( "Culling pass" ); const auto frustum { info.camera_frustum }; - for ( auto* leaf : info.game_objects.getAllLeafsInFrustum( frustum ) ) + ImGui::Checkbox( "Enable culling", &enable_culling ); + + if ( !enable_culling ) + { + return; + } + + auto leafs { info.game_objects.getAllLeafsInFrustum( frustum ) }; + + for ( auto* leaf : leafs ) { assert( leaf ); + for ( auto& obj : *leaf ) { //Has model? @@ -43,6 +55,8 @@ namespace fgl::engine } } } + + info.in_view_leafs = std::move( leafs ); } void CullingSystem::runner() diff --git a/src/engine/systems/CullingSystem.hpp b/src/engine/systems/CullingSystem.hpp index 32b1288..e0d932a 100644 --- a/src/engine/systems/CullingSystem.hpp +++ b/src/engine/systems/CullingSystem.hpp @@ -6,6 +6,8 @@ #include +#include "concepts.hpp" + namespace fgl::engine { struct FrameInfo; @@ -34,4 +36,7 @@ namespace fgl::engine void wait(); }; + static_assert( is_system< CullingSystem > ); + static_assert( is_threaded_system< CullingSystem > ); + } // namespace fgl::engine diff --git a/src/engine/systems/EntityRendererSystem.cpp b/src/engine/systems/EntityRendererSystem.cpp index 22a3a2e..2465f2a 100644 --- a/src/engine/systems/EntityRendererSystem.cpp +++ b/src/engine/systems/EntityRendererSystem.cpp @@ -113,9 +113,7 @@ namespace fgl::engine std::uint64_t object_counter { 0 }; std::uint64_t primitive_counter { 0 }; - const auto in_view_leafs { info.game_objects.getAllLeafsInFrustum( info.camera_frustum ) }; - - for ( auto* node : in_view_leafs ) + for ( auto* node : info.in_view_leafs ) { ZoneScopedN( "Process leaf" ); for ( const auto& obj : *node ) diff --git a/src/engine/systems/concepts.hpp b/src/engine/systems/concepts.hpp new file mode 100644 index 0000000..b0a5d25 --- /dev/null +++ b/src/engine/systems/concepts.hpp @@ -0,0 +1,33 @@ +// +// Created by kj16609 on 3/11/24. +// + +#ifndef GAME_CONCEPTS_HPP +#define GAME_CONCEPTS_HPP + +namespace fgl::engine +{ + + struct FrameInfo; + + template < typename T > + concept is_system = requires( T t, FrameInfo info ) { + { + t.pass( info ) + }; + }; + + template < typename T > + concept is_threaded_system = requires( T t, FrameInfo info ) { + requires is_system< T >; + { + t.startPass( info ) + }; + { + t.wait() + }; + }; + +} // namespace fgl::engine + +#endif //GAME_CONCEPTS_HPP diff --git a/src/engine/tree/octtree/OctTreeNode.cpp b/src/engine/tree/octtree/OctTreeNode.cpp index 475c48c..3eef06b 100644 --- a/src/engine/tree/octtree/OctTreeNode.cpp +++ b/src/engine/tree/octtree/OctTreeNode.cpp @@ -30,12 +30,13 @@ namespace fgl::engine #endif } - std::vector< NodeLeaf* > OctTreeNode::getAllLeafsInFrustum( const Frustum< CoordinateSpace::World >& frustum ) + void OctTreeNode:: + getAllLeafsInFrustum( const Frustum< CoordinateSpace::World >& frustum, std::vector< NodeLeaf* >& out_leafs ) { - std::vector< NodeLeaf* > leafs {}; - //Check if we are inside of the frustum. - if ( !isInFrustum( frustum ) ) return leafs; + if ( !isInFrustum( frustum ) ) return; + + auto& leafs { out_leafs }; switch ( m_node_data.index() ) { @@ -45,62 +46,35 @@ namespace fgl::engine NodeArray& node_array { std::get< NodeArray >( m_node_data ) }; //Search deeper -#ifndef NDEBUG - for ( int x = 0; x < 2; ++x ) - for ( int y = 0; y < 2; ++y ) - for ( int z = 0; z < 2; ++z ) assert( node_array[ x ][ y ][ z ] ); -#endif + node_array[ LEFT ][ FORWARD ][ TOP ]->getAllLeafsInFrustum( frustum, out_leafs ); + node_array[ LEFT ][ FORWARD ][ BOTTOM ]->getAllLeafsInFrustum( frustum, out_leafs ); - { - const auto ret { node_array[ LEFT ][ FORWARD ][ TOP ]->getAllLeafsInFrustum( frustum ) }; - leafs = std::move( ret ); - } - { - const auto ret { node_array[ LEFT ][ FORWARD ][ BOTTOM ]->getAllLeafsInFrustum( frustum ) }; - leafs.insert( leafs.end(), ret.begin(), ret.end() ); - } - { - const auto ret { node_array[ LEFT ][ BACK ][ TOP ]->getAllLeafsInFrustum( frustum ) }; - leafs.insert( leafs.end(), ret.begin(), ret.end() ); - } - { - const auto ret { node_array[ LEFT ][ BACK ][ BOTTOM ]->getAllLeafsInFrustum( frustum ) }; - leafs.insert( leafs.end(), ret.begin(), ret.end() ); - } + node_array[ LEFT ][ BACK ][ TOP ]->getAllLeafsInFrustum( frustum, out_leafs ); + node_array[ LEFT ][ BACK ][ BOTTOM ]->getAllLeafsInFrustum( frustum, out_leafs ); - { - const auto ret { node_array[ RIGHT ][ FORWARD ][ TOP ]->getAllLeafsInFrustum( frustum ) }; - leafs.insert( leafs.end(), ret.begin(), ret.end() ); - } - { - const auto ret { node_array[ RIGHT ][ FORWARD ][ BOTTOM ]->getAllLeafsInFrustum( frustum ) }; - leafs.insert( leafs.end(), ret.begin(), ret.end() ); - } - { - const auto ret { node_array[ RIGHT ][ BACK ][ TOP ]->getAllLeafsInFrustum( frustum ) }; - leafs.insert( leafs.end(), ret.begin(), ret.end() ); - } - { - const auto ret { node_array[ RIGHT ][ BACK ][ BOTTOM ]->getAllLeafsInFrustum( frustum ) }; - leafs.insert( leafs.end(), ret.begin(), ret.end() ); - } - return leafs; + node_array[ RIGHT ][ FORWARD ][ TOP ]->getAllLeafsInFrustum( frustum, out_leafs ); + node_array[ RIGHT ][ FORWARD ][ BOTTOM ]->getAllLeafsInFrustum( frustum, out_leafs ); + + node_array[ RIGHT ][ BACK ][ TOP ]->getAllLeafsInFrustum( frustum, out_leafs ); + node_array[ RIGHT ][ BACK ][ BOTTOM ]->getAllLeafsInFrustum( frustum, out_leafs ); + return; } case 1: // NodeLeaf { assert( std::holds_alternative< NodeLeaf >( m_node_data ) ); - leafs.reserve( 4096 ); - leafs.emplace_back( &std::get< NodeLeaf >( m_node_data ) ); + NodeLeaf& leaf { std::get< NodeLeaf >( m_node_data ) }; + leafs.reserve( LEAF_RESERVE_SIZE ); + leafs.emplace_back( &leaf ); //debug::world::drawBoundingBox( m_bounds ); - return leafs; + return; } default: - throw std::runtime_error( "OctTreeNode::Index out of bounds" ); + std::unreachable(); } - return leafs; + std::unreachable(); } OctTreeNode::OctTreeNode( const WorldCoordinate center, float span, OctTreeNode* parent ) : @@ -115,6 +89,7 @@ namespace fgl::engine void OctTreeNode::split( int depth ) { + ZoneScoped; if ( std::holds_alternative< NodeArray >( m_node_data ) ) return; auto& game_objects { std::get< NodeLeaf >( m_node_data ) }; @@ -212,7 +187,7 @@ namespace fgl::engine } } - bool OctTreeNode::isInFrustum( const Frustum< CoordinateSpace::World >& frustum ) + bool OctTreeNode::isInFrustum( const Frustum< CoordinateSpace::World >& frustum ) const { #if ENABLE_IMGUI if ( isEmpty() ) return false; @@ -308,11 +283,9 @@ namespace fgl::engine return m_parent->getRoot(); } - std::vector< NodeLeaf* > OctTreeNode::getAllLeafs() + void OctTreeNode::getAllLeafs( std::vector< NodeLeaf* >& objects ) { ZoneScoped; - std::vector< NodeLeaf* > objects {}; - if ( std::holds_alternative< NodeLeaf >( m_node_data ) ) { auto& leaf { std::get< NodeLeaf >( m_node_data ) }; @@ -335,8 +308,6 @@ namespace fgl::engine } } } - - return objects; } bool OctTreeNode::recalculateBoundingBoxes() diff --git a/src/engine/tree/octtree/OctTreeNode.hpp b/src/engine/tree/octtree/OctTreeNode.hpp index 95ce7ed..eac1ad2 100644 --- a/src/engine/tree/octtree/OctTreeNode.hpp +++ b/src/engine/tree/octtree/OctTreeNode.hpp @@ -5,6 +5,7 @@ #pragma once #include +#include #include "engine/GameObject.hpp" #include "engine/primitives/boxes/AxisAlignedBoundingCube.hpp" @@ -28,6 +29,34 @@ namespace fgl::engine class OctTreeNode; class GameObject; + template < typename T > + class OctTreeAllocator : public std::allocator< T > + { + std::vector< std::vector< std::byte > > blocks; + using BlockIDX = int; + + //! Map for each pointer to their respective blocks + std::unordered_map< T*, BlockIDX > m_block_map; + }; + + template < typename T > + using unique_alloc_ptr = std::unique_ptr< T, std::function< void( T* ) > >; + + template < typename T, typename... Ts > + unique_alloc_ptr< T > make_unique_from_allocator( OctTreeAllocator< T >& allocator, Ts... args ) + { + T* ptr = allocator.allocate( 1 ); + allocator.construct( ptr, args... ); + + auto deleter = [ &allocator ]( const auto* ptr_i ) -> void + { + allocator.destroy( ptr_i ); + allocator.deallocate( ptr_i, 1 ); + }; + + return std::unique_ptr< T, decltype( deleter ) >( ptr, deleter ); + } + using NodeArray = std::array< std::array< std::array< std::unique_ptr< OctTreeNode >, 2 >, 2 >, 2 >; using NodeLeaf = std::vector< GameObject >; @@ -44,7 +73,10 @@ namespace fgl::engine //! Real bounds of the node AxisAlignedBoundingCube< CoordinateSpace::World > m_bounds; - std::variant< NodeArray, NodeLeaf > m_node_data; + using NodeDataT = NodeArray; + using LeafDataT = NodeLeaf; + + std::variant< NodeDataT, LeafDataT > m_node_data; OctTreeNode* m_parent; @@ -77,7 +109,7 @@ namespace fgl::engine GameObject extract( const GameObject::ID id ); - bool isInFrustum( const Frustum< CoordinateSpace::World >& frustum ); + bool isInFrustum( const Frustum< CoordinateSpace::World >& frustum ) const; bool isEmpty() const { @@ -86,13 +118,34 @@ namespace fgl::engine auto getGameObjectItter( const GameObject::ID id ); + void getAllLeafs( std::vector< NodeLeaf* >& out_leafs ); + void getAllLeafsInFrustum( + const Frustum< CoordinateSpace::World >& frustum, std::vector< NodeLeaf* >& out_leafs ); + public: bool recalculateBoundingBoxes(); - std::vector< NodeLeaf* > getAllLeafs(); + constexpr static std::size_t LEAF_RESERVE_SIZE { 1024 }; - std::vector< NodeLeaf* > getAllLeafsInFrustum( const Frustum< CoordinateSpace::World >& frustum ); + [[nodiscard]] inline std::vector< NodeLeaf* > getAllLeafs() + { + ZoneScoped; + std::vector< NodeLeaf* > leafs; + leafs.reserve( LEAF_RESERVE_SIZE ); + this->getAllLeafs( leafs ); + return leafs; + } + + [[nodiscard]] inline std::vector< NodeLeaf* > getAllLeafsInFrustum( const Frustum< CoordinateSpace::World >& + frustum ) + { + ZoneScoped; + std::vector< NodeLeaf* > leafs; + leafs.reserve( LEAF_RESERVE_SIZE ); + this->getAllLeafsInFrustum( frustum, leafs ); + return leafs; + } //! Adds a game object, Will split the node if the auto split threshold is reached OctTreeNode* addGameObject( GameObject&& obj );