<p>The post October 22, 2019 version of the OpenGL 4.6 standard gives atomic counters the same incoherency restrictions as image load/store and SSBO operations. You have to use explicit barriers to synchronize access to them and so forth. This is a textual change from older versions of the standard, but it isn't a behavioral change from implementations. The older wording <a href="https://github.com/KhronosGroup/OpenGL-API/issues/14" rel="nofollow noreferrer">is considered a bug</a> and thus it should be assumed that atomic counters have always worked incoherently.</p>

<hr>

<p>Note: the following predates the October 22, 2019 update to OpenGL 4.6.</p>

<p>From the OpenGL 4.6 specification, section 7.12: Shader Memory Access:</p>

<blockquote>
  <p>As described in the OpenGL Shading Language Specification, shaders may perform random-access reads and writes to buffer object memory by reading from, assigning to, or performing atomic memory operation on shader buffer variables, or to texture or buffer object memory by using built-in image load, store, and atomic functions operating on shader image variables. The ability to perform such random-access reads and writes in systems that may be highly pipelined results in ordering and synchronization issues discussed in the sections below.</p>
</blockquote>

<p>Notice something missing from that list? It mentions "shader buffer variables", and "shader image variables". But atomic counter variables are not mentioned. And atomic counter variables are a different kind of thing from either of those.</p>

<p>Therefore, that entire section (which is what explains the behavior of <code>glMemoryBarrier</code>) does not apply to atomic counters. Well, except where it specifically says otherwise, but that's only where it defines that helper FS invocations don't have side-effects. Note that even this <em>explicitly</em> calls out atomic counters as being something different from regular buffer or image operations: "stores, atomics, and atomic counter updates".</p>

<p>To lend greater credence to this view, the <a href="https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_shader_atomic_counters.txt" rel="nofollow noreferrer">ARB_atomic_counter_buffer_object</a> extension does not mention barriers at all. It doesn't require <a href="https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_shader_image_load_store.txt" rel="nofollow noreferrer">ARB_shader_image_load_store</a> as a companion extension either, which is what defines <code>glMemoryBarrier</code>. Indeed, it has no interactions whatsoever with image load/store, while image load/store does have specified interactions with atomic counters.</p>

<p>Given the weight of the evidence in the specifications, I would have to say that the Wiki is right. In the interest of full disclosure, I did write that Wiki article. Though I also did all this research <em>before</em> I wrote it.</p>

<p>Basically, what the API seems to be saying is that buffer updates from atomic counters are treated like buffer updates from feedback operations. The implementation is required to track when you attempt to use that buffer for a read operation, then issue any synchronization needed to make sure that you can read the value. Or if you write to the value in the buffer (like clearing it to a value), then the implementation must automatically synchronize this.</p>

<p>The likely reason the specification permits this for atomic counters but not for image load/store is that the range of data for atomic counters is <em>fixed</em>. SSBOs and image load/store through buffer textures can write to arbitrary parts of the bound range of buffer data. By contrast, atomic counters write to 4 bytes times the number of atomic counter variables used by the shader.</p>

<p>Note however that atomic counters are affected by the in-shader <code>memoryBarrier</code> function. That is, atomic counters are subject to the requirements of, as the Wiki calls it, "<a href="https://www.khronos.org/opengl/wiki/Memory_Model#Internal_visibility" rel="nofollow noreferrer">Internal Visibility</a>". Granted, that's not very useful most of the time, as the primary use of atomic counters is for when multiple invocations are all updating the same one.</p>

<hr>

<p>On the other hand:</p>

<blockquote>
  <p>the glMemoryBarrier() function supports a bit specifically for synchronizing access to atomic counters with other parts of the OpenGL pipeline</p>
</blockquote>

<p>The specification describes this particular barrier as:</p>

<blockquote>
  <p>Memory accesses using shader atomic counter built-in functions issued after the barrier will reflect data written by shaders prior to the barrier. Additionally, atomic counter function invocations after the barrier will not execute until all memory accesses (e.g., loads, stores, texture fetches, vertex fetches) initiated prior to the barrier complete.</p>
</blockquote>

<p>What's curious about this is the "all memory accesses" part. This specific wording is only used in two other bits: shader storage and shader image. Other barriers for coherent operations like query buffers and transform feedbacks tend to use the term "all shader writes".</p>

<p>So... I would say that there is confusion at the specification level.</p>

CC BY-SA 4.0
2020-02-26T13:00:57.040Z
Which apparently prompted https://github.com/KhronosGroup/OpenGL-API/issues/14 !
bernie
CC BY-SA 4.0
2020-02-27T13:29:44.137Z
I referenced your issue in my research for https://stackoverflow.com/questions/56340333/glsl-about-coherent-qualifier/60434348#60434348 Since you wrote the wiki article in question, I'd be very interested to have you take on my findings.
bernie
CC BY-SA 4.0
2017-09-04T04:21:54.893Z
2020-04-12T16:25:21.887Z
2020-04-12T16:25:21.887Z
Nicol Bolas
<p>The OpenGL SuperBible 7th Edition points out that </p>

<blockquote>
  <p>the glMemoryBarrier() function supports a bit specifically for synchronizing access to atomic counters with other parts of the OpenGL pipeline</p>
</blockquote>

<p>and describes its usage.</p>

<p>The <a href="https://www.khronos.org/opengl/wiki/Atomic_Counter" rel="nofollow noreferrer">OpenGL Wiki</a> says:</p>

