优化了 还是卡

This commit is contained in:
2026-08-25 20:43:33 +08:00
parent 5437b1b267
commit 4f3430e3ad
40 changed files with 1575 additions and 760 deletions
+84 -33
View File
@@ -1,5 +1,6 @@
#include "Plot.hpp"
#include "Renderable_Adapter.hpp"
#include "Taskflow_Trace_Json.hpp"
#include <nlohmann/json.hpp>
#include <magic_enum/magic_enum.hpp>
#include <render_2D/plottable/Plottables.hpp>
@@ -202,6 +203,8 @@ void append_event_statistics_json(nlohmann::json& output,
}
}
}
nlohmann::json taskflow_trace_json(const Taskflow_Frame_Trace& trace) {
nlohmann::json markers = nlohmann::json::object();
for (const auto& marker : trace.markers)
@@ -265,6 +268,7 @@ nlohmann::json taskflow_trace_json(const Taskflow_Frame_Trace& trace) {
{"executions", std::move(executions)}};
}
namespace {
template <typename Scene_Object>
void dispatch_plot_input(Scene_Object& scene, const Plot_Input_Event& input) {
@@ -372,6 +376,8 @@ struct Plot::Private {
mutable std::mutex taskflow_trace_mutex{}; /* 只保护低频请求结果的交换。 */
std::size_t taskflow_trace_requested_count{}; /* 当前批次请求总帧数。 */
std::vector<Taskflow_Frame_Trace> taskflow_traces{}; /* 已完成帧直接发布的 DAG 与 Observer 结果。 */
Task_Node completion_tail{}; /* Scene 完成图中当前最后一个业务阶段。 */
std::vector<std::unique_ptr<Task_Graph>> completion_extensions{}; /* 生命周期覆盖 Scene 对子图的借用。 */
template <typename Scene_Object>
Private(std::unique_ptr<Scene_Object> value_scene,
@@ -383,6 +389,15 @@ struct Plot::Private {
else
slot.frame = std::make_unique<Frame_3D>(Frame_Identity{});
}
auto& completion = std::visit(
[](auto& scene_value) -> Task_Graph& {
return scene_value->completion_taskflow();
}, scene);
completion_tail = completion.add("plot.frame.publish", [this] {
publish_completed_frame();
});
completion_tail.describe("owner", "plot")
.describe("stage", "completed pixels publish");
}
[[nodiscard]] nlohmann::json schema() const;
@@ -391,7 +406,9 @@ struct Plot::Private {
void consume_tick(std::weak_ptr<Plot> lifetime);
void clock_tick(const Plot_Render_Tick& tick);
void render_frame(Plot_Render_Tick tick);
void queue_completed_frame(Render_Frame* frame);
void publish_completed_frame();
void retire_completed_frame(Render_Frame* frame);
void attach_completion(std::unique_ptr<Task_Graph> completion);
[[nodiscard]] bool mark_taskflow_trace(Render_Frame& frame);
void fail(std::exception_ptr failure) noexcept;
};
@@ -598,9 +615,7 @@ void Plot::Private::render_frame(Plot_Render_Tick tick) {
const Frame_Identity identity{sequence, tick.sequence == 0 ? sequence : tick.sequence};
if (auto* scene_2d = std::get_if<std::unique_ptr<Scene_2D>>(&scene)) {
auto& output = *std::get<std::unique_ptr<Frame_2D>>(managed->frame);
output.begin(identity, pacing.video_enabled
? render_2d::Pixel_Format::rgba8
: Frame_2D::native_pixel_format);
output.begin(identity, Frame_2D::native_pixel_format);
taskflow_trace_claimed = mark_taskflow_trace(output);
record_plot_measurements(output);
(*scene_2d)->set<&Render_Scene_2D::Prop::viewport>(
@@ -644,10 +659,8 @@ void Plot::Private::render_frame(Plot_Render_Tick tick) {
}
void Plot::Private::queue_completed_frame(Render_Frame* frame) {
if (!frame)
throw std::invalid_argument("Plot received a null completed frame");
std::size_t slot_index{scene_frame_capacity};
void Plot::Private::publish_completed_frame() {
Render_Frame* frame{};
Managed_Frame* managed{};
{
std::lock_guard lock(frame_mutex);
@@ -665,42 +678,29 @@ void Plot::Private::queue_completed_frame(Render_Frame* frame) {
callback_retired_slot.reset();
}
for (std::size_t index = 0; index < frame_slots.size(); ++index) {
Render_Frame* address = std::visit(
if (frame_slots[index].state != Frame_State::in_flight) continue;
if (managed)
throw std::logic_error("Plot has multiple active Scene frames");
frame = std::visit(
[](const auto& value) -> Render_Frame* { return value.get(); },
frame_slots[index].frame);
if (address != frame) continue;
slot_index = index;
managed = &frame_slots[index];
break;
}
if (!managed || managed->state != Frame_State::in_flight)
throw std::logic_error("frame callback has no externally owned active frame");
throw std::logic_error("Scene completion graph has no active Plot frame");
}
const auto retire = [this, slot_index] {
std::lock_guard lock(frame_mutex);
auto& completed = frame_slots[slot_index];
if (completed.state != Frame_State::in_flight) return;
if (callback_retired_slot)
throw std::logic_error("Plot has more than one callback-retired frame");
completed.state = Frame_State::callback_retired;
callback_retired_slot = slot_index;
};
try {
if (frame->taskflow_trace_requested()) {
auto trace = frame->taskflow_trace();
std::lock_guard lock(taskflow_trace_mutex);
taskflow_traces.push_back(std::move(trace));
}
const auto pacing = frame_policy.snapshot();
const auto identity = frame->identity();
Frame_Identity rendered_identity = identity;
std::shared_ptr<const std::vector<std::byte>> pixel_storage;
Plot_Pixel_Layout pixel_layout{Plot_Pixel_Layout::rgba8};
std::uint32_t width{};
std::uint32_t height{};
if (auto* frame_2d =
std::get_if<std::unique_ptr<Frame_2D>>(&managed->frame)) {
pixel_layout = Plot_Pixel_Layout::bgra8;
const auto image = (*frame_2d)->image();
width = static_cast<std::uint32_t>(image.width);
height = static_cast<std::uint32_t>(image.height);
@@ -725,7 +725,7 @@ void Plot::Private::queue_completed_frame(Render_Frame* frame) {
}
auto pixels = std::make_shared<const Plot_Pixel_Frame>(Plot_Pixel_Frame{
std::move(pixel_storage), managed->presentation_time,
std::move(pixel_storage), pixel_layout, managed->presentation_time,
identity.sequence, identity.correlation_id,
rendered_identity.sequence, rendered_identity.correlation_id,
width, height});
@@ -738,14 +738,60 @@ void Plot::Private::queue_completed_frame(Render_Frame* frame) {
static_cast<std::uint64_t>(std::max<std::int64_t>(0,
std::chrono::duration_cast<std::chrono::nanoseconds>(
std::chrono::steady_clock::now() - publish_started).count())));
retire();
}
catch (...) {
retire();
throw;
}
}
void Plot::Private::retire_completed_frame(Render_Frame* frame) {
if (!frame)
throw std::invalid_argument("Plot received a null completed frame");
std::size_t slot_index{scene_frame_capacity};
{
std::lock_guard lock(frame_mutex);
for (std::size_t index = 0; index < frame_slots.size(); ++index) {
auto* address = std::visit(
[](const auto& value) -> Render_Frame* { return value.get(); },
frame_slots[index].frame);
if (address != frame) continue;
if (frame_slots[index].state != Frame_State::in_flight)
throw std::logic_error("completed Plot frame is not in flight");
slot_index = index;
break;
}
if (slot_index == scene_frame_capacity)
throw std::logic_error(
"frame callback has no externally owned active frame");
if (callback_retired_slot)
throw std::logic_error("Plot has more than one callback-retired frame");
frame_slots[slot_index].state = Frame_State::callback_retired;
callback_retired_slot = slot_index;
}
if (frame->taskflow_trace_requested()) {
auto trace = frame->taskflow_trace();
std::lock_guard lock(taskflow_trace_mutex);
taskflow_traces.push_back(std::move(trace));
}
}
void Plot::Private::attach_completion(
std::unique_ptr<Task_Graph> completion) {
if (!completion || completion->empty())
throw std::invalid_argument("Plot completion pipeline is empty");
auto& scene_completion = std::visit(
[](auto& scene_value) -> Task_Graph& {
return scene_value->completion_taskflow();
}, scene);
completion_extensions.push_back(std::move(completion));
auto extension = scene_completion.compose(
completion_extensions.back()->name(), *completion_extensions.back());
extension.describe("owner", "scene")
.describe("stage", "frame pipeline extension");
completion_tail.precede(extension);
completion_tail = std::move(extension);
}
Plot::Plot(std::unique_ptr<Scene_2D> scene,
std::unique_ptr<Scene_View> view)
: d(std::make_unique<Private>(std::move(scene), std::move(view))) {}
@@ -754,6 +800,11 @@ Plot::Plot(std::unique_ptr<Scene_3D> scene,
: d(std::make_unique<Private>(std::move(scene), std::move(view))) {}
Plot::~Plot() = default;
void Plot::attach_scene_completion(
std::unique_ptr<Task_Graph> completion) {
d->attach_completion(std::move(completion));
}
void Plot::ensure_started() {
std::call_once(d->start_once, [this] {
/*
@@ -765,7 +816,7 @@ void Plot::ensure_started() {
(*scene)->set_frame_callback(
[weak = weak_from_this()](Frame_2D* frame) {
if (auto owner = weak.lock()) {
try { owner->d->queue_completed_frame(frame); }
try { owner->d->retire_completed_frame(frame); }
catch (...) { owner->d->fail(std::current_exception()); }
}
});
@@ -773,7 +824,7 @@ void Plot::ensure_started() {
std::get<std::unique_ptr<Scene_3D>>(d->scene)->set_frame_callback(
[weak = weak_from_this()](Frame_3D* frame) {
if (auto owner = weak.lock()) {
try { owner->d->queue_completed_frame(frame); }
try { owner->d->retire_completed_frame(frame); }
catch (...) { owner->d->fail(std::current_exception()); }
}
});