Android 双缓冲减慢帧渲染| systrace分析

Android 双缓冲减慢帧渲染| systrace分析,android,graphics,double-buffering,systrace,Android,Graphics,Double Buffering,Systrace,我在一个简单的2D游戏中使用自定义视图画布绘制(postInvalidate())和。经过数周的性能分析,我决定通过接口将我的更新和绘图操作与VSYNC脉冲同步。我认为这是获得流畅动作的正确方法 然而,我仍在经历波涛汹涌的运动。我用进行了分析,发现is与我的缓冲队列有关。一旦设置双缓冲,帧时间就会超过16ms。我对我的追踪做了一个截图,并做了一些解释: 整个绘制操作等待SurfaceFlinger(使用者)的缓冲区释放,以使其自己的新空缓冲区出列 你能告诉我这是不是一种正常的行为或者是什么原因

我在一个简单的2D游戏中使用自定义视图画布绘制(postInvalidate())和。经过数周的性能分析,我决定通过接口将我的更新和绘图操作与VSYNC脉冲同步。我认为这是获得流畅动作的正确方法

然而,我仍在经历波涛汹涌的运动。我用进行了分析,发现is与我的缓冲队列有关。一旦设置双缓冲,帧时间就会超过16ms。我对我的追踪做了一个截图,并做了一些解释:

整个绘制操作等待SurfaceFlinger(使用者)的缓冲区释放,以使其自己的新空缓冲区出列


你能告诉我这是不是一种正常的行为或者是什么原因吗

在图形上,您有一个注释,“SurfaceFlinger未命中VSYNC”

但是,如果查看BufferQueue行,可以看到缓冲区在VSYNC截止日期之后到达。苏菲林格醒了,但无事可做

然后,你的应用程序提供了一个额外的缓冲区,这意味着你有两个等待处理的缓冲区。由于您继续在每个VSYNC上提供一个缓冲区,因此队列从未恢复到零缓冲区。由于队列已满,每次尝试添加额外缓冲区都会导致阻塞

FWIW,您的缓冲队列是三重缓冲的:两个在队列中,一个在显示屏上

您可以做以下几件事:

  • 如果您错过了最后期限,请让应用程序删除框架
  • 指定帧的显示时间,以便在时间过了时SurfaceFlinger将删除这些帧
  • 每隔一段时间故意放下一帧,让队列清空。(不是首选方法。)
  • #2只适用于SurfaceView上的GLES,因此我们可以忽略该选项

    #我可能会为你工作;你可以看到一个。它本质上是说,“如果下一个VSYNC在不到2ms的时间内启动,或者已经启动了,不要麻烦渲染当前帧。”但是,查看/失效方法并没有提供与GLES相同的细粒度控制,所以我不确定这会有多好

    在繁忙的设备上平滑动画的关键不是以每秒60帧的速度播放每一帧。关键是让你的更新基于增量时间,这样即使你投下一两帧,事情看起来也很顺利


    有关图形体系结构的更多详细信息,请参阅。

    谢谢您的详细回答!我决定使用GLSurfaceView实现OpenGL ES 1。现在,我在onDrawFrame()方法中测量每个帧中的增量时间。在过去的帧时间内进行额外的插值(以消除较大的“口吃跳跃”)是一个很大的改进。现在我的游戏运行非常顺利!