glDeleteTextures函数对内存的优化

函数介绍

void glDeleteTextures(  GLsizei n, const GLuint * textures);

从字面意思来理解,该函数是用来删除纹理的。通过官方文档是这样介绍的:
glDeleteTextures deletes n textures named by the elements of the array textures. After a texture is deleted, it has no contents or dimensionality, and its name is again unused. If a texture that is currently bound is deleted, the binding reverts to 0 (the default texture).

Unused names in textures that have been marked as used for the purposes of glGenTextures are marked as unused again. glDeleteTextures silently ignores 0’s and names that do not correspond to existing textures.

大概意思就是,glDeleteTextures函数可以删除n个纹理对象数组元素。删除后,该纹理不再可用,如果被删除的纹理已经被绑定,那么程序将绑定一个为0的纹理对象。
被glDeleteTextures函数delete掉的纹理,可以通过glGenTextures再次返回,重复使用。如果glDeleteTextures要删除的纹理是一个为0的纹理对象,或者不存在的纹理对象,那么也不会有什么影响。

问题分析

纹理对象是一个GLuint类型,因此纹理对象的数量应该是很大的。程序里面我们可以生成很多的纹理对象,对于这个数量而言,一般都应该能满足我们的需求。然而,纹理对象越多,占用的内存就越多。因为,每个纹理对象最终都要绑定一种纹理类型,然后把纹理数据载入到纹理对象对应的内存中,纹理数据是很占内存的。

对于一般的使用场景,都会在初始化的时候把所有的纹理都加载好,在渲染的时候直接使用就好了,但是有些情况下,需要在程序运行的过程中动态的加载纹理,然后使用该纹理渲染。这个时候假设有数量很多的纹理,如果每次都是这样:

GLuint texture = 0;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
...
glTexImage2D(...);

那么我们程序将会产生越来越多的纹理对象,每个纹理对象都在对应的内存中保存了该纹理的数据。当数量达到一定程度,那么内存便被耗尽,程序自然就要挂了。

我在我手机上面做了一个测试,将如上代码所示的加载纹理过程,放在了每一帧的渲染中,这样就相当于每次都产生新的纹理对象,每次分配内存保存纹理数据。结果程序在加载了1400多次纹理之后挂了。

后来,我在每次加载新的纹理之前使用glDeleteTextures函数,删除不再需要的纹理,然后继续前面的加载纹理的操作,程序就运行正常,不再出现挂掉的现象。

而且,再次使用glGenTextures的时候,会返回刚才delete的纹理对象

这个不一定总是这样,原因是看你删除纹理对象的时机,如果前面创建的纹理已经使用了一段时间,
在他没有被delete之前,glGenTextures已经又产生了好几的纹理,此时,先delete该纹理,
然后再glGenTextures,就不会返回前面被删除的纹理,这是因为纹理对象的分配是递增的0123...这样,
如果他已经分配到了3,此时1释放,下次分配的时候也会分配4,而不是1;
而如果分配到了3,此时释放3,再次分配的时候就会接着分配3

说明通过glDeleteTextures函数之后,纹理被释放,相应的内存也被释放。

glGenTextures和glDeleteTextures就像是c++中的new和delete一样,一个产生对象,一个销毁对象。
glGenTextures产生纹理对象,glDeleteTextures释放对象,同时释放内存。

对于上面所说的情况,其实也可以使用另一种方法:glGenTextures创建一个纹理对象,后面新的纹理都使用这个纹理对象,绑定定数据,重复使用这一个纹理对象,这样做的目的就是不让产生新纹理对象,重复使用内存资源。相对而言,个人感觉使用glDeleteTextures函数更省事。

因此,对于那些不需要一直显示的纹理,显示结束之后,使用glDeleteTextures函数就能有效的缓解内存压力。

你可能感兴趣的:(opengl-es)