2012-12-17 38 views
1

我的最后一个问题没有回答,所以我尝试了一种不同的方法。我将很多纹理(256x256 RGBA888)加载到内存中,并在需要时丢弃它们。问题是,有时当我将纹理上传到OpenGL ES时,需要40-80ms,很少。我弄清楚,这个缓慢的时间是在垃圾收集之后。问题是,GC有时会阻塞GL线程(FPS丢弃),有时会阻塞纹理加载器线程(OK)。有没有一种好方法可以在GL线程上以某种方式不允许GC发生?OpenGL ES线程垃圾回收

我试过之后调用纹理加载器线程System.gc()每1,2,3个... N纹理解码,这对GL线程有效去除GC-ing,但现在的纹理加载慢得多,因为线程必须等待为GC完成。使“n”更大使得加载更快,但GL线程上的GC更可能,因此动荡不稳。

是否有某种方法可以在GL线程上删除GC-ing线程以便在不同线程中解码位图?我不解码/分配GL线程上的任何位图,GC-ing仅在加载新纹理时发生。

编辑: 应用程序的目标是Android 3.2和更新,也是手机。这发生在手机(HTC One S - 4.0.3)和平板电脑(Nexus 7 - 4.1,Galaxy Tab 2 10.1 - 3.2和4.0,Acer Icona A200 - 4.0)

+0

你正在测试什么版本的机器人? –

+0

@Ali Imran编辑我的帖子,添加设备和Androod版本 – shelll

+0

@Ali Imran这也是我很久以前的问题。它不会解决我目前的问题,因为每个BitmapFactory.decodeStream(...)都会创建一个新的位图,这个位图将在未来的某个时间进行GC编辑。我使用的是类似的方法,但没有“双缓存位图”,最终没有给我带来任何好处。 – shelll

回答

0

感谢这video有一个简单的解决方案适用于相同大小的瓷砖,并针对Android 3.0及更高版本。

BitmapOptions.inBitmap这将为每个新瓷砖重新使用一个Bitmap,因此不再需要更多的固件。

2

您不能完全禁用垃圾收集,由Dalvik VM发起,无需入侵。

您可以通过使用一些自定义的纹理加载(如使用预先分配的数组来存储源纹理数据等)来最大限度地减少内存分配和释放。正如您所提到的,所有纹理都具有相同的尺寸和颜色深度,对于任何图像都需要一个相同大小的临时缓冲区(256x256x4 = 262144字节)。

最终,您可以将OpenGL代码移动到JNI C/C++代码,以便以您想要的方式管理内存。

+0

我正在考虑将位图创建部分移动到C中,但我也必须管理将位图发送到C中的OpenGL的线程,所以在Java中没有位图实例,它将是GC -ed。你可以指导我如何发送一个Java InputStream(我从APK扩展文件中打开PNG)到本地代码,在那里解码并将它发送给GL线程,并在我的Java类中设置纹理ID和准备好标志instace“瓷砖”?谢谢 – shelll

+0

我不擅长JNI编程,我只是建议您使用它,因为在本地C代码中,您将能够以任何您需要的方式管理内存。 另外,你可以用Java来做,但方式不同。不要将PNG文件加载到“位图”中,而是以二进制RGBA888格式加载准备好的纹理,以便直接加载到GPU。这样您将需要一个预先分配的临时缓冲区来加载所有纹理,请参阅我的编辑进行回答。 – keaukraine

+0

在8888格式下让它们不被使用,对我来说不是最好的主意,那将是2GiB左右的数据。我可能不得不查看本机代码并混合使用Java和本机OpenGL ES调用。 – shelll