更新
This commit is contained in:
@@ -97,6 +97,13 @@ inline void end_tracy_task_zone(Tracy_Task_Zone zone) noexcept {
|
||||
if (zone.context.active == 0) return;
|
||||
TracyCZoneEnd(zone.context)
|
||||
}
|
||||
template <class Tags>
|
||||
void attach_tracy_task_tags(Tracy_Task_Zone zone, const Tags& tags) {
|
||||
if (zone.context.active == 0) return;
|
||||
Tracy_Text_Sink sink;
|
||||
serialize(sink, tags);
|
||||
if (!sink.empty()) TracyCZoneText(zone.context, sink.data(), sink.size())
|
||||
}
|
||||
template <class Make_Tags>
|
||||
void attach_tracy_tags(tracy::ScopedZone& zone, Make_Tags&& make_tags) {
|
||||
if (!zone.IsActive()) return;
|
||||
@@ -122,10 +129,12 @@ inline void end_tracy_task_zone(Tracy_Task_Zone) noexcept {}
|
||||
#define AETHERA_TRACE_PLOT_I(name, value) do { if (::aethera::observation::tracy_connected()) TracyCPlotI(name, static_cast<std::int64_t>(value)) } while (false)
|
||||
#define AETHERA_TRACE_THREAD_NAME(name) do { ::aethera::observation::set_tracy_thread_name(name); } while (false)
|
||||
#define AETHERA_TRACE_FRAME(name) FrameMarkNamed(name)
|
||||
#define AETHERA_TRACE_TASKFLOW_CONTEXT_ARG(frame, generation) , ::aethera::Taskflow_Trace_Context{frame, generation}
|
||||
#else
|
||||
#define AETHERA_TRACE_ZONE(name)
|
||||
#define AETHERA_TRACE_ZONE_TAGS(name, ...)
|
||||
#define AETHERA_TRACE_PLOT_I(name, value)
|
||||
#define AETHERA_TRACE_THREAD_NAME(name)
|
||||
#define AETHERA_TRACE_FRAME(name)
|
||||
#define AETHERA_TRACE_TASKFLOW_CONTEXT_ARG(frame, generation)
|
||||
#endif
|
||||
|
||||
@@ -52,6 +52,10 @@ enum struct Initialize_Task_Runtime_Result : std::uint8_t {
|
||||
};
|
||||
using Taskflow_Completion = std::function<void(std::exception_ptr)>;
|
||||
using Taskflow_Exception_Boundary = std::function<void(std::exception_ptr)>;
|
||||
struct Taskflow_Trace_Context {
|
||||
std::uint64_t frame{};
|
||||
std::uint64_t generation{};
|
||||
};
|
||||
namespace task_flow {
|
||||
struct Task_Node : facade_builder
|
||||
::add_convention<_describe_node, Describe_Task_Graph_Node_Result(std::string, std::string)>
|
||||
@@ -70,8 +74,8 @@ struct Task_Graph_Compose_Facade : facade_builder
|
||||
::add_facade_with_substitution<Task_Graph_Common_Facade>
|
||||
::add_convention<_compose, std::expected<proxy<Task_Node>, Compose_Task_Graph_Result>(std::string, proxy<Task_Graph_Component> &)>
|
||||
::add_convention<_precede, Precede_Task_Graph_Result(proxy<Task_Node> &, proxy<Task_Node> &)>
|
||||
::add_convention<_run, Run_Taskflow_Result(Taskflow_Completion)>
|
||||
::add_convention<_run_observed, Run_Taskflow_Result(Taskflow_Completion, Taskflow_Observation)>
|
||||
::add_convention<_run, Run_Taskflow_Result(Taskflow_Completion), Run_Taskflow_Result(Taskflow_Completion, Taskflow_Trace_Context)>
|
||||
::add_convention<_run_observed, Run_Taskflow_Result(Taskflow_Completion, Taskflow_Observation), Run_Taskflow_Result(Taskflow_Completion, Taskflow_Observation, Taskflow_Trace_Context)>
|
||||
::add_convention<_corun_until, void(std::function<bool()>)>
|
||||
::build {};
|
||||
struct Task_Graph_Facade : facade_builder::add_facade_with_substitution<Task_Graph_Build_Facade>::add_facade_with_substitution<Task_Graph_Compose_Facade>::build {};
|
||||
|
||||
@@ -19,7 +19,9 @@ struct Task_Graph_Model::Private : Prev_Private {
|
||||
void clear();
|
||||
bool empty() const noexcept;
|
||||
Run_Taskflow_Result run(Taskflow_Completion completion);
|
||||
Run_Taskflow_Result run(Taskflow_Completion completion, Taskflow_Trace_Context trace_context);
|
||||
Run_Taskflow_Result run_observed(Taskflow_Completion completion, Taskflow_Observation observation);
|
||||
Run_Taskflow_Result run_observed(Taskflow_Completion completion, Taskflow_Observation observation, Taskflow_Trace_Context trace_context);
|
||||
void corun_until(std::function<bool()> predicate);
|
||||
private:
|
||||
std::shared_ptr<aethera::Task_Graph> graph; /* 所有消费 facade 共享的唯一权威任务图。 */
|
||||
|
||||
@@ -52,7 +52,7 @@ using Clock = std::chrono::steady_clock;
|
||||
* 升级 Taskflow 时必须重新审核版本、字段布局、对齐以及 topology/on_exit 完成顺序。
|
||||
*/
|
||||
static_assert(TF_VERSION == 400100);
|
||||
void* task_observation(const tf::TaskView& task) noexcept {
|
||||
detail::Taskflow_Observation_Execution* task_observer_execution(const tf::TaskView& task) noexcept {
|
||||
static_assert(sizeof(tf::TaskView) == sizeof(tf::Node*));
|
||||
static_assert(alignof(tf::TaskView) == alignof(tf::Node*));
|
||||
static_assert(sizeof(tf::Task) == sizeof(tf::Node*));
|
||||
@@ -60,7 +60,7 @@ void* task_observation(const tf::TaskView& task) noexcept {
|
||||
auto* node = *reinterpret_cast<tf::Node* const*>(std::addressof(task));
|
||||
tf::Task handle{};
|
||||
*reinterpret_cast<tf::Node**>(std::addressof(handle)) = node;
|
||||
return handle.data();
|
||||
return static_cast<detail::Taskflow_Observation_Execution*>(handle.data());
|
||||
}
|
||||
const tf::Worker& task_worker(const tf::WorkerView& worker) noexcept {
|
||||
static_assert(sizeof(tf::WorkerView) == sizeof(tf::Worker*));
|
||||
@@ -71,6 +71,13 @@ const tf::Worker& task_worker(const tf::WorkerView& worker) noexcept {
|
||||
struct Task_Observer final : tf::ObserverInterface {
|
||||
#ifdef TRACY_ENABLE
|
||||
static constexpr std::size_t Tracy_Zone_Depth = 128;
|
||||
struct Frame_Task_Trace_Tags {
|
||||
std::uint64_t frame{};
|
||||
std::uint64_t generation{};
|
||||
std::string_view graph{};
|
||||
std::size_t worker{};
|
||||
std::uint64_t task{};
|
||||
};
|
||||
struct Tracy_Worker_State {
|
||||
std::array<observation::Tracy_Task_Zone, Tracy_Zone_Depth> zones{};
|
||||
std::size_t depth{};
|
||||
@@ -88,7 +95,7 @@ struct Task_Observer final : tf::ObserverInterface {
|
||||
observation::set_tracy_thread_name(name.data());
|
||||
state.named = true;
|
||||
}
|
||||
void trace_entry(const tf::Worker& worker, const tf::TaskView& task, std::uint64_t native_id) noexcept {
|
||||
void trace_entry(const tf::Worker& worker, const tf::TaskView& task, std::uint64_t native_id, const detail::Taskflow_Observation_Execution* execution) noexcept {
|
||||
auto& state = tracy_worker_states[worker.id()];
|
||||
name_worker(state, worker.id());
|
||||
if (state.ignored_depth != 0) {
|
||||
@@ -104,7 +111,13 @@ struct Task_Observer final : tf::ObserverInterface {
|
||||
return;
|
||||
}
|
||||
const std::string_view name{task.name()};
|
||||
state.zones[state.depth++] = observation::begin_tracy_task_zone(name, native_id);
|
||||
auto& zone = state.zones[state.depth++];
|
||||
zone = observation::begin_tracy_task_zone(name, native_id);
|
||||
if (execution == nullptr) return;
|
||||
std::string_view graph;
|
||||
const auto* context = execution->trace_context(graph);
|
||||
if (context == nullptr) return;
|
||||
observation::attach_tracy_task_tags(zone, Frame_Task_Trace_Tags{context->frame, context->generation, graph, worker.id(), native_id});
|
||||
}
|
||||
void trace_exit(const tf::Worker& worker) noexcept {
|
||||
auto& state = tracy_worker_states[worker.id()];
|
||||
@@ -125,34 +138,28 @@ struct Task_Observer final : tf::ObserverInterface {
|
||||
#endif
|
||||
}
|
||||
void on_entry(tf::WorkerView worker, tf::TaskView task) override {
|
||||
auto* observation_execution = task_observation(task);
|
||||
auto* observation_execution = task_observer_execution(task);
|
||||
#ifdef TRACY_ENABLE
|
||||
const auto& native_worker = task_worker(worker);
|
||||
const auto native_id = static_cast<std::uint64_t>(task.hash_value());
|
||||
if (observation_execution != nullptr) {
|
||||
auto& execution = *static_cast<detail::Taskflow_Observation_Execution*>(observation_execution);
|
||||
execution.observe_entry(native_worker, native_id, Clock::now());
|
||||
}
|
||||
trace_entry(native_worker, task, native_id);
|
||||
if (observation_execution != nullptr && observation_execution->records_observation()) observation_execution->observe_entry(native_worker, native_id, Clock::now());
|
||||
trace_entry(native_worker, task, native_id, observation_execution);
|
||||
#else
|
||||
if (observation_execution == nullptr) return;
|
||||
auto& execution = *static_cast<detail::Taskflow_Observation_Execution*>(observation_execution);
|
||||
execution.observe_entry(task_worker(worker), static_cast<std::uint64_t>(task.hash_value()), Clock::now());
|
||||
if (observation_execution == nullptr || !observation_execution->records_observation()) return;
|
||||
observation_execution->observe_entry(task_worker(worker), static_cast<std::uint64_t>(task.hash_value()), Clock::now());
|
||||
#endif
|
||||
}
|
||||
void on_exit(tf::WorkerView worker, tf::TaskView task) override {
|
||||
auto* observation_execution = task_observation(task);
|
||||
auto* observation_execution = task_observer_execution(task);
|
||||
#ifdef TRACY_ENABLE
|
||||
const auto& native_worker = task_worker(worker);
|
||||
const auto native_id = static_cast<std::uint64_t>(task.hash_value());
|
||||
trace_exit(native_worker);
|
||||
if (observation_execution == nullptr) return;
|
||||
auto& execution = *static_cast<detail::Taskflow_Observation_Execution*>(observation_execution);
|
||||
execution.observe_exit(native_worker, native_id, Clock::now());
|
||||
if (observation_execution == nullptr || !observation_execution->records_observation()) return;
|
||||
observation_execution->observe_exit(native_worker, native_id, Clock::now());
|
||||
#else
|
||||
if (observation_execution == nullptr) return;
|
||||
auto& execution = *static_cast<detail::Taskflow_Observation_Execution*>(observation_execution);
|
||||
execution.observe_exit(task_worker(worker), static_cast<std::uint64_t>(task.hash_value()), Clock::now());
|
||||
if (observation_execution == nullptr || !observation_execution->records_observation()) return;
|
||||
observation_execution->observe_exit(task_worker(worker), static_cast<std::uint64_t>(task.hash_value()), Clock::now());
|
||||
#endif
|
||||
}
|
||||
};
|
||||
@@ -188,7 +195,7 @@ public:
|
||||
if (!predicate) throw std::invalid_argument("task graph cooperative predicate is empty");
|
||||
executor->corun_until(std::move(predicate));
|
||||
}
|
||||
Run_Taskflow_Result run(Task_Graph& graph, Taskflow_Completion completion, std::optional<Taskflow_Observation> observation) {
|
||||
Run_Taskflow_Result run(Task_Graph& graph, Taskflow_Completion completion, std::optional<Taskflow_Observation> observation, std::optional<Taskflow_Trace_Context> trace_context) {
|
||||
if (!ready()) {
|
||||
return Run_Taskflow_Result::runtime_not_initialized;
|
||||
}
|
||||
@@ -215,6 +222,11 @@ public:
|
||||
if (!observation_execution) {
|
||||
return Run_Taskflow_Result::observation_unavailable;
|
||||
}
|
||||
#ifdef TRACY_ENABLE
|
||||
if (trace_context && observation::tracy_connected()) observation_execution->set_trace_context(*trace_context, graph_execution->native_taskflow().name());
|
||||
#else
|
||||
(void)trace_context;
|
||||
#endif
|
||||
auto execution = std::make_shared<Taskflow_Execution>(std::move(graph_execution), std::move(*observation_execution), std::move(completion), *completion_boundary);
|
||||
execution->graph->bind_observation(execution->observation.binding());
|
||||
(void)executor->run(execution->graph->native_taskflow(), [execution] {
|
||||
@@ -260,10 +272,16 @@ Initialize_Task_Runtime_Result initialize_task_runtime(std::size_t workers, Unkn
|
||||
return Task_Resource::instance().initialize(workers, failure_policy, std::move(exception_boundary));
|
||||
}
|
||||
Run_Taskflow_Result run_taskflow(Task_Graph& graph, Taskflow_Completion completion) {
|
||||
return Task_Resource::instance().run(graph, std::move(completion), std::nullopt);
|
||||
return Task_Resource::instance().run(graph, std::move(completion), std::nullopt, std::nullopt);
|
||||
}
|
||||
Run_Taskflow_Result run_taskflow(Task_Graph& graph, Taskflow_Completion completion, Taskflow_Trace_Context trace_context) {
|
||||
return Task_Resource::instance().run(graph, std::move(completion), std::nullopt, trace_context);
|
||||
}
|
||||
Run_Taskflow_Result run_taskflow(Task_Graph& graph, Taskflow_Completion completion, Taskflow_Observation observation) {
|
||||
return Task_Resource::instance().run(graph, std::move(completion), std::move(observation));
|
||||
return Task_Resource::instance().run(graph, std::move(completion), std::move(observation), std::nullopt);
|
||||
}
|
||||
Run_Taskflow_Result run_taskflow(Task_Graph& graph, Taskflow_Completion completion, Taskflow_Observation observation, Taskflow_Trace_Context trace_context) {
|
||||
return Task_Resource::instance().run(graph, std::move(completion), std::move(observation), trace_context);
|
||||
}
|
||||
|
||||
void detail::corun_taskflow_until(std::function<bool()> predicate) {
|
||||
|
||||
@@ -14,6 +14,8 @@ void corun_taskflow_until(std::function<bool()> predicate);
|
||||
}
|
||||
/* 完成回调接收业务任务传播出的 Unknown Failure;本次执行不记录观察数据。 */
|
||||
Run_Taskflow_Result run_taskflow(Task_Graph& graph, Taskflow_Completion completion);
|
||||
Run_Taskflow_Result run_taskflow(Task_Graph& graph, Taskflow_Completion completion, Taskflow_Trace_Context trace_context);
|
||||
/* 完成回调接收业务任务传播出的 Unknown Failure;observation 记录本次执行。 */
|
||||
Run_Taskflow_Result run_taskflow(Task_Graph& graph, Taskflow_Completion completion, Taskflow_Observation observation);
|
||||
Run_Taskflow_Result run_taskflow(Task_Graph& graph, Taskflow_Completion completion, Taskflow_Observation observation, Taskflow_Trace_Context trace_context);
|
||||
}
|
||||
|
||||
@@ -161,8 +161,20 @@ detail::Taskflow_Observation_Execution::~Taskflow_Observation_Execution() {
|
||||
}
|
||||
detail::Taskflow_Observation_Execution::Taskflow_Observation_Execution(
|
||||
Taskflow_Observation_Execution&&) noexcept = default;
|
||||
bool detail::Taskflow_Observation_Execution::records_observation() const noexcept {
|
||||
return observation != nullptr;
|
||||
}
|
||||
void detail::Taskflow_Observation_Execution::set_trace_context(Taskflow_Trace_Context context, std::string_view graph) noexcept {
|
||||
trace_context_data = context;
|
||||
trace_graph = graph;
|
||||
}
|
||||
const Taskflow_Trace_Context* detail::Taskflow_Observation_Execution::trace_context(std::string_view& graph) const noexcept {
|
||||
if (!trace_context_data) return nullptr;
|
||||
graph = trace_graph;
|
||||
return std::addressof(*trace_context_data);
|
||||
}
|
||||
detail::Taskflow_Observation_Execution* detail::Taskflow_Observation_Execution::binding() noexcept {
|
||||
return observation ? this : nullptr;
|
||||
return observation || trace_context_data ? this : nullptr;
|
||||
}
|
||||
void detail::Taskflow_Observation_Execution::observe_entry(
|
||||
const tf::Worker& worker,
|
||||
|
||||
@@ -10,7 +10,9 @@
|
||||
#include <expected>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
namespace tf {
|
||||
class Taskflow;
|
||||
@@ -73,6 +75,9 @@ public:
|
||||
const Taskflow_Observation_Execution&) = delete;
|
||||
Taskflow_Observation_Execution& operator=(
|
||||
const Taskflow_Observation_Execution&) = delete;
|
||||
bool records_observation() const noexcept;
|
||||
void set_trace_context(Taskflow_Trace_Context context, std::string_view graph) noexcept;
|
||||
const Taskflow_Trace_Context* trace_context(std::string_view& graph) const noexcept;
|
||||
Taskflow_Observation_Execution* binding() noexcept;
|
||||
void observe_entry(
|
||||
const tf::Worker& worker,
|
||||
@@ -89,5 +94,7 @@ private:
|
||||
std::shared_ptr<Taskflow_Observation::Private> observation) noexcept;
|
||||
void cancel() noexcept;
|
||||
std::shared_ptr<Taskflow_Observation::Private> observation; /* 可空记录所有权;空表示本次执行未请求观察。 */
|
||||
std::optional<Taskflow_Trace_Context> trace_context_data{};
|
||||
std::string_view trace_graph{};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -45,9 +45,15 @@ bool Task_Graph_Model::Private::empty() const noexcept {
|
||||
Run_Taskflow_Result Task_Graph_Model::Private::run(Taskflow_Completion completion) {
|
||||
return run_taskflow(*graph, std::move(completion));
|
||||
}
|
||||
Run_Taskflow_Result Task_Graph_Model::Private::run(Taskflow_Completion completion, Taskflow_Trace_Context trace_context) {
|
||||
return run_taskflow(*graph, std::move(completion), trace_context);
|
||||
}
|
||||
Run_Taskflow_Result Task_Graph_Model::Private::run_observed(Taskflow_Completion completion, Taskflow_Observation observation) {
|
||||
return run_taskflow(*graph, std::move(completion), std::move(observation));
|
||||
}
|
||||
Run_Taskflow_Result Task_Graph_Model::Private::run_observed(Taskflow_Completion completion, Taskflow_Observation observation, Taskflow_Trace_Context trace_context) {
|
||||
return run_taskflow(*graph, std::move(completion), std::move(observation), trace_context);
|
||||
}
|
||||
void Task_Graph_Model::Private::corun_until(std::function<bool()> predicate) {
|
||||
aethera::detail::corun_taskflow_until(std::move(predicate));
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "Render_Scene_2D.hpp"
|
||||
#include "observation/Tracy.hpp"
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
@@ -63,6 +64,7 @@ void Render_Scene_2D::Private::dispatch_events(Event_Batch& events) {
|
||||
Render_Scene_2D_Result Render_Scene_2D::Private::render(Frame_2D* frame, Completion completion) {
|
||||
if (!frame) return std::unexpected(Render_Scene_2D_Error{Render_Scene_2D_State_Result::frame_missing});
|
||||
if (!completion) return std::unexpected(Render_Scene_2D_Error{Render_Scene_2D_State_Result::completion_missing});
|
||||
AETHERA_TRACE_FRAME("Render2D");
|
||||
auto properties = concurrent<Prop_Tag>();
|
||||
properties.internal.advance();
|
||||
commit<aethera::scene::Renderable>();
|
||||
@@ -77,9 +79,10 @@ Render_Scene_2D_Result Render_Scene_2D::Private::render(Frame_2D* frame, Complet
|
||||
const auto built = build_frame(target, current.viewport, current.background);
|
||||
if (!built) return built;
|
||||
auto completed = [frame, completion = std::move(completion)](std::exception_ptr failure) mutable {
|
||||
AETHERA_TRACE_ZONE_TAGS("Render2D.Completion", Taskflow_Trace_Context{frame->identity().sequence, frame->identity().generation});
|
||||
completion(frame, std::move(failure));
|
||||
};
|
||||
const auto submitted = frame->taskflow_trace_requested() ? taskflow()->run_observed(std::move(completed), detail::Frame_2D_Access::taskflow_observation(frame)) : taskflow()->run(std::move(completed));
|
||||
const auto submitted = frame->taskflow_trace_requested() ? taskflow()->run_observed(std::move(completed), detail::Frame_2D_Access::taskflow_observation(frame) AETHERA_TRACE_TASKFLOW_CONTEXT_ARG(frame->identity().sequence, frame->identity().generation)) : taskflow()->run(std::move(completed) AETHERA_TRACE_TASKFLOW_CONTEXT_ARG(frame->identity().sequence, frame->identity().generation));
|
||||
if (submitted != Run_Taskflow_Result::submitted) return std::unexpected(Render_Scene_2D_Error{submitted});
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "../detail/Exception.hpp"
|
||||
#include "../detail/Gpu_Completion_Service.hpp"
|
||||
#include "Error_handling_specification/Failure_Policy.hpp"
|
||||
#include "observation/Tracy.hpp"
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <chrono>
|
||||
@@ -237,6 +238,7 @@ inline void Render_Scene_3D::Private::render_datoviz(const Shared_Render_Executi
|
||||
frame->mark(Frame_Trace_Marker::backend_submit_queued);
|
||||
auto shared_reservation = std::make_shared<detail::Gpu_Completion_Service::Reservation>(std::move(reservation.reservation));
|
||||
submit(*execution->datoviz_frame, [this, execution, frame, shared_reservation = std::move(shared_reservation)](std::exception_ptr submission_failure) mutable {
|
||||
AETHERA_TRACE_ZONE_TAGS("Render3D.Submit.Callback", Taskflow_Trace_Context{frame->identity().sequence, frame->identity().generation});
|
||||
try {
|
||||
frame->mark(Frame_Trace_Marker::backend_queue_left);
|
||||
if (submission_failure) {
|
||||
@@ -272,6 +274,7 @@ inline void Render_Scene_3D::Private::render_datoviz(const Shared_Render_Executi
|
||||
}
|
||||
|
||||
inline void Render_Scene_3D::Private::observe_datoviz_completion(const Shared_Render_Execution& execution, std::optional<detail::Gpu_Completion_Service::Result> result, std::exception_ptr failure) noexcept {
|
||||
AETHERA_TRACE_ZONE_TAGS("Render3D.GPU.Completion", Taskflow_Trace_Context{execution->frame->identity().sequence, execution->frame->identity().generation});
|
||||
execution->frame->mark(Frame_Trace_Marker::gpu_completed);
|
||||
execution->completion_result = std::move(result);
|
||||
execution->backend_failure = std::move(failure);
|
||||
@@ -291,7 +294,7 @@ inline void Render_Scene_3D::Private::try_complete(const Shared_Render_Execution
|
||||
if (!task) throw std::logic_error("failed to create 3D completion task");
|
||||
const auto submitted = graph->run([execution](std::exception_ptr runtime_failure) mutable {
|
||||
complete_execution(std::move(execution), std::move(runtime_failure));
|
||||
});
|
||||
} AETHERA_TRACE_TASKFLOW_CONTEXT_ARG(execution->frame->identity().sequence, execution->frame->identity().generation));
|
||||
if (submitted != Run_Taskflow_Result::submitted) throw std::runtime_error("3D completion task runtime is unavailable");
|
||||
}
|
||||
catch (...) {
|
||||
@@ -330,6 +333,7 @@ inline std::exception_ptr Render_Scene_3D::Private::collect_datoviz(Render_Execu
|
||||
|
||||
inline void Render_Scene_3D::Private::complete_execution(Shared_Render_Execution execution, std::exception_ptr runtime_failure) {
|
||||
auto* frame = execution->frame;
|
||||
AETHERA_TRACE_ZONE_TAGS("Render3D.Frame.Completion", Taskflow_Trace_Context{frame->identity().sequence, frame->identity().generation});
|
||||
auto callback = std::move(execution->completion);
|
||||
auto failure = execution->cpu_failure ? std::move(execution->cpu_failure) : std::move(execution->backend_failure);
|
||||
if (!failure) failure = std::move(execution->collection_failure);
|
||||
@@ -360,6 +364,7 @@ inline void Render_Scene_3D::Private::fail_datoviz(std::exception_ptr failure) n
|
||||
inline Render_Scene_3D::Render_Result Render_Scene_3D::Private::render(Frame_3D* frame, Completion completion) {
|
||||
if (!frame) return Render_Result::frame_missing;
|
||||
if (!completion) return Render_Result::completion_missing;
|
||||
AETHERA_TRACE_FRAME("Render3D");
|
||||
frame->mark(Frame_Trace_Marker::scene_render_entered);
|
||||
try {
|
||||
frame->mark(Frame_Trace_Marker::scene_advance_started);
|
||||
@@ -376,12 +381,13 @@ inline Render_Scene_3D::Render_Result Render_Scene_3D::Private::render(Frame_3D*
|
||||
auto graph = build_frame_graph(execution, parameters);
|
||||
frame->mark(Frame_Trace_Marker::scene_render_requested);
|
||||
auto completed = [this, execution](std::exception_ptr failure) {
|
||||
AETHERA_TRACE_ZONE_TAGS("Render3D.CPU.Completion", Taskflow_Trace_Context{execution->frame->identity().sequence, execution->frame->identity().generation});
|
||||
execution->cpu_failure = std::move(failure);
|
||||
if (execution->cpu_failure && !execution->backend_started.load(std::memory_order_acquire)) execution->backend_finished.store(true, std::memory_order_release);
|
||||
execution->cpu_finished.store(true, std::memory_order_release);
|
||||
try_complete(execution);
|
||||
};
|
||||
const auto submitted = frame->taskflow_trace_requested() ? graph->run_observed(std::move(completed), detail::Frame_3D_Access::taskflow_observation(frame)) : graph->run(std::move(completed));
|
||||
const auto submitted = frame->taskflow_trace_requested() ? graph->run_observed(std::move(completed), detail::Frame_3D_Access::taskflow_observation(frame) AETHERA_TRACE_TASKFLOW_CONTEXT_ARG(frame->identity().sequence, frame->identity().generation)) : graph->run(std::move(completed) AETHERA_TRACE_TASKFLOW_CONTEXT_ARG(frame->identity().sequence, frame->identity().generation));
|
||||
if (submitted != Run_Taskflow_Result::submitted) return Render_Result::backend_unavailable;
|
||||
return Render_Result::submitted;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user