确保释放 OpenGL 纹理内存

Posted

技术标签:

【中文标题】确保释放 OpenGL 纹理内存【英文标题】:Ensuring OpenGL Texture Memory is Released 【发布时间】:2011-03-14 18:33:21 【问题描述】:

我的应用程序在两个活动之间切换时内存不足。第一个活动正在运行 OpenGL 场景,第二个活动不是。我想确保释放 OpenGL 场景使用的所有纹理。

我现在正在使用这种方法

getNativeHeapAllocatedSize()

跟踪纹理使用的相对内存量。如果我分配纹理,这个数字会增加大约 4 兆。然而,它似乎永远不会再次下降。

在我的第一个活动“OnPause”中,我有以下代码:

SurfaceView.onPause();
mTexture = null;

然后,在第二个活动中,我多次调用 getNativeHeapAllocatedSize()。即使在 GC 运行之后,内存仍然没有下降。

编辑:

经过更多研究,它似乎与加载数据的代码有关。我已经从方程中删除了 OpenGL,内存仍然没有被释放。

try 
        InputStream is = null;
        
            AssetManager am = MyActivity.getAssetMgr();
            is = am.open( fileName );
        

        Bitmap b = BitmapFactory.decodeStream( is );
        if( b != null ) 
            mResX = b.getWidth();
            mResY = b.getHeight();
            Bitmap.Config bc = b.getConfig();
            if( bc == Bitmap.Config.ARGB_8888 )
                mBPP = 4;
            else
                mBPP = 2;

            mImageData = ByteBuffer.allocateDirect( mResX * mResY * mBPP );
            mImageData.order( ByteOrder.nativeOrder() );
            b.copyPixelsToBuffer( mImageData );
            mImageData.position( 0 );


            return true;
        
     catch (IOException e)        
        e.printStackTrace();
     catch (Exception e) 
        e.printStackTrace();
           
    return false;

编辑2:

我确实添加了你所有的想法。然而,这似乎是我的问题......

ByteBuffer not releasing memory

【问题讨论】:

【参考方案1】:

我假设您的意思是通过 gl.glTexImage* 或任何其他辅助方法加载到 GPU 的纹理。在那种情况下,GC 不会帮助你,它不会清理纹理使用的内部内存

您是否尝试过通过 gl.glDeleteTextures 手动删除纹理?

根据新代码编辑:

您的代码中有几个漏洞:

关闭输入流 将数据复制到 ByteBuffer 后回收位图 我猜你使用带有图像数据的 byteBuffer 将纹理上传到 GPU,确保在上传数据后不要存储对这些缓冲区的引用。

我在此代码中没有看到任何其他问题,如果在此修复后它仍然无法正常工作,那么请仔细查看您的应用中的任何位图用法。

【讨论】:

我只是指传递给 OpenGL 的数据。由于我之前发布过,我已经从等式中删除了 OpenGL,所以它必须与我的 ByteBuffer 或 Bitmap 处理有关。附带说明一下,当使用 Surface 视图时,您会调用 glDeleteTextures 吗?调用 onPause 时有一个函数可以覆盖,现在我说的是每个纹理中的 GL10 对象,但它似乎有点 hacky。 关于 glDeleteTextures - 通常你不应该删除它们,android 会为你做。我只是不确定它是否会关闭应用程序或活动暂停。但无论如何,GPU 中使用的内存不应该影响您的第二个屏幕 -关闭输入流-检查-将数据复制到 ByteBuffer 后回收位图-检查-我猜你使用带有图像数据的 byteBuffer 将纹理上传到 GPU,确保不存储上传数据后对这些缓冲区的引用。 - 所以在我通过glTexImage2D传递字节缓冲区之后,释放ByteBuffer就可以了吗?我会试一试。

以上是关于确保释放 OpenGL 纹理内存的主要内容,如果未能解决你的问题,请参考以下文章

什么是纹理内存,由 OpenGL 分配,受限制?

OpenGL纹理内存布局和查找速度

OpenGL纹理映射总结

有没有办法确定 OpenGL 纹理或 QOpenGLTexture 的图形内存占用?

超过 128MB 的纹理时出现 OpenGL“内存不足”错误

opengl:纹理删除