Imagination PowerVR SDK Blog

Issues with PowerVR SGX 540 fragment shaders


#1

Hello,

I'm an Android developer, our App applies real-time effects to the camera preview, using some fairly simple GLSL shaders.

We are getting some issues with devices that use the PowerVR SGX 540 (Galaxy S and Droid 3 among others).

The errors don't affect all variants of the devices equally, our Galaxy S works fine, but the ones from the American carriers don't: some effects don't show up, we have some error reporting features in the App, and the typical error we get is a GL_INVALID_OPERATION after either glDrawArrays or glGetUniformLocation (and the shader doesn't work)

We've tried all sorts of things with no luck: packing uniforms into vec4s, removing uniforms altogether, rearrange client code, etc...

My questions are:
- Do all devices use the same drivers? Different variants of the same phone seem to behave differently.

- Are there any known bugs with these devices? should I be avoiding any particular features?

As an example of our shaders, this is one that creates a cartoon effect:

precision mediump float;   

varying vec4 v_yTexCoord;
varying vec4 v_effectTexCoord;

uniform sampler2D effectTexture;
uniform sampler2D effectTexture2;
uniform sampler2D yTexture;                                                   
uniform sampler2D uvTexture;                                                                                                                           

uniform vec4 pvalues;
uniform vec4 textureSize;

float yDecode(vec2 texCoord)
{
    return 1.164 * ( texture2D(yTexture, texCoord).r - 0.0627 );                       
}

vec4 yuvDecode(vec2 texCoord)
{
    vec4 y = 1.164 * ( texture2D(yTexture, texCoord) - 0.0627 );                   
    vec4 uv = texture2D(uvTexture, texCoord) - 0.5;                                                                       
    return y + vec4( 1.596 * uv.r, - 0.813 * uv.r - 0.391 * uv.a, 2.018 * uv.a, 1.0);       
}

float edgeDetection(vec2 texCoords)
{   
    vec2 xdisp = vec2(1.0/textureSize.x, 0.0);
    vec2 ydisp = vec2(0.0, 1.0/textureSize.y);
   
    //grab surrounding px colors
    float tl = yDecode(texCoords - xdisp - ydisp);
    float l =  yDecode(texCoords - xdisp);
    float bl = yDecode(texCoords - xdisp + ydisp);
    float t =  yDecode(texCoords - xdisp);
    float b =  yDecode(texCoords + ydisp);
    float tr = yDecode(texCoords + xdisp - ydisp);
    float r =  yDecode(texCoords + xdisp);
    float br = yDecode(texCoords + xdisp + ydisp);
   
    float dX = -tl - 2.0*l - bl + tr + 2.0*r + br;
    float dY = -tl - 2.0*t - tr + bl + 2.0*b + br;
   
    //compute the magnitude
    float grad = abs(dX) + abs(dY);
   
    return clamp(grad*pvalues.z, 0.0, 1.0);       
}

void main()
{   
    float grad = edgeDetection(v_yTexCoord.xy);
    highp vec4 color = yuvDecode(v_yTexCoord.xy);
   
    vec3 yuv;
    yuv.r = 0.299 * color.r + 0.587 * color.g + 0.114 * color.b;   
    yuv.g = (color.b-yuv.r)*0.565;   
    yuv.b = (color.r-yuv.r)*0.713;   
    float grayscale = yuv.r;
   
    float chalk = floor((yuv.r * 5.0 ) + 0.5);
    float howmuch = 48.0;
   
    yuv.r = ceil((yuv.r * 256.0 / howmuch)-0.5);
    yuv.r *= howmuch;
    yuv.r /= 256.0;
   
    vec3 colorC;
    colorC.r = yuv.r + 1.403 * yuv.b;
    colorC.g = yuv.r - 0.344 * yuv.g - 0.714 * yuv.b;   
    colorC.b = yuv.r + 1.770 * yuv.g;
   
    grad = mix(grad, 0.5, grad);
    color.rgb = vec3(1.0 - grad);

    vec2 halfCoord = v_effectTexCoord.xy * 0.5;
    vec2 topLeft = vec2(0.0, 0.0);
    vec2 topRight = vec2(0.5, 0.0);
    vec2 bottomLeft = vec2(0.0, 0.5);
    vec2 bottomRight = vec2(0.5, 0.5);
   
    if ( chalk < 1.0 )
    {
        color.rgb -= vec3(1.0 - texture2D( effectTexture, halfCoord.xy + bottomRight  ).rgb);       
    }
    if ( (chalk >= 1.0  ) && (chalk < 2.0) )
    {
        color.rgb -= vec3(1.0 - texture2D( effectTexture, halfCoord.xy + bottomLeft ).rgb);       
    }
    if ( (chalk >= 2.0 ) && (chalk < 3.0) )
    {
        color.rgb -= vec3(1.0 - texture2D( effectTexture, halfCoord.xy + topRight ).rgb);       
    }
    if ( (chalk >= 3.0) )
    {
        color.rgb -= vec3(1.0 - texture2D( effectTexture, halfCoord.xy + topLeft ).rgb);       
    }
   
    color.rgb = mix(colorC  * vec3(229.0/255.0, 170.0/255.0, 110.0/255.0), color.rgb, 0.65);
   
    // Contrast 2*(Src*t + 0.25 - 0.5*t)   
    color.xyz = ((color.rgb - 0.5) * max(pvalues.x, 0.0)) + 0.5;
   
    // Brightness   
    color.xyz *= vec3(pvalues.y, pvalues.y, pvalues.y);
   
    gl_FragColor = color;   
}






madruga2011-09-09 21:19:23