无法跟踪从另一个线程渲染的帧

时间:2018-08-09 17:00:48

标签: android opengl-es systrace

我们公司开发了多种移动平台游戏,包括Android。我们将OpenGL用于所有可视项,包括UI(更多技术细节在下面)。

我们在发布前的报告中从Google Play控制台收到了一些奇怪的警告,例如“您的应用启动需要20764毫秒”。在此报告随附的视频中,游戏耗时约一秒钟开始。

经过一些调查,我们发现Android Systrace无法检测到从另一个线程进行的OpenGL绘制。因此,发布前测试(错误地)认为我们的游戏非常慢。

是否有某种方法可以通知系统已绘制边框?似乎eglSwapBuffers()不够。

与Cocos2d相同的问题有一个链接:https://discuss.cocos2d-x.org/t/frozen-frames-warnings-by-google-play-pre-launch-report-for-3-17-cocos-demo-app/42894

一些细节

将新版本发布到Google Play控制台后,会在不同设备上执行一些自动测试。这些测试的结果可在Google Play控制台的预发布报告部分中找到。

从4月初开始,我们在某些设备(总是相同的设备)上收到奇怪的性能警告。两个例子:

  • 启动时间:您的应用需要20764毫秒才能启动...
  • 冻结的帧:33.33%的帧渲染时间超过了700ms

这两个问题听起来都是可怕的-他们会是真的吗?但是,当我们检查测试视频时,我们看不到任何问题。所有游戏的启动速度都非常快,并且运行时不会出现视觉卡顿现象。

Systrace报告

这是systrace的图片,显示了我们游戏开始5秒钟(我画了矩形)。

systrace

如您所见,systrace仅发现了从RenderThread绘制的4个渲染帧(粉红色矩形)。但是由于某种原因,Android无法检测到我们在其他线程(蓝色矩形)中执行的GL绘制调用。

发布前报告还仅显示3到4帧,每帧长300-400毫秒。

初始化代码

我们的游戏引擎在单独的线程中运行所有游戏逻辑并渲染代码。这是简化的初始化代码。

工作线程是通过Activity的onStart()重写方法创建的。

public class MyActivity extends Activity
{
    protected Thread worker = null;

    private native void Run();

    @Override
    protected void onStart()
    {
        super.onStart();

        if(worker == null)
        {
            worker = new Thread()
            {
                public void run()
                {
                    Run();
                }
            };

            worker.start();
        }
    }
}

线程唯一要做的就是Run()本机函数。此功能可以解析为以下形式:

void MyActivity::Run()
{
    initApp();

    while(!destroyRequested())
    {
        // Process the game logic.
        if (activated && window != NULL)
        {
            time->process();
            input->process();
            sound->process();
            logic->process();
            graphics->draw();
        }
    }

    clearApp();
}

如您所见,辅助线程不断旋转更新和绘制循环。 Vsync可防止环路性能过高。资源加载等繁重的操作是异步完成的,以避免冻结。

从用户方面来看,这种方法很好用。游戏加载迅速且运行顺利。

0 个答案:

没有答案