<blockquote>
<p>If there is no such function, why have noone made an extension for this yet?</p>
</blockquote>
<p>Just because something might be &quot;useful&quot; doesn't mean it would be possible or cheap.</p>
<p>GPU hardware achieves blending by using an <em>entirely separate</em> piece of hardware, one that preserves the order of the fragment values generated by unordered fragment shader executions. These <a href="https://en.wikipedia.org/wiki/Render_output_unit" rel="nofollow noreferrer">execution units, commonly called &quot;ROPs&quot;</a>, are distinct hardware from fragment shaders.</p>
<p>CS's can't just do that. They have a fundamentally unordered execution model, and what you're talking about requires at least some ordering between them. That's not simple or cheap to implement, even if it's <em>possible</em> at all.</p>
<p>The closest you can get to that is <a href="https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_fragment_shader_interlock.txt" rel="nofollow noreferrer">fragment_shader_interlock</a>, which can force parts of FS execution to be ordered by primitive order and to execute critical sections that prevent overlapping executions. But as the name suggests, that's a feature of fragment shaders (and not one universally supported), not a feature of compute shaders.</p>
<p>Also, it doesn't really make sense to use a compute shader for post-processing effects, since FS's are perfectly capable of dealing with that sort of thing, and actually have access to ROPs.</p>

CC BY-SA 4.0
2021-03-14T18:41:33.080Z
BTW, it can make sense to use a compute shader for postprocessing in some cases, e.g. if it's an algorithm that can take advantage of threadgroup shared memory, or if it's beneficial to use async compute to overlap postprocessing work with something else.
Nathan Reed
CC BY-SA 4.0
2021-03-14T14:16:36.297Z
2021-03-14T14:16:36.297Z
Nicol Bolas
<p>You can always just do an image load, apply whatever math you want to the value, and then store it back out. This only works if you can ensure multiple CS invocations aren't trying to modify the same pixel—otherwise you get a race condition—but that limitation is fine for most lighting and postprocessing applications, where you're running a single CS dispatch across a whole framebuffer (or some tiles within a framebuffer), with one invocation per pixel.</p>

CC BY-SA 4.0
2021-03-14T18:59:07.887Z
"*This only works if you can ensure multiple CS invocations aren't trying to modify the same pixel*" It's not just modifying the same pixel; you can't read any pixel that another invocation *writes* to. So you'd have to write to a different image or different region of the image.
Nicol Bolas
CC BY-SA 4.0
2021-03-14T17:59:20.273Z
2021-03-14T17:59:20.273Z
Nathan Reed
<p>What I want is a function like <code>imageStore</code>, but instead of replacing a value - applying a blend operation to it, e.g. addition. It is not possible to do something like this with atomics due to them only operating on 32bit integers.</p>
<p>If there is no such function, why have noone made an extension for this yet? It seems rather useful for compute shader lighting, and some post-processing effects.</p>

<opengl><glsl><vulkan><compute-shader>
Is there an efficient way to achieve color blending in compute shaders?
user369070
# Is there an efficient way to achieve color blending in compute shaders?

(Asked by: username_0 on 2021-03-14)

What I want is a function like `imageStore`, but instead of replacing a value - applying a blend operation to it, e.g. addition. It is not possible to do something like this with atomics due to them only operating on 32bit integers.

If there is no such function, why have noone made an extension for this yet? It seems rather useful for compute shader lighting, and some post-processing effects.

**Tags:** opengl, glsl, vulkan, compute-shader


---

## 2 answers

### Answer by username_1 on 2021-03-14. Score: 1 | Accepted answer

> If there is no such function, why have noone made an extension for this yet?

Just because something might be "useful" doesn't mean it would be possible or cheap.

GPU hardware achieves blending by using an *entirely separate* piece of hardware, one that preserves the order of the fragment values generated by unordered fragment shader executions. These [execution units, commonly called "ROPs"](https://en.wikipedia.org/wiki/Render_output_unit), are distinct hardware from fragment shaders.

CS's can't just do that. They have a fundamentally unordered execution model, and what you're talking about requires at least some ordering between them. That's not simple or cheap to implement, even if it's *possible* at all.

The closest you can get to that is [fragment\_shader\_interlock](https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_fragment_shader_interlock.txt), which can force parts of FS execution to be ordered by primitive order and to execute critical sections that prevent overlapping executions. But as the name suggests, that's a feature of fragment shaders (and not one universally supported), not a feature of compute shaders.

Also, it doesn't really make sense to use a compute shader for post-processing effects, since FS's are perfectly capable of dealing with that sort of thing, and actually have access to ROPs.

> **Comments:**
> **username_2**: BTW, it can make sense to use a compute shader for postprocessing in some cases, e.g. if it's an algorithm that can take advantage of threadgroup shared memory, or if it's beneficial to use async compute to overlap postprocessing work with something else.  

---

### Answer by username_2 on 2021-03-14. Score: 0

You can always just do an image load, apply whatever math you want to the value, and then store it back out. This only works if you can ensure multiple CS invocations aren't trying to modify the same pixel—otherwise you get a race condition—but that limitation is fine for most lighting and postprocessing applications, where you're running a single CS dispatch across a whole framebuffer (or some tiles within a framebuffer), with one invocation per pixel.

> **Comments:**
> **username_1**: "*This only works if you can ensure multiple CS invocations aren't trying to modify the same pixel*" It's not just modifying the same pixel; you can't read any pixel that another invocation *writes* to. So you'd have to write to a different image or different region of the image.  

---

