我试图让一个非常简单的openGL ES 1程序在几个设备上以平稳的60fps稳定运行,而我却陷入了HTC的渴望。手机本身快速,灵活,功能强大,使用起来轻而易举;但是,使用OpenGL,我似乎无法以60fps全屏显示任何内容。在长时间困扰我的应用程序之后,我决定直接从文档中的示例代码制作一个带有代码的测试应用程序。
这是我在做什么。使用GLSurfaceView的简单初始化代码。我有三个版本的onDrawFrame,都死了很简单。一个是空的。一个仅包含glClear。一个仅包含足够的状态以仅绘制全屏四边形。跟踪之前和之后的时间。除了我的程序中的GLSurfaceView外,没有其他视图。我无法解释我得到的时间。
在所有情况下,onDrawFrame函数本身总是在2ms以下完成。但是很多时候,onDrawFrame在30〜40ms之前不会再次被调用,这使我的帧速率一直下降到30fps或更小。
使用空的onDrawFrame可以达到约50fps,使用glClear可以达到45fps,使用Quad时可以达到35fps。
相同的代码在HTC Magic,Samsung Galaxy S和Sharp ISO1上以60 fps的速度运行。由于其屏幕,Sony Experia X10的上限为稳定的30fps。我在HTC Magic上以稳定的60fps进行了更为复杂的场景,与Desire相比,这种功能的功能非常弱。我没有要测试的Nexus One。
当然,除了缓冲区交换要阻塞几毫秒。但是它一直都在跳过帧。
为了找出电话在onDrawFrame处理程序之外的功能,我尝试使用Debug.startMethodTracing。我无法获得跟踪信息来反映手机花费在环路之外的实际时间。
在onDrawFrame的结尾,我使用startMethodTracing,然后将当前时间(SystemClock.uptimeMillis)保存在变量中。在下一个开始时,我记录自该函数上次退出以来的时间差,然后停止方法跟踪。这将一遍又一遍地被调用,因此一旦安排了40毫秒以上的暂停跟踪,我便安排停止。
结果轨迹上的时间标度小于2毫秒,好像系统在我的程序之外花费了38毫秒。
我尝试了很多事情。枚举EGL配置并一个接一个地尝试。只看它是否有任何变化,当脏方案要求在每帧重绘时,我切换到了渲染。无济于事。无论我做什么,交换缓冲区的预期间隔为14〜16ms大约需要30 + ms的一半时间,无论我做什么,似乎设备正在等待两次屏幕刷新。设备上的ps显示我的应用程序的cPU约为10%,System_server约为35%。当然,我也尝试了显而易见的方法,杀死了其他进程,重新启动了设备……我总是得到完全相同的结果。
画布绘制没有相同的问题。
有谁知道欲望(以及仅渴望欲望)为什么会这样表现?
供参考,这是我的测试代码如下所示:
public class GLTest extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mGLView = new GLSurfaceView(this);
mGLView.setRenderer(new ClearRenderer());
setContentView(mGLView);
}
@Override
protected void onPause() {
super.onPause();
mGLView.onPause();
}
@Override
protected void onResume() {
super.onResume();
mGLView.onResume();
}
private GLSurfaceView mGLView;
}
class ClearRenderer implements GLSurfaceView.Renderer {
public void onSurfaceCreated(GL10 gl, EGLConfig config) {}
public void onSurfaceChanged(GL10 gl, int w, int h) { gl.glViewport(0, 0, w, h); }
long start;
long end;
public void onDrawFrame(GL10 gl)
{
start = System.currentTimeMillis();
if (start - end > 20)
Log.e("END TO START", Long.toString(start - end));
// gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
end = System.currentTimeMillis();
if (end - start > 15)
Log.e("START TO END", Long.toString(end - start));
}
}
最佳答案
您应该看看这个http://www.google.com/events/io/2010/sessions/writing-real-time-games-android.html
他建议您将帧率保持在30fps,而不是60fps。