5

下面两个问题。

我们有一个图形 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示例和demo,在所有平台上经过彻底测试,无内存泄漏,无无效内存访问,很少调用一些小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)

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

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

谢谢!

4

1 回答 1

0

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

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

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

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

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

public class OurSubclassOfNativeActivity extends NativeActivity
{
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);   
        super.onCreate(savedInstanceState);
    }
}

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

于 2018-11-08T17:37:44.683 回答