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?

Shepard
  • 801
  • 3
  • 9
  • 17
  • 2
    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? – Andon M. Coleman Aug 17 '15 at 01:36
  • 2
    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. – Andon M. Coleman Aug 17 '15 at 01:41
  • 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. – Shepard Aug 17 '15 at 15:04
  • 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. – Andon M. Coleman Aug 19 '15 at 00:41
  • 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. – Shepard Aug 19 '15 at 14:07
  • I cannot reproduce the problem with your code. Obviously, you are not showing your draw code. Would you mind writing up an MWE? – Nobody moving away from SE Jan 19 '16 at 14:04

2 Answers2

6

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.

SRG
  • 498
  • 7
  • 19
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.