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