Gradient calculation inside a conditional block

Hello,

I am trying to perform 2D convolution on SGX530 with the following code:

#ifdef GL_FRAGMENT_PRECISION_HIGH
    precision highp float;
#else
    precision mediump float;
#endif

uniform sampler2D texture0;
uniform sampler2D texture1;
uniform float w; // inverse dimension of the texture - necessary to not overflow floats

varying vec2 vTexCoord;

// same as above
vec4 pack(float value);
float unpack(vec4 texel);

void main(void)
{
    const int kSpan = 3;
    const int spread = kSpan / 2;
    vec4 samp[kSpan * kSpan];

    vec4 value;

    // load the part of the image which will be used for convolution from texture memory
    for (int i = -spread; i <= spread; ++i)
    {
        for (int j = -spread; j <= spread; ++j)
        {
            if ((vTexCoord.x + float(j) * w) > 1.0 ||
                (vTexCoord.x + float(j) * w) < 0.0 ||
                (vTexCoord.y + float(i) * w) > 1.0 ||
                (vTexCoord.y + float(i) * w) < 0.0)
            {
                value = vec4(0.0);
            }
            else
            {
                value = texture2D(texture0, vTexCoord + vec2(float(j) * w, float(i) * w));
            }
            samp[(i + spread) * kSpan + (j + spread)] = value;
        }
    }

    float result = 0.0;

    float step = 1.0 / float (1 + kSpan); // how much step through the kernel texture

    // do the convolution (dot product)
    for (int i = 0; i < kSpan; ++i)
    {
        for (int j = 0; j < kSpan; ++j)
        {
            result += unpack(samp[i * kSpan + j] * 255.0) * unpack(texture2D(texture1, vec2(step * float(j + 1), step * float(i + 1))) * 255.0);
        }
    }

    // do the last transformation to float
    gl_FragColor = pack(result);
}

And the result is a warning from the compiler:

WARNING: 0:82: Calls to any function that may require a gradient calculation inside a conditional block may return undefined results
WARNING: 0:100: Calls to any function that may require a gradient calculation inside a conditional block may return undefined results
WARNING: 2 compilation warnings.

I searched for some answers but just found out this which mentions that I should replace the branches with a mix or step which I did, like this:


    // load the part of the image which will be used for convolution from texture memory
    for (int i = -spread; i <= spread; ++i)
    {
        for (int j = -spread; j <= spread; ++j)
        {
            float outside = float((vTexCoord.x + float(j) * w) > 1.0 ||
                           (vTexCoord.x + float(j) * w) < 0.0 ||
                           (vTexCoord.y + float(i) * w) > 1.0 ||
                           (vTexCoord.y + float(i) * w) < 0.0);
            value = mix(texture2D(texture0, vTexCoord + vec2(float(j) * w, float(i) * w)), vec4(0), outside);
            samp[(i + spread) * kSpan + (j + spread)] = value;
        }
    }

However it still complains about the branch. How would I circumvent the error and how can I see the generated assembly?

Hi jduchniewicz,

Many thanks for your thoughtful feedback.

One engineer from the Ecosystem Team came across a similar issue not long ago, he is looking into it (thanks for all the data provided). He’ll come back to you once he has verified what is generating those warning messages.

Best regards,
Alejandro

Hi jduchniewicz,

We managed to reproduce the issue in PVRShaderEditor. We’re looking into this and will get back to you soon.

In the meantime, would you be able to provide us the driver version?
You can query that information using the following command:

cat /sys/kernel/debug/pvr/version

Best regards,
Dihara

Hi Dihara,

I do not seem to have this file. However, the dmesg logs are as follows:
dmesg | grep -i pvr

[   75.860456] pvrsrvkm: loading out-of-tree module taints kernel.
[   76.107208] [drm] Initialized pvr 1.14.3699939 20110701 for 56000000.sgx on minor 2
[   76.378760] PVR_K: UM DDK-(3699939) and KM DDK-(3699939) match. [ OK ]

Hi jduchniewicz,

I heard back from the compiler team and they suggested to manually unroll the for-loops to supress the warning.

With GLSL ES 3.0 you could potentially use the textureLod() function to avoid derivatives being computed, however this isn’t available in the GLSL version you are using, so unrolling the for-loops is the only viable solution here.

Best regards,
Dihara

2 Likes

Hi Dihara,

I was able to unroll the loops and make the convolution calculation work! What is interesting, I had to store the sampled texels to variables, otherwise they were replaced by 0.0 in my calculations. It is probably some quirk of how the SGX GPU’s execute the shader code.

Jakub

Hi Jakub,

Glad to hear it worked! And yes, that might be an issue with the older compiler.

Best regards,
Dihara

1 Like