<p>After looking into this for a while, I found out a couple of things:</p>

<ol>
<li><p><strong>You cannot avoid a memcpy</strong>: You cannot write directly into texture storage allocated for a compressed texture using only OpenGL API calls. This means that you cannot avoid the call to <code>glCompressedTexImage2D</code> with a bound PBO. That being said, you may be able to use a 16-bit RGBA texture and a GLSL image type in your compute shader.</p></li>
<li><p><strong>You do need to synchronize memory</strong>: In order to make sure that your compute shader finishes writing to your storage buffer, you must make sure that all reads and writes to it finish. This is done by calling <code>glMemoryBarrier</code> with <code>GL_SHADER_STORAGE_BARRIER_BIT</code>.</p></li>
</ol>

<p>The full code for something that writes into a buffer to be used as a compressed texture looks like this:</p>

<pre><code>GLuint buffer;
glGenBuffers(1, &amp;buffer);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
glBufferStorage(GL_SHADER_STORAGE_BUFFER, tex_size_in_bytes, 0, 0);

glUseProgram(compute_shader_prog);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, compute_shader_bind_point, buffer);
glDispatchCompute(wg_x, wg_y, wg_z);
glMemoryBarrier(GL_SHADER_STORAGE_BUFFER_BIT);

glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
glCompressedTexImage2D(GL_TEXTURE_2D, 0, fmt, w, h, 0, tex_size_in_bytes, 0);
</code></pre>

CC BY-SA 3.0
2015-09-19T01:12:24.700Z
"you may be able to use a 16-bit RGBA texture and a" AND A WHAT??? :)
Nathan Reed
CC BY-SA 3.0
2015-09-19T01:13:15.507Z
Haha, this is what happens when you leave the tab open to finish later. Edited.
Mokosha
CC BY-SA 3.0
2016-11-05T17:57:19.030Z
`GL_SHADER_STORAGE_BARRIER_BIT` Wrong barrier. The barrier you provide states how you will *use* the memory. Not how the shader wrote to it. You are doing a pixel transfer, so you need to use `GL_TEXTURE_UPDATE_BARRIER_BIT`
Nicol Bolas
CC BY-SA 3.0
2016-12-09T04:00:06.630Z
Are you sure? According to [the docs](http://docs.gl/gl4/glMemoryBarrier), `GL_TEXTURE_UPDATE_BARRIER_BIT` is used when synchronizing calls to `glTexImage`, and has nothing to do with the memory used in storage buffers. I think you meant `GL_PIXEL_BUFFER_BARRIER_BIT`?
Mokosha
CC BY-SA 3.0
2015-09-19T00:23:24.103Z
2015-09-19T01:13:41.147Z
2015-09-19T01:13:41.147Z
Mokosha
<p>I'm trying to figure out what the best way is to generate an OpenGL texture using a compute shader. So far, I've read that pixel buffer objects are good for non-blocking CPU -> GPU transfers, and that compute shaders are capable of reading and writing buffers regardless of how they're bound. Ideally, I'd like to avoid as many copies as possible. In other words, I'd like to allocate a buffer on the GPU, write compressed texture data to it, and then use that buffer as a texture object in a shader.</p>

<p>Currently, my code looks something like this:</p>

<pre><code>GLuint buffer;
glGenBuffers(1, &amp;buffer);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
glBufferStorage(GL_SHADER_STORAGE_BUFFER, tex_size_in_bytes, 0, 0);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);

// Bind buffer to resource in compute shader
// execute compute shader

glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
glCompressedTexImage2D(GL_TEXTURE_2D, 0, fmt, w, h, 0, tex_size_in_bytes, 0);
</code></pre>

<p>Is this correct? I read somewhere about guaranteeing synchronization, too. What do I need to add to make sure that my compute shader completes execution prior to copying from the buffer object?</p>

CC BY-SA 3.0
2015-09-10T17:13:32.990Z
Would you like to specify which texture compression format you prefer? I am guessing but your answer will likely involve a compute-mode texture compression routine.
ap_
<opengl><texture><compression><compute-shader>
Writing to a compressed texture using a compute shader, with no extra copies
Mokosha
# Writing to a compressed texture using a compute shader, with no extra copies

(Asked by: username_0 on 2015-08-21)

I'm trying to figure out what the best way is to generate an OpenGL texture using a compute shader. So far, I've read that pixel buffer objects are good for non-blocking CPU -> GPU transfers, and that compute shaders are capable of reading and writing buffers regardless of how they're bound. Ideally, I'd like to avoid as many copies as possible. In other words, I'd like to allocate a buffer on the GPU, write compressed texture data to it, and then use that buffer as a texture object in a shader.

Currently, my code looks something like this:

```
GLuint buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
glBufferStorage(GL_SHADER_STORAGE_BUFFER, tex_size_in_bytes, 0, 0);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);

// Bind buffer to resource in compute shader
// execute compute shader

glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
glCompressedTexImage2D(GL_TEXTURE_2D, 0, fmt, w, h, 0, tex_size_in_bytes, 0);

```

Is this correct? I read somewhere about guaranteeing synchronization, too. What do I need to add to make sure that my compute shader completes execution prior to copying from the buffer object?

**Tags:** opengl, texture, compression, compute-shader

> **Comments:**
> **username_1**: Would you like to specify which texture compression format you prefer? I am guessing but your answer will likely involve a compute-mode texture compression routine.  

---

## 1 answers

### Answer by username_0 on 2015-09-19. Score: 3

After looking into this for a while, I found out a couple of things:

1. **You cannot avoid a memcpy**: You cannot write directly into texture storage allocated for a compressed texture using only OpenGL API calls. This means that you cannot avoid the call to `glCompressedTexImage2D` with a bound PBO. That being said, you may be able to use a 16-bit RGBA texture and a GLSL image type in your compute shader.
2. **You do need to synchronize memory**: In order to make sure that your compute shader finishes writing to your storage buffer, you must make sure that all reads and writes to it finish. This is done by calling `glMemoryBarrier` with `GL_SHADER_STORAGE_BARRIER_BIT`.

The full code for something that writes into a buffer to be used as a compressed texture looks like this:

```
GLuint buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
glBufferStorage(GL_SHADER_STORAGE_BUFFER, tex_size_in_bytes, 0, 0);

glUseProgram(compute_shader_prog);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, compute_shader_bind_point, buffer);
glDispatchCompute(wg_x, wg_y, wg_z);
glMemoryBarrier(GL_SHADER_STORAGE_BUFFER_BIT);

glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
glCompressedTexImage2D(GL_TEXTURE_2D, 0, fmt, w, h, 0, tex_size_in_bytes, 0);

```

> **Comments:**
> **username_2**: "you may be able to use a 16-bit RGBA texture and a" AND A WHAT??? :)  
> **username_0**: Haha, this is what happens when you leave the tab open to finish later. Edited.  
> **username_3**: `GL_SHADER_STORAGE_BARRIER_BIT` Wrong barrier. The barrier you provide states how you will *use* the memory. Not how the shader wrote to it. You are doing a pixel transfer, so you need to use `GL_TEXTURE_UPDATE_BARRIER_BIT`  
> **username_0**: Are you sure? According to [the docs](http://docs.gl/gl4/glMemoryBarrier), `GL_TEXTURE_UPDATE_BARRIER_BIT` is used when synchronizing calls to `glTexImage`, and has nothing to do with the memory used in storage buffers. I think you meant `GL_PIXEL_BUFFER_BARRIER_BIT`?  

---