<blockquote>
  <p>Atomic counter memory access is not incoherent. So it follows the same rules as for texture reads, framebuffer writes, and so forth, not the Image Load/Store rules. You do not need to use a glMemoryBarrier to synchronize counter accesses.</p>
</blockquote>

<p>So now I am confused:</p>

<p>Do I (and if so when do I) need to use <code>glMemoryBarrier</code> when using an atomic counter?</p>

<opengl><memory>
Do I need to use glMemoryBarrier with atomic counters?
Startec
# Do I need to use glMemoryBarrier with atomic counters?

(Asked by: username_0 on 2017-09-04)

The OpenGL SuperBible 7th Edition points out that

> the glMemoryBarrier() function supports a bit specifically for synchronizing access to atomic counters with other parts of the OpenGL pipeline

and describes its usage.

The [OpenGL Wiki](https://www.khronos.org/opengl/wiki/Atomic_Counter) says:

> Atomic counter memory access is not incoherent. So it follows the same rules as for texture reads, framebuffer writes, and so forth, not the Image Load/Store rules. You do not need to use a glMemoryBarrier to synchronize counter accesses.

So now I am confused:

Do I (and if so when do I) need to use `glMemoryBarrier` when using an atomic counter?

**Tags:** opengl, memory


---

## 1 answers

### Answer by username_1 on 2017-09-04. Score: 4 | Accepted answer

The post October 22, 2019 version of the OpenGL 4.6 standard gives atomic counters the same incoherency restrictions as image load/store and SSBO operations. You have to use explicit barriers to synchronize access to them and so forth. This is a textual change from older versions of the standard, but it isn't a behavioral change from implementations. The older wording [is considered a bug](https://github.com/KhronosGroup/OpenGL-API/issues/14) and thus it should be assumed that atomic counters have always worked incoherently.

---

Note: the following predates the October 22, 2019 update to OpenGL 4.6.

From the OpenGL 4.6 specification, section 7.12: Shader Memory Access:

> As described in the OpenGL Shading Language Specification, shaders may perform random-access reads and writes to buffer object memory by reading from, assigning to, or performing atomic memory operation on shader buffer variables, or to texture or buffer object memory by using built-in image load, store, and atomic functions operating on shader image variables. The ability to perform such random-access reads and writes in systems that may be highly pipelined results in ordering and synchronization issues discussed in the sections below.

Notice something missing from that list? It mentions "shader buffer variables", and "shader image variables". But atomic counter variables are not mentioned. And atomic counter variables are a different kind of thing from either of those.

Therefore, that entire section (which is what explains the behavior of `glMemoryBarrier`) does not apply to atomic counters. Well, except where it specifically says otherwise, but that's only where it defines that helper FS invocations don't have side-effects. Note that even this *explicitly* calls out atomic counters as being something different from regular buffer or image operations: "stores, atomics, and atomic counter updates".

To lend greater credence to this view, the [ARB\_atomic\_counter\_buffer\_object](https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_shader_atomic_counters.txt) extension does not mention barriers at all. It doesn't require [ARB\_shader\_image\_load\_store](https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_shader_image_load_store.txt) as a companion extension either, which is what defines `glMemoryBarrier`. Indeed, it has no interactions whatsoever with image load/store, while image load/store does have specified interactions with atomic counters.

Given the weight of the evidence in the specifications, I would have to say that the Wiki is right. In the interest of full disclosure, I did write that Wiki article. Though I also did all this research *before* I wrote it.

Basically, what the API seems to be saying is that buffer updates from atomic counters are treated like buffer updates from feedback operations. The implementation is required to track when you attempt to use that buffer for a read operation, then issue any synchronization needed to make sure that you can read the value. Or if you write to the value in the buffer (like clearing it to a value), then the implementation must automatically synchronize this.

The likely reason the specification permits this for atomic counters but not for image load/store is that the range of data for atomic counters is *fixed*. SSBOs and image load/store through buffer textures can write to arbitrary parts of the bound range of buffer data. By contrast, atomic counters write to 4 bytes times the number of atomic counter variables used by the shader.

Note however that atomic counters are affected by the in-shader `memoryBarrier` function. That is, atomic counters are subject to the requirements of, as the Wiki calls it, "[Internal Visibility](https://www.khronos.org/opengl/wiki/Memory_Model#Internal_visibility)". Granted, that's not very useful most of the time, as the primary use of atomic counters is for when multiple invocations are all updating the same one.

---

On the other hand:

> the glMemoryBarrier() function supports a bit specifically for synchronizing access to atomic counters with other parts of the OpenGL pipeline

The specification describes this particular barrier as:

> Memory accesses using shader atomic counter built-in functions issued after the barrier will reflect data written by shaders prior to the barrier. Additionally, atomic counter function invocations after the barrier will not execute until all memory accesses (e.g., loads, stores, texture fetches, vertex fetches) initiated prior to the barrier complete.

What's curious about this is the "all memory accesses" part. This specific wording is only used in two other bits: shader storage and shader image. Other barriers for coherent operations like query buffers and transform feedbacks tend to use the term "all shader writes".

So... I would say that there is confusion at the specification level.

> **Comments:**
> **username_2**: Which apparently prompted https://github.com/KhronosGroup/OpenGL-API/issues/14 !  
> **username_2**: I referenced your issue in my research for https://stackoverflow.com/questions/56340333/glsl-about-coherent-qualifier/60434348#60434348 Since you wrote the wiki article in question, I'd be very interested to have you take on my findings.  

---

