Skip to content

Commit 956453f

Browse files
committed
feat: Parallel system execution
1 parent f45ca6c commit 956453f

File tree

14 files changed

+701
-71
lines changed

14 files changed

+701
-71
lines changed

ecsact/entt/execution.hh

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ struct actions_map {
6868
}
6969

7070
template<typename Action>
71-
auto as_action_span() -> std::span<const Action*> {
71+
auto as_action_span() const -> const std::span<const Action* const> {
7272
ecsact_action_id action_id = Action::id;
7373

7474
if(!raw_value.contains(action_id)) {
@@ -78,8 +78,8 @@ struct actions_map {
7878
auto& action_data_list = raw_value.at(action_id);
7979
auto action_list_data_ptr = action_data_list.data();
8080

81-
return std::span<const Action*>{
82-
reinterpret_cast<const Action**>(action_list_data_ptr),
81+
return std::span<const Action* const>{
82+
reinterpret_cast<const Action* const*>(action_list_data_ptr),
8383
action_data_list.size(),
8484
};
8585
}
@@ -94,7 +94,8 @@ struct actions_map {
9494
template<typename System>
9595
auto execute_system( //
9696
::entt::registry& registry,
97-
ecsact_system_execution_context* parent
97+
ecsact_system_execution_context* parent,
98+
const ecsact::entt::actions_map& actions_map
9899
) -> void {
99100
static_assert(detail::unimplemented_by_codegen<System>, R"(
100101
-----------------------------------------------------------------------------
@@ -114,8 +115,9 @@ auto execute_system( //
114115
*/
115116
template<typename Action>
116117
auto execute_actions( //
117-
::entt::registry& registry,
118-
std::span<Action const*> action_range
118+
::entt::registry& registry,
119+
ecsact_system_execution_context* parent,
120+
const ecsact::entt::actions_map& actions_map
119121
) -> void {
120122
static_assert(detail::unimplemented_by_codegen<Action>, R"(
121123
-----------------------------------------------------------------------------
@@ -126,6 +128,12 @@ auto execute_actions( //
126128
)");
127129
}
128130

131+
using execute_fn_t = void (*)(
132+
::entt::registry& registry,
133+
ecsact_system_execution_context* parent,
134+
const ecsact::entt::actions_map& actions_map
135+
);
136+
129137
/**
130138
* Allocates EnTT groups and storage if necessary for the system or action.
131139
* NOTE: Template specializations are made available via the codegen plugin

ecsact/entt/wrapper/core.hh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,15 @@ inline auto prepare_component(ecsact_registry_id registry_id) -> void {
411411
}
412412
}
413413

414+
template<typename S>
415+
inline auto prepare_system(ecsact_registry_id registry_id) -> void {
416+
using namespace ecsact::entt::detail;
417+
auto& reg = ecsact::entt::get_registry(registry_id);
418+
419+
reg.template storage<system_sorted<S>>();
420+
reg.template storage<pending_lazy_execution<S>>();
421+
}
422+
414423
template<typename C, typename V>
415424
auto has_component_changed(entt::entity_id entity, V& view) -> bool {
416425
using detail::exec_itr_beforechange_storage;

rt_entt_codegen/core/BUILD.bazel

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ cc_library(
1111

1212
# keep sorted
1313
_CORE_CODEGEN_METHODS = {
14-
"execute_systems": [],
14+
"execute_systems": [
15+
"//rt_entt_codegen/shared:parallel",
16+
],
1517
"create_registry": [],
1618
"entity_matches": [
1719
"//rt_entt_codegen/shared:sorting",
@@ -22,6 +24,7 @@ _CORE_CODEGEN_METHODS = {
2224
"//rt_entt_codegen/shared:comps_with_caps",
2325
"//rt_entt_codegen/shared:sorting",
2426
"//rt_entt_codegen/shared:system_util",
27+
"//rt_entt_codegen/shared:parallel",
2528
"@entt//:entt",
2629
"@ecsact_rt_entt//:lib",
2730
],

rt_entt_codegen/core/core.hh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@
66

77
namespace ecsact::rt_entt_codegen::core {
88

9+
auto print_parallel_system_execute(
10+
codegen_plugin_context& ctx,
11+
const ecsact_entt_details& details
12+
) -> void;
13+
914
auto print_execute_systems( //
1015
codegen_plugin_context& ctx,
1116
const ecsact_entt_details& details

rt_entt_codegen/core/execute_systems.cc

Lines changed: 92 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,44 @@
11
#include "core.hh"
22

3+
#include "rt_entt_codegen/shared/parallel.hh"
34
#include "ecsact/lang-support/lang-cc.hh"
45
#include "rt_entt_codegen/shared/util.hh"
56
#include "ecsact/cpp_codegen_plugin_util.hh"
67

78
constexpr auto METHOD_BODY_TOP = R"(
8-
auto& reg = ecsact::entt::get_registry(registry_id);
9-
auto actions = ecsact::entt::actions_map{};
9+
auto& registry = ecsact::entt::get_registry(registry_id);
10+
auto actions_map = ecsact::entt::actions_map{};
1011
)";
1112

13+
auto ecsact::rt_entt_codegen::core::print_parallel_system_execute(
14+
codegen_plugin_context& ctx,
15+
const ecsact_entt_details& details
16+
) -> void {
17+
using ecsact::cc_lang_support::cpp_identifier;
18+
using ecsact::cpp_codegen_plugin_util::block;
19+
using ecsact::rt_entt_codegen::util::method_printer;
20+
21+
ctx.write("template<std::size_t N>\n");
22+
auto printer = //
23+
method_printer{ctx, "execute_parallel_cluster"} //
24+
.parameter("::entt::registry&", "registry")
25+
.parameter("ecsact_system_execution_context*", "parent_context")
26+
.parameter("std::array<exec_entry_t, N>", "system_arr")
27+
.return_type("void");
28+
29+
block(
30+
ctx,
31+
"std::for_each(std::execution::par_unseq, system_arr.begin(), "
32+
"system_arr.end(), [&registry](exec_entry_t pair)",
33+
[&]() {
34+
ctx.write("auto fn_ptr = pair.first;\n");
35+
ctx.write("auto& actions_map = pair.second;\n");
36+
ctx.write("fn_ptr(registry, nullptr, actions_map);");
37+
}
38+
);
39+
ctx.write(");\n");
40+
}
41+
1242
auto ecsact::rt_entt_codegen::core::print_execute_systems( //
1343
codegen_plugin_context& ctx,
1444
const ecsact_entt_details& details
@@ -33,7 +63,9 @@ auto ecsact::rt_entt_codegen::core::print_execute_systems( //
3363
ctx.indentation += 1;
3464
ctx.write("\n");
3565

36-
ctx.write("actions.collect(i, execution_count, execution_options_list);\n");
66+
ctx.write( //
67+
"actions_map.collect(i, execution_count, execution_options_list);\n"
68+
);
3769

3870
block(ctx, "if(execution_options_list != nullptr)", [&] {
3971
ctx.write(
@@ -45,26 +77,65 @@ auto ecsact::rt_entt_codegen::core::print_execute_systems( //
4577
});
4678
});
4779

48-
for(auto sys_like : details.top_execution_order) {
49-
auto cpp_decl_name = cpp_identifier(ecsact::meta::decl_full_name(sys_like));
80+
auto parallel_system_cluster =
81+
ecsact::rt_entt_codegen::parallel::get_parallel_execution_cluster(
82+
ctx,
83+
details,
84+
details.top_execution_order
85+
);
5086

51-
if(details.is_action(sys_like)) {
52-
ctx.write(
53-
"ecsact::entt::execute_actions<",
54-
cpp_decl_name,
55-
">(reg, actions.as_action_span<",
56-
cpp_decl_name,
57-
">());\n"
58-
);
59-
} else if(details.is_system(sys_like)) {
60-
ctx.write(
61-
"ecsact::entt::execute_system<",
62-
cpp_decl_name,
63-
">(reg, nullptr);\n"
64-
);
65-
} else {
66-
ctx.write("// ??? unhandled ??? ", cpp_decl_name, "\n");
87+
for(const auto& systems_to_parallel : parallel_system_cluster) {
88+
if(systems_to_parallel.size() == 1) {
89+
auto sync_sys_id = systems_to_parallel[0];
90+
91+
auto sync_sys_name =
92+
cpp_identifier(ecsact::meta::decl_full_name(sync_sys_id));
93+
94+
if(details.is_action(sync_sys_id)) {
95+
ctx.write(std::format(
96+
"ecsact::entt::execute_actions<{}>(registry, {}, "
97+
"actions_map);\n",
98+
sync_sys_name,
99+
"nullptr"
100+
));
101+
}
102+
if(details.is_system(sync_sys_id)) {
103+
ctx.write(std::format(
104+
"ecsact::entt::execute_system<{}>(registry, {}, "
105+
"actions_map);\n",
106+
sync_sys_name,
107+
"nullptr"
108+
));
109+
}
110+
continue;
111+
}
112+
113+
ctx.write("execute_parallel_cluster(registry, nullptr, ");
114+
ctx.write(std::format(
115+
"std::array<exec_entry_t, {}> {{\n",
116+
systems_to_parallel.size()
117+
));
118+
for(const auto system_like_id : systems_to_parallel) {
119+
auto cpp_decl_name =
120+
cpp_identifier(ecsact::meta::decl_full_name(system_like_id));
121+
122+
if(details.is_action(system_like_id)) {
123+
ctx.write(
124+
"exec_entry_t{&ecsact::entt::execute_actions<",
125+
cpp_decl_name,
126+
">, actions_map},\n"
127+
);
128+
} else if(details.is_system(system_like_id)) {
129+
ctx.write(
130+
"exec_entry_t{&ecsact::entt::execute_system<",
131+
cpp_decl_name,
132+
">, actions_map},\n"
133+
);
134+
} else {
135+
ctx.write("// ??? unhandled ??? ", cpp_decl_name, "\n");
136+
}
67137
}
138+
ctx.write("});\n");
68139
}
69140

70141
ctx.write("\nupdate_all_beforechange_storage(registry_id);\n");

rt_entt_codegen/core/init_registry_storage.cc

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,18 @@ auto ecsact::rt_entt_codegen::core::print_init_registry_storage(
1919
for(auto comp_id : details.all_components) {
2020
auto cpp_comp_name = cpp_identifier(decl_full_name(comp_id));
2121

22-
ctx.write(
23-
"ecsact::entt::wrapper::core::prepare_component<",
24-
cpp_comp_name,
25-
">(registry_id)"
26-
);
27-
ctx.write(";\n");
22+
ctx.write(std::format(
23+
"ecsact::entt::wrapper::core::prepare_component<{}>(registry_id);\n",
24+
cpp_comp_name
25+
));
26+
}
27+
28+
for(auto system_id : details.all_systems) {
29+
auto cpp_sys_name = cpp_identifier(decl_full_name(system_id));
30+
31+
ctx.write(std::format(
32+
"ecsact::entt::wrapper::core::prepare_system<{}>(registry_id);\n",
33+
cpp_sys_name
34+
));
2835
}
2936
}

0 commit comments

Comments
 (0)