diff --git a/kernel/src/kernel/base/object.hpp b/kernel/src/kernel/base/object.hpp index ad7da77..ba48554 100644 --- a/kernel/src/kernel/base/object.hpp +++ b/kernel/src/kernel/base/object.hpp @@ -36,6 +36,13 @@ concept Impl_Mechanisms = requires { requires Rely_List>; }; } +template +concept Attached = requires { + requires Object_Core; + typename T::Attached_Object; + requires Object_Root; + requires std::derived_from; +}; template requires detail::Impl_Mechanisms struct Impl : Base { @@ -59,13 +66,14 @@ struct Impl : Base { void after_exchange(Self*, Prop*, State*, const Prop*, const State*) {} }; using Prev_Private = Private; -}; -template -concept Attached = requires { - requires Object_Core; - typename T::Attached_Object; - requires Object_Root; - requires std::derived_from; + template + static void walk_private(Object* object, Callback& callback) { + if constexpr (requires { typename Layer::Prev_Object; }) { + if constexpr (!Reverse) walk_private(object, callback); + callback(static_cast(object->d)); + if constexpr (Reverse) walk_private(object, callback); + } + } }; template struct Attach_Object : Obj { diff --git a/kernel/src/kernel/render_2D.hpp b/kernel/src/kernel/render_2D.hpp index 03b534a..7c8b583 100644 --- a/kernel/src/kernel/render_2D.hpp +++ b/kernel/src/kernel/render_2D.hpp @@ -1,3 +1,4 @@ +#pragma once #include "base.hpp" #include namespace aethera::_2D { @@ -5,22 +6,13 @@ struct Prepare_Data_Tag {}; struct Paint_Tag {}; namespace detail { using Flow_Message = oneapi::tbb::flow::continue_msg; -using Flow_Async_Node = oneapi::tbb::flow::async_node; -using Flow_Gateway = typename Flow_Async_Node::gateway_type; -template -concept Sync_Task = std::invocable; -template -concept Async_Task = std::invocable; } struct Color_Cache {}; struct Secene; struct Renderable : Impl> { public: - using Message = detail::Flow_Message; - using Async_Node = detail::Flow_Async_Node; - using Gateway = detail::Flow_Gateway; + struct Private; struct Node_Data { - void (*prepare)(Root*, Gateway&){}; Renderable* renderable{}; }; struct Prop : Prev_Prop {}; @@ -28,17 +20,7 @@ public: bool operator==(const State&) const = default; }; private: - using Task_Call = void (*)(void*, Gateway&); - using Task_State = std::tuple; Node_Data node_data; - template - static void walk_private(Object* object, Callback& callback) { - if constexpr (requires { typename Layer::Prev_Object; }) { - if constexpr (!Reverse) walk_private(object, callback); - callback(static_cast(object->d)); - if constexpr (Reverse) walk_private(object, callback); - } - } protected: template static void execute_prepare_data(Object* object) { @@ -55,49 +37,6 @@ protected: } public: struct Private : Prev_Private { - template Context> - static void set_sync(Double_Buffer& buffer, Context* context, bool initial) { - Task_State task{ - context, - [](void* value, Gateway& gateway) { - std::invoke(Callback, static_cast(value)); - (void)gateway.try_put(Message{}); - } - }; - *buffer.cache = task; - if (initial) *buffer.render = task; - } - template Context> - static void set_async(Double_Buffer& buffer, Context* context, bool initial) { - Task_State task{ - context, - [](void* value, Gateway& gateway) { - gateway.reserve_wait(); - std::invoke(Callback, static_cast(value), gateway); - } - }; - *buffer.cache = task; - if (initial) *buffer.render = task; - } - static void publish(Double_Buffer& buffer) { - Task_State value = *buffer.cache; - buffer.exchange(); - *buffer.cache = value; - } - template - static void prepare(Object* object) { - execute_prepare_data(object); - } - template - static void bind(Renderable* renderable, Object* object) { - renderable->paint_call = [](Renderable* value) { - auto* current = static_cast(value); - auto& private_data = static_cast(current->d); - private_data.template paint(current); - }; - set_sync<&Private::template prepare>(renderable->prepare_task, object, true); - set_sync<&Object::paint>(renderable->paint_task, object, true); - } template void prepare_data(Object*) {} template @@ -105,43 +44,31 @@ public: static_cast(object)->paint_dirty = true; } template - void after_exchange( - Object* object, - typename Object::Prop*, - typename Object::State*, - const typename Object::Prop*, - const typename Object::State*) { - auto* renderable = static_cast(object); - publish(renderable->prepare_task); - publish(renderable->paint_task); - } - template void paint(Object*) {} }; private: using Call = void (*)(Renderable*); + Call prepare_call{}; Call paint_call{}; bool paint_dirty{true}; - Double_Buffer prepare_task; - Double_Buffer paint_task; friend struct Secene; protected: template void bind_object_crtp() { Prev_Object::template bind_object_crtp(); - Private::bind(this, static_cast(this)); + prepare_call = [](Renderable* value) { + execute_prepare_data(static_cast(value)); + }; + paint_call = [](Renderable* value) { + auto* current = static_cast(value); + auto& private_data = static_cast(current->d); + private_data.template paint(current); + }; } public: template void bind_rely_node(Rely::Node* node) { - if (!node_data.prepare) { - auto* object = static_cast(this); - object->template mark_dirty(); - node_data.prepare = [](Root* root, Gateway& gateway) { - execute_prepare_data(static_cast(root)); - (void)gateway.try_put(Message{}); - }; - } + if (!node_data.renderable) mark_dirty(); node_data.renderable = this; node->data = &node_data; } @@ -162,51 +89,6 @@ public: void paint() { paint_call(this); } - template Context> - void set_prepare_task(Context* context) { - Private::template set_sync(prepare_task, context, false); - } - template Context> - void set_prepare_async_task(Context* context) { - Private::template set_async(prepare_task, context, false); - } - template Context> - void set_paint_task(Context* context) { - Private::template set_sync(paint_task, context, false); - } - template Context> - void set_paint_async_task(Context* context) { - Private::template set_async(paint_task, context, false); - } - template - struct Builder : Prev_Builder { - using Base = Prev_Builder; - using Base::Base; - template requires detail::Sync_Task - Builder& set_prepare_task() { - auto* renderable = static_cast(this->object.get()); - Private::template set_sync(renderable->prepare_task, this->object.get(), true); - return *this; - } - template requires detail::Async_Task - Builder& set_prepare_async_task() { - auto* renderable = static_cast(this->object.get()); - Private::template set_async(renderable->prepare_task, this->object.get(), true); - return *this; - } - template requires detail::Sync_Task - Builder& set_paint_task() { - auto* renderable = static_cast(this->object.get()); - Private::template set_sync(renderable->paint_task, this->object.get(), true); - return *this; - } - template requires detail::Async_Task - Builder& set_paint_async_task() { - auto* renderable = static_cast(this->object.get()); - Private::template set_async(renderable->paint_task, this->object.get(), true); - return *this; - } - }; }; namespace detail { template @@ -219,59 +101,35 @@ struct Secene : Impl, Rely_Type struct Stage : Pinned { struct Node : Pinned { - using Gate = oneapi::tbb::flow::continue_node; + using Execute = oneapi::tbb::flow::continue_node; static auto body(Root* object, Renderable::Node_Data* data) { if constexpr (std::same_as) { - return [object, data](const Message&, typename Async_Node::gateway_type& gateway) { - if (!object->take_dirty()) { - (void)gateway.try_put(Message{}); - return; - } - if (!data->renderable) { - data->prepare(object, gateway); - return; - } - auto& task = *data->renderable->prepare_task.render; - std::get<1>(task)(std::get<0>(task), gateway); + return [object, renderable = data->renderable](const Message&) { + if (object->take_dirty()) renderable->prepare_call(renderable); + return Message{}; }; } else { - return [renderable = data->renderable](const Message&, typename Async_Node::gateway_type& gateway) { - if (!renderable->take_paint_dirty()) { - (void)gateway.try_put(Message{}); - return; - } - auto& task = *renderable->paint_task.render; - std::get<1>(task)(std::get<0>(task), gateway); + return [renderable = data->renderable](const Message&) { + if (renderable->take_paint_dirty()) renderable->paint_call(renderable); + return Message{}; }; } } - Gate gate; - Async_Node execute; - Node(oneapi::tbb::flow::graph& graph, Root* object, Renderable::Node_Data* data) : - gate( - graph, - [](const Message&) { - return Message{}; - } - ), - execute(graph, oneapi::tbb::flow::unlimited, body(object, data)) { - oneapi::tbb::flow::make_edge(gate, execute); - } + Execute execute; + Node(oneapi::tbb::flow::graph& graph, Root* object, Renderable::Node_Data* data) : execute(graph, body(object, data)) {} }; oneapi::tbb::flow::graph graph; oneapi::tbb::flow::broadcast_node start; std::pmr::list nodes; std::uint64_t revision; template - Stage(const Object* object, std::pmr::memory_resource* resource) : - start(graph), - nodes(resource), - revision(object->template render_rely().revision()) { + Stage(const Object* object, std::pmr::memory_resource* resource) : start(graph), + nodes(resource), + revision(object->template render_rely().revision()) { (void)object->template for_each_rely_dag( [&](const Rely::View& view, const Rely::Node& rely_node) { auto* data = static_cast(rely_node.data); @@ -279,10 +137,10 @@ struct Secene : Impl, Rely_Typegate); + if (dependencies.empty()) oneapi::tbb::flow::make_edge(start, node->execute); for (const auto* dependency : dependencies) { auto* source = static_cast(dependency->runtime); - oneapi::tbb::flow::make_edge(source->execute, node->gate); + oneapi::tbb::flow::make_edge(source->execute, node->execute); } } ); @@ -300,7 +158,8 @@ struct Secene : Impl, Rely_Typeprepare_stage && object->paint_stage && object->prepare_stage->revision == prepare_rely.revision() && - object->paint_stage->revision == paint_rely.revision()) return; + object->paint_stage->revision == paint_rely.revision()) + return; if (object->prepare_stage) object->prepare_stage->graph.wait_for_all(); if (object->paint_stage) object->paint_stage->graph.wait_for_all(); auto prepare = std::make_unique>(object, object->memory_resource());