Skip to content

Commit

Permalink
copy/move schedule, Run* support CommandBufferView
Browse files Browse the repository at this point in the history
  • Loading branch information
Ubpa committed Mar 22, 2021
1 parent 7f7668d commit 8288be9
Show file tree
Hide file tree
Showing 8 changed files with 96 additions and 49 deletions.
6 changes: 6 additions & 0 deletions include/UECS/CommandBuffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ namespace Ubpa::UECS {

auto& GetCommands() noexcept { return commands; }
const auto& GetCommands() const noexcept { return commands; }

void Run() {
for (const auto& cmd : commands)
cmd();
commands.clear();
}
private:
std::vector<std::function<void()>> commands;
};
Expand Down
14 changes: 10 additions & 4 deletions include/UECS/Schedule.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ namespace Ubpa::UECS {
class SystemMngr;
class SysFuncGraph;

static constexpr int SpecialLayer = -std::numeric_limits<int>::max();

// [description]
// system infomation record
// - SystemFunc
Expand Down Expand Up @@ -117,12 +119,17 @@ namespace Ubpa::UECS {
Schedule& Disable(std::string_view sys, int layer = 0);

// clear every frame
std::pmr::monotonic_buffer_resource* GetFrameMonotonicResource() { return &frame_rsrc; }
std::pmr::monotonic_buffer_resource* GetFrameMonotonicResource() { return frame_rsrc.get(); }
template<typename T, typename... Args>
T* CreateFrameObject(Args&&... args) const;
std::string_view RegisterFrameString(std::string_view str);

~Schedule();
private:
Schedule();
Schedule(const Schedule&);
Schedule(Schedule&&) noexcept = default;
~Schedule();

template<typename... Args>
const SystemFunc* Request(int layer, Args&&...);

Expand Down Expand Up @@ -163,8 +170,7 @@ namespace Ubpa::UECS {

std::map<int, LayerInfo> layerInfos;

mutable std::pmr::monotonic_buffer_resource frame_rsrc; // release in every frame
std::string_view RegisterFrameString(std::string_view str);
std::unique_ptr<std::pmr::monotonic_buffer_resource> frame_rsrc; // release in every frame

friend class World;
};
Expand Down
4 changes: 4 additions & 0 deletions include/UECS/SystemFunc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
#include <functional>

namespace Ubpa::UECS {
class Schedule;

// [- description]
// system function registered by Schedule in <System>::OnUpdate(Schedule&)
// name + query(archetype filter + component locator) + singleton locator + function<...>
Expand Down Expand Up @@ -72,6 +74,8 @@ namespace Ubpa::UECS {

bool operator==(const SystemFunc& sysFunc) const noexcept { return name == sysFunc.name; }
private:
friend class Schedule;
SystemFunc(const SystemFunc&) = default;
Mode mode;
std::string_view name;
std::size_t hashCode; // after name
Expand Down
11 changes: 4 additions & 7 deletions include/UECS/World.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,7 @@ namespace Ubpa::UECS {
// SystemMngr + EntityMngr
class World {
public:
World() :
jobRsrc{ std::make_unique<std::pmr::unsynchronized_pool_resource>() },
systemMngr { this } {}
// not copy/move schedule, so you can't use DumpUpdateJobGraph() and GenUpdateFrameGraph() before Update()
World();
World(const World&);
World(World&&) noexcept;
~World();
Expand Down Expand Up @@ -57,7 +54,7 @@ namespace Ubpa::UECS {
// <tagged-components>: [const] <Cmpt>*...
// CmptsView
template<typename Func>
void RunEntityJob(
CommandBuffer RunEntityJob(
Func&&,
bool isParallel = true,
ArchetypeFilter = {},
Expand Down Expand Up @@ -91,7 +88,7 @@ namespace Ubpa::UECS {
// std::size_t entityBeginIndexInQuery
// ChunkView (necessary)
template<typename Func>
void RunChunkJob(
CommandBuffer RunChunkJob(
Func&&,
ArchetypeFilter = {},
bool isParallel = true,
Expand Down Expand Up @@ -136,7 +133,7 @@ namespace Ubpa::UECS {
std::mutex commandBufferMutex;
void RunCommands(int layer);

void Run(SystemFunc*);
CommandBuffer Run(SystemFunc*);

std::pmr::synchronized_pool_resource frame_sync_rsrc;
};
Expand Down
5 changes: 3 additions & 2 deletions include/UECS/details/Schedule.inl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace Ubpa::UECS {
template<typename T, typename... Args>
T* Schedule::CreateFrameObject(Args&&... args) const {
void* buffer = frame_rsrc.allocate(sizeof(T), alignof(T));
void* buffer = frame_rsrc->allocate(sizeof(T), alignof(T));
return new(buffer)T(std::forward<Args>(args)...);
}

Expand Down Expand Up @@ -111,7 +111,8 @@ namespace Ubpa::UECS {

template<typename... Args>
const SystemFunc* Schedule::Request(int layer, Args&&... args) {
SystemFunc* sysFunc = (SystemFunc*)frame_rsrc.allocate(sizeof(SystemFunc), alignof(SystemFunc));
assert(layer != SpecialLayer);
SystemFunc* sysFunc = (SystemFunc*)frame_rsrc->allocate(sizeof(SystemFunc), alignof(SystemFunc));
new(sysFunc)SystemFunc(std::forward<Args>(args)...);
layerInfos[layer].sysFuncs.emplace(sysFunc->GetValue(), sysFunc);
return sysFunc;
Expand Down
14 changes: 9 additions & 5 deletions include/UECS/details/World.inl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Ubpa::UECS {
template<typename Func>
void World::RunEntityJob(
CommandBuffer World::RunEntityJob(
Func&& func,
bool isParallel,
ArchetypeFilter filter,
Expand All @@ -19,7 +19,7 @@ namespace Ubpa::UECS {
{},
isParallel
};
Run(&sys);
return Run(&sys);
}

template<typename Func>
Expand All @@ -35,6 +35,8 @@ namespace Ubpa::UECS {
"const RunEntityJob should use const World*");
static_assert(Length_v<Filter_t<ArgList, IsWrite>> == 0,
"const RunEntityJob can't write cmpt");
static_assert(!Contain_v<ArgList, CommandBufferView>,
"const RunEntityJob shouldn't use CommandBufferView");
assert("const RunEntityJob can't write cmpt"
&& !cmptLocator.HasWriteTypeID());

Expand All @@ -48,7 +50,7 @@ namespace Ubpa::UECS {
}

template<typename Func>
void World::RunChunkJob(
CommandBuffer World::RunChunkJob(
Func&& func,
ArchetypeFilter filter,
bool isParallel,
Expand All @@ -63,7 +65,7 @@ namespace Ubpa::UECS {
{},
isParallel
};
Run(&sys);
return Run(&sys);
}

template<typename Func>
Expand All @@ -74,8 +76,10 @@ namespace Ubpa::UECS {
SingletonLocator singletonLocator
) const {
using ArgList = FuncTraits_ArgList<Func>;
static_assert(Contain_v<ArgList, World*> == 0,
static_assert(!Contain_v<ArgList, World*>,
"const RunChunkJob should use const World*");
static_assert(!Contain_v<ArgList, CommandBufferView>,
"const RunChunkJob shouldn't use CommandBufferView");
assert("const RunChunkJob can't write cmpt"
&& !filter.HaveWriteTypeID());

Expand Down
43 changes: 30 additions & 13 deletions src/core/Schedule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,51 @@ using namespace Ubpa;
using namespace Ubpa::UECS;
using namespace std;

Schedule::~Schedule() {
Clear();
Schedule::Schedule() : frame_rsrc{ std::make_unique<std::pmr::monotonic_buffer_resource>() } {}

Schedule::~Schedule() { Clear(); }

Schedule::Schedule(const Schedule& other) :
frame_rsrc{ std::make_unique<std::pmr::monotonic_buffer_resource>() },
layerInfos{ other.layerInfos }
{
for (auto& [layer, info] : layerInfos) {
for (auto& [id, sys] : info.sysFuncs) {
sys = CreateFrameObject<SystemFunc>(*sys);
sys->name = RegisterFrameString(sys->Name());
}
}
}

std::string_view Schedule::RegisterFrameString(std::string_view str) {
auto* buffer = (char*)frame_rsrc.allocate((str.size() + 1) * sizeof(char), alignof(char));
auto* buffer = (char*)frame_rsrc->allocate((str.size() + 1) * sizeof(char), alignof(char));
std::memcpy(buffer, str.data(), str.size() * sizeof(char));
buffer[str.size()] = 0;
return str;
}

Schedule& Schedule::Order(string_view x, string_view y, int layer) {
assert(layer != SpecialLayer);
layerInfos[layer].sysFuncOrder.emplace(SystemFunc::GetValue(x), SystemFunc::GetValue(y));
return *this;
}

Schedule& Schedule::AddNone(string_view sys, TypeID type, int layer) {
assert(layer != SpecialLayer);
std::size_t hashcode = SystemFunc::GetValue(sys);
layerInfos[layer].sysNones[hashcode].push_back(type);
return *this;
}

Schedule& Schedule::Disable(std::string_view sys, int layer) {
assert(layer != SpecialLayer);
layerInfos[layer].disabledSysFuncs.insert(SystemFunc::GetValue(sys));
return *this;
}

void Schedule::Clear() {
for (auto& [layer, layerinfo] : layerInfos) {
//auto alloc = std::pmr::polymorphic_allocator<SystemFunc>{ &frame_rsrc };
//auto alloc = std::pmr::polymorphic_allocator<SystemFunc>{ frame_rsrc.get() };
for (const auto& [hash, sysFunc] : layerinfo.sysFuncs) {
sysFunc->~SystemFunc();
// no need to deallocate
Expand All @@ -47,21 +62,22 @@ void Schedule::Clear() {
layerinfo.sysNones.clear();
}
layerInfos.clear();
frame_rsrc.release();
frame_rsrc->release();
}

Schedule::CmptSysFuncsMap* Schedule::GenCmptSysFuncsMap(int layer) const {
assert(layer != SpecialLayer);
const auto& layerinfo = layerInfos.at(layer);
const auto& sysFuncs = layerinfo.sysFuncs;
const auto& disabledSysFuncs = layerinfo.disabledSysFuncs;

CmptSysFuncsMap* rst = CreateFrameObject<CmptSysFuncsMap>(CmptSysFuncsMap::allocator_type{ &frame_rsrc });
CmptSysFuncsMap* rst = CreateFrameObject<CmptSysFuncsMap>(CmptSysFuncsMap::allocator_type{ frame_rsrc.get() });
for (const auto& [hashcode, sysFunc] : sysFuncs) {
if (disabledSysFuncs.contains(hashcode))
continue;

for (const auto& type : sysFunc->entityQuery.locator.AccessTypeIDs()) {
auto& cmptSysFuncs = rst->try_emplace(type, &frame_rsrc).first->second;
auto& cmptSysFuncs = rst->try_emplace(type, frame_rsrc.get()).first->second;
switch (type.GetAccessMode())
{
case AccessMode::LAST_FRAME:
Expand All @@ -79,7 +95,7 @@ Schedule::CmptSysFuncsMap* Schedule::GenCmptSysFuncsMap(int layer) const {
}
}
for (const auto& type : sysFunc->singletonLocator.SingletonTypes()) {
auto& cmptSysFuncs = rst->try_emplace(type, &frame_rsrc).first->second;
auto& cmptSysFuncs = rst->try_emplace(type, frame_rsrc.get()).first->second;
switch (type.GetAccessMode())
{
case AccessMode::LAST_FRAME:
Expand All @@ -97,7 +113,7 @@ Schedule::CmptSysFuncsMap* Schedule::GenCmptSysFuncsMap(int layer) const {
}
}
for (const auto& type : sysFunc->randomAccessor.types) {
auto& cmptSysFuncs = rst->try_emplace(type, &frame_rsrc).first->second;
auto& cmptSysFuncs = rst->try_emplace(type, frame_rsrc.get()).first->second;
switch (type.GetAccessMode())
{
case AccessMode::LAST_FRAME:
Expand All @@ -118,7 +134,7 @@ Schedule::CmptSysFuncsMap* Schedule::GenCmptSysFuncsMap(int layer) const {
if (sysFunc->GetMode() == SystemFunc::Mode::Chunk) {
const auto& filter = sysFunc->entityQuery.filter;
for (const auto& type : filter.all) {
auto& cmptSysFuncs = rst->try_emplace(type, &frame_rsrc).first->second;
auto& cmptSysFuncs = rst->try_emplace(type, frame_rsrc.get()).first->second;
switch (type.GetAccessMode())
{
case AccessMode::LAST_FRAME:
Expand All @@ -137,7 +153,7 @@ Schedule::CmptSysFuncsMap* Schedule::GenCmptSysFuncsMap(int layer) const {
}

for (const auto& type : filter.any) {
auto& cmptSysFuncs = rst->try_emplace(type, &frame_rsrc).first->second;
auto& cmptSysFuncs = rst->try_emplace(type, frame_rsrc.get()).first->second;
switch (type.GetAccessMode())
{
case AccessMode::LAST_FRAME:
Expand All @@ -160,6 +176,7 @@ Schedule::CmptSysFuncsMap* Schedule::GenCmptSysFuncsMap(int layer) const {
}

SysFuncGraph* Schedule::GenSysFuncGraph(int layer) const {
assert(layer != SpecialLayer);
const auto& layerinfo = layerInfos.at(layer);
const auto& sysNones = layerinfo.sysNones;
const auto& sysFuncs = layerinfo.sysFuncs;
Expand All @@ -182,7 +199,7 @@ SysFuncGraph* Schedule::GenSysFuncGraph(int layer) const {
CmptSysFuncsMap* cmptSysFuncsMap = GenCmptSysFuncsMap(layer); // use frame rsrc, no need to release

// [gen graph]
SysFuncGraph* graph = CreateFrameObject<SysFuncGraph>(&frame_rsrc);
SysFuncGraph* graph = CreateFrameObject<SysFuncGraph>(frame_rsrc.get());

// [gen graph] - vertex
for (const auto& [hashcode, sysFunc] : sysFuncs) {
Expand Down Expand Up @@ -228,7 +245,7 @@ SysFuncGraph* Schedule::GenSysFuncGraph(int layer) const {
if (cmptSysFuncs.writeSysFuncs.empty())
continue;

SysFuncGraph* subgraph = CreateFrameObject<SysFuncGraph>(&frame_rsrc);
SysFuncGraph* subgraph = CreateFrameObject<SysFuncGraph>(frame_rsrc.get());
graph->SubGraph(*subgraph, std::span{ cmptSysFuncs.writeSysFuncs.data(), cmptSysFuncs.writeSysFuncs.size() });
auto [success, sorted_wirtes] = subgraph->Toposort();
assert(success);
Expand Down
Loading

0 comments on commit 8288be9

Please sign in to comment.