2
$\begingroup$

In my project, for convenience I would like to use many buffers. Many buffers in my case means 50-100 terrain patches represented by buffers with vertex coordinates, normals, indices and maybe color. The magnitude of data would be, let's say 10^4 floats per buffer. Some of this data can be shared between each terrain patch, f.ex. xz-coordinates and indices.

During the rendering loop, some terrain patches will be updated. Which means that for certain buffers I call glBufferSubData() for the whole buffer.

My question is; are there any pros/cons, performance wise between these two methods:

1) Controlling my data in many buffers (50-100), thus letting me call glBufferSubData on a complete buffer when needed.

2) Controlling my data in fewer (5-20) buffers, with more data in each. But then having to set up a system where I need to call glBufferSubData on smaller portion of a buffer. (Which leads to a more complex design in my case).

$\endgroup$
3
$\begingroup$

It depends. There are a few competing factors at work here.

First, consolidating terrain data into fewer buffers (or one) may allow you to combine multiple terrain patches together in a single draw call—assuming there aren't other state changes between patches that would prevent this. So, you may be able to reduce draw-call overhead this way, or at least reduce the state-change overhead between draws. That being said, 50–100 draw calls is not that many, so this may not be a real performance concern.

In addition, do you anticipate needing to use the terrain data for other shader effects? For example, maybe a shader procedurally generates grass growing on the terrain, or you use height above the terrain to influence lighting or AO or some such. In that case having all the terrain data in one big buffer that you can pass to those shaders may simplify things.

On the other hand, if you're having the terrain deformed/edited in real-time (which it sounds like you are), then it may be faster to update the entirety of a small buffer than to update a small portion of a large buffer. The problem is when the CPU and GPU are working asynchronously, and you update a buffer from the CPU, the GPU may still be using the previous version of that buffer. To fix this, the driver internally keeps 2–3 instances of the buffer (much like double/triple buffering the screen). If you always update the entire buffer at once, the driver can just put the updated data into the "next" instance of that buffer. But if you update only part of the buffer, the driver must copy all the rest of the data from the current instance to the next instance. This extra copy will consume some performance either on the CPU or on the GPU.

So, if the terrain data was entirely static I'd say it's better to put it all in one big buffer. However, if you're going to be updating portions of the data in real-time, it may be better to keep it in smaller buffers so that you can update exactly the ones that have changed while leaving others alone.

In the end, you'll have to do some profiling to see which approach is better.

$\endgroup$
  • $\begingroup$ Thank you for this detailed answer. Good input for me to start planing my setup. $\endgroup$ – remi000 Jan 30 '17 at 22:09

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.