Framebuffer FBO renderowanie do tekstury jest bardzo wolne, używając OpenGL ES 2.0 na Androida, dlaczego?

Programuję grę 2D na Androida za pomocą opengl es 2.0. Po narysowaniu moich spritów do bufora tylnego rysuję światła do FBO i próbuję ponownie połączyć je z buforem tylnym. Kiedy rysuję FBO do bufora ramek, nawet trasparent bez żadnego koloru, framerates spada z 60 do 30 na Samsung Galaxy W (ma adreno 205 jako gpu). Szukałem wszędzie i próbowałem wszystkiego, nawet jeśli narysuję pojedynczy sprite na scenie i zmieszam trasparent tekstury FBO na ekranie spada liczba klatek na sekundę. Próbowałem innych gier z efektami świetlnymi na tym telefonie i działają dobrze, prawie każda gra jest w porządku na tym telefonie, wierzę, że używają również bufora ramki. NA Galaxy SII (mali 400 gpu) działa dobrze, jestem całkiem nowy w opengl, więc wierzę, że gdzieś popełniam błąd, dzielę się moim kodem.

// Create a framebuffer and renderbuffer
GLES20.glGenFramebuffers(1, fb, offset);
GLES20.glGenRenderbuffers(1, depthRb, offset);

// Create a texture to hold the frame buffer
GLES20.glGenTextures(1, renderTex, offset);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, renderTex[offset]);

GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA,
                    screenWidth, screenHeight, 0,
                    GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE,
                    null);


GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,
                       GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,
                       GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER,
                       GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,
                       GLES20.GL_LINEAR);

//bind renderbuffer
GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, depthRb[offset]);

GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER, GLES20.GL_DEPTH_COMPONENT16,
                             screenWidth, screenHeight);

// bind the framebuffer
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fb[offset]);

// specify texture as color attachment
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0,
                              GLES20.GL_TEXTURE_2D, renderTex[offset], 0);

// specify depth_renderbufer as depth attachment
GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_DEPTH_ATTACHMENT,
                                 GLES20.GL_RENDERBUFFER, depthRb[0]);

// Check FBO status.
int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER);

if ( status == GLES20.GL_FRAMEBUFFER_COMPLETE )
{
    Log.d("GLGame framebuffer creation", "Framebuffer complete");
}


// set default framebuffer
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
Robię to raz na powierzchni. Nie jestem pewien, czy to prawda. Zachowuję identyfikatory texture i framebuffer, aby przełączyć się na nie w razie potrzeby. Mój kod do rysowania:
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);
ShaderProgram program = glgame.getProgram();

//put vertices in the floatbuffer
mTriangleVertices.put(vertices, 0, len);
mTriangleVertices.flip();

GLES20.glVertexAttribPointer(program.POSITION_LOCATION, 2, GLES20.GL_FLOAT, false,
                             TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);

//preparing parameter for texture position
mTriangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET);
GLES20.glEnableVertexAttribArray(program.POSITION_LOCATION);

//preparing parameter for texture coords
GLES20.glVertexAttribPointer(program.TEXTURECOORD_LOCATION, 2, GLES20.GL_FLOAT,
                             false, TRIANGLE_VERTICES_DATA_STRIDE_BYTES,
                             mTriangleVertices);

//set projection matrix
GLES20.glEnableVertexAttribArray(program.TEXTURECOORD_LOCATION);
GLES20.glUniformMatrix4fv(program.MATRIX_LOCATION, 1, false, matrix, 0);

//draw triangle with indices to form a rectangle
GLES20.glDrawElements(GLES20.GL_TRIANGLES, numSprites * 6, GLES20.GL_UNSIGNED_SHORT,
                      indicesbuf);

//clear buffers
mTriangleVertices.clear();
mVertexColors.clear();

Wszystko jest renderowane na ekranie poprawnie, ale wydajność jest zrujnowana właśnie wtedy, gdy rysuję teksturę FBO. Dziękuję bardzo za pomoc. Ciężko nad tym pracowałem i nie znalazłem rozwiązania.

Author: abergmeier, 2012-05-24

1 answers

Zgodnie z Qualcomm docs, musisz glclear po każdym buforze glbindframebuffer, jest to problem związany z architekturą kafelkową, jeśli przełączasz bufory ramek, dane muszą być kopiowane z fastmem do normalnej pamięci, aby zapisać bieżący bufor ramek i z slowmem do fast mem, aby uzyskać zawartość nowo bindowanej ramki, w przypadku gdy czyścisz tuż po glbind żadne dane nie są kopiowane ze slowmem do fastmem i oszczędzasz czas, ale musisz przeprojektować swój rurociąg renderowania często, więc będzie unikaj czytania danych tam iz powrotem między powolną i szybką pamięcią, więc spróbuj zrobić glclear po każdym wiązaniu i powinno to pomóc, możesz również użyć adreno profiler, aby uzyskać dodatkowe informacje o problematycznych połączeniach, ale wątpię, że pomoże to z adreno200 próbuję uzyskać dwa bufory dla rozmycia i kończę na 10fps, połączenie bindframebuffer może trwać do 20msec, jeśli nie jest wyczyszczone, jeśli jest, powinno zakończyć się na 2ms.

 12
Author: ZZZ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-15 14:13:41