Trying tutorial43 in ogldev.org it builds and runs fine except for an error message I get when I close the window, this is shown in image 1.
As can be seen in the image I printed out the texture units used the sampler2d and samplerCube and they are indeed different. The top of the trace output is shown in image3.
The correct image is as in image 2 produced by the program.
This indicates that at some point, when the program was “validated” against the current GL state (**), then the shader program:
Makes use of 2+ sampler uniforms,
At least 2 of these survive compile+link and are used in the resulting shader program binary, and
The texture image assigned to 2 or more of these are assigned the same texture image unit number.
(**) Shader program validation occurs when glValidateProgram() is called or a draw call is made with that shader program bound to the context.
So check the code for this. Assuming it’s not a driver bug, it’s likely being invoked someplace you’ve not looked at.
The easy way to avoid this is to just specify the texture unit bindings in your shader code, rather than specify them externally via glUniform1i(). For instance:
However, there’s no proper GL state setup before this call to glValidateProgram() to put the context in a reasonable state to validate or render with this shader program. That’s likely the problem here.
Evidence to support this is the prefix on that error message you quoted above.
Invalid shader program: active samplers with a different type refer to the same texture image unit
That’s the same prefix used to log error validation errors after glValidateProgram() is called:
However, the font shader source code doesn’t make use of more than 1 sampler uniform. So it’s vindicated.
So the cause of the validation error seems to be the lack of proper GL state setup prior to calling glValidateProgram() for the tutorial43 LightingTechnique shader program making use of the lighting.fs fragment shader. Specifically, the sampler uniform values for gColorMap and gShaderMap likely need to be setup properly first (glGetUniformLocation() + glUniform1i()) so that their texture image unit indices are distinct.
Just adding layout ( binding = 0 ) and layout ( binding = 1 ) in the fragment shader before the uniforms of sampler2D and samplerCube got rid of the error message. Thanks a lot for your expertise. I know this is the easy way out, will try to trace and set up the state correctly before glValidateProgram get called…
Adding explicit layout qualifiers is generally preferred in modern OpenGL, and enables greater code robustness as a tradeoff vs flexibility you probably don’t need.
Another robustness “trick” I generally use is to always bind different texture types to different texture units. OpenGL has well-defined rules for how all this works if you use the same texture unit, but using different texture units means that one part of my code becomes less dependent on what might be going on in other parts of it.
Once again: it’s easy, it’s lazy, but my code is simpler, each module is more robust against unwanted side-effects, and I get to spend more time writing new code than I spend debugging existing code.
Thanks for your response. Totally agree with you. In this case the hard way is a major overhaul/refactoring of someone else code which is not worth pursuing…
Happy to help! And this isn’t just the easy way out. This is the newer way, and the way that Vulkan requires it in Vulkan GLSL (if you’re thinking about that yet).
It makes your GLSL more portable if you’re largely doing things “the Vulkan way”.