iOS纹理占用33%的额外内存 [英] iOS Textures Taking 33% Extra Memory

查看:134
本文介绍了iOS纹理占用33%的额外内存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在测试我的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)
返回info.resident_size;

返回0;
}

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



以下是我如何分配纹理:

  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);

返回true;
}

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

解决方案

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



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



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。


I was testing my iOS game and noticed a discrepancy between how much memory it was taking up and how much it thought it should be taking up. Eventually I narrowed down the problem to textures taking 33% more memory than I thought they should be taking.

For instance, I would think a 256x256 uncompressed 32-bit texture should take 256*256*4 bytes = 256k. However, I would notice the app's memory grow by something like 340k when allocating a 256x256 texture. It was as if the device were allocating enough memory to store the texture and all of its mipmaps, but I'm not using mip maps or asking for the space in any way.

This extra memory stood out, because it would only happen on certain devices. I noticed the extra memory when testing the game on an iPod Touch 4. However, the problem didn't occur on an iPhone 3GS, iPod 3G, or iPad 1.

The os versions on the devices are:

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)

EDIT

Here's a little more info. I measure the app's memory like this

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;
}

This returns the same value that you will see in the Insturments program for Real Mem. It's actually very useful.

And here's how I allocate my textures:

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;
}

It's all very basic stuff. The only thing that led me to find the memory problems in the first place was the discrepancy between different devices. In fact, it was the discrepancy between total app memory and resource memory (I track images and sound memory myself) that made me investigate to find this bug.

解决方案

I found a workaround already, so I'm going to answer my own question. But I thought I'd post this because it seems to be an important piece of information to be aware of.

Other people have found this bug. For instance, see here:

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

The good news is that there's a workaround for the bug. The workaround is to only use non-power-of-2 (npot) textures. NPOT textures can not be mip mapped so iOS doesn't try to allocate the extra mip map memory (at least that's the theory of why it works.)

Fortunately, this was easy to do in my engine, since it already divides images up into multiple textures if necessary just to fit into power-of-2 textures without using too much memory. So, I just tweaked my code to not divide up images to fit into power-of-2 textures, and further to force any image that happened to be a power of 2 in both dimensions to load into a texture that was 1 pixel bigger than necessary in width. So, for instance, I would put a 256x256 image into a 257x256 texture.

This eliminated the 33% extra memory growth.

Note that older devices such as the iPod 3G can't do npot textures so it's important to check whether its possible before doing this fix. To check for this you can query the GL_APPLE_texture_2D_limited_npot extension. Also, be careful not to exceed the maximum texture size in adding this extra pixel to force the texture to be npot.

这篇关于iOS纹理占用33%的额外内存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