Skip to content

Commit

Permalink
EntityMngr += copy and swap
Browse files Browse the repository at this point in the history
  • Loading branch information
Ubpa committed Sep 1, 2020
1 parent 3cbed3e commit 5198f46
Show file tree
Hide file tree
Showing 17 changed files with 157 additions and 21 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.14 FATAL_ERROR)

project(UECS VERSION 0.12.1)
project(UECS VERSION 0.12.2)
message(STATUS "[Project] ${PROJECT_NAME}")

include(cmake/InitUCMake.cmake)
Expand Down
9 changes: 6 additions & 3 deletions include/UECS/EntityMngr.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,11 @@ namespace Ubpa::UECS {
// - when free entries is empty, use new entity entry (version is 0)
class EntityMngr {
public:
RTDCmptTraits cmptTraits;
EntityMngr(World* world) : world{ world } {}
EntityMngr(const EntityMngr& em);

// same world
void Swap(EntityMngr& rhs) noexcept;

template<typename... Cmpts>
std::tuple<Entity, Cmpts*...> Create();
Expand Down Expand Up @@ -91,12 +95,11 @@ namespace Ubpa::UECS {

private:
Pool<Chunk> sharedChunkPool; // destruct finally
World* world;

friend class World;
friend class Archetype;

EntityMngr() = default;

static bool IsSet(const CmptType* types, size_t num) noexcept;

template<typename... Cmpts>
Expand Down
1 change: 1 addition & 0 deletions include/UECS/System.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Ubpa::UECS {
class World;

// stateless
class System {
public:
System(World* world, std::string name) noexcept : world{ world }, name{ name } {}
Expand Down
1 change: 1 addition & 0 deletions include/UECS/World.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ namespace Ubpa::UECS {

SystemMngr systemMngr;
EntityMngr entityMngr;
RTDCmptTraits cmptTraits;

// 1. schedule: run registered System's static OnUpdate(Schedule&)
// 2. gen job graph: schedule -> graph
Expand Down
3 changes: 3 additions & 0 deletions include/UECS/detail/Archetype.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ namespace Ubpa::UECS {
template<typename... Cmpts>
Archetype(EntityMngr*, TypeList<Cmpts...>);

// copy
Archetype(EntityMngr*, const Archetype&);

~Archetype();

// auto add Entity, use RTDCmptTraits
Expand Down
41 changes: 38 additions & 3 deletions src/core/Archetype.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include <UECS/detail/Archetype.h>

#include <UECS/World.h>

#include <UECS/EntityMngr.h>

using namespace Ubpa::UECS;
Expand Down Expand Up @@ -27,6 +29,39 @@ Archetype::~Archetype() {
entityMngr->sharedChunkPool.Recycle(chunk);
}

Archetype::Archetype(EntityMngr* em, const Archetype& src)
: entityMngr{ em }
{
types = src.types;
cmptTraits = src.cmptTraits;
type2offset = src.type2offset;
entityNum = src.entityNum;
chunkCapacity = src.chunkCapacity;

chunks.resize(src.chunks.size(), nullptr);
for (size_t i = 0; i < src.chunks.size(); i++) {
auto srcChunk = src.chunks[i];
auto dstChunk = chunks[i] = entityMngr->sharedChunkPool.Request();
size_t num = src.EntityNumOfChunk(i);
for (auto type : types.data) {
auto offset = Offsetof(type);
auto srcBegin = srcChunk->Data() + offset;
auto dstBegin = dstChunk->Data() + offset;
auto size = cmptTraits.Sizeof(type);
auto target = cmptTraits.copy_constructors.find(type);
if (target != cmptTraits.copy_constructors.end()) {
const auto& copy_ctor = target->second;
for (size_t j = 0; j < num; j++) {
auto offset_j = j * size;
copy_ctor(dstBegin + offset_j, srcBegin + offset_j);
}
}
else
memcpy(dstBegin, srcBegin, num * size);
}
}
}

void Archetype::SetLayout() {
vector<size_t> alignments;
vector<size_t> sizes;
Expand Down Expand Up @@ -58,7 +93,7 @@ Archetype* Archetype::New(EntityMngr* entityMngr, const CmptType* types, size_t
rst->types.data.insert(CmptType::Of<Entity>);
rst->cmptTraits.Register<Entity>();
for (size_t i = 0; i < num; i++)
rst->cmptTraits.Register(entityMngr->cmptTraits, types[i]);
rst->cmptTraits.Register(entityMngr->world->cmptTraits, types[i]);
rst->SetLayout();
return rst;
}
Expand All @@ -73,7 +108,7 @@ Archetype* Archetype::Add(const Archetype* from, const CmptType* types, size_t n
rst->cmptTraits = from->cmptTraits;
rst->types.Insert(types, num);
for (size_t i = 0; i < num; i++)
rst->cmptTraits.Register(rst->entityMngr->cmptTraits, types[i]);
rst->cmptTraits.Register(rst->entityMngr->world->cmptTraits, types[i]);

rst->SetLayout();

Expand Down Expand Up @@ -102,7 +137,7 @@ size_t Archetype::Create(Entity e) {
size_t idxInChunk = idx % chunkCapacity;
byte* buffer = chunks[idx / chunkCapacity]->Data();

const auto& rtdct = entityMngr->cmptTraits;
const auto& rtdct = entityMngr->world->cmptTraits;
for (const auto& type : types.data) {
if (type.Is<Entity>()) {
constexpr size_t size = sizeof(Entity);
Expand Down
50 changes: 46 additions & 4 deletions src/core/EntityMngr.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <UECS/EntityMngr.h>

#include <UECS/World.h>
#include <UECS/IListener.h>

using namespace Ubpa::UECS;
Expand All @@ -17,6 +18,48 @@ size_t EntityMngr::RequestEntityFreeEntry() {
return entry;
}

EntityMngr::EntityMngr(const EntityMngr& em)
: world{ em.world }
{
ts2a.reserve(em.ts2a.size());
for (const auto& [ts, a] : em.ts2a) {
auto [iter, success] = ts2a.try_emplace(ts, std::make_unique<Archetype>(this, *a));
assert(success);
}
entityTableFreeEntry = em.entityTableFreeEntry;
entityTable.resize(em.entityTable.size());
for (size_t i = 0; i < em.entityTable.size(); i++) {
auto& dst = entityTable[i];
const auto& src = em.entityTable[i];
dst.idxInArchetype = src.idxInArchetype;
dst.version = src.version;
dst.archetype = ts2a.find(src.archetype->types)->second.get();
}
queryCache.reserve(em.queryCache.size());
for (const auto& [query, srcArchetypes] : em.queryCache) {
auto& dstArchetypes = queryCache[query];
for (auto archetype : srcArchetypes)
dstArchetypes.insert(ts2a.find(archetype->types)->second.get());
}
}

void EntityMngr::Swap(EntityMngr& rhs) noexcept {
assert(world == rhs.world);

using std::swap;

swap(ts2a, rhs.ts2a);
swap(entityTableFreeEntry, rhs.entityTableFreeEntry);
swap(entityTable, rhs.entityTable);
swap(queryCache, rhs.queryCache);

auto pool = std::move(sharedChunkPool);
sharedChunkPool.~Pool();
new(&sharedChunkPool)Pool<Chunk>(std::move(rhs.sharedChunkPool));
rhs.sharedChunkPool.~Pool();
new(&rhs.sharedChunkPool)Pool<Chunk>(std::move(pool));
}

void EntityMngr::RecycleEntityEntry(Entity e) {
assert(Exist(e));

Expand Down Expand Up @@ -115,8 +158,8 @@ void EntityMngr::Attach(Entity e, const CmptType* types, size_t num) {
if (origArchetype->GetCmptTypeSet().Contains(type))
continue;

auto target = cmptTraits.default_constructors.find(type);
if (target == cmptTraits.default_constructors.end())
auto target = world->cmptTraits.default_constructors.find(type);
if (target == world->cmptTraits.default_constructors.end())
continue;

target->second(info.archetype->At(type, info.idxInArchetype));
Expand Down Expand Up @@ -354,13 +397,12 @@ void EntityMngr::GenChunkJob(World* w, Job* job, SystemFunc* sys) const {
assert(job != nullptr);
for (Archetype* archetype : QueryArchetypes(sys->entityQuery)) {
size_t chunkNum = archetype->ChunkNum();
SingletonsView singletonsView{ singletons.data(), singletons.size() };

for (size_t i = 0; i < chunkNum; i++) {
job->emplace([=, singletons = singletons]() {
(*sys)(
w,
singletonsView,
SingletonsView{ singletons.data(), singletons.size() },
ChunkView{ archetype, i }
);
});
Expand Down
4 changes: 2 additions & 2 deletions src/core/World.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ using namespace Ubpa::UECS;
using namespace Ubpa;
using namespace std;

World::World() : systemMngr{ this } {}
World::World() : systemMngr{ this }, entityMngr{ this } {}

void World::Update() {
schedule.Clear();
Expand Down Expand Up @@ -118,7 +118,7 @@ UGraphviz::Graph World::GenUpdateFrameGraph() const {
unordered_map<size_t, size_t> sysFuncHashcode2idx;

auto queryCmptName = [this](CmptType type) -> string {
auto cmptName = entityMngr.cmptTraits.Nameof(type);
auto cmptName = cmptTraits.Nameof(type);
return cmptName.empty() ? std::to_string(type.HashCode()) : string{ cmptName };
};

Expand Down
2 changes: 1 addition & 1 deletion src/test/02_order/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ int main() {
World w;
w.systemMngr.Register<DataSystem>();

w.entityMngr.cmptTraits.Register<
w.cmptTraits.Register<
Data1,
Data2
>();
Expand Down
2 changes: 1 addition & 1 deletion src/test/11_runtime_cmpt/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ int main() {

World w;
w.systemMngr.Register<RTDSystem>();
w.entityMngr.cmptTraits
w.cmptTraits
.RegisterSize(type, 8)
.RegisterDefaultConstructor(type, [](void*) { cout << "construct" << endl; })
.RegisterDestructor(type, [](void*) { cout << "destruct" << endl; });
Expand Down
2 changes: 1 addition & 1 deletion src/test/12_framegraph/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ int main() {
World w;
w.systemMngr.Register<MySystem>();

w.entityMngr.cmptTraits
w.cmptTraits
.RegisterName(CmptType::Of<A>, "A")
.RegisterName(CmptType::Of<B>, "B")
.RegisterName(CmptType::Of<C>, "C")
Expand Down
4 changes: 2 additions & 2 deletions src/test/14_serialize/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ class Dumper : public IListener {
cout << "{" << endl;
indent++;
PrintIndent();
cout << "\"type\" : \"" << w->entityMngr.cmptTraits.Nameof(cmpt->Type()) << "\"";
cout << "\"type\" : \"" << w->cmptTraits.Nameof(cmpt->Type()) << "\"";
if (cmpt->Type().Is<Velocity>()) {
auto v = cmpt->As<Velocity>();
cout << "," << endl;
Expand Down Expand Up @@ -167,7 +167,7 @@ class MoverSystem : public System {

int main() {
World w;
w.entityMngr.cmptTraits.Register<Position, Velocity>();
w.cmptTraits.Register<Position, Velocity>();
w.systemMngr.Register<MoverSystem>();
w.entityMngr.Create<Position, Velocity>();
w.entityMngr.Create<Position>();
Expand Down
2 changes: 1 addition & 1 deletion src/test/15_chunk_job/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ int main() {
World w;
w.systemMngr.Register<SAB_System>();

w.entityMngr.cmptTraits.Register<S, A, B>();
w.cmptTraits.Register<S, A, B>();

w.entityMngr.Create<S>();
w.entityMngr.Create<S, A>();
Expand Down
2 changes: 1 addition & 1 deletion src/test/16_singleton/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ int main() {
w.systemMngr.Register<MoverSystem>();
w.entityMngr.Create<Position, Velocity>();
w.entityMngr.Create<Timer>();
w.entityMngr.cmptTraits.Register
w.cmptTraits.Register
<Timer, Velocity, Position>();

w.Update();
Expand Down
2 changes: 1 addition & 1 deletion src/test/17_serial/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ int main() {
w.entityMngr.Create<A, B>();
w.entityMngr.Create<A, C>();
w.entityMngr.Create<A, B, C>();
w.entityMngr.cmptTraits.Register
w.cmptTraits.Register
<A, B, C>();

for (size_t i = 0; i < 5; i++) {
Expand Down
6 changes: 6 additions & 0 deletions src/test/18_copy/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Ubpa_GetTargetName(core "${PROJECT_SOURCE_DIR}/src/core")
Ubpa_AddTarget(
TEST
MODE EXE
LIB ${core}
)
45 changes: 45 additions & 0 deletions src/test/18_copy/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#include <UECS/World.h>

#include <iostream>

using namespace Ubpa::UECS;

struct Position { float val{ 0.f }; };
struct Velocity { float val{ 1.f }; };

class MoverSystem : public System {
public:
using System::System;

virtual void OnUpdate(Schedule& schedule) override {
schedule.RegisterEntityJob(
[](const Velocity* v, Position* p) {
p->val += v->val;
},
"Mover"
);
schedule.RegisterEntityJob(
[](const Velocity* v, const Position* p) {
std::cout << "v:" << v->val << std::endl;
std::cout << "p:" << p->val << std::endl;
},
"Print"
);
}
};

int main() {
World w;
w.systemMngr.Register<MoverSystem>();
w.entityMngr.Create<Position, Velocity>();

auto copy_e = w.entityMngr;

w.entityMngr.Swap(copy_e);
w.Update();
w.entityMngr.Create<Position, Velocity>();
w.Update();
std::cout << "swap" << std::endl;
w.entityMngr.Swap(copy_e);
w.Update();
}

0 comments on commit 5198f46

Please sign in to comment.