【问题标题】:iOS Textures Taking 33% Extra MemoryiOS 纹理占用 33% 额外内存
【发布时间】:2012-03-15 07:57:34
【问题描述】:

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

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

【问题讨论】:

  • 显示器不一定会影响代码,但我想知道它是否与 Retina 显示器有关?
  • 你是如何测量应用程序内存的?

标签: ios memory opengl-es textures


【解决方案1】:

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

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

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

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

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

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

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

【讨论】:

  • 我试图接受答案,但您必须等待 2 天才能执行此操作。这似乎是有道理的,实际上。那么也许有人会有更好的答案。
【解决方案2】:

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

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

编辑:

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

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

【讨论】:

  • 这很有趣,因为我遇到了这个确切的链接,并认为可能会以某种方式自动创建 mipmap,但您实际上需要调用 glGenerateMipmap 才能发生这种情况,而我没有调用它。跨度>
猜你喜欢
  • 2023-04-09
  • 1970-01-01
  • 2011-02-17
  • 2012-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多