When is Vertex Data uploaded to Graphics Card?

Hi all,
I am confused about when and how CPU sends vertex data to GPU via VAO, VBO and EBO. Suppose I have a piece of codes like this:

// do intialization
glBindVertexArray(VAO);

glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

glVertexAttribPointer(…);
glEnableVertexAttribArray(0);

// in render loop
glUseProgram(…);
glBindVertexArray(VAO);
glDrawElements(…);
glBindVertexArray(0);

Learning how to use these APIs is not that difficult for me, but I really suffer from understanding principles behind them. In my opinion, just a guess, when initialization, CPU sends data to GPU through glBufferData() and stores some GPU states/contexts configuration via VAO. When doing render loop, by rebinding target VAO, it actually tells GPU which part of data in GPU memory should be used in shaders and tell GPU to set proper states/contexts meanwhile.

So, I have several questions:

  1. Is vertex data uploaded to GPU when calling glBufferData() instantly?
  2. Is vertex data uploaded to GPU only once when initialization or in each frame during render loop?
  3. Is indices data uploaded to GPU either? Once or in each frame? (Because I find that when calling glDrawElements(), I can pass a pointer to a indices array through the fourth parameter if EBO is not used)
  4. What if GPU memory is insufficient when uploading vertex data?
  5. Is it safe/correct to release memory on CPU side (I mean original vertex data or indices data) after calling glBufferData()? Will graphics library or graphics card driver keep a copy of my original data after calling specific APIs such as glBufferData()?

Thanks a lot!

It is uploaded as if it were instantly. That is, data is not referenced after this function returns.

This doesn’t mean the GPU has actually stored the data in its final destination at this point. The driver could copy the data from your pointer into an internal allocation, from which the driver will later do a DMA into actual GPU-accessible memory. But you can’t tell one way or the other (without profiling); the implementation has to make the various functions behave “as if” the transfer is complete when the function returns.

Note that this applies to pretty much all OpenGL functions that take pointers to user data.

OpenGL itself has no concept of “initialization” or “frame”; there are just the sequence of functions you call. It is not OpenGL’s responsibility to decide when something gets uploaded; you tell OpenGL to do an upload, and it will happen.

Therefore, if you upload only during some period that you consider to be “initialization”, then that’s the only period that uploading will happen. Assuming that contention for GPU memory isn’t too high.

Despite the appearance in the API, there is no such thing as a “vertex buffer object” or an “index buffer object.” Not as far as OpenGL itself is concerned. There are buffer objects, all of which store linear, unformatted bytes of data that you put there via some process. These buffer objects can be used in a variety of ways (for vertex data, index data, transform feedback, UBOs, etc). But all buffer objects are equal; they don’t gain or lose special properties based on what they’re being used as at the moment.

So everything I said above applies to all buffers.

That depends on the circumstances. Modern GPUs have some memory virtualization, so they can dynamically page stuff into and out of GPU-accessible memory. Or it may give you an OpenGL out-of-memory error.

I answered this in the answer to the first part.

1 Like

Thank you so mush! You helped me a lot.

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.