blob: c38804276664853db5256e8a87eee2ef044451b1 [file] [log] [blame]
José Fonseca0b217312011-06-30 14:32:57 +01001About **apitrace**
2==================
3
4**apitrace** consists of a set of tools to:
5
6* trace OpenGL, D3D9, D3D8, D3D7, and DDRAW APIs calls to a file;
7
8* retrace OpenGL calls from a file;
9
José Fonseca892cad62011-09-23 08:24:28 +010010* inspect OpenGL state at any call while retracing;
11
12* visualize and edit trace files.
José Fonseca0b217312011-06-30 14:32:57 +010013
14
José Fonseca6d617002011-09-06 01:17:48 +010015Basic usage
16===========
José Fonseca0b217312011-06-30 14:32:57 +010017
18
19Linux
20-----
21
22Run the application you want to trace as
23
24 LD_PRELOAD=/path/to/glxtrace.so /path/to/application
25
26and it will generate a trace named `application.trace` in the current
27directory. You can specify the written trace filename by setting the
28`TRACE_FILE` environment variable before running.
29
30View the trace with
31
32 /path/to/tracedump application.trace | less -R
33
34Replay the trace with
35
36 /path/to/glretrace application.trace
37
38Pass the `-sb` option to use a single buffered visual. Pass `--help` to
39glretrace for more options.
40
41Start the GUI as
42
43 /path/to/qapitrace application.trace
44
45
46The `LD_PRELOAD` mechanism should work with most applications. There are some
47applications, e.g., Unigine Heaven, which global function pointers with the
48same name as GL entrypoints, living in a shared object that wasn't linked with
49`-Bsymbolic` flag, so relocations to those globals function pointers get
50overwritten with the address to our wrapper library, and the application will
51segfault when trying to write to them. For these applications it is possible
52to trace by using `glxtrace.so` as an ordinary `libGL.so` and injecting into
53`LD_LIBRARY_PATH`:
54
55 ln -s glxtrace.so libGL.so
56 ln -s glxtrace.so libGL.so.1
57 ln -s glxtrace.so libGL.so.1.2
58 export LD_LIBRARY_PATH=/path/to/directory/where/glxtrace/is:$LD_LIBRARY_PATH
59 export TRACE_LIBGL=/path/to/real/libGL.so.1
60 /path/to/application
61
José Fonsecaed348d52011-07-04 10:20:42 +010062See the `ld.so` man page for more information about `LD_PRELOAD` and
José Fonseca0b217312011-06-30 14:32:57 +010063`LD_LIBRARY_PATH` environment flags.
64
José Fonsecacf61ced2011-07-02 15:42:57 +010065
José Fonseca0b217312011-06-30 14:32:57 +010066
67Mac OS X
68--------
69
70Usage on Mac OS X is similar to Linux above, except for the tracing procedure,
71which is instead:
72
73 DYLD_LIBRARY_PATH=/path/to/apitrace/wrappers /path/to/application
74
75Note that although Mac OS X has an `LD_PRELOAD` equivalent,
76`DYLD_INSERT_LIBRARIES`, it is mostly useless because it only works with
77`DYLD_FORCE_FLAT_NAMESPACE=1` which breaks most applications. See the `dyld` man
78page for more details about these environment flags.
79
80
81Windows
82-------
83
84* Copy `opengl32.dll`, `d3d8.dll`, or `d3d9.dll` from build/wrappers directory
85 to the directory with the application you want to trace.
86
87* Run the application.
88
89* View the trace with
90
José Fonsecaed348d52011-07-04 10:20:42 +010091 \path\to\tracedump application.trace
José Fonseca0b217312011-06-30 14:32:57 +010092
93* Replay the trace with
94
José Fonsecaed348d52011-07-04 10:20:42 +010095 \path\to\glretrace application.trace
José Fonseca0b217312011-06-30 14:32:57 +010096
97
José Fonseca6d617002011-09-06 01:17:48 +010098Advanced command line usage
99===========================
100
101
José Fonsecae62cabc2011-09-18 10:31:04 +0100102Emitting annotations to the trace from GL applications
103------------------------------------------------------
104
105You can emit string and frame annotations through the
106[`GL_GREMEDY_string_marker`](http://www.opengl.org/registry/specs/GREMEDY/string_marker.txt)
107and
108[`GL_GREMEDY_frame_terminator`](http://www.opengl.org/registry/specs/GREMEDY/frame_terminator.txt)
109GL extensions.
110
José Fonseca892cad62011-09-23 08:24:28 +0100111**apitrace** will advertise and intercept these GL extensions independently of
José Fonsecae62cabc2011-09-18 10:31:04 +0100112the GL implementation. So all you have to do is to use these extensions when
113available.
114
115For example, if you use [GLEW](http://glew.sourceforge.net/) to dynamically
116detect and use GL extensions, you could easily accomplish this by doing:
117
118 void foo() {
119
120 if (GLEW_GREMEDY_string_marker) {
121 glStringMarkerGREMEDY(0, __FUNCTION__ ": enter");
122 }
123
124 ...
125
126 if (GLEW_GREMEDY_string_marker) {
127 glStringMarkerGREMEDY(0, __FUNCTION__ ": leave");
128 }
129
130 }
131
132This has the added advantage of working equally well with gDEBugger.
133
134
José Fonseca6d617002011-09-06 01:17:48 +0100135Dump GL state at a particular call
136----------------------------------
137
138You can get a dump of the bound GL state at call 12345 by doing:
139
140 /path/to/glretrace -D 12345 application.trace > 12345.json
141
142This is precisely the mechanism the GUI obtains its own state.
143
144You can compare two state dumps with the jsondiff.py script:
145
146 ./scripts/jsondiff.py 12345.json 67890.json
147
148
149Comparing two traces side by side
150---------------------------------
151
152 ./scripts/tracediff.sh trace1.trace trace2.trace
153
154This works only on Unices, and it will truncate the traces due to performance
155limitations.
156
157
158Recording a video with FFmpeg
159-----------------------------
160
161You can make a video of the output by doing
162
163 /path/to/glretrace -s - application.trace \
164 | ffmpeg -r 30 -f image2pipe -vcodec ppm -i pipe: -vcodec mpeg4 -y output.mp4
165
166
167Advanced usage for OpenGL implementors
168======================================
169
José Fonsecaff427582011-09-18 10:49:13 +0100170There are several advanced usage examples meant for OpenGL implementors.
José Fonseca6d617002011-09-06 01:17:48 +0100171
172
173Regression testing
174------------------
175
José Fonseca892cad62011-09-23 08:24:28 +0100176These are the steps to create a regression test-suite around **apitrace**:
José Fonseca6d617002011-09-06 01:17:48 +0100177
178* obtain a trace
179
180* obtain reference snapshots, by doing:
181
182 mkdir /path/to/snapshots/
183 /path/to/glretrace -s /path/to/reference/snapshots/ application.trace
184
185 on reference system.
186
187* prune the snapshots which are not interesting
188
189* to do a regression test, do:
190
191 /path/to/glretrace -c /path/to/reference/snapshots/ application.trace
192
193 Alternatively, for a HTML summary, use the snapdiff script:
194
195 /path/to/glretrace -s /path/to/current/snapshots/ application.trace
196 ./scripts/snapdiff.py --output summary.html /path/to/reference/snapshots/ /path/to/current/snapshots/
197
198
199Automated git-bisection
200-----------------------
201
202With tracecheck.py it is possible to automate git bisect and pinpoint the
203commit responsible for a regression.
204
205Below is an example of using tracecheck.py to bisect a regression in the
206Mesa-based Intel 965 driver. But the procedure could be applied to any GL
207driver hosted on a git repository.
208
209First, create a build script, named build-script.sh, containing:
210
211 #!/bin/sh
212 set -e
213 export PATH=/usr/lib/ccache:$PATH
214 export CFLAGS='-g'
215 export CXXFLAGS='-g'
216 ./autogen.sh --disable-egl --disable-gallium --disable-glut --disable-glu --disable-glw --with-dri-drivers=i965
217 make clean
218 make "$@"
219
220It is important that builds are both robust, and efficient. Due to broken
221dependency discovery in Mesa's makefile system, it was necessary invoke `make
222clean` in every iteration step. `ccache` should be installed to avoid
223recompiling unchanged source files.
224
225Then do:
226
227 cd /path/to/mesa
228 export LIBGL_DEBUG=verbose
229 export LD_LIBRARY_PATH=$PWD/lib
230 export LIBGL_DRIVERS_DIR=$PWD/lib
231 git bisect start \
232 6491e9593d5cbc5644eb02593a2f562447efdcbb 71acbb54f49089b03d3498b6f88c1681d3f649ac \
233 -- src/mesa/drivers/dri/intel src/mesa/drivers/dri/i965/
234 git bisect run /path/to/tracecheck.py \
235 --precision-threshold 8.0 \
236 --build /path/to/build-script.sh \
237 --gl-renderer '.*Mesa.*Intel.*' \
238 --retrace=/path/to/glretrace \
239 -c /path/to/reference/snapshots/ \
240 topogun-1.06-orc-84k.trace
241
242The trace-check.py script will skip automatically when there are build
243failures.
244
245The `--gl-renderer` option will also cause a commit to be skipped if the
246`GL_RENDERER` is unexpected (e.g., when a software renderer or another GL
José Fonsecaff427582011-09-18 10:49:13 +0100247driver is unintentionally loaded due to missing symbol in the DRI driver, or
José Fonseca6d617002011-09-06 01:17:48 +0100248another runtime fault).
249
250
251Side by side retracing
252----------------------
253
254In order to determine which draw call a regression first manifests one could
José Fonseca05ba4192011-09-17 21:18:57 +0100255generate snapshots for every draw call, using the `-S` option. That is, however,
José Fonseca6d617002011-09-06 01:17:48 +0100256very inefficient for big traces with many draw calls.
257
258A faster approach is to run both the bad and a good GL driver side-by-side.
José Fonsecaff427582011-09-18 10:49:13 +0100259The latter can be either a previously known good build of the GL driver, or a
José Fonseca6d617002011-09-06 01:17:48 +0100260reference software renderer.
261
262This can be achieved with retracediff.py script, which invokes glretrace with
263different environments, allowing to choose the desired GL driver by
264manipulating variables such as `LD_LIBRARY_PATH` or `LIBGL_DRIVERS_DIR`.
265
266For example:
267
268 ./scripts/retracediff.py \
269 --ref-env LD_LIBRARY_PATH=/path/to/reference/GL/implementation \
270 -r ./glretrace \
271 --diff-prefix=/path/to/output/diffs \
272 application.trace
273
274
275
José Fonseca0b217312011-06-30 14:32:57 +0100276Links
277=====
278
279About **apitrace**:
280
Zack Rusind029d5f2011-08-22 21:50:08 -0400281* [Official mailing list](http://lists.freedesktop.org/mailman/listinfo/apitrace)
282
José Fonseca0b217312011-06-30 14:32:57 +0100283* [Zack Rusin's blog introducing the GUI](http://zrusin.blogspot.com/2011/04/apitrace.html)
284
285* [Jose's Fonseca blog introducing the tool](http://jrfonseca.blogspot.com/2008/07/tracing-d3d-applications.html)
286
287
288Direct3D
289--------
290
291Open-source:
292
293* [Proxy DLL](http://www.mikoweb.eu/index.php?node=21)
294
295 * [Intercept Calls to DirectX with a Proxy DLL](http://www.codeguru.com/cpp/g-m/directx/directx8/article.php/c11453/)
296
297* [Direct3D 9 API Interceptor](http://graphics.stanford.edu/~mdfisher/D3D9Interceptor.html)
298
299Closed-source:
300
301* [Microsoft PIX](http://msdn.microsoft.com/en-us/library/ee417062.aspx)
302
303 * [D3DSpy](http://doc.51windows.net/Directx9_SDK/?url=/directx9_sdk/graphics/programmingguide/TutorialsAndSamplesAndToolsAndTips/Tools/D3DSpy.htm): the predecessor of PIX
304
305* [AMD GPU PerfStudio](http://developer.amd.com/gpu/PerfStudio/pages/APITraceWindow.aspx)
306
307
308OpenGL
309------
310
311Open-source:
312
313* [BuGLe](http://www.opengl.org/sdk/tools/BuGLe/)
314
315* [GLIntercept](http://code.google.com/p/glintercept/)
316
317* [tracy](https://gitorious.org/tracy): OpenGL ES and OpenVG trace, retrace, and state inspection
318
319Closed-source:
320
321* [gDEBugger](http://www.gremedy.com/products.php)
322
323* [glslDevil](http://cumbia.informatik.uni-stuttgart.de/glsldevil/index.html)
324
325* [AMD GPU PerfStudio](http://developer.amd.com/gpu/PerfStudio/pages/APITraceWindow.aspx)
326