๐ŸŽ‰ Celebrating 25 Years of GameDev.net! ๐ŸŽ‰

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Binary Shaders fail to link in OpenGL (Intel only issue)

Started by
3 comments, last by KarimIO 2ย years, 9ย months ago

I'm working on an OpenGL application and my shader binaries compiler properly, but fail to link and I can't find a reason. They only fail on my integrated Intel drivers, no warnings or errors occur in Nvidia. It fails to link when I add a third output to my shader. So my essential questions are:

  • Why is the linker failing when I add three or more outputs (the third being buffer2)
  • How to find linker errors like these in the future at compile time, or give the reason for the error at least!

I'm using spirv-cross and shaderc to convert a vulkan shader to an opengl shader to an opengl binary.

My debug won't give me any info either:

---------------
Debug message (1): SHADER_ID_LINK error has been generated. GLSL link failed for program 1, "Test Shader":
Source: Shader Compiler
Type: Error
Severity: high

---------------
Debug message (1282): Error has been generated. GL error GL_INVALID_OPERATION in UseProgram: (ID: 1001309929) Generic error
Source: API
Type: Error
Severity: high

I've posted my code in a gist as well as below. https://gist.github.com/KarimIO/e6b9716ce491cfdfe74196e426376bf5

Vertex Shader:

#version 450

layout(binding = 0, std140) uniform EngineUbo
{
    mat4 proj;
    mat4 view;
    mat4 model;
} ubo;

layout(location = 0) in vec3 vertexPosition;
layout(location = 0) out vec3 fragmentPosition;
layout(location = 1) out vec3 fragmentNormal;
layout(location = 1) in vec3 vertexNormal;
layout(location = 2) out vec3 fragmentTangent;
layout(location = 2) in vec3 vertexTangent;
layout(location = 3) out vec2 fragmentTexCoord0;
layout(location = 3) in vec2 vertexTexCoord0;

void main()
{
    vec4 posVec4 = ubo.model * vec4(vertexPosition, 1.0);
    gl_Position = (ubo.proj * ubo.view) * posVec4;
    fragmentPosition = posVec4.xyz;
    fragmentNormal = vertexNormal;
    fragmentTangent = vertexTangent;
    fragmentTexCoord0 = vertexTexCoord0;
}

Fragment Shader:

#version 450

layout(binding = 1, std140) uniform MaterialUbo
{
    vec4 color;
} materialUbo;

layout(binding = 2) uniform sampler2D albedoTexture;
layout(binding = 3) uniform sampler2D normalTexture;
layout(binding = 4) uniform sampler2D metalnessTexture;
layout(binding = 5) uniform sampler2D roughnessTexture;

layout(location = 3) in vec2 fragmentTexCoord0;
layout(location = 1) in vec3 fragmentNormal;
layout(location = 2) in vec3 fragmentTangent;
layout(location = 0) out vec4 gbuffer0;
layout(location = 0) in vec3 fragmentPosition;
layout(location = 1) out vec4 gbuffer1;
layout(location = 2) out vec4 gbuffer2;

vec3 TransformNormalToWorldSpace(vec3 vertexNormalValue, vec3 normalTextureSample, vec3 vertexTangentValue)
{
    vec3 bumpMapNormal = normalTextureSample;
    if (all(equal(normalTextureSample, vec3(0.0))))
    {
        return vertexNormalValue;
    }
    vec3 newNormal = normalize(vertexNormalValue);
    vec3 newTangent = normalize(vertexTangentValue);
    newTangent = normalize(newTangent - (newNormal * dot(newTangent, newNormal)));
    vec3 bitangent = cross(newTangent, newNormal);
    bumpMapNormal = (bumpMapNormal * 2.0) - vec3(1.0);
    bumpMapNormal = vec3(-bumpMapNormal.xy, bumpMapNormal.z);
    mat3 tangentBitangentNormalMatrix = mat3(vec3(newTangent), vec3(bitangent), vec3(newNormal));
    return normalize(tangentBitangentNormalMatrix * bumpMapNormal);
}

void main()
{
    vec4 albedo = materialUbo.color * texture(albedoTexture, fragmentTexCoord0);
    vec3 textureSpaceNormal = texture(normalTexture, fragmentTexCoord0).xyz;
    float metalness = texture(metalnessTexture, fragmentTexCoord0).x;
    float roughness = texture(roughnessTexture, fragmentTexCoord0).x;
    vec3 specular = mix(vec3(0.039999999105930328369140625), albedo.xyz, vec3(metalness));
    vec3 param = fragmentNormal;
    vec3 param_1 = textureSpaceNormal;
    vec3 param_2 = fragmentTangent;
    vec3 worldSpaceNormal = TransformNormalToWorldSpace(param, param_1, param_2);
    gbuffer0 = vec4(fragmentPosition, 1.0);
    gbuffer1 = vec4(worldSpaceNormal, 1.0);
    gbuffer2 = albedo;
}
Advertisement

Did you actually check if the driver support binary shader blobs? In my experience with OpenGL, I would not assume anything other can core behavior and even then you will encounter differences amongst the different IHV( your AMD, Nvidia, Intel etc.)

@cgrant Good point

I recommend OpenGL extensions viewer by realtech VR to see what's what.

http://www.realtech-vr.com/home/glview

๐Ÿ™‚๐Ÿ™‚๐Ÿ™‚๐Ÿ™‚๐Ÿ™‚<โ†The tone posse, ready for action.

@cgrant That's a good point, but the binary shaders were working before I added a third shader output! And I was testing multiple 5+ shader outputs per fragment shader on my previous engine.

@fleabay Thank you for your suggestion, this is the only unsupported content, up to 4.6 is completely supported, and I don't think any of these extensions are very related?

This topic is closed to new replies.

Advertisement