提升观测系统
隔离taskflow
This commit is contained in:
@@ -21,10 +21,10 @@ struct Afterglow::Private : Prev_Private {
|
||||
void bind_sources(Frequency_Object* frequency_axis_value, Power_Object* power_axis_value);
|
||||
/* CRTP 覆盖:构建累加、归一化和着色三阶段 Prepare 子图。 */
|
||||
template <Attached Object>
|
||||
[[nodiscard]] tf::Taskflow build_prepare_graph(Object* object, const Prop& state);
|
||||
[[nodiscard]] Task_Graph build_prepare_graph(Object* object, const Prop& state);
|
||||
/* CRTP 覆盖:构建消费色块矩阵的 Paint 子图。 */
|
||||
template <Attached Object>
|
||||
[[nodiscard]] tf::Taskflow build_paint_graph(Object* object, const Prop& state);
|
||||
[[nodiscard]] Task_Graph build_paint_graph(Object* object, const Prop& state);
|
||||
/* CRTP 覆盖:分块数量改变时请求重建 Prepare 子图。 */
|
||||
template <Attached Object>
|
||||
[[nodiscard]] bool should_rebuild_prepare_graph(Object* object, const Prop& state);
|
||||
@@ -85,27 +85,27 @@ bool Afterglow::Private::should_rebuild_prepare_graph(Object* object, const Prop
|
||||
return graph_partition_count != detail::curve_partition_count(state.partition_mode, state.partition_count, std::max<std::size_t>(1, columns));
|
||||
}
|
||||
template <Attached Object>
|
||||
tf::Taskflow Afterglow::Private::build_prepare_graph(Object* object, const Prop& state) {
|
||||
Task_Graph Afterglow::Private::build_prepare_graph(Object* object, const Prop& state) {
|
||||
const std::size_t available = object->template access_query_stream<Afterglow_Stream_Tag>(
|
||||
[](std::span<const std::shared_ptr<const std::vector<Plot_Value>>> spectra) {
|
||||
return spectra.empty() ? 0 : spectra.back()->size();
|
||||
});
|
||||
const std::size_t columns = state.frequency_point_size ? std::min(state.frequency_point_size, available) : available;
|
||||
graph_partition_count = detail::curve_partition_count(state.partition_mode, state.partition_count, std::max<std::size_t>(1, columns));
|
||||
tf::Taskflow graph;
|
||||
auto begin = graph.emplace([this, object] {
|
||||
Task_Graph graph{"afterglow.prepare"};
|
||||
auto begin = graph.add("frame", [this, object] {
|
||||
prepare_frame(object);
|
||||
}).name("afterglow.prepare.frame");
|
||||
auto normalize = graph.emplace([this] {
|
||||
});
|
||||
auto normalize = graph.add("normalize", [this] {
|
||||
normalize_frame();
|
||||
}).name("afterglow.prepare.normalize");
|
||||
});
|
||||
for (Plot_Partition_Count index = 0; index < graph_partition_count; ++index) {
|
||||
auto accumulate = graph.emplace([this, object, index] {
|
||||
auto accumulate = graph.add("accumulate", [this, object, index] {
|
||||
accumulate_partition(object, index);
|
||||
}).name("afterglow.prepare.accumulate");
|
||||
auto color = graph.emplace([this, object, index] {
|
||||
});
|
||||
auto color = graph.add("color", [this, object, index] {
|
||||
color_partition(object, index);
|
||||
}).name("afterglow.prepare.color");
|
||||
});
|
||||
begin.precede(accumulate);
|
||||
accumulate.precede(normalize);
|
||||
normalize.precede(color);
|
||||
@@ -113,11 +113,11 @@ tf::Taskflow Afterglow::Private::build_prepare_graph(Object* object, const Prop&
|
||||
return graph;
|
||||
}
|
||||
template <Attached Object>
|
||||
tf::Taskflow Afterglow::Private::build_paint_graph(Object* object, const Prop&) {
|
||||
tf::Taskflow graph;
|
||||
graph.emplace([this, object] {
|
||||
Task_Graph Afterglow::Private::build_paint_graph(Object* object, const Prop&) {
|
||||
Task_Graph graph{"afterglow.paint"};
|
||||
graph.add("frame", [this, object] {
|
||||
paint_frame(object);
|
||||
}).name("afterglow.paint.frame");
|
||||
});
|
||||
return graph;
|
||||
}
|
||||
template <Attached Object>
|
||||
|
||||
@@ -15,9 +15,9 @@ struct Frequency_Trace::Private : Prev_Private {
|
||||
Plot_Partition_Count graph_partition_count{}; /* 当前 Prepare 子图固化的分块数。 */
|
||||
void bind_sources(Time_Object* time_axis_value, Value_Object* value_axis_value);
|
||||
/* CRTP 覆盖:按当前样本规模构建分块 Prepare 子图。 */
|
||||
template <Attached Object> [[nodiscard]] tf::Taskflow build_prepare_graph(Object* object, const Prop& state);
|
||||
template <Attached Object> [[nodiscard]] Task_Graph build_prepare_graph(Object* object, const Prop& state);
|
||||
/* CRTP 覆盖:构建消费已准备曲线的 Paint 子图。 */
|
||||
template <Attached Object> [[nodiscard]] tf::Taskflow build_paint_graph(Object* object, const Prop& state);
|
||||
template <Attached Object> [[nodiscard]] Task_Graph build_paint_graph(Object* object, const Prop& state);
|
||||
/* CRTP 覆盖:分块数量改变时请求重建 Prepare 子图。 */
|
||||
template <Attached Object> [[nodiscard]] bool should_rebuild_prepare_graph(Object* object, const Prop& state);
|
||||
template <Attached Object> void prepare_frame(Object* object, Plot_Partition_Count partition_count);
|
||||
@@ -36,14 +36,14 @@ std::expected<std::unique_ptr<Object>, Dependency_Graph_Error> Frequency_Trace::
|
||||
template <Attached Object>
|
||||
bool Frequency_Trace::Private::should_rebuild_prepare_graph(Object* object, const Prop& state) { return graph_partition_count != detail::curve_partition_count(state.partition_mode, state.partition_count, object->template access_query_stream<Frequency_Trace_Stream_Tag>([](std::span<const Frequency_Trace_Sample> samples) { return samples.size(); })); }
|
||||
template <Attached Object>
|
||||
tf::Taskflow Frequency_Trace::Private::build_prepare_graph(Object* object, const Prop& state) {
|
||||
graph_partition_count = detail::curve_partition_count(state.partition_mode, state.partition_count, object->template access_query_stream<Frequency_Trace_Stream_Tag>([](std::span<const Frequency_Trace_Sample> samples) { return samples.size(); })); tf::Taskflow graph;
|
||||
auto begin = graph.emplace([this, object] { prepare_frame(object, graph_partition_count); }).name("frequency_trace.prepare.frame");
|
||||
for (Plot_Partition_Count index = 0; index < graph_partition_count; ++index) { auto task = graph.emplace([this, object, index] { prepare_partition(object, index); }).name("frequency_trace.prepare.partition"); begin.precede(task); }
|
||||
Task_Graph Frequency_Trace::Private::build_prepare_graph(Object* object, const Prop& state) {
|
||||
graph_partition_count = detail::curve_partition_count(state.partition_mode, state.partition_count, object->template access_query_stream<Frequency_Trace_Stream_Tag>([](std::span<const Frequency_Trace_Sample> samples) { return samples.size(); })); Task_Graph graph{"frequency_trace.prepare"};
|
||||
auto begin = graph.add("frame", [this, object] { prepare_frame(object, graph_partition_count); });
|
||||
for (Plot_Partition_Count index = 0; index < graph_partition_count; ++index) { auto task = graph.add("partition", [this, object, index] { prepare_partition(object, index); }); begin.precede(task); }
|
||||
return graph;
|
||||
}
|
||||
template <Attached Object>
|
||||
tf::Taskflow Frequency_Trace::Private::build_paint_graph(Object* object, const Prop&) { tf::Taskflow graph; graph.emplace([this, object] { paint_frame(object); }).name("frequency_trace.paint.frame"); return graph; }
|
||||
Task_Graph Frequency_Trace::Private::build_paint_graph(Object* object, const Prop&) { Task_Graph graph{"frequency_trace.paint"}; graph.add("frame", [this, object] { paint_frame(object); }); return graph; }
|
||||
template <Attached Object>
|
||||
void Frequency_Trace::Private::prepare_frame(Object* object, Plot_Partition_Count partition_count) {
|
||||
const auto& state = object->template read_prop<Frequency_Trace::Base_Tag>(); const auto& time_layout = time_axis->template read_prop<Abs_Axis::Base_Tag>(); const auto& value_layout = value_axis->template read_prop<Abs_Axis::Base_Tag>();
|
||||
|
||||
@@ -42,9 +42,9 @@ struct Spectrum::Private : Prev_Private {
|
||||
/* CRTP State 钩子:Spectrum 业务状态写入后标记自身 Prepare;其他继承层状态由各自 Private 负责。 */
|
||||
template <typename Object, typename Owner, typename Member, typename Prop_Type> void after_prop_set(Object* object, Member Owner::* member, Prop_Access<Prop_Type> pending_states);
|
||||
/* CRTP 子图能力:按当前样本数和 State 分块策略构建并行 Prepare 图。 */
|
||||
template <Attached Object> [[nodiscard]] tf::Taskflow build_prepare_graph(Object* object, const Prop& state);
|
||||
template <Attached Object> [[nodiscard]] Task_Graph build_prepare_graph(Object* object, const Prop& state);
|
||||
/* CRTP 子图能力:构建背景、分块曲线和覆盖标记的 Paint 图。 */
|
||||
template <Attached Object> [[nodiscard]] tf::Taskflow build_paint_graph(Object* object, const Prop& state);
|
||||
template <Attached Object> [[nodiscard]] Task_Graph build_paint_graph(Object* object, const Prop& state);
|
||||
/* CRTP 覆盖:样本规模或分块配置改变时重建 Prepare 子图。 */
|
||||
template <Attached Object> [[nodiscard]] bool should_rebuild_prepare_graph(Object* object, const Prop& state);
|
||||
template <Attached Object> [[nodiscard]] std::size_t desired_partition_count(const Object* object, const Prop& state) const;
|
||||
@@ -95,21 +95,21 @@ bool Spectrum::Private::should_rebuild_prepare_graph(Object* object, const Prop&
|
||||
return prepare_graph_partition_count != desired_partition_count(object, state);
|
||||
}
|
||||
template <Attached Object>
|
||||
tf::Taskflow Spectrum::Private::build_prepare_graph(Object* object, const Prop& state) {
|
||||
Task_Graph Spectrum::Private::build_prepare_graph(Object* object, const Prop& state) {
|
||||
const std::size_t partition_count = desired_partition_count(object, state);
|
||||
prepare_graph_partition_count = partition_count;
|
||||
tf::Taskflow graph;
|
||||
auto begin = graph.emplace([this, object, partition_count] { prepare_frame(object, partition_count); }).name("spectrum.prepare.frame");
|
||||
Task_Graph graph{"spectrum.prepare"};
|
||||
auto begin = graph.add("frame", [this, object, partition_count] { prepare_frame(object, partition_count); });
|
||||
for (std::size_t index = 0; index < partition_count; ++index) {
|
||||
auto partition = graph.emplace([this, object, index] { prepare_partition(object, index); }).name("spectrum.prepare.partition");
|
||||
auto partition = graph.add("partition", [this, object, index] { prepare_partition(object, index); });
|
||||
begin.precede(partition);
|
||||
}
|
||||
return graph;
|
||||
}
|
||||
template <Attached Object>
|
||||
tf::Taskflow Spectrum::Private::build_paint_graph(Object* object, const Prop&) {
|
||||
tf::Taskflow graph;
|
||||
graph.emplace([this, object] { paint_frame(object); }).name("spectrum.paint.frame");
|
||||
Task_Graph Spectrum::Private::build_paint_graph(Object* object, const Prop&) {
|
||||
Task_Graph graph{"spectrum.paint"};
|
||||
graph.add("frame", [this, object] { paint_frame(object); });
|
||||
return graph;
|
||||
}
|
||||
template <Attached Object>
|
||||
|
||||
@@ -27,9 +27,9 @@ struct Sweep_Spectrum::Private : Prev_Private {
|
||||
Plot_Partition_Count graph_partition_count{}; /* 当前 Prepare 子图分块数。 */
|
||||
void bind_sources(Frequency_Object* frequency_axis_value, Power_Object* power_axis_value);
|
||||
/* CRTP 覆盖:按扫描点规模构建分块 Prepare 子图。 */
|
||||
template <Attached Object> [[nodiscard]] tf::Taskflow build_prepare_graph(Object* object, const Prop& state);
|
||||
template <Attached Object> [[nodiscard]] Task_Graph build_prepare_graph(Object* object, const Prop& state);
|
||||
/* CRTP 覆盖:构建消费曲线分块的 Paint 子图。 */
|
||||
template <Attached Object> [[nodiscard]] tf::Taskflow build_paint_graph(Object* object, const Prop& state);
|
||||
template <Attached Object> [[nodiscard]] Task_Graph build_paint_graph(Object* object, const Prop& state);
|
||||
/* CRTP 覆盖:分块数量改变时请求重建 Prepare 子图。 */
|
||||
template <Attached Object> [[nodiscard]] bool should_rebuild_prepare_graph(Object* object, const Prop& state);
|
||||
template <Attached Object> void prepare_frame(Object* object);
|
||||
@@ -48,9 +48,9 @@ std::expected<std::unique_ptr<Object>, Dependency_Graph_Error> Sweep_Spectrum::B
|
||||
template <Attached Object>
|
||||
bool Sweep_Spectrum::Private::should_rebuild_prepare_graph(Object*, const Prop& state) { return graph_partition_count != detail::curve_partition_count(state.partition_mode, state.partition_count, stored_point_count()); }
|
||||
template <Attached Object>
|
||||
tf::Taskflow Sweep_Spectrum::Private::build_prepare_graph(Object* object, const Prop& state) { graph_partition_count = detail::curve_partition_count(state.partition_mode, state.partition_count, stored_point_count()); tf::Taskflow graph; auto begin = graph.emplace([this, object] { prepare_frame(object); }).name("sweep_spectrum.prepare.frame"); for (Plot_Partition_Count index = 0; index < graph_partition_count; ++index) { auto task = graph.emplace([this, object, index] { prepare_partition(object, index); }).name("sweep_spectrum.prepare.partition"); begin.precede(task); } return graph; }
|
||||
Task_Graph Sweep_Spectrum::Private::build_prepare_graph(Object* object, const Prop& state) { graph_partition_count = detail::curve_partition_count(state.partition_mode, state.partition_count, stored_point_count()); Task_Graph graph{"sweep_spectrum.prepare"}; auto begin = graph.add("frame", [this, object] { prepare_frame(object); }); for (Plot_Partition_Count index = 0; index < graph_partition_count; ++index) { auto task = graph.add("partition", [this, object, index] { prepare_partition(object, index); }); begin.precede(task); } return graph; }
|
||||
template <Attached Object>
|
||||
tf::Taskflow Sweep_Spectrum::Private::build_paint_graph(Object* object, const Prop&) { tf::Taskflow graph; graph.emplace([this, object] { paint_frame(object); }).name("sweep_spectrum.paint.frame"); return graph; }
|
||||
Task_Graph Sweep_Spectrum::Private::build_paint_graph(Object* object, const Prop&) { Task_Graph graph{"sweep_spectrum.paint"}; graph.add("frame", [this, object] { paint_frame(object); }); return graph; }
|
||||
template <Attached Object>
|
||||
void Sweep_Spectrum::Private::prepare_frame(Object* object) {
|
||||
const auto& state = object->template read_prop<Sweep_Spectrum::Base_Tag>(); const auto& frequency_layout = frequency_axis->template read_prop<Abs_Axis::Base_Tag>(); const auto& power_layout = power_axis->template read_prop<Abs_Axis::Base_Tag>(); const auto& power_state = power_axis->template read_prop<Numeric_Axis::Base_Tag>(); prepared = {}; prepared.canvas = scene->template read_prop<Render_Scene_2D::Base_Tag>().viewport;
|
||||
|
||||
@@ -32,10 +32,10 @@ struct Waterfall::Private : Prev_Private {
|
||||
void bind_sources(Frequency_Object* frequency_axis_value, Time_Object* time_axis_value);
|
||||
/* CRTP 覆盖:按当前色块工作量构建分块 Prepare 子图。 */
|
||||
template <Attached Object>
|
||||
[[nodiscard]] tf::Taskflow build_prepare_graph(Object* object, const Prop& state);
|
||||
[[nodiscard]] Task_Graph build_prepare_graph(Object* object, const Prop& state);
|
||||
/* CRTP 覆盖:构建消费色块矩阵和提示信息的 Paint 子图。 */
|
||||
template <Attached Object>
|
||||
[[nodiscard]] tf::Taskflow build_paint_graph(Object* object, const Prop& state);
|
||||
[[nodiscard]] Task_Graph build_paint_graph(Object* object, const Prop& state);
|
||||
/* CRTP 覆盖:分块数量改变时请求重建 Prepare 子图。 */
|
||||
template <Attached Object>
|
||||
[[nodiscard]] bool should_rebuild_prepare_graph(Object* object, const Prop& state);
|
||||
@@ -96,29 +96,29 @@ bool Waterfall::Private::should_rebuild_prepare_graph(Object* object, const Prop
|
||||
return graph_partition_count != detail::curve_partition_count(state.partition_mode, state.partition_count, cells);
|
||||
}
|
||||
template <Attached Object>
|
||||
tf::Taskflow Waterfall::Private::build_prepare_graph(Object* object, const Prop& state) {
|
||||
Task_Graph Waterfall::Private::build_prepare_graph(Object* object, const Prop& state) {
|
||||
const std::size_t cells = object->template access_query_stream<Waterfall_Stream_Tag>([&](std::span<const std::shared_ptr<const Waterfall_Row>> rows) {
|
||||
return rows.size() * (state.frequency_bin_count ? state.frequency_bin_count : rows.empty() ? 1 : rows.back()->values.size());
|
||||
});
|
||||
graph_partition_count = detail::curve_partition_count(state.partition_mode, state.partition_count, cells);
|
||||
tf::Taskflow graph;
|
||||
auto begin = graph.emplace([this, object] {
|
||||
Task_Graph graph{"waterfall.prepare"};
|
||||
auto begin = graph.add("frame", [this, object] {
|
||||
prepare_frame(object);
|
||||
}).name("waterfall.prepare.frame");
|
||||
});
|
||||
for (Plot_Partition_Count index = 0; index < graph_partition_count; ++index) {
|
||||
auto task = graph.emplace([this, object, index] {
|
||||
auto task = graph.add("partition", [this, object, index] {
|
||||
prepare_partition(object, index);
|
||||
}).name("waterfall.prepare.partition");
|
||||
});
|
||||
begin.precede(task);
|
||||
}
|
||||
return graph;
|
||||
}
|
||||
template <Attached Object>
|
||||
tf::Taskflow Waterfall::Private::build_paint_graph(Object* object, const Prop&) {
|
||||
tf::Taskflow graph;
|
||||
graph.emplace([this, object] {
|
||||
Task_Graph Waterfall::Private::build_paint_graph(Object* object, const Prop&) {
|
||||
Task_Graph graph{"waterfall.paint"};
|
||||
graph.add("frame", [this, object] {
|
||||
paint_frame(object);
|
||||
}).name("waterfall.paint.frame");
|
||||
});
|
||||
return graph;
|
||||
}
|
||||
template <Attached Object>
|
||||
|
||||
@@ -9,7 +9,7 @@ Render_Scene_2D::render(Frame_2D* frame) {
|
||||
return static_cast<Private&>(*d).dispatch->render(this, frame);
|
||||
}
|
||||
void Render_Scene_2D::set_frame_callback(Frame_Callback callback) { static_cast<Private&>(*d).dispatch->set_frame_callback(this, std::move(callback)); }
|
||||
tf::Taskflow& Render_Scene_2D::completion_taskflow() {
|
||||
Task_Graph& Render_Scene_2D::completion_taskflow() {
|
||||
return static_cast<Private&>(*d).completion_graph;
|
||||
}
|
||||
void Render_Scene_2D::activate_view() {
|
||||
|
||||
@@ -48,7 +48,7 @@ struct Render_Scene_2D : Def<Render_Scene_2D, Scene,
|
||||
* completion Taskflow 完成前调用方必须保持本帧像素所有权;节点若启动更晚结束的异步工作,
|
||||
* 必须捕获拥有像素所有权的对象,禁止只捕获会被下一帧复用的裸 Frame_2D*。
|
||||
*/
|
||||
[[nodiscard]] tf::Taskflow& completion_taskflow();
|
||||
[[nodiscard]] Task_Graph& completion_taskflow();
|
||||
/* 激活后 render 才会执行。 */
|
||||
void activate_view();
|
||||
/* 停止后续 render 调用,不清除最后一帧。 */
|
||||
|
||||
@@ -64,8 +64,8 @@ struct Render_Scene_2D::Private : Prev_Private {
|
||||
bool frame_in_flight{}; /* render 准入到完成回调返回的唯一状态源。 */
|
||||
Frame_Callback frame_callback{}; /* 合成完成后的唯一像素发布出口。 */
|
||||
Frame_Statistics_Accumulator frame_statistics{}; /* Scene 内部增量计算;State 只发布定长统计结果。 */
|
||||
tf::Taskflow completion_graph{}; /* 最终像素完成后、发布回调前执行的外部续写图。 */
|
||||
std::unique_ptr<tf::Taskflow> paint_taskflow{}; /* 仅由二维 Paint 图构建的执行图。 */
|
||||
Task_Graph completion_graph{"render_2d.completion"}; /* 最终像素完成后、发布回调前执行的外部续写图。 */
|
||||
std::unique_ptr<Task_Graph> paint_taskflow{}; /* 仅由二维 Paint 图构建的执行图。 */
|
||||
~Private();
|
||||
Frame_2D* active_frame{}; /* 当前同步 process 借用的外部帧;render 返回前清空。 */
|
||||
Blend2D_Cache* frame_target{}; /* 当前 render(frame) 所属外部颜色层;调用返回后清空。 */
|
||||
@@ -104,7 +104,7 @@ void Render_Scene_2D::Private::after_advance(Object* object, Prop*, State_Access
|
||||
rebuild = true;
|
||||
}
|
||||
if (!rebuild) return;
|
||||
if (!paint_taskflow) paint_taskflow = std::make_unique<tf::Taskflow>();
|
||||
if (!paint_taskflow) paint_taskflow = std::make_unique<Task_Graph>("render_2d.paint");
|
||||
auto& taskflow = *paint_taskflow;
|
||||
taskflow.clear();
|
||||
const auto dependencies = object->template current_dependency_graph<Paint_Tag>();
|
||||
@@ -139,14 +139,15 @@ void Render_Scene_2D::Private::after_advance(Object* object, Prop*, State_Access
|
||||
std::unordered_set<Root*> closed_groups;
|
||||
for (auto current = paint_order.rbegin(); current != paint_order.rend(); ++current)
|
||||
if (current->cache_owner && closed_groups.insert(current->cache_owner).second) current->cache_group_last = true;
|
||||
tf::Task previous;
|
||||
Task_Node previous;
|
||||
bool has_previous{};
|
||||
for (std::size_t index = 0; index < paint_order.size(); ++index) {
|
||||
auto& paint_node = paint_order[index];
|
||||
Root* root = paint_node.object;
|
||||
auto& data = *paint_node.private_data;
|
||||
auto* dispatch = data.dispatch;
|
||||
auto paint_if = taskflow.emplace([this, &data, dispatch, root, index] {
|
||||
const auto task_prefix = std::string(dispatch->business_name) + ".paint";
|
||||
auto paint_if = taskflow.add_condition(task_prefix + ".condition", [this, &data, dispatch, root, index] {
|
||||
auto& state = *dispatch->state.pending(root);
|
||||
state.paint_graph_rebuilt = false;
|
||||
state.paint_execution_time_ns = 0;
|
||||
@@ -158,7 +159,7 @@ void Render_Scene_2D::Private::after_advance(Object* object, Prop*, State_Access
|
||||
state.paint_graph_rebuilt = true;
|
||||
root->template mark_dirty<Paint_Tag>();
|
||||
}
|
||||
state.paint_task_count = data.paint_graph->num_tasks();
|
||||
state.paint_task_count = data.paint_graph->size();
|
||||
} else state.paint_task_count = dispatch->paint.run ? 1 : 0;
|
||||
const bool dirty = root->template dirty<Paint_Tag>();
|
||||
state.paint_dirty = dirty;
|
||||
@@ -169,15 +170,14 @@ void Render_Scene_2D::Private::after_advance(Object* object, Prop*, State_Access
|
||||
std::chrono::steady_clock::now().time_since_epoch()).count());
|
||||
}
|
||||
return state.paint_executed ? 0 : 1;
|
||||
}).name("render_2d.paint.condition");
|
||||
tf::Task paint_run;
|
||||
});
|
||||
Task_Node paint_run;
|
||||
if (dispatch->paint.builder) {
|
||||
if (!data.paint_graph) data.paint_graph = std::make_unique<tf::Taskflow>();
|
||||
paint_run = taskflow.composed_of(*data.paint_graph).name("render_2d.paint.graph");
|
||||
} else paint_run = taskflow.emplace([dispatch, root] { if (dispatch->paint.run) dispatch->paint.run(root); }).name("render_2d.paint.data");
|
||||
auto paint_extension = taskflow.composed_of(data.paint_extension)
|
||||
.name("renderable.paint.extension");
|
||||
auto paint_done = taskflow.emplace([dispatch, root] {
|
||||
if (!data.paint_graph) data.paint_graph = std::make_unique<Task_Graph>(task_prefix + ".graph");
|
||||
paint_run = taskflow.compose(task_prefix + ".graph", *data.paint_graph);
|
||||
} else paint_run = taskflow.add(task_prefix + ".data", [dispatch, root] { if (dispatch->paint.run) dispatch->paint.run(root); });
|
||||
auto paint_extension = taskflow.compose(task_prefix + ".extension", data.paint_extension);
|
||||
auto paint_done = taskflow.add(task_prefix + ".complete", [dispatch, root] {
|
||||
auto& state = *dispatch->state.pending(root);
|
||||
if (state.paint_executed) {
|
||||
root->template take_dirty<Paint_Tag>();
|
||||
@@ -187,15 +187,16 @@ void Render_Scene_2D::Private::after_advance(Object* object, Prop*, State_Access
|
||||
state.paint_execution_time_ns = finished - state.paint_execution_time_ns;
|
||||
}
|
||||
dispatch->state.publish(root);
|
||||
}).name("render_2d.paint.complete");
|
||||
paint_if.precede(paint_run, paint_done);
|
||||
});
|
||||
paint_if.precede(paint_run);
|
||||
paint_if.precede(paint_done);
|
||||
paint_run.precede(paint_extension);
|
||||
paint_extension.precede(paint_done);
|
||||
if (has_previous) previous.precede(paint_if);
|
||||
previous = paint_done;
|
||||
if (paint_node.cache_group_last) {
|
||||
Root* cache_owner = paint_node.cache_owner;
|
||||
auto composite = taskflow.emplace([this, object, cache_owner] {
|
||||
auto composite = taskflow.add(task_prefix + ".cache_composite", [this, object, cache_owner] {
|
||||
const auto group = std::find_if(cache_groups.begin(), cache_groups.end(), [cache_owner](const Cache_Group& value) { return value.owner == cache_owner; });
|
||||
const auto owner_node = std::find_if(paint_order.begin(), paint_order.end(), [cache_owner](const Paint_Node& value) { return value.object == cache_owner; });
|
||||
if (group == cache_groups.end() || owner_node == paint_order.end()) return;
|
||||
@@ -204,7 +205,7 @@ void Render_Scene_2D::Private::after_advance(Object* object, Prop*, State_Access
|
||||
if (!frame_target) throw std::logic_error("2D paint graph has no external frame target");
|
||||
frame_target->composite(*owner_node->private_data->valid_cache);
|
||||
}
|
||||
}).name("render_2d.paint.cache.composite");
|
||||
});
|
||||
paint_done.precede(composite);
|
||||
previous = composite;
|
||||
}
|
||||
@@ -295,7 +296,13 @@ void Render_Scene_2D::Private::process(Object* object, Callback&& callback)
|
||||
Pen{.style = Line_Style::none}, Brush{state.background, Brush_Style::solid});
|
||||
}
|
||||
prepare_paint_targets(object, frame, state.viewport);
|
||||
if (paint_taskflow && !paint_taskflow->empty()) aethera::detail::run_taskflow(*paint_taskflow);
|
||||
if (paint_taskflow && !paint_taskflow->empty()) {
|
||||
if (frame_object->taskflow_trace_requested())
|
||||
aethera::detail::run_taskflow(*paint_taskflow, *frame_object,
|
||||
"render_2d.paint");
|
||||
else
|
||||
aethera::detail::run_taskflow(*paint_taskflow);
|
||||
}
|
||||
frame_object->mark(Frame_Trace_Marker::paint_finished);
|
||||
});
|
||||
std::invoke(std::forward<Callback>(callback));
|
||||
@@ -322,6 +329,14 @@ Render_Scene_2D::Private::render(Object* object, Frame_2D* frame) {
|
||||
}
|
||||
} admission{*this};
|
||||
frame->mark(Frame_Trace_Marker::scene_render_requested);
|
||||
const bool trace_started = aethera::detail::begin_taskflow_trace(*frame);
|
||||
struct Trace_Scope {
|
||||
Frame_2D* frame{}; /* 异常路径仍需关闭本帧 Observer 写入窗口。 */
|
||||
bool active{}; /* 只有成功取得全局捕获槽位才负责关闭。 */
|
||||
~Trace_Scope() {
|
||||
if (active) aethera::detail::finish_taskflow_trace(*frame);
|
||||
}
|
||||
} trace_scope{frame, trace_started};
|
||||
struct Active_Frame_Scope {
|
||||
Frame_2D*& target; /* 最终 Private 的同步 process 帧槽位。 */
|
||||
Frame_2D* previous{}; /* 嵌套调用前的帧;析构时恢复。 */
|
||||
@@ -333,7 +348,17 @@ Render_Scene_2D::Private::render(Object* object, Frame_2D* frame) {
|
||||
completed = true;
|
||||
frame->mark(Frame_Trace_Marker::scene_render_finished);
|
||||
/* 帧准入直到 completion 图和最终回调都结束才释放,因此图运行期间外部帧不会被下一帧复用。 */
|
||||
if (!completion_graph.empty()) aethera::detail::run_taskflow(completion_graph);
|
||||
if (!completion_graph.empty()) {
|
||||
if (frame->taskflow_trace_requested())
|
||||
aethera::detail::run_taskflow(completion_graph, *frame,
|
||||
"render_2d.completion");
|
||||
else
|
||||
aethera::detail::run_taskflow(completion_graph);
|
||||
}
|
||||
if (trace_started) {
|
||||
aethera::detail::finish_taskflow_trace(*frame);
|
||||
trace_scope.active = false;
|
||||
}
|
||||
frame->mark(Frame_Trace_Marker::callback_started);
|
||||
callback(frame);
|
||||
frame->mark(Frame_Trace_Marker::callback_finished);
|
||||
|
||||
@@ -95,12 +95,12 @@ TEST(axis_render, scene_prepares_and_paints_uncached_axis_into_frame) {
|
||||
}).has_value()));
|
||||
int paint_extension_calls{};
|
||||
int completion_calls{};
|
||||
axis->paint_taskflow().emplace(
|
||||
[&] { ++paint_extension_calls; }).name("test.axis.paint.extension");
|
||||
scene->completion_taskflow().emplace([&] {
|
||||
axis->paint_taskflow().add(
|
||||
"test.axis.paint.extension", [&] { ++paint_extension_calls; });
|
||||
scene->completion_taskflow().add("test.scene_2d.completion", [&] {
|
||||
EXPECT_EQ(paint_extension_calls, 1);
|
||||
++completion_calls;
|
||||
}).name("test.scene_2d.completion");
|
||||
});
|
||||
const auto frame = render_frame(scene.get());
|
||||
EXPECT_EQ(paint_extension_calls, 1);
|
||||
EXPECT_EQ(completion_calls, 1);
|
||||
|
||||
Reference in New Issue
Block a user