Multithreading

From JPCT
Jump to: navigation, search

Multithreading

jPCT's renderers are single threaded by default unless you are using the AWTGLRenderer (or the JOGL-support). In that case, rendering and calculations are split into two different threads. This isn't done just for fun, but because the actual drawing has to happen in the AWT event dispatch thread, which usually isn't the thread that executes your game logic. When using one of these renderers, make sure that any GL and LWJGL(JOGL related code is executed in the dispatch thread too. To do this, put it into one of the methods that the IPaintListener-interface offers instead of executing it directly in your main thread.

It is possible to use multithreading in the "normal" GL renderer too. Just set Config.useMultipleThreads to true before initializing the renderer. All said above about the AWTGLRenderer then applies to the normal renderer too.

When using Config.useMultipleThreads on the software renderer, it will uses multiple cores to render the scene. Because jPCT still is Java 1.1. compatible, it doesn't determine the number of actual cores. Configuring the software renderer for optimal performance on multiple cores requires some more steps, which are covered in the section below.


The software renderer on multiple cores

When using the software renderer on a multi core setup, it's a good idea to use all cores (or at least some of them) to speed up rendering. To do so, set Config.useMultipleThreads to true before instantiating the frame buffer. By default, jPCT will use four cores, which matches a quad core cpu. If the setup that runs the application uses less cores, it's advised to adjust this value before instantiating the frame buffer. You can use Runtime.availableProcessors() for this. jPCT doesn't do it by itself, because that part is still Java 1.1 compatible, which doesn't provide that method. Another option is to make the blitting to the screen multi threaded. This may help, it may make things worse...which is why it's disabled by default. Enable it by setting Config.useMultiThreadedBlitting to true. You also may want to choose the type of load balancing. By default, it's static. That means that jPCT will split the scene in equal parts without taking the actual load of each into account. This is fine for scenes with evenly distributed geometry. However, something like a landscape usually isn't: While the sky is pretty empty, a lot of polygons are located in the lower parts of the screen. For this, dynamic load balancing should be used. Enable it by setting Config.loadBalancingStrategy to 1. Dynamic load balancing usually is the better choice. It's not enable by default simply because it can cause small artifacts in combination with the texel filtering that jPCT uses (some pixels may flicker from time to time). To visualize the load, Config.mtDebug can be set to true. It draws some white lines at the end of each part. There's a simple example on the Collision detection page that uses multiple threads for the software renderer.

The WorldProcessor

jPCT 1.24 introduces a new concept, the WorldProcessor class. By default, each World uses a single threaded instance of this and in most cases, this should be sufficient. However, when using multiple objects of which most aren't visible or when using the hybrid pipeline, it can help to improve performance to assign a multi threaded instance of the WorldProcessor to the World. Just play around with this to see if it helps in your case. It might hurt performance as well if the additional overhead eats up the speedup.

The threading framework

jPCT comes with a simple threading framework. It's used by the software renderer. Feel free to create your own Worker instance to use it in your own application. It's nothing fancy, just a simple framework that does what jPCT needs.


Thread safety

Just like Swing, jPCT isn't thread safe. That means, that you must not modify any jPCT object from any other thread than the thread that executes the render loop. Keep in mind, that all key and mouse listeners are running in the AWT event dispatch thread, i.e. not in your main thread. Don't modify jPCT objects from within these listeners' methods unless your render loop is executed in that thread too (which i don't recommend, but some people are doing it this way). If you want to modify a jPCT object based on mouse or key events, just set a flag in the listener and do the actual modifications in your render thread...or synchronize everything correctly, which can be much more painful and error-prone.