Framebuffer FBO render texture very slowly using OpenGL ES 2.0 on Android, why?

I am programming an Android 2d game using opengl es 2.0. After I draw the sprites for the buffer, I draw the lights in the FBO and again try to mix it with the back buffer. When I draw FBO in a framebuffer, even transparent without any color, the framemaker drops from 60 to 30 on the Samsung Galaxy w (it has adreno 205 as gpu). I searched everywhere and tried everything, even if I draw one sprite on the scene and mix the transparent FBO texture on the screen, the frame rate drops. I tried other games with lighting effects on this phone, and they work fine, almost every game is fine on this phone, I believe that they also use a framebuffer. On Galaxy SII (mali 400 gpu) it works fine, I'm completely new to opengl, so I think I'm doing something, I am sharing my code.

// 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); 

I do this once when creating a surface. Not sure if this is correct. I save the texture and framebuffer identifiers to switch to them when I need to. My drawing code:

 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(); 

Everything displays correctly on the screen, but the performance crashes when I paint the FBO texture. Many thanks for your help. I worked a lot on this and did not find a solution.

+6
source share
1 answer

According to qualcomm docs, you need glclear after each glbindframebuffer, this is a tiled architecture problem, if you switch framebuffers, the data needs to be copied from fastmem to normal memory to save the current framebuffer and from slowmem to fast mem to get the contents of the newly bound frame, in case you clear immediately after glbind, no data is copied from slowmem to fastmem, and you saved time, but you often need to redo the rendering pipeline, so it avoids reading the data back and forth between slow oh and fast memory, so try to do glclear after each binding, and this should help, you can also use the adreno profiler for more information about problem calls, but I doubt it will help with adreno200. I try to get two buffers for blur and I end up with 10fps, the bindframebuffer call can take up to 20 ms if it is not cleared, if it should end in 2 ms.

+12
source

Source: https://habr.com/ru/post/916507/


All Articles