Read the PBuffer (glReadPixels too Slow...)

Hi,

My program is rendered in a PBuffer and I wanted to know if there is another way better than glReadPixels() to access to the rendered Surface because I need to use it 45 times per second and know framerate falls to 17FPS ?
I don’t really need to copy the rendered Surface but just to read it… :frowning:

Does glGetPointerv works? How could I use it? I tried to use it but I don’t know exactly how… I am in the good way?

Hi Norwy,

Generally glReadPixels() is slow and should really only be used when doing screencapture at which point performance is non critical. The main cause for this loss of performance is due to synchronisation: the glReadPixels() call forces synchronisation between the CPU and the Graphics Core thus serialising them and resulting in lost CPU and Graphics Core performance. At which point it does not matter that much if you access only a single pixel or copy the whole buffer, you lost most of the performance with the synchronisation.

For most applications which access the render target there is usually some other way to achieve the same result without having to read the rendertarget. Could you explain in more detail why you are trying to acccess the rendered surface 45 times per second using glReadPixels ?

Thanks,

K-


Kristof Beets
Third Party Relations Manager
Business Development, PowerVR
www.imgtec.com

I am doing an offscreen rendering to put the result in a surface that I use in a 2D library (its a bit strange but it does exactly what I want with glReadPixels but it’s too slow) 45 times per second…

It’s like the Render to Texture Method except that I need to access directly to the buffer. Do you know how could I do it by this way ?

I made this:


unsigned char pixels = new unsigned char [glWindowWidth*glWindowHeight*4]; 
GLuint RenderedTex; 
glGenTextures(1, &RenderedTex); 
glBindTexture(GL_TEXTURE_2D, RenderedTex); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, glWindowWidth, glWindowHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); 
 
void drawScene(int width, int height) 
{ 
// Scene ... 
 
glEnable(GL_TEXTURE_2D); 
glBindTexture(GL_TEXTURE_2D, RenderedTex); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); 
} 

It’s typically the Render to Texture method but the problem is that I can not reach the modified internal buffer of the texture… And I don’t know why the last parameter pixels is required (it doesn’t work without)…

One thing you could try is to have multiple pbuffers, and while you render to one you read from another that was previously rendered to. That way you give the graphics core more time to finish rendering a certain frame before you try reading it. The number of pbuffers you need depends on the amount of command buffering the OpenGL ES implementation does. 3 or 4 might be a good number to start from.

Pseudocode:

// one time pbuffer initialization
EGLSurface pbuffer[NUM_PBUFFERS];
for (int i = 0; i < NUM_PBUFFERS; ++i)
    pbuffer[i] = eglCreatePbufferSurface(eglDisplay, eglConfig, attribs);

// per frame render target setup
void renderScene()
{
    static int frameNumber = 0;

    int writeBuffer = frameNumber % NUM_PBUFFERS;
    int readBuffer = (frameNumber + 1) % NUM_PBUFFERS;
    eglMakeCurrent(eglDisplay, pbuffer[writeBuffer], pbuffer[readBuffer], eglContext);
    ...

    frameNumber++;
}

There are only two ways to get the contents of a surface: glReadPixels and, if the surface is a pixmap, whatever way of access the native 2D graphics system provides. However, both methods have the same problem of synchronisation.

It’s typically the Render to Texture method but the problem is that I can not reach the modified internal buffer of the texture… And I don’t know why the last parameter pixels is required (it doesn’t work without)…

You just upload an array of bytes to the OpenGL ES implementation as a texture there. This is not render to texture.

Thanks to all, it works now, the good way was to render into a Pixmap with eglCreatePixmapSurface method and then read easily its pixels.

Now it runs @ 45FPS and not @ 17FPS with glReadPixels… exactly as I wanted…

Thank you all…

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.