<p>There are various options, even with OpenGL 3.3 (over a decade old), that will depend on hardware factors, GPU, bus, etc., the driver-specific implementations, and finally, the sort of access patterns and frequency of updates to the VBO that the application will be making.</p>
<p>I'm not entirely clear what you are thinking in terms of when and how a vertex array object 'knows' it's out of date. The VAO has attribute array bindings to specific buffers - and when the application modifies a VBO, it does so through the GL API. Therefore, the GL is forced to synchronize these updates - and that means potentially stalling the pipeline, which is a <a href="https://www.khronos.org/opengl/wiki/Buffer_Object_Streaming#The_problem" rel="nofollow noreferrer">problem</a>. And because it's a complex problem, there are several solutions...</p>
<hr />
<p>The first is just to call <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBufferData.xhtml" rel="nofollow noreferrer"><code>glBufferData</code></a> again, and replace the data. That might be fine for infrequent changes or small buffers - again, it's too hard to give a one-size-fits-all solution.</p>
<p>A better strategy in a lot of cases is 'orphaning'. Effectively, call <code>glBufferData</code> again, but this time with <code>data = NULL</code>. This can be very effective, because the GL knows it doesn't have to retain that data. There is still some cost in calling <code>glBufferData</code> or <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetBufferSubData.xhtml" rel="nofollow noreferrer"><code>glBufferSubData</code></a> - this time with <em>actual</em> data; but it doesn't need to synchronize waiting for a partial update.</p>
<p>VBOs have been around since OpenGL 1.5, so it's a well-established technique that drivers have optimized for a long time. It's relatively simple to implement, and tends to have good results. In most VBO update code I've written, it tends to perform well over a wide range of platforms.</p>
<p>There's the idea of 'ping-pong' buffers (alternating VBOs). Update a buffer not currently in use, while another is being used as a source. When a frame is finished, swap the VBOs used for a particular vertex attribute stream. I don't know how effective this is with more recent GPUs.</p>
<p>As an alternative approach, there's <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glMapBuffer.xhtml" rel="nofollow noreferrer"><code>glMapBuffer</code></a>, and the corresponding <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glUnmapBuffer.xhtml" rel="nofollow noreferrer"><code>glUnmapBuffer</code></a>. The driver is responsible for presenting the VBO data in a (modifiable) region of memory for the application. When the application has updated the data, the 'unmap' call updates the VBO. There are obvious issues with DMA transfers to and from GPU memory. The GL is effectively stalled - the VBO can't be used without generating errors - until the memory is unmapped.</p>
<hr />
<p>Then there are <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glMapBufferRange.xhtml" rel="nofollow noreferrer">'ranged'</a> buffer updates, with finer control over synchronization. To be honest, I'm getting out of my depth at this point, and the <a href="https://www.khronos.org/opengl/wiki/Buffer_Object_Streaming#The_problem" rel="nofollow noreferrer">link</a> I referenced earlier provides a better background than I can.</p>

CC BY-SA 4.0
2021-10-28T14:16:53.187Z
2021-10-28T14:21:53.703Z
2021-10-28T14:21:53.703Z
Brett Hale
<p>The data sent to the GPU <em>is</em> formatted. The GPU has to be programmed to know what that format is. If you want to add more data to the vertex attributes then the entire pipeline has to be reprogrammed, this includes overwriting the vertex attributes, changing the shaders, and reprogramming the GPU to know the data sizes.</p>
<p>If you change just the data, the GPU will have no clue, and will happily process garbage.</p>
<p>The are of course other ways to get data to a shader such as the so called &quot;shader buffer object&quot;. But that seems to be outside the scope of your question.</p>

CC BY-SA 4.0
2021-05-31T11:30:58.457Z
2021-05-31T11:50:58.660Z
2021-05-31T11:50:58.660Z
pmw1234
<p>I'm learning OpenGL and I'm trying to understand things properly. If my understanding is incorrect at <strong>any</strong> point, please correct me.</p>
<h1>Introduction</h1>
<p>So let's say we have a triangle. This triangle has its vertices. Let's say these vertices only have the position set - no color, not anything else. These vertices are passed to the shaders using a buffer - let's call it VB (VBO in tutorials).</p>
<p>The shaders are the following:</p>
<p>Vertex shader:</p>
<pre class="lang-cpp prettyprint-override"><code>#version 330 core
layout (location = 0) in vec3 aPos;

void main()
{
    gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
}
</code></pre>
<p>Fragment shader:</p>
<pre class="lang-cpp prettyprint-override"><code>#version 330 core
out vec4 FragColor;

void main()
{
    FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
}
</code></pre>
<p>The VB is an non-formatted array of data. For example, if we wanted to pass 3 one-byte values to this buffer (0, 255, 16), the data would look like this:</p>
<p><code>00FFF0</code></p>
<p>However, the shaders do not know how to read the data, so we need to &quot;instruct&quot; them by telling them what is what. To do this we use Vertex Array Objects. Let's call our Vertex Array Object VA.</p>
<p>To pass data to the buffer, <code>glBufferData</code> is used. When calling the function like this:</p>
<pre class="lang-cpp prettyprint-override"><code>glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
</code></pre>
<p>We inform OpenGL that we want to buffer <code>sizeof(vertices)</code> elements from array <code>vertices</code> to the buffer currently bound to <code>GL_ARRAY_BUFFER</code> for static drawing.</p>
<p>Then, we inform VA how to use the data like this:</p>
<pre class="lang-cpp prettyprint-override"><code>glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
</code></pre>
<p>This way we tell VA to get 3 floating point values from active buffer at the offset 0 while not normalizing coordinates and set this data to the vertex attribute at location 0.</p>
<p>This way, the shaders finally get all the data they need to work and our triangle is drawn.</p>
<h1>Question</h1>
<p>However, what if we wanted to change one vertex <strong>after</strong> we've already passed the data to the buffer?</p>
<p>In my understanding, we'd need to call <code>glBufferData</code> the same way as before. But how does it influence the data that was originally in the buffer? Does it overwrite it?</p>
<p>If it does overwrite it, how do we pass another data, let's say colors, without overwriting the positions?</p>
<p>If it doesn't, how does VA know the data it's &quot;pointing&quot; to is no longer up to date?</p>

