Skip to content

Commit 44b6843

Browse files
committed
feat: using code generator (wip)
1 parent b8cecbe commit 44b6843

File tree

15 files changed

+608
-43
lines changed

15 files changed

+608
-43
lines changed

ecsact/entt/detail/globals.hh

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#pragma once
2+
3+
#include <unordered_map>
4+
#include "ecsact/runtime/common.h"
5+
#include "entt/entity/registry.hpp"
6+
7+
/**
8+
* A small set of globals exepected to be available the ecsact_rt_entt_codegen
9+
* generated source.
10+
*/
11+
namespace ecsact::entt::detail::globals {
12+
13+
/**
14+
* Ecsact registry ID mapped to EnTT registry instance.
15+
*/
16+
extern std::unordered_map< //
17+
ecsact_registry_id,
18+
::entt::registry>
19+
registries;
20+
21+
/**
22+
* Stored last registry ID. Used to create new registry IDs.
23+
*/
24+
extern ecsact_registry_id last_registry_id;
25+
26+
/**
27+
* System-like implementation functions set by dynamic API.
28+
*/
29+
extern std::unordered_map< //
30+
ecsact_system_like_id,
31+
ecsact_system_execution_impl>
32+
system_impls;
33+
} // namespace ecsact::entt::detail::globals

ecsact/entt/execution.hh

Lines changed: 92 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,89 @@
22

33
#include <vector>
44
#include <unordered_map>
5+
#include <cassert>
6+
#include <span>
7+
#include <type_traits>
58
#include "ecsact/runtime/common.h"
69
#include "entt/entity/registry.hpp"
710

11+
namespace ecsact::entt::detail {
12+
template<typename>
13+
constexpr bool unimplemented_by_codegen = false;
14+
}
15+
816
namespace ecsact::entt {
917

18+
struct actions_map {
19+
using raw_value_t =
20+
std::unordered_map<ecsact_action_id, std::vector<const void*>>;
21+
22+
raw_value_t raw_value = {};
23+
24+
/**
25+
* Collect from execution options passed to `ecsact_execute_systems`
26+
*/
27+
inline auto collect( //
28+
int32_t index,
29+
int32_t execution_count,
30+
const ecsact_execution_options* execution_options_list
31+
) -> void {
32+
raw_value.clear();
33+
34+
if(execution_options_list == nullptr) {
35+
return;
36+
}
37+
38+
assert(index < execution_count);
39+
auto options = execution_options_list[index];
40+
41+
if(options.actions_length == 0) {
42+
return;
43+
}
44+
45+
auto actions_span = std::span{
46+
options.actions,
47+
static_cast<size_t>(options.actions_length),
48+
};
49+
50+
for(auto& action : actions_span) {
51+
raw_value[action.action_id].push_back(action.action_data);
52+
}
53+
}
54+
55+
template<typename Action>
56+
auto as_action_span() -> std::span<const Action*> {
57+
ecsact_action_id action_id = Action::id;
58+
59+
if(!raw_value.contains(action_id)) {
60+
return {};
61+
}
62+
63+
auto& action_data_list = raw_value.at(action_id);
64+
65+
return std::span<Action>{
66+
static_cast<const Action**>(action_data_list.data()),
67+
action_data_list.size(),
68+
};
69+
}
70+
};
71+
1072
/**
1173
* Executes system implementation for @tp System.
1274
*
1375
* NOTE: Template specializations are made available via the codegen plugin
1476
* `ecsact_rt_entt_codegen`.
1577
*/
1678
template<typename System>
17-
auto execute_system(::entt::registry&) -> void;
79+
auto execute_system(::entt::registry&) -> void {
80+
static_assert(detail::unimplemented_by_codegen<System>, R"(
81+
-----------------------------------------------------------------------------
82+
| (!) CODEGEN ERROR |
83+
| `execute_system<>` template specialization cannot be found. This is |
84+
| typically generated by ecsact_rt_entt_codegen. |
85+
-----------------------------------------------------------------------------
86+
)");
87+
}
1888

1989
/**
2090
* Executes action implementation for @tp Action for every action in @p
@@ -24,25 +94,33 @@ auto execute_system(::entt::registry&) -> void;
2494
* `ecsact_rt_entt_codegen`.
2595
*/
2696
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;
97+
auto execute_actions( //
98+
::entt::registry& registry,
99+
std::span<const Action*>&& action_range
100+
) -> void {
101+
static_assert(detail::unimplemented_by_codegen<Action>, R"(
102+
-----------------------------------------------------------------------------
103+
| (!) CODEGEN ERROR |
104+
| `execute_actions<>` template specialization cannot be found. This is |
105+
| typically generated by ecsact_rt_entt_codegen. |
106+
-----------------------------------------------------------------------------
107+
)");
108+
}
39109

40110
/**
41111
* Allocates EnTT groups and storage if necessary for the system or action.
42112
* NOTE: Template specializations are made available via the codegen plugin
43113
* `ecsact_rt_entt_codegen`.
44114
*/
45115
template<typename SystemLike>
46-
auto prepare_system_like(::entt::registry&) -> void;
116+
auto prepare_system_like(::entt::registry&) -> void {
117+
static_assert(detail::unimplemented_by_codegen<SystemLike>, R"(
118+
-----------------------------------------------------------------------------
119+
| (!) CODEGEN ERROR |
120+
| `prepare_system_like<>` template specialization cannot be found. This is |
121+
| typically generated by ecsact_rt_entt_codegen. |
122+
-----------------------------------------------------------------------------
123+
)");
124+
}
47125

48126
} // namespace ecsact::entt

