1 //
2 // Copyright 2019 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // OverlayWidgets.cpp:
7 // Implements functions that interpret widget data. Data formats and limits correspond to the
8 // Vulkan implementation (as the only implementation). They are generic enough so other backends
9 // could respect them too, if they implement the overlay.
10 //
11
12 #include "libANGLE/Overlay.h"
13 #include "libANGLE/Overlay_font_autogen.h"
14
15 #include <functional>
16
17 namespace gl
18 {
19 namespace
20 {
21 // Internally, every widget is either Text or Graph.
22 enum class WidgetInternalType
23 {
24 Text,
25 Graph,
26
27 InvalidEnum,
28 EnumCount = InvalidEnum,
29 };
30
31 // A map that says how the API-facing widget types map to internal types.
32 constexpr angle::PackedEnumMap<WidgetType, WidgetInternalType> kWidgetTypeToInternalMap = {
33 {WidgetType::Count, WidgetInternalType::Text},
34 {WidgetType::Text, WidgetInternalType::Text},
35 {WidgetType::PerSecond, WidgetInternalType::Text},
36 {WidgetType::RunningGraph, WidgetInternalType::Graph},
37 {WidgetType::RunningHistogram, WidgetInternalType::Graph},
38 };
39
40 // Structures and limits matching uniform buffers in vulkan/shaders/src/OverlayDraw.comp. The size
41 // of text and graph widgets is chosen such that they could fit in uniform buffers with minimum
42 // required Vulkan size.
43 constexpr size_t kMaxRenderableTextWidgets = 32;
44 constexpr size_t kMaxRenderableGraphWidgets = 32;
45 constexpr size_t kMaxTextLength = 256;
46 constexpr size_t kMaxGraphDataSize = 256;
47
48 constexpr angle::PackedEnumMap<WidgetInternalType, size_t> kWidgetInternalTypeMaxWidgets = {
49 {WidgetInternalType::Text, kMaxRenderableTextWidgets},
50 {WidgetInternalType::Graph, kMaxRenderableGraphWidgets},
51 };
52
53 ANGLE_ENABLE_STRUCT_PADDING_WARNINGS
54
55 // Structure matching buffer in vulkan/shaders/src/OverlayCull.comp.
56 struct WidgetCoordinates
57 {
58 uint32_t coordinates[kMaxRenderableTextWidgets + kMaxRenderableGraphWidgets][4];
59 };
60
61 // Structures matching buffers in vulkan/shaders/src/OverlayDraw.comp.
62 struct TextWidgetData
63 {
64 uint32_t coordinates[4];
65 float color[4];
66 uint32_t fontSize[3];
67 uint32_t padding;
68 uint8_t text[kMaxTextLength];
69 };
70
71 struct GraphWidgetData
72 {
73 uint32_t coordinates[4];
74 float color[4];
75 uint32_t valueWidth;
76 uint32_t padding[3];
77 uint32_t values[kMaxGraphDataSize];
78 };
79
80 struct TextWidgets
81 {
82 TextWidgetData widgets[kMaxRenderableTextWidgets];
83 };
84
85 struct GraphWidgets
86 {
87 GraphWidgetData widgets[kMaxRenderableGraphWidgets];
88 };
89
90 ANGLE_DISABLE_STRUCT_PADDING_WARNINGS
91
GetWidgetCoord(int32_t src,uint32_t extent)92 uint32_t GetWidgetCoord(int32_t src, uint32_t extent)
93 {
94 int32_t dst = src < 0 ? extent + src : src;
95
96 return std::min<uint32_t>(std::max(dst, 0), extent - 1);
97 }
98
GetWidgetCoordinates(const int32_t srcCoords[4],const gl::Extents & imageExtent,uint32_t dstCoordsOut[4])99 void GetWidgetCoordinates(const int32_t srcCoords[4],
100 const gl::Extents &imageExtent,
101 uint32_t dstCoordsOut[4])
102 {
103 dstCoordsOut[0] = GetWidgetCoord(srcCoords[0], imageExtent.width);
104 dstCoordsOut[1] = GetWidgetCoord(srcCoords[1], imageExtent.height);
105 dstCoordsOut[2] = GetWidgetCoord(srcCoords[2], imageExtent.width);
106 dstCoordsOut[3] = GetWidgetCoord(srcCoords[3], imageExtent.height);
107 }
108
GetWidgetColor(const float srcColor[4],float dstColor[4])109 void GetWidgetColor(const float srcColor[4], float dstColor[4])
110 {
111 memcpy(dstColor, srcColor, 4 * sizeof(dstColor[0]));
112 }
113
GetTextFontSize(int srcFontSize,uint32_t dstFontSize[3])114 void GetTextFontSize(int srcFontSize, uint32_t dstFontSize[3])
115 {
116 // .xy contains the font glyph width/height
117 dstFontSize[0] = overlay::kFontGlyphWidth >> srcFontSize;
118 dstFontSize[1] = overlay::kFontGlyphHeight >> srcFontSize;
119 // .z contains the mip
120 dstFontSize[2] = srcFontSize;
121 }
122
GetGraphValueWidth(const int32_t srcCoords[4],size_t valueCount,uint32_t * dstValueWidth)123 void GetGraphValueWidth(const int32_t srcCoords[4], size_t valueCount, uint32_t *dstValueWidth)
124 {
125 const int32_t graphWidth = std::abs(srcCoords[2] - srcCoords[0]);
126
127 // If valueCount doesn't divide graphWidth, the graph bars won't fit well in its frame.
128 // Fix initOverlayWidgets() in that case.
129 ASSERT(graphWidth % valueCount == 0);
130
131 *dstValueWidth = graphWidth / valueCount;
132 }
133
GetTextString(const std::string & src,uint8_t textOut[kMaxTextLength])134 void GetTextString(const std::string &src, uint8_t textOut[kMaxTextLength])
135 {
136 for (size_t i = 0; i < src.length() && i < kMaxTextLength; ++i)
137 {
138 // The font image has 95 ASCII characters starting from ' '.
139 textOut[i] = src[i] - ' ';
140 }
141 }
142
GetGraphValues(const std::vector<uint64_t> srcValues,size_t startIndex,float scale,uint32_t valuesOut[kMaxGraphDataSize])143 void GetGraphValues(const std::vector<uint64_t> srcValues,
144 size_t startIndex,
145 float scale,
146 uint32_t valuesOut[kMaxGraphDataSize])
147 {
148 ASSERT(srcValues.size() <= kMaxGraphDataSize);
149
150 for (size_t i = 0; i < srcValues.size(); ++i)
151 {
152 size_t index = (startIndex + i) % srcValues.size();
153 valuesOut[i] = static_cast<uint32_t>(srcValues[index] * scale);
154 }
155 }
156
CreateHistogram(const std::vector<uint64_t> values)157 std::vector<uint64_t> CreateHistogram(const std::vector<uint64_t> values)
158 {
159 std::vector<uint64_t> histogram(values.size(), 0);
160
161 for (uint64_t rank : values)
162 {
163 ++histogram[static_cast<size_t>(rank)];
164 }
165
166 return histogram;
167 }
168
169 using OverlayWidgetCounts = angle::PackedEnumMap<WidgetInternalType, uint32_t>;
170 using AppendWidgetDataFunc = void (*)(const overlay::Widget *widget,
171 const gl::Extents &imageExtent,
172 TextWidgetData *textWidget,
173 GraphWidgetData *graphWidget,
174 OverlayWidgetCounts *widgetCounts);
175 } // namespace
176
177 namespace overlay_impl
178 {
179 #define ANGLE_DECLARE_APPEND_WIDGET_PROC(WIDGET_ID) \
180 static void Append##WIDGET_ID(const overlay::Widget *widget, const gl::Extents &imageExtent, \
181 TextWidgetData *textWidget, GraphWidgetData *graphWidget, \
182 OverlayWidgetCounts *widgetCounts);
183
184 // This class interprets the generic data collected in every element into a human-understandable
185 // widget. This often means generating text specific to this item and scaling graph data to
186 // something sensible.
187 class AppendWidgetDataHelper
188 {
189 public:
190 ANGLE_WIDGET_ID_X(ANGLE_DECLARE_APPEND_WIDGET_PROC)
191
192 private:
193 static std::ostream &OutputPerSecond(std::ostream &out, const overlay::PerSecond *perSecond);
194
195 static std::ostream &OutputText(std::ostream &out, const overlay::Text *text);
196
197 static std::ostream &OutputCount(std::ostream &out, const overlay::Count *count);
198
199 static void AppendTextCommon(const overlay::Widget *widget,
200 const gl::Extents &imageExtent,
201 const std::string &text,
202 TextWidgetData *textWidget,
203 OverlayWidgetCounts *widgetCounts);
204
205 using FormatGraphTitleFunc = std::function<std::string(uint64_t curValue, uint64_t maxValue)>;
206 static void AppendRunningGraphCommon(const overlay::Widget *widget,
207 const gl::Extents &imageExtent,
208 TextWidgetData *textWidget,
209 GraphWidgetData *graphWidget,
210 OverlayWidgetCounts *widgetCounts,
211 FormatGraphTitleFunc formatFunc);
212
213 using FormatHistogramTitleFunc =
214 std::function<std::string(size_t peakRange, size_t maxValueRange, size_t numRanges)>;
215 static void AppendRunningHistogramCommon(const overlay::Widget *widget,
216 const gl::Extents &imageExtent,
217 TextWidgetData *textWidget,
218 GraphWidgetData *graphWidget,
219 OverlayWidgetCounts *widgetCounts,
220 FormatHistogramTitleFunc formatFunc);
221
222 static void AppendGraphCommon(const overlay::Widget *widget,
223 const gl::Extents &imageExtent,
224 const std::vector<uint64_t> runningValues,
225 size_t startIndex,
226 float scale,
227 GraphWidgetData *graphWidget,
228 OverlayWidgetCounts *widgetCounts);
229 };
230
AppendTextCommon(const overlay::Widget * widget,const gl::Extents & imageExtent,const std::string & text,TextWidgetData * textWidget,OverlayWidgetCounts * widgetCounts)231 void AppendWidgetDataHelper::AppendTextCommon(const overlay::Widget *widget,
232 const gl::Extents &imageExtent,
233 const std::string &text,
234 TextWidgetData *textWidget,
235 OverlayWidgetCounts *widgetCounts)
236 {
237 GetWidgetCoordinates(widget->coords, imageExtent, textWidget->coordinates);
238 GetWidgetColor(widget->color, textWidget->color);
239 GetTextFontSize(widget->fontSize, textWidget->fontSize);
240 GetTextString(text, textWidget->text);
241
242 ++(*widgetCounts)[WidgetInternalType::Text];
243 }
244
AppendGraphCommon(const overlay::Widget * widget,const gl::Extents & imageExtent,const std::vector<uint64_t> runningValues,size_t startIndex,float scale,GraphWidgetData * graphWidget,OverlayWidgetCounts * widgetCounts)245 void AppendWidgetDataHelper::AppendGraphCommon(const overlay::Widget *widget,
246 const gl::Extents &imageExtent,
247 const std::vector<uint64_t> runningValues,
248 size_t startIndex,
249 float scale,
250 GraphWidgetData *graphWidget,
251 OverlayWidgetCounts *widgetCounts)
252 {
253 const overlay::RunningGraph *widgetAsGraph = static_cast<const overlay::RunningGraph *>(widget);
254
255 GetWidgetCoordinates(widget->coords, imageExtent, graphWidget->coordinates);
256 GetWidgetColor(widget->color, graphWidget->color);
257 GetGraphValueWidth(widget->coords, widgetAsGraph->runningValues.size(),
258 &graphWidget->valueWidth);
259 GetGraphValues(runningValues, startIndex, scale, graphWidget->values);
260
261 ++(*widgetCounts)[WidgetInternalType::Graph];
262 }
263
AppendRunningGraphCommon(const overlay::Widget * widget,const gl::Extents & imageExtent,TextWidgetData * textWidget,GraphWidgetData * graphWidget,OverlayWidgetCounts * widgetCounts,AppendWidgetDataHelper::FormatGraphTitleFunc formatFunc)264 void AppendWidgetDataHelper::AppendRunningGraphCommon(
265 const overlay::Widget *widget,
266 const gl::Extents &imageExtent,
267 TextWidgetData *textWidget,
268 GraphWidgetData *graphWidget,
269 OverlayWidgetCounts *widgetCounts,
270 AppendWidgetDataHelper::FormatGraphTitleFunc formatFunc)
271 {
272 const overlay::RunningGraph *graph = static_cast<const overlay::RunningGraph *>(widget);
273 const overlay::Widget *matchToWidget = widget->matchToWidget;
274
275 if (matchToWidget == nullptr)
276 {
277 matchToWidget = widget;
278 }
279 const overlay::RunningGraph *matchToGraph =
280 static_cast<const overlay::RunningGraph *>(matchToWidget);
281
282 const uint64_t maxValue =
283 *std::max_element(graph->runningValues.begin(), graph->runningValues.end());
284 const uint64_t maxValueInMatchToGraph =
285 *std::max_element(matchToGraph->runningValues.begin(), matchToGraph->runningValues.end());
286 const int32_t graphHeight = std::abs(widget->coords[3] - widget->coords[1]);
287 const float graphScale = static_cast<float>(graphHeight) / maxValueInMatchToGraph;
288
289 const size_t graphSize = graph->runningValues.size();
290 const size_t currentIdx = graph->lastValueIndex - 1;
291
292 const uint64_t curValue = graph->runningValues[(graphSize + currentIdx) % graphSize];
293
294 AppendGraphCommon(widget, imageExtent, graph->runningValues, graph->lastValueIndex + 1,
295 graphScale, graphWidget, widgetCounts);
296
297 if ((*widgetCounts)[WidgetInternalType::Text] <
298 kWidgetInternalTypeMaxWidgets[WidgetInternalType::Text])
299 {
300 std::string text = formatFunc(curValue, maxValue);
301 AppendTextCommon(&graph->description, imageExtent, text, textWidget, widgetCounts);
302 }
303 }
304
305 // static
AppendRunningHistogramCommon(const overlay::Widget * widget,const gl::Extents & imageExtent,TextWidgetData * textWidget,GraphWidgetData * graphWidget,OverlayWidgetCounts * widgetCounts,FormatHistogramTitleFunc formatFunc)306 void AppendWidgetDataHelper::AppendRunningHistogramCommon(const overlay::Widget *widget,
307 const gl::Extents &imageExtent,
308 TextWidgetData *textWidget,
309 GraphWidgetData *graphWidget,
310 OverlayWidgetCounts *widgetCounts,
311 FormatHistogramTitleFunc formatFunc)
312 {
313 const overlay::RunningHistogram *runningHistogram =
314 static_cast<const overlay::RunningHistogram *>(widget);
315
316 std::vector<uint64_t> histogram = CreateHistogram(runningHistogram->runningValues);
317 auto peakRangeIt = std::max_element(histogram.rbegin(), histogram.rend());
318 const uint64_t peakRangeValue = *peakRangeIt;
319 const int32_t graphHeight = std::abs(widget->coords[3] - widget->coords[1]);
320 const float graphScale = static_cast<float>(graphHeight) / peakRangeValue;
321 auto maxValueIter = std::find_if(histogram.rbegin(), histogram.rend(),
322 [](uint64_t value) { return value != 0; });
323
324 AppendGraphCommon(widget, imageExtent, histogram, 0, graphScale, graphWidget, widgetCounts);
325
326 if ((*widgetCounts)[WidgetInternalType::Text] <
327 kWidgetInternalTypeMaxWidgets[WidgetInternalType::Text])
328 {
329 size_t peakRange = std::distance(peakRangeIt, histogram.rend() - 1);
330 size_t maxValueRange = std::distance(maxValueIter, histogram.rend() - 1);
331
332 std::string text = formatFunc(peakRange, maxValueRange, histogram.size());
333 AppendTextCommon(&runningHistogram->description, imageExtent, text, textWidget,
334 widgetCounts);
335 }
336 }
337
AppendFPS(const overlay::Widget * widget,const gl::Extents & imageExtent,TextWidgetData * textWidget,GraphWidgetData * graphWidget,OverlayWidgetCounts * widgetCounts)338 void AppendWidgetDataHelper::AppendFPS(const overlay::Widget *widget,
339 const gl::Extents &imageExtent,
340 TextWidgetData *textWidget,
341 GraphWidgetData *graphWidget,
342 OverlayWidgetCounts *widgetCounts)
343 {
344 const overlay::PerSecond *fps = static_cast<const overlay::PerSecond *>(widget);
345 std::ostringstream text;
346 text << "FPS: ";
347 OutputPerSecond(text, fps);
348
349 AppendTextCommon(widget, imageExtent, text.str(), textWidget, widgetCounts);
350 }
351
AppendVulkanLastValidationMessage(const overlay::Widget * widget,const gl::Extents & imageExtent,TextWidgetData * textWidget,GraphWidgetData * graphWidget,OverlayWidgetCounts * widgetCounts)352 void AppendWidgetDataHelper::AppendVulkanLastValidationMessage(const overlay::Widget *widget,
353 const gl::Extents &imageExtent,
354 TextWidgetData *textWidget,
355 GraphWidgetData *graphWidget,
356 OverlayWidgetCounts *widgetCounts)
357 {
358 const overlay::Text *lastValidationMessage = static_cast<const overlay::Text *>(widget);
359 std::ostringstream text;
360 text << "Last VVL Message: ";
361 OutputText(text, lastValidationMessage);
362
363 AppendTextCommon(widget, imageExtent, text.str(), textWidget, widgetCounts);
364 }
365
AppendVulkanValidationMessageCount(const overlay::Widget * widget,const gl::Extents & imageExtent,TextWidgetData * textWidget,GraphWidgetData * graphWidget,OverlayWidgetCounts * widgetCounts)366 void AppendWidgetDataHelper::AppendVulkanValidationMessageCount(const overlay::Widget *widget,
367 const gl::Extents &imageExtent,
368 TextWidgetData *textWidget,
369 GraphWidgetData *graphWidget,
370 OverlayWidgetCounts *widgetCounts)
371 {
372 const overlay::Count *validationMessageCount = static_cast<const overlay::Count *>(widget);
373 std::ostringstream text;
374 text << "VVL Message Count: ";
375 OutputCount(text, validationMessageCount);
376
377 AppendTextCommon(widget, imageExtent, text.str(), textWidget, widgetCounts);
378 }
379
AppendVulkanRenderPassCount(const overlay::Widget * widget,const gl::Extents & imageExtent,TextWidgetData * textWidget,GraphWidgetData * graphWidget,OverlayWidgetCounts * widgetCounts)380 void AppendWidgetDataHelper::AppendVulkanRenderPassCount(const overlay::Widget *widget,
381 const gl::Extents &imageExtent,
382 TextWidgetData *textWidget,
383 GraphWidgetData *graphWidget,
384 OverlayWidgetCounts *widgetCounts)
385 {
386 auto format = [](uint64_t curValue, uint64_t maxValue) {
387 std::ostringstream text;
388 text << "RenderPass Count: " << maxValue;
389 return text.str();
390 };
391
392 AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
393 }
394
AppendVulkanSecondaryCommandBufferPoolWaste(const overlay::Widget * widget,const gl::Extents & imageExtent,TextWidgetData * textWidget,GraphWidgetData * graphWidget,OverlayWidgetCounts * widgetCounts)395 void AppendWidgetDataHelper::AppendVulkanSecondaryCommandBufferPoolWaste(
396 const overlay::Widget *widget,
397 const gl::Extents &imageExtent,
398 TextWidgetData *textWidget,
399 GraphWidgetData *graphWidget,
400 OverlayWidgetCounts *widgetCounts)
401 {
402 auto format = [](size_t peakRange, size_t maxValueRange, size_t numRanges) {
403 std::ostringstream text;
404 size_t peakPercent = (peakRange * 100 + 50) / numRanges;
405 text << "CB Pool Waste (Peak: " << peakPercent << "%)";
406 return text.str();
407 };
408
409 AppendRunningHistogramCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts,
410 format);
411 }
412
AppendVulkanWriteDescriptorSetCount(const overlay::Widget * widget,const gl::Extents & imageExtent,TextWidgetData * textWidget,GraphWidgetData * graphWidget,OverlayWidgetCounts * widgetCounts)413 void AppendWidgetDataHelper::AppendVulkanWriteDescriptorSetCount(const overlay::Widget *widget,
414 const gl::Extents &imageExtent,
415 TextWidgetData *textWidget,
416 GraphWidgetData *graphWidget,
417 OverlayWidgetCounts *widgetCounts)
418 {
419 auto format = [](uint64_t curValue, uint64_t maxValue) {
420 std::ostringstream text;
421 text << "WriteDescriptorSet Count: " << maxValue;
422 return text.str();
423 };
424
425 AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
426 }
427
AppendVulkanDescriptorSetAllocations(const overlay::Widget * widget,const gl::Extents & imageExtent,TextWidgetData * textWidget,GraphWidgetData * graphWidget,OverlayWidgetCounts * widgetCounts)428 void AppendWidgetDataHelper::AppendVulkanDescriptorSetAllocations(const overlay::Widget *widget,
429 const gl::Extents &imageExtent,
430 TextWidgetData *textWidget,
431 GraphWidgetData *graphWidget,
432 OverlayWidgetCounts *widgetCounts)
433 {
434 auto format = [](uint64_t curValue, uint64_t maxValue) {
435 std::ostringstream text;
436 text << "Descriptor Set Allocations: " << maxValue;
437 return text.str();
438 };
439
440 AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
441 }
442
AppendVulkanShaderResourceDSHitRate(const overlay::Widget * widget,const gl::Extents & imageExtent,TextWidgetData * textWidget,GraphWidgetData * graphWidget,OverlayWidgetCounts * widgetCounts)443 void AppendWidgetDataHelper::AppendVulkanShaderResourceDSHitRate(const overlay::Widget *widget,
444 const gl::Extents &imageExtent,
445 TextWidgetData *textWidget,
446 GraphWidgetData *graphWidget,
447 OverlayWidgetCounts *widgetCounts)
448 {
449 auto format = [](uint64_t curValue, uint64_t maxValue) {
450 std::ostringstream text;
451 text << "Shader Resource DS Hit Rate (Max: " << maxValue << "%)";
452 return text.str();
453 };
454
455 AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
456 }
457
AppendVulkanDynamicBufferAllocations(const overlay::Widget * widget,const gl::Extents & imageExtent,TextWidgetData * textWidget,GraphWidgetData * graphWidget,OverlayWidgetCounts * widgetCounts)458 void AppendWidgetDataHelper::AppendVulkanDynamicBufferAllocations(const overlay::Widget *widget,
459 const gl::Extents &imageExtent,
460 TextWidgetData *textWidget,
461 GraphWidgetData *graphWidget,
462 OverlayWidgetCounts *widgetCounts)
463 {
464 auto format = [](uint64_t curValue, uint64_t maxValue) {
465 std::ostringstream text;
466 text << "DynamicBuffer Allocations (Max: " << maxValue << ")";
467 return text.str();
468 };
469
470 AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
471 }
472
AppendVulkanTextureDescriptorCacheSize(const overlay::Widget * widget,const gl::Extents & imageExtent,TextWidgetData * textWidget,GraphWidgetData * graphWidget,OverlayWidgetCounts * widgetCounts)473 void AppendWidgetDataHelper::AppendVulkanTextureDescriptorCacheSize(
474 const overlay::Widget *widget,
475 const gl::Extents &imageExtent,
476 TextWidgetData *textWidget,
477 GraphWidgetData *graphWidget,
478 OverlayWidgetCounts *widgetCounts)
479 {
480 auto format = [](uint64_t curValue, uint64_t maxValue) {
481 std::ostringstream text;
482 text << "Total Texture Descriptor Cache Size: " << curValue;
483 return text.str();
484 };
485
486 AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
487 }
488
AppendVulkanUniformDescriptorCacheSize(const overlay::Widget * widget,const gl::Extents & imageExtent,TextWidgetData * textWidget,GraphWidgetData * graphWidget,OverlayWidgetCounts * widgetCounts)489 void AppendWidgetDataHelper::AppendVulkanUniformDescriptorCacheSize(
490 const overlay::Widget *widget,
491 const gl::Extents &imageExtent,
492 TextWidgetData *textWidget,
493 GraphWidgetData *graphWidget,
494 OverlayWidgetCounts *widgetCounts)
495 {
496 auto format = [](uint64_t curValue, uint64_t maxValue) {
497 std::ostringstream text;
498 text << "Total Uniform Descriptor Cache Size: " << curValue;
499 return text.str();
500 };
501
502 AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
503 }
504
AppendVulkanDescriptorCacheSize(const overlay::Widget * widget,const gl::Extents & imageExtent,TextWidgetData * textWidget,GraphWidgetData * graphWidget,OverlayWidgetCounts * widgetCounts)505 void AppendWidgetDataHelper::AppendVulkanDescriptorCacheSize(const overlay::Widget *widget,
506 const gl::Extents &imageExtent,
507 TextWidgetData *textWidget,
508 GraphWidgetData *graphWidget,
509 OverlayWidgetCounts *widgetCounts)
510 {
511 auto format = [](uint64_t curValue, uint64_t maxValue) {
512 std::ostringstream text;
513 text << "Total Descriptor Cache Size: " << curValue;
514 return text.str();
515 };
516
517 AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
518 }
519
AppendVulkanDescriptorCacheKeySize(const overlay::Widget * widget,const gl::Extents & imageExtent,TextWidgetData * textWidget,GraphWidgetData * graphWidget,OverlayWidgetCounts * widgetCounts)520 void AppendWidgetDataHelper::AppendVulkanDescriptorCacheKeySize(const overlay::Widget *widget,
521 const gl::Extents &imageExtent,
522 TextWidgetData *textWidget,
523 GraphWidgetData *graphWidget,
524 OverlayWidgetCounts *widgetCounts)
525 {
526 const overlay::Count *countWidget = static_cast<const overlay::Count *>(widget);
527 std::ostringstream text;
528 double kb = static_cast<double>(countWidget->count) / 1000.0;
529 text << "DS Cache Key Size: " << std::fixed << std::setprecision(1) << kb << " kb";
530
531 AppendTextCommon(widget, imageExtent, text.str(), textWidget, widgetCounts);
532 }
533
AppendVulkanAttemptedSubmissions(const overlay::Widget * widget,const gl::Extents & imageExtent,TextWidgetData * textWidget,GraphWidgetData * graphWidget,OverlayWidgetCounts * widgetCounts)534 void AppendWidgetDataHelper::AppendVulkanAttemptedSubmissions(const overlay::Widget *widget,
535 const gl::Extents &imageExtent,
536 TextWidgetData *textWidget,
537 GraphWidgetData *graphWidget,
538 OverlayWidgetCounts *widgetCounts)
539 {
540 auto format = [](uint64_t curValue, uint64_t maxValue) {
541 std::ostringstream text;
542 text << "Attempted submissions (peak): " << maxValue;
543 return text.str();
544 };
545
546 AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
547 }
548
AppendVulkanActualSubmissions(const overlay::Widget * widget,const gl::Extents & imageExtent,TextWidgetData * textWidget,GraphWidgetData * graphWidget,OverlayWidgetCounts * widgetCounts)549 void AppendWidgetDataHelper::AppendVulkanActualSubmissions(const overlay::Widget *widget,
550 const gl::Extents &imageExtent,
551 TextWidgetData *textWidget,
552 GraphWidgetData *graphWidget,
553 OverlayWidgetCounts *widgetCounts)
554 {
555 auto format = [](uint64_t curValue, uint64_t maxValue) {
556 std::ostringstream text;
557 text << "Actual submissions (peak): " << maxValue;
558 return text.str();
559 };
560
561 AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
562 }
563
AppendVulkanPipelineCacheLookups(const overlay::Widget * widget,const gl::Extents & imageExtent,TextWidgetData * textWidget,GraphWidgetData * graphWidget,OverlayWidgetCounts * widgetCounts)564 void AppendWidgetDataHelper::AppendVulkanPipelineCacheLookups(const overlay::Widget *widget,
565 const gl::Extents &imageExtent,
566 TextWidgetData *textWidget,
567 GraphWidgetData *graphWidget,
568 OverlayWidgetCounts *widgetCounts)
569 {
570 auto format = [](uint64_t curValue, uint64_t maxValue) {
571 std::ostringstream text;
572 text << "Pipeline Cache Lookups (peak): " << maxValue;
573 return text.str();
574 };
575
576 AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
577 }
578
AppendVulkanPipelineCacheMisses(const overlay::Widget * widget,const gl::Extents & imageExtent,TextWidgetData * textWidget,GraphWidgetData * graphWidget,OverlayWidgetCounts * widgetCounts)579 void AppendWidgetDataHelper::AppendVulkanPipelineCacheMisses(const overlay::Widget *widget,
580 const gl::Extents &imageExtent,
581 TextWidgetData *textWidget,
582 GraphWidgetData *graphWidget,
583 OverlayWidgetCounts *widgetCounts)
584 {
585 auto format = [](uint64_t curValue, uint64_t maxValue) {
586 std::ostringstream text;
587 text << "Pipeline Cache Misses (peak): " << maxValue;
588 return text.str();
589 };
590
591 AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
592 }
593
AppendVulkanTotalPipelineCacheHitTimeMs(const overlay::Widget * widget,const gl::Extents & imageExtent,TextWidgetData * textWidget,GraphWidgetData * graphWidget,OverlayWidgetCounts * widgetCounts)594 void AppendWidgetDataHelper::AppendVulkanTotalPipelineCacheHitTimeMs(
595 const overlay::Widget *widget,
596 const gl::Extents &imageExtent,
597 TextWidgetData *textWidget,
598 GraphWidgetData *graphWidget,
599 OverlayWidgetCounts *widgetCounts)
600 {
601 const overlay::Count *totalTime = static_cast<const overlay::Count *>(widget);
602 std::ostringstream text;
603 text << "Total Pipeline Cache Hit Time: ";
604 OutputCount(text, totalTime);
605 text << "ms";
606
607 AppendTextCommon(widget, imageExtent, text.str(), textWidget, widgetCounts);
608 }
609
AppendVulkanTotalPipelineCacheMissTimeMs(const overlay::Widget * widget,const gl::Extents & imageExtent,TextWidgetData * textWidget,GraphWidgetData * graphWidget,OverlayWidgetCounts * widgetCounts)610 void AppendWidgetDataHelper::AppendVulkanTotalPipelineCacheMissTimeMs(
611 const overlay::Widget *widget,
612 const gl::Extents &imageExtent,
613 TextWidgetData *textWidget,
614 GraphWidgetData *graphWidget,
615 OverlayWidgetCounts *widgetCounts)
616 {
617 const overlay::Count *totalTime = static_cast<const overlay::Count *>(widget);
618 std::ostringstream text;
619 text << "Total Pipeline Cache Miss Time: ";
620 OutputCount(text, totalTime);
621 text << "ms";
622
623 AppendTextCommon(widget, imageExtent, text.str(), textWidget, widgetCounts);
624 }
625
OutputPerSecond(std::ostream & out,const overlay::PerSecond * perSecond)626 std::ostream &AppendWidgetDataHelper::OutputPerSecond(std::ostream &out,
627 const overlay::PerSecond *perSecond)
628 {
629 return out << perSecond->lastPerSecondCount;
630 }
631
OutputText(std::ostream & out,const overlay::Text * text)632 std::ostream &AppendWidgetDataHelper::OutputText(std::ostream &out, const overlay::Text *text)
633 {
634 return out << text->text;
635 }
636
OutputCount(std::ostream & out,const overlay::Count * count)637 std::ostream &AppendWidgetDataHelper::OutputCount(std::ostream &out, const overlay::Count *count)
638 {
639 return out << count->count;
640 }
641 } // namespace overlay_impl
642
643 namespace
644 {
645 #define ANGLE_APPEND_WIDGET_MAP_PROC(WIDGET_ID) \
646 {WidgetId::WIDGET_ID, overlay_impl::AppendWidgetDataHelper::Append##WIDGET_ID},
647
648 constexpr angle::PackedEnumMap<WidgetId, AppendWidgetDataFunc> kWidgetIdToAppendDataFuncMap = {
649 ANGLE_WIDGET_ID_X(ANGLE_APPEND_WIDGET_MAP_PROC)};
650 } // namespace
651
652 namespace overlay
653 {
getDescriptionWidget() const654 const Text *Widget::getDescriptionWidget() const
655 {
656 return nullptr;
657 }
RunningGraph(size_t n)658 RunningGraph::RunningGraph(size_t n) : runningValues(n, 0) {}
659 RunningGraph::~RunningGraph() = default;
getDescriptionWidget() const660 const Text *RunningGraph::getDescriptionWidget() const
661 {
662 return &description;
663 }
664 } // namespace overlay
665
getWidgetCoordinatesBufferSize() const666 size_t OverlayState::getWidgetCoordinatesBufferSize() const
667 {
668 return sizeof(WidgetCoordinates);
669 }
670
getTextWidgetsBufferSize() const671 size_t OverlayState::getTextWidgetsBufferSize() const
672 {
673 return sizeof(TextWidgets);
674 }
675
getGraphWidgetsBufferSize() const676 size_t OverlayState::getGraphWidgetsBufferSize() const
677 {
678 return sizeof(GraphWidgets);
679 }
680
fillWidgetData(const gl::Extents & imageExtents,uint8_t * textData,uint8_t * graphData,uint32_t * activeTextWidgetCountOut,uint32_t * activeGraphWidgetCountOut) const681 void OverlayState::fillWidgetData(const gl::Extents &imageExtents,
682 uint8_t *textData,
683 uint8_t *graphData,
684 uint32_t *activeTextWidgetCountOut,
685 uint32_t *activeGraphWidgetCountOut) const
686 {
687 TextWidgets *textWidgets = reinterpret_cast<TextWidgets *>(textData);
688 GraphWidgets *graphWidgets = reinterpret_cast<GraphWidgets *>(graphData);
689
690 memset(textWidgets, overlay::kFontCharacters, sizeof(*textWidgets));
691 memset(graphWidgets, 0, sizeof(*graphWidgets));
692
693 OverlayWidgetCounts widgetCounts = {};
694
695 for (WidgetId id : angle::AllEnums<WidgetId>())
696 {
697 const std::unique_ptr<overlay::Widget> &widget = mOverlayWidgets[id];
698 if (!widget->enabled)
699 {
700 continue;
701 }
702
703 WidgetInternalType internalType = kWidgetTypeToInternalMap[widget->type];
704 ASSERT(internalType != WidgetInternalType::InvalidEnum);
705
706 if (widgetCounts[internalType] >= kWidgetInternalTypeMaxWidgets[internalType])
707 {
708 continue;
709 }
710
711 AppendWidgetDataFunc appendFunc = kWidgetIdToAppendDataFuncMap[id];
712 ASSERT(appendFunc);
713 appendFunc(widget.get(), imageExtents,
714 &textWidgets->widgets[widgetCounts[WidgetInternalType::Text]],
715 &graphWidgets->widgets[widgetCounts[WidgetInternalType::Graph]], &widgetCounts);
716 }
717
718 *activeTextWidgetCountOut = widgetCounts[WidgetInternalType::Text];
719 *activeGraphWidgetCountOut = widgetCounts[WidgetInternalType::Graph];
720 }
721
722 } // namespace gl
723