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

Started by
2 comments, last by KarimIO 2 years, 8 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 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