Wednesday, August 17, 2005

Another pygame release at last.

There is finally a new release for pygame out. I was the one who did this release(with lots of help from others), and below are some notes on how it went, and what is next for pygame.

What is pygame?

Pygame is a is a set of Python modules designed for writing games. It is written on top of the excellent SDL library. This allows you to create fully featured games and multimedia programs in the python language. Pygame is highly portable and runs on nearly every platform and operating system.

Compared to the 1.7.0 release, there is a whole bunch of bug fixes. Compared to the commonly used pygame 1.6.2 there are heaps of changes. A different version of SDL, a different compiler used for the windows version, and a rewrite of the sprite classes.

Lots of new people have begun to submit patches and test things out. Which is really nice. We also followed a release plan. Which was made necessary because of the multiple people working on the release compared to one person previously.

There is also a new website which allows people to register, and show people their projects using pygame. Along with the upcoming pyweek competition with over 150 entrants, pygame continues to live and grow.


What is there to do for the next release?

For me I want to improve what is already in pygame. I want to speed up some areas, and fix up any remaining bugs. For example pygame on linux requires X libraries. Where it should be able to just use the frame buffer.

One place that could do with speed improvements is the transform module. For things like scaling, rotation, flipping, and rotozooming.

I would like to make them quicker by improving the api, and by optimizing the C code, as well as doing asm versions.

However first we need benchmark programs for all of these features. Games can be used, as well as writing programs which stress test the features. For example a rotation benchmark which rotates 30 different images of different sizes, and then blits them to the screen. Another part of the test would be to rotate different same size images without blitting them.

Repeatable benchmarks are important to test the speed on different computers, and to compare between different versions of pygame. The benchmarks can also be used of examples on how to use that functionality.


How ASM(mmx, sse, 3dnow, altivec) optimizations will be done.

I am going to do the asm versions just like the SDL blitters are done. That is detect what cpu features are available and then register the fastest function with the processor features available. This way the same version of the code will run on different processors.

def rotate_C(...):
pass
def rotate_mmx(...):
pass
def rotate_sse(...):
pass

if(has_mmx() and not has_sse()):
rotate = rotate_mmx
elif(has_sse()):
rotate = rotate_sse
else:
rotate = rotate_C

Using vectorizing compilers to make first versions of optimized code.

To start with I am going to use vectorising compilers to make the first pass at the optimized ASM. gcc4. vectorC, msvcc, and icc are all ones which can do auto vectorization. Some compilers are better at vectorizing than others.

Once the first pass is done with those compilers I can see which ones were able to successfuly vectorize the code. Then run them through the benchmark to see which is faster.

Then I can see if changing the algorithm can speed them up at all.

The final pass at optimization would be to change the asm code itself for optimizations.



Rotation as an example of API optimization.

As an example of an api change that could improve the speed, I will describe the rotate api and a way that it can be improved.

The rotate function could be made to do its thing inplace. So instead of this:
newsurf = pygame.transform.rotate(surf, 90)

A new api that could do things 'in place' could be made. ie:
pygame.transform.rotate_ip(angle, src_surf, dest_surf, dest_rect)

Where the destination surface could be reused on each call to rotate. Therefore saving memory allocations, and reusing memory. The given api could even be used to rotate directly onto the screen. Ie a rotating blitter :)

One problem with this api is that a rotated image can use up more space than the original image. Therefore we need to make sure that the destination surface is large enough to hold the rotated image.

Therefore we may need a helper function to calculate the maximum size of a rotated image.
arect = pygame.transform.rotate_maxsize(src_surf, angle = None)

If an angle is given then we get the size of the image that will be created for that angle.

Such a rotation function is going to be quite complex to implement in a way which is easy for the user.

No comments: