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

我正在测试我的iOS游戏,并注意到它占用了多少内存与它应该占用的内存之间存在差异。 最终我将问题缩小到纹理,占用的内存比我认为应该占用的内存多33%。

例如,我认为256×256未压缩的32位纹理应该采用256 * 256 * 4字节= 256k。 但是,我会注意到应用程序的内存在分配256×256纹理时增长了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; } 

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

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

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

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

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

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

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

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

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

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

编辑:

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

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