• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
42   * Example: `ANGLE_CAPTURE_OUT_DIR=samples/capture_replay`. Default is the CWD.
43 * `ANGLE_CAPTURE_FRAME_START=<n>`:
44   * Uses mid-execution capture to write "Setup" functions that starts a Context at frame `n`.
45   * Example: `ANGLE_CAPTURE_FRAME_START=2`. Default is `0`.
46 * `ANGLE_CAPTURE_FRAME_END=<n>`:
47   * Example: `ANGLE_CAPTURE_FRAME_END=4`. Default is `0` which disables capture.
48 * `ANGLE_CAPTURE_LABEL=<label>`:
49   * When specified, files and functions will be labeled uniquely.
50   * Example: `ANGLE_CAPTURE_LABEL=foo`
51     * Results in filenames like this:
52       ```
53       foo.angledata.gz
54       foo_context1_001.cpp
55       foo_context1_002.cpp
56       foo_context1_003.cpp
57       foo_context1.cpp
58       foo_context1.h
59       foo.json
60       foo_shared.cpp
61       ...
62       ```
63 * `ANGLE_CAPTURE_SERIALIZE_STATE`:
64   * Set to `1` to enable GL state serialization. Default is `0`.
65
66A good way to test out the capture is to use environment variables in conjunction with the sample
67template. For example:
68
69```
70$ ANGLE_CAPTURE_FRAME_END=4 ANGLE_CAPTURE_OUT_DIR=samples/capture_replay out/Debug/simple_texture_2d --use-angle=vulkan
71```
72
73## Running the capture_replay sample (desktop only)
74
75To run a sample replay you can use a template located in
76[samples/capture_replay](../samples/capture_replay). First run your sample and ensure all capture
77files are written to `samples/capture_replay`. You can conveniently use `ANGLE_CAPTURE_OUT_DIR`.
78Make sure `ANGLE_CAPTURE_LABEL` is left unset during capture to use the default file names.
79Then enable the `capture_replay_sample` via `gn args`:
80
81```
82angle_build_capture_replay_sample = true
83```
84
85See [samples/BUILD.gn](../samples/BUILD.gn) for details. Then build and run your replay sample:
86
87```
88$ autoninja -C out/Debug capture_replay_sample
89$ out/Debug/capture_replay_sample
90```
91
92## Running a perf test replay (all platforms, including Android)
93
94To run your capture on any platform (Windows, Linux, Android, Mac (untested)), you'll need to
95compile it as part of ANGLE's Trace Replay harness, which is part of `angle_perftests`.
96
97Create a folder under `src/tests/restricted_traces` that matches the `ANGLE_CAPTURE_LABEL` you
98used above.
99
100Place all the trace output files into it.  For example, if the label was `desktop_test`:
101```
102src/tests/restricted_traces$ ls -1 desktop_test/
103desktop_test.angledata.gz
104desktop_test_context1_001.cpp
105desktop_test_context1_002.cpp
106desktop_test_context1_003.cpp
107desktop_test_context1.cpp
108desktop_test_context1.h
109desktop_test.json
110desktop_test_shared.cpp
111```
112Then add the label of your trace to
113[restricted_traces.json](../src/tests/restricted_traces/restricted_traces.json).
114Note it includes a version with the string.  Just use the number `1` for local changes.
115```
116     "dead_trigger_2 1",
117+    "desktop_test 1",
118     "disney_tsum_tsum 5",
119```
120Now you should be able to compile and run the perf test including your trace:
121```
122autoninja -C out/Debug angle_perftests
123ANGLE_CAPTURE_ENABLED=0 out/Debug/angle_perftests --gtest_filter="*desktop_test*" --verbose
124```
125## Capturing an Android application
126
127In order to capture on Android, the following additional steps must be taken. These steps
128presume you've built and installed the ANGLE APK with capture enabled, and selected ANGLE
129as the GLES driver for your application.
130
1311. Create the output directory
132
133    Determine your package name:
134    ```
135    export PACKAGE_NAME com.android.gl2jni
136    ```
137    Then create an output directory that it can write to:
138    ```
139    $ adb shell mkdir -p /sdcard/Android/data/$PACKAGE_NAME/angle_capture
140    ```
141
1422. Set properties to use for environment variable
143
144    On Android, it is difficult to set an environment variable before starting native code.
145    To work around this, ANGLE will read debug system properties before starting the capture
146    and use them to prime environment variables used by the capture code.
147
148    Note: Mid-execution capture doesn't work for Android just yet, so frame_start must be
149    zero, which is the default. This it is sufficient to only set the end frame.
150    ```
151    $ adb shell setprop debug.angle.capture.frame_end 200
152    ```
153
154    There are other properties that can be set that match 1:1 with the env vars, but
155    they are not required for capture:
156    ```
157    # Optional
158    $ adb shell setprop debug.angle.capture.enabled 0
159    $ adb shell setprop debug.angle.capture.out_dir foo
160    $ adb shell setprop debug.angle.capture.frame_start 0
161    $ adb shell setprop debug.angle.capture.label bar
162    ```
163
1643.  Run the application, then pull the files to the capture_replay directory
165    ```
166    $ cd samples/capture_replay
167    $ adb pull /sdcard/Android/data/$PACKAGE_NAME/angle_capture replay_files
168    $ cp replay_files/* .
169    ```
170
1714. Update your GN args to specifiy which context will be replayed.
172
173    By default Context ID 1 will be replayed. On Android, Context ID 2 is more typical, some apps
174    we've run go as high as ID 6.
175    Note: this solution is temporary until EGL capture is in place.
176    ```
177    angle_capture_replay_sample_context_id = 2
178    ```
179
1805. Replay the capture on desktop
181
182    Until we have samples building for Android, the replay sample must be run on desktop.
183    We will also be plumbing replay files into perf and correctness tests which will run on Android.
184    ```
185    $ autoninja -C out/Release capture_replay_sample
186    $ out/Release/capture_replay_sample
187    ```
188
189### Starting capture at an arbitrary frame
190In some scenarios, you don't know which frame you want to start on. You'll only know when target
191content is being rendered.  For that we've added a trigger that can allow starting the capture at
192any time.
193
194To use it, set the following environment variable, in addition to all the setup steps above. Set
195the trigger value equal to the number of frames you'd like to capture.
196```
197adb shell setprop debug.angle.capture.trigger 20
198```
199When this value is set, `ANGLE_CAPTURE_FRAME_START` and `ANGLE_CAPTURE_FRAME_END` will be ignored.
200
201While your content is rendering, wait until you arrive at the scene you'd like to capture. Then
202set the value back to zero:
203```
204adb shell setprop debug.angle.capture.trigger 0
205```
206ANGLE will detect this change and start recording the requested number of frames.
207
208## Testing
209
210### Regression Testing Architecture
211The [python script][link_to_python_script] uses the job queue pattern. We spawn n-1 independent
212worker processes, where n is the value returned by multiprocessing.cpu_count(). Whenever a worker
213process finishes a job and becomes available, it grabs the next job from a shared job queue and
214runs that job on its CPU core. When there are no more jobs in the queue, the worker processes
215terminate and the main process reports results.
216
217![Point-in-time snapshot of the job queue](img/RegressionTestingArchitecture.png)
218
219### Job unit
220A job unit is a test batch. Each test has to go through 3 stages: capture run, replay build, and
221replay run. The test batch batches the replay build stage of multiple tests together, and the
222replay run stage of multiple tests together.
223
224![A test batch as a job unit](img/JobUnit.png)
225
226### Running tests
227From the command line, navigate to the ANGLE root folder [angle][angle_folder] then run the
228command below:
229```
230python3 src/tests/capture_replay_tests.py --use-goma --gtest_filter=*/ES2_Vulkan --keep-temp-files --output-to-file --batch-count=8
231```
232
233* `--use-goma` to turn on/off building with goma
234* `--gtest_filter` to run only specific tests
235* `--keep-temp-files` to keep the trace files
236* `--output-to-file` to write the log to results.txt at
237 [src/tests/capture_replay_tests][capture_replay_test_folder] folder.
238* `--batch-count` to set the number of tests in a batch. More tests in a batch means that
239the tests will finish faster, but also means a lower level of granularity.
240All command line arguments can be found at the top of the [python script][link_to_python_script].
241
242[angle_folder]: ../
243[capture_replay_test_folder]: ../src/tests/capture_replay_tests/
244[link_to_python_script]: ../src/tests/capture_replay_tests.py
245[CaptureTrigger]: ../src/tests/restricted_traces/README.md#trigger-the-capture
246