Threads do not work, refrain from this approach.
Creating multiple threads fails, as you noticed, because only one thread has the current OpenGL context. In principle, you could make the context relevant in each glReadPixels before calling glReadPixels , but this will require additional synchronization on your part (otherwise the thread may be squeezed out between making the context relevant and read!) And (wgl|glx)MakeCurrent is an awfully slow feature that will seriously stop OpenGL. In the end, you will do more work to get something much slower.
There is no way to make glReadPixels faster than 1, but you can separate the time spent on it (that is, reading is performed asynchronously), so it does not block your application and does not appear to run โfasterโ.
You want to use a Pixel buffer object for this. Make sure the buffer flags are correct.
Please note that displaying the buffer to access its contents will still be blocked if the full content does not complete the transfer, so it will not be faster anyway. To account for this, you either need to read the previous frame, or use the fence object that you can request to make sure that this is done.
Or, easier but less reliable, you can insert a โdifferent jobโ between glReadPixels and data access. This does not guarantee that the transfer will be completed by the time the data is accessed, so it can still be blocked. However, it can simply work, and it will most likely be blocked for a shorter time (thus, "faster").
1 There are many ways to do this slower, for example. if you ask OpenGL to do some weird conversions or use the wrong buffer flags. However, as a rule, there is no way to do this faster, because its speed depends on all previous drawing commands that ended before the transfer can even begin, and the data is transferred via the PCIe bus (which has a fixed temporary load plus final bandwidth).
The only viable way to speed up reading reviews is hiding this delay. This, of course, is not faster yet, but you do not feel it.
Damon
source share