Trivial OpenGL Shader Storage Buffer Object (SSBO) not working
Asked Answered
M

2

5

I am trying to figure out how SSBO works with a very basic example. The vertex shader:

#version 430

layout(location = 0) in vec2 Vertex;

void main() {
    gl_Position = vec4(Vertex, 0.0, 1.0);
}

And the fragment shader:

#version 430

layout(std430, binding = 2) buffer ColorSSBO {
    vec3 color;
};

void main() {
    gl_FragColor = vec4(color, 1.0);
}

I know they work because if I replace vec4(color, 1.0) with vec4(1.0, 1.0, 1.0, 1.0) I see a white triangle in the center of the screen.

I initialize and bind the SSBO with the following code:

GLuint ssbo;
glGenBuffers(1, &ssbo);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
float color[] = {1.f, 1.f, 1.f};
glBufferData(GL_SHADER_STORAGE_BUFFER, 3*sizeof(float), color, GL_DYNAMIC_COPY);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, ssbo);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);

What is wrong here?

Mackie answered 16/8, 2015 at 13:10 Comment(6)
Your usage flags strike me as a little odd, though I've never put any faith in them. You've told GL that this buffer is going to be filled with data that you copy from some other buffer, yet... when you allocate the buffer you're filling it with data from the client itself. I've long considered those hints a placebo, but you never know - this might be the world's first driver that actually takes those hints literally? :) Have you tried the more logical GL_DYNAMIC_DRAW usage hint?Virtual
You are going to run into an alignment issue if you try to extend this SSBO into an array though. You will need to change color to vec4 or place a float immediately after it. I'm sure you know this though.Virtual
The idea is to use that buffer to implement linked-list order indipendent transparency, so it will be written and then read only by fragment shaders, but in the meantime I'm testing it with host data. I tried both your suggestions but what I see is still a black screen :( Very frustrating.Mackie
Does the shader compiler / linker give you any error log information? I can easily picture the fragment shader working when you use a constant color but not when color is used in the event that something went wrong with the SSBO declaration.Virtual
No error is raised. I check the compilation and linking with standard code took from an official tutorial, then I do a double check with assert(glGetError() == GL_NO_ERROR). I have changed the clear color and now when using SSBO I see a black triangle. It seems that for a mysterious reason the data is not uploaded. I'm wondering if it's a driver issue.. the code is very very simple and I can't find any misuse of the API.Mackie
I cannot reproduce the problem with your code. Obviously, you are not showing your draw code. Would you mind writing up an MWE?Disarmament
E
7

My guess is that you are missing the SSBO binding before rendering. In your example, you are copying the content and then you bind it immediately, which is unnecessary for the declaration. In other words, the following line in your example:

...
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, ssbo);
...

Must be placed before rendering, such as:

...
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, ssbo);

/*
 Your render calls and other bindings here.
*/

glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
...

Without this, your shader (theoretically) will not be able to see the content.

In addition, as Andon M. Coleman has suggested, you have to use padding for your elements when declaring arrays (e.g., use vec4 instead of vec3). If you don't, it will apparently work but produce strange results because of this fact.

The following two links have helped me out understanding the meaning of an SSBO and how to handle them in your code:

https://www.khronos.org/opengl/wiki/Shader_Storage_Buffer_Object http://www.geeks3d.com/20140704/tutorial-introduction-to-opengl-4-3-shader-storage-buffers-objects-ssbo-demo/

I hope this helps to anyone facing similar issues!

P.S.: I know this post is old, but I wanted to contribute.

Euphorbia answered 18/10, 2017 at 21:32 Comment(0)
K
1

When drawing a triangle, three points are necessary, and 3 separate sets of red green blue values are required for each point. You are only putting one set into the shader buffer. For the other two points, the value of color drops to the default, which is black (0.0,0.0,0.0). If you don't have blending enabled, it is likely that the triangle is being painted completely black because two of its vertices are black.

Try putting 2 more sets of red green blue values into the storage buffer to see it will load them as color values for the other two points.

Kellogg answered 18/9, 2016 at 10:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.