I am using two OpenGL contexts in my application.
The first one is used to render data, the second one to background load and generate VBOs and textures.
When my loading context generates a VBO and sends it to my rendering thread, I get invalid data (all zeroes) in my VBO unless I call glFlush
or glFinish
after creating the VBO on the loading context.
I think that this is due to my loading context not having any buffer swap or anything to tell the GPU to start working on its command queue and doing nothing (which leads to an empty VBO on the rendering context side).
From what I've seen, this flush is not necessary on Windows (tested with an Nvidia GPU, it works even without the flushes) but is necessary on linux/macOS.
This page on Apple's documentation says that calling glFlush
is necessary (https://developer.apple.com/library/archive/documentation/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/OpenGLESApplicationDesign/OpenGLESApplicationDesign.html)
If your app shares OpenGL ES objects (such as vertex buffers or textures) between multiple contexts, you should call the glFlush function to synchronize access to these resources. For example, you should call the glFlush function after loading vertex data in one context to ensure that its contents are ready to be retrieved by another context.
But is calling glFinish
or glFlush
necessary or is there simpler/lighter commands available to achieve the same result ? (and which is necessary, glFlush
or glFinish
?)
Also, is there a documentation or reference somewhere that talks about this ? I couldn't find any mentions and it seems to work differently between implementations.
Because any GL program might be executed over a network, or on an accelerator that buffers commands, all programs should call glFlush whenever they count on having all of their previously issued commands completed. For example, call glFlush before waiting for user input that depends on the generated image.
The docs say that glFlush() and glFinish() will push all buffered operations to OpenGL so that one can be assured they will all be executed, the difference being that glFlush() returns immediately where as glFinish() blocks until all the operations are complete.
Because OpenGL is defined to be synchronous, when any of these functions have returned, they must have finished with the client memory. When glReadPixels returns, the pixel data is in your client memory (unless you are reading into a buffer object).
Different OpenGL implementations buffer commands in several different locations, including network buffers and the graphics accelerator itself. The glFlush function empties all these buffers, causing all issued commands to be executed as quickly as they are accepted by the actual rendering engine.
If you manipulate the contents of any object in thread A, those contents are not visible to some other thread B until two things have happened:
The commands modifying the object have completed. glFlush
does not complete commands; you must use glFinish
or a sync object to ensure command completion.
Note that the completion needs to be communicated to thread B, but the synchronization command has to be issued on thread A. So if thread A uses glFinish
, it now must use some CPU synchronization to communicate that the thread is finished to thread B. If you use fence sync objects instead, you need to create the fence on thread A, then hand it over to thread B who can test/wait on that fence.
The object must be re-bound to the context of thread B. That is, you have to bind it to that context after the commands have completed (either directly with a glBind*
command or indirectly by binding a container object that has this object attached to it).
This is detailed in Chapter 5 of the OpenGL specification.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With