Identifying Uniform buffer in a GLSL shader - opengl

I use glGetActiveUniform to query uniforms from the shaders.But I also use uniform buffers (regular and std140).Querying them returns an arrays with the primitive type of the uniform in the buffer.But I need a way to identify those are uniform buffers and not uniforms.
Examples of uniform buffers in a shader:
layout(std140, binding = LIGHTS_UBO_INDEX) uniform LightsBuffer {
LightInfo lights[MAX_LIGHTS];
};
Is it possible to query only buffers from GLSL shader?

Technically, what you actually have here is a uniform block. It has a name, but no type; its members (which are uniforms) have types, and I think that is what you are actually describing.
It is a pretty important distinction because of the way program introspection works. Using OpenGL 4.3+ (or GL_ARB_program_interface_query), you will find that you cannot query a type for GL_UNIFORM_BLOCK interfaces.
glGetActiveUniformBlockiv (...) can be used to query information about the uniform block, but "LightsBuffer" is still a block and not a buffer. By that I mean even though it has an attribute called GL_BUFFER_BINDING, that is really the binding location of the uniform block and not the buffer that is currently bound to that location. Likewise, GL_BUFFER_DATA_SIZE is the size of the data required by the uniform block and not the size of the buffer currently bound.

Related

Specifying Binding for Texture Arrays in glsl

In glsl 420 functionality was added to specify binding in the shader instead of having to call glUniform1i. For example:
layout(binding = 0) uniform sampler2D u_Texture;
But how can that be done for arrays?
layout(binding ?) uniform sampler2D u_Textures[16];
I want the bindings to be 0,1,2,...,15. Is there no way for me to do this in glsl without any glUniform calls?
See OpenGL Shading Language 4.60 Specification - 4.4.5. Uniform and Shader Storage Block Layout Qualifiers:
When used with OpenGL, if the binding qualifier is used with a uniform block or shader storage block instanced as an array, the first element of the array takes the specified block binding and each subsequent element takes the next consecutive binding point.
That means you just have to specify the binding point of the first sampler in the array:
layout(binding = 0) uniform sampler2D u_Textures[16];
But note, when samplers aggregated into arrays within a shader, these types can only be indexed with a dynamically uniform expression, or texture lookup will result in undefined values.
I recommend to use sampler2DArray (see Sampler) rather than an array of sampler2D.
See also:
Why are Uniform variables not working in GLSL?
In a fragment shader, why can't I use a flat input integer to index a uniform array of sampler2D?

Using glUniform and binding an UBO at the same time

As far as I understand uniforms in user defined uniform blocks are still regular uniforms. What happens if I use glUniform* to access it directly and at the same time bind a UBO to its binding point? Is this defined behaviour?
That's impossible. While uniforms in a uniform block are "uniforms" in some sense, that doesn't mean that block uniforms are the same as non-block uniforms in all ways.
Uniforms in a block do not have a location. If you try to use glGetUniformLocation with that uniform's name, it will return -1 (unless there's some non-block uniform with that name). Therefore, there is no way to use glUniform* to set their value.

Multiple UBOs without specifying binding point index explicitly

I am looking into OpenGL Uniform Buffer Objects and Shader Storage Buffers. I think the question applies to both of them, but let's just focus on UBOs.
Tutorials seem to be saying that "block index" and "binding point index" are different things, and if I have more than one UBO in a shader, I need to specify the binding index
layout(binding = 0) uniform first_buffer {...};
layout(binding = 1) uniform second_buffer {...};
I get the impression that the block index is determined by the linker and can be read from glGetUniformBlockIndex, but the binding point index has to be hard-coded with arbitrary distinct binding=N in the layout, and a corresponding glBindBufferBase(GL_UNIFORM_BUFFER, N, ubo_handle), which strikes me as fragile and a nuisance.
What is the difference between a block index and a binding point?
Can I omit the binding=N in the layout? What happens then with glBindBufferBase?
Is this all the same for SSBOs?
See OpenGL 4.6 API Core Profile Specification - 7.6 Uniform Variables
Named uniform blocks, as described in the OpenGL Shading Language Specification, store uniform values in the data store of a buffer object corresponding to
the uniform block. Such blocks are assigned a uniform block index.
The block index is the "handle" for the active program resource of a shader program. If you have different shader programs with the "same" uniform block, then they may have different buffer indices.
A buffer is bound to the uniform block of a shader program the binding point (e.g. in shader by a Binding point Layout Qualifier). On the one side a uniform block (index) is associated to a binding point and on the other side a buffer is bound to the binding point (by glBindBufferBase). So one buffer can be bound to the uniform blocks of different programs.
While the buffer index is fixed and and can't be changed after the program is linked, the binding point is a dynamic value and can be changed by glUniformBlockBinding. When the program is linked, then the binding point is initialized by 0 or by the value which is set by the Binding point Layout Qualifier.
This principle is the same for a Shader Storage Buffer Object.
Related questions are:
Difference between glBindBuffer and glBindBufferBase
Is it safe to use the block index as the binding point for UniformBufferObject, ShaderStorageBufferObjects, etc?
How do I query the alignment/stride for an SSBO struct?

