OverlayWidgets.cpp (30948B)
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 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 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 109 void GetWidgetColor(const float srcColor[4], float dstColor[4]) 110 { 111 memcpy(dstColor, srcColor, 4 * sizeof(dstColor[0])); 112 } 113 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 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 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 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 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 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 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 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 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 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 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 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 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 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 413 void AppendWidgetDataHelper::AppendVulkanRenderPassBufferCount(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 << "RP VkBuffers (Max: " << maxValue << ")"; 422 return text.str(); 423 }; 424 425 AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format); 426 } 427 428 void AppendWidgetDataHelper::AppendVulkanWriteDescriptorSetCount(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 << "WriteDescriptorSet Count: " << maxValue; 437 return text.str(); 438 }; 439 440 AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format); 441 } 442 443 void AppendWidgetDataHelper::AppendVulkanDescriptorSetAllocations(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 << "Descriptor Set Allocations: " << maxValue; 452 return text.str(); 453 }; 454 455 AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format); 456 } 457 458 void AppendWidgetDataHelper::AppendVulkanShaderResourceDSHitRate(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 << "Shader Resource DS Hit Rate (Max: " << maxValue << "%)"; 467 return text.str(); 468 }; 469 470 AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format); 471 } 472 473 void AppendWidgetDataHelper::AppendVulkanDynamicBufferAllocations(const overlay::Widget *widget, 474 const gl::Extents &imageExtent, 475 TextWidgetData *textWidget, 476 GraphWidgetData *graphWidget, 477 OverlayWidgetCounts *widgetCounts) 478 { 479 auto format = [](uint64_t curValue, uint64_t maxValue) { 480 std::ostringstream text; 481 text << "DynamicBuffer Allocations (Max: " << maxValue << ")"; 482 return text.str(); 483 }; 484 485 AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format); 486 } 487 488 void AppendWidgetDataHelper::AppendVulkanTextureDescriptorCacheSize( 489 const overlay::Widget *widget, 490 const gl::Extents &imageExtent, 491 TextWidgetData *textWidget, 492 GraphWidgetData *graphWidget, 493 OverlayWidgetCounts *widgetCounts) 494 { 495 auto format = [](uint64_t curValue, uint64_t maxValue) { 496 std::ostringstream text; 497 text << "Total Texture Descriptor Cache Size: " << curValue; 498 return text.str(); 499 }; 500 501 AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format); 502 } 503 504 void AppendWidgetDataHelper::AppendVulkanUniformDescriptorCacheSize( 505 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 Uniform Descriptor Cache Size: " << curValue; 514 return text.str(); 515 }; 516 517 AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format); 518 } 519 520 void AppendWidgetDataHelper::AppendVulkanDescriptorCacheSize(const overlay::Widget *widget, 521 const gl::Extents &imageExtent, 522 TextWidgetData *textWidget, 523 GraphWidgetData *graphWidget, 524 OverlayWidgetCounts *widgetCounts) 525 { 526 auto format = [](uint64_t curValue, uint64_t maxValue) { 527 std::ostringstream text; 528 text << "Total Descriptor Cache Size: " << curValue; 529 return text.str(); 530 }; 531 532 AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format); 533 } 534 535 void AppendWidgetDataHelper::AppendVulkanDescriptorCacheKeySize(const overlay::Widget *widget, 536 const gl::Extents &imageExtent, 537 TextWidgetData *textWidget, 538 GraphWidgetData *graphWidget, 539 OverlayWidgetCounts *widgetCounts) 540 { 541 const overlay::Count *countWidget = static_cast<const overlay::Count *>(widget); 542 std::ostringstream text; 543 double kb = static_cast<double>(countWidget->count) / 1000.0; 544 text << "DS Cache Key Size: " << std::fixed << std::setprecision(1) << kb << " kb"; 545 546 AppendTextCommon(widget, imageExtent, text.str(), textWidget, widgetCounts); 547 } 548 549 void AppendWidgetDataHelper::AppendVulkanAttemptedSubmissions(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 << "Attempted submissions (peak): " << maxValue; 558 return text.str(); 559 }; 560 561 AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format); 562 } 563 564 void AppendWidgetDataHelper::AppendVulkanActualSubmissions(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 << "Actual submissions (peak): " << maxValue; 573 return text.str(); 574 }; 575 576 AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format); 577 } 578 579 void AppendWidgetDataHelper::AppendVulkanPipelineCacheLookups(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 Lookups (peak): " << maxValue; 588 return text.str(); 589 }; 590 591 AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format); 592 } 593 594 void AppendWidgetDataHelper::AppendVulkanPipelineCacheMisses(const overlay::Widget *widget, 595 const gl::Extents &imageExtent, 596 TextWidgetData *textWidget, 597 GraphWidgetData *graphWidget, 598 OverlayWidgetCounts *widgetCounts) 599 { 600 auto format = [](uint64_t curValue, uint64_t maxValue) { 601 std::ostringstream text; 602 text << "Pipeline Cache Misses (peak): " << maxValue; 603 return text.str(); 604 }; 605 606 AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format); 607 } 608 609 void AppendWidgetDataHelper::AppendVulkanTotalPipelineCacheHitTimeMs( 610 const overlay::Widget *widget, 611 const gl::Extents &imageExtent, 612 TextWidgetData *textWidget, 613 GraphWidgetData *graphWidget, 614 OverlayWidgetCounts *widgetCounts) 615 { 616 const overlay::Count *totalTime = static_cast<const overlay::Count *>(widget); 617 std::ostringstream text; 618 text << "Total Pipeline Cache Hit Time: "; 619 OutputCount(text, totalTime); 620 text << "ms"; 621 622 AppendTextCommon(widget, imageExtent, text.str(), textWidget, widgetCounts); 623 } 624 625 void AppendWidgetDataHelper::AppendVulkanTotalPipelineCacheMissTimeMs( 626 const overlay::Widget *widget, 627 const gl::Extents &imageExtent, 628 TextWidgetData *textWidget, 629 GraphWidgetData *graphWidget, 630 OverlayWidgetCounts *widgetCounts) 631 { 632 const overlay::Count *totalTime = static_cast<const overlay::Count *>(widget); 633 std::ostringstream text; 634 text << "Total Pipeline Cache Miss Time: "; 635 OutputCount(text, totalTime); 636 text << "ms"; 637 638 AppendTextCommon(widget, imageExtent, text.str(), textWidget, widgetCounts); 639 } 640 641 std::ostream &AppendWidgetDataHelper::OutputPerSecond(std::ostream &out, 642 const overlay::PerSecond *perSecond) 643 { 644 return out << perSecond->lastPerSecondCount; 645 } 646 647 std::ostream &AppendWidgetDataHelper::OutputText(std::ostream &out, const overlay::Text *text) 648 { 649 return out << text->text; 650 } 651 652 std::ostream &AppendWidgetDataHelper::OutputCount(std::ostream &out, const overlay::Count *count) 653 { 654 return out << count->count; 655 } 656 } // namespace overlay_impl 657 658 namespace 659 { 660 #define ANGLE_APPEND_WIDGET_MAP_PROC(WIDGET_ID) \ 661 {WidgetId::WIDGET_ID, overlay_impl::AppendWidgetDataHelper::Append##WIDGET_ID}, 662 663 constexpr angle::PackedEnumMap<WidgetId, AppendWidgetDataFunc> kWidgetIdToAppendDataFuncMap = { 664 ANGLE_WIDGET_ID_X(ANGLE_APPEND_WIDGET_MAP_PROC)}; 665 } // namespace 666 667 namespace overlay 668 { 669 const Text *Widget::getDescriptionWidget() const 670 { 671 return nullptr; 672 } 673 RunningGraph::RunningGraph(size_t n) : runningValues(n, 0) {} 674 RunningGraph::~RunningGraph() = default; 675 const Text *RunningGraph::getDescriptionWidget() const 676 { 677 return &description; 678 } 679 } // namespace overlay 680 681 size_t OverlayState::getWidgetCoordinatesBufferSize() const 682 { 683 return sizeof(WidgetCoordinates); 684 } 685 686 size_t OverlayState::getTextWidgetsBufferSize() const 687 { 688 return sizeof(TextWidgets); 689 } 690 691 size_t OverlayState::getGraphWidgetsBufferSize() const 692 { 693 return sizeof(GraphWidgets); 694 } 695 696 void OverlayState::fillWidgetData(const gl::Extents &imageExtents, 697 uint8_t *textData, 698 uint8_t *graphData, 699 uint32_t *activeTextWidgetCountOut, 700 uint32_t *activeGraphWidgetCountOut) const 701 { 702 TextWidgets *textWidgets = reinterpret_cast<TextWidgets *>(textData); 703 GraphWidgets *graphWidgets = reinterpret_cast<GraphWidgets *>(graphData); 704 705 memset(textWidgets, overlay::kFontCharacters, sizeof(*textWidgets)); 706 memset(graphWidgets, 0, sizeof(*graphWidgets)); 707 708 OverlayWidgetCounts widgetCounts = {}; 709 710 for (WidgetId id : angle::AllEnums<WidgetId>()) 711 { 712 const std::unique_ptr<overlay::Widget> &widget = mOverlayWidgets[id]; 713 if (!widget->enabled) 714 { 715 continue; 716 } 717 718 WidgetInternalType internalType = kWidgetTypeToInternalMap[widget->type]; 719 ASSERT(internalType != WidgetInternalType::InvalidEnum); 720 721 if (widgetCounts[internalType] >= kWidgetInternalTypeMaxWidgets[internalType]) 722 { 723 continue; 724 } 725 726 AppendWidgetDataFunc appendFunc = kWidgetIdToAppendDataFuncMap[id]; 727 ASSERT(appendFunc); 728 appendFunc(widget.get(), imageExtents, 729 &textWidgets->widgets[widgetCounts[WidgetInternalType::Text]], 730 &graphWidgets->widgets[widgetCounts[WidgetInternalType::Graph]], &widgetCounts); 731 } 732 733 *activeTextWidgetCountOut = widgetCounts[WidgetInternalType::Text]; 734 *activeGraphWidgetCountOut = widgetCounts[WidgetInternalType::Graph]; 735 } 736 737 } // namespace gl