ALSA, one of the two major Linux sound APIs, has a limitation in that each sound device can normally only be opened by one application at a time. This can be worked around by setting up the dmix plugin on your system (see The Den for more information on setting up the dmix plugin), and that is what we have typically recommended. However, dmix is often not set up by default, and that defeats our desire to work "out-of-the-box" as much as possible. This affects any game which tries to open the sound device multiple times - for example, Steam can do so with the recently added "friends" support due to the associated voice chat feature. That can result in games being unable to launch at all, or launching but without sound support. Similarly, some games such as EVE Online will restart themselves in certain circumstances, and if the original copy hasn't shut down before the new one tries to grab the sound device, it can fail to start.
It turns out that many sound cards will export multiple devices in ALSA which can be used simultaneously. We have thus taught our ALSA back-end to recognize them and try to make use of them if necessary. We've also put in a more complete fallback path for trying different device names as well instead of requiring the user to specify them manually in many circumstances. This results in a more robust ALSA back-end and a more seamless user experience overall, and it should now "just work" in more cases.
As part of ongoing graphical work, we examined and revised our method of copying textures when using FBOs (Framebuffer Objects). Copying textures is necessary when games perform operations such as rendering things offscreen which they then want to apply in part or in full to another texture. Direct3D provides applications quite a few ways to do this, and some of our methods weren't nearly as efficient as they could have been. Optimizing this section of code has yielded noticeable frame-rate improvements in a number of games since some games use these types of operations very frequently. This has also improved the performance of many games that use multisampling. As an example, Oblivion performance has increased 10-20% overall, with the frame-rate at the menus doubling.
We've done a fair amount of work to reorganize how our shaders are parsed. Basically, whenever an application gives Direct3D a vertex or pixel shader, it's encoded in a special binary format. Previously, we had separate front-end and back-end code to deal with this, in one area to figure out the length, and in another to actually read it in for conversion. In anticipation of Shader Model 3.0 support, we've been consolidating the two into one shared chunk of code. By having all this code in one place, we hope to minimize any duplication of effort that would be required in adding new functionality for reading in Shader Model 3.0 shaders.
In conjunction with this, we've worked up a test case infrastructure for testing this shared chunk of code. This allows us to check, after each improvement we make, whether or not we've broken any of hundreds of supported shaders of all versions and flavours. We believe this will allow us to catch regressions in this code very early, speeding up development and minimizing the impact on already-supported games.
As mentioned in last month's development report, we recently added support for opening directory handles via CreateFile. Sometimes, paradoxically, adding a new feature can cause a game to break, even when there aren't bugs in that feature. Once City of Heroes noticed that it could open directories, it then expected to be able to use the peripherally-related feature of I/O completion ports on directory handles. Since we didn't have support for that feature, the game no longer started. So, we have now extended the I/O completion work we did a while ago for sockets so that file and directory handles are now supported as well. As a result, City of Heroes is once again happy.
Finally, the process of optimizing game performance is often a long and drawn-out process. Typically there's lots of trial and error involved, going down paths which lead to dead-ends, breaking lots of stuff and as a result only getting a few percent performance improvement for one's efforts. However, sometimes we'll find that a game is doing something atypical and is resulting in one particular function being a major bottleneck. Such was the case with Need for Speed: Carbon. We noticed one system function being called a whole lot and being particularly slow, and the value that was being set was not being changed between calls. So, with some judicious caching, the overall performance of that title increased on the order of 30%, with parts running 2-3 times faster. One never knows what will be found!
Mark Adams
Development Manager
TransGaming Technologies
Broadening The Playing Field