• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Debug Overlay in ANGLE’s Vulkan Backend
2
3## Motivation
4A complex application has frequently changing performance characteristics due to
5both a varying number of objects to draw and different effects that need to be
6applied to them. When characterizing the performance of an application, it can
7be easy to miss scenes which need optimization, especially if they are
8ephemeral.
9
10A debug overlay that shows on-the-fly statistics from the running application
11can greatly aid the developer in finding where the bottlenecks are and which
12scenes need further investigation and profiling.
13
14ANGLE’s Vulkan debug overlay is drawn in a single compute pass for efficiency.
15The initial implementation includes a few pieces of information for
16demonstration purposes. Here’s the glmark2 *terrain* scene with these overlay
17items enabled:
18
19![glmark2 terrain scene](img/VangleDebugOverlay.png)
20
21This is a screenshot of a debug build, hence the low FPS.
22The command graph size is constant every frame.
23
24## Implementation
25Overlay items are of two fundamental types:
26* Text items: A single line of text with small, medium or large font.
27* Graph items: A bar graph of data. These each have a Text item attached
28  that is automatically rendered with the graph item.
29
30Built on these, various overlay item types are defined that gather statistics.
31Five such types are defined with one item per type as example:
32* **Count**: An item that counts something. **VulkanValidationMessageCount**
33  is an overlay item of this type that shows the number of validation messages
34  received from the validation layers.
35* **Text**: A generic text widget. **VulkanLastValidationMessage** is an overlay
36  item of this type that shows the last validation message.
37* **PerSecond**: A value that gets reset every second automatically. **FPS** is
38  an overlay item of this type that simply gets incremented on every `swap()`.
39* **RunningGraph**: A graph of the last N values. **VulkanRenderPassCount** is an
40  overlay of this type. This counter reports the number of RenderPasses rendered
41  in each vkQueueSubmit call.
42* **RunningHistogram**: A histogram of last N values. Input values are in the
43  [0, 1] range and they are ranked to N buckets for histogram calculation.
44  **VulkanSecondaryCommandBufferPoolWaste** is an overlay item of this type.
45  On `vkQueueSubmit()`, the memory waste from command buffer pool allocations
46  is recorded in the histogram.
47
48Overlay font are placed in [libANGLE/overlay/](../src/libANGLE/overlay/)
49which [gen_overlay_fonts.py](../src/libANGLE/gen_overlay_fonts.py) processes
50to create an array of bits, which is processed at runtime to create
51the actual font image (an image with 3 layers).
52
53The overlay widget layout is defined in
54[overlay_widgets.json](../src/libANGLE/overlay_widgets.json)
55which [gen_overlay_widgets.py](../src/libANGLE/gen_overlay_widgets.py)
56processes to generate an array of widgets, each of its respective type,
57and sets their properties, such as color and bounding box.
58The json file allows widgets to align against other widgets as well as against
59the framebuffer edges. The following is a part of this file:
60```json
61{
62    "name": "VulkanValidationMessageCount",
63    "type": "Count",
64    "color": [255, 0, 0, 255],
65    "coords": [10, "VulkanLastValidationMessage.top.adjacent"],
66    "font": "small",
67    "length": 25
68},
69{
70    "name": "VulkanSecondaryCommandBufferPoolWaste",
71    "type": "RunningHistogram(50)",
72    "color": [255, 200, 75, 200],
73    "coords": [-50, 100],
74    "bar_width": 6,
75    "height": 100,
76    "description": {
77        "color": [255, 200, 75, 255],
78        "coords": ["VulkanSecondaryCommandBufferPoolWaste.left.align",
79                   "VulkanSecondaryCommandBufferPoolWaste.top.adjacent"],
80        "font": "small",
81        "length": 40
82    }
83}
84```
85Negative coordinates in this file indicate alignment to the right/bottom of the
86framebuffer. `OtherItem.edge.mode` lets an item be aligned with another.
87If `mode` is `align`, the item has the same origin as `OtherItem` and expands
88in the same direction. If `adjacent`, the item expands in the opposite
89direction.
90
91Two compute shaders are implemented to efficiently render the UI:
92* **OverlayCull**: This shader creates a bitset of Text and Graph items whose
93  bounding boxes intersect a corresponding subgroup processed by OverlayDraw.
94  This is done only when the enabled overlay items are changed or the surface
95  is resized. This shader uses `subgroupBallot()` where possible, if not
96  `subgroupOr()` where possible or otherwise shared buffers to create the bitset
97  collaboratively.
98* **OverlayDraw**: Using the bitsets generated by **OverlayCull**, values that
99  are uniform for each workgroup (set to be equal to hardware subgroup size),
100  this shader loops over enabled items that can possibly intersect the pixel
101  being processed and renders and blends in texts and graphs. This is done once
102  per frame on `present()`.
103
104To build ANGLE with overlay capability, `angle_enable_overlay = true` must be
105placed in `args.gn`.
106
107Currently, to enable overlay items an environment variable is used. For example:
108
109```commandline
110$ export ANGLE_OVERLAY=FPS:VulkanSecondaryCommandBufferPoolWaste
111$ ./hello_triangle --use-angle=vulkan
112```
113
114## Future Work
115Possible future work
116* On Android, add settings in developer options and enable items based on those.
117* Spawn a small server in ANGLE and write an application that sends
118  enable/disable commands remotely.
119* Implement the Overlay rendering functionality in the front-end to benefit all
120  backends.
121* Add more overlay widgets.
122* Implement automatic widget layout to remove the need to specify positions in the overlay widgets JSON.
123
124
125
126
127
128
129