Imagination PowerVR SDK Blog

Shader fails to compile on Galaxy S but runs fine everywhere else


#1

I have a simple test app where I include a shader like this:



Fragment shader:



uniform float u_fogMaxDist;

uniform float u_fogMinDist;

uniform vec4 u_fogColor;



varying vec4 v_eyePos;



float computeLinearFogFactor()

{

float factor;



// Compute linear fog equation

factor = (u_fogMaxDist - length(v_eyePos.xyz)) /

(u_fogMaxDist - u_fogMinDist );



// Clamp in the [0,1] range

factor = clamp( factor, 0.0, 1.0 );



return factor;

}



vec4 getColorWithFog(vec4 baseColor)

{

float a = baseColor.a;

float fogFactor = computeLinearFogFactor();

vec4 fogColor = fogFactor * u_fogColor;

vec4 c = baseColor * fogFactor + fogColor * (1.0 - fogFactor);

c.a = a;

return c;

}





Vertex shader:



varying vec4 v_eyePos;

uniform mat4 u_worldViewMatrix;



void applyEyePos(vec4 position)

{

v_eyePos = u_worldViewMatrix * position;

}





I include these from my main vertex and fragment shaders. It runs on many mobile devices without any problems(including iPhone 3GS with PowerVR SGX535, and various other Android devices with Adreno, PowerVR and Mali GPUs). However when I test it on a Samsung Galaxy S with a PowerVR SGX540 GPU, the shader fails in the line:



factor = clamp( factor, 0.0, 1.0 );





It runs fine when I comment this line out.



Is this a bug in the OpenGL drivers? If yes, is there a workaround?



Thanks in advance!


#2

Hello



did you try to replace the clamp function to see how it behave ?

in pseudo code

float fastcp( float a, float b, float c ) {<br />
return a >= 0 ? b : c;<br />
}<br />
<br />
float customclamp ( float a, float min, float max )<br />
{<br />
a = fastcp( a - min , a, min );<br />
return fastcp( a - max, max, a );<br />
}
```<br />
<br />
kind regards<br />
david

#3

Yes, it works fine with the custom clamp function. Would it be slower to use a branching function like this instead of the builtin one? I suppose yes. But for now I’m stuck with this. :slight_smile:


#4

I also tried casting the return value of clamp explicitly to float. That didn’t work either. And the only error message returned from the driver is “Compile failed.”


#5

wow that is wierd ,

did you see the wonderfull sample provided in the SDK called FOG with four modes provided:

- No Fogging

  • Fog: Linear
  • Fog: Exponential
  • Fog: Exponential Squared



    sure that doesnt solve your problem but give a solution that work on all POWERVR





    i am sure Joe or Tobias will solve that.



    Kind regards

    david

#6

from the sdk



uniform sampler2D sTexture;



uniform lowp vec3 FogColor;



varying mediump vec2 TexCoord;

varying lowp vec3 DiffuseLight;

varying lowp vec3 FogIntensity;



void main()

{

// Get color from the texture and modulate with diffuse lighting

lowp vec3 texColor = texture2D(sTexture, TexCoord).rgb;

lowp vec3 color = texColor * DiffuseLight;



// interpolate the fog color with the texture-diffuse color using the

// fog intensity calculated in the vertex shader

color = mix(FogColor, color, FogIntensity);

gl_FragColor = vec4(color, 1.0);

}




and



attribute highp vec4 inVertex;

attribute highp vec3 inNormal;

attribute highp vec2 inTexCoord;



uniform highp mat4 MVPMatrix;

uniform highp mat4 ModelViewMatrix;

uniform highp vec3 LightDirection;

// fog uniforms

uniform lowp int iFogMode;

uniform highp float FogDensity;

uniform highp float FogEnd;

uniform highp float FogRcpEndStartDiff;



varying mediump vec2 TexCoord;

varying lowp vec3 DiffuseLight;

varying lowp vec3 FogIntensity;



void main()

{

// transform position to view space as we need the distance to the eye for fog

highp vec3 viewPos = vec3(ModelViewMatrix * inVertex);

highp float eyeDist = length(viewPos);



// transform vertex position

gl_Position = MVPMatrix * inVertex;



// texcoords pass through

TexCoord = inTexCoord;



// calculate lighting

// We use a directional light with direction given in model space

lowp float DiffuseIntensity = dot(inNormal, normalize(LightDirection));



// clamp negative values and add some ambient light

DiffuseLight = vec3(max(DiffuseIntensity, 0.0) * 0.5 + 0.5);





// select fog function. 1 is linear, 2 is exponential, 3 is exponential squared, 0 is no fog.

highp float fogIntensity = 1.0;

if(iFogMode == 1)

{

fogIntensity = (FogEnd - eyeDist) * FogRcpEndStartDiff;

}

else if(iFogMode >= 2)

{

highp float scaledDist = eyeDist * FogDensity;

if (iFogMode == 3)

{

scaledDist *= scaledDist;

}

fogIntensity = exp2(-scaledDist);



}



// clamp the intensity within a valid range

FogIntensity = vec3(clamp(fogIntensity, 0.0, 1.0));

}




interesting


#7

According to the GLSL ES docs, clamp is calculated as min(max(x, minVal), maxVal). Replacing the clamp line with



factor = min(max(factor, 0.0), 1.0);



still fails. I tried explicit casts like float( min( float(max(factor, 0.0)), 1.0) ) but it didn’t work either. (And still works fine everywhere else I test.)


#8

are you absolutely sure about the factor value (no division by zero )?

maybe each driver treat error differently…


#9

The shader fails during compilation, not when running it, so I doubt it’s a division by zero error.



And the only division I have there is the (u_fogMaxDist - length(v_eyePos.xyz)) / (u_fogMaxDist - u_fogMinDist ), I make sure u_fogMaxDist != u_fogMinDist in my application code.


#10

ok.

i try to compile it and i have no error by my side.i use glslcompiler_sgx543 .Reusing something that work well might be interesting as well the Fog sample is interesting.



cheers

david