在Android上上传纹理时避免失速

use*_*134 6 c++ android opengl-es

我们的游戏要求我们不断加载和创建新图像,然后将其放在纹理页面上然后用于渲染.我们使用glTexSubImage2d上传来修改纹理页面的一部分.我们不保留系统副本.每当我们这样做时,我们在glTexSubImage2d调用中有一个六帧延迟.我们在游戏开始之前将大部分图像加载到纹理上,但有些东西必然是动态的.

我假设整个渲染管道,无论是双缓冲还是三缓冲都被刷新,因为我想修改它正在使用的纹理,或者有一个引用.即便如此,六帧加(0.1秒)似乎过度.我们在IOS上完全相同,并且在修改纹理时几乎没有注意到任何延迟.游戏通常在1或2帧上运行.

任何人都知道发生了什么事?这是在三星Galaxy Note GTN7000上运行的.我们正在使用SurfaceView类.你能"关掉这个摊位"吗?我理解这可能意味着一个框架左右的人工制品,其中渲染可能没有更新的纹理.

此外,任何想法如何知道或设置内部是否是双缓冲或三缓冲.

我还读到,大多数桌面/ PC OpenGL驱动程序通过拥有两个或三个纹理副本并仅更新当前未使用的纹理,然后及时更新副本来解决这个问题.我们根本就没有记忆!

谢谢

肖恩

Muz*_*zza 2

Mali GPU(用于 N7000)是这种纹理上传停顿最严重的 GPU。其他 GPU 处理得更好(或者至少驱动程序处理得更好)。

我遇到了与您描述的完全相同的问题,对我来说唯一的解决方案是保留纹理数据的 CPU 副本,并对纹理进行三重缓冲。每当我修改纹理时,我仅修改 CPU 副本,并将纹理标记为脏。在每一帧开始时,如果缓冲区已更新,我会循环三个纹理并对其中一个执行 glTexSubImage2D,然后该纹理将成为活动纹理。

如果您使用的纹理少于三个,或者如果您犯了任何错误并且在最后两帧内使用了您执行 glTexSubImage2D 的纹理,它仍然会停止。

我仅在检测到 Mali GPU 时执行此操作(检查驱动程序 GL 字符串)。对于其他 GPU 和 iOS,驱动程序足够好,不需要三重缓冲(因此我也不必保留数据的 CPU 副本)。我确实在 Arm/Mali 开发者论坛上查看了有关此问题的信息,他们建议使用三重缓冲。不过,您不需要超过三个。

我取得了一些有限成功的另一个解决方法是在 Mali GPU 上始终使用 glTexImage2D 而不是 glTexSubImage2D。这需要保留纹理数据的 CPU 端副本。在我的测试中它的执行速度要快得多,大概是因为在驱动程序中它正在制作纹理的新副本,因此如果仍在使用先前的纹理,则不必停止。

我也实现了另一种可能的解决方案,但不再使用。您可以使用 Android GraphicBuffers。有关一些基本信息,请参阅此链接:在 Android 上使用直接纹理 这种方法可以让您在没有停顿的情况下写入纹理,但是,它不是官方支持的 API,我只能让它在 Mali 上工作,并且需要付出很大的努力。它本身并不能完全解决问题,因为您仍然需要自己进行同步控制,否则您的应用程序可能会在使用纹理数据时覆盖纹理数据,最终导致屏幕上出现一些损坏。