@@ -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 ( ) ;