Skip to content

Commit b8cecbe

Browse files
committed
feat: ecsact codegen plugin for optimization
1 parent 0defb9e commit b8cecbe

File tree

8 files changed

+260
-0
lines changed

8 files changed

+260
-0
lines changed

ecsact/entt/detail/registry_info.hh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "ecsact/entt/system_view.hh"
1414
#include "ecsact/entt/event_markers.hh"
1515
#include "ecsact/entt/entity.hh"
16+
#include "ecsact/entt/execution.hh"
1617
#include "ecsact/entt/detail/internal_markers.hh"
1718

1819
#include "meta_util.hh"
@@ -32,6 +33,7 @@ struct registry_info {
3233
using ecsact::entt::component_removed;
3334
using ecsact::entt::detail::beforechange_storage;
3435
using ecsact::entt::detail::mp_for_each_available_component;
36+
using ecsact::entt::detail::mp_for_each_available_system_like;
3537
using ecsact::entt::detail::temp_storage;
3638

3739
mp_for_each_available_component<package>([&]<typename C>(C) {
@@ -44,6 +46,10 @@ struct registry_info {
4446
registry.storage<beforechange_storage<C>>();
4547
}
4648
});
49+
50+
mp_for_each_available_system_like<package>([&]<typename S>(S) {
51+
::ecsact::entt::prepare_system_like<S>(registry);
52+
});
4753
}
4854

4955
template<typename C>

ecsact/entt/execution.hh

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#pragma once
2+
3+
#include <vector>
4+
#include <unordered_map>
5+
#include "ecsact/runtime/common.h"
6+
#include "entt/entity/registry.hpp"
7+
8+
namespace ecsact::entt {
9+
10+
/**
11+
* Executes system implementation for @tp System.
12+
*
13+
* NOTE: Template specializations are made available via the codegen plugin
14+
* `ecsact_rt_entt_codegen`.
15+
*/
16+
template<typename System>
17+
auto execute_system(::entt::registry&) -> void;
18+
19+
/**
20+
* Executes action implementation for @tp Action for every action in @p
21+
* action_range.
22+
*
23+
* NOTE: Template specializations are made available via the codegen plugin
24+
* `ecsact_rt_entt_codegen`.
25+
*/
26+
template<typename Action>
27+
auto execute_actions(::entt::registry&, auto&& action_range) -> void;
28+
29+
/**
30+
* Executes all systems/actions
31+
*
32+
* NOTE: Implementation is generated by the `ecsact_rt_entt_codegen` plugin
33+
*/
34+
auto execute_systems(
35+
::entt::registry& registry,
36+
int32_t execution_count,
37+
std::unordered_map<ecsact_action_id, std::vector<const void*>> actions
38+
) -> void;
39+
40+
/**
41+
* Allocates EnTT groups and storage if necessary for the system or action.
42+
* NOTE: Template specializations are made available via the codegen plugin
43+
* `ecsact_rt_entt_codegen`.
44+
*/
45+
template<typename SystemLike>
46+
auto prepare_system_like(::entt::registry&) -> void;
47+
48+
} // namespace ecsact::entt

ecsact/entt/runtime.hh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1298,6 +1298,16 @@ public:
12981298
}
12991299
return true;
13001300
}
1301+
1302+
auto get_system_execution_impl(ecsact_system_like_id sys_like_id)
1303+
-> ecsact_system_execution_impl {
1304+
auto itr = _sys_impl_fns.find(sys_like_id);
1305+
if(itr != _sys_impl_fns.end()) {
1306+
return itr->second;
1307+
}
1308+
1309+
return nullptr;
1310+
}
13011311
#endif
13021312

