0

I heard of PBOs in OpenGL, they are pretty neat in texture loading / uploading. Using PBO involves using synchronisation fences, like they are used in this PBO tutorial. I've tried this technique and it's a great replacement of glTexImage and glGetTexImage in case of big images. Now I want to apply the same approach to other loading / uploading routines (and possibly some other).

If I understand OpenGL client—server model correctly, it works as follows:

(Italics are the things I am not sure of)

  1. Client (my program) 'asks' OGL context to place new commands into OGL command queue. It is done by simply calling the gl* functions in the order that client wants them to execute;
  2. If command flushing is enabled (it is by default), commands are immidiately flushed to the GPU (e. g. via PCI). Otherwise they are placed in some buffer and flushed afterwards when needed (call to glFlush does this);
  3. GPU (server) receives commands from OGL context and executes them in desired order and changes object / context state;
  4. GPU sends back a reply that context (client) asked for;
  5. Context replies to client with the data received from server.

Fences may be used to indicate whether GPU is done executing previous commands.

(2) implies that command execution is not necessarily done instantly. One can, for example, block command flushing by calling glWaitSync, place new commands into queue and then call glFlush. Commands will be flushed to GPU and executed asynchronously (independently from client). When GPU is busy executing given commands, CPU can focus on doing other stuff (e. g. sending info to a remote TCP server, or receiving input from user, or pretty much anything else). When CPU needs to perform something with OGL context again, it can wait until GPU is done with previous job by calling glClientWaitSync and place new commands in the queue, and the cycle repeats.

Based on all of the above, in case of that PBO tutorial, OGL context receives data from the program, buffers it and then sends it to GPU. Sending large amounts of data takes time, hence fence is used to know when sending is complete.

However, Khronos wiki says that only rendering functions are asynchronous. I understand it: rendering also takes time. But then why does the PBO example above work? And it's not like the image upload to GPU is instant, fence is not signaled instantly. Surely, the time it takes to finish uploading depends on how big is the image (I tested it with different image sizes).

Another example: I send a source code for a shader with glShaderSource and then do glCompileShader. Then I instantly check the GL_COMPILE_STATUS with glGetShaderiv. If the shader is not yet compiled when I do glGetShaderiv (it simply did not have enough time to compile), is it possible that GL_COMPILE_STATUS will state that shader is not compiled? Or is it guaranteed that the GL_COMPILE_STATUS is only returned after the compilation? Or is the compilation performed on CPU and does not need to communicate with GPU? (i. e. compilation does not place any commands in GPU queue). It has never really happened to me that shader compilation failed due to time limits, it failed only because of bad shader code.

The questions are:

  1. Is my understanding of OGL client—server model correct or does it need some adjustments?
  2. If not all functions can be executed asynchronously, what are those functions exactly?
  3. Why does wiki say that only render actions may be performed asynchronously?
  4. If command execution may indeed be 'deferred' (not really the right word for it...) with glWaitSync for example, how can I upload and compile shaders the same way images are uploaded in PBO example? Or how can I perform VBO / EBO upload the same way? Or UBO? Or TBO? Non-buffer objects? Is it just uploading and then waiting for fence to be signaled?

In case it matters, I use OGL with latest GLFW github release, latest GLAD (configuration) and C++ (MinGWx64 11.2.0).

UPD: I found this answer that touches the subject of my question. However, I must specify that my question is not about where and how OGL functions are executed, it's about how to control the flow of them, i. e. control when they are executed, to perform asynchronous work of GPU and CPU if it is even possible (it seems to be, if I understand wiki page right).

  • 2
    "*If command flushing is enabled (it is by default)*" This is not a thing. Flushing is a thing, but there is no automatic flushing to be enabled. – Nicol Bolas Jan 07 '23 at 18:41
  • 1
    "*Why does wiki say that only render actions may be performed asynchronously?*" It doesn't. It does use rendering commands as a point of reference, but at no point does it say that *only* rendering commands are asynchronous. – Nicol Bolas Jan 07 '23 at 18:44
  • @NicolBolas By saying that command flushing is enabled by default I meant that by default commands execution is not blocked (if there was no `glWaitSync`) – postcoital.solitaire Jan 07 '23 at 19:06
  • @NicolBolas Hmm, I must've assumed that it's true for rendering only. With this said, does [this paragraph](https://www.khronos.org/opengl/wiki/Synchronization#:%7E:text=OpenGL%20Rendering%20Commands%20are%20assumed%20to%20execute%20be%20asynchronous:~:text=The%20OpenGL%20API%20however%20is%20defined%20to%20be%20synchronous) mean that commands which depend on previous commands calls block until the latter ones finish? – postcoital.solitaire Jan 07 '23 at 19:18

0 Answers0