Jump to content

View more

Image of the Day

Adding some finishing touches...
Follow us for more
#screenshotsaturday #indiedev... by #MakeGoodGames https://t.co/Otbwywbm3a
IOTD | Top Screenshots

The latest, straight to your Inbox.

Subscribe to GameDev.net Direct to receive the latest updates and exclusive content.

Sign up now

OpenGL equivalent of D3D staging textures

4: Adsense

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
2 replies to this topic

#1 B_old   Members   


Posted 19 November 2013 - 08:25 AM

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?

Edited by B_old, 19 November 2013 - 01:32 PM.

#2 swiftcoder   Senior Moderators   


Posted 19 November 2013 - 12:42 PM

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 - Software Engineer @ Amazon - [swiftcoding] [GitHub]

#3 BGB   Members   


Posted 20 November 2013 - 11:31 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.

Edited by BGB, 20 November 2013 - 08:02 PM.

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.