From cb09d279a4970b0b3dbf087557cdbcdc8edfcc9e Mon Sep 17 00:00:00 2001 From: Ubpa Date: Thu, 30 Dec 2021 23:34:09 +0800 Subject: [PATCH] move function definitions to cpp files --- CMakeLists.txt | 2 +- include/UECS/Chunk.hpp | 33 +++++++++++++++-------------- include/UECS/CmptLocator.hpp | 4 ++-- include/UECS/CmptsView.hpp | 6 +++--- include/UECS/CommandBuffer.hpp | 30 ++++++++++---------------- include/UECS/Entity.hpp | 4 +++- include/UECS/EntityMngr.hpp | 28 ++++++++++++------------ include/UECS/EntityQuery.hpp | 20 ++++------------- include/UECS/Schedule.hpp | 2 +- include/UECS/SingletonLocator.hpp | 6 +++--- include/UECS/SingletonsView.hpp | 2 +- include/UECS/SystemFunc.hpp | 20 ++++++++--------- include/UECS/World.hpp | 10 ++++----- include/UECS/details/SystemFunc.inl | 10 ++++----- include/UECS/details/World.inl | 8 +++---- src/core/Archetype.cpp | 10 ++++----- src/core/Archetype.hpp | 6 +++--- src/core/Chunk.cpp | 31 +++++++++++++++++++++++---- src/core/CmptLocator.cpp | 4 ++++ src/core/CmptsView.cpp | 6 ++++++ src/core/CommandBuffer.cpp | 31 +++++++++++++++++++++++++++ src/core/EntityMngr.cpp | 29 +++++++++++++++++++------ src/core/EntityQuery.cpp | 23 ++++++++++++++++++++ src/core/Schedule.cpp | 2 ++ src/core/SingletonLocator.cpp | 5 +++++ src/core/SingletonsView.cpp | 2 +- src/core/SystemFunc.cpp | 18 ++++++++++++---- src/core/World.cpp | 7 ++++++ src/test/03_query_entity/main.cpp | 8 +++---- src/test/23_syncpoint/main.cpp | 4 ++-- 30 files changed, 241 insertions(+), 130 deletions(-) create mode 100644 src/core/EntityQuery.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 0ac20fe..4d915c2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.14 FATAL_ERROR) -project(UECS VERSION 0.16.1) +project(UECS VERSION 0.16.2) message(STATUS "[Project] ${PROJECT_NAME}") include(cmake/InitUCMake.cmake) diff --git a/include/UECS/Chunk.hpp b/include/UECS/Chunk.hpp index 8e60fac..e1e7130 100644 --- a/include/UECS/Chunk.hpp +++ b/include/UECS/Chunk.hpp @@ -18,10 +18,10 @@ namespace Ubpa::UECS { bool DidOrderChange(std::size_t version) const noexcept; std::uint64_t GetComponentVersion(TypeID cmptType) const noexcept; - std::uint64_t GetOrderVersion() const noexcept { return GetHead()->order_version; } + std::uint64_t GetOrderVersion() const noexcept; - std::size_t EntityNum() const noexcept { return GetHead()->num_entity; } - std::size_t ComponentNum() const noexcept { return GetHead()->num_component; } + std::size_t EntityNum() const noexcept; + std::size_t ComponentNum() const noexcept; // if not contains the component, return nullptr void* GetCmptArray(TypeID cmptType) const noexcept; @@ -34,10 +34,10 @@ namespace Ubpa::UECS { else return {}; } - std::span GetEntityArray() const noexcept { return GetCmptArray(); } + std::span GetEntityArray() const noexcept; - bool Full() const noexcept { return GetHead()->capacity == GetHead()->num_entity; } - bool Empty() const noexcept { return GetHead()->num_entity == 0; } + bool Full() const noexcept; + bool Empty() const noexcept; bool HasAnyChange(std::span types, std::uint64_t version) const noexcept; @@ -46,10 +46,11 @@ namespace Ubpa::UECS { // ApplyChanges std::tuple, small_vector> Locate(std::span types); - std::pmr::unsynchronized_pool_resource* GetChunkUnsyncResource() noexcept { return &GetHead()->chunk_unsync_rsrc; } - std::pmr::monotonic_buffer_resource* GetChunkUnsyncFrameResource() noexcept { return (std::pmr::monotonic_buffer_resource*)&GetHead()->chunk_unsync_frame_rsrc; } + std::pmr::unsynchronized_pool_resource* GetChunkUnsyncResource() noexcept; + std::pmr::monotonic_buffer_resource* GetChunkUnsyncFrameResource() noexcept; - template T* ChunkUnsyncNewFrameObject(Args&&... args) { + template + T* ChunkUnsyncNewFrameObject(Args&&... args) { auto rsrc = GetChunkUnsyncFrameResource(); auto obj = (T*)rsrc->allocate(sizeof(T), alignof(T)); std::pmr::polymorphic_allocator{ rsrc }.construct(obj, std::forward(args)...); @@ -79,20 +80,20 @@ namespace Ubpa::UECS { static_assert(sizeof(CmptInfo) == 24); // sorted by ID - std::span GetCmptInfos() noexcept { return { (CmptInfo*)(this + 1), num_component }; } - std::span GetCmptInfos() const noexcept { return const_cast(this)->GetCmptInfos(); } - - void ForceUpdateVersion(std::uint64_t version); + std::span GetCmptInfos() noexcept; + std::span GetCmptInfos() const noexcept; }; Chunk() noexcept = default; - ~Chunk() { GetHead()->~Head(); } + ~Chunk(); - Head* GetHead() noexcept { return reinterpret_cast(data); } - const Head* GetHead() const noexcept { return reinterpret_cast(data); } + Head* GetHead() noexcept; + const Head* GetHead() const noexcept; std::size_t Erase(std::size_t idx); + void ForceUpdateVersion(std::uint64_t version); + static_assert(ChunkSize > sizeof(Head)); std::uint8_t data[ChunkSize]; }; diff --git a/include/UECS/CmptLocator.hpp b/include/UECS/CmptLocator.hpp index 20c8ebe..ceeb8d7 100644 --- a/include/UECS/CmptLocator.hpp +++ b/include/UECS/CmptLocator.hpp @@ -21,9 +21,9 @@ namespace Ubpa::UECS { template CmptLocator& Combine(); - std::size_t GetValue() const noexcept { return hashCode; } + std::size_t GetValue() const noexcept; - const AccessTypeIDSet& AccessTypeIDs() const noexcept { return cmptTypes; } + const AccessTypeIDSet& AccessTypeIDs() const noexcept; bool operator==(const CmptLocator& rhs) const noexcept; diff --git a/include/UECS/CmptsView.hpp b/include/UECS/CmptsView.hpp index f7b1d46..df340d9 100644 --- a/include/UECS/CmptsView.hpp +++ b/include/UECS/CmptsView.hpp @@ -7,11 +7,11 @@ namespace Ubpa::UECS { class CmptsView { public: - CmptsView() noexcept = default; - CmptsView(std::span cmpts) noexcept : cmpts{ cmpts } {} + CmptsView() noexcept; + CmptsView(std::span cmpts) noexcept; CmptAccessPtr GetCmpt(AccessTypeID) const noexcept; - std::span Components() const noexcept { return cmpts; } + std::span AccessComponents() const noexcept; private: std::span cmpts; }; diff --git a/include/UECS/CommandBuffer.hpp b/include/UECS/CommandBuffer.hpp index ea528c2..7a748ed 100644 --- a/include/UECS/CommandBuffer.hpp +++ b/include/UECS/CommandBuffer.hpp @@ -6,32 +6,24 @@ namespace Ubpa::UECS { class CommandBuffer { public: - void AddCommand(std::function command) { commands.push_back(std::move(command)); } - void AddCommandBuffer(CommandBuffer cb) { - commands.reserve(commands.size() + cb.commands.size()); - for (auto& cmd : cb.commands) - commands.push_back(std::move(cmd)); - } - bool Empty() const noexcept { return commands.empty(); } - void Clear() { commands.clear(); } + void AddCommand(std::function command); + void AddCommandBuffer(CommandBuffer cb); + bool Empty() const noexcept; + void Clear() noexcept; - auto& GetCommands() noexcept { return commands; } - const auto& GetCommands() const noexcept { return commands; } + std::span> GetCommands() noexcept; + std::span> GetCommands() const noexcept; - void Run() { - for (const auto& cmd : commands) - cmd(); - commands.clear(); - } + void Run(); private: std::vector> commands; }; - class CommandBufferView { + class CommandBufferPtr { public: - CommandBufferView(CommandBuffer* cb = nullptr) : commandBuffer{ cb } {} - CommandBuffer* GetCommandBuffer() const noexcept { return commandBuffer; } - CommandBuffer* operator->()const noexcept { return commandBuffer; } + CommandBufferPtr(CommandBuffer* cb = nullptr); + CommandBuffer* Get() const noexcept; + CommandBuffer* operator->()const noexcept; private: CommandBuffer* commandBuffer; }; diff --git a/include/UECS/Entity.hpp b/include/UECS/Entity.hpp index d7a2367..f2bd95b 100644 --- a/include/UECS/Entity.hpp +++ b/include/UECS/Entity.hpp @@ -11,7 +11,9 @@ namespace Ubpa::UECS { std::uint64_t index; std::uint64_t version; - static constexpr Entity Invalid() noexcept { return { .index = static_cast(-1), .version = static_cast(-1) }; } + static constexpr Entity Invalid() noexcept + { return { .index = static_cast(-1), .version = static_cast(-1) }; } + constexpr bool Valid() const noexcept { return index != static_cast(-1); } constexpr auto operator<=>(const Entity&) const = default; }; diff --git a/include/UECS/EntityMngr.hpp b/include/UECS/EntityMngr.hpp index f965198..450704d 100644 --- a/include/UECS/EntityMngr.hpp +++ b/include/UECS/EntityMngr.hpp @@ -21,8 +21,8 @@ namespace Ubpa::UECS { // auto maintain Component's lifecycle ({default|copy|move} constructor, destructor) // [API] // - Entity: Create, Instantiate, Destroy, Exist - // - Component: Attach, Emplace, Detach, Have, Get, Components - // - Singleton: IsSingleton, GetSingletonEntity, GetSingleton + // - Component: Attach, Emplace, Detach, Have, Get, AccessComponents + // - Singleton: IsSingleton, GetSingletonEntity, AccessSingleton // - other: EntityNum, AddCommand // [important] // - some API with TypeID need CmptTraits to get {size|alignment|lifecycle function} (throw std::logic_error) @@ -44,17 +44,17 @@ namespace Ubpa::UECS { bool Have(Entity, TypeID) const; // nullptr if not containts TypeID - CmptAccessPtr GetComponent(Entity, AccessTypeID) const; - CmptAccessPtr WriteComponent(Entity e, TypeID t) const { return GetComponent(e, { t, AccessMode::WRITE }); } - CmptAccessPtr ReadComponent(Entity e, TypeID t) const { return GetComponent(e, { t, AccessMode::LATEST }); } + CmptAccessPtr AccessComponent(Entity, AccessTypeID) const; + CmptAccessPtr WriteComponent(Entity e, TypeID t) const; + CmptAccessPtr ReadComponent(Entity e, TypeID t) const; template Cmpt* WriteComponent(Entity e) const { return WriteComponent(e, TypeID_of).template As(); } template const Cmpt* ReadComponent(Entity e) const { return ReadComponent(e, TypeID_of).template As(); } - std::vector Components(Entity, AccessMode) const; - std::vector WriteComponents(Entity e) const { return Components(e, AccessMode::WRITE); } - std::vector ReadComponents(Entity e) const { return Components(e, AccessMode::LATEST); } + std::vector AccessComponents(Entity, AccessMode) const; + std::vector WriteComponents(Entity e) const; + std::vector ReadComponents(Entity e) const; // chunk + index in chunk std::tuple GetChunk(Entity e) const; @@ -63,17 +63,17 @@ namespace Ubpa::UECS { void Destroy(Entity); - std::size_t TotalEntityNum() const noexcept { return entityTable.size() - entityTableFreeEntry.size(); } + std::size_t TotalEntityNum() const noexcept; std::size_t EntityNum(const EntityQuery&) const; // use entry in reverse - std::span GetEntityFreeEntries() const noexcept { return { entityTableFreeEntry.data(), entityTableFreeEntry.size() }; } - std::size_t GetEntityVersion(std::size_t idx) const noexcept { return entityTable[idx].version; } + std::span GetEntityFreeEntries() const noexcept; + std::size_t GetEntityVersion(std::size_t idx) const noexcept; bool IsSingleton(TypeID) const; Entity GetSingletonEntity(TypeID) const; - CmptAccessPtr GetSingleton(AccessTypeID) const; - CmptAccessPtr WriteSingleton(TypeID type) const { return GetSingleton({ type, AccessMode::WRITE }); } - CmptAccessPtr ReadSingleton(TypeID type) const { return GetSingleton({ type, AccessMode::LATEST }); } + CmptAccessPtr AccessSingleton(AccessTypeID) const; + CmptAccessPtr WriteSingleton(TypeID type) const; + CmptAccessPtr ReadSingleton(TypeID type) const; template Cmpt* WriteSingleton() const { return WriteSingleton(TypeID_of).template As(); } template diff --git a/include/UECS/EntityQuery.hpp b/include/UECS/EntityQuery.hpp index 2a0ce98..b7d6b46 100644 --- a/include/UECS/EntityQuery.hpp +++ b/include/UECS/EntityQuery.hpp @@ -10,24 +10,12 @@ namespace Ubpa::UECS { ArchetypeFilter filter; CmptLocator locator; - std::size_t GetValue() const noexcept { return hash_combine(filter.GetValue(), locator.GetValue()); } + std::size_t GetValue() const noexcept; - bool IsMatch(const small_flat_set& types) const noexcept{ - return std::find_if_not(filter.all.begin(), filter.all.end(), - [&](const auto& type) { return types.contains(type); }) == filter.all.end() - && (filter.any.empty() - || std::find_if(filter.any.begin(), filter.any.end(), - [&](const auto& type) { return types.contains(type); }) != filter.any.end()) - && std::find_if(filter.none.begin(), filter.none.end(), - [&](const auto& type) { return types.contains(type); }) == filter.none.end() - && std::find_if_not(locator.AccessTypeIDs().begin(), locator.AccessTypeIDs().end(), - [&](const auto& type) { return types.contains(type); }) == locator.AccessTypeIDs().end(); - } - - friend bool operator==(const EntityQuery& lhs, const EntityQuery& rhs) noexcept { - return lhs.filter == rhs.filter && lhs.locator == rhs.locator; - } + bool IsMatch(const small_flat_set& types) const noexcept; }; + + bool operator==(const EntityQuery& lhs, const EntityQuery& rhs) noexcept; } template<> diff --git a/include/UECS/Schedule.hpp b/include/UECS/Schedule.hpp index b2f90a8..e4e1461 100644 --- a/include/UECS/Schedule.hpp +++ b/include/UECS/Schedule.hpp @@ -118,7 +118,7 @@ namespace Ubpa::UECS { Schedule& AddNone(std::string_view sys, TypeID, int layer = 0); Schedule& Disable(std::string_view sys, int layer = 0); - World* GetWorld() const noexcept { return world; } + World* GetWorld() const noexcept; std::string_view RegisterFrameString(std::string_view str); diff --git a/include/UECS/SingletonLocator.hpp b/include/UECS/SingletonLocator.hpp index e50c23d..f73a62c 100644 --- a/include/UECS/SingletonLocator.hpp +++ b/include/UECS/SingletonLocator.hpp @@ -8,9 +8,9 @@ namespace Ubpa::UECS { class SingletonLocator { public: - SingletonLocator(std::set types) : singletonTypes{ std::move(types) } {} + SingletonLocator(std::set types); SingletonLocator(std::span types); - SingletonLocator() = default; + SingletonLocator(); template static SingletonLocator Generate(); @@ -18,7 +18,7 @@ namespace Ubpa::UECS { template SingletonLocator& Combine(); - const std::set& SingletonTypes() const noexcept { return singletonTypes; } + const std::set& SingletonTypes() const noexcept; bool HasWriteSingletonType() const noexcept; diff --git a/include/UECS/SingletonsView.hpp b/include/UECS/SingletonsView.hpp index 1165159..3f65c9e 100644 --- a/include/UECS/SingletonsView.hpp +++ b/include/UECS/SingletonsView.hpp @@ -10,7 +10,7 @@ namespace Ubpa::UECS { SingletonsView(std::span singletons) noexcept : singletons{ singletons } {} - CmptAccessPtr GetSingleton(AccessTypeID) const noexcept; + CmptAccessPtr AccessSingleton(AccessTypeID) const noexcept; std::span Singletons() const noexcept { return singletons; } private: std::span singletons; diff --git a/include/UECS/SystemFunc.hpp b/include/UECS/SystemFunc.hpp index c9455d2..1ecf215 100644 --- a/include/UECS/SystemFunc.hpp +++ b/include/UECS/SystemFunc.hpp @@ -28,11 +28,11 @@ namespace Ubpa::UECS { // * : {LastFrame|Write|Latest}... // * CmptsView // * ChunkView - // * CommandBufferView + // * CommandBufferPtr // 2. Mode::Chunk // * std::size_t entityBeginIndexInQuery // * ChunkView (necessary) - // * CommandBufferView + // * CommandBufferPtr // 3. Mode::Job // * Write> (only job can write singletons) class SystemFunc { @@ -62,27 +62,27 @@ namespace Ubpa::UECS { template SystemFunc(Func&&, std::string_view name, SingletonLocator, RandomAccessor); - std::string_view Name() const noexcept { return name; } + std::string_view Name() const noexcept; static constexpr std::size_t GetValue(std::string_view name) noexcept { return string_hash(name); } - std::size_t GetValue() const noexcept { return hashCode; } + std::size_t GetValue() const noexcept; - void operator()(World*, SingletonsView, Entity, std::size_t entityIndexInQuery, CmptsView, CommandBufferView) const; - void operator()(World*, SingletonsView, std::size_t entityBeginIndexInQuery, ChunkView, CommandBufferView) const; + void operator()(World*, SingletonsView, Entity, std::size_t entityIndexInQuery, CmptsView, CommandBufferPtr) const; + void operator()(World*, SingletonsView, std::size_t entityBeginIndexInQuery, ChunkView, CommandBufferPtr) const; void operator()(World*, SingletonsView) const; - Mode GetMode() const noexcept { return mode; } - bool IsParallel() const noexcept { return isParallel; } + Mode GetMode() const noexcept; + bool IsParallel() const noexcept; - bool operator==(const SystemFunc& sysFunc) const noexcept { return name == sysFunc.name; } + bool operator==(const SystemFunc& sysFunc) const noexcept; private: friend class Schedule; Mode mode; std::string_view name; std::size_t hashCode; // after name bool isParallel; - std::function func; + std::function func; }; } diff --git a/include/UECS/World.hpp b/include/UECS/World.hpp index 554bab2..484bdcf 100644 --- a/include/UECS/World.hpp +++ b/include/UECS/World.hpp @@ -147,15 +147,15 @@ namespace Ubpa::UECS { SingletonLocator = {} ) const; - synchronized_monotonic_buffer_resource* GetSyncFrameResource() { return sync_frame_rsrc.get(); } - std::pmr::monotonic_buffer_resource* GetUnsyncFrameResource() { return unsync_frame_rsrc.get(); } - std::pmr::synchronized_pool_resource* GetSyncResource() { return sync_rsrc.get(); } - std::pmr::unsynchronized_pool_resource* GetUnsyncResource() { return unsync_rsrc.get(); } + synchronized_monotonic_buffer_resource* GetSyncFrameResource(); + std::pmr::monotonic_buffer_resource* GetUnsyncFrameResource(); + std::pmr::synchronized_pool_resource* GetSyncResource(); + std::pmr::unsynchronized_pool_resource* GetUnsyncResource(); template T* SyncNewFrameObject(Args&&... args); template T* UnsyncNewFrameObject(Args&&... args); - std::uint64_t Version() const noexcept { return version; } + std::uint64_t Version() const noexcept; private: bool inRunningJobGraph{ false }; diff --git a/include/UECS/details/SystemFunc.inl b/include/UECS/details/SystemFunc.inl index 65411c6..96495cb 100644 --- a/include/UECS/details/SystemFunc.inl +++ b/include/UECS/details/SystemFunc.inl @@ -104,8 +104,8 @@ namespace Ubpa::UECS { && !Contain_v && !Contain_v && !Contain_v - && !Contain_v, - "(Mode::Job) SystemFunc's argument list cann't have Entity, indexInQuery CmptsView, ChunkView or CommandBufferView" + && !Contain_v, + "(Mode::Job) SystemFunc's argument list cann't have Entity, indexInQuery CmptsView, ChunkView or CommandBufferPtr" ); } } @@ -127,7 +127,7 @@ namespace Ubpa::UECS::details { std::size_t entityIndexInQuery, CmptsView cmpts, ChunkView chunkView, - CommandBufferView cbv) + CommandBufferPtr cb) { auto args = std::tuple{ w, @@ -136,9 +136,9 @@ namespace Ubpa::UECS::details { e, entityIndexInQuery, cmpts, - reinterpret_cast(cmpts.Components()[Find_v].Ptr())..., + reinterpret_cast(cmpts.AccessComponents()[Find_v].Ptr())..., chunkView, - cbv + cb }; func(std::get(args)...); }; diff --git a/include/UECS/details/World.inl b/include/UECS/details/World.inl index a06ed98..8210b7e 100644 --- a/include/UECS/details/World.inl +++ b/include/UECS/details/World.inl @@ -35,8 +35,8 @@ namespace Ubpa::UECS { "const RunEntityJob should use const World*"); static_assert(Length_v> == 0, "const RunEntityJob can't write cmpt"); - static_assert(!Contain_v, - "const RunEntityJob shouldn't use CommandBufferView"); + static_assert(!Contain_v, + "const RunEntityJob shouldn't use CommandBufferPtr"); assert("const RunEntityJob can't write cmpt" && !cmptLocator.HasWriteTypeID()); @@ -78,8 +78,8 @@ namespace Ubpa::UECS { using ArgList = FuncTraits_ArgList; static_assert(!Contain_v, "const RunChunkJob should use const World*"); - static_assert(!Contain_v, - "const RunChunkJob shouldn't use CommandBufferView"); + static_assert(!Contain_v, + "const RunChunkJob shouldn't use CommandBufferPtr"); assert("const RunChunkJob can't write cmpt" && !filter.HaveWriteTypeID()); diff --git a/src/core/Archetype.cpp b/src/core/Archetype.cpp index 7621952..e30b239 100644 --- a/src/core/Archetype.cpp +++ b/src/core/Archetype.cpp @@ -45,7 +45,7 @@ Archetype::Archetype(const Archetype& src, World* world) : world{ world } { std::memcpy(dstChunk, srcChunk, sizeof(Chunk::Head) + sizeof(Chunk::Head::CmptInfo) * cmptTraits.GetTypes().size()); new(&dstChunk->GetHead()->chunk_unsync_rsrc)std::pmr::unsynchronized_pool_resource(world->GetSyncResource()); new(&dstChunk->GetHead()->chunk_unsync_frame_rsrc)std::pmr::monotonic_buffer_resource(world->GetSyncFrameResource()); - dstChunk->GetHead()->ForceUpdateVersion(world->Version()); + dstChunk->ForceUpdateVersion(world->Version()); dstChunk->GetHead()->archetype = this; std::size_t num = srcChunk->EntityNum(); for (std::size_t j = 0; j < cmptTraits.GetTraits().size(); j++) { @@ -160,7 +160,7 @@ Archetype::EntityAddress Archetype::Create(Entity e) { else trait.DefaultConstruct(dst, chunk->GetChunkUnsyncResource()); } - chunk->GetHead()->ForceUpdateVersion(world->Version()); + chunk->ForceUpdateVersion(world->Version()); return addr; } @@ -179,7 +179,7 @@ Archetype::EntityAddress Archetype::RequestBuffer() { info.ID = cmptTraits.GetTypes().data()[i]; info.offset = offsets[i]; } - chunk->GetHead()->ForceUpdateVersion(world->Version()); + chunk->ForceUpdateVersion(world->Version()); new(&chunk->GetHead()->chunk_unsync_rsrc)std::pmr::unsynchronized_pool_resource(world->GetSyncResource()); new(&chunk->GetHead()->chunk_unsync_frame_rsrc)std::pmr::monotonic_buffer_resource(world->GetSyncFrameResource()); @@ -253,7 +253,7 @@ Archetype::EntityAddress Archetype::Instantiate(Entity e, EntityAddress src) { trait.CopyConstruct(dstCmpt, srcCmpt, dstChunk->GetChunkUnsyncResource()); } - dstChunk->GetHead()->ForceUpdateVersion(world->Version()); + dstChunk->ForceUpdateVersion(world->Version()); entityNum++; @@ -315,7 +315,7 @@ std::size_t Archetype::Erase(EntityAddress addr) { return movedEntityIdx; } -vector Archetype::Components(EntityAddress addr, AccessMode mode) const { +vector Archetype::AccessComponents(EntityAddress addr, AccessMode mode) const { vector rst; for (const auto& type : cmptTraits.GetTypes()) { diff --git a/src/core/Archetype.hpp b/src/core/Archetype.hpp index 3d1d4a1..cad36e7 100644 --- a/src/core/Archetype.hpp +++ b/src/core/Archetype.hpp @@ -59,9 +59,9 @@ namespace Ubpa::UECS { const Cmpt* ReadAt(EntityAddress addr) const { return ReadAt(TypeID_of, addr).template As(); } // no Entity - std::vector Components(EntityAddress addr, AccessMode mode) const; - std::vector WriteComponents(EntityAddress addr) const { return Components(addr, AccessMode::WRITE); } - std::vector ReadComponents(EntityAddress addr) const { return Components(addr, AccessMode::LATEST); } + std::vector AccessComponents(EntityAddress addr, AccessMode mode) const; + std::vector WriteComponents(EntityAddress addr) const { return AccessComponents(addr, AccessMode::WRITE); } + std::vector ReadComponents(EntityAddress addr) const { return AccessComponents(addr, AccessMode::LATEST); } // no init EntityAddress RequestBuffer(); diff --git a/src/core/Chunk.cpp b/src/core/Chunk.cpp index 19e4994..8a7497b 100644 --- a/src/core/Chunk.cpp +++ b/src/core/Chunk.cpp @@ -27,6 +27,11 @@ std::uint64_t Chunk::GetComponentVersion(TypeID cmptType) const noexcept { return target->version; } +std::uint64_t Chunk::GetOrderVersion() const noexcept { return GetHead()->order_version; } + +std::size_t Chunk::EntityNum() const noexcept { return GetHead()->num_entity; } +std::size_t Chunk::ComponentNum() const noexcept { return GetHead()->num_component; } + void* Chunk::GetCmptArray(TypeID cmptType) const noexcept { const auto infos = GetHead()->GetCmptInfos(); auto target = std::lower_bound(infos.begin(), infos.end(), cmptType, std::less<>{}); @@ -36,6 +41,11 @@ void* Chunk::GetCmptArray(TypeID cmptType) const noexcept { return (std::uint8_t*)data + target->offset; } +std::span Chunk::GetEntityArray() const noexcept { return GetCmptArray(); } + +bool Chunk::Full() const noexcept { return GetHead()->capacity == GetHead()->num_entity; } +bool Chunk::Empty() const noexcept { return GetHead()->num_entity == 0; } + bool Chunk::HasAnyChange(std::span types, std::uint64_t version) const noexcept { const auto infos = GetHead()->GetCmptInfos(); for (const auto& type : types) { @@ -93,7 +103,7 @@ std::size_t Chunk::Erase(std::size_t idx) { } } - head->ForceUpdateVersion(head->archetype->Version()); + ForceUpdateVersion(head->archetype->Version()); entityNum--; @@ -143,8 +153,21 @@ std::tuple, Ubpa::small_vectorchunk_unsync_rsrc; } +std::pmr::monotonic_buffer_resource* Chunk::GetChunkUnsyncFrameResource() noexcept { return (std::pmr::monotonic_buffer_resource*)&GetHead()->chunk_unsync_frame_rsrc; } + +std::span Chunk::Head::GetCmptInfos() noexcept { return { (CmptInfo*)(this + 1), num_component }; } +std::span Chunk::Head::GetCmptInfos() const noexcept { return const_cast(this)->GetCmptInfos(); } + +void Chunk::ForceUpdateVersion(std::uint64_t version) { + Head* const head = GetHead(); + head->order_version = version; + for (auto& info : head->GetCmptInfos()) info.version = version; } + +Chunk::~Chunk() { GetHead()->~Head(); } + +Chunk::Head* Chunk::GetHead() noexcept { return reinterpret_cast(data); } +const Chunk::Head* Chunk::GetHead() const noexcept { return reinterpret_cast(data); } diff --git a/src/core/CmptLocator.cpp b/src/core/CmptLocator.cpp index c3ee77f..11c4c67 100644 --- a/src/core/CmptLocator.cpp +++ b/src/core/CmptLocator.cpp @@ -20,6 +20,10 @@ CmptLocator::CmptLocator(std::span types) { CmptLocator::CmptLocator() : hashCode{ TypeID_of.GetValue() } {} +std::size_t CmptLocator::GetValue() const noexcept { return hashCode; } + +const AccessTypeIDSet& CmptLocator::AccessTypeIDs() const noexcept { return cmptTypes; } + void CmptLocator::UpdateGetValue() noexcept { std::size_t rst = TypeID_of.GetValue(); for (const auto& type : cmptTypes) diff --git a/src/core/CmptsView.cpp b/src/core/CmptsView.cpp index 3e10a13..d09dbd8 100644 --- a/src/core/CmptsView.cpp +++ b/src/core/CmptsView.cpp @@ -2,6 +2,10 @@ using namespace Ubpa::UECS; +CmptsView::CmptsView() noexcept = default; + +CmptsView::CmptsView(std::span cmpts) noexcept : cmpts{ cmpts } {} + CmptAccessPtr CmptsView::GetCmpt(AccessTypeID t) const noexcept { for(const auto& cmpt : cmpts) { if (cmpt.AccessType() == t) @@ -9,3 +13,5 @@ CmptAccessPtr CmptsView::GetCmpt(AccessTypeID t) const noexcept { } return CmptAccessPtr::Invalid(); } + +std::span CmptsView::AccessComponents() const noexcept { return cmpts; } diff --git a/src/core/CommandBuffer.cpp b/src/core/CommandBuffer.cpp index e69de29..df6e8f6 100644 --- a/src/core/CommandBuffer.cpp +++ b/src/core/CommandBuffer.cpp @@ -0,0 +1,31 @@ +#include + +using namespace Ubpa::UECS; + +void CommandBuffer::AddCommand(std::function command) { commands.push_back(std::move(command)); } + +void CommandBuffer::AddCommandBuffer(CommandBuffer cb) { + commands.reserve(commands.size() + cb.commands.size()); + for (auto& cmd : cb.commands) + commands.push_back(std::move(cmd)); +} + +bool CommandBuffer::Empty() const noexcept { return commands.empty(); } + +void CommandBuffer::Clear() noexcept { commands.clear(); } + +std::span> CommandBuffer::GetCommands() noexcept { return commands; } + +std::span> CommandBuffer::GetCommands() const noexcept { + return const_cast(this)->GetCommands(); +} + +void CommandBuffer::Run() { + for (const auto& cmd : commands) + cmd(); + commands.clear(); +} + +CommandBufferPtr::CommandBufferPtr(CommandBuffer * cb) : commandBuffer{cb} {} +CommandBuffer* CommandBufferPtr::Get() const noexcept { return commandBuffer; } +CommandBuffer* CommandBufferPtr::operator->()const noexcept { return commandBuffer; } diff --git a/src/core/EntityMngr.cpp b/src/core/EntityMngr.cpp index 08f3530..a4fa840 100644 --- a/src/core/EntityMngr.cpp +++ b/src/core/EntityMngr.cpp @@ -71,13 +71,16 @@ bool EntityMngr::Have(Entity e, TypeID type) const { return entityTable[e.index].archetype->GetCmptTraits().GetTypes().contains(type); } -CmptAccessPtr EntityMngr::GetComponent(Entity e, AccessTypeID type) const { +CmptAccessPtr EntityMngr::AccessComponent(Entity e, AccessTypeID type) const { assert(!type.Is()); if (!Exist(e)) throw std::invalid_argument("Entity is invalid"); const auto& info = entityTable[e.index]; return info.archetype->At(type, { info.chunkIdx, info.idxInChunk }); } +CmptAccessPtr EntityMngr::WriteComponent(Entity e, TypeID t) const { return AccessComponent(e, { t, AccessMode::WRITE }); } +CmptAccessPtr EntityMngr::ReadComponent(Entity e, TypeID t) const { return AccessComponent(e, { t, AccessMode::LATEST }); } + bool EntityMngr::Exist(Entity e) const noexcept { return e.index < entityTable.size() && e.version == entityTable[e.index].version && entityTable[e.index].archetype; } @@ -260,13 +263,16 @@ void EntityMngr::Detach(Entity e, std::span types) { ts2a.emplace(std::move(dstTypeIDSet), std::unique_ptr{dstArchetype}); } -vector EntityMngr::Components(Entity e, AccessMode mode) const { +vector EntityMngr::AccessComponents(Entity e, AccessMode mode) const { if (!Exist(e)) throw std::invalid_argument("Entity is invalid"); const auto& info = entityTable[e.index]; - return info.archetype->Components({info.chunkIdx, info.idxInChunk}, mode); + return info.archetype->AccessComponents({info.chunkIdx, info.idxInChunk}, mode); } +std::vector EntityMngr::WriteComponents(Entity e) const { return AccessComponents(e, AccessMode::WRITE); } +std::vector EntityMngr::ReadComponents(Entity e) const { return AccessComponents(e, AccessMode::LATEST); } + Entity EntityMngr::Instantiate(Entity srcEntity) { if (!Exist(srcEntity)) throw std::invalid_argument("Entity is invalid"); @@ -331,12 +337,20 @@ void EntityMngr::Destroy(Entity e) { RecycleEntityEntry(e); } +std::size_t EntityMngr::TotalEntityNum() const noexcept +{ return entityTable.size() - entityTableFreeEntry.size(); } + +std::span EntityMngr::GetEntityFreeEntries() const noexcept +{ return { entityTableFreeEntry.data(), entityTableFreeEntry.size() }; } + +std::size_t EntityMngr::GetEntityVersion(std::size_t idx) const noexcept { return entityTable[idx].version; } + Ubpa::small_vector EntityMngr::LocateSingletons(const SingletonLocator& locator) const { std::size_t numSingletons = 0; small_vector rst; rst.reserve(locator.SingletonTypes().size()); for (const auto& t : locator.SingletonTypes()) { - auto ptr = GetSingleton(t); + auto ptr = AccessSingleton(t); if (ptr.Ptr() == nullptr) return {}; rst.push_back(ptr); @@ -576,7 +590,7 @@ void EntityMngr::Accept(IListener* listener) const { for (std::size_t j = 0; j < a->GetChunks()[i]->EntityNum(); j++) { auto e = *a->ReadAt({ i,j }); listener->EnterEntity(e); - for (const auto& cmpt : a->Components({ i,j }, AccessMode::WRITE)) { + for (const auto& cmpt : a->AccessComponents({ i,j }, AccessMode::WRITE)) { listener->EnterCmpt({ cmpt.AccessType(), cmpt.Ptr() }); listener->ExistCmpt({ cmpt.AccessType(), cmpt.Ptr() }); } @@ -609,7 +623,7 @@ Entity EntityMngr::GetSingletonEntity(TypeID t) const { return *archetype->ReadAt({ 0,0 }); } -CmptAccessPtr EntityMngr::GetSingleton(AccessTypeID access_type) const { +CmptAccessPtr EntityMngr::AccessSingleton(AccessTypeID access_type) const { ArchetypeFilter filter{ {access_type}, {}, {} }; EntityQuery query{ move(filter) }; const auto& archetypes = QueryArchetypes(query); @@ -629,6 +643,9 @@ CmptAccessPtr EntityMngr::GetSingleton(AccessTypeID access_type) const { return { access_type, nullptr }; } +CmptAccessPtr EntityMngr::WriteSingleton(TypeID type) const { return AccessSingleton({ type, AccessMode::WRITE }); } +CmptAccessPtr EntityMngr::ReadSingleton(TypeID type) const { return AccessSingleton({ type, AccessMode::LATEST }); } + void EntityMngr::NewFrame() noexcept { for (auto& [ts, a] : ts2a) a->NewFrame(); diff --git a/src/core/EntityQuery.cpp b/src/core/EntityQuery.cpp new file mode 100644 index 0000000..905fe1a --- /dev/null +++ b/src/core/EntityQuery.cpp @@ -0,0 +1,23 @@ +#include + +using namespace Ubpa::UECS; + +std::size_t EntityQuery::GetValue() const noexcept { return hash_combine(filter.GetValue(), locator.GetValue()); } + +bool EntityQuery::IsMatch(const small_flat_set& types) const noexcept { + return std::find_if_not(filter.all.begin(), filter.all.end(), + [&](const auto& type) { return types.contains(type); }) == filter.all.end() + && (filter.any.empty() + || std::find_if(filter.any.begin(), filter.any.end(), + [&](const auto& type) { return types.contains(type); }) != filter.any.end()) + && std::find_if(filter.none.begin(), filter.none.end(), + [&](const auto& type) { return types.contains(type); }) == filter.none.end() + && std::find_if_not(locator.AccessTypeIDs().begin(), locator.AccessTypeIDs().end(), + [&](const auto& type) { return types.contains(type); }) == locator.AccessTypeIDs().end(); +} + +namespace Ubpa::UECS { + bool operator==(const EntityQuery& lhs, const EntityQuery& rhs) noexcept { + return lhs.filter == rhs.filter && lhs.locator == rhs.locator; + } +} \ No newline at end of file diff --git a/src/core/Schedule.cpp b/src/core/Schedule.cpp index 209e620..f8d904b 100644 --- a/src/core/Schedule.cpp +++ b/src/core/Schedule.cpp @@ -57,6 +57,8 @@ Schedule& Schedule::Disable(std::string_view sys, int layer) { return *this; } +World* Schedule::GetWorld() const noexcept { return world; } + void Schedule::Clear() { for (auto& [layer, layerinfo] : layerInfos) { //auto alloc = std::pmr::polymorphic_allocator{ frame_rsrc.get() }; diff --git a/src/core/SingletonLocator.cpp b/src/core/SingletonLocator.cpp index 248ce18..429b936 100644 --- a/src/core/SingletonLocator.cpp +++ b/src/core/SingletonLocator.cpp @@ -3,11 +3,16 @@ using namespace Ubpa::UECS; using namespace std; +SingletonLocator::SingletonLocator(std::set types) : singletonTypes{ std::move(types) } {} +SingletonLocator::SingletonLocator() = default; + SingletonLocator::SingletonLocator(std::span types) { for (const auto& type : types) singletonTypes.insert(type); } +const std::set& SingletonLocator::SingletonTypes() const noexcept { return singletonTypes; } + bool SingletonLocator::HasWriteSingletonType() const noexcept { for (const auto& type : singletonTypes) { if (type.GetAccessMode() == AccessMode::WRITE) diff --git a/src/core/SingletonsView.cpp b/src/core/SingletonsView.cpp index 8679954..98b37be 100644 --- a/src/core/SingletonsView.cpp +++ b/src/core/SingletonsView.cpp @@ -2,7 +2,7 @@ using namespace Ubpa::UECS; -CmptAccessPtr SingletonsView::GetSingleton(AccessTypeID t) const noexcept { +CmptAccessPtr SingletonsView::AccessSingleton(AccessTypeID t) const noexcept { for (const auto& singleton : singletons) { if (singleton.AccessType() == t) return singleton; diff --git a/src/core/SystemFunc.cpp b/src/core/SystemFunc.cpp index b05b320..df316b1 100644 --- a/src/core/SystemFunc.cpp +++ b/src/core/SystemFunc.cpp @@ -2,7 +2,11 @@ using namespace Ubpa::UECS; -void SystemFunc::operator()(World* w, SingletonsView singletonsView, Entity e, std::size_t entityIndexInQuery, CmptsView cmptsView, CommandBufferView cbv) const { +std::string_view SystemFunc::Name() const noexcept { return name; } + +std::size_t SystemFunc::GetValue() const noexcept { return hashCode; } + +void SystemFunc::operator()(World* w, SingletonsView singletonsView, Entity e, std::size_t entityIndexInQuery, CmptsView cmptsView, CommandBufferPtr cb) const { assert(mode == Mode::Entity); return func( w, @@ -11,11 +15,11 @@ void SystemFunc::operator()(World* w, SingletonsView singletonsView, Entity e, s entityIndexInQuery, cmptsView, {}, - cbv + cb ); } -void SystemFunc::operator()(World* w, SingletonsView singletonsView, std::size_t entityBeginIndexInQuery, ChunkView chunkView, CommandBufferView cbv) const { +void SystemFunc::operator()(World* w, SingletonsView singletonsView, std::size_t entityBeginIndexInQuery, ChunkView chunkView, CommandBufferPtr cb) const { assert(mode == Mode::Chunk); return func( w, @@ -24,7 +28,7 @@ void SystemFunc::operator()(World* w, SingletonsView singletonsView, std::size_t entityBeginIndexInQuery, {}, chunkView, - cbv + cb ); } @@ -40,3 +44,9 @@ void SystemFunc::operator()(World* w, SingletonsView singletonsView) const { {} ); } + + +SystemFunc::Mode SystemFunc::GetMode() const noexcept { return mode; } +bool SystemFunc::IsParallel() const noexcept { return isParallel; } + +bool SystemFunc::operator==(const SystemFunc& sysFunc) const noexcept { return name == sysFunc.name; } diff --git a/src/core/World.cpp b/src/core/World.cpp index ee79e8c..dc0b011 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -373,6 +373,13 @@ void World::Accept(IListener* listener) const { listener->ExistWorld(this); } +synchronized_monotonic_buffer_resource* World::GetSyncFrameResource() { return sync_frame_rsrc.get(); } +std::pmr::monotonic_buffer_resource* World::GetUnsyncFrameResource() { return unsync_frame_rsrc.get(); } +std::pmr::synchronized_pool_resource* World::GetSyncResource() { return sync_rsrc.get(); } +std::pmr::unsynchronized_pool_resource* World::GetUnsyncResource() { return unsync_rsrc.get(); } + +std::uint64_t World::Version() const noexcept { return version; } + void World::AddCommand(std::function command, int layer) { std::lock_guard guard(commandBufferMutex); lcommandBuffer[layer].AddCommand(command); diff --git a/src/test/03_query_entity/main.cpp b/src/test/03_query_entity/main.cpp index 52c53c9..3172244 100644 --- a/src/test/03_query_entity/main.cpp +++ b/src/test/03_query_entity/main.cpp @@ -13,8 +13,8 @@ struct C {}; struct MySystem { static void OnUpdate(Schedule& schedule) { schedule.RegisterEntityJob( - [](World* w, Entity e, const A* a, const B* b, CommandBufferView cbv) { - cbv->AddCommand( + [](World* w, Entity e, const A* a, const B* b, CommandBufferPtr cb) { + cb->AddCommand( [e, w]() { if (!w->entityMngr.Have(e, TypeID_of)) { cout << "Attach C" << endl; @@ -26,8 +26,8 @@ struct MySystem { "AB" ); schedule.RegisterEntityJob( - [](World* w, Entity e, const A* a, const B* b, const C* c, CommandBufferView cbv) { - cbv->AddCommand( + [](World* w, Entity e, const A* a, const B* b, const C* c, CommandBufferPtr cb) { + cb->AddCommand( [e, w]() { if (w->entityMngr.Have(e, TypeID_of)) { cout << "Dettach C" << endl; diff --git a/src/test/23_syncpoint/main.cpp b/src/test/23_syncpoint/main.cpp index f4b295c..2f48a46 100644 --- a/src/test/23_syncpoint/main.cpp +++ b/src/test/23_syncpoint/main.cpp @@ -19,9 +19,9 @@ struct MoverSystem { } ); schedule.RegisterEntityJob( - [](World* w, Entity e, CommandBufferView cbv) { + [](World* w, Entity e, CommandBufferPtr cb) { std::cout << "Attach Velocity" << std::endl; - cbv->AddCommand([w, e]() { + cb->AddCommand([w, e]() { w->entityMngr.Attach(e, TypeIDs_of); w->entityMngr.WriteComponent(e)->val = 1.f; });