Questions about uniform buffer objects

Is it guaranteed that if a uniform block is declared the same in multiple shader programs, say
uniform Matrices
{
mat4 ProjectionMatrix;
mat4 CameraMatrix;
mat4 ModelMatrix;
};
Will it have the same block index returned by glGetUniformBlockIndex(program, "Matrices")?
If the answer is yes, then I'm able to query the index of the block once and use it for all the shader programs that contain that block, right?
Second question: will ProjectionMatrix, CameraMatrix, ModelMatrix, always have the same layout order in memory, respectively? I'm asking this because the tutorial I read uses the next functions
// Query for the offsets of each block variable
const GLchar *names[] = { "InnerColor", "OuterColor",
"RadiusInner", "RadiusOuter" };
GLuint indices[4];
glGetUniformIndices(programHandle, 4, names, indices);
GLint offset[4];
glGetActiveUniformsiv(programHandle, 4, indices,
GL_UNIFORM_OFFSET, offset);
And I'm not sure if that's really needed, as long as I know the uniforms order inside the uniform block..?
will ProjectionMatrix, CameraMatrix, ModelMatrix, always have the same layout order in memory, respectively?
No. Here's what the standard states (emphasis mine):
If pname is UNIFORM_BLOCK_DATA_SIZE, then the implementation-
dependent minimum total buffer object size, in basic machine units, required to hold all active uniforms in the uniform block identified by uniformBlockIndex is returned. It is neither guaranteed nor expected that a given implementation will arrange uniform values as tightly packed in a buffer object. The exception to this is the std140 uniform block layout, which guarantees specific packing behavior and does not require the application to query for offsets and strides.
I'm not sure if that's really needed, as long as I know the uniforms order inside the uniform block..?
So, yes, the author is right in not assuming the layout is contiguous and does what's sensible (guaranteed to work always in all implementations): gets the uniform indices and assigns their values respectively.
Specifying layout(std140) will do the trick then, right?
Yes, you can avoid querying the location and uploading data every time by making use of both uniform buffer objects and std140. However, make sure you understand its alignment requirements. This information is detailed in ARB_uniform_buffer_object's specification. For an elaborate treatment with examples see OpenTK's article on Uniform Buffer Objects (UBO) using the std140 layout specification.
Is it guaranteed that if a uniform block is declared the same in multiple shader programs, will it have the same block index returned by glGetUniformBlockIndex(program, "Matrices")?
No. I've searched the OpenGL 3.3 specification which gives no such guarantees. From the standard's viewpoint, uniform blocks (default or named) are associated to a program, period. No existence/association of uniform blocks beyond a program is made in the specification.
Because there is no guarantee that uniform blocks will have the same index in different shader program, that means I need to call glBindBufferBase() everytime I switch programs, right?
Yes, see ARB_uniform_buffer_object's specification for an example.

GLSL, Array of textures of differing size

When doing multitexturing in GLSL, is there anyway to have an indexable array of samplers where each texture is a different size? This syntax isn't valid:
uniform sampler2D texArray[5];
Right now it seems like the only option is to individually create the samplers:
uniform sampler2D tex1;
uniform sampler2D tex2;
uniform sampler2D tex3;
uniform sampler2D tex4;
uniform sampler2D tex5;
But then I can't iterate through them, which is a real pain in the ass. Is there a solution?
This syntax isn't valid:
Says who? Arrays of samplers most certainly are valid (depending on the version). How you use them is a different matter.
GLSL 1.20 and below do not allow sampler arrays.
In GLSL 1.30 to 3.30, you can have sampler arrays, but with severe restrictions on the index. The index must be an integral constant expression. Thus, while you can declare a sampler array, you can't loop over it.
GLSL 4.00 and above allow the index to be a "dynamically uniform integral expression". That term basically means that all instantiations of the shader (within the same draw call) must get the same values.
So you can loop over a constant range in GLSL 4.00+, and index a sampler array with the loop counter. You can even get the index from a uniform variable. What you can't do is have the index depend on an input to the shader stage (unless that value is the same across all instances caused by the rendering command), or come from a value derived from a texture access (unless that value is the same across all instances caused by the rendering command), or something.
The only requirement on the textures placed in arrays of samplers is that they match the sampler type. So you have to use a GL_TEXTURE_2D on all the elements of a sampler2D array. Beyond that, the textures can have any number of differences, including size. The array exists to make coding easier; it doesn't change the semantics of what is there.
And remember: each individual element in the sampler array needs to be bound to its own texture image unit.
is there anyway to have an indexable array of samplers where each texture is a different size?
Not yet. Maybe this gets added to a later OpenGL version down the road, but I doubt it.
But then I can't iterate through them, which is a real pain in the ass. Is there a solution?
As a workaround you could use Array Textures and use only subregions of each layer. Use a vec4 array to store the boudaries of each picture on each layer.