Framebuffer FBO рендерится на текстуру очень медленно, используя OpenGL ES 2.0 на Android, почему?
Я программирую игру для Android 2d, используя opengl es 2.0. После того, как я рисую свои спрайты в буфер, я рисую источники света в FBO и пытаюсь снова смешать их с задним буфером. Когда я рисую FBO в кадровом буфере, даже прозрачном без какого-либо цвета, частота кадров падает с 60 до 30 на Samsung Galaxy w (у него adreno 205 как gpu). Я искал везде и пробовал все, даже если я рисую один спрайт на сцене и смешиваю прозрачную текстуру FBO с экраном, частота кадров падает. Я пробовал другие игры со световыми эффектами на этом телефоне, и они работают нормально, почти все игры на этом телефоне хороши, я думаю, что они также используют кадровый буфер. На Galaxy SII (mali 400 gpu) работает нормально, я новичок в opengl, поэтому я считаю, что я где-то ошибаюсь, я делюсь своим кодом.
// 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);
Я делаю это один раз при создании поверхности. Не уверен, если это правильно. Я сохраняю идентификаторы текстур и кадрового буфера, чтобы переключаться на них, когда мне это нужно. Мой код для рисования:
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();
Все отображается правильно на экране, но производительность ухудшается, когда я рисую текстуру FBO. Большое спасибо за Вашу помощь. Я очень много работал над этим и не нашел решения.
1 ответ
В соответствии с документами qualcomm, после каждого glbindframebuffer необходимо указывать, что это проблема, связанная с мозаичной архитектурой. Если вы переключаете кадровые буферы, данные должны копироваться из fastmem в обычную память для сохранения текущего кадрового буфера и из slowmem в fast mem для получения содержимое нового связанного фрейма, в случае, если вы очищаете сразу после glbind, никакие данные не копируются из slowmem в fastmem, и вы экономите время, но вам нужно часто переделывать конвейер рендеринга, чтобы он не читал данные назад и вперед между медленным и медленным быстрая память, поэтому старайтесь делать glclear после каждой привязки, и это должно помочь, вы также можете использовать adreno profiler для получения дополнительной информации о проблемных вызовах, но я сомневаюсь, что это поможет с adreno200. Я пытаюсь получить два буфера для размытия, и я заканчивая 10fps, вызов bindframebuffer может занять до 20 мсек, если он не очищен, если это так, он должен заканчиваться на 2 мс.