在Android上上传纹理时避免暂停
Avoiding stalls while uploading textures on Android
我们的游戏要求我们不断加载和创建新的图像,我们将这些图像放在纹理页面上,然后用于渲染。我们使用glTexSubImage2d上传来修改纹理页面的一部分。我们不保留系统副本。每当我们这样做时,我们在glTexSubImage2d调用中都会有六帧延迟。我们确实会在游戏开始前将大部分图像加载到纹理上,但有些东西一定是动态的。
我认为整个渲染管道,无论是双缓冲还是三缓冲,都会被刷新,因为我想修改它正在使用或引用的纹理。即使如此,六帧加(0.1秒)似乎也太多了。我们在IOS上也做了同样的操作,当纹理被修改时,你几乎不会注意到任何延迟。游戏通常在1或2帧上运行。
有人知道发生了什么事吗?这是在三星Galaxy Note GTN7000上运行的。我们正在使用SurfaceView类。你能"把这个摊位关掉"吗。我知道这可能意味着渲染可能没有更新纹理的帧左右的伪影。
此外,任何关于如何知道或设置其内部是双重缓冲还是三重缓冲的想法。
我还读到,大多数Desktop/PC OpenGL驱动程序都通过拥有两到三个纹理副本,只更新当前未使用的纹理副本,然后及时更新副本来绕过这一问题。我们根本没有记忆!
感谢
Shaun
马里GPU(用于N7000)是这种纹理上传停滞最糟糕的GPU。其他GPU处理得更好(或者至少驱动程序处理得更好)。
我遇到过与你描述的完全相同的问题,对我来说唯一的解决方案是保留纹理数据的CPU副本,并将纹理缓冲三倍。每当我修改纹理时,我只修改CPU副本,并将纹理标记为脏。在每帧开始时,如果缓冲区已经更新,我会循环这三个纹理,并在其中一个纹理上执行glTexSubImage2D,然后它就变成了活动纹理。
如果您使用的纹理少于三个,或者如果您犯了任何错误,并且在最后两帧内使用了glTexSubImage2D的纹理,它仍然会停滞。
我只在检测到马里GPU时才会这样做(检查驱动程序GL字符串)。对于其他GPU和iOS,驱动程序足够好,不需要三重缓冲(因此我也不必保留数据的CPU副本)。我确实在Arm/Mali开发者论坛上查看了这个问题,他们建议使用三重缓冲。不过你应该不需要超过三个。
我成功的另一个解决方法是在马里GPU上始终使用glTexImage2D而不是glTexSubImage2D。这需要保留纹理数据的CPU侧副本。它在我的测试中表现得更快,大概是因为在驱动程序中,它正在制作纹理的新副本,因此如果以前的纹理仍在使用,就不必停滞。
还有一种可能的解决方案,我也实现了,但不再使用。您可以使用Android GraphicBuffers。有关一些基本信息,请参阅此链接:在Android上使用直接纹理这种方法可以让你在没有停滞的情况下编写纹理,然而,它不是官方支持的API,我只能在马里使用它,而且需要付出很多努力。它本身并不能完全解决问题,因为你仍然需要自己进行同步控制,否则你的应用程序可能会在使用时覆盖纹理数据,最终导致屏幕上出现一些损坏。
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- OpenInventor从9.8升级到10.4.2后,GLSL纹理返回零
- SFML纹理像播放器
- OpenGL大的3D纹理(>2GB)非常慢
- UE4-如何在给定4个屏幕坐标的情况下缩放纹理或材质
- 着色器纹理值与创建纹理时写入的值不同
- OpenGL将纹理四边形渲染为(0,0)
- 宽度为奇数的16位纹理为片状
- 使用 CUDA 和纹理进行图像减法
- 在不使用统一的情况下将纹理传递给 GLSL 着色器?
- 将使用太多的纹理插值器 - 带旋转的着色器
- dx11 渲染到纹理仅显示透明颜色
- OpenGL 4.3 错误地将第 4 个纹理坐标映射到与第 3 个纹理坐标相同的位置
- 如何使用 DXGI 格式DXGI_FORMAT_R1_UNORM创建 2D 纹理?
- 如何暂停插孔音频客户端
- 纹理单位重叠?渲染了错误的纹理
- SFML 纹理变换(放大)
- SDL2 二维纹理分配/池化
- Qt OpenGL 渲染到纹理性能问题
- 在Android上上传纹理时避免暂停