更新
This commit is contained in:
@@ -12,10 +12,6 @@ struct Frame_Context {
|
||||
const auto identity = make_identity(frame, generation);
|
||||
return Frame_Context{make_root_context(identity), frame, generation};
|
||||
}
|
||||
inline void trace_frame(const Frame_Context& value) noexcept {
|
||||
AETHERA_TRACE_FRAME("Aethera.Frame");
|
||||
AETHERA_TRACE_MESSAGE_TAGS(value);
|
||||
}
|
||||
template <class Sink>
|
||||
void trace_serialize(Sink& sink, const Frame_Context& value) {
|
||||
sink.field("event", "frame");
|
||||
@@ -23,4 +19,8 @@ void trace_serialize(Sink& sink, const Frame_Context& value) {
|
||||
sink.field("frame", value.frame);
|
||||
sink.field("generation", value.generation);
|
||||
}
|
||||
inline void trace_frame(const Frame_Context& value) noexcept {
|
||||
AETHERA_TRACE_FRAME("Aethera.Frame");
|
||||
AETHERA_TRACE_MESSAGE_TAGS(value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
#pragma once
|
||||
#include "Frame_Timing.hpp"
|
||||
#include "GPU_Completion.hpp"
|
||||
#include "Frame_Policy.hpp"
|
||||
#include "Tracy.hpp"
|
||||
#include "Vulkan.hpp"
|
||||
#include <cstdint>
|
||||
namespace aethera::observation {
|
||||
struct Frame_Attention {
|
||||
Frame_Timing timing{};
|
||||
std::uint64_t gpu_render_ns{};
|
||||
std::uint64_t gpu_total_ns{};
|
||||
std::uint64_t uploaded_bytes{};
|
||||
std::uint64_t readback_bytes{};
|
||||
std::uint64_t upload_ns{};
|
||||
std::uint64_t upload_queue_wait_ns{};
|
||||
std::uint64_t upload_fence_wait_ns{};
|
||||
std::uint64_t shader_compile_ns{};
|
||||
std::uint64_t pipeline_create_ns{};
|
||||
std::uint32_t pipeline_create_count{};
|
||||
Vulkan_State vulkan{};
|
||||
GPU_Completion_State gpu_completion{};
|
||||
};
|
||||
struct Frame_Attention_Index {
|
||||
Frame_Context frame{};
|
||||
bool resource_activity{};
|
||||
bool upload_wait{};
|
||||
bool pipeline_build{};
|
||||
bool frame_overlap{};
|
||||
bool non_frame_submission{};
|
||||
bool completion_queue_gap{};
|
||||
bool completion_saturated{};
|
||||
};
|
||||
[[nodiscard]] inline Frame_Attention_Index make_frame_attention_index(const Frame_Attention& value) noexcept {
|
||||
return Frame_Attention_Index{
|
||||
value.timing.frame,
|
||||
value.uploaded_bytes != 0 || value.readback_bytes != 0 || value.upload_ns != 0 || value.shader_compile_ns != 0 || value.pipeline_create_ns != 0 || value.pipeline_create_count != 0,
|
||||
value.upload_queue_wait_ns != 0 || value.upload_fence_wait_ns != 0,
|
||||
value.shader_compile_ns != 0 || value.pipeline_create_ns != 0 || value.pipeline_create_count != 0,
|
||||
value.vulkan.frames_in_flight > 1,
|
||||
value.vulkan.pending_submissions > value.vulkan.frames_in_flight,
|
||||
value.gpu_completion.in_flight > value.gpu_completion.active,
|
||||
value.gpu_completion.capacity != 0 && value.gpu_completion.in_flight >= value.gpu_completion.capacity};
|
||||
}
|
||||
[[nodiscard]] inline bool has_frame_attention_index(const Frame_Attention_Index& value) noexcept {
|
||||
return value.resource_activity || value.upload_wait || value.pipeline_build || value.frame_overlap || value.non_frame_submission || value.completion_queue_gap || value.completion_saturated;
|
||||
}
|
||||
template <class Sink>
|
||||
void trace_serialize(Sink& sink, const Frame_Attention& value) {
|
||||
sink.field("event", "frame_attention");
|
||||
trace_serialize(sink, value.timing.frame.context);
|
||||
sink.field("frame", value.timing.frame.frame);
|
||||
sink.field("generation", value.timing.frame.generation);
|
||||
sink.field("render_latency_ns", value.timing.render_latency_ns);
|
||||
sink.field("graph_start_latency_ns", value.timing.graph_start_latency_ns);
|
||||
sink.field("graph_to_submit_ns", value.timing.graph_to_submit_ns);
|
||||
sink.field("backend_prepare_ns", value.timing.backend_prepare_ns);
|
||||
sink.field("submit_path_ns", value.timing.submit_path_ns);
|
||||
sink.field("completion_tail_ns", value.timing.completion_tail_ns);
|
||||
sink.field("gpu_render_ns", value.gpu_render_ns);
|
||||
sink.field("gpu_total_ns", value.gpu_total_ns);
|
||||
sink.field("uploaded_bytes", value.uploaded_bytes);
|
||||
sink.field("readback_bytes", value.readback_bytes);
|
||||
sink.field("upload_ns", value.upload_ns);
|
||||
sink.field("upload_queue_wait_ns", value.upload_queue_wait_ns);
|
||||
sink.field("upload_fence_wait_ns", value.upload_fence_wait_ns);
|
||||
sink.field("shader_compile_ns", value.shader_compile_ns);
|
||||
sink.field("pipeline_create_ns", value.pipeline_create_ns);
|
||||
sink.field("pipeline_create_count", value.pipeline_create_count);
|
||||
sink.field("vulkan_pending", value.vulkan.pending_submissions);
|
||||
sink.field("frames_in_flight", value.vulkan.frames_in_flight);
|
||||
sink.field("completion_in_flight", value.gpu_completion.in_flight);
|
||||
sink.field("completion_active", value.gpu_completion.active);
|
||||
sink.field("completion_capacity", value.gpu_completion.capacity);
|
||||
sink.field("completion_capacity_exhausted", value.gpu_completion.capacity_exhausted_count);
|
||||
sink.field("completion_errors", value.gpu_completion.error_count);
|
||||
}
|
||||
template <class Sink>
|
||||
void trace_serialize(Sink& sink, const Frame_Attention_Index& value) {
|
||||
sink.field("event", "frame_attention_index");
|
||||
trace_serialize(sink, value.frame.context);
|
||||
sink.field("frame", value.frame.frame);
|
||||
sink.field("generation", value.frame.generation);
|
||||
if (value.resource_activity) sink.field("resource_activity", true);
|
||||
if (value.upload_wait) sink.field("upload_wait", true);
|
||||
if (value.pipeline_build) sink.field("pipeline_build", true);
|
||||
if (value.frame_overlap) sink.field("frame_overlap", true);
|
||||
if (value.non_frame_submission) sink.field("non_frame_submission", true);
|
||||
if (value.completion_queue_gap) sink.field("completion_queue_gap", true);
|
||||
if (value.completion_saturated) sink.field("completion_saturated", true);
|
||||
}
|
||||
inline void trace_frame_attention(const Frame_Attention& value) noexcept {
|
||||
#ifdef TRACY_ENABLE
|
||||
if (!tracy_connected()) return;
|
||||
AETHERA_TRACE_MESSAGE_TAGS(value);
|
||||
trace_frame_policy_context(value.timing.frame);
|
||||
const auto index = make_frame_attention_index(value);
|
||||
if (has_frame_attention_index(index)) AETHERA_TRACE_MESSAGE_TAGS(index);
|
||||
#else
|
||||
static_cast<void>(value);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -15,16 +15,6 @@ struct Frame_Policy_State_View {
|
||||
const State& state;
|
||||
Frame_Policy_Slots slots{};
|
||||
};
|
||||
template <class State>
|
||||
inline void trace_frame_policy_state(std::uintptr_t policy, const State& state, Frame_Policy_Slots slots) noexcept {
|
||||
#ifdef TRACY_ENABLE
|
||||
AETHERA_TRACE_MESSAGE_TAGS(Frame_Policy_State_View<State>{policy, state, slots});
|
||||
#else
|
||||
static_cast<void>(policy);
|
||||
static_cast<void>(state);
|
||||
static_cast<void>(slots);
|
||||
#endif
|
||||
}
|
||||
template <class Sink, class State>
|
||||
void trace_serialize(Sink& sink, const Frame_Policy_State_View<State>& value) {
|
||||
sink.field("event", "frame_policy_state");
|
||||
@@ -55,4 +45,14 @@ void trace_serialize(Sink& sink, const Frame_Policy_State_View<State>& value) {
|
||||
sink.field("end_to_end_stddev_ns", value.state.end_to_end_time_ns.standard_deviation);
|
||||
}
|
||||
}
|
||||
template <class State>
|
||||
inline void trace_frame_policy_state(std::uintptr_t policy, const State& state, Frame_Policy_Slots slots) noexcept {
|
||||
#ifdef TRACY_ENABLE
|
||||
AETHERA_TRACE_MESSAGE_TAGS(Frame_Policy_State_View<State>{policy, state, slots});
|
||||
#else
|
||||
static_cast<void>(policy);
|
||||
static_cast<void>(state);
|
||||
static_cast<void>(slots);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,16 @@ struct GPU_Completion_Metrics {
|
||||
std::int32_t error{};
|
||||
std::int32_t backend_result{};
|
||||
};
|
||||
template <class Sink>
|
||||
void trace_serialize(Sink& sink, const GPU_Completion_Metrics& value) {
|
||||
sink.field("event", value.event);
|
||||
sink.field("in_flight", value.in_flight);
|
||||
sink.field("active", value.active);
|
||||
sink.field("capacity", value.capacity);
|
||||
if (value.wait_ns != 0) sink.field("wait_ns", value.wait_ns);
|
||||
if (value.error != 0) sink.field("error", value.error);
|
||||
if (value.backend_result != 0) sink.field("backend_result", value.backend_result);
|
||||
}
|
||||
inline void trace_gpu_completion_admitted(std::size_t in_flight) noexcept {
|
||||
#ifdef TRACY_ENABLE
|
||||
AETHERA_TRACE_PLOT_I("Aethera.GPUCompletion.InFlight", in_flight);
|
||||
@@ -71,14 +81,4 @@ inline void trace_gpu_completion_completed(std::size_t in_flight, std::size_t ac
|
||||
static_cast<void>(backend_result);
|
||||
#endif
|
||||
}
|
||||
template <class Sink>
|
||||
void trace_serialize(Sink& sink, const GPU_Completion_Metrics& value) {
|
||||
sink.field("event", value.event);
|
||||
sink.field("in_flight", value.in_flight);
|
||||
sink.field("active", value.active);
|
||||
sink.field("capacity", value.capacity);
|
||||
if (value.wait_ns != 0) sink.field("wait_ns", value.wait_ns);
|
||||
if (value.error != 0) sink.field("error", value.error);
|
||||
if (value.backend_result != 0) sink.field("backend_result", value.backend_result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,20 +32,6 @@ struct Frame_Resource_Metrics {
|
||||
[[nodiscard]] constexpr bool has_resource_activity(const Frame_Resource_Metrics& value) noexcept {
|
||||
return value.uploaded_bytes != 0 || value.readback_bytes != 0 || value.buffer_create_ns != 0 || value.texture_create_ns != 0 || value.shader_compile_ns != 0 || value.pipeline_create_ns != 0 || value.upload_ns != 0 || value.staging_allocate_ns != 0 || value.host_copy_ns != 0 || value.submit_queue_wait_ns != 0 || value.fence_wait_ns != 0 || value.transfer_ns != 0 || value.pipeline_create_count != 0;
|
||||
}
|
||||
inline void trace_frame_resources(const Frame_Resource_Metrics& value) noexcept {
|
||||
#ifdef TRACY_ENABLE
|
||||
AETHERA_TRACE_PLOT_I("Aethera.Resource.UploadedBytes", value.uploaded_bytes);
|
||||
AETHERA_TRACE_PLOT_I("Aethera.Resource.ReadbackBytes", value.readback_bytes);
|
||||
AETHERA_TRACE_PLOT_I("Aethera.Resource.UploadNs", value.upload_ns);
|
||||
AETHERA_TRACE_PLOT_I("Aethera.Resource.UploadQueueWaitNs", value.submit_queue_wait_ns);
|
||||
AETHERA_TRACE_PLOT_I("Aethera.Resource.UploadFenceWaitNs", value.fence_wait_ns);
|
||||
AETHERA_TRACE_PLOT_I("Aethera.Resource.ShaderCompileNs", value.shader_compile_ns);
|
||||
AETHERA_TRACE_PLOT_I("Aethera.Resource.PipelineCreateNs", value.pipeline_create_ns);
|
||||
if (has_resource_activity(value)) AETHERA_TRACE_MESSAGE_TAGS(value);
|
||||
#else
|
||||
static_cast<void>(value);
|
||||
#endif
|
||||
}
|
||||
template <class Sink>
|
||||
void trace_serialize(Sink& sink, const Frame_Resource_Metrics& value) {
|
||||
sink.field("event", "frame_resources");
|
||||
@@ -66,4 +52,18 @@ void trace_serialize(Sink& sink, const Frame_Resource_Metrics& value) {
|
||||
sink.field("transfer_ns", value.transfer_ns);
|
||||
sink.field("pipeline_create_count", value.pipeline_create_count);
|
||||
}
|
||||
inline void trace_frame_resources(const Frame_Resource_Metrics& value) noexcept {
|
||||
#ifdef TRACY_ENABLE
|
||||
AETHERA_TRACE_PLOT_I("Aethera.Resource.UploadedBytes", value.uploaded_bytes);
|
||||
AETHERA_TRACE_PLOT_I("Aethera.Resource.ReadbackBytes", value.readback_bytes);
|
||||
AETHERA_TRACE_PLOT_I("Aethera.Resource.UploadNs", value.upload_ns);
|
||||
AETHERA_TRACE_PLOT_I("Aethera.Resource.UploadQueueWaitNs", value.submit_queue_wait_ns);
|
||||
AETHERA_TRACE_PLOT_I("Aethera.Resource.UploadFenceWaitNs", value.fence_wait_ns);
|
||||
AETHERA_TRACE_PLOT_I("Aethera.Resource.ShaderCompileNs", value.shader_compile_ns);
|
||||
AETHERA_TRACE_PLOT_I("Aethera.Resource.PipelineCreateNs", value.pipeline_create_ns);
|
||||
if (has_resource_activity(value)) AETHERA_TRACE_MESSAGE_TAGS(value);
|
||||
#else
|
||||
static_cast<void>(value);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include <utility>
|
||||
namespace aethera::observation {
|
||||
namespace detail {
|
||||
void trace_serialize() = delete;
|
||||
template <class Sink, class T>
|
||||
concept Custom_Serializable = requires(Sink& sink, const T& value) { trace_serialize(sink, value); };
|
||||
template <class Sink, class T>
|
||||
|
||||
@@ -125,7 +125,7 @@ struct Tracy_Task_Zone {
|
||||
inline void trace_tracy_text_truncation(const char* channel, const Tracy_Text_Sink& truncated) noexcept {
|
||||
Tracy_Text_Sink sink;
|
||||
serialize(sink, Tracy_Text_Truncation{channel, truncated.required_size(), truncated.capacity()});
|
||||
TracyCMessage(sink.data(), sink.size())
|
||||
TracyCMessage(sink.data(), sink.size());
|
||||
}
|
||||
inline void set_tracy_thread_name(const char* name) noexcept {
|
||||
TracyCSetThreadName(name)
|
||||
@@ -161,7 +161,7 @@ void emit_tracy_message(const Tags& tags) {
|
||||
if (!trace_capture_active()) return;
|
||||
Tracy_Text_Sink sink;
|
||||
serialize(sink, tags);
|
||||
if (!sink.empty()) TracyCMessage(sink.data(), sink.size())
|
||||
if (!sink.empty()) TracyCMessage(sink.data(), sink.size());
|
||||
if (sink.truncated()) trace_tracy_text_truncation("message", sink);
|
||||
}
|
||||
#else
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
#pragma once
|
||||
#include "Tracy.hpp"
|
||||
#ifdef TRACY_ENABLE
|
||||
#include <tracy/TracyVulkan.hpp>
|
||||
#define AETHERA_TRACE_VULKAN_CONTEXT(...) TracyVkContext(__VA_ARGS__)
|
||||
#define AETHERA_TRACE_VULKAN_DESTROY(context) TracyVkDestroy(context)
|
||||
#define AETHERA_TRACE_VULKAN_CONTEXT_NAME(context, name, size) TracyVkContextName(context, name, size)
|
||||
#define AETHERA_TRACE_VULKAN_ZONE(context, command_buffer, name) TracyVkZone(context, command_buffer, name)
|
||||
#define AETHERA_TRACE_VULKAN_ZONE_TAGS(context, command_buffer, name, ...) AETHERA_TRACE_MESSAGE_TAGS(__VA_ARGS__); TracyVkZone(context, command_buffer, name)
|
||||
#define AETHERA_TRACE_VULKAN_COLLECT(context, command_buffer) TracyVkCollect(context, command_buffer)
|
||||
#define AETHERA_TRACE_VULKAN_COLLECT_HOST(context) TracyVkCollectHost(context)
|
||||
#else
|
||||
#define AETHERA_TRACE_VULKAN_CONTEXT(...) nullptr
|
||||
#define AETHERA_TRACE_VULKAN_DESTROY(context)
|
||||
#define AETHERA_TRACE_VULKAN_CONTEXT_NAME(context, name, size)
|
||||
#define AETHERA_TRACE_VULKAN_ZONE(context, command_buffer, name)
|
||||
#define AETHERA_TRACE_VULKAN_ZONE_TAGS(context, command_buffer, name, ...)
|
||||
#define AETHERA_TRACE_VULKAN_COLLECT(context, command_buffer)
|
||||
#define AETHERA_TRACE_VULKAN_COLLECT_HOST(context)
|
||||
#endif
|
||||
@@ -55,38 +55,6 @@ decltype(auto) trace_vulkan_submit(Submit&& submit) {
|
||||
AETHERA_TRACE_ZONE("Vulkan.Submit");
|
||||
return std::invoke(std::forward<Submit>(submit));
|
||||
}
|
||||
inline void trace_vulkan_submitted(const Vulkan_Submission_Context& submission) noexcept {
|
||||
#ifdef TRACY_ENABLE
|
||||
AETHERA_TRACE_MESSAGE_TAGS(submission);
|
||||
#else
|
||||
static_cast<void>(submission);
|
||||
#endif
|
||||
}
|
||||
inline void trace_vulkan_completed(const Vulkan_Submission_Context& submission, std::uint64_t latency_ns) noexcept {
|
||||
#ifdef TRACY_ENABLE
|
||||
const auto value = make_vulkan_completion_context(submission, latency_ns);
|
||||
AETHERA_TRACE_MESSAGE_TAGS(value);
|
||||
if (submission.frame_bound) AETHERA_TRACE_PLOT_I("Aethera.Vulkan.FrameSubmitToCompleteNs", latency_ns);
|
||||
else AETHERA_TRACE_PLOT_I("Aethera.Vulkan.ImmediateSubmitToCompleteNs", latency_ns);
|
||||
#else
|
||||
static_cast<void>(submission);
|
||||
static_cast<void>(latency_ns);
|
||||
#endif
|
||||
}
|
||||
inline void trace_vulkan_gpu_timing(const Vulkan_Submission_Context& submission, std::uint64_t render_ns, std::uint64_t transition_ns, std::uint64_t copy_ns, std::uint64_t total_ns) noexcept {
|
||||
#ifdef TRACY_ENABLE
|
||||
const auto value = make_vulkan_gpu_timing_context(submission, render_ns, transition_ns, copy_ns, total_ns);
|
||||
AETHERA_TRACE_MESSAGE_TAGS(value);
|
||||
AETHERA_TRACE_PLOT_I("Aethera.Vulkan.GPU.RenderNs", render_ns);
|
||||
AETHERA_TRACE_PLOT_I("Aethera.Vulkan.GPU.TotalNs", total_ns);
|
||||
#else
|
||||
static_cast<void>(submission);
|
||||
static_cast<void>(render_ns);
|
||||
static_cast<void>(transition_ns);
|
||||
static_cast<void>(copy_ns);
|
||||
static_cast<void>(total_ns);
|
||||
#endif
|
||||
}
|
||||
template <class Sink>
|
||||
void trace_serialize(Sink& sink, const Vulkan_Submission_Context& value) {
|
||||
sink.field("event", "vulkan_submit");
|
||||
@@ -122,4 +90,36 @@ void trace_serialize(Sink& sink, const Vulkan_Completion_Context& value) {
|
||||
if (value.queue != 0) sink.field("queue", value.queue);
|
||||
sink.field("latency_ns", value.latency_ns);
|
||||
}
|
||||
inline void trace_vulkan_submitted(const Vulkan_Submission_Context& submission) noexcept {
|
||||
#ifdef TRACY_ENABLE
|
||||
AETHERA_TRACE_MESSAGE_TAGS(submission);
|
||||
#else
|
||||
static_cast<void>(submission);
|
||||
#endif
|
||||
}
|
||||
inline void trace_vulkan_completed(const Vulkan_Submission_Context& submission, std::uint64_t latency_ns) noexcept {
|
||||
#ifdef TRACY_ENABLE
|
||||
const auto value = make_vulkan_completion_context(submission, latency_ns);
|
||||
AETHERA_TRACE_MESSAGE_TAGS(value);
|
||||
if (submission.frame_bound) AETHERA_TRACE_PLOT_I("Aethera.Vulkan.FrameSubmitToCompleteNs", latency_ns);
|
||||
else AETHERA_TRACE_PLOT_I("Aethera.Vulkan.ImmediateSubmitToCompleteNs", latency_ns);
|
||||
#else
|
||||
static_cast<void>(submission);
|
||||
static_cast<void>(latency_ns);
|
||||
#endif
|
||||
}
|
||||
inline void trace_vulkan_gpu_timing(const Vulkan_Submission_Context& submission, std::uint64_t render_ns, std::uint64_t transition_ns, std::uint64_t copy_ns, std::uint64_t total_ns) noexcept {
|
||||
#ifdef TRACY_ENABLE
|
||||
const auto value = make_vulkan_gpu_timing_context(submission, render_ns, transition_ns, copy_ns, total_ns);
|
||||
AETHERA_TRACE_MESSAGE_TAGS(value);
|
||||
AETHERA_TRACE_PLOT_I("Aethera.Vulkan.GPU.RenderNs", render_ns);
|
||||
AETHERA_TRACE_PLOT_I("Aethera.Vulkan.GPU.TotalNs", total_ns);
|
||||
#else
|
||||
static_cast<void>(submission);
|
||||
static_cast<void>(render_ns);
|
||||
static_cast<void>(transition_ns);
|
||||
static_cast<void>(copy_ns);
|
||||
static_cast<void>(total_ns);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "Throttled_Latest_Only.hpp"
|
||||
#include "Error_handling_specification/Failure_Policy.hpp"
|
||||
#include "Trace_Adapter.hpp"
|
||||
#include <algorithm>
|
||||
#include <concepts>
|
||||
#include <exception>
|
||||
@@ -385,6 +386,9 @@ void Throttled_Latest_only::Private::finish_stop_if_ready() {
|
||||
}
|
||||
}
|
||||
void Throttled_Latest_only::Private::publish_state() {
|
||||
#ifdef TRACY_ENABLE
|
||||
frame_policy_trace::published(this, *concurrent<State_Tag>().internal.use(), frames);
|
||||
#endif
|
||||
concurrent<State_Tag>().internal.advance();
|
||||
}
|
||||
bool Throttled_Latest_only::Private::destructible() const noexcept {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "Task_Runtime.hpp"
|
||||
#include "detail/Taskflow_Execution.ipp"
|
||||
#include "observation/Tracy.hpp"
|
||||
#include "Trace_Adapter.hpp"
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <expected>
|
||||
@@ -71,28 +71,15 @@ 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::array<task_flow_trace::Task_Zone, Tracy_Zone_Depth> zones{};
|
||||
std::size_t depth{};
|
||||
std::size_t ignored_depth{};
|
||||
bool named{};
|
||||
};
|
||||
void name_worker(Tracy_Worker_State& state, std::size_t worker_id) noexcept {
|
||||
if (state.named) return;
|
||||
constexpr std::string_view Prefix{"Aethera.Taskflow."};
|
||||
std::array<char, 64> name{};
|
||||
std::memcpy(name.data(), Prefix.data(), Prefix.size());
|
||||
const auto [end, error] = std::to_chars(name.data() + Prefix.size(), name.data() + name.size() - 1, worker_id);
|
||||
if (error != std::errc{}) return;
|
||||
*end = '\0';
|
||||
observation::set_tracy_thread_name(name.data());
|
||||
task_flow_trace::name_worker(worker_id);
|
||||
state.named = true;
|
||||
}
|
||||
void trace_entry(const tf::Worker& worker, const tf::TaskView& task, std::uint64_t native_id, const detail::Taskflow_Observation_Execution* execution) noexcept {
|
||||
@@ -102,7 +89,7 @@ struct Task_Observer final : tf::ObserverInterface {
|
||||
++state.ignored_depth;
|
||||
return;
|
||||
}
|
||||
if (!observation::tracy_connected()) {
|
||||
if (!task_flow_trace::capture_active()) {
|
||||
if (state.depth != 0) state.ignored_depth = 1;
|
||||
return;
|
||||
}
|
||||
@@ -112,12 +99,12 @@ struct Task_Observer final : tf::ObserverInterface {
|
||||
}
|
||||
const std::string_view name{task.name()};
|
||||
auto& zone = state.zones[state.depth++];
|
||||
zone = observation::begin_tracy_task_zone(name, native_id);
|
||||
zone = task_flow_trace::begin_task(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});
|
||||
task_flow_trace::attach_frame(zone, *context);
|
||||
}
|
||||
void trace_exit(const tf::Worker& worker) noexcept {
|
||||
auto& state = tracy_worker_states[worker.id()];
|
||||
@@ -126,7 +113,7 @@ struct Task_Observer final : tf::ObserverInterface {
|
||||
return;
|
||||
}
|
||||
if (state.depth == 0) return;
|
||||
observation::end_tracy_task_zone(state.zones[--state.depth]);
|
||||
task_flow_trace::end_task(state.zones[--state.depth]);
|
||||
}
|
||||
std::vector<Tracy_Worker_State> tracy_worker_states;
|
||||
#endif
|
||||
@@ -223,7 +210,7 @@ public:
|
||||
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());
|
||||
if (trace_context && task_flow_trace::capture_active()) observation_execution->set_trace_context(*trace_context, graph_execution->native_taskflow().name());
|
||||
#else
|
||||
(void)trace_context;
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user