ecsact/entt/registry_util.hh

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#pragma once
2+
3+
#include <cassert>
4+
#include "entt/entity/registry.hpp"
5+
#include "ecsact/entt/detail/globals.hh"
6+
7+
namespace ecsact::entt {
8+
9+
inline auto get_registry( //
10+
ecsact_registry_id id
11+
) -> ::entt::registry& {
12+
using ecsact::entt::detail::globals::registries;
13+
14+
// Check to make sure we're not trying to get a registry that doesn't exist
15+
// or has been destroyed.
16+
assert(registries.contains(id));
17+
return registries.at(id);
18+
}
19+
20+
inline auto create_registry()
21+
-> std::tuple<ecsact_registry_id, ::entt::registry&> {
22+
using ecsact::entt::detail::globals::last_registry_id;
23+
using ecsact::entt::detail::globals::registries;
24+
25+
auto registry_id = static_cast<ecsact_registry_id>(
26+
++reinterpret_cast<int32_t&>(last_registry_id)
27+
);
28+
auto& registry = registries[registry_id];
29+
30+
return {registry_id, std::ref(registry)};
31+
}
32+
33+
} // namespace ecsact::entt

rt_entt_codegen/BUILD.bazel

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
load("//bazel:copts.bzl", "copts")
2-
load("@ecsact_runtime//:codegen_plugin.bzl", "cc_ecsact_codegen_plugin")
2+
load("@ecsact_codegen//:codegen_plugin.bzl", "cc_ecsact_codegen_plugin")
33

44
package(default_visibility = ["//visibility:public"])
55

66
cc_ecsact_codegen_plugin(
77
name = "ecsact_rt_entt_codegen",
8-
srcs = glob(["*.cc", "*.hh"]),
8+
srcs = ["rt_entt_codegen.cc"],
99
copts = copts,
10-
output_extension = "rt_entt.hh",
11-
deps = ["@ecsact_lang_cpp//:support"],
10+
output_extension = "rt_entt.cc",
11+
deps = [
12+
"//rt_entt_codegen/core",
13+
"//rt_entt_codegen/shared:ecsact_entt_details",
14+
"//rt_entt_codegen/shared:util",
15+
"@ecsact_lang_cpp//:support",
16+
],
1217
)
1318

