Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
gpu_diagnostics.hpp
Go to the documentation of this file.
1// gpu_diagnostics.hpp — one sink for GPU-layer diagnostics.
2//
3// Dawn hands errors to a callback; Skia hands log records to an SkLogHandler.
4// Both funnel through emit_gpu_diagnostic(), which publishes a `gpu`-category
5// Perfetto instant event so a device error lands on the same timeline as the
6// frame that provoked it. This ADDS a trace signal — every call site keeps its
7// runtime::log_* call, because a log is what a user reads and a trace is what a
8// timeline query joins against.
9//
10// RT-safety: the Dawn uncaptured-error callback fires on the render thread.
11// emit_gpu_diagnostic() allocates nothing: the message is copied into a bounded
12// stack buffer and attached to a compile-time event name as a debug annotation,
13// so the event name stays interned and nothing reaches the heap. It is still a
14// Perfetto TRACE_EVENT and therefore must never be placed on the audio thread's
15// live process() path (see trace.hpp).
16//
17// Observability: a bridge that quietly emits nothing forever is indistinguishable
18// from a quiet GPU. gpu_diagnostics_stats() and skia_log_bridge_state() exist so
19// "nothing was wired up" is always distinguishable from "nothing went wrong".
20#pragma once
21
22#if defined(PULP_GPU_RUNTIME)
23// This build's device layer is gpu-runtime's (tools/cmake/PulpGpuRuntime.cmake):
24// these are its types and functions under their Pulp names, so a Pulp object
25// and a gpu-runtime object are one and the same.
26#include <gpu_runtime/gpu_diagnostics.hpp>
27
28namespace pulp::render {
29using gpu_runtime::emit_gpu_diagnostic;
30using gpu_runtime::gpu_diagnostics_stats;
31using gpu_runtime::GpuDiagnosticSeverity;
32using gpu_runtime::GpuDiagnosticsStats;
33using gpu_runtime::install_skia_log_bridge;
34using gpu_runtime::install_skia_log_bridge_if_enabled;
35using gpu_runtime::kGpuDiagnosticMessageLimit;
36using gpu_runtime::kSkiaLogTextLimit;
37using gpu_runtime::LogTextBudget;
38using gpu_runtime::skia_log_bridge_available;
39using gpu_runtime::skia_log_bridge_enabled;
40using gpu_runtime::skia_log_bridge_state;
41using gpu_runtime::SkiaLogBridgeState;
42using gpu_runtime::SkiaLogBridgeStatus;
43using gpu_runtime::to_string;
44} // namespace pulp::render
45#else // !PULP_GPU_RUNTIME
46
47#include <atomic>
48#include <cstddef>
49#include <cstdint>
50#include <string_view>
51
52namespace pulp::render {
53
61
63const char* to_string(GpuDiagnosticSeverity severity) noexcept;
64
74void emit_gpu_diagnostic(GpuDiagnosticSeverity severity, const char* source,
75 std::string_view message) noexcept;
76
79inline constexpr std::size_t kGpuDiagnosticMessageLimit = 512;
80
85 std::uint64_t emitted = 0;
87 std::uint64_t traced = 0;
89 std::uint64_t truncated = 0;
90};
91
93
111
113const char* to_string(SkiaLogBridgeStatus status) noexcept;
114
127
131inline constexpr std::uint64_t kSkiaLogTextLimit = 50;
132
136 public:
137 explicit constexpr LogTextBudget(std::uint64_t limit) noexcept : limit_(limit) {}
138
139 bool admit() noexcept {
140 const auto index = seen_.fetch_add(1, std::memory_order_relaxed);
141 return index < limit_;
142 }
143
144 std::uint64_t admitted() const noexcept {
145 const auto seen = seen_.load(std::memory_order_relaxed);
146 return seen < limit_ ? seen : limit_;
147 }
148
149 std::uint64_t suppressed() const noexcept {
150 const auto seen = seen_.load(std::memory_order_relaxed);
151 return seen > limit_ ? seen - limit_ : 0;
152 }
153
154 private:
155 std::uint64_t limit_;
156 std::atomic<std::uint64_t> seen_{0};
157};
158
160
165
171
176
182
183} // namespace pulp::render
184
185#endif // PULP_GPU_RUNTIME
bool admit() noexcept
Definition gpu_diagnostics.hpp:139
std::uint64_t suppressed() const noexcept
Definition gpu_diagnostics.hpp:149
std::uint64_t admitted() const noexcept
Definition gpu_diagnostics.hpp:144
constexpr LogTextBudget(std::uint64_t limit) noexcept
Definition gpu_diagnostics.hpp:137
Definition gpu_fwd.hpp:31
const char * to_string(GpuDiagnosticSeverity severity) noexcept
Stable lowercase label for a severity, suitable as a trace annotation value.
bool skia_log_bridge_available() noexcept
True when this build contains the Skia log-handler subclass at all.
bool skia_log_bridge_enabled() noexcept
True when the opt-in is satisfied: a PULP_TRACING=ON build, or PULP_GPU_LOG_BRIDGE set to 1/true/yes/...
SkiaLogBridgeStatus install_skia_log_bridge_if_enabled() noexcept
Install the bridge, honouring the opt-in.
@ index
Definition gpu_pass.hpp:140
constexpr std::uint64_t kSkiaLogTextLimit
How many Skia log records the bridge copies into the text log before it stops, so a chatty Skia canno...
Definition gpu_diagnostics.hpp:131
GpuDiagnosticSeverity
Severity of one GPU diagnostic record.
Definition gpu_diagnostics.hpp:55
@ warning
Definition gpu_diagnostics.hpp:57
@ info
Definition gpu_diagnostics.hpp:56
@ error
Definition gpu_diagnostics.hpp:58
@ fatal
Definition gpu_diagnostics.hpp:59
constexpr std::size_t kGpuDiagnosticMessageLimit
Longest message text carried into a trace annotation.
Definition gpu_diagnostics.hpp:79
void emit_gpu_diagnostic(GpuDiagnosticSeverity severity, const char *source, std::string_view message) noexcept
Publish one GPU diagnostic as a gpu-category instant event.
SkiaLogBridgeStatus
Outcome of trying to route Skia's process-global log handler into the sink.
Definition gpu_diagnostics.hpp:99
@ declined_handler_present
Somebody else installed a handler first; theirs is left untouched.
Definition gpu_diagnostics.hpp:105
@ installed
This process owns Skia's log handler and records are flowing.
Definition gpu_diagnostics.hpp:103
@ unavailable_no_skia
This build has no Skia, so there is no handler to install.
Definition gpu_diagnostics.hpp:109
@ declined_not_enabled
The opt-in was absent, so no install was attempted.
Definition gpu_diagnostics.hpp:107
@ not_attempted
install_skia_log_bridge*() has not run yet.
Definition gpu_diagnostics.hpp:101
GpuDiagnosticsStats gpu_diagnostics_stats() noexcept
SkiaLogBridgeState skia_log_bridge_state() noexcept
SkiaLogBridgeStatus install_skia_log_bridge() noexcept
Install the bridge regardless of the opt-in — calling this IS the explicit opt-in.
Counters that separate "the sink was never called" from "the sink was calledbut this build compiles t...
Definition gpu_diagnostics.hpp:83
std::uint64_t truncated
Records whose message text was truncated to the limit above.
Definition gpu_diagnostics.hpp:89
std::uint64_t emitted
Records handed to emit_gpu_diagnostic() in this process.
Definition gpu_diagnostics.hpp:85
std::uint64_t traced
Records forwarded to Perfetto. Always 0 in a PULP_TRACING=OFF build.
Definition gpu_diagnostics.hpp:87
Definition gpu_diagnostics.hpp:115
std::uint64_t text_logged
Forwarded records also written to the text log (runtime::log_*).
Definition gpu_diagnostics.hpp:122
SkiaLogBridgeStatus status
Definition gpu_diagnostics.hpp:116
std::uint64_t records_forwarded
Skia log records forwarded into the sink.
Definition gpu_diagnostics.hpp:120
std::uint64_t text_suppressed
Forwarded records NOT written to the text log because the budget below ran out.
Definition gpu_diagnostics.hpp:125