<p>To write to an arbitrary location in a FBO you need to do rasterization of point primitive at that location. This is significantly more costly than a single <code>imageStore</code> because it involves invoking the vertex shader, the ROP units, and possibly rasterizing a whole 2x2 quad or more for just a single pixel.<sup>†</sup> With <code>imageLoad</code>/<code>imageStore</code> you have greater flexibility and finer control of where you read and write, including atomics, barriers, etc... Since you skip the ROP and give up the API-order guarantee, such direct writes might be faster even for filling triangles.</p>

<hr>

<p>† I'm not sure about this last point, but since the screen-space derivatives are still available in the fragment shader, and point primitives are typically used for larger sprites, it means that the implementations are more likely to just go the typical rasterization route used for lines and triangles.</p>

CC BY-SA 3.0
2017-07-27T11:28:31.237Z
2017-07-27T11:28:31.237Z
Yakov Galka
<p>The documentation quickly sum up the idea with: </p>

<blockquote>
  <p>The idea with image load/store is that the user can bind one of the
  images in a Texture to a number of image binding points (which are
  separate from texture image units). Shaders can read information from
  these images and write information to them, in ways that they cannot
  with textures.</p>
</blockquote>

<p>Aside for the simplicity of usage, from <a href="http://rastergrid.com/blog/2011/08/an-introduction-to-opengl-4-2/" rel="nofollow noreferrer">An introduction to OpenGL 4.2 | Daniel Rákos Blog</a> at the section <strong>ARB_shader_image_load_store</strong> you can perform more complex operations and algorithms in GLSL to a single level of a texture (which is called an image) and from any shader stage.</p>

<p>I am also curious about the implementation of the example with FBO since I don't understand why you cannot write to a specific pixel coordinate too.</p>

CC BY-SA 3.0
2017-07-27T11:03:05.473Z
2018-04-09T09:41:50.900Z
2018-04-09T09:41:50.900Z
AlexM
<blockquote>
  <p>Why would you use Images instead of Framebuffers?</p>
</blockquote>

<p><a href="https://www.khronos.org/opengl/wiki/Image_Load_Store" rel="noreferrer">Image Load/Store</a> is not intended to replace framebuffers. It's a feature that allows (relatively) arbitrary reading and writing to memory. So you would use images when you need to arbitrarily read and write to memory. You would use framebuffers when you're rasterizing primitives for rendering purposes.</p>

<p>The fact that you can build scenarios where you would use the latter in place of the former does not mean that this is the purpose of the feature.</p>

<blockquote>
  <p>What advantages do they offer?</p>
</blockquote>

<p>Again, it's not meant to replace framebuffers. But the comparison is pretty simple.</p>

<p>A particular FS invocation cannot:</p>

<ul>
<li><p>Choose what framebuffer texel(s) to write to. An FS invocation will only ever write outputs to the framebuffer texel(s) that map to its current fragment location. <code>gl_FragCoord</code> is an input value; it is non-modifiable. An FS's outputs will either be <a href="https://www.khronos.org/opengl/wiki/Fragment#Fragment_discard" rel="noreferrer">discard</a> or written to the framebuffer texel(s) corresponding to <code>gl_FragCoord.xy</code>.</p>

<p>Yes, through point rasterization, you can select which fragment is being generated. But it isn't the fragment shader <em>itself</em> that's deciding this; it's whatever process wrote the vertex to the buffer that it's being read from. That is not under the direct control of the FS invocation itself.</p></li>
<li><p>Choose to write to multiple distinct framebuffer texel(s) locations. A fragment cannot cover multiple texels.</p></li>
<li>Choose which output attachments in the framebuffer to write to. The decision of which <a href="https://www.khronos.org/opengl/wiki/Fragment#Fragment_shader_outputs" rel="noreferrer">fragment shader outputs</a> will be written is made by the <a href="https://www.khronos.org/opengl/wiki/Write_Mask" rel="noreferrer">write mask state</a>, which the FS has zero control over. An FS can choose to be <a href="https://www.khronos.org/opengl/wiki/Fragment#Fragment_discard" rel="noreferrer">discarded</a>, but that discards <em>all</em> of its outputs.</li>
<li>Choose to read from the current framebuffer texel(s) it is writing to. <a href="https://www.khronos.org/opengl/wiki/Blending" rel="noreferrer">Blending</a> is done by a fixed-function stage; the FS has zero control over this. The closest you can get is to employ some <a href="https://www.khronos.org/opengl/wiki/Texture_Barrier" rel="noreferrer">texture barrier gymnastics</a>, but that's not something the FS can directly control.</li>
<li>Choose to read from framebuffer texel(s) other than the one it's writing to. Even with texture barrier gymnastics, you cannot read from other people's texels.</li>
</ul>

<p>Now granted, image load/store doesn't exactly make read/modify/write passes easy, due to <a href="https://www.khronos.org/opengl/wiki/Memory_Model#Incoherent_memory_access" rel="noreferrer">incoherent memory access rules</a>.</p>

<p>Of course, image load/store cannot handle (easily):</p>

<ul>
<li>Depth testing. Or at least, not in any way that is <em>nearly</em> as efficient as the rasterizer. The read/modify/write nature of the depth test makes this exceedingly tricky with image load/store. With a regular depth buffer however, this is trivial.</li>
<li>Simple blending. Again, you can do it, but it's really hard, and far less efficient than the normal rendering process.</li>
</ul>

CC BY-SA 3.0
2017-07-27T16:21:35.037Z
2017-07-27T16:21:35.037Z
Nicol Bolas
<p><a href="https://github.com/Erkaman/image-load-store-demo" rel="nofollow noreferrer">One example</a> of Image Load / Stores that I have seen could be done using framebuffers instead of Image Load / Stores.  Framebuffers have been available longer in OpenGL and so my question is:</p>

