Binding and unbinding GL_ATOMIC_COUNTER buffers

Hi,

I would like a clarification about to allocate data to an atomic counter buffer, and how to use it later on.

For the allocation, shall I do:

glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicId);
glBufferData(GL_ATOMIC_COUNTER_BUFFER, ... data ...);
glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);

or:

glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicId);
glBufferData(GL_ATOMIC_COUNTER_BUFFER, ... data ...);
glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, 0); (*)

In other words, shall my binding be “based” when I allocate?

Second, how am I supposed to un-bind a buffer bound using glBindBufferBase (*)? Buffers bound using glBindBuffer can be unbound with glBindBuffer(…, 0) as stated in the documentation : “buffer set to zero effectively unbinds any buffer object previously bound”.
However, nothing is said in the documentation of glBindBufferBase, and buffer=zero does not cause an un-bind.

Note that this question also applies to when I bind/unbind upon shader execution. In this case I do need to use glBindBufferBase… how shall I un-bind?

Thanks,
Fred

NB: sorry if this question seems silly, but I would like to make sure I am doing exactly the right thing.

I think what you want is in the OpenGL 4.5 Specification in “Section 6.1.1 Binding Buffer Objects to Indexed Targets”:

Buffer objects may be created and bound to indexed targets by calling one of the
commands …BindBufferRange…BindBufferBase

target must be one of ATOMIC_COUNTER_BUFFER, SHADER_STORAGE_BUFFER,
TRANSFORM_FEEDBACK_BUFFER or UNIFORM_BUFFER. Additional language
specific to each target is included in sections referred to for each target in table 6.1.

Each target represents an indexed array of buffer object binding points, as well
as a single general binding point that can be used by other buffer object manipulation
functions, such as BindBuffer or MapBuffer. Both commands bind the
buffer object named by buffer to both the general binding point, and to the binding
point in the array given by index.

Or you can just toss the whole idea of needing a bind point to allocate, and just use DSA (glNamedBufferDataEXT()).

Second, how am I supposed to un-bind a buffer bound using glBindBufferBase (*)? Buffers bound using glBindBuffer can be unbound with glBindBuffer(…, 0) as stated in the documentation : “buffer set to zero effectively unbinds any buffer object previously bound”.
However, nothing is said in the documentation of glBindBufferBase, and buffer=zero does not cause an un-bind.

Pass 0 for buffer. But why do you need to unbind it? Just bind something else to it when needed.

Re the unbinding, this info from the spec may be useful:

BindBuffersBase is equivalent (assuming no errors are generated) to:

for (i = 0; i < count; i++ )
{
if (buffers == NULL)
BindBufferBase(target, first + i, 0);
else
BindBufferBase(target, first + i, buffers[i]);
}

except that the single general buffer binding corresponding to target is unmodified,
and that buffers will not be created if they do not exist.

BindBuffersRange is equivalent (assuming no errors are generated) to:

for (i = 0; i < count; i++)
{
if (buffers == NULL)
BindBufferRange(target, first + i, 0, 0, 0);
else
BindBufferRange(target, first + i, buffers[i], offsets[i], sizes[i]);
}

except that the single general buffer binding corresponding to target is unmodified,
and that buffers will not be created if they do not exist.

I think what you may be referring to is that BindBuffeBase sets the indexed binding point, but doesn’t set the general binding point. Don’t know why you care but if you do, use glBindBuffer.

Thanks for the clarification, Dark Photon.
I did actually see the BindBufferRange documentation and concluded I could use BindBufferBase(…,…,0); I find it weird that this is not specified in the BindBufferBase documentation itself.

I’m unbinding because I need to read the data back.

I care because I want compatibility with various setups: GPU vendors and even to some extent, drivers. It’s painful to debug code against a specific GPU setup: you always wonder if it is a driver bug, or a misbehavior in your code.

Another thing bugging me at the moment is the order in which I can bind based buffers with respects to UseProgram.
It seems that BindBufferBase is better called after UseProgram. Some setups don’t cope well if the function is called before, eg. things go wrong. As far as I can tell, this is an obscure point in the spec, too.