2012-01-08 43 views
1

我注意到当我加载几十个纹理时,我的应用程序崩溃,没有任何通知等。它只是返回到手机的上一个屏幕。难道是因为手机无法在内存中存储太多内容吗?我应该在游戏开始之前不加载所有纹理吗?加载数十个纹理后,应用程序崩溃

+2

请报告纹理的大小,它们的数量和代码的摘录,以更好地帮助你:) 这样就好像,我的车没有启动,是什么问题? :) :) – 2012-01-08 13:04:40

+0

也发布崩溃日志 – nandeesh 2012-01-08 13:06:07

+0

纹理的总大小为3.2mb,平均每个图像100kb。共有27个PNG,分辨率为1024 x 1024。 – 2012-01-08 13:37:19

回答

2

你有你的答案已经作为评论的一部分,但我会在这里写这样的结论:

资产的存储的大小并不重要,因为它们可能被压缩。重要的是实际工作集的大小。在图像的情况下就可以计算出它作为

width * height * sizeof(pixel) 

其中

sizeof(pixel) = sum[channels]{ sizeof(channel) } 

在1024×1024,4个通道(RGBA),每个信道1个字节的单个纹理的你的工作集大小的情况下将是:

1024*1024 = 1Mi 
1Mi * 4 * 1B = 4MiB 

在27纹理的情况下,这相当于27*4MiB = 108MiB。现在OpenGL根据抽象机器来定义,这意味着你不能问它,有多少内存需要花费。它只会告诉你它是否耗尽内存。如果不是所有东西都适合视频RAM,OpenGL也可以使用普通的系统RAM。无论哪种方式,如果试图上传超过100MiB的纹理数据,在手持设备上,您可能会耗尽内存。

在游戏开始之前我不应该加载所有纹理吗?

不,你不应该。事实上,“流”你的游戏内容,按需加载东西更好。另外某种垃圾收集或回收计划也有很大帮助。分配纹理非常昂贵(即调用glTexImage),而替换数据便宜(glTexSubImage),所以我建议在纹理管理结构中添加一个“未使用”的计数器。每次绑定纹理并从中拉出时,都将其设置为零。在完成帧增量后,每个纹理对象的“未使用”计数器。如果你需要加载一个新的纹理来迭代所有的纹理对象,选择那些匹配的格式(大小和通道数量相同),按未使用的计数器排序,然后重复使用纹理对象的“未使用”值,即在排序的“未使用”集的中间。每个“更高的未使用”质地应该被释放,其他人留作储备。如果您需要首先分配来自N个中值对象的多个纹理(可能)。使用该策略可以使您随时可以使用纹理对象,并且偶尔还可以释放未使用的内存。

1

为了回顾评论,在RGBA模式下,通过分配可能的纹理,共计27个1024 x 1024像素,每次纹理分配4 MB视频RAM,总共110 MB。

为了避免这种崩溃并与多个Android系统兼容,您应该缩小纹理的大小(有时会降低整体质量)。

毫无意义的是,纹理必须在不再使用时才被卸载,以便为其他新负载腾出空间。