4

My application is dependent on reading depth information back from the framebuffer. I've implemented this with glReadPixels(0, 0, width, height, GL_DEPTH_COMPONENT, GL_FLOAT, &depth_data)

However this runs unreasonable slow, it brings my application from a smooth 30fps to a laggy 3fps. If I try to other dimensions or data to read back it runs on an acceptable level.

To give an overview:

  • No glReadPixels -> 30 frames per second
  • glReadPixels(0, 0, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth_data); -> 20 frames per second, acceptable
  • glReadPixels(0, 0, width, height, GL_RED, GL_FLOAT, &depth_data); -> 20 frames per second, acceptable
  • glReadPixels(0, 0, width, height, GL_DEPTH_COMPONENT, GL_FLOAT, &depth_data); -> 3 frames per second, not acceptable

Why should the last one be so slow compared to the other calls? Is there any way to remedy it?

width x height is approximately 100 x 1000, the call gets increasingly slower as I increase the dimensions.

I've also tried to use pixel buffer objects but this has no significant effect on performance, it only delays the slowness till the glMapBuffer() call.

(I've tested this on a MacBook Air nVidia 320m graphics OS X 10.6, strangely enough my old MacBook Intel GMA x3100 got ~15 fps reading the depth buffer.)

UPDATE: leaving GLUT_MULTISAMPLE out of the glutInitDisplayMode options made a world of difference bringing the application back to a smooth 20fps again. I don't know what the option does in the first place, can anyone explain?

Paul Wagener
  • 432
  • 6
  • 12
  • I know this is a non-answer but don't use glRead* or glGet* if fps matter! If you want the depth information for rendering purposes only you'd better write a custom shader that has read access to the depth buffer. If you really need those depth information for your app/game logic I'd strongly recommend reconsidering the overall approach. – Jonas Bötel Mar 31 '11 at 14:48

3 Answers3

3

If your main framebuffer is MSAA-enabled (GLUT_MULTISAMPLE is present), then 2 actual framebuffers are created - one with MSAA and one regular.

The first one is needed for you to fill. It contains front and back color surfaces, plus depth and stencil. The second one has to contain only color that is produced by resolving the corresponding MSAA surface.

However, when you are trying to read depth using glReadPixels the driver is forced to resolve the MSAA-enabled depth surface too, which probably causes your slowdown.

kvark
  • 5,291
  • 2
  • 24
  • 33
1

What is the storage format you chose for your depth buffer ?

If it is not GLfloat, then you're asking GL to convert every single depth in the depth buffer to float when reading it. (And it's the same for your 3rd bullet, with GL_RED. was your Color buffer a float buffer ?)

Bahbar
  • 17,760
  • 43
  • 62
  • I don't know, I've left it unspecified and used the GLUT defaults. I've tried every type in the glReadPixels documentation and they all run slow (except for the ones that give an invalid argument error). – Paul Wagener Mar 31 '11 at 12:45
0

No matter it is GL_FLOAT or GL_UNSIGNED_BYTE, glReadPixels is still very slow. If you use PBO to get RGB value, it will be very fast. When using PBO to handle RGB value, the CPU usage is 4%. But it will increase to 50% when handling depth value. I've tried GL_FLOAT, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, GL_UNSIGNED_INT_24_8. So I can conclude that PBO is useless for reading depth value