Search code examples
javaandroidc++opengl-esandroid-ndk

Why would a OpenGL ES 2.0 leak graphics memory on Android, but not iOS with the same code


I have an Android NDK based game which we build partially off of parts of an open source engine (Cocos2d-x). Most of the engine is custom, but for things like OpenGL context setup, Java bridging, and events, we found it convenient to use an off the shelf solution.

Fast forward to today, we are having stability issues, cocos2d-x is no longer maintained, and we are having some serious stability issues. I have spent about 1 week debugging this, and have not been able to find a way to trace it down. Here is what I've tried

  • Compiling with the old NDK it came with
  • Changing the SDK as old as it would allow
  • Using HWASan
  • Setting CheckJNI
  • Attempting to audit all of the JNI bridge code

The way in which it crashes varies greatly

  • When attached to the debugger, it crashes within the first second. Almost always in the Android runtime. Many times around garbage collection or involving the JNI bridge
  • When not attached to the debugger, sometimes it would be stable.
  • When HWASan is attached, it would occasionally crash in the ANGLE library if OpenGL is set to use it on the phone
  • Sometimes the graphics memory will simply leak and eventually lead to a crash, and other times it will not leak at all

I would also like to say that the app is very stable on all other platforms besides Android, and 95% of our code is in the shared c++. I even commented out actually booting our code in c++ and the game still crashed on a black screen with just the out of the box engine code.

I am considering taking the leap to port to SDL so the engine will at least be supported, but if anyone has any tips on tracing this sort of thing down, I would be very happy to see hear it.

UPDATE:

I believe the crash issue when attached to the debugger may be a separate issue with the engine setup. For production users, the issue seems to be that the OpenGL graphics memory from either frame buffers or textures is not being released back to the system. I should note that the code is the same as iOS which does not have this problem, so it must have something to do with the share context or how the drivers work. I will accept any answer that only solves this problem.

CONCLUSION Android development is terrible. There are random non texture related draw calls which would cause leaks simply because its the background thread.


Solution

  • Ok, I continued to struggle with this, and this solution is not at all satisfactory to me, but I thought I would come back to share in case anyone is ever in this situation so they have something they can try. For me, it appears that by putting a glFinish() prior to calling usleep() in the background thread, made it actually give the memory back and not leak. This feels like a bad driver sort of issue, but it definitely stopped leaking even on very complex cases, so I will take that as a solution.