glBufferData(....) = Allocate memory and fill data
You are indeed allocating memory for the buffer. But that is different from allocating memory for the buffer object.
Let's put this in C++ terms. A buffer object is like a vector<char>
. Doing glGenBuffers/glBindBuffer
is like allocating a vector<char>
object (and let's do it on the heap):
auto buffer = new vector<char>;
buffer
points to a real, live object. sizeof(*buffer)
will return a number of bytes of memory, which how much memory the object pointed to by buffer
requires. You can request buffer->size()
and it will return a legitimate and well-defined value.
glGetBufferParameteri64v(target, GL_BUFFER_SIZE)
would be the equivalent of calling buffer->size()
. You can call this function after creating the object, before you call glBufferData
.
In both cases, buffer->size()
and GL_BUFFER_SIZE
, the size returned will be 0. Because you haven't put anything into the object yet. In both cases, the object now exists, but it is empty.
glBufferData
is like calling buffer->resize
. You are now telling the object you allocated to itself allocate some storage of a certain size and (optionally) fill it with certain data.
A vertex array object is different only its purpose. The purpose of a buffer object is to contain storage. The purpose of a vertex array object is to define the association between storage (stored in buffers) and vertex arrays that feed rendering operations.
A VAO in our C++ analogy is more like a regular struct:
struct VAO
{
int elementBuffer;
VertexFormat vf[16];
VertexBufferBinding vb[16];
};
This VAO
struct doesn't need allocated storage beyond sizeof(VAO)
. Just like many C++ objects don't need to allocate storage besides themselves. Therefore, it doesn't have the equivalent of glBufferData
.
So to answer your question, the memory for all OpenGL objects is owned by the OpenGL context that created them. It's just that some OpenGL objects can have additional storage beyond that for their basic object. vector<char>
has an internal array of bytes. And buffer objects have an internal array of bytes.
VAOs don't have internal arrays of storage beyond the object itself.