PDA

View Full Version : 2 Samplers FS fails: Different sampler types for same sample texture unit in fragment



Betrayal
10-17-2014, 11:18 AM
Hello,

my little program implements multitexturing. One ordinary texture and one cubemap.
The shaders compile and link fine but in validation i get the following error:

"Validation failed! - Different sampler types for same sample texture unit in fragment shader."

This is the code of the fragmentshader:



#version 330

uniform sampler2D colorMap;
uniform samplerCube cubeMap;

uniform vec4 diffuseColor;
uniform vec4 ambientColor;

in vec3 vVaryingCubeTexCoords;
in vec2 vVarying2DTexCoords;

out vec4 vFragColor;

void main(void)
{
vFragColor = texture(cubeMap, vec3(vVaryingCubeTexCoords.x, vVaryingCubeTexCoords.y, -vVaryingCubeTexCoords.z));
vFragColor *= texture(colorMap, vVarying2DTexCoords.st);
}



Again: the error appears at validation, so long before any rendering, so the actual renderingcode is not important (Fun fact: everything renders as expected on my machine. I nevertheless want to understand the error)

Now, when i change the sampler declarations into the following
layout(binding=7) uniform sampler2D colorMap;
layout(binding=4) uniform samplerCube cubeMap;
the error disappears. The numbers 7 and 4 are entirely arbitrary and i don't understand what's going on. If both numbers are the same, the error comes back; if they are different, the error is solved.
Even after googleing i don't understand what 'binding' does. It is, as far as i see, not related to uniform-locations. My locations later in rendering code are setup correct (afair):


GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, texSphere);
GL.ActiveTexture(TextureUnit.Texture1);
GL.BindTexture(TextureTarget.TextureCubeMap, texCubeMap);
GL.Uniform1(locColorMap, 0);
GL.Uniform1(locCubeMap, 1);



Can anyone help or explain?
Thanks in advance and excuse my bad english.

Nikki_k
10-17-2014, 02:17 PM
From looking at the code to bind the textures and set the samplers, I think that at validation time both samplers do indeed point to the same texture unit. You should make these GL.Uniform calls right after linking.

arekkusu
10-17-2014, 02:45 PM
See the (https://www.opengl.org/discussion_boards/showthread.php/183706-sampler2D-limitations?highlight=arekkusu) previous (https://www.opengl.org/discussion_boards/showthread.php/163160-validate-error?highlight=validateprogram) threads (https://www.opengl.org/discussion_boards/showthread.php/176778-Strange-link-error-when-using-samplerCube?highlight=validateprogram).

Highlighting the important part of the documentation (https://www.khronos.org/opengles/sdk/docs/man/xhtml/glValidateProgram.xml):

glValidateProgram checks to see whether the executables contained in program can execute given the current OpenGL state.

So: if your validation is part of your shader loading, consider re-factoring it into a wrapper around your draw calls instead.

Betrayal
10-17-2014, 10:52 PM
Indeed i was calling glValidate right after linking of my shaders. That's what i "learnt" from my textbook but now after reading the official documentation and your hint i refactored the code into:



shader.Use();
shader.SetUniforms(...);
shader.Validate();
drawcall();


and the validation succeeds now. It makes sense because the Uniform-Values for the two samplers are correctly bound to two different textureunits now.
So thank you very much for you help.

But i'm wondering whats the best practice when vadidating shaders.



This function is typically useful only during application development. The informational string stored in the information log is completely implementation dependent; therefore, an application should not expect different OpenGL implementations to produce identical information strings.
Why only during development? Especially when the outcome is implementation defined it could happen that validation fails on other machines and gives valueable feedback, right?
So maybe something like this:


if(first)
{
shader.Validate();
first = false;
}
drawcall();

That means at validate the shaders right before the very first drawcall. Any recommendations?

arekkusu
10-17-2014, 11:52 PM
Why only during development? Especially when the outcome is implementation defined it could happen that validation fails on other machines and gives valueable feedback, right?


That's what beta testers and assert builds are for. After you've resolved all failures, turn off validate/geterror/etc in your release builds.

Osbios
10-18-2014, 05:50 AM
Why only during development? Especially when the outcome is implementation defined it could happen that validation fails on other machines and gives valueable feedback, right?
So maybe something like this:


if(first)
{
shader.Validate();
first = false;
}
drawcall();

That means at validate the shaders right before the very first drawcall. Any recommendations?

Well the problem with this is that it only tests with one set of input data (e.g. uniforms). But the input normally would change dynamically over the runtime of the application. Most likely you use a shader several times in the same frame with different uniform values.

Betrayal
10-18-2014, 06:57 AM
Thank you for your answers people.