Jump to content
  • Advertisement
Sign in to follow this  
Armagedon

glLinkProgram crash on Intel

This topic is 1166 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello,

 

recently i stumbled on error with GLSL shader crashing on intel gpu(Bay Trail Graphics) in method glLinkProgram(ProgramID). Tested on Windows 10.

Code compiles and works fine on two AMD gpu..

 

It's uber shader that computes lightning and texturing of mesh. It works fine if i specify only lights without shadows, if i add any light that use sampler2D with shadowmap, it crashes without any error on line glLinkProgram() indicating driver bug.

 

Code of directional shadow light looks like:

struct LightDirectional
{
    vec3 Color;
    vec3 Direction;
    sampler2D ShadowTexture;
    vec2 ShadowMapSize;
};
 
#if NUM_DIRECTIONAL_SHADOW > 0
in vec4 DirectionalShadowCoord[NUM_DIRECTIONAL_SHADOW];    //On Vertex Shader side, there is code that computes and specify this as 'out'
uniform LightDirectional DirectionalShadow[NUM_DIRECTIONAL_SHADOW];

vec3 CalculateDirectionalShadow(int id, vec3 Normal, vec3 DiffuseColor, vec3 CameraVector, vec3 WorldPos)
{
    float nDotL = dot(Normal, -DirectionalShadow[id].Direction);
    
    if(nDotL > 0.0)
    {
        float Shadow = CalcShadowTermSoftPCF(DirectionalShadow[id].ShadowTexture, DirectionalShadowCoord[id].xyz, 5, DirectionalShadow[id].ShadowMapSize);

        return CalculateLight(Normal, CameraVector, WorldPos, -DirectionalShadow[id].Direction, DirectionalShadow[id].Color, DiffuseColor, nDotL) * Shadow;
    }
    
    return vec3(0.0, 0.0, 0.0);
}
#endif
 
//This method is called from void main() of mesh shader
vec3 lighting(vec3 Normal, vec4 DiffuseTextureColor, vec3 CameraVector, vec3 WorldPos)
{    
   vec3 DiffuseAmount = vec3(0.01, 0.01, 0.01);
   //...Other kinds of lights

#if NUM_DIRECTIONAL_SHADOW > 0
    for(int i = 0; i < NUM_DIRECTIONAL_SHADOW; i++)
    {
        DiffuseAmount += CalculateDirectionalShadow(i, Normal, DiffuseTextureColor.rgb, CameraVector, WorldPos);
    }
#endif
   //... Other kinds of lights

    return DiffuseAmount;
}
 

Is there any GLSL rule that forbids that kind of sampling texture in loop?

If NUM_DIRECTIONAL_SHADOW is compile time define shouldn't it be unrolled by compiler? (That's sad there is no [unroll] like in hlsl)

Is there any workaround to that issue?

 

Best Regards

Edited by Armus

Share this post


Link to post
Share on other sites
Advertisement

Can you post your whole shader? There's a lot missing from your abbreviated version which could potentially be causing issues

Share this post


Link to post
Share on other sites

Problem is that, this shader is quite big, and consist of several files, with many #Ifdefs, but here is link to it: https://www.dropbox.com/sh/9vafm0neagtnavs/AADI3BY8XWV9om-PK3j6p6oma?dl=0.

 

The snipper that i posted in first post is part of shader that is being compiled with deadcode removed by #define NUM_DIRECTIONAL_SHADOW 1, as any other lighting calculations are removed from shader code due to the fact that other defines are defined as:
#define NUM_DIRECTIONAL 0

#define NUM_POINT 0

etc.

 

So i suppose that the problematic code is this snipper that i posted
 

Share this post


Link to post
Share on other sites

in vec4 DirectionalShadowCoord[NUM_DIRECTIONAL_SHADOW];

 
Linking is all about 'in' and 'out' (or 'varying' in the case of older versions of GL). This is the only line that points to that. So my guess is that defines aren't matched between vertex/pixel shaders (different values for NUM_DIRECTIONAL_SHADOW), causing this variable to be defined in one, but not the other, and the driver probably crashes in error handling code. Edited by snake5

Share this post


Link to post
Share on other sites

But how is it possible that it works correctly on two amd gpus(hd 7770, windows 10; hd 6470,. windows 7)? And both produces correct images?

If there were any mismatch between vertex and pixel shader there would be an error on amd gpus or at least they would produce incorrect image.

Share this post


Link to post
Share on other sites

