1# Debugging Tips 2 3There are many ways to debug ANGLE using generic or platform-dependent tools. Here is a list of tips 4on how to use them. 5 6## Running ANGLE under apitrace on Linux 7 8[Apitrace](http://apitrace.github.io/) captures traces of OpenGL commands for later analysis, 9allowing us to see how ANGLE translates OpenGL ES commands. In order to capture the trace, it 10inserts a driver shim using `LD_PRELOAD` that records the command and then forwards it to the OpenGL 11driver. 12 13The problem with ANGLE is that it exposes the same symbols as the OpenGL driver so apitrace captures 14the entry point calls intended for ANGLE and reroutes them to the OpenGL driver. In order to avoid 15this problem, use the following: 16 171. Link your application against the static ANGLE libraries (libGLESv2_static and libEGL_static) so 18 they don't get shadowed by apitrace's shim. 192. Ask apitrace to explicitly load the driver instead of using a dlsym on the current module. 20 Otherwise apitrace will use ANGLE's symbols as the OpenGL driver entrypoint (causing infinite 21 recursion). To do this you must point an environment variable to your GL driver. For example: 22 `export TRACE_LIBGL=/usr/lib/libGL.so.1`. You can find your libGL with 23 `ldconfig -p | grep libGL`. 243. Link ANGLE against libGL instead of dlsyming the symbols at runtime; otherwise ANGLE won't use 25 the replaced driver entry points. This is done with the gn arg `angle_link_glx = true`. 26 27If you follow these steps, apitrace will work correctly aside from a few minor bugs like not being 28able to figure out what the default framebuffer size is if there is no glViewport command. 29 30For example, to trace a run of `hello_triangle`, assuming the apitrace executables are in `$PATH`: 31 32``` 33gn args out/Debug # add "angle_link_glx = true" 34# edit samples/BUILD.gn and append "_static" to "angle_util", "libEGL", "libGLESv2" 35ninja -C out/Debug 36export TRACE_LIBGL="/usr/lib/libGL.so.1" # may require a different path 37apitrace trace -o mytrace ./out/Debug/hello_triangle 38qapitrace mytrace 39``` 40 41## Enabling General Logging 42 43Normally, ANGLE only logs errors and warnings (e.g. to Android logcat). General logging, or 44additional levels of "trace" messages will be logged when the following GN arg is set: 45``` 46angle_enable_trace = true 47``` 48 49## Debug Angle on Android 50 51Android is built as an Android APK, which makes it more difficult to debug an APK that is using ANGLE. The following information can allow you to debug ANGLE with LLDB. 52* You need to build ANGLE with debug symbols enabled. Assume your build variant is called Debug. Make sure you have these lines in out/Debug/args.gn 53``` 54is_component_build = false 55is_debug = true 56is_official_build = false 57symbol_level = 2 58strip_debug_info = false 59ignore_elf32_limitations = true 60angle_extract_native_libs = true 61``` 62The following local patch may also be necessary: 63``` 64diff --git a/build/config/compiler/compiler.gni b/build/config/compiler/compiler.gni 65index 96a18d91a3f6..ca7971fdfd48 100644 66--- a/build/config/compiler/compiler.gni 67+++ b/build/config/compiler/compiler.gni 68@@ -86,7 +86,8 @@ declare_args() { 69 # Whether an error should be raised on attempts to make debug builds with 70 # is_component_build=false. Very large debug symbols can have unwanted side 71 # effects so this is enforced by default for chromium. 72- forbid_non_component_debug_builds = build_with_chromium 73+ forbid_non_component_debug_builds = false 74``` 75 76Build/install/enable ANGLE apk for your application following other instructions. 77* Modify gdbclient.py script to let it find the ANGLE symbols. 78``` 79diff --git a/scripts/gdbclient.py b/scripts/gdbclient.py 80index 61fac4000..1f43f4f64 100755 81--- a/scripts/gdbclient.py 82+++ b/scripts/gdbclient.py 83@@ -395,6 +395,8 @@ def generate_setup_script(debugger_path, sysroot, linker_search_dir, binary_file 84 vendor_paths = ["", "hw", "egl"] 85 solib_search_path += [os.path.join(symbols_dir, x) for x in symbols_paths] 86 solib_search_path += [os.path.join(vendor_dir, x) for x in vendor_paths] 87+ solib_search_path += ["/your_path_to_chromium_src/out/Debug/lib.unstripped/"] 88 if linker_search_dir is not None: 89 solib_search_path += [linker_search_dir] 90``` 91* Start your lldbclient.py from `/your_path_to_chromium_src/out/Debug` folder. This adds the ANGLE source-file paths to what is visible to LLDB, which allows LLDB to show ANGLE's source files. Refer to https://source.android.com/devices/tech/debug/gdb for how to attach the app for debugging. 92* If you are debugging angle_perftests, you can use `--shard-timeout 100000000` to disable the timeout so that the test won't get killed while you are debugging. If the test runs too fast that you don't have time to attach, use `--delay-test-start=60` to give you extra time to attach. 93 94## Enabling Debug-Utils Markers 95 96ANGLE can emit debug-utils markers for every GLES API command that are visible to both Android GPU 97Inspector (AGI) and RenderDoc. This support requires 98[enabling general logging](#enabling-general-logging) as well as setting the following additional 99GN arg: 100``` 101angle_enable_annotator_run_time_checks = true 102``` 103In addition, if the following GN arg is set, the API calls will output to Android's logcat: 104``` 105angle_enable_trace_android_logcat = true 106``` 107Once compiled, the markers need to be turned on. 108 109### Turning on Debug Markers on Android 110 111On Android, debug markers are turned on and off with an Android debug property that is 112automatically deleted at the next reboot: 113 114``` 115adb shell setprop debug.angle.markers 1 116``` 117 118* 0: Turned off/disabled (default) 119* 1: Turned on/enabled 120 121### Turning on Debug Markers on Desktop 122 123On desktop, debug markers are turned on and off with the ANGLE_ENABLE_DEBUG_MARKERS environment 124variable (set in OS-specific manner): 125 126* 0: Turned off/disabled (default) 127* 1: Turned on/enabled 128 129 130## Running ANGLE under GAPID on Linux 131 132[GAPID](https://github.com/google/gapid) can be used to capture trace of Vulkan commands on Linux. 133When capturing traces of gtest based tests built inside Chromium checkout, make sure to run the 134tests with `--single-process-tests` argument. 135 136## Running ANGLE under GAPID on Android 137 138[GAPID](https://github.com/google/gapid) can be used to capture a trace of the Vulkan or OpenGL ES 139command stream on Android. For it to work, ANGLE's libraries must have different names from the 140system OpenGL libraries. This is done with the gn arg: 141 142``` 143angle_libs_suffix = "_ANGLE_DEV" 144``` 145 146All 147[AngleNativeTest](https://chromium.googlesource.com/chromium/src/+/main/third_party/angle/src/tests/test_utils/runner/android/java/src/com/android/angle/test/AngleNativeTest.java) 148based tests share the same activity name, `com.android.angle.test.AngleUnitTestActivity`. 149Thus, prior to capturing your test trace, the specific test APK must be installed on the device. 150When you build the test, a test launcher is generated, for example, 151`./out/Release/bin/run_angle_end2end_tests`. The best way to install the APK is to run this test 152launcher once. 153 154In GAPID's "Capture Trace" dialog, "Package / Action:" should be: 155 156``` 157android.intent.action.MAIN:com.android.angle.test/com.android.angle.test.AngleUnitTestActivity 158``` 159 160The mandatory [extra intent 161argument](https://developer.android.com/studio/command-line/adb.html#IntentSpec) for starting the 162activity is `org.chromium.native_test.NativeTest.StdoutFile`. Without it the test APK crashes. Test 163filters can be specified via either the `org.chromium.native_test.NativeTest.CommandLineFlags` or 164the `org.chromium.native_test.NativeTest.GtestFilter` argument. Example "Intent Arguments:" values in 165GAPID's "Capture Trace" dialog: 166 167``` 168-e org.chromium.native_test.NativeTest.StdoutFile /sdcard/chromium_tests_root/out.txt -e org.chromium.native_test.NativeTest.CommandLineFlags "--gtest_filter=*ES2_VULKAN" 169``` 170 171or 172 173``` 174-e org.chromium.native_test.NativeTest.StdoutFile /sdcard/chromium_tests_root/out.txt --e org.chromium.native_test.NativeTest.GtestFilter RendererTest.SimpleOperation/ES2_VULKAN:SimpleOperationTest.DrawWithTexture/ES2_VULKAN 175``` 176 177## Running ANGLE under RenderDoc 178 179An application running through ANGLE can confuse [RenderDoc](https://github.com/baldurk/renderdoc), 180as RenderDoc [hooks to EGL](https://github.com/baldurk/renderdoc/issues/1045) and ends up tracing 181the calls the application makes, instead of the calls ANGLE makes to its backend. As ANGLE is a 182special case, there's little support for it by RenderDoc, though there are workarounds. 183 184### Windows 185 186On Windows, RenderDoc supports setting the environment variable `RENDERDOC_HOOK_EGL` to 0 to avoid 187this issue. 188 189### Linux 190 191On Linux, there is no supported workaround by RenderDoc. See [this 192issue](https://github.com/baldurk/renderdoc/issues/1045#issuecomment-463999869). To capture Vulkan 193traces, the workaround is to build RenderDoc without GL(ES) support. 194 195Building RenderDoc is straightforward. However, here are a few instructions to keep in mind. 196 197``` 198# Install dependencies based on RenderDoc document. Here are some packages that are unlikely to be already installed: 199$ sudo apt install libxcb-keysyms1-dev python3-dev qt5-qmake libqt5svg5-dev libqt5x11extras5-dev 200 201# Inside the RenderDoc directory: 202$ cmake -DCMAKE_BUILD_TYPE=Release -Bbuild -H. -DENABLE_GLES=OFF -DENABLE_GL=OFF 203 204# QT_SELECT=5 is necessary if your distribution doesn't default to Qt5 205$ QT_SELECT=5 make -j -C build 206 207# Run RenderDoc from the build directory: 208$ ./build/bin/qrenderdoc 209``` 210 211If your distribution does not provide a recent Vulkan SDK package, you would need to manually 212install that. This script tries to perform this installation as safely as possible. It would 213overwrite the system package's files, so follow at your own risk. Place this script just above the 214extracted SDK directory. 215 216``` 217#! /bin/bash 218 219if [ $# -lt 1 ]; then 220 echo "Usage: $0 <version>" 221 exit 1 222fi 223 224ver=$1 225 226if [ ! -d "$ver" ]; then 227 echo "$ver is not a directory" 228fi 229 230# Verify everything first 231echo "Verifying files..." 232echo "$ver"/x86_64/bin/vulkaninfo 233test -f "$ver"/x86_64/bin/vulkaninfo || exit 1 234echo "$ver"/x86_64/etc/explicit_layer.d/ 235test -d "$ver"/x86_64/etc/explicit_layer.d || exit 1 236echo "$ver"/x86_64/lib/ 237test -d "$ver"/x86_64/lib || exit 1 238 239echo "Verified. Performing copy..." 240 241echo sudo cp "$ver"/x86_64/bin/vulkaninfo /usr/bin/vulkaninfo 242sudo cp "$ver"/x86_64/bin/vulkaninfo /usr/bin/vulkaninfo 243echo sudo cp "$ver"/x86_64/etc/explicit_layer.d/* /etc/explicit_layer.d/ 244sudo cp "$ver"/x86_64/etc/explicit_layer.d/* /etc/explicit_layer.d/ 245echo sudo rm /usr/lib/x86_64-linux-gnu/libvulkan.so* 246sudo rm /usr/lib/x86_64-linux-gnu/libvulkan.so* 247echo sudo cp -P "$ver"/x86_64/lib/lib* /usr/lib/x86_64-linux-gnu/ 248sudo cp -P "$ver"/x86_64/lib/lib* /usr/lib/x86_64-linux-gnu/ 249 250echo "Done." 251``` 252 253### Android 254 255If you are on Linux, make sure not to use the build done in the previous section. The GL renderer 256disabled in the previous section is actually needed in this section. 257 258Define the following environment variables, for example in `.bashrc` (values are examples): 259 260``` 261export JAVA_HOME=/usr/local/buildtools/java/jdk 262export ANDROID_SDK=$HOME/chromium/src/third_party/android_sdk/public 263export ANDROID_NDK=$HOME/chromium/src/third_party/android_ndk 264export ANDROID_NDK_HOME=$HOME/chromium/src/third_party/android_ndk 265``` 266 267In the renderdoc directory, create Android builds of RenderDoc: 268 269``` 270mkdir build-android-arm32 271cd build-android-arm32/ 272cmake -DBUILD_ANDROID=On -DANDROID_ABI=armeabi-v7a .. 273make -j 274cd ../ 275 276mkdir build-android-arm64 277cd build-android-arm64/ 278cmake -DBUILD_ANDROID=On -DANDROID_ABI=arm64-v8a .. 279make -j 280cd ../ 281``` 282 283Note that you need both arm32 and arm64 builds even if working with an arm64 device. See 284[RenderDoc's documentation](https://github.com/baldurk/renderdoc/blob/v1.x/docs/CONTRIBUTING/Compiling.md#android) 285for more information. 286 287When you run RenderDoc, choose the "Replay Context" from the bottom-left part of the UI (defaults to 288Local). When selecting the device, you should see the RenderDoc application running. 289 290In ANGLE itself, make sure you add a suffix for its names to be different from the system's. Add 291this to gn args: 292 293``` 294angle_libs_suffix = "_ANGLE_DEV" 295``` 296 297Next, you need to install an ANGLE test apk. When you build the test, a test launcher is generated, 298for example, `./out/Release/bin/run_angle_end2end_tests`. The best way to install the APK is to run 299this test launcher once. 300 301In RenderDoc, use `com.android.angle.test/com.android.angle.test.AngleUnitTestActivity` as the 302Executable Path, and provide the following arguments: 303 304``` 305-e org.chromium.native_test.NativeTest.StdoutFile /sdcard/chromium_tests_root/out.txt -e org.chromium.native_test.NativeTest.CommandLineFlags "--gtest_filter=*ES2_VULKAN" 306``` 307 308Note that in the above, only a single command line argument is supported with RenderDoc. If testing 309dEQP on a non-default platform, the easiest way would be to modify `GetDefaultAPIName()` in 310`src/tests/deqp_support/angle_deqp_gtest.cpp` (and avoid `--use-angle=X`). 311 312## Testing with Chrome Canary 313 314Many of ANGLE's OpenGL ES entry points are exposed in Chromium as WebGL 1.0 and WebGL 2.0 APIs that 315are available via JavaScript. For testing purposes, custom ANGLE builds may be injected in Chrome 316Canary. 317 318### Setup 319 320#### Windows 321 3221. Download and install [Google Chrome Canary](https://www.google.com/chrome/canary/). 3232. Build ANGLE x64, Release. 3243. Run `python scripts\update_canary_angle.py` to replace Canary's ANGLE with your custom ANGLE 325(note: Canary must be closed). 326 327#### macOS 328 3291. Download and install [Google Chrome Canary](https://www.google.com/chrome/canary/). 3302. Clear all attributes. 331 ``` 332 % xattr -cr /Applications/Google\ Chrome\ Canary.app 333 ``` 3343. Build ANGLE x64 or arm64, Release. 3354. Replace ANGLE libraries, adjusting paths if needed. 336 ``` 337 % cp angle/out/Release/{libEGL.dylib,libGLESv2.dylib} /Applications/Google\ Chrome\ Canary.app/Contents/Frameworks/Google\ Chrome\ Framework.framework/Libraries 338 ``` 3395. Re-sign the application bundle. 340 ``` 341 % codesign --force --sign - --deep /Applications/Google\ Chrome\ Canary.app 342 ``` 343 344### Usage 345 346Run `%LOCALAPPDATA%\Google\Chrome SxS\chrome.exe` (Windows) or `./Google\ Chrome\ Canary.app/Contents/MacOS/Google\ Chrome\ Canary` (macOS) with the following command-line options: 347* `--use-cmd-decoder=passthrough --use-gl=angle` and one of 348 * `--use-angle=d3d9` (Direct3D 9 renderer, Windows only) 349 * `--use-angle=d3d11` (Direct3D 11 renderer, Windows only) 350 * `--use-angle=d3d11on12` (Direct3D 11on12 renderer, Windows only) 351 * `--use-angle=gl` (OpenGL renderer) 352 * `--use-angle=gles` (OpenGL ES renderer) 353 * `--use-angle=vulkan` (Vulkan renderer) 354 * `--use-angle=swiftshader` (SwiftShader renderer) 355 * `--use-angle=metal` (Metal renderer, macOS only) 356