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 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