From d30839597f521204f69e0ee80ae7b0dab19bae1a Mon Sep 17 00:00:00 2001 From: wyc <1104749580@qq.com> Date: Wed, 2 Sep 2026 11:43:48 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../include/function/renderable/rely_facade.h | 14 --- .../include/function/scene/rely_facade.h | 19 --- .../include/task_flow/Task_Graph_Types.hpp | 10 -- .../include/task_flow/Task_Runtime_Types.hpp | 19 --- .../include/task_flow/task_flow_facade.cpp | 90 ------------- .../module/frame_policy/export/export.h | 12 ++ .../frame_policy/src}/Frame_Policy.cpp | 3 + .../frame_policy/src}/Frame_Policy.hpp | 10 +- .../frame_policy/src}/Frame_Policy.ipp | 0 .../src}/Throttled_Latest_Only.cpp | 0 .../src}/Throttled_Latest_Only.hpp | 20 +-- .../src}/Throttled_Latest_Only.ipp | 0 .../frame_policy/src}/rely_facade.h | 2 +- .../test}/Throttled_Latest_Only_Tests.cpp | 2 +- kernel/kernel/module/main.cmake | 26 ++++ .../kernel/module/renderable/export/export.h | 1 + .../module/renderable/src/rely_facade.h | 12 ++ .../module/renderable/src/renderable.cpp | 7 ++ .../renderable/src}/renderable.hpp | 0 .../renderable/src}/renderable.ipp | 4 +- .../renderable/test/Renderable_Tests.cpp | 19 +++ kernel/kernel/module/scene/export/export.h | 6 + .../scene => module/scene/src}/Scene.cpp | 22 ++-- .../scene => module/scene/src}/Scene.hpp | 3 +- .../scene => module/scene/src}/Scene.ipp | 2 +- kernel/kernel/module/scene/src/rely_facade.h | 12 ++ .../kernel/module/scene/test/Scene_Tests.cpp | 103 +++++++++++++++ .../kernel/module/task_flow/export/export.h | 25 ++++ .../task_flow/src}/Task_Graph.cpp | 0 .../task_flow/src}/Task_Graph.hpp | 2 +- .../module/task_flow/src/Task_Graph_Model.hpp | 30 +++++ .../task_flow/src}/Task_Runtime.cpp | 0 .../task_flow/src}/Task_Runtime.hpp | 10 +- .../task_flow/src}/Taskflow_Observation.cpp | 0 .../task_flow/src}/Taskflow_Observation.hpp | 6 +- .../task_flow/src}/Taskflow_Trace.hpp | 0 .../task_flow/src}/design.md | 0 .../src}/detail/Taskflow_Execution.ipp | 2 +- .../task_flow/src}/rely_facade.h | 0 .../module/task_flow/src/task_flow_facade.cpp | 37 ++++++ .../test}/Taskflow_Observation_Tests.cpp | 4 +- .../kernel/module/time_thread/export/export.h | 11 ++ .../time_thread/src}/Timer_Service.cpp | 31 ++--- .../time_thread/src}/Timer_Service.hpp | 9 +- .../time_thread/src/Timer_Service_Model.hpp | 27 ++++ .../time_thread/src}/Timer_Time_Source.hpp | 5 +- .../src}/detail/Timer_Scheduler.cpp | 0 .../src}/detail/Timer_Scheduler.hpp | 4 +- .../time_thread/src}/rely_facade.h | 0 .../time_thread/test}/Timer_Service_Tests.cpp | 6 +- kernel/kernel/test/model/Model_Tests.cpp | 118 +----------------- kernel/main.cmake | 29 +++-- 52 files changed, 402 insertions(+), 372 deletions(-) delete mode 100644 kernel/kernel/include/function/renderable/rely_facade.h delete mode 100644 kernel/kernel/include/function/scene/rely_facade.h delete mode 100644 kernel/kernel/include/task_flow/Task_Graph_Types.hpp delete mode 100644 kernel/kernel/include/task_flow/Task_Runtime_Types.hpp delete mode 100644 kernel/kernel/include/task_flow/task_flow_facade.cpp create mode 100644 kernel/kernel/module/frame_policy/export/export.h rename kernel/kernel/{include/function/frame_policy => module/frame_policy/src}/Frame_Policy.cpp (95%) rename kernel/kernel/{include/function/frame_policy => module/frame_policy/src}/Frame_Policy.hpp (90%) rename kernel/kernel/{include/function/frame_policy => module/frame_policy/src}/Frame_Policy.ipp (100%) rename kernel/kernel/{include/function/frame_policy => module/frame_policy/src}/Throttled_Latest_Only.cpp (100%) rename kernel/kernel/{include/function/frame_policy => module/frame_policy/src}/Throttled_Latest_Only.hpp (64%) rename kernel/kernel/{include/function/frame_policy => module/frame_policy/src}/Throttled_Latest_Only.ipp (100%) rename kernel/kernel/{include/function/frame_policy => module/frame_policy/src}/rely_facade.h (89%) rename kernel/kernel/{test/function/frame_policy => module/frame_policy/test}/Throttled_Latest_Only_Tests.cpp (99%) create mode 100644 kernel/kernel/module/main.cmake create mode 100644 kernel/kernel/module/renderable/export/export.h create mode 100644 kernel/kernel/module/renderable/src/rely_facade.h create mode 100644 kernel/kernel/module/renderable/src/renderable.cpp rename kernel/kernel/{include/function/renderable => module/renderable/src}/renderable.hpp (100%) rename kernel/kernel/{include/function/renderable => module/renderable/src}/renderable.ipp (76%) create mode 100644 kernel/kernel/module/renderable/test/Renderable_Tests.cpp create mode 100644 kernel/kernel/module/scene/export/export.h rename kernel/kernel/{include/function/scene => module/scene/src}/Scene.cpp (68%) rename kernel/kernel/{include/function/scene => module/scene/src}/Scene.hpp (87%) rename kernel/kernel/{include/function/scene => module/scene/src}/Scene.ipp (81%) create mode 100644 kernel/kernel/module/scene/src/rely_facade.h create mode 100644 kernel/kernel/module/scene/test/Scene_Tests.cpp create mode 100644 kernel/kernel/module/task_flow/export/export.h rename kernel/kernel/{include/task_flow => module/task_flow/src}/Task_Graph.cpp (100%) rename kernel/kernel/{include/task_flow => module/task_flow/src}/Task_Graph.hpp (98%) create mode 100644 kernel/kernel/module/task_flow/src/Task_Graph_Model.hpp rename kernel/kernel/{include/task_flow => module/task_flow/src}/Task_Runtime.cpp (100%) rename kernel/kernel/{include/task_flow => module/task_flow/src}/Task_Runtime.hpp (77%) rename kernel/kernel/{include/task_flow => module/task_flow/src}/Taskflow_Observation.cpp (100%) rename kernel/kernel/{include/task_flow => module/task_flow/src}/Taskflow_Observation.hpp (91%) rename kernel/kernel/{include/task_flow => module/task_flow/src}/Taskflow_Trace.hpp (100%) rename kernel/kernel/{include/task_flow => module/task_flow/src}/design.md (100%) rename kernel/kernel/{include/task_flow => module/task_flow/src}/detail/Taskflow_Execution.ipp (99%) rename kernel/kernel/{include/task_flow => module/task_flow/src}/rely_facade.h (100%) create mode 100644 kernel/kernel/module/task_flow/src/task_flow_facade.cpp rename kernel/kernel/{test/task_flow => module/task_flow/test}/Taskflow_Observation_Tests.cpp (98%) create mode 100644 kernel/kernel/module/time_thread/export/export.h rename kernel/kernel/{include/time_thread => module/time_thread/src}/Timer_Service.cpp (84%) rename kernel/kernel/{include/time_thread => module/time_thread/src}/Timer_Service.hpp (82%) create mode 100644 kernel/kernel/module/time_thread/src/Timer_Service_Model.hpp rename kernel/kernel/{include/time_thread => module/time_thread/src}/Timer_Time_Source.hpp (83%) rename kernel/kernel/{include/time_thread => module/time_thread/src}/detail/Timer_Scheduler.cpp (100%) rename kernel/kernel/{include/time_thread => module/time_thread/src}/detail/Timer_Scheduler.hpp (89%) rename kernel/kernel/{include/time_thread => module/time_thread/src}/rely_facade.h (100%) rename kernel/kernel/{test/time_thread => module/time_thread/test}/Timer_Service_Tests.cpp (96%) diff --git a/kernel/kernel/include/function/renderable/rely_facade.h b/kernel/kernel/include/function/renderable/rely_facade.h deleted file mode 100644 index da4fe7b..0000000 --- a/kernel/kernel/include/function/renderable/rely_facade.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once -#include "global.hpp" -#include "../scene/rely_facade.h" -#include -#include -#include -#include -#include -namespace aethera::renderable { -enum struct Add_Task_Graph_Result : std::uint8_t { work_missing }; -struct Task_Node : facade_builder::add_skill::build {}; -struct Task_Graph : facade_builder::add_convention<_add, std::expected, Add_Task_Graph_Result>(std::string, std::function)>::add_convention<_clear, void()>::add_convention<_empty, bool() const noexcept>::add_convention<_taskflow, proxy()>::support_relocation::build {}; -proxy make_task_graph(std::string name); -} // namespace aethera::renderable diff --git a/kernel/kernel/include/function/scene/rely_facade.h b/kernel/kernel/include/function/scene/rely_facade.h deleted file mode 100644 index bdd7268..0000000 --- a/kernel/kernel/include/function/scene/rely_facade.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once -#include "global.hpp" -#include -#include -#include -#include -#include -#include -namespace aethera::scene { -enum struct Compose_Task_Graph_Result : std::uint8_t { component_unavailable, dependency_cycle, already_composed }; -enum struct Precede_Task_Graph_Result : std::uint8_t { preceded, node_unavailable, dependency_cycle }; -enum struct Run_Task_Graph_Result : std::uint8_t { submitted, runtime_not_initialized, completion_missing }; -using Taskflow_Completion = std::function; -struct Task_Node : facade_builder::add_skill::build {}; -struct Task_Graph_Component : facade_builder::add_skill::build {}; -struct Task_Graph : facade_builder::add_convention<_component, proxy()>::add_convention<_compose, std::expected, Compose_Task_Graph_Result>(std::string, proxy&)>::add_convention<_precede, Precede_Task_Graph_Result(proxy&, proxy&)>::add_convention<_empty, bool() const noexcept>::add_convention<_run, Run_Task_Graph_Result(Taskflow_Completion)>::support_relocation::build {}; -proxy make_task_graph(std::string name); -struct Renderable : facade_builder::add_convention<_advance, void()>::add_convention<_taskflow, proxy()>::support_relocation::build {}; -} // namespace aethera::scene diff --git a/kernel/kernel/include/task_flow/Task_Graph_Types.hpp b/kernel/kernel/include/task_flow/Task_Graph_Types.hpp deleted file mode 100644 index 2e4d469..0000000 --- a/kernel/kernel/include/task_flow/Task_Graph_Types.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once -#include -namespace aethera { -enum struct Add_Task_Graph_Result : std::uint8_t { work_missing }; -enum struct Add_Condition_Task_Graph_Result : std::uint8_t { condition_missing }; -enum struct Compose_Task_Graph_Result : std::uint8_t { component_unavailable, dependency_cycle, already_composed }; -enum struct Precede_Task_Graph_Result : std::uint8_t { preceded, node_unavailable, node_stale, different_graph }; -enum struct Describe_Task_Graph_Result : std::uint8_t { described, key_missing }; -enum struct Describe_Task_Graph_Node_Result : std::uint8_t { described, node_unavailable, node_stale, key_missing }; -} // namespace aethera diff --git a/kernel/kernel/include/task_flow/Task_Runtime_Types.hpp b/kernel/kernel/include/task_flow/Task_Runtime_Types.hpp deleted file mode 100644 index a14e3f0..0000000 --- a/kernel/kernel/include/task_flow/Task_Runtime_Types.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once -#include -#include -#include -namespace aethera { -enum struct Run_Taskflow_Result : std::uint8_t { - submitted, - runtime_not_initialized, - completion_missing, - observation_unavailable -}; -enum struct Taskflow_Unknown_Failure_Policy : std::uint8_t { - fast_fail, - exception -}; -using Taskflow_Completion = std::function; -/* Runtime owns one immutable copy for its process lifetime; borrowed captures must outlive the runtime. */ -using Taskflow_Exception_Boundary = std::function; -} // namespace aethera diff --git a/kernel/kernel/include/task_flow/task_flow_facade.cpp b/kernel/kernel/include/task_flow/task_flow_facade.cpp deleted file mode 100644 index 873ee21..0000000 --- a/kernel/kernel/include/task_flow/task_flow_facade.cpp +++ /dev/null @@ -1,90 +0,0 @@ -#include "Task_Graph.hpp" -#include "Task_Runtime.hpp" -#include "function/renderable/rely_facade.h" -#include "function/scene/rely_facade.h" -#include "model/Model.hpp" -#include -#include - -namespace aethera { -namespace detail { -struct Scene_Task_Node { explicit Scene_Task_Node(Task_Node value) : value(std::move(value)) {} Task_Node value; }; -struct Scene_Task_Component { explicit Scene_Task_Component(std::shared_ptr value) : value(std::move(value)) {} std::shared_ptr value; }; -struct Renderable_Task_Node { explicit Renderable_Task_Node(Task_Node value) : value(std::move(value)) {} Task_Node value; }; - -struct Scene_Task_Graph_Model : Def { - struct Private; - explicit Scene_Task_Graph_Model(std::shared_ptr graph) : Def(std::move(graph)) {} -}; - -struct Renderable_Task_Graph_Model : Def { - struct Private; - explicit Renderable_Task_Graph_Model(std::shared_ptr graph) : Def(std::move(graph)) {} -}; - -struct Scene_Task_Graph_Model::Private : Prev_Private { - explicit Private(std::shared_ptr graph) : graph(std::move(graph)) {} - proxy component() { return pro::make_proxy(graph); } - auto compose(std::string name, proxy& child) -> std::expected, scene::Compose_Task_Graph_Result>; - scene::Precede_Task_Graph_Result precede(proxy& before, proxy& after); - bool empty() const noexcept { return graph->empty(); } - scene::Run_Task_Graph_Result run(scene::Taskflow_Completion completion); - std::shared_ptr graph; /* 共享同一权威任务图,仅用于为不同消费模块生成视图。 */ -}; - -struct Renderable_Task_Graph_Model::Private : Prev_Private { - explicit Private(std::shared_ptr graph) : graph(std::move(graph)) {} - auto add(std::string name, std::function work) -> std::expected, renderable::Add_Task_Graph_Result>; - void clear() { graph->clear(); } - bool empty() const noexcept { return graph->empty(); } - proxy taskflow() { return make_model_proxy(graph); } - std::shared_ptr graph; /* 共享同一权威任务图,仅用于为不同消费模块生成视图。 */ -}; -} // namespace detail - -auto detail::Scene_Task_Graph_Model::Private::compose(std::string name, proxy& child) -> std::expected, scene::Compose_Task_Graph_Result> { - auto* component = child ? proxy_cast(&*child) : nullptr; - if (component == nullptr) return std::unexpected(scene::Compose_Task_Graph_Result::component_unavailable); - auto result = graph->compose(std::move(name), *component->value); - if (!result) { - switch (result.error()) { - case aethera::Compose_Task_Graph_Result::component_unavailable: return std::unexpected(scene::Compose_Task_Graph_Result::component_unavailable); - case aethera::Compose_Task_Graph_Result::dependency_cycle: return std::unexpected(scene::Compose_Task_Graph_Result::dependency_cycle); - case aethera::Compose_Task_Graph_Result::already_composed: return std::unexpected(scene::Compose_Task_Graph_Result::already_composed); - } - } - return pro::make_proxy(std::move(*result)); -} - -scene::Precede_Task_Graph_Result detail::Scene_Task_Graph_Model::Private::precede(proxy& before, proxy& after) { - auto* before_node = before ? proxy_cast(&*before) : nullptr; - auto* after_node = after ? proxy_cast(&*after) : nullptr; - if (before_node == nullptr || after_node == nullptr) return scene::Precede_Task_Graph_Result::node_unavailable; - switch (before_node->value.precede(after_node->value)) { - case aethera::Precede_Task_Graph_Result::preceded: return scene::Precede_Task_Graph_Result::preceded; - case aethera::Precede_Task_Graph_Result::node_unavailable: return scene::Precede_Task_Graph_Result::node_unavailable; - case aethera::Precede_Task_Graph_Result::node_stale: - case aethera::Precede_Task_Graph_Result::different_graph: return scene::Precede_Task_Graph_Result::node_unavailable; - } - std::terminate(); -} - -scene::Run_Task_Graph_Result detail::Scene_Task_Graph_Model::Private::run(scene::Taskflow_Completion completion) { - switch (run_taskflow(*graph, std::move(completion))) { - case Run_Taskflow_Result::submitted: return scene::Run_Task_Graph_Result::submitted; - case Run_Taskflow_Result::runtime_not_initialized: return scene::Run_Task_Graph_Result::runtime_not_initialized; - case Run_Taskflow_Result::completion_missing: return scene::Run_Task_Graph_Result::completion_missing; - case Run_Taskflow_Result::observation_unavailable: std::terminate(); - } - std::terminate(); -} - -auto detail::Renderable_Task_Graph_Model::Private::add(std::string name, std::function work) -> std::expected, renderable::Add_Task_Graph_Result> { - auto result = graph->add(std::move(name), std::move(work)); - if (!result) return std::unexpected(renderable::Add_Task_Graph_Result::work_missing); - return pro::make_proxy(std::move(*result)); -} - -proxy scene::make_task_graph(std::string name) { return make_model_proxy(std::make_shared(std::move(name))); } -proxy renderable::make_task_graph(std::string name) { return make_model_proxy(std::make_shared(std::move(name))); } -} // namespace aethera diff --git a/kernel/kernel/module/frame_policy/export/export.h b/kernel/kernel/module/frame_policy/export/export.h new file mode 100644 index 0000000..15cb846 --- /dev/null +++ b/kernel/kernel/module/frame_policy/export/export.h @@ -0,0 +1,12 @@ +#pragma once +#include + +namespace aethera { +enum struct Frame_Policy_Configuration_Result : std::uint8_t { invalid_user_frame_rate, interval_out_of_range, invalid_statistics_window }; +enum struct Frame_Policy_Render_Submission_Result : std::uint8_t { runtime_not_initialized, task_graph_invalid }; +enum struct Throttled_Latest_Only_Start_Result : std::uint8_t { already_running, start_in_progress, stop_in_progress, dependency_unavailable, frame_unavailable, invalid_user_frame_rate, interval_out_of_range, invalid_statistics_window }; +enum struct Throttled_Latest_Only_Stop_Result : std::uint8_t { already_stopped, already_stopping, start_in_progress, completion_missing }; +namespace frame_policy { +enum struct Render_Scene_Result : std::uint8_t { submitted, runtime_not_initialized, task_graph_invalid, frame_missing, completion_missing }; +} // namespace frame_policy +} // namespace aethera diff --git a/kernel/kernel/include/function/frame_policy/Frame_Policy.cpp b/kernel/kernel/module/frame_policy/src/Frame_Policy.cpp similarity index 95% rename from kernel/kernel/include/function/frame_policy/Frame_Policy.cpp rename to kernel/kernel/module/frame_policy/src/Frame_Policy.cpp index 83087f1..e63b080 100644 --- a/kernel/kernel/include/function/frame_policy/Frame_Policy.cpp +++ b/kernel/kernel/module/frame_policy/src/Frame_Policy.cpp @@ -1,10 +1,13 @@ #include "Frame_Policy.hpp" +#include "rely_facade.h" +#include "time_thread/src/Timer_Service_Model.hpp" #include #include #include namespace aethera { +proxy frame_policy::make_timer_service() { return time_thread::make_timer_service_proxy(make_steady_timer_time_source()); } namespace { auto capacity_fps(const Sliding_Statistics& statistics) noexcept -> std::optional { const double average = statistics.summary().average; diff --git a/kernel/kernel/include/function/frame_policy/Frame_Policy.hpp b/kernel/kernel/module/frame_policy/src/Frame_Policy.hpp similarity index 90% rename from kernel/kernel/include/function/frame_policy/Frame_Policy.hpp rename to kernel/kernel/module/frame_policy/src/Frame_Policy.hpp index 0fbffd4..9c59a4e 100644 --- a/kernel/kernel/include/function/frame_policy/Frame_Policy.hpp +++ b/kernel/kernel/module/frame_policy/src/Frame_Policy.hpp @@ -1,4 +1,5 @@ #pragma once +#include "../export/export.h" #include "concurrent/base/Concurrent_Struct.hpp" #include "model/Model.hpp" #include "statistics/Sliding_Statistics.hpp" @@ -8,15 +9,6 @@ #include #include namespace aethera { -enum struct Frame_Policy_Configuration_Result : std::uint8_t { - invalid_user_frame_rate, - interval_out_of_range, - invalid_statistics_window -}; -enum struct Frame_Policy_Render_Submission_Result : std::uint8_t { - runtime_not_initialized, - task_graph_invalid -}; struct Frame_Policy_Prop { std::optional user_frames_per_second; /* 有值时作为用户帧率上限;无值时不参与限速。 */ bool render_rate_limit_enabled{}; /* true 时用渲染平均耗时推导理论生成上限。 */ diff --git a/kernel/kernel/include/function/frame_policy/Frame_Policy.ipp b/kernel/kernel/module/frame_policy/src/Frame_Policy.ipp similarity index 100% rename from kernel/kernel/include/function/frame_policy/Frame_Policy.ipp rename to kernel/kernel/module/frame_policy/src/Frame_Policy.ipp diff --git a/kernel/kernel/include/function/frame_policy/Throttled_Latest_Only.cpp b/kernel/kernel/module/frame_policy/src/Throttled_Latest_Only.cpp similarity index 100% rename from kernel/kernel/include/function/frame_policy/Throttled_Latest_Only.cpp rename to kernel/kernel/module/frame_policy/src/Throttled_Latest_Only.cpp diff --git a/kernel/kernel/include/function/frame_policy/Throttled_Latest_Only.hpp b/kernel/kernel/module/frame_policy/src/Throttled_Latest_Only.hpp similarity index 64% rename from kernel/kernel/include/function/frame_policy/Throttled_Latest_Only.hpp rename to kernel/kernel/module/frame_policy/src/Throttled_Latest_Only.hpp index af1eb7c..1de6233 100644 --- a/kernel/kernel/include/function/frame_policy/Throttled_Latest_Only.hpp +++ b/kernel/kernel/module/frame_policy/src/Throttled_Latest_Only.hpp @@ -1,5 +1,5 @@ #pragma once -#include "function/frame_policy/Frame_Policy.hpp" +#include "Frame_Policy.hpp" #include "rely_facade.h" #include #include @@ -10,22 +10,8 @@ namespace aethera { * 三槽均忙时丢弃本次 tick;stop completion 前排空 Scene/Sink 借用并销毁全部帧。 */ struct Throttled_Latest_only : Def { - enum struct Start_Result : std::uint8_t { - already_running, - start_in_progress, - stop_in_progress, - dependency_unavailable, - frame_unavailable, - invalid_user_frame_rate, - interval_out_of_range, - invalid_statistics_window - }; - enum struct Stop_Result : std::uint8_t { - already_stopped, - already_stopping, - start_in_progress, - completion_missing - }; + using Start_Result = Throttled_Latest_Only_Start_Result; + using Stop_Result = Throttled_Latest_Only_Stop_Result; using Stop_Completion = std::function; struct Private; Throttled_Latest_only(proxy timer_service, proxy scene, proxy sink); diff --git a/kernel/kernel/include/function/frame_policy/Throttled_Latest_Only.ipp b/kernel/kernel/module/frame_policy/src/Throttled_Latest_Only.ipp similarity index 100% rename from kernel/kernel/include/function/frame_policy/Throttled_Latest_Only.ipp rename to kernel/kernel/module/frame_policy/src/Throttled_Latest_Only.ipp diff --git a/kernel/kernel/include/function/frame_policy/rely_facade.h b/kernel/kernel/module/frame_policy/src/rely_facade.h similarity index 89% rename from kernel/kernel/include/function/frame_policy/rely_facade.h rename to kernel/kernel/module/frame_policy/src/rely_facade.h index 6d57e3e..015258b 100644 --- a/kernel/kernel/include/function/frame_policy/rely_facade.h +++ b/kernel/kernel/module/frame_policy/src/rely_facade.h @@ -1,4 +1,5 @@ #pragma once +#include "../export/export.h" #include "global.hpp" #include #include @@ -12,7 +13,6 @@ using Timer_Callback = std::function; struct Frame : facade_builder::build {}; using Frame_Completion = std::function&)>; using Render_Completion = std::function&, std::exception_ptr)>; -enum struct Render_Scene_Result : std::uint8_t { submitted, runtime_not_initialized, task_graph_invalid, frame_missing, completion_missing }; struct Scene : facade_builder::add_convention<_create_frame, proxy()>::add_convention<_render, Render_Scene_Result(proxy&, Render_Completion)>::support_relocation::build {}; struct Sink : facade_builder::add_convention<_send, void(proxy&, Frame_Completion)>::support_relocation::build {}; struct Timer_Service : facade_builder::add_convention<_schedule_every, Timer_Id(std::chrono::nanoseconds, Timer_Callback)>::add_convention<_cancel, void(Timer_Id, Timer_Callback)>::add_convention<_reschedule, void(Timer_Id, std::chrono::nanoseconds)>::support_relocation::build {}; diff --git a/kernel/kernel/test/function/frame_policy/Throttled_Latest_Only_Tests.cpp b/kernel/kernel/module/frame_policy/test/Throttled_Latest_Only_Tests.cpp similarity index 99% rename from kernel/kernel/test/function/frame_policy/Throttled_Latest_Only_Tests.cpp rename to kernel/kernel/module/frame_policy/test/Throttled_Latest_Only_Tests.cpp index d2ec11e..f1ef64f 100644 --- a/kernel/kernel/test/function/frame_policy/Throttled_Latest_Only_Tests.cpp +++ b/kernel/kernel/module/frame_policy/test/Throttled_Latest_Only_Tests.cpp @@ -1,4 +1,4 @@ -#include "function/frame_policy/Throttled_Latest_Only.hpp" +#include "frame_policy/src/Throttled_Latest_Only.hpp" #include "statistics/Sliding_Statistics.hpp" #include diff --git a/kernel/kernel/module/main.cmake b/kernel/kernel/module/main.cmake new file mode 100644 index 0000000..157eafa --- /dev/null +++ b/kernel/kernel/module/main.cmake @@ -0,0 +1,26 @@ +function(aethera_kernel_add_module target module_name) + set(module_dir "${Aethera_Kernel_module_dir}/${module_name}") + append_glob_source(module_sources "${module_dir}/src" "${module_dir}/export") + add_library(${target} STATIC ${module_sources}) + target_include_directories(${target} PUBLIC "$") + target_link_libraries(${target} PUBLIC Aethera_Kernel_Core ${ARGN}) + append_glob_source(Aethera_Kernel_module_test_sources "${module_dir}/test") + set(Aethera_Kernel_module_test_sources "${Aethera_Kernel_module_test_sources}" PARENT_SCOPE) +endfunction() + +aethera_kernel_add_module(Aethera_Kernel_Task_Flow task_flow Taskflow::Taskflow) +add_library(Aethera_Kernel::Task_Flow ALIAS Aethera_Kernel_Task_Flow) +target_link_libraries(Aethera_Kernel_Task_Flow PRIVATE Threads::Threads) + +aethera_kernel_add_module(Aethera_Kernel_Time_Thread time_thread) +add_library(Aethera_Kernel::Time_Thread ALIAS Aethera_Kernel_Time_Thread) +target_link_libraries(Aethera_Kernel_Time_Thread PRIVATE Threads::Threads) + +aethera_kernel_add_module(Aethera_Kernel_Frame_Policy frame_policy Aethera_Kernel_Time_Thread) +add_library(Aethera_Kernel::Frame_Policy ALIAS Aethera_Kernel_Frame_Policy) + +aethera_kernel_add_module(Aethera_Kernel_Renderable renderable Aethera_Kernel_Task_Flow) +add_library(Aethera_Kernel::Renderable ALIAS Aethera_Kernel_Renderable) + +aethera_kernel_add_module(Aethera_Kernel_Scene scene Aethera_Kernel_Task_Flow Aethera_Kernel_Renderable Aethera_Kernel_Frame_Policy) +add_library(Aethera_Kernel::Scene ALIAS Aethera_Kernel_Scene) diff --git a/kernel/kernel/module/renderable/export/export.h b/kernel/kernel/module/renderable/export/export.h new file mode 100644 index 0000000..6f70f09 --- /dev/null +++ b/kernel/kernel/module/renderable/export/export.h @@ -0,0 +1 @@ +#pragma once diff --git a/kernel/kernel/module/renderable/src/rely_facade.h b/kernel/kernel/module/renderable/src/rely_facade.h new file mode 100644 index 0000000..0fc8700 --- /dev/null +++ b/kernel/kernel/module/renderable/src/rely_facade.h @@ -0,0 +1,12 @@ +#pragma once +#include "global.hpp" +#include "task_flow/export/export.h" +#include +#include +#include +#include + +namespace aethera::renderable { +struct Task_Graph : facade_builder::add_convention<_add, std::expected, aethera::Add_Task_Graph_Result>(std::string, std::function)>::add_convention<_component, proxy()>::add_convention<_clear, void()>::add_convention<_empty, bool() const noexcept>::support_relocation::build {}; +proxy make_task_graph(std::string name); +} // namespace aethera::renderable diff --git a/kernel/kernel/module/renderable/src/renderable.cpp b/kernel/kernel/module/renderable/src/renderable.cpp new file mode 100644 index 0000000..07de4a7 --- /dev/null +++ b/kernel/kernel/module/renderable/src/renderable.cpp @@ -0,0 +1,7 @@ +#include "renderable.hpp" +#include "task_flow/src/Task_Graph_Model.hpp" +#include + +namespace aethera { +proxy renderable::make_task_graph(std::string name) { return task_flow::make_task_graph(std::move(name)); } +} // namespace aethera diff --git a/kernel/kernel/include/function/renderable/renderable.hpp b/kernel/kernel/module/renderable/src/renderable.hpp similarity index 100% rename from kernel/kernel/include/function/renderable/renderable.hpp rename to kernel/kernel/module/renderable/src/renderable.hpp diff --git a/kernel/kernel/include/function/renderable/renderable.ipp b/kernel/kernel/module/renderable/src/renderable.ipp similarity index 76% rename from kernel/kernel/include/function/renderable/renderable.ipp rename to kernel/kernel/module/renderable/src/renderable.ipp index aea73a2..45324e1 100644 --- a/kernel/kernel/include/function/renderable/renderable.ipp +++ b/kernel/kernel/module/renderable/src/renderable.ipp @@ -2,7 +2,7 @@ namespace aethera { template struct Renderable::Private : Prev_Private { void advance(); - proxy taskflow(); + proxy taskflow(); proxy& internal_taskflow() noexcept { return graph; } private: proxy graph{renderable::make_task_graph("renderable")}; /* 唯一拥有本 Renderable 的任务图代理。 */ @@ -11,5 +11,5 @@ template void Renderable::Private::advance() { auto& private_data = static_cast(*this); if constexpr (requires { private_data.advance_renderable(); }) private_data.advance_renderable(); } -template proxy Renderable::Private::taskflow() { return graph->taskflow(); } +template proxy Renderable::Private::taskflow() { return graph->component(); } } // namespace aethera diff --git a/kernel/kernel/module/renderable/test/Renderable_Tests.cpp b/kernel/kernel/module/renderable/test/Renderable_Tests.cpp new file mode 100644 index 0000000..d97932d --- /dev/null +++ b/kernel/kernel/module/renderable/test/Renderable_Tests.cpp @@ -0,0 +1,19 @@ +#include "renderable/src/renderable.hpp" +#include "scene/src/rely_facade.h" +#include + +namespace { +struct Test_Renderable : aethera::Def> { + struct Private : Prev_Private { + void advance_renderable() { ++advance_count; auto& graph = internal_taskflow(); graph->clear(); (void)graph->add("test.prepare", [] {}); } + int advance_count{}; + }; +}; +static_assert(pro::proxiable, aethera::scene::Renderable>); + +TEST(Renderable, Facade_Uses_Private_Task_Graph_Capabilities) { + auto renderable = aethera::make_model_proxy(); + renderable->advance(); + EXPECT_TRUE(renderable->taskflow()); +} +} // namespace diff --git a/kernel/kernel/module/scene/export/export.h b/kernel/kernel/module/scene/export/export.h new file mode 100644 index 0000000..584c814 --- /dev/null +++ b/kernel/kernel/module/scene/export/export.h @@ -0,0 +1,6 @@ +#pragma once +#include + +namespace aethera { +enum struct Scene_Create_Taskflow_Result : std::uint8_t { component_unavailable, dependency_cycle, already_composed, dependency_unavailable }; +} // namespace aethera diff --git a/kernel/kernel/include/function/scene/Scene.cpp b/kernel/kernel/module/scene/src/Scene.cpp similarity index 68% rename from kernel/kernel/include/function/scene/Scene.cpp rename to kernel/kernel/module/scene/src/Scene.cpp index 06f63fb..802e15a 100644 --- a/kernel/kernel/include/function/scene/Scene.cpp +++ b/kernel/kernel/module/scene/src/Scene.cpp @@ -1,4 +1,5 @@ #include "Scene.hpp" +#include "task_flow/src/Task_Graph_Model.hpp" #include #include #include @@ -6,6 +7,7 @@ namespace aethera { namespace detail { struct Scene_Frame {}; } +proxy scene::make_task_graph(std::string name) { return task_flow::make_task_graph(std::move(name)); } Scene::Private::Private() = default; proxy Scene::Private::create_frame() { return pro::make_proxy(); @@ -15,21 +17,20 @@ proxy& Scene::Private::taskflow() { } auto Scene::Private::create_taskflow() -> std::expected, Create_Taskflow_Result> { auto result = scene::make_task_graph("scene.renderables"); - std::unordered_map> nodes; + std::unordered_map> nodes; auto& renderables = get().internal.use(); std::optional error; renderables.for_each_topological([&](Dag_Node_Id id, proxy& renderable) { if (error) return; - auto taskflow = renderable->taskflow(); - auto component = taskflow->component(); + auto component = renderable->taskflow(); auto composed = result->compose("renderable." + std::to_string(id.value), component); if (!composed) { switch (composed.error()) { - case scene::Compose_Task_Graph_Result::component_unavailable: error = Create_Taskflow_Result::component_unavailable; + case Compose_Task_Graph_Result::component_unavailable: error = Create_Taskflow_Result::component_unavailable; break; - case scene::Compose_Task_Graph_Result::dependency_cycle: error = Create_Taskflow_Result::dependency_cycle; + case Compose_Task_Graph_Result::dependency_cycle: error = Create_Taskflow_Result::dependency_cycle; break; - case scene::Compose_Task_Graph_Result::already_composed: error = Create_Taskflow_Result::already_composed; + case Compose_Task_Graph_Result::already_composed: error = Create_Taskflow_Result::already_composed; break; } return; @@ -38,7 +39,7 @@ auto Scene::Private::create_taskflow() -> std::expected }); if (error) return std::unexpected(*error); renderables.for_each_dependency([&](Dag_Node_Id target, Dag_Node_Id source) { - if (result->precede(nodes.at(source.value), nodes.at(target.value)) != scene::Precede_Task_Graph_Result::preceded) error = Create_Taskflow_Result::dependency_unavailable; + if (result->precede(nodes.at(source.value), nodes.at(target.value)) != Precede_Task_Graph_Result::preceded) error = Create_Taskflow_Result::dependency_unavailable; }); if (error) return std::unexpected(*error); return result; @@ -62,9 +63,10 @@ frame_policy::Render_Scene_Result Scene::Private::render(proxy diff --git a/kernel/kernel/include/function/scene/Scene.ipp b/kernel/kernel/module/scene/src/Scene.ipp similarity index 81% rename from kernel/kernel/include/function/scene/Scene.ipp rename to kernel/kernel/module/scene/src/Scene.ipp index 3d5a5ec..fccafa1 100644 --- a/kernel/kernel/include/function/scene/Scene.ipp +++ b/kernel/kernel/module/scene/src/Scene.ipp @@ -1,7 +1,7 @@ #pragma once namespace aethera { struct Scene::Private : Prev_Private { - enum struct Create_Taskflow_Result : std::uint8_t { component_unavailable, dependency_cycle, already_composed, dependency_unavailable }; + using Create_Taskflow_Result = Scene_Create_Taskflow_Result; Private(); proxy create_frame(); frame_policy::Render_Scene_Result render(proxy& frame, frame_policy::Render_Completion completion); diff --git a/kernel/kernel/module/scene/src/rely_facade.h b/kernel/kernel/module/scene/src/rely_facade.h new file mode 100644 index 0000000..8d426b2 --- /dev/null +++ b/kernel/kernel/module/scene/src/rely_facade.h @@ -0,0 +1,12 @@ +#pragma once +#include "global.hpp" +#include "task_flow/export/export.h" +#include +#include +#include + +namespace aethera::scene { +struct Task_Graph : facade_builder::add_convention<_component, proxy()>::add_convention<_compose, std::expected, aethera::Compose_Task_Graph_Result>(std::string, proxy&)>::add_convention<_precede, aethera::Precede_Task_Graph_Result(proxy&, proxy&)>::add_convention<_empty, bool() const noexcept>::add_convention<_run, aethera::Run_Taskflow_Result(aethera::Taskflow_Completion)>::support_relocation::build {}; +proxy make_task_graph(std::string name); +struct Renderable : facade_builder::add_convention<_advance, void()>::add_convention<_taskflow, proxy()>::support_relocation::build {}; +} // namespace aethera::scene diff --git a/kernel/kernel/module/scene/test/Scene_Tests.cpp b/kernel/kernel/module/scene/test/Scene_Tests.cpp new file mode 100644 index 0000000..664f3fb --- /dev/null +++ b/kernel/kernel/module/scene/test/Scene_Tests.cpp @@ -0,0 +1,103 @@ +#include "renderable/src/renderable.hpp" +#include "scene/src/Scene.hpp" +#include +#include +#include +#include +#include + +namespace { +struct Test_Renderable : aethera::Def> { + struct Private : Prev_Private { void advance_renderable() { auto& graph = internal_taskflow(); graph->clear(); (void)graph->add("test.prepare", [] {}); } }; +}; +struct Test_Dag_Renderable : aethera::Def> { + Test_Dag_Renderable(std::shared_ptr> advance_order, int id) : Def(std::move(advance_order), id) {} + struct Private : Prev_Private { + Private(std::shared_ptr> advance_order, int id) : advance_order(std::move(advance_order)), id(id) {} + void advance_renderable() { advance_order->push_back(id); auto& graph = internal_taskflow(); graph->clear(); (void)graph->add("prepare", [] {}); } + std::shared_ptr> advance_order; + int id{}; + }; +}; +static_assert(pro::proxiable, aethera::frame_policy::Scene>); + +TEST(Scene, Advances_Renderables_And_Composes_Task_Graph_In_Dag_Order) { + auto advance_order = std::make_shared>(); + aethera::Dag::Builder builder; + builder.add({2}, aethera::make_model_proxy(advance_order, 2)); + builder.add({1}, aethera::make_model_proxy(advance_order, 1)); + builder.add({3}, aethera::make_model_proxy(advance_order, 3)); + builder.add_dependency({2}, {1}); + builder.add_dependency({3}, {1}); + auto graph = builder.build(); + ASSERT_TRUE(graph.has_value()); + aethera::Scene scene; + EXPECT_TRUE(scene.d->create_frame()); + scene.write(std::move(*graph)); + EXPECT_TRUE(scene.d->advance().has_value()); + EXPECT_EQ(*advance_order, (std::vector{1, 2, 3})); + EXPECT_FALSE(scene.d->taskflow()->empty()); + advance_order->clear(); + std::optional edit_error; + scene.write([](aethera::Dag::Editor& editor) { editor.remove({99}); }, [&](std::expected result) { if (!result) edit_error = result.error(); }); + EXPECT_TRUE(scene.d->advance().has_value()); + ASSERT_TRUE(edit_error.has_value()); + EXPECT_EQ(*edit_error, aethera::Edit_Dag_Result::node_not_found); + EXPECT_EQ(*advance_order, (std::vector{1, 2, 3})); +} + +TEST(Scene, Dag_Rejects_Unallocated_Id_And_Missing_Object) { + aethera::Dag::Builder invalid_id_builder; + invalid_id_builder.add({0}, aethera::make_model_proxy()); + const auto invalid_id = invalid_id_builder.build(); + ASSERT_FALSE(invalid_id.has_value()); + EXPECT_EQ(invalid_id.error(), aethera::Build_Dag_Result::invalid_node_id); + aethera::Dag::Builder missing_object_builder; + missing_object_builder.add({1}, {}); + const auto missing_object = missing_object_builder.build(); + ASSERT_FALSE(missing_object.has_value()); + EXPECT_EQ(missing_object.error(), aethera::Build_Dag_Result::node_object_missing); +} + +TEST(Scene, Owned_Dag_Rolls_Back_The_Whole_Invalid_Edit) { + auto advance_order = std::make_shared>(); + aethera::Dag::Builder builder; + builder.add({1}, aethera::make_model_proxy(advance_order, 1)); + auto graph = builder.build(); + ASSERT_TRUE(graph.has_value()); + aethera::Scene scene; + scene.write(std::move(*graph)); + ASSERT_TRUE(scene.d->advance().has_value()); + advance_order->clear(); + std::optional edit_error; + scene.write([advance_order](aethera::Dag::Editor& editor) { editor.add({2}, aethera::make_model_proxy(advance_order, 2)); editor.add_dependency({2}, {99}); }, [&](std::expected result) { if (!result) edit_error = result.error(); }); + ASSERT_TRUE(scene.d->advance().has_value()); + ASSERT_TRUE(edit_error.has_value()); + EXPECT_EQ(*edit_error, aethera::Edit_Dag_Result::node_not_found); + EXPECT_EQ(*advance_order, (std::vector{1})); +} + +TEST(Scene, Render_Returns_Known_Submission_Result) { + aethera::Scene scene; + auto frame = scene.d->create_frame(); + bool completed{}; + EXPECT_EQ(scene.d->render(frame, [&](aethera::proxy&, std::exception_ptr) { completed = true; }), aethera::frame_policy::Render_Scene_Result::runtime_not_initialized); + EXPECT_FALSE(completed); + aethera::proxy empty_frame; + EXPECT_EQ(scene.d->render(empty_frame, [&](aethera::proxy&, std::exception_ptr) {}), aethera::frame_policy::Render_Scene_Result::frame_missing); + EXPECT_EQ(scene.d->render(frame, {}), aethera::frame_policy::Render_Scene_Result::completion_missing); +} + +TEST(Scene, Rejects_The_Same_Renderable_Task_Graph_Twice) { + Test_Renderable renderable; + aethera::Dag::Builder builder; + builder.add({1}, aethera::model_proxy_view(renderable)); + builder.add({2}, aethera::model_proxy_view(renderable)); + auto graph = builder.build(); + ASSERT_TRUE(graph.has_value()); + aethera::Scene scene; + scene.write(std::move(*graph)); + auto frame = scene.d->create_frame(); + EXPECT_EQ(scene.d->render(frame, [](aethera::proxy&, std::exception_ptr) {}), aethera::frame_policy::Render_Scene_Result::task_graph_invalid); +} +} // namespace diff --git a/kernel/kernel/module/task_flow/export/export.h b/kernel/kernel/module/task_flow/export/export.h new file mode 100644 index 0000000..778dc11 --- /dev/null +++ b/kernel/kernel/module/task_flow/export/export.h @@ -0,0 +1,25 @@ +#pragma once +#include "global.hpp" +#include +#include +#include +#include + +namespace aethera { +enum struct Add_Task_Graph_Result : std::uint8_t { work_missing }; +enum struct Add_Condition_Task_Graph_Result : std::uint8_t { condition_missing }; +enum struct Compose_Task_Graph_Result : std::uint8_t { component_unavailable, dependency_cycle, already_composed }; +enum struct Precede_Task_Graph_Result : std::uint8_t { preceded, node_unavailable, node_stale, different_graph }; +enum struct Describe_Task_Graph_Result : std::uint8_t { described, key_missing }; +enum struct Describe_Task_Graph_Node_Result : std::uint8_t { described, node_unavailable, node_stale, key_missing }; +enum struct Run_Taskflow_Result : std::uint8_t { submitted, runtime_not_initialized, completion_missing, observation_unavailable }; +enum struct Taskflow_Unknown_Failure_Policy : std::uint8_t { fast_fail, exception }; +enum struct Initialize_Task_Runtime_Result : std::uint8_t { initialized, invalid_worker_count, exception_boundary_missing, exception_boundary_unexpected, already_initialized, initialization_in_progress }; +enum struct Take_Taskflow_Observation_Result : std::uint8_t { not_recorded, recording, already_taken }; +using Taskflow_Completion = std::function; +using Taskflow_Exception_Boundary = std::function; +namespace task_flow { +struct Task_Node : facade_builder::add_skill::build {}; +struct Task_Graph_Component : facade_builder::add_skill::build {}; +} // namespace task_flow +} // namespace aethera diff --git a/kernel/kernel/include/task_flow/Task_Graph.cpp b/kernel/kernel/module/task_flow/src/Task_Graph.cpp similarity index 100% rename from kernel/kernel/include/task_flow/Task_Graph.cpp rename to kernel/kernel/module/task_flow/src/Task_Graph.cpp diff --git a/kernel/kernel/include/task_flow/Task_Graph.hpp b/kernel/kernel/module/task_flow/src/Task_Graph.hpp similarity index 98% rename from kernel/kernel/include/task_flow/Task_Graph.hpp rename to kernel/kernel/module/task_flow/src/Task_Graph.hpp index 25ad716..7bd1487 100644 --- a/kernel/kernel/include/task_flow/Task_Graph.hpp +++ b/kernel/kernel/module/task_flow/src/Task_Graph.hpp @@ -1,5 +1,5 @@ #pragma once -#include "Task_Graph_Types.hpp" +#include "../export/export.h" #include #include #include diff --git a/kernel/kernel/module/task_flow/src/Task_Graph_Model.hpp b/kernel/kernel/module/task_flow/src/Task_Graph_Model.hpp new file mode 100644 index 0000000..49d0b9c --- /dev/null +++ b/kernel/kernel/module/task_flow/src/Task_Graph_Model.hpp @@ -0,0 +1,30 @@ +#pragma once +#include "Task_Graph.hpp" +#include "../export/export.h" +#include "model/Model.hpp" +#include +#include +#include +#include + +namespace aethera::task_flow { +struct Task_Graph_Model : Def { + struct Private; + explicit Task_Graph_Model(std::shared_ptr graph) : Def(std::move(graph)) {} +}; + +struct Task_Graph_Model::Private : Prev_Private { + explicit Private(std::shared_ptr graph) : graph(std::move(graph)) {} + auto add(std::string name, std::function work) -> std::expected, Add_Task_Graph_Result>; + proxy component(); + auto compose(std::string name, proxy& child) -> std::expected, Compose_Task_Graph_Result>; + Precede_Task_Graph_Result precede(proxy& before, proxy& after); + void clear(); + bool empty() const noexcept; + Run_Taskflow_Result run(Taskflow_Completion completion); +private: + std::shared_ptr graph; /* 所有消费 facade 共享的唯一权威任务图。 */ +}; + +template proxy make_task_graph(std::string name) { return make_model_proxy(std::make_shared(std::move(name))); } +} // namespace aethera::task_flow diff --git a/kernel/kernel/include/task_flow/Task_Runtime.cpp b/kernel/kernel/module/task_flow/src/Task_Runtime.cpp similarity index 100% rename from kernel/kernel/include/task_flow/Task_Runtime.cpp rename to kernel/kernel/module/task_flow/src/Task_Runtime.cpp diff --git a/kernel/kernel/include/task_flow/Task_Runtime.hpp b/kernel/kernel/module/task_flow/src/Task_Runtime.hpp similarity index 77% rename from kernel/kernel/include/task_flow/Task_Runtime.hpp rename to kernel/kernel/module/task_flow/src/Task_Runtime.hpp index 7ee20e4..f63da6a 100644 --- a/kernel/kernel/include/task_flow/Task_Runtime.hpp +++ b/kernel/kernel/module/task_flow/src/Task_Runtime.hpp @@ -1,6 +1,6 @@ #pragma once #include "Task_Graph.hpp" -#include "Task_Runtime_Types.hpp" +#include "../export/export.h" #include "Taskflow_Observation.hpp" #include #include @@ -8,14 +8,6 @@ #include #include namespace aethera { -enum struct Initialize_Task_Runtime_Result : std::uint8_t { - initialized, - invalid_worker_count, - exception_boundary_missing, - exception_boundary_unexpected, - already_initialized, - initialization_in_progress -}; Initialize_Task_Runtime_Result initialize_task_runtime(std::size_t workers = std::thread::hardware_concurrency(), Taskflow_Unknown_Failure_Policy failure_policy = Taskflow_Unknown_Failure_Policy::fast_fail, Taskflow_Exception_Boundary exception_boundary = {}); /* 完成回调接收业务任务传播出的 Unknown Failure;本次执行不记录观察数据。 */ Run_Taskflow_Result run_taskflow( diff --git a/kernel/kernel/include/task_flow/Taskflow_Observation.cpp b/kernel/kernel/module/task_flow/src/Taskflow_Observation.cpp similarity index 100% rename from kernel/kernel/include/task_flow/Taskflow_Observation.cpp rename to kernel/kernel/module/task_flow/src/Taskflow_Observation.cpp diff --git a/kernel/kernel/include/task_flow/Taskflow_Observation.hpp b/kernel/kernel/module/task_flow/src/Taskflow_Observation.hpp similarity index 91% rename from kernel/kernel/include/task_flow/Taskflow_Observation.hpp rename to kernel/kernel/module/task_flow/src/Taskflow_Observation.hpp index 8ee3764..729bfdd 100644 --- a/kernel/kernel/include/task_flow/Taskflow_Observation.hpp +++ b/kernel/kernel/module/task_flow/src/Taskflow_Observation.hpp @@ -1,4 +1,5 @@ #pragma once +#include "../export/export.h" #include "Taskflow_Trace.hpp" #include #include @@ -8,11 +9,6 @@ namespace aethera { namespace detail { struct Taskflow_Observation_Execution; } -enum struct Take_Taskflow_Observation_Result : std::uint8_t { - not_recorded, - recording, - already_taken -}; /* * 前台诊断显式请求的单次 Taskflow 执行记录,例如连续请求 N 帧时为每帧分别创建一个对象。 * 它只给帧附加原始任务执行信息,不属于业务状态、持续事件流或可复用快照;未传入执行接口时不记录。 diff --git a/kernel/kernel/include/task_flow/Taskflow_Trace.hpp b/kernel/kernel/module/task_flow/src/Taskflow_Trace.hpp similarity index 100% rename from kernel/kernel/include/task_flow/Taskflow_Trace.hpp rename to kernel/kernel/module/task_flow/src/Taskflow_Trace.hpp diff --git a/kernel/kernel/include/task_flow/design.md b/kernel/kernel/module/task_flow/src/design.md similarity index 100% rename from kernel/kernel/include/task_flow/design.md rename to kernel/kernel/module/task_flow/src/design.md diff --git a/kernel/kernel/include/task_flow/detail/Taskflow_Execution.ipp b/kernel/kernel/module/task_flow/src/detail/Taskflow_Execution.ipp similarity index 99% rename from kernel/kernel/include/task_flow/detail/Taskflow_Execution.ipp rename to kernel/kernel/module/task_flow/src/detail/Taskflow_Execution.ipp index 8b24a0a..f55f6bb 100644 --- a/kernel/kernel/include/task_flow/detail/Taskflow_Execution.ipp +++ b/kernel/kernel/module/task_flow/src/detail/Taskflow_Execution.ipp @@ -1,6 +1,6 @@ #pragma once #include "../Task_Graph.hpp" -#include "../Task_Runtime_Types.hpp" +#include "../../export/export.h" #include "../Taskflow_Observation.hpp" #include "../Taskflow_Trace.hpp" #include diff --git a/kernel/kernel/include/task_flow/rely_facade.h b/kernel/kernel/module/task_flow/src/rely_facade.h similarity index 100% rename from kernel/kernel/include/task_flow/rely_facade.h rename to kernel/kernel/module/task_flow/src/rely_facade.h diff --git a/kernel/kernel/module/task_flow/src/task_flow_facade.cpp b/kernel/kernel/module/task_flow/src/task_flow_facade.cpp new file mode 100644 index 0000000..fa8a60f --- /dev/null +++ b/kernel/kernel/module/task_flow/src/task_flow_facade.cpp @@ -0,0 +1,37 @@ +#include "Task_Graph_Model.hpp" +#include "Task_Runtime.hpp" +#include + +namespace aethera::task_flow { +namespace detail { +struct Proxied_Task_Node { explicit Proxied_Task_Node(aethera::Task_Node value) : value(std::move(value)) {} aethera::Task_Node value; }; +struct Proxied_Task_Graph_Component { explicit Proxied_Task_Graph_Component(std::shared_ptr value) : value(std::move(value)) {} std::shared_ptr value; }; +} // namespace detail + +auto Task_Graph_Model::Private::add(std::string name, std::function work) -> std::expected, Add_Task_Graph_Result> { + auto result = graph->add(std::move(name), std::move(work)); + if (!result) return std::unexpected(result.error()); + return pro::make_proxy(std::move(*result)); +} + +proxy Task_Graph_Model::Private::component() { return pro::make_proxy(graph); } + +auto Task_Graph_Model::Private::compose(std::string name, proxy& child) -> std::expected, Compose_Task_Graph_Result> { + auto* component = child ? proxy_cast(&*child) : nullptr; + if (component == nullptr) return std::unexpected(Compose_Task_Graph_Result::component_unavailable); + auto result = graph->compose(std::move(name), *component->value); + if (!result) return std::unexpected(result.error()); + return pro::make_proxy(std::move(*result)); +} + +Precede_Task_Graph_Result Task_Graph_Model::Private::precede(proxy& before, proxy& after) { + auto* before_node = before ? proxy_cast(&*before) : nullptr; + auto* after_node = after ? proxy_cast(&*after) : nullptr; + if (before_node == nullptr || after_node == nullptr) return Precede_Task_Graph_Result::node_unavailable; + return before_node->value.precede(after_node->value); +} + +void Task_Graph_Model::Private::clear() { graph->clear(); } +bool Task_Graph_Model::Private::empty() const noexcept { return graph->empty(); } +Run_Taskflow_Result Task_Graph_Model::Private::run(Taskflow_Completion completion) { return run_taskflow(*graph, std::move(completion)); } +} // namespace aethera::task_flow diff --git a/kernel/kernel/test/task_flow/Taskflow_Observation_Tests.cpp b/kernel/kernel/module/task_flow/test/Taskflow_Observation_Tests.cpp similarity index 98% rename from kernel/kernel/test/task_flow/Taskflow_Observation_Tests.cpp rename to kernel/kernel/module/task_flow/test/Taskflow_Observation_Tests.cpp index bd47f9c..a1d9a44 100644 --- a/kernel/kernel/test/task_flow/Taskflow_Observation_Tests.cpp +++ b/kernel/kernel/module/task_flow/test/Taskflow_Observation_Tests.cpp @@ -1,5 +1,5 @@ -#include "task_flow/Task_Runtime.hpp" -#include "task_flow/detail/Taskflow_Execution.ipp" +#include "task_flow/src/Task_Runtime.hpp" +#include "../src/detail/Taskflow_Execution.ipp" #include diff --git a/kernel/kernel/module/time_thread/export/export.h b/kernel/kernel/module/time_thread/export/export.h new file mode 100644 index 0000000..cfe4f71 --- /dev/null +++ b/kernel/kernel/module/time_thread/export/export.h @@ -0,0 +1,11 @@ +#pragma once +#include +#include +#include + +namespace aethera { +using Timer_Id = std::uint64_t; +using Timer_Callback = std::function; +using Timer_Time_Point = std::chrono::steady_clock::time_point; +enum struct Make_Timer_Service_Result : std::uint8_t { time_source_unavailable }; +} // namespace aethera diff --git a/kernel/kernel/include/time_thread/Timer_Service.cpp b/kernel/kernel/module/time_thread/src/Timer_Service.cpp similarity index 84% rename from kernel/kernel/include/time_thread/Timer_Service.cpp rename to kernel/kernel/module/time_thread/src/Timer_Service.cpp index 0b56e4a..cbce0e6 100644 --- a/kernel/kernel/include/time_thread/Timer_Service.cpp +++ b/kernel/kernel/module/time_thread/src/Timer_Service.cpp @@ -1,8 +1,7 @@ #include "Timer_Service.hpp" +#include "Timer_Service_Model.hpp" #include "detail/Timer_Scheduler.hpp" -#include "function/frame_policy/rely_facade.h" -#include "model/Model.hpp" #include #include @@ -22,7 +21,10 @@ struct Steady_Timer_Time_Source : Def { struct Steady_Timer_Time_Source::Private : Prev_Private { Timer_Time_Point now() const noexcept { return std::chrono::steady_clock::now(); } }; +} // namespace +namespace time_thread { +namespace detail = aethera::detail; struct Thread_Timer_Service_State : Immovable { struct Impl { static constexpr std::chrono::seconds Maximum_Wait{1}; @@ -189,19 +191,13 @@ struct Thread_Timer_Service_State : Immovable { std::shared_ptr impl; /* proxy 与计时线程共享的运行状态所有权。 */ }; -struct Thread_Timer_Service : Def { - struct Private; - explicit Thread_Timer_Service(proxy time_source) : Def(std::move(time_source)) {} -}; -struct Thread_Timer_Service::Private : Prev_Private { - explicit Private(proxy time_source) : state(std::move(time_source)) {} - Timer_Id schedule_after(std::chrono::nanoseconds delay, Timer_Callback callback) { return state.schedule_after(delay, std::move(callback)); } - Timer_Id schedule_every(std::chrono::nanoseconds interval, Timer_Callback callback) { return state.schedule_every(interval, std::move(callback)); } - void reschedule(Timer_Id id, std::chrono::nanoseconds delay) { state.reschedule(id, delay); } - void cancel(Timer_Id id, Timer_Callback completion) { state.cancel(id, std::move(completion)); } - Thread_Timer_Service_State state; -}; -} +} // namespace time_thread + +Timer_Id time_thread::Timer_Service_Model::Private::schedule_after(std::chrono::nanoseconds delay, Timer_Callback callback) { return state->schedule_after(delay, std::move(callback)); } +Timer_Id time_thread::Timer_Service_Model::Private::schedule_every(std::chrono::nanoseconds interval, Timer_Callback callback) { return state->schedule_every(interval, std::move(callback)); } +void time_thread::Timer_Service_Model::Private::reschedule(Timer_Id id, std::chrono::nanoseconds delay) { state->reschedule(id, delay); } +void time_thread::Timer_Service_Model::Private::cancel(Timer_Id id, Timer_Callback completion) { state->cancel(id, std::move(completion)); } +std::shared_ptr time_thread::make_timer_service_state(proxy time_source) { return std::make_shared(std::move(time_source)); } proxy make_steady_timer_time_source() { return make_model_proxy(); } @@ -211,9 +207,6 @@ make_timer_service(proxy time_source) { return std::unexpected( Make_Timer_Service_Result::time_source_unavailable); } - return make_model_proxy_shared(std::move(time_source)); -} -proxy frame_policy::make_timer_service() { - return make_model_proxy_shared(make_steady_timer_time_source()); + return time_thread::make_timer_service_proxy(std::move(time_source)); } } diff --git a/kernel/kernel/include/time_thread/Timer_Service.hpp b/kernel/kernel/module/time_thread/src/Timer_Service.hpp similarity index 82% rename from kernel/kernel/include/time_thread/Timer_Service.hpp rename to kernel/kernel/module/time_thread/src/Timer_Service.hpp index 8beabfa..e8ee61c 100644 --- a/kernel/kernel/include/time_thread/Timer_Service.hpp +++ b/kernel/kernel/module/time_thread/src/Timer_Service.hpp @@ -1,5 +1,6 @@ #pragma once +#include "../export/export.h" #include "Timer_Time_Source.hpp" #include @@ -9,10 +10,6 @@ #include namespace aethera { -using Timer_Id = std::uint64_t; -using Timer_Callback = std::function; - - struct Timer_Service : facade_builder ::add_convention< _schedule_every, @@ -29,10 +26,6 @@ struct Timer_Service : facade_builder ::support_relocation ::build {}; -enum struct Make_Timer_Service_Result : std::uint8_t { - time_source_unavailable -}; - [[nodiscard]] std::expected, Make_Timer_Service_Result> make_timer_service(proxy time_source); } diff --git a/kernel/kernel/module/time_thread/src/Timer_Service_Model.hpp b/kernel/kernel/module/time_thread/src/Timer_Service_Model.hpp new file mode 100644 index 0000000..39d00fc --- /dev/null +++ b/kernel/kernel/module/time_thread/src/Timer_Service_Model.hpp @@ -0,0 +1,27 @@ +#pragma once +#include "Timer_Service.hpp" +#include "model/Model.hpp" +#include +#include + +namespace aethera::time_thread { +struct Thread_Timer_Service_State; + +struct Timer_Service_Model : Def { + struct Private; + explicit Timer_Service_Model(std::shared_ptr state) : Def(std::move(state)) {} +}; + +struct Timer_Service_Model::Private : Prev_Private { + explicit Private(std::shared_ptr state) : state(std::move(state)) {} + Timer_Id schedule_after(std::chrono::nanoseconds delay, Timer_Callback callback); + Timer_Id schedule_every(std::chrono::nanoseconds interval, Timer_Callback callback); + void reschedule(Timer_Id id, std::chrono::nanoseconds delay); + void cancel(Timer_Id id, Timer_Callback completion); +private: + std::shared_ptr state; /* facade 与计时线程共享同一运行状态所有权。 */ +}; + +std::shared_ptr make_timer_service_state(proxy time_source); +template proxy make_timer_service_proxy(proxy time_source) { return make_model_proxy_shared(make_timer_service_state(std::move(time_source))); } +} // namespace aethera::time_thread diff --git a/kernel/kernel/include/time_thread/Timer_Time_Source.hpp b/kernel/kernel/module/time_thread/src/Timer_Time_Source.hpp similarity index 83% rename from kernel/kernel/include/time_thread/Timer_Time_Source.hpp rename to kernel/kernel/module/time_thread/src/Timer_Time_Source.hpp index 6eda186..0d9e19f 100644 --- a/kernel/kernel/include/time_thread/Timer_Time_Source.hpp +++ b/kernel/kernel/module/time_thread/src/Timer_Time_Source.hpp @@ -1,15 +1,12 @@ #pragma once +#include "../export/export.h" #include "global.hpp" #include #include namespace aethera { -using Timer_Time_Point = std::chrono::steady_clock::time_point; - - - struct Timer_Time_Source : facade_builder::add_convention<_now, Timer_Time_Point() const noexcept>::support_relocation::build {}; [[nodiscard]] proxy make_steady_timer_time_source(); diff --git a/kernel/kernel/include/time_thread/detail/Timer_Scheduler.cpp b/kernel/kernel/module/time_thread/src/detail/Timer_Scheduler.cpp similarity index 100% rename from kernel/kernel/include/time_thread/detail/Timer_Scheduler.cpp rename to kernel/kernel/module/time_thread/src/detail/Timer_Scheduler.cpp diff --git a/kernel/kernel/include/time_thread/detail/Timer_Scheduler.hpp b/kernel/kernel/module/time_thread/src/detail/Timer_Scheduler.hpp similarity index 89% rename from kernel/kernel/include/time_thread/detail/Timer_Scheduler.hpp rename to kernel/kernel/module/time_thread/src/detail/Timer_Scheduler.hpp index 3244c68..1df437a 100644 --- a/kernel/kernel/include/time_thread/detail/Timer_Scheduler.hpp +++ b/kernel/kernel/module/time_thread/src/detail/Timer_Scheduler.hpp @@ -1,7 +1,7 @@ #pragma once -#include "time_thread/Timer_Service.hpp" -#include "time_thread/Timer_Time_Source.hpp" +#include "../Timer_Service.hpp" +#include "../Timer_Time_Source.hpp" #include #include diff --git a/kernel/kernel/include/time_thread/rely_facade.h b/kernel/kernel/module/time_thread/src/rely_facade.h similarity index 100% rename from kernel/kernel/include/time_thread/rely_facade.h rename to kernel/kernel/module/time_thread/src/rely_facade.h diff --git a/kernel/kernel/test/time_thread/Timer_Service_Tests.cpp b/kernel/kernel/module/time_thread/test/Timer_Service_Tests.cpp similarity index 96% rename from kernel/kernel/test/time_thread/Timer_Service_Tests.cpp rename to kernel/kernel/module/time_thread/test/Timer_Service_Tests.cpp index d21af79..5949248 100644 --- a/kernel/kernel/test/time_thread/Timer_Service_Tests.cpp +++ b/kernel/kernel/module/time_thread/test/Timer_Service_Tests.cpp @@ -1,6 +1,6 @@ -#include "time_thread/Timer_Service.hpp" -#include "time_thread/Timer_Time_Source.hpp" -#include "time_thread/detail/Timer_Scheduler.hpp" +#include "time_thread/src/Timer_Service.hpp" +#include "time_thread/src/Timer_Time_Source.hpp" +#include "../src/detail/Timer_Scheduler.hpp" #include "model/Model.hpp" #include diff --git a/kernel/kernel/test/model/Model_Tests.cpp b/kernel/kernel/test/model/Model_Tests.cpp index 5fba618..84444cd 100644 --- a/kernel/kernel/test/model/Model_Tests.cpp +++ b/kernel/kernel/test/model/Model_Tests.cpp @@ -1,22 +1,14 @@ #include "concurrent/base/Concurrent_List.hpp" -#include "../../include/function/renderable/renderable.hpp" -#include "../../include/function/scene/Scene.hpp" #include "model/Model.hpp" #include -#include -#include -#include #include + namespace { PRO_DEF_MEM_DISPATCH(Test_Model_Private_Read, private_value); struct Test_Model_Private_Facade : aethera::facade_builder::add_convention::support_relocation::build {}; PRO_DEF_MEM_DISPATCH(Other_Test_Model_Private_Read, other_private_value); struct Other_Test_Model_Private_Facade : aethera::facade_builder::add_convention::support_relocation::build {}; -struct Test_Model_Prop { - int base_number{}; - int number{}; - int other{}; -}; +struct Test_Model_Prop { int base_number{}; int number{}; int other{}; }; struct Test_Model_Numbers : std::vector {}; struct Test_Model_Base : aethera::Model_Layer, aethera::Storage_Registration> { using Prop = Test_Model_Prop; @@ -25,30 +17,11 @@ struct Test_Model_Base : aethera::Model_Layer { - struct Private : Prev_Private { - int private_value() const { return 41; } - int other_private_value() const { return 43; } - }; + struct Private : Prev_Private { int private_value() const { return 41; } int other_private_value() const { return 43; } }; }; -struct Test_Renderable : aethera::Def> { - struct Private : Prev_Private { - void advance_renderable() { ++advance_count; auto& graph = internal_taskflow(); graph->clear(); (void)graph->add("test.prepare", [] {}); } - int advance_count{}; - }; -}; -struct Test_Dag_Renderable : aethera::Def> { - Test_Dag_Renderable(std::shared_ptr> advance_order, int id) : Def(std::move(advance_order), id) {} - struct Private : Prev_Private { - Private(std::shared_ptr> advance_order, int id) : advance_order(std::move(advance_order)), id(id) {} - void advance_renderable() { advance_order->push_back(id); auto& graph = internal_taskflow(); graph->clear(); (void)graph->add("prepare", [] {}); } - std::shared_ptr> advance_order; - int id{}; - }; -}; -static_assert(pro::proxiable, aethera::scene::Renderable>); -static_assert(pro::proxiable, aethera::frame_policy::Scene>); static_assert(pro::proxiable, Test_Model_Private_Facade>); static_assert(pro::proxiable, Other_Test_Model_Private_Facade>); + TEST(Model, Registered_Value_Types_Build_Independent_Storages) { Test_Model::Builder builder; int struct_initializer_calls{}; @@ -68,6 +41,7 @@ TEST(Model, Registered_Value_Types_Build_Independent_Storages) { numbers.internal.advance(); EXPECT_EQ(*numbers.internal.use(), (std::vector{13, 17})); } + TEST(Model, Registered_Struct_Write_Publishes_To_The_Same_Tagged_Storage) { auto model = Test_Model::Builder{}.build(); model->write(&Test_Model_Prop::number, 13); @@ -75,91 +49,11 @@ TEST(Model, Registered_Struct_Write_Publishes_To_The_Same_Tagged_Storage) { properties.internal.advance(); EXPECT_EQ(properties.internal.use()->number, 13); } + TEST(Model, Consumer_Facade_Selects_One_Model_Private_View) { auto model = aethera::make_model_proxy(); EXPECT_EQ(model->private_value(), 41); auto other_model = aethera::make_model_proxy(); EXPECT_EQ(other_model->other_private_value(), 43); } -TEST(Model, Renderable_Facade_Uses_Private_Task_Graph_Capabilities) { - auto renderable = aethera::make_model_proxy(); - renderable->advance(); - auto graph = renderable->taskflow(); - EXPECT_TRUE(graph); -} -TEST(Model, Scene_Advances_Renderables_And_Composes_Task_Graph_In_Dag_Order) { - auto advance_order = std::make_shared>(); - aethera::Dag::Builder builder; - builder.add({2}, aethera::make_model_proxy(advance_order, 2)); - builder.add({1}, aethera::make_model_proxy(advance_order, 1)); - builder.add({3}, aethera::make_model_proxy(advance_order, 3)); - builder.add_dependency({2}, {1}); - builder.add_dependency({3}, {1}); - auto graph = builder.build(); - ASSERT_TRUE(graph.has_value()); - aethera::Scene scene; - EXPECT_TRUE(scene.d->create_frame()); - scene.write(std::move(*graph)); - EXPECT_TRUE(scene.d->advance().has_value()); - EXPECT_EQ(*advance_order, (std::vector{1, 2, 3})); - EXPECT_FALSE(scene.d->taskflow()->empty()); - advance_order->clear(); - std::optional edit_error; - scene.write([](aethera::Dag::Editor& editor) { editor.remove({99}); }, [&](std::expected result) { if (!result) edit_error = result.error(); }); - EXPECT_TRUE(scene.d->advance().has_value()); - ASSERT_TRUE(edit_error.has_value()); - EXPECT_EQ(*edit_error, aethera::Edit_Dag_Result::node_not_found); - EXPECT_EQ(*advance_order, (std::vector{1, 2, 3})); -} -TEST(Model, Dag_Rejects_Unallocated_Id_And_Missing_Object) { - aethera::Dag::Builder invalid_id_builder; - invalid_id_builder.add({0}, aethera::make_model_proxy()); - const auto invalid_id = invalid_id_builder.build(); - ASSERT_FALSE(invalid_id.has_value()); - EXPECT_EQ(invalid_id.error(), aethera::Build_Dag_Result::invalid_node_id); - aethera::Dag::Builder missing_object_builder; - missing_object_builder.add({1}, {}); - const auto missing_object = missing_object_builder.build(); - ASSERT_FALSE(missing_object.has_value()); - EXPECT_EQ(missing_object.error(), aethera::Build_Dag_Result::node_object_missing); -} -TEST(Model, Owned_Dag_Rolls_Back_The_Whole_Invalid_Edit) { - auto advance_order = std::make_shared>(); - aethera::Dag::Builder builder; - builder.add({1}, aethera::make_model_proxy(advance_order, 1)); - auto graph = builder.build(); - ASSERT_TRUE(graph.has_value()); - aethera::Scene scene; - scene.write(std::move(*graph)); - ASSERT_TRUE(scene.d->advance().has_value()); - advance_order->clear(); - std::optional edit_error; - scene.write([advance_order](aethera::Dag::Editor& editor) { editor.add({2}, aethera::make_model_proxy(advance_order, 2)); editor.add_dependency({2}, {99}); }, [&](std::expected result) { if (!result) edit_error = result.error(); }); - ASSERT_TRUE(scene.d->advance().has_value()); - ASSERT_TRUE(edit_error.has_value()); - EXPECT_EQ(*edit_error, aethera::Edit_Dag_Result::node_not_found); - EXPECT_EQ(*advance_order, (std::vector{1})); -} -TEST(Model, Scene_Render_Returns_Known_Submission_Result) { - aethera::Scene scene; - auto frame = scene.d->create_frame(); - bool completed{}; - EXPECT_EQ(scene.d->render(frame, [&](aethera::proxy&, std::exception_ptr) { completed = true; }), aethera::frame_policy::Render_Scene_Result::runtime_not_initialized); - EXPECT_FALSE(completed); - aethera::proxy empty_frame; - EXPECT_EQ(scene.d->render(empty_frame, [&](aethera::proxy&, std::exception_ptr) {}), aethera::frame_policy::Render_Scene_Result::frame_missing); - EXPECT_EQ(scene.d->render(frame, {}), aethera::frame_policy::Render_Scene_Result::completion_missing); -} -TEST(Model, Scene_Rejects_The_Same_Renderable_Task_Graph_Twice) { - Test_Renderable renderable; - aethera::Dag::Builder builder; - builder.add({1}, aethera::model_proxy_view(renderable)); - builder.add({2}, aethera::model_proxy_view(renderable)); - auto graph = builder.build(); - ASSERT_TRUE(graph.has_value()); - aethera::Scene scene; - scene.write(std::move(*graph)); - auto frame = scene.d->create_frame(); - EXPECT_EQ(scene.d->render(frame, [](aethera::proxy&, std::exception_ptr) {}), aethera::frame_policy::Render_Scene_Result::task_graph_invalid); -} } // namespace diff --git a/kernel/main.cmake b/kernel/main.cmake index 1cac24d..902adb0 100644 --- a/kernel/main.cmake +++ b/kernel/main.cmake @@ -25,27 +25,35 @@ if (Aethera_BUILD_TESTS) find_package(benchmark CONFIG REQUIRED) endif () set(Aethera_Kernel_source_dir "${CMAKE_CURRENT_LIST_DIR}/kernel/include") +set(Aethera_Kernel_module_dir "${CMAKE_CURRENT_LIST_DIR}/kernel/module") set(Aethera_concurrentqueue_dir "${CMAKE_CURRENT_LIST_DIR}/third_party/concurrentqueue-1.0.5") add_subdirectory("${Aethera_concurrentqueue_dir}" "${CMAKE_CURRENT_BINARY_DIR}/aethera_concurrentqueue" EXCLUDE_FROM_ALL) -append_glob_source(Aethera_Kernel_sources "${Aethera_Kernel_source_dir}") -add_library(Aethera_Kernel STATIC ${Aethera_Kernel_sources}) -target_include_directories(Aethera_Kernel PUBLIC +append_glob_source(Aethera_Kernel_Core_sources "${Aethera_Kernel_source_dir}") +add_library(Aethera_Kernel_Core STATIC ${Aethera_Kernel_Core_sources}) +target_include_directories(Aethera_Kernel_Core PUBLIC "$" "$" "$" ) -target_compile_features(Aethera_Kernel PUBLIC cxx_std_20) -target_link_libraries(Aethera_Kernel PUBLIC - Taskflow::Taskflow +target_compile_features(Aethera_Kernel_Core PUBLIC cxx_std_20) +target_link_libraries(Aethera_Kernel_Core PUBLIC magic_enum::magic_enum msft_proxy4::proxy "$" ) -target_link_libraries(Aethera_Kernel PRIVATE Threads::Threads) if (MSVC) - target_compile_options(Aethera_Kernel PUBLIC /utf-8) + target_compile_options(Aethera_Kernel_Core PUBLIC /utf-8) endif () +include("${Aethera_Kernel_module_dir}/main.cmake") +add_library(Aethera_Kernel INTERFACE) +target_link_libraries(Aethera_Kernel INTERFACE + Aethera_Kernel_Core + Aethera_Kernel_Task_Flow + Aethera_Kernel_Time_Thread + Aethera_Kernel_Renderable + Aethera_Kernel_Scene + Aethera_Kernel_Frame_Policy) if (Aethera_BUILD_TESTS) set(Aethera_Kernel_test_dir "${CMAKE_CURRENT_LIST_DIR}/kernel/test") set(Aethera_Kernel_cdb @@ -57,10 +65,7 @@ if (Aethera_BUILD_TESTS) append_glob_source(Aethera_Kernel_module_test_sources "${Aethera_Kernel_test_dir}/concurrent" - "${Aethera_Kernel_test_dir}/model" - "${Aethera_Kernel_test_dir}/task_flow" - "${Aethera_Kernel_test_dir}/time_thread" - "${Aethera_Kernel_test_dir}/function/frame_policy") + "${Aethera_Kernel_test_dir}/model") foreach (Aethera_Kernel_module_test_source IN LISTS Aethera_Kernel_module_test_sources) if (NOT Aethera_Kernel_module_test_source MATCHES "\\.(c|cc|cpp|cxx)$") continue()