TL、まったく描画を行っていない場合でも、DRAndroidのEGL/OpenGL ESのフレームレート吃音
は、Androidデバイス上でのOpenGL ESのレンダリングスレッドで60Hzの更新率を維持することは不可能と思われます。不思議なスパイクは頻繁に盛り上がります(コードの下に表示されています)。カスタムレンダリングスレッドを使用したさらに複雑な例のタイミングでは、eglSwapBuffers()が頻繁に17ms-32msを超えて発生する原因となることが一貫して示されています。助けて?
詳細
我々のプロジェクトのレンダリングの要件が円滑他の画面の片側から速度の固定、高い速度で水平スクロール画面整列要素であるので、これは特に破滅的です。つまり、プラットフォームゲームです。 60Hzから頻繁に低下すると、時間ベースの動きの有無にかかわらず、目立つポッピングとぶら下がりが発生します。 30Hzでのレンダリングは、スクロール速度の高速化のために選択肢にはなりません。スクロール速度は設計の非交渉可能な部分です。
私たちのプロジェクトは、互換性を最大限に高めるためにJavaベースであり、OpenGL ES 2.0を使用しています。 API 7-8デバイスでのOpenGL ES 2.0レンダリング用のNDKと、API 7デバイスでのETC1サポートのみに絞り込みます。以下に示すテストコードとその両方で、ログ印刷と自動スレッド以外の割り当て/ GCイベントは制御できませんでした。
在庫のAndroidクラスを使用し、NDKを使用しない1つのファイルで問題を再現しました。下記のコードは、Eclipseで作成された新しいAndroidプロジェクトに貼り付けることができ、APIレベル8以上を選択している限り、すぐに使えるはずです。
試験のGPUとOSのバージョンの範囲でさまざまなデバイス上で再生された:
- ギャラクシータブ10.1(アンドロイド3.1)
- ネクサスS(アンドロイド2.3.4)
- ギャラクシーS II(アンドロイド2.3.3)
- XPERIAは(アンドロイド2.3.2)を再生
- ドロイド信じられない(アンドロイド2.2)
- ギャラクシーS(アンドロイド2.1アップデート1)(DR
Spike: 0.017554 Spike: 0.017767 Spike: 0.018017 Spike: 0.016855 Spike: 0.016759 Spike: 0.016669 Spike: 0.024925 Spike: 0.017083999 Spike: 0.032984 Spike: 0.026052998 Spike: 0.017372
私はしばらくの間、これを追いかけてきたし、約レンガを直撃している:レベル7までのAPIの要件)
実行時間の1秒の下から集められたサンプル出力を()opping壁。修正が利用できない場合は、少なくともこれがなぜ起こるかについての説明と、同様の要件を持つプロジェクトでこれがどのように克服されたかについてのアドバイスを大いにいただければ幸いです。
サンプルコード
package com.test.spikeglsurfview;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Window;
import android.view.WindowManager;
import android.widget.LinearLayout;
/**
* A simple Activity that demonstrates frequent frame rate dips from 60Hz,
* even when doing no rendering at all.
*
* This class targets API level 8 and is meant to be drop-in compatible with a
* fresh auto-generated Android project in Eclipse.
*
* This example uses stock Android classes whenever possible.
*
* @author Bill Roeske
*/
public class SpikeActivity extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// Make the activity fill the screen.
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
// Get a reference to the default layout.
final LayoutInflater factory = getLayoutInflater();
final LinearLayout layout = (LinearLayout)factory.inflate(R.layout.main, null);
// Clear the layout to remove the default "Hello World" TextView.
layout.removeAllViews();
// Create a GLSurfaceView and add it to the layout.
GLSurfaceView glView = new GLSurfaceView(getApplicationContext());
layout.addView(glView);
// Configure the GLSurfaceView for OpenGL ES 2.0 rendering with the test renderer.
glView.setEGLContextClientVersion(2);
glView.setRenderer(new SpikeRenderer());
// Apply the modified layout to this activity's UI.
setContentView(layout);
}
}
class SpikeRenderer implements GLSurfaceView.Renderer
{
@Override
public void onDrawFrame(GL10 gl)
{
// Update base time values.
final long timeCurrentNS = System.nanoTime();
final long timeDeltaNS = timeCurrentNS - timePreviousNS;
timePreviousNS = timeCurrentNS;
// Determine time since last frame in seconds.
final float timeDeltaS = timeDeltaNS * 1.0e-9f;
// Print a notice if rendering falls behind 60Hz.
if(timeDeltaS > (1.0f/60.0f))
{
Log.d("SpikeTest", "Spike: " + timeDeltaS);
}
/*// Clear the screen.
gl.glClear(GLES20.GL_COLOR_BUFFER_BIT);*/
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height)
{
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config)
{
// Set clear color to purple.
gl.glClearColor(0.5f, 0.0f, 0.5f, 1.0f);
}
private long timePreviousNS = System.nanoTime();
}
時計logcat出力あなたはJavaでそれを構築している場合、それは事実の寿命です。 Androidの新しいバージョンでは同時のGCがありますが、ときどき完全なGCと付随する一時停止を避けることは困難です。あなたは40fpsに満足し、同時GCを目指すべきです。 –