blob: 28d481cc9999710d8f3a49a1682e429aff622c80 [file] [log] [blame]
José Fonseca21278192015-01-20 14:27:04 +00001Basic usage
2===========
3
4Run the application you want to trace as
5
6 apitrace trace --api API /path/to/application [args...]
7
8and it will generate a trace named `application.trace` in the current
9directory. You can specify the written trace filename by passing the
10`--output` command line option.
11
12Problems while tracing (e.g, if the application uses calls/parameters
13unsupported by apitrace) will be reported via stderr output on Unices. On
14Windows you'll need to run
15[DebugView](http://technet.microsoft.com/en-us/sysinternals/bb896647) to view
16these messages.
17
José Fonseca91da6b52015-01-20 14:48:03 +000018If you cannot obtain a trace, check the [application specific instructions on
19the wiki](https://github.com/apitrace/apitrace/wiki/Applications), or the
20[manual tracing instructions below](#tracing-manually).
José Fonseca21278192015-01-20 14:27:04 +000021
22View the trace with
23
24 apitrace dump application.trace
25
26Replay an OpenGL trace with
27
28 apitrace replay application.trace
29
30Pass the `--sb` option to use a single buffered visual. Pass `--help` to
31`apitrace replay` for more options.
32
José Fonseca91da6b52015-01-20 14:48:03 +000033If you run into problems [check if it is a known issue and file an issue if
34not](BUGS.markdown).
35
José Fonseca21278192015-01-20 14:27:04 +000036
37Basic GUI usage
38===============
39
40Start the GUI as
41
42 qapitrace application.trace
43
44You can also tell the GUI to go directly to a specific call
45
46 qapitrace application.trace 12345
47
Jose Fonsecaa5255fd2015-01-26 14:38:39 +000048Press `Ctrl-T` to see per-frame thumbnails. And while inspecting frame calls,
49press again `Ctrl-T` to see per-draw call thumbnails.
50
José Fonseca21278192015-01-20 14:27:04 +000051
52Backtrace Capturing
53===================
54
José Fonseca91da6b52015-01-20 14:48:03 +000055apitrace now has the ability to capture the call stack to an OpenGL call on
56certain OSes (only Android and Linux at the moment). This can be helpful in
57determing which piece of code made that glDrawArrays call.
José Fonseca21278192015-01-20 14:27:04 +000058
59To use the feature you need to set an environment variable with the list of GL
60call prefixes you wish to capture stack traces to.
61
62 export APITRACE_BACKTRACE="glDraw* glUniform*"
63
64The backtrace data will show up in qapitrace in the bottom section as a new tab.
65
66
67Advanced command line usage
68===========================
69
70
71Call sets
72---------
73
74Several tools take `CALLSET` arguments, e.g:
75
76 apitrace dump --calls=CALLSET foo.trace
77 apitrace dump-images --calls=CALLSET foo.trace
78 apitrace trim --calls=CALLSET1 --calls=CALLSET2 foo.trace
79
80The call syntax is very flexible. Here are a few examples:
81
82 * `4` one call
83
84 * `0,2,4,5` set of calls
85
86 * `"0 2 4 5"` set of calls (commas are optional and can be replaced with whitespace)
87
88 * `0-100/2` calls 1, 3, 5, ..., 99
89
90 * `0-1000/draw` all draw calls between 0 and 1000
91
92 * `0-1000/fbo` all fbo changes between calls 0 and 1000
93
94 * `frame` all calls at end of frames
95
96 * `@foo.txt` read call numbers from `foo.txt`, using the same syntax as above
97
98
99
100Tracing manually
101----------------
102
103### Linux ###
104
105On 64 bits systems, you'll need to determine whether the application is 64 bits
106or 32 bits. This can be done by doing
107
108 file /path/to/application
109
110But beware of wrapper shell scripts -- what matters is the architecture of the
111main process.
112
113Run the GLX application you want to trace as
114
115 LD_PRELOAD=/path/to/apitrace/wrappers/glxtrace.so /path/to/application
116
117and it will generate a trace named `application.trace` in the current
118directory. You can specify the written trace filename by setting the
119`TRACE_FILE` environment variable before running.
120
121For EGL applications you will need to use `egltrace.so` instead of
122`glxtrace.so`.
123
124The `LD_PRELOAD` mechanism should work with the majority of applications. There
125are some applications (e.g., Unigine Heaven, Android GPU emulator, etc.), that
126have global function pointers with the same name as OpenGL entrypoints, living in a
127shared object that wasn't linked with `-Bsymbolic` flag, so relocations to
128those global function pointers get overwritten with the address to our wrapper
129library, and the application will segfault when trying to write to them. For
130these applications it is possible to trace by using `glxtrace.so` as an
131ordinary `libGL.so` and injecting it via `LD_LIBRARY_PATH`:
132
133 ln -s glxtrace.so wrappers/libGL.so
134 ln -s glxtrace.so wrappers/libGL.so.1
135 ln -s glxtrace.so wrappers/libGL.so.1.2
136 export LD_LIBRARY_PATH=/path/to/apitrace/wrappers:$LD_LIBRARY_PATH
137 export TRACE_LIBGL=/path/to/real/libGL.so.1
138 /path/to/application
139
140If you are an application developer, you can avoid this either by linking with
141`-Bsymbolic` flag, or by using some unique prefix for your function pointers.
142
143See the `ld.so` man page for more information about `LD_PRELOAD` and
144`LD_LIBRARY_PATH` environment flags.
145
146### Android ###
147
148To trace standalone native OpenGL ES applications, use
149`LD_PRELOAD=/path/to/egltrace.so /path/to/application` as described in the
150previous section. To trace Java applications, refer to Dalvik.markdown.
151
152### Mac OS X ###
153
154Run the application you want to trace as
155
156 DYLD_FRAMEWORK_PATH=/path/to/apitrace/wrappers /path/to/application
157
158Note that although Mac OS X has an `LD_PRELOAD` equivalent,
159`DYLD_INSERT_LIBRARIES`, it is mostly useless because it only works with
160`DYLD_FORCE_FLAT_NAMESPACE=1` which breaks most applications. See the `dyld` man
161page for more details about these environment flags.
162
163### Windows ###
164
165When tracing third-party applications, you can identify the target
166application's main executable, either by:
167
168* right clicking on the application's icon in the _Start Menu_, choose
169 _Properties_, and see the _Target_ field;
170
171* or by starting the application, run Windows Task Manager (taskmgr.exe), right
172 click on the application name in the _Applications_ tab, choose _Go To Process_,
173 note the highlighted _Image Name_, and search it on `C:\Program Files` or
174 `C:\Program Files (x86)`.
175
176On 64 bits Windows, you'll need to determine ether the application is a 64 bits
177or 32 bits. 32 bits applications will have a `*32` suffix in the _Image Name_
178column of the _Processes_ tab of _Windows Task Manager_ window.
179
180You also need to know which graphics API is being used. If you are unsure, the
181simplest way to determine what API an application uses is to:
182
183* download and run [Process Explorer](http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx)
184
185* search and select the application's process in _Process Explorer_
186
187* list the DLLs by pressing `Ctrl + D`
188
189* sort DLLs alphabetically, and look for the DLLs such as `opengl32.dll`,
190 `d3d9.dll`, `d3d10.dll`, etc.
191
192Copy the appropriate `opengl32.dll`, `d3d8.dll`, or `d3d9.dll` from the
193wrappers directory to the directory with the application you want to trace.
194Then run the application as usual.
195
196You can specify the written trace filename by setting the `TRACE_FILE`
197environment variable before running.
198
199For D3D10 and higher you really must use `apitrace trace -a DXGI ...`. This is
200because D3D10-11 API span many DLLs which depend on each other, and once a DLL
201with a given name is loaded Windows will reuse it for LoadLibrary calls of the
202same name, causing internal calls to be traced erroneously. `apitrace trace`
203solves this issue by injecting a DLL `dxgitrace.dll` and patching all modules
204to hook only the APIs of interest.
205
206
207Emitting annotations to the trace
208---------------------------------
209
210From within OpenGL applications you can embed annotations in the trace file
211through the following extensions:
212
213* [`GL_KHR_debug`](http://www.opengl.org/registry/specs/KHR/debug.txt)
214
215* [`GL_ARB_debug_output`](http://www.opengl.org/registry/specs/ARB/debug_output.txt)
216
217* [`GL_EXT_debug_marker`](http://www.khronos.org/registry/gles/extensions/EXT/EXT_debug_marker.txt)
218
219* [`GL_EXT_debug_label`](http://www.opengl.org/registry/specs/EXT/EXT_debug_label.txt)
220
221* [`GL_AMD_debug_output`](http://www.opengl.org/registry/specs/AMD/debug_output.txt)
222
223* [`GL_GREMEDY_string_marker`](http://www.opengl.org/registry/specs/GREMEDY/string_marker.txt)
224
225* [`GL_GREMEDY_frame_terminator`](http://www.opengl.org/registry/specs/GREMEDY/frame_terminator.txt)
226
227**apitrace** will advertise and intercept these OpenGL extensions regardless
228of whether the OpenGL implementation supports them or not. So all you have
229to do is to use these extensions when available, and you can be sure they
230will be available when tracing inside **apitrace**.
231
232For example, if you use [GLEW](http://glew.sourceforge.net/) to dynamically
233detect and use OpenGL extensions, you could easily accomplish this by doing:
234
235 void foo() {
236
237 if (GLEW_KHR_debug) {
238 glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, __FUNCTION__);
239 }
240
241 ...
242
243 if (GLEW_KHR_debug) {
244 glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_OTHER,
245 0, GL_DEBUG_SEVERITY_MEDIUM, -1, "bla bla");
246 }
247
248 ...
249
250 if (GLEW_KHR_debug) {
251 glPopDebugGroup();
252 }
253
254 }
255
256This has the added advantage of working equally well with other OpenGL debugging tools.
257
258Also, provided that the OpenGL implementation supports `GL_KHR_debug`, labels
259defined via glObjectLabel() , and the labels of several objects (textures,
260framebuffers, samplers, etc. ) will appear in the GUI state dumps, in the
261parameters tab.
262
263
264For OpenGL ES applications you can embed annotations in the trace file through the
265[`GL_KHR_debug`](http://www.khronos.org/registry/gles/extensions/KHR/debug.txt) or
266[`GL_EXT_debug_marker`](http://www.khronos.org/registry/gles/extensions/EXT/EXT_debug_marker.txt)
267extensions.
268
269
270For Direct3D applications you can follow the standard procedure for
271[adding user defined events to Visual Studio Graphics Debugger / PIX](http://msdn.microsoft.com/en-us/library/vstudio/hh873200.aspx):
272
273- `D3DPERF_BeginEvent`, `D3DPERF_EndEvent`, and `D3DPERF_SetMarker` for D3D9 applications.
274
275- `ID3DUserDefinedAnnotation::BeginEvent`,
276 `ID3DUserDefinedAnnotation::EndEvent`, and
277 `ID3DUserDefinedAnnotation::SetMarker` for D3D11.1 applications.
278
279
280Dump OpenGL state at a particular call
281----------------------------------
282
283You can get a dump of the bound OpenGL state at call 12345 by doing:
284
285 apitrace replay -D 12345 application.trace > 12345.json
286
287This is precisely the mechanism the GUI uses to obtain its own state.
288
289You can compare two state dumps by doing:
290
291 apitrace diff-state 12345.json 67890.json
292
293
294Comparing two traces side by side
295---------------------------------
296
297 apitrace diff trace1.trace trace2.trace
298
299This works only on Unices, and it will truncate the traces due to performance
300limitations.
301
302
303Recording a video with FFmpeg/Libav
304-----------------------------------
305
306You can make a video of the output with FFmpeg by doing
307
308 apitrace dump-images -o - application.trace \
309 | ffmpeg -r 30 -f image2pipe -vcodec ppm -i pipe: -vcodec mpeg4 -y output.mp4
310
311or Libav (which replaces FFmpeg on recent Debian/Ubuntu distros) doing
312
313 apitrace dump-images -o - application.trace \
314 | avconv -r 30 -f image2pipe -vcodec ppm -i - -vcodec mpeg4 -y output.mp4
315
316Recording a video with gstreamer
317--------------------------------------
318
319You can make a video of the output with gstreamer by doing
320
321 glretrace --snapshot-format=RGB -s - smokinguns.trace | gst-launch-0.10 fdsrc blocksize=409600 ! queue \
322 ! videoparse format=rgb width=1920 height=1080 ! queue ! ffmpegcolorspace ! queue \
323 ! vaapiupload direct-rendering=0 ! queue ! vaapiencodeh264 ! filesink location=xxx.264
324
325Trimming a trace
326----------------
327
328You can truncate a trace by doing:
329
330 apitrace trim --exact --calls 0-12345 -o trimed.trace application.trace
331
332If you need precise control over which calls to trim you can specify the
333individual call numbers in a plain text file, as described in the 'Call sets'
334section above.
335
336There is also experimental support for automatically trimming the calls
337necessary for a given frame or call:
338
339 apitrace trim --auto --calls=12345 -o trimed.trace application.trace
340 apitrace trim --auto --frames=12345 -o trimed.trace application.trace
341
342
343Profiling a trace
344-----------------
345
346You can perform gpu and cpu profiling with the command line options:
347
348 * `--pgpu` record gpu times for frames and draw calls.
349
350 * `--pcpu` record cpu times for frames and draw calls.
351
352 * `--ppd` record pixels drawn for each draw call.
353
354The results from these can then be read by hand or analyzed with a script.
355
356`scripts/profileshader.py` will read the profile results and format them into a
357table which displays profiling results per shader.
358
359For example, to record all profiling data and utilise the per shader script:
360
361 apitrace replay --pgpu --pcpu --ppd foo.trace | ./scripts/profileshader.py
362
363
364Advanced usage for OpenGL implementors
365======================================
366
367There are several advanced usage examples meant for OpenGL implementors.
368
369
370Regression testing
371------------------
372
373These are the steps to create a regression test-suite around **apitrace**:
374
375* obtain a trace
376
377* obtain reference snapshots, by doing on a reference system:
378
379 mkdir /path/to/reference/snapshots/
380 apitrace dump-images -o /path/to/reference/snapshots/ application.trace
381
382* prune the snapshots which are not interesting
383
384* to do a regression test, use `apitrace diff-images`:
385
386 apitrace dump-images -o /path/to/test/snapshots/ application.trace
387 apitrace diff-images --output summary.html /path/to/reference/snapshots/ /path/to/test/snapshots/
388
389
390Automated git-bisection
391-----------------------
392
393With tracecheck.py it is possible to automate git bisect and pinpoint the
394commit responsible for a regression.
395
396Below is an example of using tracecheck.py to bisect a regression in the
397Mesa-based Intel 965 driver. But the procedure could be applied to any OpenGL
398driver hosted on a git repository.
399
400First, create a build script, named build-script.sh, containing:
401
402 #!/bin/sh
403 set -e
404 export PATH=/usr/lib/ccache:$PATH
405 export CFLAGS='-g'
406 export CXXFLAGS='-g'
407 ./autogen.sh --disable-egl --disable-gallium --disable-glut --disable-glu --disable-glw --with-dri-drivers=i965
408 make clean
409 make "$@"
410
411It is important that builds are both robust, and efficient. Due to broken
412dependency discovery in Mesa's makefile system, it was necessary to invoke `make
413clean` in every iteration step. `ccache` should be installed to avoid
414recompiling unchanged source files.
415
416Then do:
417
418 cd /path/to/mesa
419 export LIBGL_DEBUG=verbose
420 export LD_LIBRARY_PATH=$PWD/lib
421 export LIBGL_DRIVERS_DIR=$PWD/lib
422 git bisect start \
423 6491e9593d5cbc5644eb02593a2f562447efdcbb 71acbb54f49089b03d3498b6f88c1681d3f649ac \
424 -- src/mesa/drivers/dri/intel src/mesa/drivers/dri/i965/
425 git bisect run /path/to/tracecheck.py \
426 --precision-threshold 8.0 \
427 --build /path/to/build-script.sh \
428 --gl-renderer '.*Mesa.*Intel.*' \
429 --retrace=/path/to/glretrace \
430 -c /path/to/reference/snapshots/ \
431 topogun-1.06-orc-84k.trace
432
433The trace-check.py script will skip automatically when there are build
434failures.
435
436The `--gl-renderer` option will also cause a commit to be skipped if the
437`GL_RENDERER` is unexpected (e.g., when a software renderer or another OpenGL
438driver is unintentionally loaded due to a missing symbol in the DRI driver, or
439another runtime fault).
440
441
442Side by side retracing
443----------------------
444
445In order to determine which draw call a regression first manifests one could
446generate snapshots for every draw call, using the `-S` option. That is, however,
447very inefficient for big traces with many draw calls.
448
449A faster approach is to run both the bad and a good OpenGL driver side-by-side.
450The latter can be either a previously known good build of the OpenGL driver, or a
451reference software renderer.
452
453This can be achieved with retracediff.py script, which invokes glretrace with
454different environments, allowing to choose the desired OpenGL driver by
455manipulating variables such as `LD_LIBRARY_PATH`, `LIBGL_DRIVERS_DIR`, or
456`TRACE_LIBGL`.
457
458For example, on Linux:
459
460 ./scripts/retracediff.py \
461 --ref-env LD_LIBRARY_PATH=/path/to/reference/OpenGL/implementation \
462 --retrace /path/to/glretrace \
463 --diff-prefix=/path/to/output/diffs \
464 application.trace
465
466Or on Windows:
467
468 python scripts\retracediff.py --retrace \path\to\glretrace.exe --ref-env TRACE_LIBGL=\path\to\reference\opengl32.dll application.trace
469
470
471Advanced GUI usage
472==================
473
474qapitrace has rudimentary support for replaying traces on a remote
475target device. This can be useful, for example, when developing for an
476embedded system. The primary GUI will run on the local host, while any
477replays will be performed on the target device.
478
479In order to target a remote device, use the command-line:
480
481 qapitrace --remote-target <HOST> <trace-file>
482
483In order for this to work, the following must be available in the
484system configuration:
485
4861. It must be possible for the current user to initiate an ssh session
487 that has access to the target's window system. The command to be
488 exectuted by qapitrace will be:
489
490 ssh <HOST> glretrace
491
492 For example, if the target device is using the X window system, one
493 can test whether an ssh session has access to the target X server
494 with:
495
496 ssh <HOST> xdpyinfo
497
498 If this command fails with something like "cannot open display"
499 then the user will have to configure the target to set the DISPLAY
500 environment variable, (for example, setting DISPLAY=:0 in the
501 .bashrc file on the target or similar).
502
503 Also, note that if the ssh session requires a custom username, then
504 this must be configured on the host side so that ssh can be
505 initiated without a username.
506
507 For example, if you normally connect with `ssh user@192.168.0.2`
508 you could configure ~/.ssh/config on the host with a block such as:
509
510 Host target
511 HostName 192.168.0.2
512 User user
513
514 And after this you should be able to connect with `ssh target` so
515 that you can also use `qapitrace --remote-target target`.
516
5172. The target host must have a functional glretrace binary available
518
5193. The target host must have access to <trace-file> at the same path
520 in the filesystem as the <trace-file> path on the host system being
521 passed to the qapitrace command line.