<p>Why would you use Images instead of Framebuffers?</p>

<p>What advantages do they offer?</p>

<p>The referenced example says:</p>

<blockquote>
  <p>Note that this demo can also easily be imlemented using Framebuffer Objects. But with Framebuffer Objects you cannot write to arbitrary locations in a texture, though.</p>
</blockquote>

<p>I am not exactly sure what is meant here. My understanding is that you <em>can</em> write to whatever pixel coordinates you want in an FBO.  Am I mistaken here?</p>

<opengl><frame-buffer>
Why use image load / stores instead of FBOs
Startec
# Why use image load / stores instead of FBOs

(Asked by: username_0 on 2017-07-27)

[One example](https://github.com/Erkaman/image-load-store-demo) of Image Load / Stores that I have seen could be done using framebuffers instead of Image Load / Stores. Framebuffers have been available longer in OpenGL and so my question is:

Why would you use Images instead of Framebuffers?

What advantages do they offer?

The referenced example says:

> Note that this demo can also easily be imlemented using Framebuffer Objects. But with Framebuffer Objects you cannot write to arbitrary locations in a texture, though.

I am not exactly sure what is meant here. My understanding is that you *can* write to whatever pixel coordinates you want in an FBO. Am I mistaken here?

**Tags:** opengl, frame-buffer


---

## 3 answers

### Answer by username_3 on 2017-07-27. Score: 6 | Accepted answer

> Why would you use Images instead of Framebuffers?

[Image Load/Store](https://www.khronos.org/opengl/wiki/Image_Load_Store) is not intended to replace framebuffers. It's a feature that allows (relatively) arbitrary reading and writing to memory. So you would use images when you need to arbitrarily read and write to memory. You would use framebuffers when you're rasterizing primitives for rendering purposes.

The fact that you can build scenarios where you would use the latter in place of the former does not mean that this is the purpose of the feature.

> What advantages do they offer?

Again, it's not meant to replace framebuffers. But the comparison is pretty simple.

A particular FS invocation cannot:

* Choose what framebuffer texel(s) to write to. An FS invocation will only ever write outputs to the framebuffer texel(s) that map to its current fragment location. `gl_FragCoord` is an input value; it is non-modifiable. An FS's outputs will either be [discard](https://www.khronos.org/opengl/wiki/Fragment#Fragment_discard) or written to the framebuffer texel(s) corresponding to `gl_FragCoord.xy`.

  Yes, through point rasterization, you can select which fragment is being generated. But it isn't the fragment shader *itself* that's deciding this; it's whatever process wrote the vertex to the buffer that it's being read from. That is not under the direct control of the FS invocation itself.
* Choose to write to multiple distinct framebuffer texel(s) locations. A fragment cannot cover multiple texels.
* Choose which output attachments in the framebuffer to write to. The decision of which [fragment shader outputs](https://www.khronos.org/opengl/wiki/Fragment#Fragment_shader_outputs) will be written is made by the [write mask state](https://www.khronos.org/opengl/wiki/Write_Mask), which the FS has zero control over. An FS can choose to be [discarded](https://www.khronos.org/opengl/wiki/Fragment#Fragment_discard), but that discards *all* of its outputs.
* Choose to read from the current framebuffer texel(s) it is writing to. [Blending](https://www.khronos.org/opengl/wiki/Blending) is done by a fixed-function stage; the FS has zero control over this. The closest you can get is to employ some [texture barrier gymnastics](https://www.khronos.org/opengl/wiki/Texture_Barrier), but that's not something the FS can directly control.
* Choose to read from framebuffer texel(s) other than the one it's writing to. Even with texture barrier gymnastics, you cannot read from other people's texels.

Now granted, image load/store doesn't exactly make read/modify/write passes easy, due to [incoherent memory access rules](https://www.khronos.org/opengl/wiki/Memory_Model#Incoherent_memory_access).

Of course, image load/store cannot handle (easily):

* Depth testing. Or at least, not in any way that is *nearly* as efficient as the rasterizer. The read/modify/write nature of the depth test makes this exceedingly tricky with image load/store. With a regular depth buffer however, this is trivial.
* Simple blending. Again, you can do it, but it's really hard, and far less efficient than the normal rendering process.


---

### Answer by username_1 on 2017-07-27. Score: 1

To write to an arbitrary location in a FBO you need to do rasterization of point primitive at that location. This is significantly more costly than a single `imageStore` because it involves invoking the vertex shader, the ROP units, and possibly rasterizing a whole 2x2 quad or more for just a single pixel.† With `imageLoad`/`imageStore` you have greater flexibility and finer control of where you read and write, including atomics, barriers, etc... Since you skip the ROP and give up the API-order guarantee, such direct writes might be faster even for filling triangles.

---

† I'm not sure about this last point, but since the screen-space derivatives are still available in the fragment shader, and point primitives are typically used for larger sprites, it means that the implementations are more likely to just go the typical rasterization route used for lines and triangles.


---

### Answer by username_2 on 2017-07-27. Score: 0

The documentation quickly sum up the idea with:

> The idea with image load/store is that the user can bind one of the
> images in a Texture to a number of image binding points (which are
> separate from texture image units). Shaders can read information from
> these images and write information to them, in ways that they cannot
> with textures.

Aside for the simplicity of usage, from [An introduction to OpenGL 4.2 | Daniel Rákos Blog](http://rastergrid.com/blog/2011/08/an-introduction-to-opengl-4-2/) at the section **ARB\_shader\_image\_load\_store** you can perform more complex operations and algorithms in GLSL to a single level of a texture (which is called an image) and from any shader stage.

I am also curious about the implementation of the example with FBO since I don't understand why you cannot write to a specific pixel coordinate too.


---

