glReadPixels very slow on 6600gt

I tested the same code below on nvidia 6600gt and nvidia 8600gt.
The first took 400 ms and the second 6 ms for an 256x256 image.
Is this normal?


...
int* ids = new int[m_aantalPixels];
glReadBuffer(GL_COLOR_ATTACHMENT1_EXT);
glTime.restart();
glReadPixels(0,0,m_width,m_height,GL_RGBA,GL_UNSIGNED_BYTE,ids);
cerr << "Elapsed time: " << glTime.elapsed() << "
";
glReadBuffer(GL_BACK);
...

thx

Are you sure your timer code is accurate and takes the asynchronous nature of the OpenGL API into account?
If you want some more reliable timer results, I suggest you use:


...
int* ids = new int[m_aantalPixels];
glReadBuffer(GL_COLOR_ATTACHMENT1_EXT);
glFinish();
glTime.restart();
for (int i=0;i<1000;++i)
    glReadPixels(0,0,m_width,m_height,GL_RGBA,GL_UNSIGNED_BYTE,ids);
glFinish();
cerr << "Readback time: " << glTime.elapsed()/1000.0 << "
";
glReadBuffer(GL_BACK);
...

One other thing. I noticed you used glReadBuffer(GL_COLOR_ATTACHMENT1_EXT) and glReadBuffer(GL_BACK)
without switching from your application created FBO to you window system provided framebuffer.

I’m not 100%, but I think you can only use GL_COLOR_ATTACHMENTi_EXT for application created FBOs and GL_FRONT,GL_BACK,… for your window system provided framebuffer.

Do you get any GL errors?

Are you sure your timer code takes the asynchronous nature of the OpenGL API into account?

I’m just using QTime (Qt) as timer, so probably not?
But my program goes very slow thanks to only these lines of code. When i remove them, it runs fast.

I tried your suggestion code to get an average time and it gave me: Readback time: 180.191 ms.

The code below gives no error in the first two checkErrors.
The last checkError gives: Error: invalid enumerant.


glReadBuffer(GL_COLOR_ATTACHMENT1_EXT);
checkError();
glReadPixels(0,0,m_width,m_height,GL_RGBA,GL_UNSIGNED_BYTE,ids);
glFinish();
checkError();
glReadBuffer(GL_BACK);
checkError();

That’s because GL_BACK is not a valid enumerant for an application created FBO like I said in my previous post.
Have you tried using GL_BGRA instead of GL_RGBA?

I have tried it now, but it doesn’t seem to make a difference.
I tried these combinations:


glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_BGRA, GL_UNSIGNED_BYTE, 0);
glReadPixels(0,0,m_width,m_height,GL_BGRA,GL_UNSIGNED_BYTE,ids);


glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
glReadPixels(0,0,m_width,m_height,GL_BGRA,GL_UNSIGNED_INT_8_8_8_8_REV,ids);

What do you expect that this code do?

If you want to copy the current read buffer into a texture use glCopyTexSubImage2D instead of glReadPixels

First I render to 2 fbo textures with a shader. One fbo texture is used for reading back values from the gpu to the cpu with glReadPixels. This works on my other gpu in 6 ms and the values i get back are correct. I use them in my program on the cpu. The second fbo texture is used in rendering to the framebuffer.

The glTexImage2D line is located where the fbo and textures are initialy created. The glReadPixels line is located before fbo->unbind.

Hello,

there are some tips in the OpenGL FAQ to increase the performance of glReadPixels.

dj3hut1