It's not unlikely that it's a driver bug. I've encountered a similar issue on Intel DX11 driver where a geometry-shader crashed the display-driver even, and once a particular beta version NVidia driver that gave incorrect results, so it happens.

 

If you want to be sure, save the pre-processed shader without any #ifdefs, and create a minimal app that draws one triangle with it.

 

I reported the issue I had with the geometry-shader to some Intel forum and they asked for crash-logs. (In the case I encountered they never fixed it though, at least for the particular platform I used, as no new driver update ever appeared, but if it's a new one that they still update they might :))

Share this post


Link to post
Share on other sites

I don't think you can put samplers into structs in GLSL. 

 

Debug or release build? To me it looks like:

- Shader compilation fails

- Your code tries to use the non-existant shader and crashes

- You get the wrong line number because there's not enough debug information

Share this post


Link to post
Share on other sites

Drivers for OpenGL use to be always a little back by every vendor, so coding "goodies" are not always supported corectly. One way how to fight it is write low level code.

 

This code:

 if(nDotL > 0.0)
    {
        float Shadow = CalcShadowTermSoftPCF(DirectionalShadow[id].ShadowTexture, DirectionalShadowCoord[id].xyz, 5, DirectionalShadow[id].ShadowMapSize);

        return CalculateLight(Normal, CameraVector, WorldPos, -DirectionalShadow[id].Direction, DirectionalShadow[id].Color, DiffuseColor, nDotL) * Shadow;
    }
    
    return vec3(0.0, 0.0, 0.0);

makes a conditional return on a per pixel volatile condition (nDotL>0). It will have to run the same condition for the pixel batch, su putting very retun to condition makes it hacked. Try to replace it with this (What better compiler and better driver does perhaps already):

 vec3 res = vec3(0.0, 0.0, 0.0);
if(nDotL > 0.0)
    {
        float Shadow = CalcShadowTermSoftPCF(DirectionalShadow[id].ShadowTexture, DirectionalShadowCoord[id].xyz, 5, DirectionalShadow[id].ShadowMapSize);

        res = CalculateLight(Normal, CameraVector, WorldPos, -DirectionalShadow[id].Direction, DirectionalShadow[id].Color, DiffuseColor, nDotL) * Shadow;
    }
    
    return res ;

If you want to depend on drivers solidity in a less extent, write as straight shaders as it gets.

Share this post


Link to post
Share on other sites

I don't think you can put samplers into structs in GLSL. 

 

Debug or release build? To me it looks like:

- Shader compilation fails

- Your code tries to use the non-existant shader and crashes

- You get the wrong line number because there's not enough debug information

 

Removing sampler2D from struct and putting it as external uniform was the way to remove crash from intel hardware! Thanks!

I Wonder if removing indexing on functions variable would improve performance(based on docs, it somehow would!), thanks again! smile.png

 

Drivers for OpenGL use to be always a little back by every vendor, so coding "goodies" are not always supported corectly. One way how to fight it is write low level code.

 

This code:

 if(nDotL > 0.0)
    {
        float Shadow = CalcShadowTermSoftPCF(DirectionalShadow[id].ShadowTexture, DirectionalShadowCoord[id].xyz, 5, DirectionalShadow[id].ShadowMapSize);

        return CalculateLight(Normal, CameraVector, WorldPos, -DirectionalShadow[id].Direction, DirectionalShadow[id].Color, DiffuseColor, nDotL) * Shadow;
    }
    
    return vec3(0.0, 0.0, 0.0);

makes a conditional return on a per pixel volatile condition (nDotL>0). It will have to run the same condition for the pixel batch, su putting very retun to condition makes it hacked. Try to replace it with this (What better compiler and better driver does perhaps already):

 vec3 res = vec3(0.0, 0.0, 0.0);
if(nDotL > 0.0)
    {
        float Shadow = CalcShadowTermSoftPCF(DirectionalShadow[id].ShadowTexture, DirectionalShadowCoord[id].xyz, 5, DirectionalShadow[id].ShadowMapSize);

        res = CalculateLight(Normal, CameraVector, WorldPos, -DirectionalShadow[id].Direction, DirectionalShadow[id].Color, DiffuseColor, nDotL) * Shadow;
    }
    
    return res ;

If you want to depend on drivers solidity in a less extent, write as straight shaders as it gets.

 I think this is way to somehow improve performance on low end hardware, thanks! smile.png

Edited by Armus

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!