2

Android NDK で可能な最速の 2D フレーム レート、私の試行が含まれています。より良いオプションを利用できますか?

NDK と OpenGL ES 2.0 を使用して、フレームをテクスチャとして GL_TRIANGLE_STRIP に表示しました。これは、Nexus One と同じハードウェアである HTC Desire で行われました。複数の GL_RGBA テクスチャを読み込んで、テクスチャを切り替えようとしました。

  • 1 テクスチャ: 4.78 fps
  • 2 テクスチャ: 19.68 fps
  • 3 テクスチャ: 20.18 fps
  • 4 テクスチャ: 28.52 fps
  • 5 テクスチャ: 29.01 fps
  • 6 テクスチャ: 30.32 fps

30.32 fps の RGBA でもまだ遅すぎると思います。

では、これは最速の 2D フレーム レート (同じ品質で) を達成するための方法ですか? それをスピードアップするための提案はありますか?

関連するコードは次のとおりです。これは、hello-gl2 NDK の例に基づいています。

=== GL2JNIView.java :

init(false, 0, 0);
ConfigChooser(5, 6, 5, 0, depth, stencil);

=== gl_code.cpp :

#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>

#include <android/log.h>

#include <stdlib.h>
#include <time.h>

typedef unsigned char byte;

static int view_width, view_height;
static byte* framebuffer;
static int framebuffer_size;
static GLuint texture_id[6];
static const char* vertexSrc =
 "precision highp float;\n"
 "precision highp int;\n"
 "attribute vec4 vertexCoords;\n"
 "attribute vec2 textureCoords;\n"
 "varying vec2 f_textureCoords;\n"
 "void main() {\n"
 "  f_textureCoords = textureCoords;\n"
 "  gl_Position = vertexCoords;\n"
 "}\n";
static const char* fragmentSrc  =
 "precision highp float;\n"
 "precision highp int;\n"
 "uniform sampler2D texture;\n"
 "varying vec2 f_textureCoords;\n"
 "void main() {\n"
 "  gl_FragColor = texture2D(texture, f_textureCoords);\n"
 "}\n";
static GLuint shaderProgram;
static GLint attrib_vertexCoords;
static GLint attrib_textureCoords;
static GLint uniform_texture;
static const GLfloat vertexCoords[] = {-1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0};
static const GLfloat textureCoords[] = {0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0};

JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_init(JNIEnv * env, jobject obj,  jint width, jint height) {
 view_width = width;
 view_height = height;

 framebuffer_size = 4*view_width*view_height;
 framebuffer = (byte*)calloc(framebuffer_size, sizeof(byte));
 for (int i = 0; i < framebuffer_size; i++) framebuffer[i] = 0;

 glViewport(0, 0, view_width, view_height);

 glGenTextures(6, &texture_id[0]);
 glActiveTexture(GL_TEXTURE0);
 glBindTexture(GL_TEXTURE_2D, texture_id[0]);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, view_width, view_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer);
 glActiveTexture(GL_TEXTURE1);
 glBindTexture(GL_TEXTURE_2D, texture_id[1]);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, view_width, view_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer);
 glActiveTexture(GL_TEXTURE2);
 glBindTexture(GL_TEXTURE_2D, texture_id[2]);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, view_width, view_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer);
 glActiveTexture(GL_TEXTURE3);
 glBindTexture(GL_TEXTURE_2D, texture_id[3]);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, view_width, view_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer);
 glActiveTexture(GL_TEXTURE4);
 glBindTexture(GL_TEXTURE_2D, texture_id[4]);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, view_width, view_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer);
 glActiveTexture(GL_TEXTURE5);
 glBindTexture(GL_TEXTURE_2D, texture_id[5]);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, view_width, view_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer);

 shaderProgram = glCreateProgram();
  GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
  glShaderSource(vertexShader, 1, &vertexSrc, NULL);
  glCompileShader(vertexShader);
 glAttachShader(shaderProgram, vertexShader);
  GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
  glShaderSource(fragmentShader, 1, &fragmentSrc, NULL);
  glCompileShader(fragmentShader);
 glAttachShader(shaderProgram, fragmentShader);
 glLinkProgram(shaderProgram);
 glUseProgram(shaderProgram);

 uniform_texture = glGetUniformLocation(shaderProgram, "texture");
 glUniform1i(uniform_texture, 0);

 attrib_vertexCoords = glGetAttribLocation(shaderProgram, "vertexCoords");
 glEnableVertexAttribArray(attrib_vertexCoords);
 glVertexAttribPointer(attrib_vertexCoords, 2, GL_FLOAT, GL_FALSE, 0, vertexCoords);

 attrib_textureCoords = glGetAttribLocation(shaderProgram, "textureCoords");
 glEnableVertexAttribArray(attrib_textureCoords);
 glVertexAttribPointer(attrib_textureCoords, 2, GL_FLOAT, GL_FALSE, 0, textureCoords);
}

JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_step(JNIEnv * env, jobject obj) {
 static int frame_count = 0;
 static clock_t last_time = clock();
 static int last_frame_count = 0;

 frame_count++;
 if (clock()-last_time > 1e7) {
  __android_log_print(ANDROID_LOG_INFO, "libgl2jni", "fps: %f", ((float)frame_count-last_frame_count)/(clock()-last_time)*1e6);
  last_time = clock();
  last_frame_count = frame_count;
 }

 static byte val = 0;
 val++;
 if (val == 256) val = 0;
 for (int i = 0; i < framebuffer_size; i++) framebuffer[i] = val;

 int tst = frame_count%6;
 if (tst == 0) {
  glActiveTexture(GL_TEXTURE0);
 } else if (tst == 1) {
  glActiveTexture(GL_TEXTURE1);
 } else if (tst == 2) {
  glActiveTexture(GL_TEXTURE2);
 } else if (tst == 3) {
  glActiveTexture(GL_TEXTURE3);
 } else if (tst == 4) {
  glActiveTexture(GL_TEXTURE4);
 } else if (tst == 5) {
  glActiveTexture(GL_TEXTURE5);
 }
 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, view_width, view_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer);
 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
4

2 に答える 2

9

あなたの質問はかなり古いものであり、おそらく解決したか、別のものに移動した可能性がありますが、他の誰かがこれに出くわした場合に備えて提案します.

まず第一にglTexImage2D、テクスチャ パラメータは呼び出し間で変化する可能性があるため、呼び出すたびにグラフィックス サブシステムがメモリの解放とテクスチャ オブジェクトの再割り当てを実行する必要があります。最適化されたドライバーは、幅、高さ、および形式を確認し、それらがすべて同じである場合、再割り当てをスキップできますが、Android ドライバーの実装者が実際にこれを行っている可能性は低いです。

テクスチャの再割り当てを完全に回避するには、 を使用glTexSubImage2Dして、ビットマップ全体またはその一部だけを置き換えることができます。これを上記のテクスチャ バッファリング スキームと組み合わせると、速度が大幅に向上するはずです。これを拡張して、ディスプレイの変更された領域を検出し、フレーム間で変更された長方形の部分のみを更新することもできます。

要約すると、テクスチャの初期化コードを変更glTexImage2Dして、NULL ビットマップ ポインタで呼び出すようにします。これにより、OpenGL はテクスチャにメモリを割り当てるだけで、実際には次のようにデータをコピーしません。

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, view_width, view_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

次に、ゲーム ループのすべてのフレームを次のように更新します。

glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, view_width, view_height, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer);
于 2011-04-04T11:34:24.140 に答える