Best Game Loop for Android?

At the Google I/O Android Game presentation, they suggested using 3 threads for a game:

  1. EDT (basically leave it alone to do user input).
  2. Draw loop, let it run flat out.
  3. Game logic loop.

I did that, and I got terrible performance. So I tried a wait/notify pattern where there draw loop would wait if there was no update from the game loop. Brilliant performance!

Well, it was brilliant on Android 1.1. My phone just updated to Android 1.5, and the performance is not so good any more (not terrible, but noticeably worse).

I tried upgrading my draw loop to use the new GLSurfaceView class, and that didn’t make any difference.

My question is, what do you guys do? Do you use 3 threads? Do you let the draw loop run flat out, or use a wait/notify pattern (GLSurfaceView.RENDERMODE_WHEN_DIRTY)? Any other advice?

Thanks!

This is a bad idea. You have to keep a lot of things synchronized to avoid weird bugs that are impossible to reproduce.

I currently use 2 threads. The EDT (which I sleep when recieving touch events thanks to Ranger) and the rendering thread provided by the GLSurfaceView. As part of the render cycle before I render anything I call logic().

Seems to work pretty well.

Kev

I initially only had 2 threads, but Google said that because the calls to the GPU take so long (which they do), you are better off having a separate game thread and making use of the idle CPU time (when the draw thread is doing I/O to the GPU).

However, when I did this, I found it was a real pain, as Markus pointed out, keeping things synchronized (ended up making a SceneData class to group the information the draw thread needed together). And my performance testing showed that the game loop would execute in about 5% of the time that the draw loop took to execute. So I’m thinking having separate draw and game threads just isn’t worth it.

Oh, well, if the gpu really is that slow, I guess separating the threads could be worth it as long as you manage to pull the synchronization off.

I’m getting my HTC Hero later this week, I’m really looking forward to playing around with android. :smiley:

I forgot, there was another reason for having separate threads. If the phone decides it has to do something else, the game loop will generally continue to run at the desired FPS, while the draw loop will start skipping frames. That way, the game won’t slow down, it will just start jumping.

If your game time is based on time since the last frame, I don’t think separating the game logic and drawing in different threads gains anything. Definitely relying on a constant framerate is a bad idea as I see framerates vary pretty wildly.

I use 3 threads: EDT, GL, and a thread for reading from the mic. Some native code somewhere has to be running a 4th thread to play music, since it continues to play even with all my threads paused. There is no way around so many threads, and it is brutal on my framerate. I am only getting 30 FPS drawing some pretty damned simple 2D stuff. Commenting my rendering hardly affects the framerate, the CPU is just busy playing music, reading from the mic, and processing the mic data. This worked a lot better on the iPhone, and I don’t think it can be blamed entirely on Dalvik (my mic processing uses native code). My theory is the Androids mic stuff is especially crappy.

I noticed on the G1, playing MP3 files takes a lot of CPU, while playing OGG files takes much less.

As my game is a multiplayer game, I decided to make the game loop run at a constant frame rate (just because I thought it would make coding easier). The draw loop is free to skip frames whenever it needs to.

I have this problem now where sometimes when I run my game, the OpenGL calls will all execute quite well, and my game will run smoothly, and other times they take forever and the game is really choppy. If anyone has any ideas as to what might be the problem, please let me know.

EDIT: I found the problem: If the window that launches my game is in landscape mode, I get about 18fps. If it is in portrait mode, I get 30fps. It’s weird because I actually force my game to run in landscape mode. I thought the launcher window may have some soft of problem with landscape mode, so I cut it right back to just 1 button, but that didn’t fix the problem. Then I thought the game might be starting multiple game loops…nope. Now to try to reproduce it in a test case.

I’ve just tried the 2 threads (logic vs GL) approach and it’s slightly better responsive wise and smoothness. Though there isn’t a great deal of difference that I can see.

Kev

Did you use GLSurfaceView.RENDERMODE_WHEN_DIRTY, or run the GL loop flat out?

Run the GL loop flat out, is it better on dirty?

Kev

OK. I don’t have a direct answer, but this is what I have done.

Android 1.1 -> GL loop flat out with my own loop, terrible performance.
Android 1.1 -> GL loop doing a wait() and game loop doing notify(), excellent performance.
Android 1.5 -> GL loop doing RENDERMODE_WHEN_DIRTY and game loop requesting repaints, I think the performance was slightly slower then wait/notify, but hard to tell.
Android 1.5 -> GL loop flat out, never tried.

hi
I use three threads in my game,

  1. UI
  2. GL (only drawTextOES)
  3. game logic

and framerate is nearly 60.
at first I use logic thread to notify the Gl thread and I got very slow performance, then I changed them 2,and it seems works fine.

I shied away from using glDrawTexiOES because in that Google I/O talk, they said that GL11Ext might not be supported by all phones. Anyone know if this likely to be true?

It is possible, so if you are going to use it, you might want a fallback. It isn’t hard to do it both ways. Or you could always wait for your game to break, then fix it. I tried it out and didn’t find it to be much better, if even better at all.