QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
GstHwPathTelemetry.cc
Go to the documentation of this file.
2
3#include <array>
4#include <atomic>
5
7
8namespace {
9
10constexpr size_t kPathCount = size_t(HwVideoBufferPath::Vulkan) + 1;
11
12struct PathCounters
13{
14 std::atomic<quint64> mapFailures{0};
15 std::atomic<quint64> textureReuseHits{0};
16 std::atomic<quint64> syncCpuWaits{0};
17 std::atomic<quint64> syncGpuWaits{0};
18 std::atomic<quint64> imageCacheHits{0};
19 std::atomic<quint64> imageCacheMisses{0};
20 std::atomic<quint64> delivered{0};
21 std::atomic<quint64> mapDurationUsEwma{0};
22 std::atomic<quint64> fenceTimeouts{0};
23 std::atomic<quint64> mmapBarrierHits{0};
24 std::atomic<quint64> explicitFenceWaits{0};
25 std::atomic<quint64> streamDemotions{0};
26};
27
28std::array<PathCounters, kPathCount> s_counters{};
29
30constexpr size_t kReasonCount = size_t(HwFallbackReason::_Count);
31std::array<std::array<std::atomic<quint64>, kReasonCount>, kPathCount> s_fallbackReasons{};
32
33inline PathCounters& slot(HwVideoBufferPath path) noexcept
34{
35 return s_counters[size_t(path)];
36}
37
38} // namespace
39
41{
42 slot(path).mapFailures.fetch_add(1, std::memory_order_relaxed);
43}
44
46{
47 return slot(path).mapFailures.exchange(0, std::memory_order_relaxed);
48}
49
51{
52 return slot(path).mapFailures.load(std::memory_order_relaxed);
53}
54
56{
57 slot(path).textureReuseHits.fetch_add(1, std::memory_order_relaxed);
58}
59
61{
62 return slot(path).textureReuseHits.exchange(0, std::memory_order_relaxed);
63}
64
65void recordSyncWait(HwVideoBufferPath path, bool gpuSide) noexcept
66{
67 auto& target = gpuSide ? slot(path).syncGpuWaits : slot(path).syncCpuWaits;
68 target.fetch_add(1, std::memory_order_relaxed);
69}
70
71quint64 takeSyncWaitCounts(HwVideoBufferPath path, quint64& gpuWaits) noexcept
72{
73 gpuWaits = slot(path).syncGpuWaits.exchange(0, std::memory_order_relaxed);
74 return slot(path).syncCpuWaits.exchange(0, std::memory_order_relaxed);
75}
76
78{
79 slot(path).imageCacheHits.fetch_add(1, std::memory_order_relaxed);
80}
81
83{
84 slot(path).imageCacheMisses.fetch_add(1, std::memory_order_relaxed);
85}
86
88{
89 return slot(path).imageCacheHits.exchange(0, std::memory_order_relaxed);
90}
91
93{
94 return slot(path).imageCacheMisses.exchange(0, std::memory_order_relaxed);
95}
96
97#if defined(QGC_HAS_ANY_GPU_PATH)
98QVideoFrameTexturesUPtr fail(HwVideoBufferPath path) noexcept
99{
100 recordMapFailure(path);
101 return {};
102}
103#endif
104
106{
107 slot(path).delivered.fetch_add(1, std::memory_order_relaxed);
108}
109
111{
112 return slot(path).delivered.load(std::memory_order_relaxed);
113}
114
116{
117 return slot(path).delivered.exchange(0, std::memory_order_relaxed);
118}
119
120void recordMapDuration(HwVideoBufferPath path, qint64 nsecs) noexcept
121{
122 if (nsecs < 0) {
123 return;
124 }
125 // EWMA in microseconds (alpha = 1/8); seed on the first sample so the average tracks immediately.
126 const quint64 sampleUs = static_cast<quint64>(nsecs) / 1000;
127 auto& ewma = slot(path).mapDurationUsEwma;
128 quint64 prev = ewma.load(std::memory_order_relaxed);
129 quint64 next;
130 do {
131 next = (prev == 0) ? sampleUs : prev - (prev >> 3) + (sampleUs >> 3);
132 } while (!ewma.compare_exchange_weak(prev, next, std::memory_order_relaxed));
133}
134
136{
137 return slot(path).mapDurationUsEwma.load(std::memory_order_relaxed);
138}
139
141{
142 slot(path).fenceTimeouts.fetch_add(1, std::memory_order_relaxed);
143}
144
146{
147 return slot(path).fenceTimeouts.load(std::memory_order_relaxed);
148}
149
151{
152 return slot(path).fenceTimeouts.exchange(0, std::memory_order_relaxed);
153}
154
156{
157 slot(path).mmapBarrierHits.fetch_add(1, std::memory_order_relaxed);
158}
159
161{
162 return slot(path).mmapBarrierHits.load(std::memory_order_relaxed);
163}
164
166{
167 return slot(path).mmapBarrierHits.exchange(0, std::memory_order_relaxed);
168}
169
171{
172 slot(path).explicitFenceWaits.fetch_add(1, std::memory_order_relaxed);
173}
174
176{
177 return slot(path).explicitFenceWaits.exchange(0, std::memory_order_relaxed);
178}
179
180void recordFallbackReason(HwVideoBufferPath attemptedPath, HwFallbackReason reason) noexcept
181{
182 s_fallbackReasons[size_t(attemptedPath)][size_t(reason)].fetch_add(1, std::memory_order_relaxed);
183}
184
185quint64 peekFallbackReason(HwVideoBufferPath attemptedPath, HwFallbackReason reason) noexcept
186{
187 return s_fallbackReasons[size_t(attemptedPath)][size_t(reason)].load(std::memory_order_relaxed);
188}
189
190quint64 takeFallbackReason(HwVideoBufferPath attemptedPath, HwFallbackReason reason) noexcept
191{
192 return s_fallbackReasons[size_t(attemptedPath)][size_t(reason)].exchange(0, std::memory_order_relaxed);
193}
194
196{
197 slot(negotiated).streamDemotions.fetch_add(1, std::memory_order_relaxed);
198}
199
200quint64 takeStreamDemotions(HwVideoBufferPath negotiated) noexcept
201{
202 return slot(negotiated).streamDemotions.exchange(0, std::memory_order_relaxed);
203}
204
205} // namespace GstHwPathTelemetry
std::atomic< quint64 > explicitFenceWaits
std::atomic< quint64 > imageCacheHits
std::atomic< quint64 > delivered
std::atomic< quint64 > mapDurationUsEwma
std::atomic< quint64 > fenceTimeouts
std::atomic< quint64 > mmapBarrierHits
std::atomic< quint64 > mapFailures
std::atomic< quint64 > syncGpuWaits
std::atomic< quint64 > streamDemotions
std::atomic< quint64 > syncCpuWaits
std::atomic< quint64 > textureReuseHits
std::atomic< quint64 > imageCacheMisses
HwVideoBufferPath
Identifies which GPU path was chosen; used by the adapter to increment the right counter.
void recordSyncWait(HwVideoBufferPath path, bool gpuSide) noexcept
GL fence sync wait; split CPU-blocking vs GPU-side.
quint64 peekMapFailureCount(HwVideoBufferPath path) noexcept
quint64 takeExplicitFenceWaits(HwVideoBufferPath path) noexcept
quint64 peekFenceTimeouts(HwVideoBufferPath path) noexcept
void recordFallbackReason(HwVideoBufferPath attemptedPath, HwFallbackReason reason) noexcept
Per-(path,reason) fallback accounting; lets a bug report show why a path demoted to CPU.
quint64 takeTextureReuseHits(HwVideoBufferPath path) noexcept
void recordMapDuration(HwVideoBufferPath path, qint64 nsecs) noexcept
Per-path mapTextures() wall-time, fed into an EWMA; peek returns the smoothed value in microseconds.
quint64 peekFallbackReason(HwVideoBufferPath attemptedPath, HwFallbackReason reason) noexcept
quint64 takeImageCacheHits(HwVideoBufferPath path) noexcept
quint64 peekMmapBarrierHits(HwVideoBufferPath path) noexcept
void recordImageCacheHit(HwVideoBufferPath path) noexcept
Native image/texture cache hit/miss accounting.
quint64 takeSyncWaitCounts(HwVideoBufferPath path, quint64 &gpuWaits) noexcept
Reads-and-resets CPU waits; writes GPU waits into gpuWaits.
quint64 peekMapDurationUsEwma(HwVideoBufferPath path) noexcept
quint64 takeFenceTimeouts(HwVideoBufferPath path) noexcept
void recordStreamDemotion(HwVideoBufferPath negotiated) noexcept
One-shot-per-epoch event: a stream that negotiated a HW path demoted to CPU. Distinct from per-frame ...
void recordImageCacheMiss(HwVideoBufferPath path) noexcept
void recordExplicitFenceWait(HwVideoBufferPath path) noexcept
DMABuf imported the producer's dma-buf/native fence and did a GPU-side wait (skipped the mmap barrier...
quint64 takeStreamDemotions(HwVideoBufferPath negotiated) noexcept
void recordFenceTimeout(HwVideoBufferPath path) noexcept
DMABuf EGL fence wait timed out (GPU stall) and fell through to the mmap barrier.
quint64 peekDeliveredCount(HwVideoBufferPath path) noexcept
quint64 takeMapFailureCount(HwVideoBufferPath path) noexcept
void recordDelivered(HwVideoBufferPath path) noexcept
Frames successfully delivered via this path.
quint64 takeImageCacheMisses(HwVideoBufferPath path) noexcept
void recordTextureReuse(HwVideoBufferPath path) noexcept
Prior frame's QRhiTexture wrappers reused (decoder pool returned same native handle).
void recordMmapBarrierHit(HwVideoBufferPath path) noexcept
DMABuf mmap CPU-side completion barrier taken (no usable fence ext).
void recordMapFailure(HwVideoBufferPath path) noexcept
mapTextures() returned an invalid bundle (GPU import failed).
quint64 takeDeliveredCount(HwVideoBufferPath path) noexcept
quint64 takeFallbackReason(HwVideoBufferPath attemptedPath, HwFallbackReason reason) noexcept
HwFallbackReason
Specific cause a HW path was rejected for a sample; surfaced as a per-(path,reason) breakdown.
quint64 takeMmapBarrierHits(HwVideoBufferPath path) noexcept