13031313
ecsact_execute_systems_error execute_systems(

rt_entt_codegen/BUILD.bazel

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
load("//bazel:copts.bzl", "copts")
2+
load("@ecsact_runtime//:codegen_plugin.bzl", "cc_ecsact_codegen_plugin")
3+
4+
package(default_visibility = ["//visibility:public"])
5+
6+
cc_ecsact_codegen_plugin(
7+
name = "ecsact_rt_entt_codegen",
8+
srcs = glob(["*.cc", "*.hh"]),
9+
copts = copts,
10+
output_extension = "rt_entt.hh",
11+
deps = ["@ecsact_lang_cpp//:support"],
12+
)
13+
14+
alias(
15+
name = "rt_entt_codegen",
16+
actual = ":ecsact_rt_entt_codegen",
17+
)
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
#include "ecsact_entt_details.hh"
2+
3+
#include <cassert>
4+
#include "ecsact/codegen_plugin.h"
5+
#include "ecsact/codegen_plugin.hh"
6+
#include "ecsact/lang-support/lang-cc.hh"
7+
#include "ecsact/runtime/meta.hh"
8+
9+
static auto collect_top_level_systems( //
10+
ecsact_package_id pkg_id,
11+
ecsact_entt_details& details
12+
) -> void {
13+
auto deps = ecsact::meta::get_dependencies(pkg_id);
14+
for(auto dep : deps) {
15+
auto tl_sys_ids = ecsact::meta::get_top_level_systems(dep);
16+
details.top_execution_order.insert(
17+
details.top_execution_order.end(),
18+
tl_sys_ids.begin(),
19+
tl_sys_ids.end()
20+
);
21+
}
22+
23+
auto main_tl_sys_ids = ecsact::meta::get_top_level_systems(pkg_id);
24+
details.top_execution_order.insert(
25+
details.top_execution_order.end(),
26+
main_tl_sys_ids.begin(),
27+
main_tl_sys_ids.end()
28+
);
29+
}
30+
31+
auto ecsact_entt_system_details::from_system_like( //
32+
ecsact_system_like_id sys_like_id
33+
) -> ecsact_entt_system_details {
34+
auto details = ecsact_entt_system_details{};
35+
auto caps = ecsact::meta::system_capabilities(sys_like_id);
36+
37+
for(auto&& [comp_id, cap] : caps) {
38+
switch(cap) {
39+
case ECSACT_SYS_CAP_INCLUDE:
40+
details.tag_comps.insert(comp_id);
41+
case ECSACT_SYS_CAP_READONLY:
42+
case ECSACT_SYS_CAP_WRITEONLY:
43+
case ECSACT_SYS_CAP_READWRITE:
44+
case ECSACT_SYS_CAP_OPTIONAL:
45+
case ECSACT_SYS_CAP_OPTIONAL_READONLY:
46+
case ECSACT_SYS_CAP_OPTIONAL_WRITEONLY:
47+
case ECSACT_SYS_CAP_OPTIONAL_READWRITE:
48+
case ECSACT_SYS_CAP_REMOVES:
49+
details.get_comps.insert(comp_id);
50+
break;
51+
case ECSACT_SYS_CAP_EXCLUDE:
52+
case ECSACT_SYS_CAP_ADDS:
53+
details.exclude_comps.insert(comp_id);
54+
break;
55+
}
56+
}
57+
58+
for(auto&& [comp_id, _] : caps) {
59+
// Santity check to make sure we've not missing any system comp IDs
60+
assert(
61+
details.get_comps.contains(comp_id) ||
62+
details.exclude_comps.contains(comp_id)
63+
);
64+
}
65+
66+
return details;
67+
}
68+
69+
auto ecsact_entt_details::from_package( //
70+
ecsact_package_id pkg_id
71+
) -> ecsact_entt_details {
72+
auto details = ecsact_entt_details{};
73+
74+
collect_top_level_systems(pkg_id, details);
75+
76+
for(auto sys_id : details.top_execution_order) {
77+
}
78+
79+
for(auto sys_id : details.top_execution_order) {
80+
assert(
81+
details.view_systems.contains(sys_id) ||
82+
details.group_systems.contains(sys_id)
83+
);
84+
}
85+
86+
return details;
87+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#pragma once
2+
3+
#include <vector>
4+
#include <unordered_set>
5+
#include <unordered_map>
6+
#include <ecsact/runtime/common.h>
7+
8+
struct ecsact_entt_system_details {
9+
/** Components/transients included in EnTT view/group */
10+
std::unordered_set<ecsact_component_like_id> get_comps;
11+
12+
/** Components/transients excluded in EnTT view/group */
13+
std::unordered_set<ecsact_component_like_id> exclude_comps;
14+
15+
/** Included in EnTT view/group, but is a tag component */
16+
std::unordered_set<ecsact_component_like_id> tag_comps;
17+
18+
static auto from_system_like( //
19+
ecsact_system_like_id sys_like_id
20+
) -> ecsact_entt_system_details;
21+
};
22+
23+
/**
24+
* Details about an the main Ecsact package in relation to EnTT runtime. Package
25+
* dependencies are flattened.
26+
*/
27+
struct ecsact_entt_details {
28+
// Systems/actions we've decided will use an EnTT group
29+
std::unordered_set<ecsact_system_like_id> group_systems;
30+
31+
// Systems/actions we've decided will use an Entt view
32+
std::unordered_set<ecsact_system_like_id> view_systems;
33+
34+
// Top level sysetms/actions in execution order
35+
std::vector<ecsact_system_like_id> top_execution_order;
36+
37+
static auto from_package(ecsact_package_id pkg_id) -> ecsact_entt_details;
38+
};

rt_entt_codegen/rt_entt_codegen.cc

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#include <string>
2+
#include <filesystem>
3+
#include "ecsact/runtime/meta.hh"
4+
#include "ecsact/codegen_plugin.h"
5+
#include "ecsact/codegen_plugin.hh"
6+
#include "ecsact/lang-support/lang-cc.hh"
7+
8+
#include "ecsact_entt_details.hh"
9+
10+
namespace fs = std::filesystem;
11+
12+
constexpr auto GENERATED_FILE_DISCLAIMER = R"(
13+
// GENERATED FILE - DO NOT EDIT
14+
)";
15+
16+
constexpr auto MAIN_PACKAGE_ONLY_DISCLAIMER = R"(
17+
// Purposely empty. ecsact_rt_entt_codegen is only for the 'main' package
18+
)";
19+
20+
void ecsact_codegen_plugin(
21+
ecsact_package_id package_id,
22+
ecsact_codegen_write_fn_t write_fn
23+
) {
24+
using ecsact::cc_lang_support::c_identifier;
25+
using ecsact::cc_lang_support::cpp_identifier;
26+
using ecsact::meta::get_all_system_like_ids;
27+
ecsact::codegen_plugin_context ctx{package_id, write_fn};
28+
29+
ctx.write(GENERATED_FILE_DISCLAIMER);
30+
31+
if(ecsact_meta_main_package() != package_id) {
32+
ctx.write(MAIN_PACKAGE_ONLY_DISCLAIMER);
33+
return;
34+
}
35+
36+
auto details = ecsact_entt_details::from_package(package_id);
37+
38+
auto cpp_header_path = ecsact::meta::package_file_path(package_id);
39+
cpp_header_path.replace_extension(
40+
cpp_header_path.extension().string() + ".hh"
41+
);
42+
43+
auto cpp_meta_header_path = ecsact::meta::package_file_path(package_id);
44+
cpp_meta_header_path.replace_extension(
45+
cpp_meta_header_path.extension().string() + ".hh"
46+
);
47+
48+
ctx.write("#include \"ecsact/entt/runtime.hh\"\n");
49+
ctx.write("\n");
50+
ctx.write("#include \"", cpp_header_path.filename().string(), "\"\n");
51+
ctx.write("#include \"", cpp_meta_header_path.filename().string(), "\"\n");
52+
ctx.write("\n");
53+
}

runtime/index.bzl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ def ecsact_entt_runtime(name, srcs = [], deps = [], system_impls = [], tags = []
1818
"@ecsact_lang_cpp//cpp_systems_header_codegen",
1919
"@ecsact_lang_cpp//systems_header_codegen",
2020
"@ecsact_lang_cpp//cpp_meta_header_codegen",
21+
"@ecsact_rt_entt//rt_entt_codegen",
2122
],
2223
**kwargs
2324
)

0 commit comments

Comments
 (0)