Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a single texture image unit with multiple sampler uniforms

I am writing a batching system which tracks currently bound textures in order to avoid unnecessary glBindTexture() calls. I'm not sure if I need to keep track of which textures have already been used by a particular batch so that if a texture is used twice, it will be bound to a different TIU for the second sampler which requires it.

Is it acceptable for an OpenGL application to use the same texture image unit for multiple samplers within the same shader stage? What about samplers in different shader stages? For example:

Fragment shader:

...
uniform sampler2D samp1;
uniform sampler2D samp2;

void main() { ... }

Main program:

...
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex_id);
glUniform1i(samp1_location, 0);
glUniform1i(samp2_location, 0);
...

I don't see any reason why this shouldn't work, but what about if the shader program also included a vertex shader like this:

Vertex shader:

...
uniform sampler2D samp1;

void main() { ... }

In this case, OpenGL is supposed to treat both instances of samp1 as referencing the same location. Therefore, the same texture unit is being used in the vertex and fragment shaders. I have read that using the same texture in two different shader stages counts doubly against GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS but this would seem to contradict that.

In a quick test on my hardware (HD 6870), all of the following scenarios worked as expected:

  • 1 TIU used for 2 sampler uniforms in same shader stage
  • 1 TIU used for 1 sampler uniform which is used in 2 shader stages
  • 1 TIU used for 2 sampler uniforms, each occurring in a different stage.

However, I don't know if this is behavior that I should expect on all hardware/drivers, or if there are performance implications.

like image 893
bcrist Avatar asked Oct 02 '22 15:10

bcrist


1 Answers

Hopefully this will clear up some of your confusion, I used an older version of the spec. for simplicity, newer versions have two additional stages (tessellation control / evaluation) so the discussion is a little more complicated.

OpenGL 3.3 (Core Profile) - 2.11. Vertex Shaders - pp. 80

Texture Access

Shaders have the ability to do a lookup into a texture map. The maximum number of texture image units available to vertex, geometry, or fragment shaders are respectively the values of the implementation-dependent constants GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS, and GL_MAX_TEXTURE_IMAGE_UNITS. The vertex shader, geometry shader, and fragment shader combined cannot use more than the value of GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS texture image units. If more than one of the vertex shader, geometry shader, and fragment processing stage access the same texture image unit, each such access counts separately against the GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS limit.

The limit is imposed based on the number of unique samplers used in each stage. Two sampler uniforms with different names but which reference the same texture unit are effectively the same as far as usage determination is concerned. Usage refers to doing something like texture (sampler, coords), if that was not already obvious. Merely declaring a sampler and assigning it a value is not going to bring you any closer to the implementation-defined limit, you actually have to use the sampler at run-time and if it has the same value as another used sampler in the same stage it does not count.

As for using the same texture object multiple times, no this is not what the GL_MAX_..._IMAGE_UNITS limit is all about. You could bind the same texture to all 48 texture units (minimum implementation requirement in GL3.3 - this effectively mandates at least 16 textures per-stage) if you wanted, this limit refers to the number of different samplers you use (again, see above) in a shader stage. You might actually want to bind the same texture to multiple texture units if you need to use it once with nearest neighbor filtering and another time with linear or a different wrap state.

If you want to know what behavior to expect on all drivers/hardware, always consult the formal OpenGL specification. I cherry picked the relevant information for you, but it would do you well to learn how to search through it for important details in the future. Every specification since OpenGL 1.0 is freely available from: http://www.opengl.org/registry/.

like image 81
Andon M. Coleman Avatar answered Oct 11 '22 12:10

Andon M. Coleman