Search code examples
androidopengl-esandroid-ndk

How do I avoid leaking Graphics memory in OpenGL ES 2.0 in a background thread on Android?


I have a game which crashes on Android under our custom engine. After a week of tracking it down, I have found that one single call can make the difference:

glDrawElements(GL_TRIANGLES, (int)Particles.size() * 6 * particle_multiplier, GL_UNSIGNED_SHORT, VBIndicies);

This call is obviously not even supposed to retain any memory, but for some reason, in the background thread, it will continue to build unreleased memory over time and eventually crash from the memory pressure.

Is there any techniques to flush this besides recreating the entire context?


Solution

  • Graphics drivers will buffer work and flush to the hardware in batches, as this is a far more efficient way to dispatch work to the GPU than doing it piece-wise. Under normal operation the flush points in OpenGL ES applications are implicit. Usually a driver will automatically flush for each rendered image and at the end of a frame, but it's implementation defined behavior.

    In your case the "leak" is simply that resources used by the draw call are getting stuck in a buffer waiting to be flushed and processed by the GPU because you are never reaching an implicit flush point before sleeping.

    Add a glFinish() before the sleep to force the rendering work to get processed. This ensures there are no pending resource references held for buffered work in that rendering context. . Using glFlush() may also work, but it's a hint and may be ignored by many drivers in my experience.