Carl Worth [Wed, 12 Jun 2013 23:22:06 +0000 (16:22 -0700)]
Fix to actually load the real libGL.so when the application asks for it.
Our wrapper library intercepts calls to dlopen "libGL.so" and returns
a handle to itself. That's correct, and as intended.
Before doing this, however, it's essential to actual dlopen "libGL.so"
for real even though we won't be returning a handle to it. This
ensures that any side effects from that dlopen are taken care of.
This fixes a bug where "fips apitrace replay foo.trace" would cause
Mesa to fail to load its driver as follows (with LIBGL_DEBUG=verbose):
Carl Worth [Wed, 12 Jun 2013 00:18:12 +0000 (17:18 -0700)]
Switch from glGetQueryObjectiv to glGetQueryObjectuiv
The latter is available in OpenGL ES 3 while the former is not.
We don't really care about the signedness either way, (we're fetching
a Boolean), so sticking consistently to the unsigned version provides
better portability with no downside.
Carl Worth [Mon, 10 Jun 2013 21:40:43 +0000 (14:40 -0700)]
Add a new GLWRAP_DEFER_WITH_RETURN macro.
This allows for the elimination of some code duplication from our
implementation of glXGetPrcAddressARB. The previous implementation
duplicated code from glwrap_lookup simply because the GLWRAP_DEFER
macro did not provide access to the return value of the wrapped
function.
With the new macro, (very much like GLWRAP_DEFER but accepting a
parameter for a variable to accept the return value), we can eliminate
this code duplication.
Of course, our symbol-extraction script is now a bit more complicated
since it has to find occurrences of DEFER_WITH_RETURN in addition to
occurrences of DEFER, and pull out the function name as the second
argument rather than the first.
Carl Worth [Mon, 10 Jun 2013 21:34:26 +0000 (14:34 -0700)]
Remove typedef for fips_glXGetProcAddressARB_t
There were two problems with this typedef. First, we don't actually
need it, (we define it here and then use it exactly once on the next
line---it's simpler to have the direct syntax for a function returning
a pointer to a function accepting void and returning void.
More importantly, the typedef was relying on the type __GLXextFuncPtr
being defined. This happens to work with Mesa on my system but is
inherently fragile. So the code is more robust not relying on this.
Carl Worth [Thu, 30 May 2013 22:10:15 +0000 (15:10 -0700)]
Makefile: Automatically generate libfips.sym symbol map
Previously, we had to manually maintain this table of symbols, (hence
it was too easy for the list to be stale). Instead, we now generate
the list automatically by examining the source code for symbols that
are wrapped.
These were previously commented out with a "FIXME" comment. I don't
recall now what original problem I ran into when trying to add these,
but they seem to work fine now.
Carl Worth [Thu, 30 May 2013 21:05:08 +0000 (14:05 -0700)]
metrics: Collect new timer-query results before report
The timers from the most-recently-completed frame may not yet be
complete, but still, for the most accurate reports, we now collect all
available timer values before printing the report.
Carl Worth [Thu, 30 May 2013 19:55:26 +0000 (12:55 -0700)]
dlwrap: Fix dlwrap_real_dlopen to only perform dlsym-lookup once
Making the real_dlopen variable static means that we perform the dlysm
lookup only once and then re-use the result for later calls. This is
what was always intended for this code.
Carl Worth [Fri, 24 May 2013 18:11:15 +0000 (11:11 -0700)]
Avoid inserting timer queries while constructing a display list
We only want to time actual drawing operations. When between glNewList
and glEndList, calls that look like drawing operations are not really,
instead these are just calls that are being recorded to be later
executed with glCallList. (And it won't work to put our timer queries
inside the display list.)
So, track when we are within glNewList/glEndList and don't add timer
queries. Instead, we will time these operations as a whole with a
timer query around the glCallList call itself.
Carl Worth [Thu, 23 May 2013 21:22:42 +0000 (14:22 -0700)]
Add several missing symbols to the libfips symbol map.
I'm not sure why these weren't added before, but without these in the
map, these calls were not being successfully wrapped, so these calls
were not being timed as they should have been.
In the future we should automatically generate the symbol list to
avoid any similar problems.
Carl Worth [Mon, 6 May 2013 18:57:24 +0000 (11:57 -0700)]
Remove useless fork before executing wrapped program.
The fork did nothing for us since the parent simply waited on the child
and then exited. It's simpler to simply exec the wrapped program, (which
simplifies running fips within a debugger, etc.).
Carl Worth [Mon, 6 May 2013 18:18:33 +0000 (11:18 -0700)]
Move metrics-tracking code from glwrap.c to new metrics.c
We're moving toward having separate *wrap.c files for each flavor of GL,
(glwrap.c, glxwrap.c, and eglwrap.c). But this metrics-tracking code is
generic to all of those so belongs in a separate module.
Carl Worth [Thu, 2 May 2013 21:33:12 +0000 (14:33 -0700)]
Reduce code duplication with with new 'glwrap_lookup' function.
We already had two copies of 'lookup', (and were anticipating additional
modules which needed it as well). The DEFER macro is now also exported
as GLWRAP_DEFER for use in additional modules.
Carl Worth [Mon, 29 Apr 2013 21:54:52 +0000 (14:54 -0700)]
configure: Add checks for GL/gl.h
Previously, the compile would just forge ahead assuming GL/gl.h was present.
Now, at configure time, actually look for gl.h, (first, by looking for
a pkg-config "gl" package, otherwise, trying to just test-compile
something with a #include <GL/gl.h>).
If things aren't found at configure time, tell the user which packages
to install.
Carl Worth [Mon, 29 Apr 2013 20:23:58 +0000 (13:23 -0700)]
Fix glwrap.c to workaround 'const' changes in OpenGL headers.
Not all OpenGL headers are created equal. Some include more "const"
keywords than others, and we don't know wheter the headers we are
compiling against include the extra "const". We force all to be equal
by using the preprocessor to remove all "const" keywords altogether.
And in each wrapper we fire of a glBeginQuery/glEndQuery measurement around
the call to measure how much GPU time is consumed by the call. At the end
of each frame, we capture all available query results and accumulate those
into per-shader-program counters based on the currently active program,
(which we track by wrapping glUseProgram and glUseProgramObjectARB).
Finally, every 60 frames, we print out a simple report showing the
accumulated time for each shader program.
The report could very easily become more sophisticated. Here are some
obvious ideas:
1. Sort the report so that the most active shaders are reported first
2. Come up with some real units for the report values rather than mega-ticks
3. Report relative execution time as percentages
4. Clear the screen for each report, (with ncurses)
5. Dump the source for the shaders themselves to a file for easy inspection
Without any of the above, things are fairly raw for now, but are
perhaps still useful.
Carl Worth [Thu, 25 Apr 2013 05:55:01 +0000 (22:55 -0700)]
Generalize glXGetProcAddressARB wrapper to work for all wrapper functions
The originally implementation here had a whitelist of function names for
which we would return a wrapped symbol, (a very short whitelist consisting
only of "glXSwapBuffers"). A hard-coded list here would be a maintenance
nightmare.
Instead, we now simply perform a dlsym lookup on the wrapper library itself
and if there's a function that exists in the library matching the name
being requested, we return that.
This way we can add functions to our wrapper library without needing to
change the implementation of glXGetProcAddressARB at all.
Carl Worth [Wed, 24 Apr 2013 22:28:43 +0000 (15:28 -0700)]
Add a simple fips.h file.
This pulls in a few widely-used header files, (config.h, stdio.h,
stdlib.h, and string.h), and also gives us a place to define common
macros such as unused and STRNCMP_LITERAL.
Carl Worth [Wed, 24 Apr 2013 08:08:54 +0000 (01:08 -0700)]
Append to, rather than replace, the LD_PRELOAD value.
This is more polite for running things such as Steam games where there
is already an LD_PRELOAD value in place. This way, both the Steam overlay
and fips can get along happily.
Carl Worth [Wed, 24 Apr 2013 07:58:26 +0000 (00:58 -0700)]
Add wrappers for dlopen, dlsym, and glXGetProcAddressARB
This allows for many applications to start working with fips that would not
work before. Specifically, applications that dlopen libGL.so.1 instead of
directly linking with it would previously bypass fips' attempts to wrap
GL calls.
With these new wrappers carefully in place, many applications now work.
I've verified the following applications at least:
apitrace replay
NightSkyHD, a Humble Bundle game, both 32 and 64-bit versions
World of Goo, via Steam
I was also happy to notice that the Steam overlay does not cause fips
any difficulties.
Carl Worth [Wed, 24 Apr 2013 00:47:20 +0000 (17:47 -0700)]
Fix fips to work without requiring an absolute path for program to run.
With the latest commit that examines the ELF header of the program to
run fips was suddenly requiring that the absolute path of the program
be provided. This was obvisouly not desired.
It's simple enough to search through the PATH environment variable to
find the absolute path of the program to be run and examine that.
Carl Worth [Wed, 24 Apr 2013 00:25:13 +0000 (17:25 -0700)]
Compile both 32-bit and 64-bit versions of the wrapper library.
This is intended to make it transparent to run fips with either a
32-bit or a 64-bit program. And it does do that once you successfully
build both versions of the library.
Actually being able to build both versions of the library is a little
tricky though. Here are some of the tricks:
1. You will need to have installed both a 32-bit and a 64-bit .so file
for each dependent library, (currently libelf and libtalloc).
The current configure script doesn't check for both versions, so
you don't get a lot of guidance here. And that's because...
2. On Debian, at least, one cannot currently install both
libtalloc-dev:amd64 and libtalloc-dev:i386 at the same time.
Contrast with libelf-dev:i386 and libelf-dev:amd64 which work just
fine when installed simultaneously.
One can work around this by just install libtalloc-dev:amd64 and then
manually creating the link you need for the i386 package. Namely:
Carl Worth [Tue, 23 Apr 2013 21:17:33 +0000 (14:17 -0700)]
Start wrapping OpenGL, and print periodic FPS value to stdout.
In addition to the fips binary, we now also compile a libfips.so library
and LD_PRELOAD that before executing the program specified on the command-
line.
The libfips.so library wraps OpenGL calls of interest for purpose of
instrumentation. So far, the only call wrapped is glXSwapBuffers and
the only instrumentation is to compute and print out a frames-per-second
value every 60 frames.