Where are textures bound to in a framebuffer?

A framebuffer has 0 or more color attachments in the form of textures, and another texture or renderbuffer for storing the depth/stencil values. OK, this is what I know as a framebuffer object, I’ve been using it for a long time without problems, so have never given it a deeper thought. But today I found sth strange while debugging my application in RenderDoc, which brought me here to ask, where are these textures (color attachments of a framebuffer) actually bound to? I mean, although they are part of the framebuffer, they are still textures, so must be bound to somewhere before use right? It seems that OpenGL hides this detail from the users, perhaps they will use whatever texture units that are empty? Or maybe use some internally reserved texture slots?

I’m asking this because I have a fragment shader that declared two texture units:

...  // textures from 0 - 26
layout(binding = 27) uniform sampler2D opacity_map;
layout(binding = 29) uniform sampler2D anisotan_map;  // anisotropic tangent map (RGB)

these two slots (27 and 29) are only declared but not currently being used, no textures are bound there, and my program is running correctly.

What’s weird is that, in the first color pass where I render a triangle to the framebuffer (multisampled with 2 render targets), RenderDoc tells me that the input has a texture called exactly opacity_map and another one called exactly anisotan_map, but I never set them up on the CPU side, they are shown as empty inputs. Clicking into the resource inspector, I can clearly see they are actually the framebuffer’s color attachments, because the target is GL_TEXTURE_2D_MULTISAMPLE and it says it’s the source of the next framebuffer blit operation (for resolving MSAA). The log even shows a low severity warning “The texture object (0) bound to texture image unit 27 and 29 does not have a defined base level and cannot be used for texture mapping”, of course I didn’t so there are no errors. I’m not sure why the framebuffer is using my texture slots 27 and 29 for its color attachments!

Well, I guess texture object (0) is something special, what’s actually happening under the hood? Could someone give me a deeper insight? If I used up all texture units available (I have 32), will there be a collision with the framebuffer?

Textures which are attached to the current framebuffer typically aren’t bound to texture units. In particular, they normally shouldn’t be bound to a texture unit which is accessible to the current shader program (i.e. to a texture unit to which a sampler uniform refers), as that usually (*) creates a feedback loop which results in undefined behaviour.

(*) To clarify: textures aren’t attached to a framebuffer, texture levels are attached to the a framebuffer, and any level which is attached to the current draw framebuffer shouldn’t be accessible to the shader. If the attached level is outside of the range GL_TEXTURE_BASE_LEVEL to GL_TEXTURE_MAX_LEVEL, there isn’t an issue.

If the variables aren’t actually used in the shader, they presumably aren’t active uniforms and would normally be eliminated. It’s possible that RenderDoc is including eliminated variables in the list, but inspecting their values is producing nonsensical results.

1 Like

Textures which are attached to the current framebuffer typically aren’t bound to texture units

textures aren’t attached to a framebuffer, texture levels are attached to the framebuffer

Well that makes sense, but then will they consume texture image units? Is collision possible if I use image load store a lot?

No.

Collisions aren’t possible, but there a limit on the total number of “shader output resources”: fragment shader outputs, image units and shader storage blocks. So the number of fragment shader outputs can affect the maximum number of image units which can be used. The limit can be queried via GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES. A link error is generated if the limit is exceeded.

1 Like