Monday, 1 September 2008

Direct memory buffer pool and DDS

Well, it's been a long time since I had checked some really important aspects of the 3d core of jClassicRPG, and looking at that part I was a bit scared. :) Now it's not a secret, it's the memory consumption ratio of the game. But don't fear -- ways to improve are at hand.

With the long ago addition of an extended version of GeometryBatchMesh (created by Snylt @ jme) a new factor was secretly creeping into the memory usage of jCRPG: the direct memory buffers are heavily allocated especially because of the dynamic nature we use the batches, adding new batch instances every step walking around in the 3D world. In Java 5 and 6 there's this thing called direct memory buffers which is handled out of the heap of jvm for quick direct access e.g. by video cards. This speeds up things a lot with jME, so it's a handy thing. But there's a small problem with that (just like with the normal garbage collection), and it is that it's freeing is out of control of the programmer. This is not necessarily bad but in a game you would aim at controlling it - and allocate as little as possible because it takes time, fragments memory etc. jCRPG could end up with a big size of memory allocated to it rather quickly while walking around in the game.

Now my solution to circumvent the inability to free the buffers is the same as always: pool them! :) And it's mostly done committed to SVN repository. I've tuned GeometryBatchMesh to get and release its buffers from/to my BufferPool object. The handled buffer's size are always multiples of bigger numbers (say 500) and are limited down to the needed size (this helps the reusability of the buffers for different capacities). Thus the consumption is more or less stable and adds less stress on to the jvm's decision mechanism (how to allocate/free/reallocate). It's a good thing! :) I've even written a speedy QuickOrderedList to store the buffers in order of capacity with quick lookup/put/remove functions.

The other thing to lessen the consumption is the good old ace of using DDS files (which possibility I was not aware of till some days ago). DDS files are by default compressed (in sys and video memory too) and with pre generated mipmaps, quickening the load of them. I've started the process to migrate the textures to .DDS format with the help of GIMP and the GIMP DDS plugin. For use with jME I had to tweak the plugin's source ( mipmap.c's get_num_mipmaps() ) to add more mipmaps (jME DDS loader is picky about it, and accepts only an exact number of mipmaps for a given image size).

So the bugfixing, optimization phase is still going on... ;) (PS.: added two screenshot of my improved Depth Of Field render pass with 'bleeding' prevention.)


Charlie said...

Looks great :-)

I love the pixelization of the DoF shader.

Paul said...

hey there!
that's a factor of the texture resolution generated for the effect so low rez -> pixelized, faster :P