9

我有一个纹理密集的 OpenGL 游戏,我想根据设备的 RAM 大小对其进行调整。最高分辨率的纹理我在 iPhone 4 或 iPad2 上运行良好,但早期的设备在加载纹理的过程中崩溃。我有这些纹理的低分辨率版本,但我需要知道何时使用它们。

我目前的策略是检测特定的旧设备(3GS 有一个低分辨率屏幕;iPad 没有摄像头),然后只为 iPad2 及更高版本和 iPhone 4 及更高版本加载高分辨率纹理——我想我需要为 iPod touch 做点什么。但我更愿意使用特征检测而不是硬编码设备模型,因为模型检测对于未来对 API 和硬件的更改是脆弱的。

我正在考虑的另一种可能性是首先加载高分辨率纹理,然后在我收到低内存警告的那一刻放下并用低分辨率替换它们。但是,我不确定我是否有机会做出回应;我注意到该应用程序通常在调试控制台上出现任何通知之前就死机了。

如何检测我正在运行的设备是否没有足够的 RAM 来加载我的纹理的高分辨率版本?

退后一步,我可以使用其他一些特定于 OpenGL 纹理内存的自适应技术吗?

笔记:

  1. 我已经在 SO 上搜索了与可用 RAM 检测相关的答案,但它们基本上都建议分析内存使用情况并消除浪费(最大限度地减少临时人员的生命周期,以及所有这些废话)。我已经尽我所能做到了,而且我无法将高分辨率纹理压缩到旧设备中。

  2. PVRTC 不是一种选择。纹理包含片段着色器使用的数据,并且必须以无损格式存储。

4

4 回答 4

11

要获得设备的总(最大)物理 RAM,请使用[NSProcessInfo processInfo].physicalMemory.

请参阅文档

于 2013-10-02T15:46:54.997 回答
7

总物理 RAM 可通过 获得sysctl(),如本博客文章中所述,并在此处实现为干净的 API (请参阅totalMemory相应 .m 文件中的实现)。

为了方便和后代,我已经解除了博客的代码:

#include <sys/sysctl.h>

size_t phys_mem()
{
 int mib[] = { CTL_HW, HW_PHYSMEM };
 size_t mem;
 size_t len = sizeof(mem);
 sysctl(mib, 2, &mem, &len, NULL, 0);
 return mem;
}

我不知道苹果是否会批准sysctl()以这种方式使用的应用程序。它已记录在案,但仅适用于 Mac OS X。

于 2011-11-09T21:55:44.697 回答
2

在这种情况下,您需要了解的内存管理最重要的一点是使用高分辨率或低分辨率纹理。我使用的最简单的方法是检查这个

CGFloat scale = [[UIScreen mainScreen] scale];
if ((scale > 1.0) || (self.view.frame.size.width > 320)) {
        highRes = TRUE;
}

到目前为止,这适用于所有设备,并且应该是未来的证明,较新的设备将使用高分辨率。您也可以在那里计算纵横比(稍后在 ipad 与 iphone 上有所帮助)

aspect = self.view.frame.size.width/self.view.frame.size.width

不要先加载高分辨率,它会浪费你的应用程序加载时间,在我的 3G 上,我的大部分启动都花在加载(即使是低分辨率)纹理上,只需在一开始就测试这一点,不要碰高分辨率的东西。

在较旧的设备上,由于纹理较大,程序会在没有警告的情况下死掉,这可能与调试器无法捕获视频内存消耗并自行死机有关。

要获得更大的优化,请考虑为 mipmap 着色以检查实际使用的最低纹理大小(仅当您使用 3D 对象时)。

忘记视频 RAM 大小的问题,内存实际上是共享的,所以你在争夺系统内存,在旧设备上你有 MB 的使用限制,但它仍然是系统内存。

关于内存管理,有很多方法可以做到,最简单的应该是标记已加载的纹理,以及需要的纹理,当内存警告来临时,将已加载但不需要的纹理转储...

于 2011-11-09T10:39:42.487 回答
0

据我所知,一个人能做的最重要的三件事是——

  1. - (void)didReceiveMemoryWarning在 iOS 发送警告 1 和 2 时实施和响应。
  2. Instruments 中的 Profile 代码试图找到泄漏和更好的 mem 最佳实现方式。
  3. 检测设备类型并可能使用该信息。
  4. 使用某种形式的纹理压缩(例如 PVRTC)来节省空间。

我认为你正在做其中的大部分。问题是人们甚至不知道 iOS 设备有多少 RAM。Apple 不会发布 iOS 设备的技术规格。

此外,不能假设只有在消耗 100mb 之后才会收到内存警告。iOS 给出的警告取决于设备的当前状态、正在运行的其他应用程序以及它们消耗的内存量。所以它变得棘手。

我可以建议 2 必须阅读的部分 -使用纹理数据和调整 OpenGL ES 应用程序的最佳实践

于 2011-11-07T04:21:17.690 回答