<opengl><vertex-buffer-object>
How does a Vertex Buffer manage memory?
Sherlock Holmes
# How does a Vertex Buffer manage memory?

(Asked by: username_0 on 2021-05-28)

I'm learning OpenGL and I'm trying to understand things properly. If my understanding is incorrect at **any** point, please correct me.

# Introduction

So let's say we have a triangle. This triangle has its vertices. Let's say these vertices only have the position set - no color, not anything else. These vertices are passed to the shaders using a buffer - let's call it VB (VBO in tutorials).

The shaders are the following:

Vertex shader:

```cpp
#version 330 core
layout (location = 0) in vec3 aPos;

void main()
{
    gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
}

```

Fragment shader:

```cpp
#version 330 core
out vec4 FragColor;

void main()
{
    FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
}

```

The VB is an non-formatted array of data. For example, if we wanted to pass 3 one-byte values to this buffer (0, 255, 16), the data would look like this:

`00FFF0`

However, the shaders do not know how to read the data, so we need to "instruct" them by telling them what is what. To do this we use Vertex Array Objects. Let's call our Vertex Array Object VA.

To pass data to the buffer, `glBufferData` is used. When calling the function like this:

```cpp
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

```

We inform OpenGL that we want to buffer `sizeof(vertices)` elements from array `vertices` to the buffer currently bound to `GL_ARRAY_BUFFER` for static drawing.

Then, we inform VA how to use the data like this:

```cpp
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);

```

This way we tell VA to get 3 floating point values from active buffer at the offset 0 while not normalizing coordinates and set this data to the vertex attribute at location 0.

This way, the shaders finally get all the data they need to work and our triangle is drawn.

# Question

However, what if we wanted to change one vertex **after** we've already passed the data to the buffer?

In my understanding, we'd need to call `glBufferData` the same way as before. But how does it influence the data that was originally in the buffer? Does it overwrite it?

If it does overwrite it, how do we pass another data, let's say colors, without overwriting the positions?

If it doesn't, how does VA know the data it's "pointing" to is no longer up to date?

**Tags:** opengl, vertex-buffer-object


---

## 2 answers

### Answer by username_1 on 2021-10-28. Score: 1

There are various options, even with OpenGL 3.3 (over a decade old), that will depend on hardware factors, GPU, bus, etc., the driver-specific implementations, and finally, the sort of access patterns and frequency of updates to the VBO that the application will be making.

I'm not entirely clear what you are thinking in terms of when and how a vertex array object 'knows' it's out of date. The VAO has attribute array bindings to specific buffers - and when the application modifies a VBO, it does so through the GL API. Therefore, the GL is forced to synchronize these updates - and that means potentially stalling the pipeline, which is a [problem](https://www.khronos.org/opengl/wiki/Buffer_Object_Streaming#The_problem). And because it's a complex problem, there are several solutions...

---

The first is just to call [`glBufferData`](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBufferData.xhtml) again, and replace the data. That might be fine for infrequent changes or small buffers - again, it's too hard to give a one-size-fits-all solution.

A better strategy in a lot of cases is 'orphaning'. Effectively, call `glBufferData` again, but this time with `data = NULL`. This can be very effective, because the GL knows it doesn't have to retain that data. There is still some cost in calling `glBufferData` or [`glBufferSubData`](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetBufferSubData.xhtml) - this time with *actual* data; but it doesn't need to synchronize waiting for a partial update.

VBOs have been around since OpenGL 1.5, so it's a well-established technique that drivers have optimized for a long time. It's relatively simple to implement, and tends to have good results. In most VBO update code I've written, it tends to perform well over a wide range of platforms.

There's the idea of 'ping-pong' buffers (alternating VBOs). Update a buffer not currently in use, while another is being used as a source. When a frame is finished, swap the VBOs used for a particular vertex attribute stream. I don't know how effective this is with more recent GPUs.

As an alternative approach, there's [`glMapBuffer`](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glMapBuffer.xhtml), and the corresponding [`glUnmapBuffer`](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glUnmapBuffer.xhtml). The driver is responsible for presenting the VBO data in a (modifiable) region of memory for the application. When the application has updated the data, the 'unmap' call updates the VBO. There are obvious issues with DMA transfers to and from GPU memory. The GL is effectively stalled - the VBO can't be used without generating errors - until the memory is unmapped.

---

Then there are ['ranged'](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glMapBufferRange.xhtml) buffer updates, with finer control over synchronization. To be honest, I'm getting out of my depth at this point, and the [link](https://www.khronos.org/opengl/wiki/Buffer_Object_Streaming#The_problem) I referenced earlier provides a better background than I can.


---

### Answer by username_2 on 2021-05-31. Score: 0

The data sent to the GPU *is* formatted. The GPU has to be programmed to know what that format is. If you want to add more data to the vertex attributes then the entire pipeline has to be reprogrammed, this includes overwriting the vertex attributes, changing the shaders, and reprogramming the GPU to know the data sizes.

If you change just the data, the GPU will have no clue, and will happily process garbage.

The are of course other ways to get data to a shader such as the so called "shader buffer object". But that seems to be outside the scope of your question.


---

