Skip to content

Commit

Permalink
feat: toggle stream + new indexed fields api (#151)
Browse files Browse the repository at this point in the history
Co-authored-by: Ezekiel Warren <ezekiel@seaube.com>
  • Loading branch information
Kelwan and zaucy authored Oct 17, 2024
1 parent dc5fdbb commit b74d827
Show file tree
Hide file tree
Showing 35 changed files with 844 additions and 75 deletions.
4 changes: 4 additions & 0 deletions BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ cc_test(
name = "test",
visibility = ["//visibility:private"],
copts = copts,
defines = [
"ECSACT_CORE_API=",
"ECSACT_DYNAMIC_API=",
],
srcs = [
"build_test.cc",
"//runtime:sources",
Expand Down
15 changes: 10 additions & 5 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ module(

bazel_dep(name = "rules_cc", version = "0.0.9")
bazel_dep(name = "bazel_skylib", version = "1.6.1")
bazel_dep(name = "rules_ecsact", version = "0.5.7")
bazel_dep(name = "ecsact_runtime", version = "0.6.9")
bazel_dep(name = "ecsact_lang_cpp", version = "0.4.7")
bazel_dep(name = "rules_ecsact", version = "0.5.8")
bazel_dep(name = "ecsact_runtime", version = "0.7.0")
bazel_dep(name = "ecsact_lang_cpp", version = "0.4.10")
bazel_dep(name = "boost.mp11", version = "1.83.0.bzl.1")
bazel_dep(name = "entt", version = "3.12.2")
bazel_dep(name = "ecsact_codegen", version = "0.4.1")
bazel_dep(name = "ecsact_cli", version = "0.3.16")
bazel_dep(name = "ecsact_codegen", version = "0.4.3")
bazel_dep(name = "ecsact_cli", version = "0.3.19")
bazel_dep(name = "xxhash", version = "0.8.2")
bazel_dep(name = "googletest", version = "1.14.0.bcr.1")
bazel_dep(name = "boost.dll", version = "1.83.0.bzl.2")
Expand Down Expand Up @@ -46,3 +46,8 @@ register_toolchains(
"@ecsact_toolchain//:all",
dev_dependency = True,
)

local_path_override(
module_name = "ecsact_lang_cpp",
path = "../ecsact_lang_cpp",
)
7 changes: 6 additions & 1 deletion build_test.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Include all headers fot the sake of a quick build test
// Include all headers for the sake of a quick build test
#include "entt/entt.hpp" // IWYU pragma: keep
#include "ecsact/entt/detail/apply_pending.hh" // IWYU pragma: keep
#include "ecsact/entt/detail/bytes.hh" // IWYU pragma: keep
Expand All @@ -8,13 +8,17 @@
#include "ecsact/entt/detail/internal_markers.hh" // IWYU pragma: keep
#include "ecsact/entt/detail/registry.hh" // IWYU pragma: keep
#include "ecsact/entt/detail/system_execution_context.hh" // IWYU pragma: keep
#include "ecsact/entt/detail/apply_component_stream_data.hh" // IWYU pragma: keep
#include "ecsact/entt/entity.hh" // IWYU pragma: keep
#include "ecsact/entt/error_check.hh" // IWYU pragma: keep
#include "ecsact/entt/event_markers.hh" // IWYU pragma: keep
#include "ecsact/entt/execution.hh" // IWYU pragma: keep
#include "ecsact/entt/registry_util.hh" // IWYU pragma: keep
#include "ecsact/entt/wrapper/core.hh" // IWYU pragma: keep
#include "ecsact/entt/wrapper/dynamic.hh" // IWYU pragma: keep
#include "ecsact/entt/stream_registries.hh" // IWYU pragma: keep
#include "ecsact/runtime/common.h" // IWYU pragma: keep
#include "entt/entity/registry.hpp" // IWYU pragma: keep

// default assign some global vars for the sake of compiling only
#define MOCK_DEF_GLOBAL(Name) \
Expand All @@ -30,6 +34,7 @@ MOCK_DEF_GLOBAL(has_component_fns);
MOCK_DEF_GLOBAL(update_component_fns);
MOCK_DEF_GLOBAL(remove_component_fns);
MOCK_DEF_GLOBAL(exec_ctx_action_fns);
MOCK_DEF_GLOBAL(ecsact_stream_fns);

auto main() -> int {
// This is only here to get compile commands working
Expand Down
36 changes: 36 additions & 0 deletions ecsact/entt/detail/apply_component_stream_data.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#pragma once

#include <entt/entt.hpp>

#include "ecsact/entt/detail/internal_markers.hh"

namespace ecsact::entt::detail {
template<typename C>
auto apply_component_stream_data(
::entt::registry& main_reg,
::entt::registry& stream_reg
) -> void {
auto view = main_reg.template view<
C>(::entt::exclude<ecsact::entt::detail::run_on_stream<C>>);

for(auto entity : view) {
if(!stream_reg.any_of<C>(entity)) {
continue;
}

auto& in_component = stream_reg.get<C>(entity);
if(main_reg.any_of<C>(entity)) {
auto& current_comp = main_reg.get<C>(entity);

auto& beforechange =
main_reg.template get<exec_beforechange_storage<C>>(entity);

if(!beforechange.has_update_occurred) {
beforechange.value = current_comp;
beforechange.has_update_occurred = true;
}
current_comp = in_component;
}
}
}
} // namespace ecsact::entt::detail
17 changes: 17 additions & 0 deletions ecsact/entt/detail/globals.hh
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,20 @@
#include "ecsact/runtime/dynamic.h"
#include "ecsact/entt/detail/system_execution_context.hh"
#include "ecsact/entt/detail/registry.hh"
#include "ecsact/entt/stream_registries.hh"

/**
* A small set of globals expected to be available the ecsact_rt_entt_codegen
* generated source.
*/
namespace ecsact::entt::detail::globals {

/**
* Holds and handles the individual registries for each thread that's passed in
* from ecsact_stream.
*/
extern stream::stream_registries stream_registries;

/**
* Ecsact registry ID mapped to EnTT registry instance.
*/
Expand Down Expand Up @@ -91,6 +98,16 @@ extern const std::unordered_map< //
decltype(&ecsact_has_component)>
has_component_fns;

/**
* ecsact_stream fn pointers
*
* NOTE: This gets is filled in by ecsact_rt_entt_codegen
*/
extern const std::unordered_map< //
ecsact_component_id,
decltype(&ecsact_stream)>
ecsact_stream_fns;

/**
* ecsact_system_execution_context_action fn pointers
*
Expand Down
11 changes: 11 additions & 0 deletions ecsact/entt/detail/internal_markers.hh
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@ struct pending_add<C> {
template<typename C>
struct pending_remove {};

/**
* This flag is added to a system when its requirements contain a streaming
* component. If the ecsact_stream is toggled to systems, this component gets
* added and systems will run.
*/
template<typename C>
struct run_on_stream {};

struct created_entity {
ecsact_placeholder_entity_id placeholder_entity_id;
};
Expand All @@ -66,6 +74,9 @@ struct system_sorted {
template<typename S>
struct pending_lazy_execution {};

/**
* Flags a notify system to run upon fulfilling its requirements
*/
template<typename S>
struct run_system {};

Expand Down
18 changes: 14 additions & 4 deletions ecsact/entt/detail/system_execution_context.hh
Original file line number Diff line number Diff line change
Expand Up @@ -37,21 +37,25 @@ struct ecsact_system_execution_context {
) -> void = 0;

virtual auto remove( //
ecsact_component_like_id component_id
ecsact_component_like_id component_id,
const void* indexed_fields
) -> void = 0;

virtual auto get( //
ecsact_component_like_id component_id,
void* out_component_data
void* out_component_data,
const void* indexed_fields
) -> void = 0;

virtual auto update( //
ecsact_component_like_id component_id,
const void* component_data
const void* component_data,
const void* indexed_fields
) -> void = 0;

virtual auto has( //
ecsact_component_like_id component_id
ecsact_component_like_id component_id,
const void* indexed_fields
) -> bool = 0;

virtual auto generate( //
Expand All @@ -60,6 +64,12 @@ struct ecsact_system_execution_context {
const void** components_data
) -> void = 0;

virtual auto stream_toggle( //
ecsact_component_id component_id,
bool enable_stream,
const void* indexed_fields
) -> void = 0;

virtual auto parent() -> const ecsact_system_execution_context* = 0;

virtual auto other( //
Expand Down
2 changes: 2 additions & 0 deletions ecsact/entt/registry_util.hh
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ inline auto create_registry()
);
auto& registry = registries[registry_id];

ecsact::entt::detail::globals::stream_registries.add_registry(registry_id);

return {registry_id, std::ref(registry)};
}

Expand Down
84 changes: 84 additions & 0 deletions ecsact/entt/stream_registries.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#pragma once

#include <thread>
#include <map>
#include <mutex>
#include <shared_mutex>
#include <vector>
#include <ranges>
#include <memory>
#include <entt/entt.hpp>
#include "ecsact/runtime/common.h"
#include "ecsact/entt/entity.hh"

namespace ecsact::entt::stream::detail {
using child_reg_thread_map =
std::unordered_map<std::thread::id, std::unique_ptr<::entt::registry>>;
using reg_thread_map =
std::unordered_map<ecsact_registry_id, child_reg_thread_map>;
} // namespace ecsact::entt::stream::detail

namespace ecsact::entt::stream {
class stream_registries {
private:
detail::reg_thread_map registry_stream_threads;
std::shared_mutex stream_mutex;

template<typename C>
auto ensure_and_add_entity_and_component(
std::unique_ptr<::entt::registry>& registry,
::ecsact::entt::entity_id entity,
const C& component
) -> void {
if(!registry->valid(entity)) {
auto new_entity = registry->create(entity);
assert(new_entity == entity.as_entt());
}

registry->template emplace_or_replace<C>(entity, component);
}

public:
stream_registries() = default;

template<typename C>
auto handle_stream(
ecsact_registry_id registry_id,
ecsact_entity_id entity_id,
const C& component
) -> void {
// Add to map if new threads/registries are introduced

auto thread_id = std::this_thread::get_id();
auto entity = ::ecsact::entt::entity_id(entity_id);

std::shared_lock shared_lk(stream_mutex);
std::unique_lock lk(stream_mutex, std::defer_lock);

auto reg_threads_itr = registry_stream_threads.find(registry_id);
assert(reg_threads_itr != registry_stream_threads.end());

auto& reg_threads = reg_threads_itr->second;
auto reg_thread_itr = reg_threads.find(thread_id);

if(reg_thread_itr == reg_threads.end()) {
auto registry = std::make_unique<::entt::registry>();
ensure_and_add_entity_and_component(registry, entity, component);
shared_lk.unlock();
lk.lock();
reg_threads.insert(
reg_threads.end(),
std::pair(thread_id, std::move(registry))
);
lk.unlock();
} else {
auto& registry = reg_thread_itr->second;
ensure_and_add_entity_and_component(registry, entity, component);
}
}

auto get_stream_registries()
-> std::vector<std::unique_ptr<::entt::registry>>;
auto add_registry(ecsact_registry_id) -> void;
};
} // namespace ecsact::entt::stream
Loading

0 comments on commit b74d827

Please sign in to comment.