forked from google/angle
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
A debug overlay system for the Vulkan backend designed with efficiency and runtime configurability in mind. Overlay widgets are of two fundamental types: - Text widgets: A single line of text with small, medium or large font. - Graph widgets: A bar graph of data. Built on these, various overlay widget types are defined that gather statistics. Five such types are defined with one widget per type as example: - Count: A widget that counts something. VulkanValidationMessageCount is an overlay widget of this type that shows the number of validation messages received from the validation layers. - Text: A generic text. VulkanLastValidationMessage is an overlay widget of this type that shows the last validation message. - PerSecond: A value that gets reset every second automatically. FPS is an overlay widget of this type that simply gets incremented on every swap(). - RunningGraph: A graph of last N values. VulkanCommandGraphSize is an overlay of this type. On every vkQueueSubmit, the number of nodes in the command graph is accumulated. On every present(), the value is taken as the number of nodes for the whole duration of the frame. - RunningHistogram: A histogram of last N values. Input values are in the [0, 1] range and they are ranked to N buckets for histogram calculation. VulkanSecondaryCommandBufferPoolWaste is an overlay widget of this type. On vkQueueSubmit, the memory waste from command buffer pool allocations is recorded in the histogram. Overlay font is placed in libANGLE/overlay/ which gen_overlay_fonts.py processes to create an array of bits, which is processed at runtime to create the actual font image (an image with 3 layers). The overlay widget layout is defined in overlay_widgets.json which gen_overlay_widgets.py processes to generate an array of widgetss, each of its respective type, and sets their properties, such as color and bounding box. The json file allows widgets to align against other widgets as well as against the framebuffer edges. Two compute shaders are implemented to efficiently render the UI: - OverlayCull: This shader creates a bitset of Text and Graph widgets whose bounding boxes intersect a corresponding subgroup processed by OverlayDraw. This is done only when the enabled overlay widgets are changed (a feature that is not yet implemented) or the surface is resized. - OverlayDraw: Using the bitsets generated by OverlayCull, values that are uniform for each workgroup (set to be equal to hardware subgroup size), this shader loops over enabled widgets that can possibly intersect the pixel being processed and renders and blends in texts and graphs. This is done once per frame on present(). Currently, to enable overlay widgets an environment variable is used. For example: $ export ANGLE_OVERLAY=FPS:VulkanSecondaryCommandBufferPoolWaste $ ./hello_triangle --use-angle=vulkan Possible future work: - On Android, add settings in developer options and enable widgets based on those. - Spawn a small server in ANGLE and write an application that sends enable/disable commands remotely. - Implement overlay for other backends. Bug: angleproject:3757 Change-Id: If9c6974d1935c18f460ec569e79b41188bd7afcc Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1729440 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: Jamie Madill <jmadill@chromium.org>
- Loading branch information
Showing
70 changed files
with
8,253 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
{ | ||
"src/libANGLE/Overlay_font_autogen.cpp": | ||
"ff9bf191978e8c9cff6de3e31f3664f2", | ||
"src/libANGLE/Overlay_font_autogen.h": | ||
"2eae247cebb716c4f591de8a251b4a8e", | ||
"src/libANGLE/gen_overlay_fonts.py": | ||
"e257b626441bf057856eb357a1a2ca5c", | ||
"src/libANGLE/overlay/DejaVuSansMono-Bold.ttf": | ||
"f580ed7569a1967ceeb96fa3e1b234d4" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"src/libANGLE/Overlay_autogen.cpp": | ||
"514b8108f62ef616c296dc511bb2f644", | ||
"src/libANGLE/gen_overlay_widgets.py": | ||
"07252fbde304fd48559ae07f8f920a08", | ||
"src/libANGLE/overlay_widgets.json": | ||
"552b1e2883a12c38d427c7fbd1c2bf22" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
// | ||
// 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. | ||
// | ||
// Overlay.cpp: | ||
// Implements the Overlay class. | ||
// | ||
|
||
#include "libANGLE/Overlay.h" | ||
|
||
#include "common/system_utils.h" | ||
#include "libANGLE/Context.h" | ||
#include "libANGLE/Overlay_font_autogen.h" | ||
#include "libANGLE/renderer/GLImplFactory.h" | ||
#include "libANGLE/renderer/OverlayImpl.h" | ||
|
||
#include <numeric> | ||
|
||
namespace gl | ||
{ | ||
namespace | ||
{ | ||
constexpr std::pair<const char *, WidgetId> kWidgetNames[] = { | ||
{"FPS", WidgetId::FPS}, | ||
{"VulkanLastValidationMessage", WidgetId::VulkanLastValidationMessage}, | ||
{"VulkanValidationMessageCount", WidgetId::VulkanValidationMessageCount}, | ||
{"VulkanCommandGraphSize", WidgetId::VulkanCommandGraphSize}, | ||
{"VulkanSecondaryCommandBufferPoolWaste", WidgetId::VulkanSecondaryCommandBufferPoolWaste}, | ||
}; | ||
} // namespace | ||
|
||
OverlayState::OverlayState() : mEnabledWidgetCount(0), mOverlayWidgets{} {} | ||
OverlayState::~OverlayState() = default; | ||
|
||
Overlay::Overlay(rx::GLImplFactory *factory) | ||
: mLastPerSecondUpdate(0), mImplementation(factory->createOverlay(mState)) | ||
{} | ||
Overlay::~Overlay() = default; | ||
|
||
angle::Result Overlay::init(const Context *context) | ||
{ | ||
initOverlayWidgets(); | ||
mLastPerSecondUpdate = angle::GetCurrentTime(); | ||
|
||
ASSERT(std::all_of( | ||
mState.mOverlayWidgets.begin(), mState.mOverlayWidgets.end(), | ||
[](const std::unique_ptr<overlay::Widget> &widget) { return widget.get() != nullptr; })); | ||
|
||
enableOverlayWidgetsFromEnvironment(); | ||
|
||
return mImplementation->init(context); | ||
} | ||
|
||
void Overlay::destroy(const gl::Context *context) | ||
{ | ||
ASSERT(mImplementation); | ||
mImplementation->onDestroy(context); | ||
} | ||
|
||
void Overlay::enableOverlayWidgetsFromEnvironment() | ||
{ | ||
std::istringstream angleOverlayWidgets(angle::GetEnvironmentVar("ANGLE_OVERLAY")); | ||
|
||
std::set<std::string> enabledWidgets; | ||
std::string widget; | ||
while (getline(angleOverlayWidgets, widget, ':')) | ||
{ | ||
enabledWidgets.insert(widget); | ||
} | ||
|
||
for (const std::pair<const char *, WidgetId> &widgetName : kWidgetNames) | ||
{ | ||
if (enabledWidgets.count(widgetName.first) > 0) | ||
{ | ||
mState.mOverlayWidgets[widgetName.second]->enabled = true; | ||
++mState.mEnabledWidgetCount; | ||
} | ||
} | ||
} | ||
|
||
void Overlay::onSwap() const | ||
{ | ||
// Increment FPS counter. | ||
getPerSecondWidget(WidgetId::FPS)->add(1); | ||
|
||
// Update per second values every second. | ||
double currentTime = angle::GetCurrentTime(); | ||
double timeDiff = currentTime - mLastPerSecondUpdate; | ||
if (timeDiff >= 1.0) | ||
{ | ||
for (const std::unique_ptr<overlay::Widget> &widget : mState.mOverlayWidgets) | ||
{ | ||
if (widget->type == WidgetType::PerSecond) | ||
{ | ||
overlay::PerSecond *perSecond = | ||
reinterpret_cast<overlay::PerSecond *>(widget.get()); | ||
perSecond->lastPerSecondCount = static_cast<size_t>(perSecond->count / timeDiff); | ||
perSecond->count = 0; | ||
} | ||
} | ||
mLastPerSecondUpdate += 1.0; | ||
} | ||
} | ||
|
||
DummyOverlay::DummyOverlay(rx::GLImplFactory *implFactory) {} | ||
DummyOverlay::~DummyOverlay() = default; | ||
|
||
} // namespace gl |
Oops, something went wrong.