Using glUniform and binding an UBO at the same time - opengl

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.

Related

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.

Identifying Uniform buffer in a GLSL shader

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.

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.

How does glGetUniformBlockIndex know whether to look in the vertex shader or the fragment shader?

I start by attaching to my program both shaders and then call glGetUniformBlockIndex to bind the uniform buffers. I would expect a glBindShader function to let me specify which shader I want to parse to find the uniform, but there is no such thing.
How can I tell OpenGL which shader it should look into?
Assuming the program has been fully linked, it doesn't matter. Here are the possibilities for glGetUniformBlockIndex and their consequences:
The uniform block name given is not in any of the shaders. Then you get back GL_INVALID_INDEX.
The uniform block name given is used in one of the shaders. Then you get back the block index for it, to be used with glUniformBlockBinding.
The uniform block name given is used in multiple shaders. Then you get back the block index that means all of them, to be used with glUniformBlockBinding.
The last part is key. If you specify a uniform block in two shaders, with the same name, then GLSL requires that the definitions of those uniform blocks be the same. If they aren't, then you get an error in glLinkProgram. Since they are the same (otherwise you wouldn't have gotten here), GLSL considers them to be the same uniform block.
Even if they're in two shader stages, they're still the same uniform block. So you can share uniform blocks between stages, all with one block binding. As long as it truly is the same uniform block.