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