1

我已经为 Android 编写了一个 OpenGL ES 3.1 应用程序,并且我正在与一个特定平台 ARM Mali GPU 上的问题作斗争。该程序似乎可以在 Adreno 和 PowerVR GPU 上正确运行。

一帧由多个渲染通道组成。渲染通道在着色器存储缓冲区对象和原子计数器的帮助下进行通信。整个事情看起来像这样:

Pass1_Initialize_SSBO_and_Atomic();
glMemoryBarrier(GL_ALL_BARRIER_BITS);

Pass2_Fill_SSBO_With_initial_Data();
glMemoryBarrier(GL_ALL_BARRIER_BITS);

for(i=0;i<N;i++)
   {
   Pass3_Render_Object(i);
   glMemoryBarrier(GL_ALL_BARRIER_BITS);
   }

Pass4_Compose_Everything();

现在,问题是在马里屏幕一直在闪烁。我做了很多录音,并逐帧观看。发生的情况是,大约 95% 的帧看起来是正确的,但每隔一段时间就会有一个任意的对象子集消失,然后在下一帧中重新出现。

############################################

问题是,我不知道是什么导致对象消失。到目前为止,我尝试的是继续删除代码以查看错误是否仍然存在 - 试图提出重现问题的最短代码段。这种方法失败了,因为我删除的代码越多,错误就越难以重现。最初它每秒大约持续发生两次,经过多次删除各种位后,我每分钟只能重现一次,最终我无法再重现它,但我不知道这是因为我刚刚删除了有问题的代码还是因为我刚刚通过了一些阈值,错误仍然存​​在,但现在很难重现。

我尝试的第二件事是通过查看 SSBO 来衡量错误。我在传递之间的某些时刻将其内存映射到 CPU,并确保它确实包含它应该包含的内容。不幸的是,只要我添加一个

glBindBuffer(GL_SHADER_STORAGE_BUFFER, mSSBO[0] );
glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, length, GL_MAP_READ_BIT);
(...) // print the buffer
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);

几乎在应用程序代码的任何地方,错误都会消失。

特别是,当我删除第一个 glMemoryBarrier() 并用上面的替换它时,错误完全消失了(我记录了 10 分钟的屏幕并逐帧观看,它消失了)。即使我根本不检查 CPU 上的缓冲区,也会发生这种情况,我只是映射它并立即取消映射(哪个 AFAIK 应该具有与 memoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT) 一样的效果??)这引起了人们的怀疑,可能是 glMemoryBarrier Mali 上的 (GL_SHADER_STORAGE_BARRIER_BIT) 有问题,所以我写了一个测试程序来看看 - 这证明 glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT) 工作得很好。

我还有一个 Mali Graphics Debugger,我可以将它连接到手机,但是当我这样做时,错误会立即消失。我停止追踪——它再次开始每秒闪烁两次。

你对如何处理这样的问题有什么建议吗?

代码是 GPL v2 并且完全可以下载——尽管它是 45k 行的 Java、XML 和 GLSL。如果有人想看看,这里是:

http

://distorted.org/redmine/projects/distorted-android/wiki/How_to_compile_and_run_the_example_code (需要查看'order-independent-transparency'分支;master运行良好)

4

0 回答 0