summaryrefslogtreecommitdiffstats
path: root/gfx/angle/checkout/src/libANGLE/OverlayWidgets.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/angle/checkout/src/libANGLE/OverlayWidgets.cpp')
-rw-r--r--gfx/angle/checkout/src/libANGLE/OverlayWidgets.cpp737
1 files changed, 737 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/libANGLE/OverlayWidgets.cpp b/gfx/angle/checkout/src/libANGLE/OverlayWidgets.cpp
new file mode 100644
index 0000000000..f0581ce9d8
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/OverlayWidgets.cpp
@@ -0,0 +1,737 @@
+//
+// Copyright 2019 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// OverlayWidgets.cpp:
+// Implements functions that interpret widget data. Data formats and limits correspond to the
+// Vulkan implementation (as the only implementation). They are generic enough so other backends
+// could respect them too, if they implement the overlay.
+//
+
+#include "libANGLE/Overlay.h"
+#include "libANGLE/Overlay_font_autogen.h"
+
+#include <functional>
+
+namespace gl
+{
+namespace
+{
+// Internally, every widget is either Text or Graph.
+enum class WidgetInternalType
+{
+ Text,
+ Graph,
+
+ InvalidEnum,
+ EnumCount = InvalidEnum,
+};
+
+// A map that says how the API-facing widget types map to internal types.
+constexpr angle::PackedEnumMap<WidgetType, WidgetInternalType> kWidgetTypeToInternalMap = {
+ {WidgetType::Count, WidgetInternalType::Text},
+ {WidgetType::Text, WidgetInternalType::Text},
+ {WidgetType::PerSecond, WidgetInternalType::Text},
+ {WidgetType::RunningGraph, WidgetInternalType::Graph},
+ {WidgetType::RunningHistogram, WidgetInternalType::Graph},
+};
+
+// Structures and limits matching uniform buffers in vulkan/shaders/src/OverlayDraw.comp. The size
+// of text and graph widgets is chosen such that they could fit in uniform buffers with minimum
+// required Vulkan size.
+constexpr size_t kMaxRenderableTextWidgets = 32;
+constexpr size_t kMaxRenderableGraphWidgets = 32;
+constexpr size_t kMaxTextLength = 256;
+constexpr size_t kMaxGraphDataSize = 256;
+
+constexpr angle::PackedEnumMap<WidgetInternalType, size_t> kWidgetInternalTypeMaxWidgets = {
+ {WidgetInternalType::Text, kMaxRenderableTextWidgets},
+ {WidgetInternalType::Graph, kMaxRenderableGraphWidgets},
+};
+
+ANGLE_ENABLE_STRUCT_PADDING_WARNINGS
+
+// Structure matching buffer in vulkan/shaders/src/OverlayCull.comp.
+struct WidgetCoordinates
+{
+ uint32_t coordinates[kMaxRenderableTextWidgets + kMaxRenderableGraphWidgets][4];
+};
+
+// Structures matching buffers in vulkan/shaders/src/OverlayDraw.comp.
+struct TextWidgetData
+{
+ uint32_t coordinates[4];
+ float color[4];
+ uint32_t fontSize[3];
+ uint32_t padding;
+ uint8_t text[kMaxTextLength];
+};
+
+struct GraphWidgetData
+{
+ uint32_t coordinates[4];
+ float color[4];
+ uint32_t valueWidth;
+ uint32_t padding[3];
+ uint32_t values[kMaxGraphDataSize];
+};
+
+struct TextWidgets
+{
+ TextWidgetData widgets[kMaxRenderableTextWidgets];
+};
+
+struct GraphWidgets
+{
+ GraphWidgetData widgets[kMaxRenderableGraphWidgets];
+};
+
+ANGLE_DISABLE_STRUCT_PADDING_WARNINGS
+
+uint32_t GetWidgetCoord(int32_t src, uint32_t extent)
+{
+ int32_t dst = src < 0 ? extent + src : src;
+
+ return std::min<uint32_t>(std::max(dst, 0), extent - 1);
+}
+
+void GetWidgetCoordinates(const int32_t srcCoords[4],
+ const gl::Extents &imageExtent,
+ uint32_t dstCoordsOut[4])
+{
+ dstCoordsOut[0] = GetWidgetCoord(srcCoords[0], imageExtent.width);
+ dstCoordsOut[1] = GetWidgetCoord(srcCoords[1], imageExtent.height);
+ dstCoordsOut[2] = GetWidgetCoord(srcCoords[2], imageExtent.width);
+ dstCoordsOut[3] = GetWidgetCoord(srcCoords[3], imageExtent.height);
+}
+
+void GetWidgetColor(const float srcColor[4], float dstColor[4])
+{
+ memcpy(dstColor, srcColor, 4 * sizeof(dstColor[0]));
+}
+
+void GetTextFontSize(int srcFontSize, uint32_t dstFontSize[3])
+{
+ // .xy contains the font glyph width/height
+ dstFontSize[0] = overlay::kFontGlyphWidth >> srcFontSize;
+ dstFontSize[1] = overlay::kFontGlyphHeight >> srcFontSize;
+ // .z contains the mip
+ dstFontSize[2] = srcFontSize;
+}
+
+void GetGraphValueWidth(const int32_t srcCoords[4], size_t valueCount, uint32_t *dstValueWidth)
+{
+ const int32_t graphWidth = std::abs(srcCoords[2] - srcCoords[0]);
+
+ // If valueCount doesn't divide graphWidth, the graph bars won't fit well in its frame.
+ // Fix initOverlayWidgets() in that case.
+ ASSERT(graphWidth % valueCount == 0);
+
+ *dstValueWidth = graphWidth / valueCount;
+}
+
+void GetTextString(const std::string &src, uint8_t textOut[kMaxTextLength])
+{
+ for (size_t i = 0; i < src.length() && i < kMaxTextLength; ++i)
+ {
+ // The font image has 95 ASCII characters starting from ' '.
+ textOut[i] = src[i] - ' ';
+ }
+}
+
+void GetGraphValues(const std::vector<uint64_t> srcValues,
+ size_t startIndex,
+ float scale,
+ uint32_t valuesOut[kMaxGraphDataSize])
+{
+ ASSERT(srcValues.size() <= kMaxGraphDataSize);
+
+ for (size_t i = 0; i < srcValues.size(); ++i)
+ {
+ size_t index = (startIndex + i) % srcValues.size();
+ valuesOut[i] = static_cast<uint32_t>(srcValues[index] * scale);
+ }
+}
+
+std::vector<uint64_t> CreateHistogram(const std::vector<uint64_t> values)
+{
+ std::vector<uint64_t> histogram(values.size(), 0);
+
+ for (uint64_t rank : values)
+ {
+ ++histogram[static_cast<size_t>(rank)];
+ }
+
+ return histogram;
+}
+
+using OverlayWidgetCounts = angle::PackedEnumMap<WidgetInternalType, uint32_t>;
+using AppendWidgetDataFunc = void (*)(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts);
+} // namespace
+
+namespace overlay_impl
+{
+#define ANGLE_DECLARE_APPEND_WIDGET_PROC(WIDGET_ID) \
+ static void Append##WIDGET_ID(const overlay::Widget *widget, const gl::Extents &imageExtent, \
+ TextWidgetData *textWidget, GraphWidgetData *graphWidget, \
+ OverlayWidgetCounts *widgetCounts);
+
+// This class interprets the generic data collected in every element into a human-understandable
+// widget. This often means generating text specific to this item and scaling graph data to
+// something sensible.
+class AppendWidgetDataHelper
+{
+ public:
+ ANGLE_WIDGET_ID_X(ANGLE_DECLARE_APPEND_WIDGET_PROC)
+
+ private:
+ static std::ostream &OutputPerSecond(std::ostream &out, const overlay::PerSecond *perSecond);
+
+ static std::ostream &OutputText(std::ostream &out, const overlay::Text *text);
+
+ static std::ostream &OutputCount(std::ostream &out, const overlay::Count *count);
+
+ static void AppendTextCommon(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ const std::string &text,
+ TextWidgetData *textWidget,
+ OverlayWidgetCounts *widgetCounts);
+
+ using FormatGraphTitleFunc = std::function<std::string(uint64_t curValue, uint64_t maxValue)>;
+ static void AppendRunningGraphCommon(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts,
+ FormatGraphTitleFunc formatFunc);
+
+ using FormatHistogramTitleFunc =
+ std::function<std::string(size_t peakRange, size_t maxValueRange, size_t numRanges)>;
+ static void AppendRunningHistogramCommon(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts,
+ FormatHistogramTitleFunc formatFunc);
+
+ static void AppendGraphCommon(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ const std::vector<uint64_t> runningValues,
+ size_t startIndex,
+ float scale,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts);
+};
+
+void AppendWidgetDataHelper::AppendTextCommon(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ const std::string &text,
+ TextWidgetData *textWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ GetWidgetCoordinates(widget->coords, imageExtent, textWidget->coordinates);
+ GetWidgetColor(widget->color, textWidget->color);
+ GetTextFontSize(widget->fontSize, textWidget->fontSize);
+ GetTextString(text, textWidget->text);
+
+ ++(*widgetCounts)[WidgetInternalType::Text];
+}
+
+void AppendWidgetDataHelper::AppendGraphCommon(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ const std::vector<uint64_t> runningValues,
+ size_t startIndex,
+ float scale,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ const overlay::RunningGraph *widgetAsGraph = static_cast<const overlay::RunningGraph *>(widget);
+
+ GetWidgetCoordinates(widget->coords, imageExtent, graphWidget->coordinates);
+ GetWidgetColor(widget->color, graphWidget->color);
+ GetGraphValueWidth(widget->coords, widgetAsGraph->runningValues.size(),
+ &graphWidget->valueWidth);
+ GetGraphValues(runningValues, startIndex, scale, graphWidget->values);
+
+ ++(*widgetCounts)[WidgetInternalType::Graph];
+}
+
+void AppendWidgetDataHelper::AppendRunningGraphCommon(
+ const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts,
+ AppendWidgetDataHelper::FormatGraphTitleFunc formatFunc)
+{
+ const overlay::RunningGraph *graph = static_cast<const overlay::RunningGraph *>(widget);
+ const overlay::Widget *matchToWidget = widget->matchToWidget;
+
+ if (matchToWidget == nullptr)
+ {
+ matchToWidget = widget;
+ }
+ const overlay::RunningGraph *matchToGraph =
+ static_cast<const overlay::RunningGraph *>(matchToWidget);
+
+ const uint64_t maxValue =
+ *std::max_element(graph->runningValues.begin(), graph->runningValues.end());
+ const uint64_t maxValueInMatchToGraph =
+ *std::max_element(matchToGraph->runningValues.begin(), matchToGraph->runningValues.end());
+ const int32_t graphHeight = std::abs(widget->coords[3] - widget->coords[1]);
+ const float graphScale = static_cast<float>(graphHeight) / maxValueInMatchToGraph;
+
+ const size_t graphSize = graph->runningValues.size();
+ const size_t currentIdx = graph->lastValueIndex - 1;
+
+ const uint64_t curValue = graph->runningValues[(graphSize + currentIdx) % graphSize];
+
+ AppendGraphCommon(widget, imageExtent, graph->runningValues, graph->lastValueIndex + 1,
+ graphScale, graphWidget, widgetCounts);
+
+ if ((*widgetCounts)[WidgetInternalType::Text] <
+ kWidgetInternalTypeMaxWidgets[WidgetInternalType::Text])
+ {
+ std::string text = formatFunc(curValue, maxValue);
+ AppendTextCommon(&graph->description, imageExtent, text, textWidget, widgetCounts);
+ }
+}
+
+// static
+void AppendWidgetDataHelper::AppendRunningHistogramCommon(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts,
+ FormatHistogramTitleFunc formatFunc)
+{
+ const overlay::RunningHistogram *runningHistogram =
+ static_cast<const overlay::RunningHistogram *>(widget);
+
+ std::vector<uint64_t> histogram = CreateHistogram(runningHistogram->runningValues);
+ auto peakRangeIt = std::max_element(histogram.rbegin(), histogram.rend());
+ const uint64_t peakRangeValue = *peakRangeIt;
+ const int32_t graphHeight = std::abs(widget->coords[3] - widget->coords[1]);
+ const float graphScale = static_cast<float>(graphHeight) / peakRangeValue;
+ auto maxValueIter = std::find_if(histogram.rbegin(), histogram.rend(),
+ [](uint64_t value) { return value != 0; });
+
+ AppendGraphCommon(widget, imageExtent, histogram, 0, graphScale, graphWidget, widgetCounts);
+
+ if ((*widgetCounts)[WidgetInternalType::Text] <
+ kWidgetInternalTypeMaxWidgets[WidgetInternalType::Text])
+ {
+ size_t peakRange = std::distance(peakRangeIt, histogram.rend() - 1);
+ size_t maxValueRange = std::distance(maxValueIter, histogram.rend() - 1);
+
+ std::string text = formatFunc(peakRange, maxValueRange, histogram.size());
+ AppendTextCommon(&runningHistogram->description, imageExtent, text, textWidget,
+ widgetCounts);
+ }
+}
+
+void AppendWidgetDataHelper::AppendFPS(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ const overlay::PerSecond *fps = static_cast<const overlay::PerSecond *>(widget);
+ std::ostringstream text;
+ text << "FPS: ";
+ OutputPerSecond(text, fps);
+
+ AppendTextCommon(widget, imageExtent, text.str(), textWidget, widgetCounts);
+}
+
+void AppendWidgetDataHelper::AppendVulkanLastValidationMessage(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ const overlay::Text *lastValidationMessage = static_cast<const overlay::Text *>(widget);
+ std::ostringstream text;
+ text << "Last VVL Message: ";
+ OutputText(text, lastValidationMessage);
+
+ AppendTextCommon(widget, imageExtent, text.str(), textWidget, widgetCounts);
+}
+
+void AppendWidgetDataHelper::AppendVulkanValidationMessageCount(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ const overlay::Count *validationMessageCount = static_cast<const overlay::Count *>(widget);
+ std::ostringstream text;
+ text << "VVL Message Count: ";
+ OutputCount(text, validationMessageCount);
+
+ AppendTextCommon(widget, imageExtent, text.str(), textWidget, widgetCounts);
+}
+
+void AppendWidgetDataHelper::AppendVulkanRenderPassCount(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ auto format = [](uint64_t curValue, uint64_t maxValue) {
+ std::ostringstream text;
+ text << "RenderPass Count: " << maxValue;
+ return text.str();
+ };
+
+ AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
+}
+
+void AppendWidgetDataHelper::AppendVulkanSecondaryCommandBufferPoolWaste(
+ const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ auto format = [](size_t peakRange, size_t maxValueRange, size_t numRanges) {
+ std::ostringstream text;
+ size_t peakPercent = (peakRange * 100 + 50) / numRanges;
+ text << "CB Pool Waste (Peak: " << peakPercent << "%)";
+ return text.str();
+ };
+
+ AppendRunningHistogramCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts,
+ format);
+}
+
+void AppendWidgetDataHelper::AppendVulkanRenderPassBufferCount(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ auto format = [](uint64_t curValue, uint64_t maxValue) {
+ std::ostringstream text;
+ text << "RP VkBuffers (Max: " << maxValue << ")";
+ return text.str();
+ };
+
+ AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
+}
+
+void AppendWidgetDataHelper::AppendVulkanWriteDescriptorSetCount(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ auto format = [](uint64_t curValue, uint64_t maxValue) {
+ std::ostringstream text;
+ text << "WriteDescriptorSet Count: " << maxValue;
+ return text.str();
+ };
+
+ AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
+}
+
+void AppendWidgetDataHelper::AppendVulkanDescriptorSetAllocations(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ auto format = [](uint64_t curValue, uint64_t maxValue) {
+ std::ostringstream text;
+ text << "Descriptor Set Allocations: " << maxValue;
+ return text.str();
+ };
+
+ AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
+}
+
+void AppendWidgetDataHelper::AppendVulkanShaderResourceDSHitRate(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ auto format = [](uint64_t curValue, uint64_t maxValue) {
+ std::ostringstream text;
+ text << "Shader Resource DS Hit Rate (Max: " << maxValue << "%)";
+ return text.str();
+ };
+
+ AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
+}
+
+void AppendWidgetDataHelper::AppendVulkanDynamicBufferAllocations(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ auto format = [](uint64_t curValue, uint64_t maxValue) {
+ std::ostringstream text;
+ text << "DynamicBuffer Allocations (Max: " << maxValue << ")";
+ return text.str();
+ };
+
+ AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
+}
+
+void AppendWidgetDataHelper::AppendVulkanTextureDescriptorCacheSize(
+ const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ auto format = [](uint64_t curValue, uint64_t maxValue) {
+ std::ostringstream text;
+ text << "Total Texture Descriptor Cache Size: " << curValue;
+ return text.str();
+ };
+
+ AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
+}
+
+void AppendWidgetDataHelper::AppendVulkanUniformDescriptorCacheSize(
+ const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ auto format = [](uint64_t curValue, uint64_t maxValue) {
+ std::ostringstream text;
+ text << "Total Uniform Descriptor Cache Size: " << curValue;
+ return text.str();
+ };
+
+ AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
+}
+
+void AppendWidgetDataHelper::AppendVulkanDescriptorCacheSize(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ auto format = [](uint64_t curValue, uint64_t maxValue) {
+ std::ostringstream text;
+ text << "Total Descriptor Cache Size: " << curValue;
+ return text.str();
+ };
+
+ AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
+}
+
+void AppendWidgetDataHelper::AppendVulkanDescriptorCacheKeySize(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ const overlay::Count *countWidget = static_cast<const overlay::Count *>(widget);
+ std::ostringstream text;
+ double kb = static_cast<double>(countWidget->count) / 1000.0;
+ text << "DS Cache Key Size: " << std::fixed << std::setprecision(1) << kb << " kb";
+
+ AppendTextCommon(widget, imageExtent, text.str(), textWidget, widgetCounts);
+}
+
+void AppendWidgetDataHelper::AppendVulkanAttemptedSubmissions(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ auto format = [](uint64_t curValue, uint64_t maxValue) {
+ std::ostringstream text;
+ text << "Attempted submissions (peak): " << maxValue;
+ return text.str();
+ };
+
+ AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
+}
+
+void AppendWidgetDataHelper::AppendVulkanActualSubmissions(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ auto format = [](uint64_t curValue, uint64_t maxValue) {
+ std::ostringstream text;
+ text << "Actual submissions (peak): " << maxValue;
+ return text.str();
+ };
+
+ AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
+}
+
+void AppendWidgetDataHelper::AppendVulkanPipelineCacheLookups(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ auto format = [](uint64_t curValue, uint64_t maxValue) {
+ std::ostringstream text;
+ text << "Pipeline Cache Lookups (peak): " << maxValue;
+ return text.str();
+ };
+
+ AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
+}
+
+void AppendWidgetDataHelper::AppendVulkanPipelineCacheMisses(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ auto format = [](uint64_t curValue, uint64_t maxValue) {
+ std::ostringstream text;
+ text << "Pipeline Cache Misses (peak): " << maxValue;
+ return text.str();
+ };
+
+ AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
+}
+
+void AppendWidgetDataHelper::AppendVulkanTotalPipelineCacheHitTimeMs(
+ const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ const overlay::Count *totalTime = static_cast<const overlay::Count *>(widget);
+ std::ostringstream text;
+ text << "Total Pipeline Cache Hit Time: ";
+ OutputCount(text, totalTime);
+ text << "ms";
+
+ AppendTextCommon(widget, imageExtent, text.str(), textWidget, widgetCounts);
+}
+
+void AppendWidgetDataHelper::AppendVulkanTotalPipelineCacheMissTimeMs(
+ const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ const overlay::Count *totalTime = static_cast<const overlay::Count *>(widget);
+ std::ostringstream text;
+ text << "Total Pipeline Cache Miss Time: ";
+ OutputCount(text, totalTime);
+ text << "ms";
+
+ AppendTextCommon(widget, imageExtent, text.str(), textWidget, widgetCounts);
+}
+
+std::ostream &AppendWidgetDataHelper::OutputPerSecond(std::ostream &out,
+ const overlay::PerSecond *perSecond)
+{
+ return out << perSecond->lastPerSecondCount;
+}
+
+std::ostream &AppendWidgetDataHelper::OutputText(std::ostream &out, const overlay::Text *text)
+{
+ return out << text->text;
+}
+
+std::ostream &AppendWidgetDataHelper::OutputCount(std::ostream &out, const overlay::Count *count)
+{
+ return out << count->count;
+}
+} // namespace overlay_impl
+
+namespace
+{
+#define ANGLE_APPEND_WIDGET_MAP_PROC(WIDGET_ID) \
+ {WidgetId::WIDGET_ID, overlay_impl::AppendWidgetDataHelper::Append##WIDGET_ID},
+
+constexpr angle::PackedEnumMap<WidgetId, AppendWidgetDataFunc> kWidgetIdToAppendDataFuncMap = {
+ ANGLE_WIDGET_ID_X(ANGLE_APPEND_WIDGET_MAP_PROC)};
+} // namespace
+
+namespace overlay
+{
+const Text *Widget::getDescriptionWidget() const
+{
+ return nullptr;
+}
+RunningGraph::RunningGraph(size_t n) : runningValues(n, 0) {}
+RunningGraph::~RunningGraph() = default;
+const Text *RunningGraph::getDescriptionWidget() const
+{
+ return &description;
+}
+} // namespace overlay
+
+size_t OverlayState::getWidgetCoordinatesBufferSize() const
+{
+ return sizeof(WidgetCoordinates);
+}
+
+size_t OverlayState::getTextWidgetsBufferSize() const
+{
+ return sizeof(TextWidgets);
+}
+
+size_t OverlayState::getGraphWidgetsBufferSize() const
+{
+ return sizeof(GraphWidgets);
+}
+
+void OverlayState::fillWidgetData(const gl::Extents &imageExtents,
+ uint8_t *textData,
+ uint8_t *graphData,
+ uint32_t *activeTextWidgetCountOut,
+ uint32_t *activeGraphWidgetCountOut) const
+{
+ TextWidgets *textWidgets = reinterpret_cast<TextWidgets *>(textData);
+ GraphWidgets *graphWidgets = reinterpret_cast<GraphWidgets *>(graphData);
+
+ memset(textWidgets, overlay::kFontCharacters, sizeof(*textWidgets));
+ memset(graphWidgets, 0, sizeof(*graphWidgets));
+
+ OverlayWidgetCounts widgetCounts = {};
+
+ for (WidgetId id : angle::AllEnums<WidgetId>())
+ {
+ const std::unique_ptr<overlay::Widget> &widget = mOverlayWidgets[id];
+ if (!widget->enabled)
+ {
+ continue;
+ }
+
+ WidgetInternalType internalType = kWidgetTypeToInternalMap[widget->type];
+ ASSERT(internalType != WidgetInternalType::InvalidEnum);
+
+ if (widgetCounts[internalType] >= kWidgetInternalTypeMaxWidgets[internalType])
+ {
+ continue;
+ }
+
+ AppendWidgetDataFunc appendFunc = kWidgetIdToAppendDataFuncMap[id];
+ ASSERT(appendFunc);
+ appendFunc(widget.get(), imageExtents,
+ &textWidgets->widgets[widgetCounts[WidgetInternalType::Text]],
+ &graphWidgets->widgets[widgetCounts[WidgetInternalType::Graph]], &widgetCounts);
+ }
+
+ *activeTextWidgetCountOut = widgetCounts[WidgetInternalType::Text];
+ *activeGraphWidgetCountOut = widgetCounts[WidgetInternalType::Graph];
+}
+
+} // namespace gl