I have a OpenGL2/OpenGLES2 application and it among others renders a sphere using the following pseudocode:

  1. Update vertices data on CPU
  2. call glBufferSubData(GL_ARRAY_BUFFER, ...) to update them on GPU size
  3. in a loop calls glDrawElements

Now I'm checking it under RenderDoc and see additional calls to glBindBuffer between glDrawElements:

  1. glBindBuffer(GL_ARRAY_BUFFER, 0)
  2. glBindBuffer(GL_ARRAY_BUFFER, my_vbo_id)
  3. glDrawElements

Why I see those additional calls? Why GL driver (or GL library?) inserts them?

  • \$\begingroup\$ Might be the driver unbinding for update, depending on the arguments of BufferSubData. To avoid such highhandedness, i'd suggest to neatly map, update and unmap the (part of the) buffer with the needed (and none more) hints. Might also be much faster. \$\endgroup\$
    – user136710
    May 19 '20 at 10:41
  • \$\begingroup\$ glBindBuffer (..., 0) doesn't "unbind"; what it actually does is revert the driver to pre-buffer-objects behaviour, where data is sourced from system memory pointers rather than from buffer objects. This can cause unintended behaviour in your program if you're not aware of it, and drivers should NEVER inject their own bindings of buffer object 0 into a command stream (it's a GL spec violation if they do). \$\endgroup\$ May 19 '20 at 11:05
  • \$\begingroup\$ @Daniel_1985 if I had glBindBuffer(..., 0) i wouldn't ask the question. The source code is here github.com/CelestiaProject/Celestia/blob/master/src/celengine/…, as you can see it's a simple for loop with glDrawElements only. For me it sounds like a bug in intel driver (mesa 19.2). \$\endgroup\$
    – blackcat
    May 19 '20 at 15:03
  • \$\begingroup\$ But vogl doesn't show additional glBindBuffer. \$\endgroup\$
    – blackcat
    May 19 '20 at 15:38
  • \$\begingroup\$ From the documentation of glBindBuffer: "... buffer set to zero effectively unbinds any buffer object previously bound ...". khronos.org/registry/OpenGL-Refpages/gl4. To the problem (if it is one), i don't have enough information for more than guesses. But i won't blame the driver prematurely, could rather be a glitch in RenderDoc, or something misread between a lot of draw calls and buffer bindings. \$\endgroup\$
    – user136710
    May 19 '20 at 20:43

Actually, those call are inserted by RenderDoc. Here the response from RenderDoc creator:

GLES has a legacy feature which allows you to specify vertex attribute pointers in CPU memory without using a vertex buffer at all

(same with indices without an index buffer)

renderdoc emulates that by checking when the drawcall happens if any such pointers exist, and quickly stuffing the data into a buffer, binding that buffer, and then restoring the state after the draw. That way most of the code only has to deal with vertex buffer handling from this century and not worry about CPU pointers

most of the heavy lifting is skipped if you use a VAO because CPU pointers can't be used with a VAO, but if you're not using one then it has to do the slower path of checking each attribute. In your case you're not using a VAO so it goes down the slow path, but then each attribute is using a vertex buffer so it never > actually has to do any emulation

it still ends up doing a couple of redundant bind calls when it's "cleaning up" > even if there's nothing to clean up


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.