13 September 2008

Tracing Gallium3D

One nice thing about Gallium3D is that it provides a clean cut abstraction of (modern) 3D graphics hardware. The purpose of this abstraction is to allow a single hardware driver to target different graphic APIs (OpenGL, D3D, etc.). That is, one pipe driver for many state trackers.

But with this abstraction in place it opens the doors to other interesting things, unthinkable until now. Namely, by intercepting the calls between the state tracker and the pipe driver one could:

  • in a debugging scenario, capture the calls of an application known to cause problems to a file and analyze it, replay it in order to isolate the bug;
  • in a virtual machine scenario, capture all calls done inside a virtual machine and replay them in the host machine;
  • in a performance analysis scenario, compute memory/performance statistics in a per-call/resource;
  • etc.

Having an itch to scratch I started tackling the former, i.e., tracing Gallium3D for debugging purposes. Actually, an itch is an understatement, it is a rash named XP Direct3D. XP Direct3D driver model is in kernel space, and the build -> reboot -> upload driver -> test application cycle takes me between 5 and 10 min depending of the application. While in Linux building and testing from a NFS share takes me less than 1min. Recording a D3D application in XP and replay and debugging it on Linux would boost my productivity by 5 to 10 times. This assuming that the bug is on the pipe driver and not on the state tracker, which tends to be the case now that our state trackers are quite mature.

Using the learned lessons from my previous experiment of tracing D3D applications I wrote a pipe driver which traces all state tracker -> pipe driver interface calls to a XML file, and after an application written in Python to replay that file (using the Gallium3D Python bindings).

I chose a semantically rich XML as trace format so that the trace dumps are cross-platform and can at least survive minor interface changes such as addition/removal of state objects members, format renumbering, etc. This way traces can be also used for regression testing. Nevertheless the code is structured in such way that a space-efficient binary format is also possible in the future with minor changes.

Here is softpipe replaying a trace captured from trace of Mesa's gloss demo (also recorded on Linux).

Simple apps are capture/replayed (e.g., progs/trivial/*, progs/demos/gloss, and many D3D DirectX SDK examples), but big applications like 3DMark05 produce over 10GB of trace data before reaching the first frame, and I run out of disk space or patience before that. Also, some minor glitches in the interfaces prevent are causing some state to leak behind our back. So the next steps are to allow to capture a single arbitrary frame, improve trace format space efficiency, and trim the interface corners.

In case anybody gets interested, there are several README files in Mesa's git explaining how to use.


Anonymous said...

Very cool. Congrats.

Anonymous said...

I'm curious, is it possible to use Gallium3D as a graphics API? It looks very nice.

Current OpenGL standard is a trainwreck and DirectX is not portable.

José Fonseca said...

I'm curious, is it possible to use Gallium3D as a graphics API?

Our goal of supporting many graphics APIs (DX10, DX11, or even GPGPU APIs) will certainly drive interface changes. So although it is not impossible to use Gallium3D as a graphics API, it would be a moving target, which is not suitable for end-user applications.

But I believe it might make sense to use Gallium3D in some middleware in order to hardness the GPU capabilities more effectively. Younes Manton's generic GPU-accelerated video decoding library using Gallum3D is an example of that.

Anonymous said...

Just had a play with the trace driver... it appears that the trace driver for some reason depends on the i965 DRI-facing driver? I spent the last hour trying to figure out why no libGL got built, and in the end it came down to the line

and 'softpipe' and 'i965simple' and...

in the SConscript of /gallium/winsys/xlib

Is there a reason for that?

José Fonseca said...

Just had a play with the trace driver... it appears that the trace driver for some reason depends on the i965 DRI-facing driver? [...] Is there a reason for that?

gallium/winsys/xlib builds a drop-in replacement for libGl.so, and it is being used as a sandbox for all sort of new driver development, namelly: the experimental port of the i965 DRI driver to gallium, which at the moment does not use DRI, but targets some emulator; and the cell driver.

Indeed it shouldn't be use as a sandbox for everything, but it is so much simpler to do it that way...

I'll update the trace driver build instructions to build i965simple driver.

If you have any further problems, please post a mail to the Mesa3D development mailing list.

Rawler said...

Just a tip about trace format; after big initial hesitation, I've personally found Google Protocol Buffers to be quite pleasant to work with when I want fast extensible serialization. Space-effiency is reasonable, although compressed XML is better, but the main advantage is very low CPU-overhead.

It also allows for good forward-backward compatibility, and has acceptable cross-language support, including Python that I see you're comfortable with for data processing.