1
$\begingroup$

The background of this question is that I am trying to write an automatic binding system, where for each uniform variable I want to declare in my GLSL code, I call a method declareUniform which is counting up the location value, saving the type and name of the uniform to a list which will be saved within my shaderobject...

I already did something similar with varyings, where I save the varying information (location, type, name, shader stage from, shader stage to, isarray, arraycount) and of cause also generating glsl string which is working fine.

I am trying to bind several things to a shader, which does not work right now. I've read, that uniform block binding indices have nothing to do with sampler binding locations here, which is totally confusing me... I also read the Explicit_uniform_location site from khronos here. I am trying to bind some sampler2D, image2D and other uniforms in one shader.

layout(location = 0) in  vec2 texCoordIn; //value from VBO
layout(binding = 0, rgba32f) uniform  image2D writeColorTexture;
layout(binding = 1) uniform  sampler2D readColorTexture;
layout(location = 0) uniform  float u_apature;
layout(location = 1) uniform  float u_focalDistance;
...

On CPU it looks like this:

GLint readColorTextureLoc = glGetUniformLocation(glShaderHandle, "readColorTexture");
GLint writeColorTextureLoc = glGetUniformLocation(glShaderHandle, "writeColorTexture");

trying to bind the samper2D:

glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
glUniform1i(readColorTextureLoc, 0);
glBindTexture(GL_TEXTURE_2D, colorTexture->id());

trying to bind the image2D:

glBindImageTexture(writeColorTextureLoc, colorImage->id(), 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_RGBA32F);

when using glGetUniformLocation(glShaderHandle, "readColorTexture"); I get the value 31 which also confuses me. This brought me to understand it to the following way: layout(location = ...) uniform is the value which will be returned by glGetUniformLocation.

The binding qualifier maps the uniform variable to a (I'll call it) "background list", which can be addressed by glActiveTexture for example if it is a sampler. As far as I understood (please correct me if I am wrong!) there are several of these "background lists". One for samplers, one for block bindings, one for images... and each of them starts with 0.

Now my question: Am I right? Did I understand it correctly? If so: which "background lists" are available and how can I bind a sampler together with an Image?

$\endgroup$
2
  • $\begingroup$ I don't want this example to just work... I want it to be perfect, so when adding another shader, that no effects start to appear, which needs a lot of time to debug. So it need to be a closed concept, which fully controls each binding slot $\endgroup$
    – Thomas
    Commented Jan 13, 2022 at 9:35
  • $\begingroup$ "automatic binding system" Don't do that. If your shader has hard-coded into it an image binding point, just use that. There's no need to query what you already know is there. $\endgroup$ Commented Jan 13, 2022 at 14:54

2 Answers 2

3
$\begingroup$

While OpenGL's organic growth as an API has led to some inconsistencies regarding the naming of things, the API here means what it says. location means location, and binding means binding. As such, a function named glGetUniformLocation should be expected to return the location of the uniform, not the binding.

When introspecting GLSL, there are several quantities to consider. For a particular kind of thing (program inputs, uniforms, etc. In the modern introspection API, these are called "interfaces"), all of the introspectable variables (called "resources") are given an index as if they're all in an array. This index is from 0 to the number of active resources in this interface.

You can then query properties about a resource (name, etc) by its index. But the index of a resource is neither its location nor its binding; it is merely an identifier for the resource.

Some resources have a location; a number used by the API to directly affect the value it gets or gives. Program inputs use locations to determine which variable gets when data from the VAO (or prior program stage if the program doesn't contain a VS). Uniform locations are how you set values into the uniform via glProgramUniform* calls. And so forth.

Some resources have a binding; a number which represents the index in a table (in the OpenGL context) for how the resource is used to access memory of some kind. The binding for opaque types determine which binding slot the given object represents. To make a memory object (texture or buffer) available to this resource, you bind that object to the binding index for that kind of access (image load/store, texture, etc).

So if you have an image uniform, the location determines how you would set its binding from the API via glProgramUniform1i. But the binding determines which index in the OpenGL context the OpenGL object you're trying to access will be bound to. If you do not assign a location to a uniform in the shader, the API will assign one itself, which you would have to query (if you need to change the binding for some reason. Which you shouldn't).

$\endgroup$
-1
$\begingroup$

https://www.khronos.org/opengl/wiki/Interface_Block_(GLSL)

uniform without buffer backed, only location, no binding.

location similar to position offset.

// shader code
layout (location = 0) uniform float fTime;

// host code
location = 0;
glUniform1f(location, 45.2f);  // update data to uniform location 0

more shader example

// each array element consume 1 location
layout(location = 0) out vec3 vals[4];      // Consumes 4 locations
// each struct field consume location
struct OutData{
    vec3 data1;                             // Consumes 1 location
    dvec4 data2;                            // Consumes 2 location
    float val[3];                           // Consumes 3 location
};
layout(location = 4) out OutData myOut;     // Consumes 6 locations
layout(location = 10) out vec2 texCoord;    // Consumes 1 location

uniform block with buffer backed, only binding, no location.

binding is something like block index, the field offset inside the buffer similar to location.

// shader code
layout(binding = 0, std140) uniform MainBlock { // blockIndex = 0
    vec3 data;
};

// host code
storageBlockIndex= 0;
uniformBlockBinding = 1; // any value
glUniformBlockBinding(program, storageBlockIndex, uniformBlockBinding);
glBindBufferBase(GL_UNIFORM_BUFFER, uniformBlockBinding, bufferId);

relation of block index and binding point:

buffer id          binding points 0            uniform block index
buffer id   \/     binding points 1    \/      uniform block index
buffer id   /\     binding points 2    /\      uniform block index

for sampler, binding is texture unit, also can specify location

// shader code
//layout (binding = 0) uniform sampler2D foo;
layout (location = 0, binding = 1) uniform sampler2D foo;

// host code
location = 0;
unit = 1;
glActiveTexture(GL_TEXTURE0 + unit);      // set active unit
glBindTexture(GL_TEXTURE_2D, textureId);  // put to current active unit

glUniformli(location, unit);

relation of texture unit and uniform location:

texture id          texture unit 0            uniform location
texture id   \/     texture unit 1    \/      uniform location
texture id   /\     texture unit 2    /\      uniform location

 
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.