1# ANGLE OpenGL Frame Capture and Replay 2 3ANGLE currently supports a limited OpenGL capture and replay framework. 4 5Limitations: 6 7 * GLES capture has many unimplemented functions. 8 * EGL capture and replay is not yet supported. 9 * Mid-execution capture is supported with the Vulkan back-end. 10 * Mid-execution capture has many unimplemented features. 11 * Capture and replay is currently only tested on desktop platforms. 12 * Binary replay is unimplemented. CPP replay is supported. 13 14## Capturing and replaying an application 15 16To build ANGLE with capture and replay enabled update your GN args: 17 18``` 19angle_with_capture_by_default = true 20``` 21 22Once built with capture enabled by default, ANGLE supports capturing OpenGL ES calls to CPP replay 23files. To enable capture, set the `ANGLE_CAPTURE_FRAME_START` and `ANGLE_CAPTURE_FRAME_END` 24environment variables to define a capture frame range, or use the [capture trigger 25property][CaptureTrigger] on Android. By default the replay will be stored in the current working 26directory. The capture files will be named according to the pattern 27`angle_capture_context{id}_frame{n}.cpp`. Each GL Context currently has its own replay sources. 28ANGLE will write out data binary blobs for large Texture or Buffer contents to 29`angle_capture_context{id}_frame{n}.angledata`. Replay programs must be able to load data from the 30corresponding `angledata` files. 31 32## Controlling Frame Capture 33 34Some simple environment variables control frame capture: 35 36 * `ANGLE_CAPTURE_ENABLED`: 37 * Set to `0` to disable capture entirely. Default is `1`. 38 * `ANGLE_CAPTURE_COMPRESSION`: 39 * Set to `0` to disable capture compression. Default is `1`. 40 * `ANGLE_CAPTURE_OUT_DIR=<path>`: 41 * Can specify an alternate replay output directory. This can either be an 42 absolute path, or relative to CWD. 43 * Example: `ANGLE_CAPTURE_OUT_DIR=samples/capture_replay`. Default is the CWD. 44 * `ANGLE_CAPTURE_FRAME_START=<n>`: 45 * Uses mid-execution capture to write "Setup" functions that starts a Context at frame `n`. 46 * Example: `ANGLE_CAPTURE_FRAME_START=2`. Default is `0`. 47 * `ANGLE_CAPTURE_FRAME_END=<n>`: 48 * Example: `ANGLE_CAPTURE_FRAME_END=4`. Default is `0` which disables capture. 49 * `ANGLE_CAPTURE_LABEL=<label>`: 50 * When specified, files and functions will be labeled uniquely. 51 * Example: `ANGLE_CAPTURE_LABEL=foo` 52 * Results in filenames like this: 53 ``` 54 foo.angledata.gz 55 foo_context1_001.cpp 56 foo_context1_002.cpp 57 foo_context1_003.cpp 58 foo_context1.cpp 59 foo_context1.h 60 foo.json 61 foo_shared.cpp 62 ... 63 ``` 64 * `ANGLE_CAPTURE_SERIALIZE_STATE`: 65 * Set to `1` to enable GL state serialization. Default is `0`. 66 67A good way to test out the capture is to use environment variables in conjunction with the sample 68template. For example: 69 70``` 71$ ANGLE_CAPTURE_FRAME_END=4 ANGLE_CAPTURE_OUT_DIR=samples/capture_replay out/Debug/simple_texture_2d --use-angle=vulkan 72``` 73 74## Running the capture_replay sample (desktop only) 75 76To run a sample replay you can use a template located in 77[samples/capture_replay](../samples/capture_replay). First run your sample and ensure all capture 78files are written to `samples/capture_replay`. You can conveniently use `ANGLE_CAPTURE_OUT_DIR`. 79Make sure `ANGLE_CAPTURE_LABEL` is left unset during capture to use the default file names. 80Then enable the `capture_replay_sample` via `gn args`: 81 82``` 83angle_build_capture_replay_sample = true 84``` 85 86See [samples/BUILD.gn](../samples/BUILD.gn) for details. Then build and run your replay sample: 87 88``` 89$ autoninja -C out/Debug capture_replay_sample 90$ out/Debug/capture_replay_sample 91``` 92 93## Running a perf test replay (all platforms, including Android) 94 95To run your capture on any platform (Windows, Linux, Android, Mac (untested)), you'll need to 96compile it as part of ANGLE's Trace Replay harness, which is part of `angle_perftests`. 97 98Create a folder under `src/tests/restricted_traces` that matches the `ANGLE_CAPTURE_LABEL` you 99used above. 100 101Place all the trace output files into it. For example, if the label was `desktop_test`: 102``` 103src/tests/restricted_traces$ ls -1 desktop_test/ 104desktop_test.angledata.gz 105desktop_test_context1_001.cpp 106desktop_test_context1_002.cpp 107desktop_test_context1_003.cpp 108desktop_test_context1.cpp 109desktop_test_context1.h 110desktop_test.json 111desktop_test_shared.cpp 112``` 113Then add the label of your trace to 114[restricted_traces.json](../src/tests/restricted_traces/restricted_traces.json). 115Note it includes a version with the string. Just use the number `1` for local changes. 116``` 117 "dead_trigger_2 1", 118+ "desktop_test 1", 119 "disney_tsum_tsum 5", 120``` 121Now you should be able to compile and run the perf test including your trace: 122``` 123autoninja -C out/Debug angle_perftests 124ANGLE_CAPTURE_ENABLED=0 out/Debug/angle_perftests --gtest_filter="*desktop_test*" --verbose 125``` 126## Capturing an Android application 127 128For more comprehensive Android capture/replay documentation, see 129the [restricted_traces README file](../src/tests/restricted_traces/README.md). 130 131In order to capture on Android, the following additional steps must be taken. These steps 132presume you've built and installed the ANGLE APK with capture enabled, and selected ANGLE 133as the GLES driver for your application. 134 1351. Create the output directory 136 137 Determine your package name: 138 ``` 139 export PACKAGE_NAME com.android.gl2jni 140 ``` 141 Then create an output directory that it can write to: 142 ``` 143 $ adb shell mkdir -p /sdcard/Android/data/$PACKAGE_NAME/angle_capture 144 $ adb shell chmod 777 /sdcard/Android/data/$PACKAGE_NAME/angle_capture 145 ``` 146 1472. Set properties to use for environment variables 148 149 On Android, it is difficult to set an environment variable before starting native code. 150 To work around this, ANGLE will read debug system properties before starting each capture 151 and use them to prime environment variables used by the capture code. 152 153 As with desktop captures, Android captures can be taken from a starting frame to an 154 ending frame or triggered at an arbitrary frame. 155 156 There are other properties that can be set that match 1:1 with the env vars, but 157 they are not required for capture: 158 ``` 159 # Optional 160 $ adb shell setprop debug.angle.capture.enabled 0 161 $ adb shell setprop debug.angle.capture.out_dir foo 162 $ adb shell setprop debug.angle.capture.frame_start 0 163 $ adb shell setprop debug.angle.capture.label bar 164 ``` 165 1663. Run the application, then pull the files to the capture_replay directory 167 ``` 168 $ cd samples/capture_replay 169 $ adb pull /sdcard/Android/data/$PACKAGE_NAME/angle_capture replay_files 170 $ cp replay_files/* . 171 ``` 172 1734. Update your GN args to specifiy which context will be replayed. 174 175 By default Context ID 1 will be replayed. On Android, Context ID 2 is more typical, some apps 176 we've run go as high as ID 6. 177 Note: this solution is temporary until EGL capture is in place. 178 ``` 179 angle_capture_replay_sample_context_id = 2 180 ``` 181 1825. Replay the capture on desktop 183 184 Until we have samples building for Android, the replay sample must be run on desktop. 185 We will also be plumbing replay files into perf and correctness tests which will run on Android. 186 ``` 187 $ autoninja -C out/Release capture_replay_sample 188 $ out/Release/capture_replay_sample 189 ``` 190 191### Starting capture at an arbitrary frame 192In some scenarios, you don't know which frame you want to start on. You'll only know when target 193content is being rendered. For that we've added a trigger that can allow starting captures at 194any time. 195 196To use it, set the following environment variable, in addition to all the setup steps above. Set 197the trigger value equal to the number of frames you'd like to capture. 198``` 199adb shell setprop debug.angle.capture.trigger 20 200``` 201When this value is set, `ANGLE_CAPTURE_FRAME_START` and `ANGLE_CAPTURE_FRAME_END` will be ignored. 202 203While your content is rendering, wait until you arrive at the scene you'd like to capture. Then 204set the value back to zero: 205``` 206adb shell setprop debug.angle.capture.trigger 0 207``` 208ANGLE will detect this change and start recording the requested number of frames, and the trace 209files will be written to OUT_DIR. 210 211Any number of traces can be captured in succession. After a trace has been captured, reset the TRIGGER 212to the number of frames to be captured, optionally reset the OUT_DIR location, and again set the 213trigger back to zero to begin the new trace. 214 215## Testing 216 217### Regression Testing Architecture 218The [python script][link_to_python_script] uses the job queue pattern. We spawn n-1 independent 219worker processes, where n is the value returned by multiprocessing.cpu_count(). Whenever a worker 220process finishes a job and becomes available, it grabs the next job from a shared job queue and 221runs that job on its CPU core. When there are no more jobs in the queue, the worker processes 222terminate and the main process reports results. 223 224 225 226### Job unit 227A job unit is a test batch. Each test has to go through 3 stages: capture run, replay build, and 228replay run. The test batch batches the replay build stage of multiple tests together, and the 229replay run stage of multiple tests together. 230 231 232 233### Running tests 234From the command line, navigate to the ANGLE root folder [angle][angle_folder] then run the 235command below: 236``` 237python3 src/tests/capture_replay_tests.py --gtest_filter=*/ES2_Vulkan --keep-temp-files --batch-count=8 238``` 239 240* `--gtest_filter` to run only specific tests 241* `--keep-temp-files` to keep the trace files 242* `--batch-count` to set the number of tests in a (capture) batch. More tests in a batch means that 243the tests will finish faster, but also means a lower level of granularity. 244All command line arguments can be found at the top of the [python script][link_to_python_script]. 245 246[angle_folder]: ../ 247[capture_replay_test_folder]: ../src/tests/capture_replay_tests/ 248[link_to_python_script]: ../src/tests/capture_replay_tests.py 249[CaptureTrigger]: ../src/tests/restricted_traces/README.md#trigger-the-capture 250