提升观测系统

隔离taskflow
This commit is contained in:
2026-08-25 10:15:59 +08:00
parent c0d5a13350
commit 2c3105cc07
37 changed files with 1538 additions and 184 deletions
@@ -185,7 +185,8 @@ void Async_Render_Backend::Implementation::enqueue(Command command) {
}
if (!schedule) return;
auto self = shared_from_this();
aethera::schedule_task([self] { self->drain(); });
aethera::schedule_task("render_3d.backend.drain",
[self] { self->drain(); });
}
void Async_Render_Backend::Implementation::drain() noexcept {
for (;;) {
@@ -10,7 +10,7 @@ bool Render_Scene_3D::Prop::operator==(const Prop&) const = default;
bool Render_Scene_3D::State::operator==(const State&) const = default;
Render_Scene_3D::Render_Result Render_Scene_3D::render(Frame_3D* frame) { return static_cast<Private&>(*d).dispatch->render(this, frame); }
void Render_Scene_3D::set_frame_callback(Frame_Callback callback) { static_cast<Private&>(*d).dispatch->set_frame_callback(this, std::move(callback)); }
tf::Taskflow& Render_Scene_3D::completion_taskflow() {
Task_Graph& Render_Scene_3D::completion_taskflow() {
return static_cast<Private&>(*d).completion_graph;
}
void Render_Scene_3D::reset_frame_statistics() {
@@ -70,7 +70,7 @@ struct Render_Scene_3D : Def<Render_Scene_3D, Scene, Dependency_Graph_Type<Submi
* completion Taskflow 完成前调用方必须保持本帧像素所有权;节点若启动更晚结束的异步工作,
* 必须捕获 share_pixels() 等拥有像素所有权的对象,禁止只捕获会被下一帧复用的裸 Frame_3D*。
*/
[[nodiscard]] tf::Taskflow& completion_taskflow();
[[nodiscard]] Task_Graph& completion_taskflow();
void activate_view();
void deactivate_view();
void reset_frame_statistics();
+36 -7
View File
@@ -30,7 +30,7 @@ struct Render_Scene_3D::Private : Prev_Private {
std::mutex render_mutex{}; /* 只保护完成回调和单帧准入。 */
bool frame_in_flight{}; /* render 准入到异步完成回调返回的唯一状态源。 */
Frame_Callback frame_callback{}; /* Scene 的唯一对外完成出口。 */
tf::Taskflow completion_graph{}; /* GPU 像素完成后、发布回调前执行的外部续写图。 */
Task_Graph completion_graph{"render_3d.completion"}; /* GPU 像素完成后、发布回调前执行的外部续写图。 */
std::mutex completion_mutex{}; /* 只保护 completion 图拓扑的在途生命周期。 */
std::condition_variable completion_condition{};
bool completion_running{}; /* 析构等待异步 completion 图结束的唯一状态源。 */
@@ -177,6 +177,7 @@ void Render_Scene_3D::Private::initialize_backend(
callback = frame_callback;
}
auto finish = [this, object, frame, callback = std::move(callback)]() mutable {
aethera::detail::finish_taskflow_trace(*frame);
frame->mark(Frame_Trace_Marker::callback_started);
if (callback) callback(frame);
frame->mark(Frame_Trace_Marker::callback_finished);
@@ -211,7 +212,11 @@ void Render_Scene_3D::Private::initialize_backend(
* GPU 完成线程只触发 Taskflow topology,不等待编码/发送节点;最终回调在 topology 完成后执行。
* 帧准入在 finish() 之前始终有效,因此 completion 图运行期间该外部 Frame 不会被下一帧复用。
*/
aethera::detail::run_taskflow(completion_graph, std::move(finish));
if (frame->taskflow_trace_requested())
aethera::detail::run_taskflow(completion_graph, *frame,
"render_3d.completion", std::move(finish));
else
aethera::detail::run_taskflow(completion_graph, std::move(finish));
});
paint_context = std::make_shared<detail::Scene_Paint_Context<Object>>(
detail::Scene_Paint_Context<Object>{
@@ -290,14 +295,27 @@ void Render_Scene_3D::Private::process(Object* object, Callback&& callback) requ
if (!state.paint_executed) return;
const auto paint_started = std::chrono::steady_clock::now();
if (dispatch->paint.builder) {
if (!data->paint_graph) data->paint_graph = std::make_unique<tf::Taskflow>();
if (!data->paint_graph) data->paint_graph = std::make_unique<Task_Graph>(
std::string(dispatch->business_name) + ".paint");
const bool rebuild = dispatch->paint.rebuild_predicate(root);
if (!data->paint_graph_built || rebuild) { *data->paint_graph = dispatch->paint.builder(root); data->paint_graph_built = true; state.paint_graph_rebuilt = true; }
state.paint_task_count = data->paint_graph->num_tasks();
if (!data->paint_graph->empty()) aethera::detail::run_taskflow(*data->paint_graph);
state.paint_task_count = data->paint_graph->size();
if (!data->paint_graph->empty()) {
if (frame->taskflow_trace_requested())
aethera::detail::run_taskflow(
*data->paint_graph, *frame,
std::string(dispatch->business_name) + ".paint");
else
aethera::detail::run_taskflow(*data->paint_graph);
}
} else { state.paint_task_count = dispatch->paint.run ? 1 : 0; if (dispatch->paint.run) dispatch->paint.run(root); }
if (!data->paint_extension.empty())
aethera::detail::run_taskflow(data->paint_extension);
if (frame->taskflow_trace_requested())
aethera::detail::run_taskflow(
data->paint_extension, *frame,
std::string(dispatch->business_name) + ".paint.extension");
else
aethera::detail::run_taskflow(data->paint_extension);
root->template take_dirty<Submit_Tag>();
state.paint_execution_time_ns = static_cast<std::uint64_t>(
std::chrono::duration_cast<std::chrono::nanoseconds>(
@@ -336,6 +354,14 @@ Render_Scene_3D::Render_Result Render_Scene_3D::Private::render(Object* object,
}
} admission{*this, submitted};
frame->mark(Frame_Trace_Marker::scene_render_requested);
const bool trace_started = aethera::detail::begin_taskflow_trace(*frame);
struct Trace_Scope {
Frame_3D* frame{}; /* 提交前异常或拒绝时关闭 Observer 写入窗口。 */
bool active{}; /* 提交成功后所有权转交异步完成回调。 */
~Trace_Scope() {
if (active) aethera::detail::finish_taskflow_trace(*frame);
}
} trace_scope{frame, trace_started};
struct Active_Frame_Scope {
Frame_3D*& target; /* 最终 Private 的同步 process 帧槽位。 */
Frame_3D* previous{}; /* 嵌套调用前的帧;析构时恢复。 */
@@ -343,7 +369,10 @@ Render_Scene_3D::Render_Result Render_Scene_3D::Private::render(Object* object,
} active_frame_scope{active_frame, active_frame};
active_frame = frame;
object->process([&] { submitted = true; frame->mark(Frame_Trace_Marker::scene_render_finished); });
if (submitted) return Render_Result::submitted;
if (submitted) {
trace_scope.active = false;
return Render_Result::submitted;
}
const auto& prop = object->template read_prop<Render_Scene_3D::Base_Tag>();
if (!prop.view_active) return Render_Result::view_inactive;
if (prop.viewport.empty()) return Render_Result::empty_viewport;
+5 -5
View File
@@ -19,7 +19,7 @@ struct Basic_Visual<Spec>::Private : Basic_Visual::Prev_Private {
void prepare_data(Object* object);
/* CRTP 子图能力:提交本 Visual 最近一次 Prepare 生成的唯一产物。 */
template <Attached Object>
[[nodiscard]] tf::Taskflow build_paint_graph(Object* object, const Prop& prop);
[[nodiscard]] Task_Graph build_paint_graph(Object* object, const Prop& prop);
/* CRTP 覆盖:绑定 Scene 后每帧执行 Paintdirty 只表示 Prepared 数据是否更新,不控制帧生成。 */
template <Attached Object>
[[nodiscard]] bool should_paint(Object* object, const State& state, bool dirty);
@@ -67,13 +67,13 @@ void Basic_Visual<Spec>::Private::prepare_data(Object* object) {
}
template <typename Spec>
template <Attached Object>
tf::Taskflow Basic_Visual<Spec>::Private::build_paint_graph(Object* object, const Prop&) {
tf::Taskflow graph;
graph.emplace([this, object] {
Task_Graph Basic_Visual<Spec>::Private::build_paint_graph(Object* object, const Prop&) {
Task_Graph graph{"render_3d.visual.paint"};
graph.add("publish", [this, object] {
if (auto context = paint_target.context.lock(); context && paint_target.enqueue) {
paint_target.enqueue(context.get(), object, prepared);
}
}).name("render_3d.paint.publish");
});
return graph;
}
template <typename Spec>
+2 -2
View File
@@ -68,9 +68,9 @@ TEST(Render_3D_Scene, Paint_Submits_Without_Waiting_For_Gpu) {
Frame_3D exchanged_unchanged_frame{Frame_Identity{3, 0}};
Frame_3D* completed_frame{};
std::atomic_size_t completion_calls{};
scene->completion_taskflow().emplace([&] {
scene->completion_taskflow().add("test.scene_3d.completion", [&] {
completion_calls.fetch_add(1, std::memory_order_release);
}).name("test.scene_3d.completion");
});
scene->set_frame_callback([&](Frame_3D* value) {
EXPECT_GT(completion_calls.load(std::memory_order_acquire), 0u);
completed_frame = value;