1419
alias(

rt_entt_codegen/core/BUILD.bazel

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
load("//bazel:copts.bzl", "copts")
2+
load("@rules_cc//cc:defs.bzl", "cc_library")
3+
4+
cc_library(
5+
name = "core_internal",
6+
visibility = ["//rt_entt_codegen:__pkg__"],
7+
copts = copts,
8+
hdrs = ["core.hh"],
9+
deps = ["//rt_entt_codegen/shared:ecsact_entt_details"],
10+
)
11+
12+
# keep sorted
13+
_CORE_CODEGEN_METHODS = {
14+
"execute_systems": [],
15+
"create_registry": [],
16+
}
17+
18+
[cc_library(
19+
name = method,
20+
srcs = ["{}.cc".format(method)],
21+
copts = copts,
22+
defines = ["ECSACT_META_API_LOAD_AT_RUNTIME"],
23+
deps = _CORE_CODEGEN_METHODS[method] + [
24+
":core_internal",
25+
"//rt_entt_codegen/shared:util",
26+
"@ecsact_runtime//:meta",
27+
"@ecsact_runtime//:codegen_plugin_cc",
28+
"@ecsact_lang_cpp//:support",
29+
],
30+
) for method in _CORE_CODEGEN_METHODS]
31+
32+
cc_library(
33+
name = "core",
34+
visibility = ["//rt_entt_codegen:__pkg__"],
35+
copts = copts,
36+
deps = [":core_internal"] + [":{}".format(method) for method in _CORE_CODEGEN_METHODS],
37+
)

rt_entt_codegen/core/core.hh

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#pragma once
2+
3+
#include "ecsact/runtime/meta.hh"
4+
#include "ecsact/codegen_plugin.hh"
5+
#include "rt_entt_codegen/shared/ecsact_entt_details.hh"
6+
7+
namespace ecsact::rt_entt_codegen::core {
8+
9+
auto print_execute_systems( //
10+
codegen_plugin_context& ctx,
11+
const ecsact_entt_details& details
12+
) -> void;
13+
14+
auto print_create_registry( //
15+
codegen_plugin_context& ctx,
16+
const ecsact_entt_details& details
17+
) -> void;
18+
19+
} // namespace ecsact::rt_entt_codegen::core
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#include "core.hh"
2+
3+
#include "ecsact/lang-support/lang-cc.hh"
4+
#include "rt_entt_codegen/shared/util.hh"
5+
6+
auto ecsact::rt_entt_codegen::core::print_create_registry( //
7+
codegen_plugin_context& ctx,
8+
const ecsact_entt_details& details
9+
) -> void {
10+
using ecsact::cc_lang_support::cpp_identifier;
11+
using ecsact::rt_entt_codegen::util::method_printer;
12+
13+
auto printer = //
14+
method_printer{ctx, "ecsact_create_registry"}
15+
.parameter("const char*", "registry_name")
16+
.return_type("ecsact_registry_id");
17+
18+
ctx.write("auto&& [registry_id, reg] = ecsact::entt::create_registry();\n\n");
19+
20+
ctx.write(
21+
"// These groups were automatically selected based on the input ecsact "
22+
"files\n"
23+
);
24+
for(auto sys_id : details.group_systems) {
25+
auto cpp_decl_name = cpp_identifier(ecsact::meta::decl_full_name(sys_id));
26+
ctx.write("ecsact::entt::prepare_system_like<", cpp_decl_name, ">(reg);\n");
27+
}
28+
29+
ctx.write("\nreturn registry_id;");
30+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#include "core.hh"
2+
3+
#include "ecsact/lang-support/lang-cc.hh"
4+
#include "rt_entt_codegen/shared/util.hh"
5+
6+
constexpr auto METHOD_BODY_TOP = R"(
7+
auto& reg = ecsact::entt::get_registry(registry_id);
8+
auto actions = ecsact::entt::actions_map{};
9+
)";
10+
11+
auto ecsact::rt_entt_codegen::core::print_execute_systems( //
12+
codegen_plugin_context& ctx,
13+
const ecsact_entt_details& details
14+
) -> void {
15+
using ecsact::cc_lang_support::cpp_identifier;
16+
using ecsact::rt_entt_codegen::util::method_printer;
17+
18+
auto printer = //
19+
method_printer{ctx, "ecsact_execute_systems"}
20+
.parameter("ecsact_registry_id", "registry_id")
21+
.parameter("int", "execution_count")
22+
.parameter("const ecsact_execution_options*", "execution_options_list")
23+
.parameter("const ecsact_execution_events_collector*", "evc")
24+
.return_type("ecsact_execute_systems_error");
25+
26+
ctx.write(METHOD_BODY_TOP);
27+
28+
ctx.write("for(auto i=0; execution_count > i; ++i) {");
29+
ctx.indentation += 1;
30+
ctx.write("\n");
31+
32+
ctx.write("actions.collect(i, execution_count, execution_options_list);\n");
33+
34+
for(auto sys_like : details.top_execution_order) {
35+
auto cpp_decl_name = cpp_identifier(ecsact::meta::decl_full_name(sys_like));
36+
37+
if(details.is_action(sys_like)) {
38+
ctx.write(
39+
"ecsact::entt::execute_actions<",
40+
cpp_decl_name,
41+
">(reg, actions.as_action_span<",
42+
cpp_decl_name,
43+
">());\n"
44+
);
45+
} else if(details.is_system(sys_like)) {
46+
ctx.write("ecsact::entt::execute_system<", cpp_decl_name, ">(reg);\n");
47+
} else {
48+
ctx.write("// ??? unhandled ??? ", cpp_decl_name, "\n");
49+
}
50+
}
51+
52+
ctx.indentation -= 1;
53+
ctx.write("\n}\n");
54+
55+
ctx.write("return ECSACT_EXEC_SYS_OK;");
56+
}

0 commit comments

Comments
 (0)