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