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

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

问题描述

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

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

这个额外的内存很突出,因为它只会在某些设备上发生.在 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 信息;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);如果 ( kerr == KERN_SUCCESS )返回 info.resident_size;返回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);返回真;}

这些都是非常基本的东西.唯一让我首先发现内存问题的是不同设备之间的差异.事实上,正是应用总内存和资源内存(我自己跟踪图像和声音内存)之间的差异,才让我进行了调查以找到这个错误.

解决方案

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

其他人发现了这个错误.例如,请参见此处:

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

好消息是该错误有一个解决方法.解决方法是仅使用非 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天全站免登陆