Android OpenGL ES:自动更正env-> self和NvRmChannelSubmit失败

dol*_*hin 5 java-native-interface android opengl-es-2.0

下面两个问题.

我们有一个图形OpenGL ES 2应用程序,在Windows,Linux,MacOS,iPhone,iPad和Android手机上运行了好几年.在过去的几个月里,我们开始收到一些Android设备用户的反馈(如Toshiba Thrive,HTC One X,Nexus 7或Asus Transformer,API 15和17),关于黑屏或闪烁屏幕的问题,或很少,应用程序崩溃.我们的应用程序针对API 9及以上,它是使用NativeActivity在NDK中编写的,直接基于nvidia android示例和演示,它已经在所有平台上进行了彻底测试,没有内存泄漏,没有无效的内存访问,它很少调用一些小的java码.

看看LogCat,我们注意到这些设备上有两种错误消息:

(1) JNI ERROR: env->self != thread-self (0x11734c0 vs. 0xd6d360); auto-correcting

(2)NvRmChannelSubmit failed (err = 196623, SyncPointValue = 0)其次是GL_OUT_OF_MEMORY

关于(1),我们知道线程与JNI问题,我们希望知道如何解决这个问题.我已经阅读了这些信息,我的问题是:"自动更正"是否意味着我们必须担心一些错误,或者它只是一个警告意味着代码在未来会表现得很糟糕,但现在它运行得很好(更正!)这与问题(2)无关?我问的原因是有时候我们也会看到以下几行:

E/libEGL: call to OpenGL ES API with no current context (logged once per thread)
E/NvEGLUtil: Failure: eglSwapBuffers, error = 0x0000300d (swap:422)
Run Code Online (Sandbox Code Playgroud)

哪个看起来很认真 我们已经在启用了JNIcheck的API 17模拟器上测试了我们的应用程序 - 没有报告任何问题,并且应用程序运行良好.

现在,关于消息(2),我找到了一些论坛(例如这里,这里也是这个),人们报告了这个消息,原因尚不清楚.看起来像固件或驱动程序问题,或GPU内存泄漏或内存碎片...许多游戏都受到屏幕闪烁的影响,人们正在尝试重启/重置设备,清除缓存,升级等,但问题似乎仍然存在.这个问题涉及很多流行的设备.尽管有GL_OUT_OF_MEMORY错误代码,但"没有足够的内存"是不合理的,因为我们用于测试的应用程序使用的是小型32x32纹理而不是常规版本中使用的512x512纹理(这些更大的纹理在旧设备上运行得非常好).任何人都有如何解决这个问题的经验,这在我们这方面是否可以解决?这是官方确认的硬件/固件/操作系统错误吗?我正在寻找一个已知的原因和这个问题的真正解决方案,而不是一个在不知道原因的情况下会意外帮助的试错工作方法.

谢谢!

dol*_*hin 0

因此,经过几年的尝试找出问题所在,是时候给出答案了:-) 这个问题非常痛苦、耗时且难以(几乎不可能)调试,它是不确定的、罕见的,只会影响某些特定设备,它似乎与系统的特定版本相关,甚至与同时运行(或不运行)其他程序相关......

\n\n

在我们的 C++ 代码中,在 nvidia 框架函数的末尾,bool Engine::initUI()我们调用了我们自己的keepScreenOn(getApp())函数,该函数使用当前活动的参数,调用了我们自己的静态 java 方法:

\n\n
//Keep the screen on.\n//Note that flag modification must be done in the UI thread:\n//https://android-developers.googleblog.com/2009/05/painless-threading.html\nstatic void keepScreenOn(Activity a) {\n    final Window w = a.getWindow();\n    if (w != null) {\n        a.runOnUiThread(new Runnable() {\n            public void run() {\n                w.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);\n            }\n        });\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

据我了解,修改 Window 标志会导致窗口被销毁并重新创建(如果我错了,请纠正我),这在应用程序启动过程中显然不是一个好主意。似乎这就是导致 \xe2\x80\x93 的原因,尽管极其罕见 \xe2\x80\x93 线程之间的一些竞争条件或某些图形驱动程序的问题......这导致延迟的错误消息,例如“NvRmChannelSubmit failed (err = 196623) ,SyncPointValue = 0)”,然后是“GL_OUT_OF_MEMORY”。

\n\n

设置窗口标志导致如此延迟的 GL 问题的事实令人惊讶,并且不是通过演绎发现的(我们花了几年时间试图在 OpenGL 代码中找到此问题的原因)。它是通过无望地注释掉任何可能影响显示的代码片段而发现的......解决方案是引入我们自己的子类,该子类NativeActivity从一开始就使用正确的标志创建主应用程序窗口:

\n\n
public class OurSubclassOfNativeActivity extends NativeActivity\n{\n    @Override\n    protected void onCreate(Bundle savedInstanceState)\n    {\n        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);   \n        super.onCreate(savedInstanceState);\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

我们想避免引入我们自己的 子类NativeActivity,但似乎需要设置强制FLAG_KEEP_SCREEN_ON我们这样做。

\n