iOS纹理占用33%的额外内存

Bri*_*ein 9 memory textures opengl-es ios

我是在试探我的iOS游戏,发现它是多么的内存占用,有多少它之间的差异认为应该占用.最终我将问题缩小到纹理,占用的内存比我认为应该占用的内存多33%.

例如,我认为256x256未压缩的32位纹理应该采用256*256*4字节= 256k.但是,我会注意到应用程序的内存在分配256x256纹理时增长了340k.好像设备分配了足够的内存来存储纹理及其所有mipmap,但我没有使用mip贴图或以任何方式询问空间.

这个额外的记忆很突出,因为它只会发生在某些设备上.我在iPod Touch 4上测试游戏时注意到了额外的内存.但是,在iPhone 3GS,iPod 3G或iPad 1上没有出现这个问题.

设备上的操作系统版本是:

iPod 3G - iOS 3.1.2(7D11)iPhone 3GS - iOS 4.3.5(8L1)iPod 4 - iOS 4.2.1(8C148)iPad - iOS 4.3(8F190)

编辑

这里有更多信息.我像这样测量应用程序的内存

int PlatformIOS::GetProcessMemUsage()
{
    task_basic_info info;
    mach_msg_type_number_t size = sizeof( info );
    kern_return_t kerr = task_info( mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &size );
    if ( kerr == KERN_SUCCESS ) 
        return info.resident_size;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这将返回您在Real Mem的Insturments程序中看到的相同值.它实际上非常有用.

这是我分配纹理的方式:

bool GL3DTextureDataPiece::CreateTextureSurface(X3DInterfaceImpl *theInterface, int theWidth, int theHeight, PixelFormat theFormat, RefCount *thePalette, bool generateMipMap)
{
    glGenTextures(1,&mTexture);
    theInterface->SetCurTexture(this);

    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,mLinearFilter?GL_LINEAR:GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,mLinearFilter?GL_LINEAR:GL_NEAREST);

    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, theWidth, theHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

    return true;
}
Run Code Online (Sandbox Code Playgroud)

这都是非常基本的东西.导致我首先发现内存问题的唯一原因是不同设备之间的差异.事实上,总应用程序内存和资源内存之间的差异(我自己跟踪图像和声音记忆)让我调查发现这个错误.

Bri*_*ein 8

我已经找到了一个解决方法,所以我将回答我自己的问题.但我想我会发布这个,因为它似乎是一个重要的信息要注意.

其他人发现了这个bug.例如,请看这里:

http://www.cocos2d-iphone.org/forum/topic/29121

好消息是这个bug有一个解决方法.解决方法是仅使用非幂2(npot)纹理.NPOT纹理不能被mip映射,因此iOS不会尝试分配额外的mip映射内存(至少这是它工作原理的理论.)

幸运的是,这在我的引擎中很容易做到,因为它已经将图像分成多个纹理,如果有必要,只需要适应2次幂纹理而不需要使用太多内存.因此,我只是将我的代码调整为不分割图像以适应2次幂纹理,并进一步强制任何在两个维度上都是2的幂的图像加载到比1个像素大的纹理中.宽度必要.因此,举例来说,我会将256x256图像放入257x256纹理中.

这消除了33%的额外内存增长.

请注意,较旧的设备(如iPod 3G)无法执行npot纹理,因此在执行此修复之前检查是否可行是很重要的.要检查这一点,您可以查询GL_APPLE_texture_2D_limited_npot扩展名.此外,在添加此额外像素时,请注意不要超过最大纹理大小,以强制纹理为npot.