PDA

View Full Version : Uniform Blocks and Uniform Buffers only?



Septimra
07-07-2015, 01:51 PM
Can I use a uniform buffer and uniform variables? All the text I see is about uniform blocks and uniform buffers. I want a way to store my uniforms in a buffer on the GPU, however I do not have any access to uniform blocks, by uniform_blocks bindings is 0. How can I get around this? I doubt the hardware the engine will run on in the end will have this limitation, but I am still curious.

Alfonse Reinheart
07-07-2015, 02:52 PM
You seem to be misunderstanding certain terminology.

An interface block (https://www.opengl.org/wiki/Interface_Block_%28GLSL%29) is a named collection of variables that are declared together. There are different types of interface blocks, which have different meanings.

A uniform block is an interface block who's data storage comes from a buffer object (https://www.opengl.org/wiki/Interface_Block_%28GLSL%29#Buffer_backed). Such a buffer is commonly called a "uniform buffer" or "uniform buffer object".

The storage for uniform variables not declared in a uniform block is part of the program object's state. They cannot be stored in buffer objects.

That being said:


however I do not have any access to uniform blocks, by uniform_blocks bindings is 0.

It's not clear what you mean by this.

If your implementation is OpenGL 3.1 or better, OpenGL ES 3.0 or better, or supports the ARB_uniform_buffer_object extension, the query GL_MAX_UNIFORM_BUFFER_BINDINGS will return at least 24 (12 per stage). It is not allowed to return 0 ever.

And if your implementation doesn't support these... then there's no way to even ask how many uniform buffer binding points there are, since the implementation doesn't know what a uniform buffer binding point is. Any attempt to query this limitation will result in an OpenGL error.

So it's not clear what you're doing if that query returns zero. Is that what you're querying or is that something else.

Septimra
07-07-2015, 04:58 PM
Yes it is odd. I queried GL_MAX_UNIFORM_BUFFER_BINDINGS and got 70. I could've sworn i got 0, must've queried something else.
Followup question:

Shaders compile.
Program links.

VertexShader looks like this:

#version 400

layout(location = 0) in vec3 pos;
layout(location = 1) in vec3 color;
layout(location = 2) in mat4 transformation;

layout(std140) uniform BlobSettings{
int scale;
};

uniform scales{
int yo;
}liked;

out vec3 out_color;

void main(){
vec4 scaled = transformation * vec4(pos, 1);
gl_Position = scaled;
out_color = color;
}

int loc = glGetUniformBlockIndex(program, "BlobSettings");

Should loc be GL_INVALID_INDEX? I thought I was getting that because GL_MAX_UNIFORM_BUFFER_BINDINGS was 0. But now I am baffled.

GClements
07-07-2015, 05:42 PM
int loc = glGetUniformBlockIndex(program, "BlobSettings");

Should loc be GL_INVALID_INDEX?

Yes. The shader doesn't access any of the members of the BlobSettings uniform block, so the block isn't active (the linker discards it). Most program queries only work for active resources (inactive resources which are discarded by the linker simply don't exist).
The glGetUniformBlockIndex reference page (https://www.opengl.org/sdk/docs/man3/xhtml/glGetUniformBlockIndex.xml) says:


If uniformBlockName does not identify an active uniform block of program, glGetUniformBlockIndex returns the special identifier, GL_INVALID_INDEX.

The std140 layout prevents the linker from removing members from the block (or otherwise altering its layout), but it doesn't prevent it from discarding the entire block.


I thought I was getting that because GL_MAX_UNIFORM_BUFFER_BINDINGS was 0. But now I am baffled.
If the program has too many uniform blocks, you'll get an error from glLinkProgram().

Septimra
07-07-2015, 06:43 PM
Just to test, what will be the simplest way to get the shader to pickup on the uniform?

I tried giving the uniform a value inside the block then use it in main, but that did not work.

Alfonse Reinheart
07-07-2015, 10:08 PM
Just to test, what will be the simplest way to get the shader to pickup on the uniform?

I tried giving the uniform a value inside the block then use it in main, but that did not work.

If you mean that you did something like this:



uniform BlockName
{
int five = 5;
};

...


Of course that didn't work. How could it work? The whole point of a uniform block is that the storage for the data is not part of the shader; the data storage comes from outside the program (in a buffer). So how could the program force a value into that storage?

If that's what you did, I'm surprised your compiler even let that compile, since it's against the grammar.

If that's not what you did, then you need to make it more clear exactly what you did do. And how it "did not work".

GClements
07-07-2015, 10:13 PM
Just to test, what will be the simplest way to get the shader to pickup on the uniform?
It has to affect the output of the program in some way. For a vertex shader, it will be kept if it affects gl_Position or affects some output which is actually used by the fragment shader (or the fixed-function pipeline if no fragment shader is present). In turn, fragment shader variables will be kept if they affect gl_FragColor or a user-defined output. In either shader, affecting the value of an atomic counter, image or buffer variable will also work.

Conversely, any variable which clearly has no effect upon the end result will be discarded. Any variable whose only effects are upon discarded variables will itself be discarded, and so on.

Also: while std140 ensures that variables won't actually be removed from the block definition, affecting a variable which is unused but kept solely because of the std140 layout may not be enough to cause the original variable to be kept.

In short: try to make the variable have an "almost visible" effect upon the output. Even if it only changes a single pixel by a minuscule amount which is eventually lost in quantisation, that should still force the compiler to keep it.

Septimra
07-08-2015, 07:32 AM
I'm still learning about these things Alfonse.. But thanks, I get it now. I just wasn't sure because you can give uniform variables a value, whynot uniform variables in a uniform buffer? But, if the
The whole point of a uniform block is that the storage for the data is not part of the shader then my bad. It makes perfect sense.

Alright. GClements, I affected it. But since there was nothing in the uniform block, it would crash if I used it, so I just didn't use it. But when I queried GL_ACTIVE_UNIFORM_BLOCKS, I got 1--Moreso when I called glGetUniformBlockIndex(program, "BlobSettings"); it gave me 0.

Thanks So much you guys.