问题
I'm writing a game in native code and all graphics is done with OpenGL ES 2.0. I've tried sparing with the texture usage by repeatedly creating them and deleting when they're not needed (with glDeleteTextures). I noticed that the OpenGL will never reuse same texture id anyway and after exactly 192 texture creations the android screen turns white, (first partially, next load makes it fully) and it does not recover except by releasing app focus and getting it back. Is this a bug or feature? glFlush() does not help either.
I have written my own font rendering engine that uses font sprite atlas to render all text into a separate new texture. This way the actual text is done once and subsequent draw calls is for one texture only. However, e.g. a player name query causes the text texture to be recreated every time a new letter is entered or deleted and here I quickly encountered the 192 limit. It does not matter what textures are loaded and deleted, screen goes white after fixed amount of creations.
This happens at least when running on my android device Samsung J5 2016 with Android 6.0. Any advice is appreciated.
回答1:
In OpenGL and OpenGL ES, texture creation is an expensive operation, therefore it is recommended that you use the smallest number of textures possible. Your approach to use a Texture Atlas for your font rendering engine is good.
However, if you are continually using the Texture Atlas, in the game, you should only create the texture once during initialisation. You only need to destroy the texture object when the Activity is exiting and you need to release the memory. Therefore you only ever have one texture in use for the Text Atlas during run time.
One useful text rendering library for OpenGL is FreeType. There is a example code here which shows the minimum steps required to initialise and use a FreeType Texture Atlas in a native OpenGL application (I've had success integrating this with my OpenGL ES Native Android applications). You can follow a similar approach for your custom font rendering engine.
For a native Android application, you call the initialisation of your native OpenGL ES code, via JNI binding to the native initialisation method from the onSurfaceCreated
callback. A call to destroy the texture and release memory in native code should be made from onDestroy
callback via JNI.
You can find further details on the Android Activity Lifecycle here. This will give you a good idea of where to initialise and destroy Textures.
回答2:
Found out the reason. I was actually deleting the framebuffer and recreating it every time I created a new render to texture operation. By doing creation only once
glGenFramebuffers(1, &m_renderFrameBuffer);
and reusing it in subsequent operations and putting delete
if (m_renderFrameBuffer != 0)
{
glDeleteFramebuffers(1, &m_renderFrameBuffer);
m_renderFrameBuffer = 0;
}
to class destructor I didn't run into the problem anymore.
But this is not obvious in the numerous examples out there or at least this is not warned. It seems that doing many framebuffer creations and deletions will eventually exhaust some resources.
来源:https://stackoverflow.com/questions/43543631/maximum-texture-creation-deletion-in-android-opengl-es-2-0