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

时间:2012-02-24 21:03:28

标签: ios memory opengl-es textures

我正在测试我的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;
}

这将返回您在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;
}

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

2 个答案:

答案 0 :(得分:8)

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

其他人发现了这个错误。例如,见这里:

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。

答案 1 :(得分:4)

确保您没有自动生成mipmap: http://www.opengl.org/wiki/Texture#Automatic_mipmap_generation

mipmap链将占用33%的额外空间,因为mipmap链接近1/3额外 - 请参阅下面的系列,其中t是原始纹理的大小: = t + t / 4 + t / 16 + t / 64等......

编辑:

请注意,发布用于衡量应用内存的方法以及用于创建纹理的方法也很有帮助。

可能是您使用的方法总是创建一个额外的33%缓冲区,或者您可能只是错误地调用该方法。