Is it normally safe to read DXT1 alpha channel from GLSL?

I recently switched to the latest (dev) mesa drivers, they are great, they perform much better than both amdgpu and decrepit crimson on my GPU (r9 270x) but they have a much stricter standard compliance that forces you to do things in the right way and this is why i’m asking this question.

I’m having an issue with a shader that simply read the texture color and do alpha discard, if i pass a dxt1 texture (so w/o alpha channel) when the alpha channel is read suddently all over the materials appear glitchy black clusters of pixels that blink when you move the camera, i suppose this is a weird memory corruption, so i’m asking if it’s normally safe to access the alpha channel of a texture that has no alpha and expect to get 1 or if it’s just a common non-standard behavior of closed source drivers.

mhhh to me it boils down to what does the spec say in the case of a texture fetch on a sampler that has less than 4 channels…
I searched a bit…couldn’t find a clear answer.
https://www.khronos.org/opengl/wiki/Sampler_(GLSL)#Basic_texture_access
Here it’s clearly stated that texture() (or before texture2D) returns a vec4… but it doesn’t say what are the default values for non existant channels…
Maybe you should have a define that tells you if your sampler has an alpha channel and set it to true when you attach the texture…

Thanks for the reply.

I’ve investigated the issue further and, while from my initial tests i thought it was related to RGB textures only, i noticed the same behavior also on RGBA (but still only on alpha channel…). So, my initial assumption was wrong.

This is the glitched version


#ifdef DIFFUSEMAPA
  uniform sampler2D m_DiffuseMapA;
#endif

#ifdef DIFFUSEMAPB
  uniform sampler2D m_DiffuseMapB;
#endif

flat in int type;

void main(){
    float alpha=0.; 
    if(type==0){
        #ifdef DIFFUSEMAPA
            vec4 diffuseColor=texture(m_DiffuseMapA,texCoord);
            alpha = diffuseColor.a;
         #endif        
    }else{
        #ifdef DIFFUSEMAPB
            vec4 diffuseColor=texture(m_DiffuseMapB,texCoord);
            alpha = diffuseColor.a;
         #endif        
    }
    if(alpha<.9)discard;
    outFragColor=vec4(0,0,0,1);
}

I’ve found that if i replace texture() with this

vec4 ___texture(in sampler2D tx,in vec2 coord){ 
    vec4 c=texture(tx,coord);
    c.a=max(c.a,c.a); // Works also with some other functions, like min and abs, doesn't work with clamp...
    return c;
}

the glitches disappear… But this is not a good solution, so i tried to mess around with the code and i’ve found out that this version doesn’t cause the glitch


#ifdef DIFFUSEMAPA
  uniform sampler2D m_DiffuseMapA;
#endif

#ifdef DIFFUSEMAPB
  uniform sampler2D m_DiffuseMapB;
#endif

flat in int type;

void main(){
    float alpha=0.; 
    if(type==0){
        #ifdef DIFFUSEMAPA
            vec4 diffuseColor=texture(m_DiffuseMapA,texCoord);
            alpha = diffuseColor.a;
            if(alpha<.9)discard; // <<<<<<<<<<<<<<<<<<<<
         #endif        
    }else{
        #ifdef DIFFUSEMAPB
            vec4 diffuseColor=texture(m_DiffuseMapB,texCoord);
            alpha = diffuseColor.a;
            if(alpha<.9)discard; // <<<<<<<<<<<<<<<<<<<<<
         #endif        
    }
 //   if(alpha<.9)discard;
    outFragColor=vec4(0,0,0,1);
}

I’m clueless on why. If leave the code as it is but i comment out the two discard lines and i leave only the bottom one, the glitches come back… probably it has something to do with the optimizations made by the mesa compiler…

That looks like a driver bug to me.
There’s a great tool on Linux called apitrace which you can use to run an application and then record the OpenGL calls from it. You can then send this recording to other people and when they replay this recording they could reproduce the bug without the application. I am sure the Mesa guys would love to see it…

I was searching for something else in the opengl doc when i stumbled upon the real reason behind this ‘issue’ Sampler (GLSL) - OpenGL Wiki

Hmm, this is quite interesting:

If the texture associated with someOtherSampler uses mipmapping or anisotropic filtering of any kind, then any texture function that requires implicit derivatives will retrieve undefined results. The third texture access happens in uniform flow control again and will produce definite results.

Since mipmapping requires the (implicit) derivative, this causes undefined behavior. Of course, once mipmapping is disabled on the sampler, it will begin working again.

You learn something new every day, I guess.

1 Like