David Ghandehari | b153652 | 2017-05-24 00:01:15 -0700 | [diff] [blame] | 1 | # Debugging Tips |
| 2 | |
Kaido Kert | 612c020 | 2020-01-22 10:28:42 -0800 | [diff] [blame] | 3 | There are many ways to debug ANGLE using generic or platform-dependent tools. Here is a list of tips |
| 4 | on how to use them. |
David Ghandehari | b153652 | 2017-05-24 00:01:15 -0700 | [diff] [blame] | 5 | |
| 6 | ## Running ANGLE under apitrace on Linux |
| 7 | |
Kaido Kert | 612c020 | 2020-01-22 10:28:42 -0800 | [diff] [blame] | 8 | [Apitrace](http://apitrace.github.io/) captures traces of OpenGL commands for later analysis, |
| 9 | allowing us to see how ANGLE translates OpenGL ES commands. In order to capture the trace, it |
| 10 | inserts a driver shim using `LD_PRELOAD` that records the command and then forwards it to the OpenGL |
| 11 | driver. |
David Ghandehari | b153652 | 2017-05-24 00:01:15 -0700 | [diff] [blame] | 12 | |
Kaido Kert | 612c020 | 2020-01-22 10:28:42 -0800 | [diff] [blame] | 13 | The problem with ANGLE is that it exposes the same symbols as the OpenGL driver so apitrace captures |
| 14 | the entry point calls intended for ANGLE and reroutes them to the OpenGL driver. In order to avoid |
| 15 | this problem, use the following: |
David Ghandehari | b153652 | 2017-05-24 00:01:15 -0700 | [diff] [blame] | 16 | |
Kaido Kert | 612c020 | 2020-01-22 10:28:42 -0800 | [diff] [blame] | 17 | 1. Link your application against the static ANGLE libraries (libGLESv2_static and libEGL_static) so |
| 18 | they don't get shadowed by apitrace's shim. |
| 19 | 2. 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`. |
| 24 | 3. 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`. |
David Ghandehari | b153652 | 2017-05-24 00:01:15 -0700 | [diff] [blame] | 26 | |
Kaido Kert | 612c020 | 2020-01-22 10:28:42 -0800 | [diff] [blame] | 27 | If you follow these steps, apitrace will work correctly aside from a few minor bugs like not being |
| 28 | able to figure out what the default framebuffer size is if there is no glViewport command. |
David Ghandehari | b153652 | 2017-05-24 00:01:15 -0700 | [diff] [blame] | 29 | |
Kaido Kert | 612c020 | 2020-01-22 10:28:42 -0800 | [diff] [blame] | 30 | For example, to trace a run of `hello_triangle`, assuming the apitrace executables are in `$PATH`: |
David Ghandehari | b153652 | 2017-05-24 00:01:15 -0700 | [diff] [blame] | 31 | |
| 32 | ``` |
Kaido Kert | 612c020 | 2020-01-22 10:28:42 -0800 | [diff] [blame] | 33 | gn args out/Debug # add "angle_link_glx = true" |
| 34 | # edit samples/BUILD.gn and append "_static" to "angle_util", "libEGL", "libGLESv2" |
David Ghandehari | b153652 | 2017-05-24 00:01:15 -0700 | [diff] [blame] | 35 | ninja -C out/Debug |
| 36 | export TRACE_LIBGL="/usr/lib/libGL.so.1" # may require a different path |
| 37 | apitrace trace -o mytrace ./out/Debug/hello_triangle |
| 38 | qapitrace mytrace |
| 39 | ``` |
Kaido Kert | 612c020 | 2020-01-22 10:28:42 -0800 | [diff] [blame] | 40 | |
| 41 | ## Running ANGLE under GAPID on Linux |
| 42 | |
| 43 | [GAPID](https://github.com/google/gapid) can be used to capture trace of Vulkan commands on Linux. |
| 44 | For it to work, libvulkan has to be a shared library, instead of being statically linked into ANGLE, |
| 45 | which is the default behavior. This is done with the gn arg: |
| 46 | |
| 47 | ``` |
| 48 | angle_shared_libvulkan = true |
| 49 | ``` |
| 50 | |
| 51 | When capturing traces of gtest based tests built inside Chromium checkout, make sure to run the |
| 52 | tests with `--single-process-tests` argument. |
| 53 | |
| 54 | ## Running ANGLE under GAPID on Android |
| 55 | |
| 56 | [GAPID](https://github.com/google/gapid) can be used to capture a trace of the Vulkan or OpenGL ES |
| 57 | command stream on Android. For it to work, ANGLE's libraries must have different names from the |
| 58 | system OpenGL libraries. This is done with the gn arg: |
| 59 | |
| 60 | ``` |
| 61 | angle_libs_suffix = "_ANGLE_DEV" |
| 62 | ``` |
| 63 | |
| 64 | All |
| 65 | [NativeTest](https://chromium.googlesource.com/chromium/src/+/master/testing/android/native_test/java/src/org/chromium/native_test/NativeTest.java) |
| 66 | based tests share the same activity name, `org.chromium.native_test.NativeUnitTestNativeActivity`. |
| 67 | Thus, prior to capturing your test trace, the specific test APK must be installed on the device. |
| 68 | When you build the test, a test launcher is generated, for example, |
| 69 | `./out/Release/bin/run_angle_end2end_tests`. The best way to install the APK is to run this test |
| 70 | launcher once. |
| 71 | |
| 72 | In GAPID's "Capture Trace" dialog, "Package / Action:" should be: |
| 73 | |
| 74 | ``` |
| 75 | android.intent.action.MAIN:org.chromium.native_test/org.chromium.native_test.NativeUnitTestNativeActivity |
| 76 | ``` |
| 77 | |
| 78 | The mandatory [extra intent |
| 79 | argument](https://developer.android.com/studio/command-line/adb.html#IntentSpec) for starting the |
| 80 | activity is `org.chromium.native_test.NativeTest.StdoutFile`. Without it the test APK crashes. Test |
| 81 | filters can be specified via either the `org.chromium.native_test.NativeTest.CommandLineFlags` or |
| 82 | the `org.chromium.native_test.NativeTest.Shard` argument. Example "Intent Arguments:" values in |
| 83 | GAPID's "Capture Trace" dialog: |
| 84 | |
| 85 | ``` |
| 86 | -e org.chromium.native_test.NativeTest.StdoutFile /sdcard/chromium_tests_root/out.txt -e org.chromium.native_test.NativeTest.CommandLineFlags "--gtest_filter=*ES2_VULKAN" |
| 87 | ``` |
| 88 | |
| 89 | or |
| 90 | |
| 91 | ``` |
| 92 | -e org.chromium.native_test.NativeTest.StdoutFile /sdcard/chromium_tests_root/out.txt --esal org.chromium.native_test.NativeTest.Shard RendererTest.SimpleOperation/ES2_VULKAN,SimpleOperationTest.DrawWithTexture/ES2_VULKAN |
| 93 | ``` |
| 94 | |
| 95 | ## Running ANGLE under RenderDoc |
| 96 | |
| 97 | An application running through ANGLE can confuse [RenderDoc](https://github.com/baldurk/renderdoc), |
| 98 | as RenderDoc [hooks to EGL](https://github.com/baldurk/renderdoc/issues/1045) and ends up tracing |
| 99 | the calls the application makes, instead of the calls ANGLE makes to its backend. As ANGLE is a |
| 100 | special case, there's little support for it by RenderDoc, though there are workarounds. |
| 101 | |
| 102 | ### Windows |
| 103 | |
| 104 | On Windows, RenderDoc supports setting the environment variable `RENDERDOC_HOOK_EGL` to 0 to avoid |
| 105 | this issue. |
| 106 | |
| 107 | ### Linux |
| 108 | |
| 109 | On Linux, there is no supported workaround by RenderDoc. See [this |
| 110 | issue](https://github.com/baldurk/renderdoc/issues/1045#issuecomment-463999869). To capture Vulkan |
| 111 | traces, the workaround is to build RenderDoc without GL(ES) support. |
| 112 | |
| 113 | Building RenderDoc is straightforward. However, here are a few instructions to keep in mind. |
| 114 | |
| 115 | ``` |
| 116 | # Install dependencies based on RenderDoc document. Here are some packages that are unlikely to be already installed: |
| 117 | $ sudo apt install libxcb-keysyms1-dev python3-dev qt5-qmake libqt5svg5-dev libqt5x11extras5-dev |
| 118 | |
| 119 | # Inside the RenderDoc directory: |
| 120 | $ cmake -DCMAKE_BUILD_TYPE=Release -Bbuild -H. -DENABLE_GLES=OFF -DENABLE_GL=OFF |
| 121 | |
| 122 | # QT_SELECT=5 is necessary if your distribution doesn't default to Qt5 |
| 123 | $ QT_SELECT=5 make -j -C build |
| 124 | |
| 125 | # Run RenderDoc from the build directory: |
| 126 | $ ./build/bin/qrenderdoc |
| 127 | ``` |
| 128 | |
| 129 | Additionally, libvulkan has to be a shared library, instead of being statically linked into ANGLE, |
| 130 | which is the default behavior. This is done with the gn arg: |
| 131 | |
| 132 | ``` |
| 133 | angle_shared_libvulkan = true |
| 134 | ``` |
| 135 | |
| 136 | If your distribution does not provide a recent Vulkan SDK package, you would need to manually |
| 137 | install that. This script tries to perform this installation as safely as possible. It would |
| 138 | overwrite the system package's files, so follow at your own risk. Place this script just above the |
| 139 | extracted SDK directory. |
| 140 | |
| 141 | ``` |
| 142 | #! /bin/bash |
| 143 | |
| 144 | if [ $# -lt 1 ]; then |
| 145 | echo "Usage: $0 <version>" |
| 146 | exit 1 |
| 147 | fi |
| 148 | |
| 149 | ver=$1 |
| 150 | |
| 151 | if [ ! -d "$ver" ]; then |
| 152 | echo "$ver is not a directory" |
| 153 | fi |
| 154 | |
| 155 | # Verify everything first |
| 156 | echo "Verifying files..." |
| 157 | echo "$ver"/x86_64/bin/vulkaninfo |
| 158 | test -f "$ver"/x86_64/bin/vulkaninfo || exit 1 |
| 159 | echo "$ver"/x86_64/etc/explicit_layer.d/ |
| 160 | test -d "$ver"/x86_64/etc/explicit_layer.d || exit 1 |
| 161 | echo "$ver"/x86_64/lib/ |
| 162 | test -d "$ver"/x86_64/lib || exit 1 |
| 163 | |
| 164 | echo "Verified. Performing copy..." |
| 165 | |
| 166 | echo sudo cp "$ver"/x86_64/bin/vulkaninfo /usr/bin/vulkaninfo |
| 167 | sudo cp "$ver"/x86_64/bin/vulkaninfo /usr/bin/vulkaninfo |
| 168 | echo sudo cp "$ver"/x86_64/etc/explicit_layer.d/* /etc/explicit_layer.d/ |
| 169 | sudo cp "$ver"/x86_64/etc/explicit_layer.d/* /etc/explicit_layer.d/ |
| 170 | echo sudo rm /usr/lib/x86_64-linux-gnu/libvulkan.so* |
| 171 | sudo rm /usr/lib/x86_64-linux-gnu/libvulkan.so* |
| 172 | echo sudo cp -P "$ver"/x86_64/lib/lib* /usr/lib/x86_64-linux-gnu/ |
| 173 | sudo cp -P "$ver"/x86_64/lib/lib* /usr/lib/x86_64-linux-gnu/ |
| 174 | |
| 175 | echo "Done." |
| 176 | ``` |
| 177 | |
| 178 | ### Android |
| 179 | |
| 180 | If you are on Linux, make sure not to use the build done in the previous section. The GL renderer |
| 181 | disabled in the previous section is actually needed in this section. |
| 182 | |
| 183 | Define the following environment variables, for example in `.bashrc` (values are examples): |
| 184 | |
| 185 | ``` |
| 186 | export JAVA_HOME=/usr/local/buildtools/java/jdk |
| 187 | export ANDROID_SDK=$HOME/chromium/src/third_party/android_sdk/public |
| 188 | export ANDROID_NDK=$HOME/chromium/src/third_party/android_ndk |
| 189 | export ANDROID_NDK_HOME=$HOME/chromium/src/third_party/android_ndk |
| 190 | ``` |
| 191 | |
| 192 | In the renderdoc directory, create Android builds of RenderDoc: |
| 193 | |
| 194 | ``` |
| 195 | mkdir build-android-arm32 |
| 196 | cd build-android-arm32/ |
| 197 | cmake -DBUILD_ANDROID=On -DANDROID_ABI=armeabi-v7a .. |
| 198 | make -j |
| 199 | cd ../ |
| 200 | |
| 201 | mkdir build-android-arm64 |
| 202 | cd build-android-arm64/ |
| 203 | cmake -DBUILD_ANDROID=On -DANDROID_ABI=arm64-v8a .. |
| 204 | make -j |
| 205 | cd ../ |
| 206 | ``` |
| 207 | |
| 208 | Note that you need both arm32 and arm64 builds even if working with an arm64 device. See |
| 209 | [RenderDoc's documentation](https://github.com/baldurk/renderdoc/blob/v1.x/docs/CONTRIBUTING/Compiling.md#android) |
| 210 | for more information. |
| 211 | |
| 212 | When you run RenderDoc, choose the "Replay Context" from the bottom-left part of the UI (defaults to |
| 213 | Local). When selecting the device, you should see the RenderDoc application running. |
| 214 | |
| 215 | In ANGLE itself, make sure you add a suffix for its names to be different from the system's. Add |
| 216 | this to gn args: |
| 217 | |
| 218 | ``` |
| 219 | angle_libs_suffix = "_ANGLE_DEV" |
| 220 | ``` |
| 221 | |
| 222 | Next, you need to install an ANGLE test apk. When you build the test, a test launcher is generated, |
| 223 | for example, `./out/Release/bin/run_angle_end2end_tests`. The best way to install the APK is to run |
| 224 | this test launcher once. |
| 225 | |
| 226 | In RenderDoc, use `org.chromium.native_test` as the Executable Path, and provide the following |
| 227 | arguments: |
| 228 | |
| 229 | ``` |
| 230 | -e org.chromium.native_test.NativeTest.StdoutFile /sdcard/chromium_tests_root/out.txt -e org.chromium.native_test.NativeTest.CommandLineFlags "--gtest_filter=*ES2_VULKAN" |
| 231 | ``` |
| 232 | |
| 233 | Note that in the above, only a single command line argument is supported with RenderDoc. If testing |
| 234 | dEQP on a non-default platform, the easiest way would be to modify `GetDefaultAPIName()` in |
| 235 | `src/tests/deqp_support/angle_deqp_gtest.cpp` (and avoid `--use-angle=X`). |