OpenGL equivalent of D3D staging textures

Started by
1 comment, last by cr88192 10 years, 5 months ago

I'm reading about texture readback in OpenGL and as usual I find many different possibilities.

From D3D I'm used to copying the texture I want to read back into a staging texture which I than map in order to read the pixels. Should I basically do the same in OpenGL or is there a preferred way?

There is both glReadPixels() and glGetTexImage() and they seem to basically do the same thing.

Pixel buffer objects are often mentioned in this context and seem to be a means of making the previous calls asynchronous until you map the PBO. Is that correct?

So is glGetTexImage() & PBO a good approach or should I still copy to a different texture first, so that I can continue rendering to the texture I want to read back?

Advertisement

Ja, glGetTextImage to a PBO is the usual approach for asynchronous texture read back to main memory.

You'll often want a pool of PBOs, so that you can buffer a couple of frames to hide the latency of reading back from the GPU.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

my experience here:

you don't really want to use glReadPixels if it can be avoided, as it tends to cause a bit of a performance hit when used;

in most cases, PBOs are likely preferable.

however, it (raw glReadPixels) does seem to be ok for a few uses:

screenshots (typically less critical of performance);

(if used with care) in-game video recording (*).

*: usually because the current frame needs to finish rendering anyways.

this does require care though in terms of choosing the right settings for reading the screen image, as doing this badly can result in a significant drop in performance. also, you don't want to do video encoding in the render-thread (this sort of thing is fairly expensive), and in fact the render thread should do no more than necessary to pass it off to an encoder thread.

in this case:

ReadPixels into render-side buffer (currently using BGRA and UNSIGNED_INT_8_8_8_8);

lock shared buffer;

memcpy (from render-side buffer into temp buffer);

update frameCount (tells encoder that a new frame image awaits);

unlock shared buffer.

one can ask, why the locks and extra copy:

mostly sacrificing a little performance in the name of avoiding tearing;

ReadPixels is still slow enough that it can block the encoder thread a lot worse than a memcpy call will;

the encoder thread will also copy the shared buffer to a local buffer (with locking), likewise to help avoid tearing (and avoid locking the buffer for an extended period of time).

PBOs would still likely be a better solution though (vs using a raw glReadPixels or similar), but will add a bit of complexity into the process.

in times where ReadPixels has been used mid-render, the performance impact (of not using PBOs) has generally often been a bit more, severe.

also, if mapped immediately, they wont buy much (they will have a similar performance cost to doing a non-PBO read), hence the need typically for multiple rotating buffers. so, generally, a person will use a raw read if the results are needed immediately.

most of this should also apply to the use of GetTexImage and similar.

This topic is closed to new replies.

Advertisement