|
|
|
@@ -1,5 +1,5 @@
|
|
|
|
|
#pragma once
|
|
|
|
|
#include "base.hpp"
|
|
|
|
|
#include "base/object.hpp"
|
|
|
|
|
#include <array>
|
|
|
|
|
#include <string>
|
|
|
|
|
#include <taskflow/taskflow.hpp>
|
|
|
|
@@ -30,7 +30,7 @@ struct Task_Worker_State {
|
|
|
|
|
double utilization{};
|
|
|
|
|
bool operator==(const Task_Worker_State&) const = default;
|
|
|
|
|
};
|
|
|
|
|
struct Task_Runtime_State : State_Type<Task_Runtime_State_Tag> {
|
|
|
|
|
struct Task_Runtime_State : ::double_buffer::State_Type<Task_Runtime_State_Tag> {
|
|
|
|
|
std::size_t worker_count{};
|
|
|
|
|
std::size_t active_topology_count{};
|
|
|
|
|
std::size_t active_taskflow_count{};
|
|
|
|
@@ -63,7 +63,7 @@ struct Task_Runtime_State : State_Type<Task_Runtime_State_Tag> {
|
|
|
|
|
};
|
|
|
|
|
void initialize_runtime(std::size_t workers = std::thread::hardware_concurrency(),
|
|
|
|
|
std::shared_ptr<tf::WorkerInterface> worker_interface = nullptr,
|
|
|
|
|
Pmr pmr = {});
|
|
|
|
|
::double_buffer::Pmr pmr = {});
|
|
|
|
|
namespace detail {
|
|
|
|
|
void set_runtime_state_callback(std::function<void(const Task_Runtime_State&)> callback);
|
|
|
|
|
void clear_runtime_state_callback();
|
|
|
|
@@ -80,30 +80,72 @@ void clear_runtime_state_callback() {
|
|
|
|
|
detail::clear_runtime_state_callback();
|
|
|
|
|
}
|
|
|
|
|
struct Renderable;
|
|
|
|
|
/*
|
|
|
|
|
* Prepare 数据模式定制点。
|
|
|
|
|
* 子类的 Private 可定义:
|
|
|
|
|
* void prepare_data(T* object);
|
|
|
|
|
* 当未定义 build_prepare_graph(...) 时必须提供该函数。
|
|
|
|
|
* 如果 prepare_data(...) 与 build_prepare_graph(...) 同时存在,Prepare 阶段选择子图模式,
|
|
|
|
|
* prepare_data(...) 不再作为该阶段的执行函数。
|
|
|
|
|
*/
|
|
|
|
|
template <typename T>
|
|
|
|
|
concept Prepare_Data_Renderable = Attached<T> && requires(typename T::Private& private_data, T* object) {
|
|
|
|
|
concept Prepare_Data_Renderable = ::double_buffer::Attached<T> && requires(typename T::Private& private_data, T* object) {
|
|
|
|
|
{ private_data.prepare_data(object) } -> std::same_as<void>;
|
|
|
|
|
};
|
|
|
|
|
/*
|
|
|
|
|
* Prepare 子图模式定制点。
|
|
|
|
|
* 子类的 Private 可定义:
|
|
|
|
|
* tf::Taskflow build_prepare_graph(T* object, const T::State& state);
|
|
|
|
|
* 只要该函数存在且签名满足此概念,Prepare 阶段就进入子图模式。
|
|
|
|
|
* 子图首次执行前一定会构建;之后仅在 should_rebuild_prepare_graph(...) 返回 true 时重建。
|
|
|
|
|
* 子图构建需要 PMR 时直接使用 detail::task_memory_resource() 获取运行时全局资源,
|
|
|
|
|
* 不把 std::pmr::memory_resource 作为 Renderable 子类接口参数传递。
|
|
|
|
|
* 不需要子图模式时不要定义一个仅返回空 Taskflow 的函数,应直接省略该定制点。
|
|
|
|
|
*/
|
|
|
|
|
template <typename T>
|
|
|
|
|
concept Prepare_Graph_Renderable = Attached<T> && requires(typename T::Private& private_data, T* object, const typename T::State& state, std::pmr::memory_resource* resource) {
|
|
|
|
|
{ private_data.build_prepare_graph(object, state, resource) } -> std::same_as<tf::Taskflow>;
|
|
|
|
|
concept Prepare_Graph_Renderable = ::double_buffer::Attached<T> && requires(typename T::Private& private_data, T* object, const typename T::State& state) {
|
|
|
|
|
{ private_data.build_prepare_graph(object, state) } -> std::same_as<tf::Taskflow>;
|
|
|
|
|
};
|
|
|
|
|
/*
|
|
|
|
|
* Paint 数据模式定制点。
|
|
|
|
|
* 子类的 Private 可定义:
|
|
|
|
|
* void paint(T* object);
|
|
|
|
|
* 当未定义 build_paint_graph(...) 时必须提供该函数。
|
|
|
|
|
* 如果 paint(...) 与 build_paint_graph(...) 同时存在,Paint 阶段选择子图模式,
|
|
|
|
|
* paint(...) 不再作为该阶段的执行函数。
|
|
|
|
|
*/
|
|
|
|
|
template <typename T>
|
|
|
|
|
concept Paint_Data_Renderable = Attached<T> && requires(typename T::Private& private_data, T* object) {
|
|
|
|
|
concept Paint_Data_Renderable = ::double_buffer::Attached<T> && requires(typename T::Private& private_data, T* object) {
|
|
|
|
|
{ private_data.paint(object) } -> std::same_as<void>;
|
|
|
|
|
};
|
|
|
|
|
/*
|
|
|
|
|
* Paint 子图模式定制点。
|
|
|
|
|
* 子类的 Private 可定义:
|
|
|
|
|
* tf::Taskflow build_paint_graph(T* object, const T::State& state);
|
|
|
|
|
* 只要该函数存在且签名满足此概念,Paint 阶段就进入子图模式。
|
|
|
|
|
* 子图首次执行前一定会构建;之后仅在 should_rebuild_paint_graph(...) 返回 true 时重建。
|
|
|
|
|
* 子图构建需要 PMR 时直接使用 detail::task_memory_resource() 获取运行时全局资源,
|
|
|
|
|
* 不把 std::pmr::memory_resource 作为 Renderable 子类接口参数传递。
|
|
|
|
|
* 不需要子图模式时不要定义一个仅返回空 Taskflow 的函数,应直接省略该定制点。
|
|
|
|
|
*/
|
|
|
|
|
template <typename T>
|
|
|
|
|
concept Paint_Graph_Renderable = Attached<T> && requires(typename T::Private& private_data, T* object, const typename T::State& state, std::pmr::memory_resource* resource) {
|
|
|
|
|
{ private_data.build_paint_graph(object, state, resource) } -> std::same_as<tf::Taskflow>;
|
|
|
|
|
concept Paint_Graph_Renderable = ::double_buffer::Attached<T> && requires(typename T::Private& private_data, T* object, const typename T::State& state) {
|
|
|
|
|
{ private_data.build_paint_graph(object, state) } -> std::same_as<tf::Taskflow>;
|
|
|
|
|
};
|
|
|
|
|
/*
|
|
|
|
|
* Renderable 子类完整契约。
|
|
|
|
|
* Prepare 与 Paint 两个阶段都必须至少提供一种实现:普通函数或子图构建函数。
|
|
|
|
|
* should_prepare(...)、should_paint(...)、should_rebuild_prepare_graph(...)、
|
|
|
|
|
* should_rebuild_paint_graph(...) 在 Renderable::Private 中提供默认行为,子类可按需重新定义。
|
|
|
|
|
*/
|
|
|
|
|
template <typename T>
|
|
|
|
|
concept Renderable_Object = Attached<T> && std::derived_from<T, Renderable> && requires(typename T::Private& private_data, T* object, const typename T::State& state, bool dirty) {
|
|
|
|
|
concept Renderable_Object = ::double_buffer::Attached<T> && std::derived_from<T, Renderable> && requires(typename T::Private& private_data, T* object, const typename T::State& state, bool dirty) {
|
|
|
|
|
{ private_data.should_prepare(object, state, dirty) } -> std::same_as<bool>;
|
|
|
|
|
{ private_data.should_paint(object, state, dirty) } -> std::same_as<bool>;
|
|
|
|
|
{ private_data.should_rebuild_prepare_graph(object, state) } -> std::same_as<bool>;
|
|
|
|
|
{ private_data.should_rebuild_paint_graph(object, state) } -> std::same_as<bool>;
|
|
|
|
|
} && (Prepare_Data_Renderable<T> || Prepare_Graph_Renderable<T>) && (Paint_Data_Renderable<T> || Paint_Graph_Renderable<T>);
|
|
|
|
|
struct Renderable : Impl<Renderable, Root, State_Type<Renderable_State_Tag>, Tagged_Buffer<Color_Cache>> {
|
|
|
|
|
struct Renderable : ::double_buffer::Impl<Renderable, ::double_buffer::Root, ::double_buffer::State_Type<Renderable_State_Tag>, ::double_buffer::Tagged_Buffer<Color_Cache>> {
|
|
|
|
|
struct Prop : Prev_Prop {};
|
|
|
|
|
struct State : Prev_State<Renderable_State_Tag> {
|
|
|
|
|
bool prepare_dirty{};
|
|
|
|
@@ -130,12 +172,12 @@ protected:
|
|
|
|
|
}
|
|
|
|
|
public:
|
|
|
|
|
struct Private : Prev_Private {
|
|
|
|
|
using Run_Predicate = bool (*)(Root*, bool);
|
|
|
|
|
using Rebuild_Predicate = bool (*)(Root*);
|
|
|
|
|
using Stage_Run = void (*)(Root*);
|
|
|
|
|
using Graph_Builder = tf::Taskflow (*)(Root*, std::pmr::memory_resource*);
|
|
|
|
|
using State_Access = State* (*)(Root*);
|
|
|
|
|
using State_Notify = void (*)(Root*);
|
|
|
|
|
using Run_Predicate = bool (*)(::double_buffer::Root*, bool);
|
|
|
|
|
using Rebuild_Predicate = bool (*)(::double_buffer::Root*);
|
|
|
|
|
using Stage_Run = void (*)(::double_buffer::Root*);
|
|
|
|
|
using Graph_Builder = tf::Taskflow (*)(::double_buffer::Root*);
|
|
|
|
|
using State_Access = State* (*)(::double_buffer::Root*);
|
|
|
|
|
using State_Notify = void (*)(::double_buffer::Root*);
|
|
|
|
|
struct Stage_Dispatch {
|
|
|
|
|
Run_Predicate predicate;
|
|
|
|
|
Rebuild_Predicate rebuild_predicate;
|
|
|
|
@@ -156,40 +198,74 @@ public:
|
|
|
|
|
std::unique_ptr<tf::Taskflow> paint_graph;
|
|
|
|
|
bool prepare_graph_built{};
|
|
|
|
|
bool paint_graph_built{};
|
|
|
|
|
bool should_rebuild_prepare_graph(Attached auto*, const State&) {
|
|
|
|
|
/*
|
|
|
|
|
* Prepare 子图重建判定定制点。
|
|
|
|
|
* 子类的 Private 可定义:
|
|
|
|
|
* bool should_rebuild_prepare_graph(T* object, const T::State& state);
|
|
|
|
|
* 仅在定义了 build_prepare_graph(...) 的子图模式下使用。
|
|
|
|
|
* 首次子图构建不依赖该返回值;默认 false 表示首次构建后不主动重建。
|
|
|
|
|
*/
|
|
|
|
|
bool should_rebuild_prepare_graph(::double_buffer::Attached auto*, const State&) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
bool should_rebuild_paint_graph(Attached auto*, const State&) {
|
|
|
|
|
/*
|
|
|
|
|
* Paint 子图重建判定定制点。
|
|
|
|
|
* 子类的 Private 可定义:
|
|
|
|
|
* bool should_rebuild_paint_graph(T* object, const T::State& state);
|
|
|
|
|
* 仅在定义了 build_paint_graph(...) 的子图模式下使用。
|
|
|
|
|
* 首次子图构建不依赖该返回值;默认 false 表示首次构建后不主动重建。
|
|
|
|
|
*/
|
|
|
|
|
bool should_rebuild_paint_graph(::double_buffer::Attached auto*, const State&) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
bool should_prepare(Attached auto*, const State&, bool dirty) {
|
|
|
|
|
/*
|
|
|
|
|
* Prepare 阶段执行判定定制点。
|
|
|
|
|
* 子类的 Private 可定义:
|
|
|
|
|
* bool should_prepare(T* object, const T::State& state, bool dirty);
|
|
|
|
|
* dirty 是运行时在完成必要的子图重建处理后读取到的 Prepare 脏状态。
|
|
|
|
|
* 返回 true 执行 Prepare 阶段,返回 false 跳过;默认仅在 dirty 为 true 时执行。
|
|
|
|
|
*/
|
|
|
|
|
bool should_prepare(::double_buffer::Attached auto*, const State&, bool dirty) {
|
|
|
|
|
return dirty;
|
|
|
|
|
}
|
|
|
|
|
bool should_paint(Attached auto*, const State&, bool dirty) {
|
|
|
|
|
/*
|
|
|
|
|
* Paint 阶段执行判定定制点。
|
|
|
|
|
* 子类的 Private 可定义:
|
|
|
|
|
* bool should_paint(T* object, const T::State& state, bool dirty);
|
|
|
|
|
* dirty 是运行时在完成必要的子图重建处理后读取到的 Paint 脏状态。
|
|
|
|
|
* 返回 true 执行 Paint 阶段,返回 false 跳过;默认仅在 dirty 为 true 时执行。
|
|
|
|
|
*/
|
|
|
|
|
bool should_paint(::double_buffer::Attached auto*, const State&, bool dirty) {
|
|
|
|
|
return dirty;
|
|
|
|
|
}
|
|
|
|
|
void after_prepare_data(Attached auto*) {}
|
|
|
|
|
/*
|
|
|
|
|
* Prepare 数据模式完成后的可选后置钩子。
|
|
|
|
|
* 子类的 Private 可定义:
|
|
|
|
|
* void after_prepare_data(T* object);
|
|
|
|
|
* 仅在 prepare_data(...) 数据模式执行完成后调用,Prepare 子图模式不会调用该钩子。
|
|
|
|
|
*/
|
|
|
|
|
void after_prepare_data(::double_buffer::Attached auto*) {}
|
|
|
|
|
};
|
|
|
|
|
private:
|
|
|
|
|
void bind_rely_object(Attached auto* object) {
|
|
|
|
|
void bind_rely_object(::double_buffer::Attached auto* object) {
|
|
|
|
|
using Object = std::remove_pointer_t<decltype(object)>;
|
|
|
|
|
static_assert(Renderable_Object<Object>);
|
|
|
|
|
auto& data = static_cast<Private&>(object->d);
|
|
|
|
|
static const Private::Dispatch dispatch{
|
|
|
|
|
{
|
|
|
|
|
[](Root* root, bool dirty) {
|
|
|
|
|
[](::double_buffer::Root* root, bool dirty) {
|
|
|
|
|
auto* value = static_cast<Object*>(root);
|
|
|
|
|
auto& private_data = static_cast<typename Object::Private&>(value->d);
|
|
|
|
|
return private_data.should_prepare(value, *value->d.state.current, dirty);
|
|
|
|
|
},
|
|
|
|
|
[](Root* root) {
|
|
|
|
|
[](::double_buffer::Root* root) {
|
|
|
|
|
auto* value = static_cast<Object*>(root);
|
|
|
|
|
auto& private_data = static_cast<typename Object::Private&>(value->d);
|
|
|
|
|
return private_data.should_rebuild_prepare_graph(value, *value->d.state.current);
|
|
|
|
|
},
|
|
|
|
|
[]() -> Private::Stage_Run {
|
|
|
|
|
if constexpr (Prepare_Data_Renderable<Object>) {
|
|
|
|
|
return [](Root* root) {
|
|
|
|
|
return [](::double_buffer::Root* root) {
|
|
|
|
|
auto* value = static_cast<Object*>(root);
|
|
|
|
|
run_prepare_data(value);
|
|
|
|
|
};
|
|
|
|
@@ -200,10 +276,10 @@ private:
|
|
|
|
|
}(),
|
|
|
|
|
[]() -> Private::Graph_Builder {
|
|
|
|
|
if constexpr (Prepare_Graph_Renderable<Object>) {
|
|
|
|
|
return [](Root* root, std::pmr::memory_resource* resource) {
|
|
|
|
|
return [](::double_buffer::Root* root) {
|
|
|
|
|
auto* value = static_cast<Object*>(root);
|
|
|
|
|
auto& private_data = static_cast<typename Object::Private&>(value->d);
|
|
|
|
|
return private_data.build_prepare_graph(value, *value->d.state.current, resource);
|
|
|
|
|
return private_data.build_prepare_graph(value, *value->d.state.current);
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
@@ -212,19 +288,19 @@ private:
|
|
|
|
|
}()
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
[](Root* root, bool dirty) {
|
|
|
|
|
[](::double_buffer::Root* root, bool dirty) {
|
|
|
|
|
auto* value = static_cast<Object*>(root);
|
|
|
|
|
auto& private_data = static_cast<typename Object::Private&>(value->d);
|
|
|
|
|
return private_data.should_paint(value, *value->d.state.current, dirty);
|
|
|
|
|
},
|
|
|
|
|
[](Root* root) {
|
|
|
|
|
[](::double_buffer::Root* root) {
|
|
|
|
|
auto* value = static_cast<Object*>(root);
|
|
|
|
|
auto& private_data = static_cast<typename Object::Private&>(value->d);
|
|
|
|
|
return private_data.should_rebuild_paint_graph(value, *value->d.state.current);
|
|
|
|
|
},
|
|
|
|
|
[]() -> Private::Stage_Run {
|
|
|
|
|
if constexpr (Paint_Data_Renderable<Object>) {
|
|
|
|
|
return [](Root* root) {
|
|
|
|
|
return [](::double_buffer::Root* root) {
|
|
|
|
|
auto* value = static_cast<Object*>(root);
|
|
|
|
|
auto& private_data = static_cast<typename Object::Private&>(value->d);
|
|
|
|
|
private_data.paint(value);
|
|
|
|
@@ -236,10 +312,10 @@ private:
|
|
|
|
|
}(),
|
|
|
|
|
[]() -> Private::Graph_Builder {
|
|
|
|
|
if constexpr (Paint_Graph_Renderable<Object>) {
|
|
|
|
|
return [](Root* root, std::pmr::memory_resource* resource) {
|
|
|
|
|
return [](::double_buffer::Root* root) {
|
|
|
|
|
auto* value = static_cast<Object*>(root);
|
|
|
|
|
auto& private_data = static_cast<typename Object::Private&>(value->d);
|
|
|
|
|
return private_data.build_paint_graph(value, *value->d.state.current, resource);
|
|
|
|
|
return private_data.build_paint_graph(value, *value->d.state.current);
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
@@ -248,11 +324,11 @@ private:
|
|
|
|
|
}()
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
[](Root* root) {
|
|
|
|
|
[](::double_buffer::Root* root) {
|
|
|
|
|
auto* value = static_cast<Object*>(root);
|
|
|
|
|
return static_cast<State*>(value->d.state.current);
|
|
|
|
|
},
|
|
|
|
|
[](Root* root) {
|
|
|
|
|
[](::double_buffer::Root* root) {
|
|
|
|
|
auto* value = static_cast<Object*>(root);
|
|
|
|
|
value->template notify_state<Renderable_State_Tag>();
|
|
|
|
|
}
|
|
|
|
@@ -261,7 +337,7 @@ private:
|
|
|
|
|
data.dispatch = &dispatch;
|
|
|
|
|
object->template mark_dirty<Prepare_Data_Tag>();
|
|
|
|
|
}
|
|
|
|
|
friend struct ::aethera::Rely;
|
|
|
|
|
friend struct ::double_buffer::Rely;
|
|
|
|
|
};
|
|
|
|
|
namespace detail {
|
|
|
|
|
enum class Renderable_Stage {
|
|
|
|
@@ -272,10 +348,10 @@ enum class Stage_Observer_Point {
|
|
|
|
|
Begin,
|
|
|
|
|
End
|
|
|
|
|
};
|
|
|
|
|
void bind_stage_observer(const tf::Taskflow* owner, std::size_t task_hash, Root* object, Renderable::Private* data, Renderable_Stage stage, Stage_Observer_Point point);
|
|
|
|
|
void bind_stage_observer(const tf::Taskflow* owner, std::size_t task_hash, ::double_buffer::Root* object, Renderable::Private* data, Renderable_Stage stage, Stage_Observer_Point point);
|
|
|
|
|
void clear_stage_observers(const tf::Taskflow* owner);
|
|
|
|
|
}
|
|
|
|
|
struct Scene : Impl<Scene, Root, State_Type<Scene_State_Tag>, Rely_Type<Prepare_Data_Tag, Renderable>, Rely_Type<Paint_Tag, Renderable>> {
|
|
|
|
|
struct Scene : ::double_buffer::Impl<Scene, ::double_buffer::Root, ::double_buffer::State_Type<Scene_State_Tag>, ::double_buffer::Rely_Type<Prepare_Data_Tag, Renderable>, ::double_buffer::Rely_Type<Paint_Tag, Renderable>> {
|
|
|
|
|
struct Prop : Prev_Prop {};
|
|
|
|
|
struct State : Prev_State<Scene_State_Tag> {
|
|
|
|
|
bool taskflow_rebuilt{};
|
|
|
|
@@ -301,9 +377,9 @@ struct Scene : Impl<Scene, Root, State_Type<Scene_State_Tag>, Rely_Type<Prepare_
|
|
|
|
|
~Private() {
|
|
|
|
|
detail::clear_stage_observers(&taskflow);
|
|
|
|
|
}
|
|
|
|
|
void after_exchange(Attached auto* object, Prop*, State*, const Prop*, const State*);
|
|
|
|
|
void after_exchange(::double_buffer::Attached auto* object, Prop*, State*, const Prop*, const State*);
|
|
|
|
|
template <std::invocable<const Result&> Callback>
|
|
|
|
|
void process(Attached auto* object, Callback&& callback) {
|
|
|
|
|
void process(::double_buffer::Attached auto* object, Callback&& callback) {
|
|
|
|
|
auto& state = static_cast<State&>(*object->d.state.current);
|
|
|
|
|
state.taskflow_rebuilt = taskflow_rebuilt;
|
|
|
|
|
state.renderable_count = renderable_count;
|
|
|
|
@@ -319,15 +395,15 @@ struct Scene : Impl<Scene, Root, State_Type<Scene_State_Tag>, Rely_Type<Prepare_
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
void Scene::Private::after_exchange(Attached auto* object, Prop*, State*, const Prop*, const State*) {
|
|
|
|
|
void Scene::Private::after_exchange(::double_buffer::Attached auto* object, Prop*, State*, const Prop*, const State*) {
|
|
|
|
|
auto* resource = detail::task_memory_resource();
|
|
|
|
|
taskflow_rebuilt = false;
|
|
|
|
|
std::pmr::unordered_set<Root*> exchanged_objects{resource};
|
|
|
|
|
std::pmr::unordered_set<::double_buffer::Root*> exchanged_objects{resource};
|
|
|
|
|
exchanged_objects.insert(object);
|
|
|
|
|
object->for_each_current_rely(
|
|
|
|
|
[&](const Rely& rely) {
|
|
|
|
|
[&](const ::double_buffer::Rely& rely) {
|
|
|
|
|
rely.for_each(
|
|
|
|
|
[&](const Rely::Node& node) {
|
|
|
|
|
[&](const ::double_buffer::Rely::Node& node) {
|
|
|
|
|
if (exchanged_objects.insert(node.object).second) node.object->exchange_object();
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
@@ -362,9 +438,9 @@ void Scene::Private::after_exchange(Attached auto* object, Prop*, State*, const
|
|
|
|
|
tf::Task paint_entry;
|
|
|
|
|
tf::Task paint_exit;
|
|
|
|
|
};
|
|
|
|
|
std::pmr::unordered_map<Root*, Stage_Tasks> stage_tasks{resource};
|
|
|
|
|
std::pmr::unordered_map<::double_buffer::Root*, Stage_Tasks> stage_tasks{resource};
|
|
|
|
|
for (auto* renderable : renderables) {
|
|
|
|
|
Root* root = renderable;
|
|
|
|
|
::double_buffer::Root* root = renderable;
|
|
|
|
|
auto* data = prepare_dependencies.private_data(root);
|
|
|
|
|
if (!data) data = paint_dependencies.private_data(root);
|
|
|
|
|
if (!data) continue;
|
|
|
|
@@ -376,7 +452,7 @@ void Scene::Private::after_exchange(Attached auto* object, Prop*, State*, const
|
|
|
|
|
if (dispatch->prepare.builder) {
|
|
|
|
|
bool rebuild = dispatch->prepare.rebuild_predicate(root);
|
|
|
|
|
if (!data->prepare_graph_built || rebuild) {
|
|
|
|
|
*data->prepare_graph = dispatch->prepare.builder(root, detail::task_memory_resource());
|
|
|
|
|
*data->prepare_graph = dispatch->prepare.builder(root);
|
|
|
|
|
data->prepare_graph_built = true;
|
|
|
|
|
state.prepare_graph_rebuilt = true;
|
|
|
|
|
root->template mark_dirty<Prepare_Data_Tag>();
|
|
|
|
@@ -416,7 +492,7 @@ void Scene::Private::after_exchange(Attached auto* object, Prop*, State*, const
|
|
|
|
|
if (dispatch->paint.builder) {
|
|
|
|
|
bool rebuild = dispatch->paint.rebuild_predicate(root);
|
|
|
|
|
if (!data->paint_graph_built || rebuild) {
|
|
|
|
|
*data->paint_graph = dispatch->paint.builder(root, detail::task_memory_resource());
|
|
|
|
|
*data->paint_graph = dispatch->paint.builder(root);
|
|
|
|
|
data->paint_graph_built = true;
|
|
|
|
|
state.paint_graph_rebuilt = true;
|
|
|
|
|
root->template mark_dirty<Paint_Tag>();
|
|
|
|
@@ -457,12 +533,12 @@ void Scene::Private::after_exchange(Attached auto* object, Prop*, State*, const
|
|
|
|
|
}
|
|
|
|
|
auto connect_dependencies = [&](const auto& rely, bool prepare) {
|
|
|
|
|
rely.for_each(
|
|
|
|
|
[&](const Rely::Node& rely_node) {
|
|
|
|
|
[&](const ::double_buffer::Rely::Node& rely_node) {
|
|
|
|
|
if (!rely.private_data(rely_node)) return;
|
|
|
|
|
auto target = stage_tasks.find(rely_node.object);
|
|
|
|
|
if (target == stage_tasks.end()) return;
|
|
|
|
|
std::pmr::unordered_set<Root*> visited{resource};
|
|
|
|
|
std::pmr::vector<const Rely::Node*> pending{resource};
|
|
|
|
|
std::pmr::unordered_set<::double_buffer::Root*> visited{resource};
|
|
|
|
|
std::pmr::vector<const ::double_buffer::Rely::Node*> pending{resource};
|
|
|
|
|
for (const auto* dependency : rely_node.dependencies) pending.push_back(dependency);
|
|
|
|
|
while (!pending.empty()) {
|
|
|
|
|
const auto* dependency = pending.back();
|
|
|
|
|