greaterThan/texture2D restriction

This topic contains 8 replies, has 2 voices, and was last updated by  hnyk 8 years, 3 months ago.

Viewing 9 posts - 1 through 9 (of 9 total)
  • Author
    Posts
  • #29889

    hnyk
    Member

    Hi

    Is there some kind of restriction on how many times one can use greaterThan function in row. I have used greaterThan function, casted the output to float and then multiplyed outputs like this:

    vec4(greaterThan(vector1, vector2)) * vec4(greaterThan(vector1, vector3)) * vec4(grea….

    When I do this 19 times in row it works but when I put one more the compiler just says: compile failed. It doesn’t even give any description what has failed. It just fails.

    Any idea what is going on?

    -hnyk


    Update:

    The vectors I use in greaterThan are from texture look-ups so the cause of the failure might be texture2D function.

    hnyk2009-08-11 07:10:11

    #33303

    Xmas
    Member

    There should be no such restriction, and it’s unlikely you’re running into shader length limits. Could you post the shader in question or send it to devtech@imgtec.com? Which compiler are you using?

    #33304

    hnyk
    Member

    Thanks for the answer. I’m using the compiler which is included in the windows sdk: PVRUniSCoEditor. Here is the shader code:

    #define SIZE 511.0
    #define plus 1.0/SIZE
    #define minus -1.0/SIZE

    uniform sampler2D  sTexture1, sTexture2, sTexture3;
    varying mediump vec2  TexCoord;

    void main()
    {

        mediump vec2 p,m;
        mediump vec4 texture11, texture12, texture13, texture14, texture15, texture16, texture17, texture18, texture19;
        mediump vec4 texture21, texture22, texture23, texture24, texture25, texture26, texture27, texture28, texture29;
        mediump vec4 texture31, texture32, texture33, texture34, texture35, texture36, texture37, texture38, texture39;
        
        p=TexCoord + plus;
        m=TexCoord + minus;
       
        texture11 = texture2D(sTexture1, vec2(m.x, p.y));
        texture12 = texture2D(sTexture1, vec2(TexCoord.x, p.y));
        texture13 = texture2D(sTexture1, p);
        texture14 = texture2D(sTexture1, vec2(m.x, TexCoord.y));
        texture15 = texture2D(sTexture1, TexCoord);
        texture16 = texture2D(sTexture1, vec2(p.x, TexCoord.y));
        texture17 = texture2D(sTexture1, m);
        texture18 = texture2D(sTexture1, vec2(TexCoord.x, m.y));
        texture19 = texture2D(sTexture1, vec2(p.x, m.y));
           
        texture21 = texture2D(sTexture2, vec2(m.x, p.y));
        texture22 = texture2D(sTexture2, vec2(TexCoord.x, p.y));
        texture23 = texture2D(sTexture2, p);
        texture24 = texture2D(sTexture2, vec2(m.x, TexCoord.y));
        texture25 = texture2D(sTexture2, TexCoord);
        texture26 = texture2D(sTexture2, vec2(p.x, TexCoord.y));
        texture27 = texture2D(sTexture2, m);
        texture28 = texture2D(sTexture2, vec2(TexCoord.x, m.y));
        texture29 = texture2D(sTexture2, vec2(p.x, m.y));
       
        texture31 = texture2D(sTexture3, vec2(m.x, p.y));
        texture32 = texture2D(sTexture3, vec2(TexCoord.x, p.y));
        texture33 = texture2D(sTexture3, p);
        texture34 = texture2D(sTexture3, vec2(m.x, TexCoord.y));
        texture35 = texture2D(sTexture3, TexCoord);
        texture36 = texture2D(sTexture3, vec2(p.x, TexCoord.y));
        texture37 = texture2D(sTexture3, m);
        texture38 = texture2D(sTexture3, vec2(TexCoord.x, m.y));
        texture39 = texture2D(sTexture3, vec2(p.x, m.y));
                      
        gl_FragColor = vec4(greaterThan(texture25, texture11)) * vec4(greaterThan(texture25, texture12)) * vec4(greaterThan(texture25, texture13)) *
                       vec4(greaterThan(texture25, texture14)) * vec4(greaterThan(texture25, texture15)) * vec4(greaterThan(texture25, texture16)) *
                       vec4(greaterThan(texture25, texture17)) * vec4(greaterThan(texture25, texture18)) * vec4(greaterThan(texture25, texture19)) *
                       vec4(greaterThan(texture25, texture31)) * vec4(greaterThan(texture25, texture32)) * vec4(greaterThan(texture25, texture33)) *
                       vec4(greaterThan(texture25, texture34)) * vec4(greaterThan(texture25, texture35)) * vec4(greaterThan(texture25, texture36)) *
                       vec4(greaterThan(texture25, texture37)) * vec4(greaterThan(texture25, texture38)) * vec4(greaterThan(texture25, texture39)) *
                       vec4(greaterThan(texture25, texture21)) * vec4(greaterThan(texture25, texture22)) * vec4(greaterThan(texture25, texture23)) *
                       vec4(greaterThan(texture25, texture24)) * vec4(greaterThan(texture25, texture26)) * vec4(greaterThan(texture25, texture27)) *
                       vec4(greaterThan(texture25, texture28)) * vec4(greaterThan(texture25, texture29));

    -hnyk
    hnyk2009-08-12 12:05:44

    #33305

    Xmas
    Member

    Hi,

    We’ll investigate the problem, which seems to be a bug in the compiler.

    In the meantime, could you describe what you want to achieve? It appears that you are trying to determine whether a specific texture sample is the maximum value in a 3x3x3 environment.

    There are several ways you could improve this shader:

    – if you are not using float textures you can use lowp precision for the texture samples

    – you could calculate the texture coordinates for each sample in the vertex shader and pass them as varyings, this reduces the fragment shader load

    – instead of comparing each of the surrounding samples with the centre sample using greaterThan, use max to calculate the maximum of the surrounding samples:

    Code:
    lowp vec4 maxvalue = texture2D(<sample 1>);

    maxvalue = max(maxvalue, texture2D(<sample 2>);

    maxvalue = max(maxvalue, texture2D(<sample 3>);

    etc.

    – the operation is separable. Depending on how large your dataset is, you might want to split it into two or three passes. That way you can reduce the number of texture reads required from 27 to 10.

    #33306

    hnyk
    Member

    Hi,

    Thanks for the tips.

    Xmas wrote:
    In the meantime, could you describe what you want to achieve? It
    appears that you are trying to determine whether a specific texture
    sample is the maximum value in a 3x3x3 environment.

    This is correct. It is part of SIFT (Scale Invariant Feature Transform) algorithm. Addition to this I have to also determine if this sample is the minimum value in a 3x3x3 environment among few other things.

    Xmas wrote:
    – the operation is separable. Depending on how large your dataset is,
    you might want to split it into two or three passes. That way you can
    reduce the number of texture reads required from 27 to 10.

    This method looks good, but I can’t figure out how you can reduce it to 10. I can only manage 18. Could you please elaborate? Thanks.

    -hnyk

    #33307

    Xmas
    Member

    In a first pass, you take one sample from each of the three texures and write out the maximum, rendering to another texture of the same size.

    Code:
    uniform sampler2D sTexture1, sTexture2, sTexture3;

    varying mediump vec2 TexCoord;

    void main()

    {

        lowp vec4 maxValue = texture2D(sTexture1, TexCoord);

        maxValue = max(maxValue, texture2D(sTexture2, TexCoord));

        gl_FragColor = max(maxValue, texture2D(sTexture3, TexCoord));

    }

    You can then either get the final result in a second pass, taking nine samples from the texture written in the first pass, calculating the maximum, and comparing it to the value sampled from sTexture2, giving a total of 3 + 9 + 1 = 13 texture reads.

    Or you can do another pass calculating the maximum of columns (or rows) of 3 pixels from the texture rendered in the first pass. This will give you 3 + 3 + 3 + 1 = 10 texture reads.

    Note that this is assuming greaterThanOrEqual is ok. If you need greaterThan, it gets a bit trickier, but is still possible.

    #33308

    hnyk
    Member

    Thanks, but it has to be greaterThan and I still can’t see how you can reduce number of texture reads below 18. :/


    You said that it could be profitable to calculate texture coordinates in vertex shader and then pass them to fragment shader. Can you tell me how many varyings the SGX530 supports? I have to process Gaussian convolutions with kernel widths of 25 or even more.
    hnyk2009-08-20 09:24:23

    #33309

    Xmas
    Member

    You create two additional textures, let’s call them Texture4 and Texture5, of the same format and size as your source textures.

    In the first pass, you bind Texture4 as the color attachment of an FBO and render to it with this fragment shader, which gives you the maximum across the three textures at each position:

    Code:
    uniform sampler2D sTexture1, sTexture2, sTexture3;

    varying mediump vec2 TexCoord;

    void main()

    {

        lowp vec4 maxValue = texture2D(sTexture1, TexCoord);

        maxValue = max(maxValue, texture2D(sTexture2, TexCoord));

        gl_FragColor = max(maxValue, texture2D(sTexture3, TexCoord));

    }

    In the second pass you attach Texture5 as your FBO’s color attachment and use Texture4 as the source texture and calculate the maximum of each pixel and its two horizontal neighbours, thus giving you the maximum of a square of 3×3 pixels from the original textures:

    Code:
    uniform sampler2D sTexture4;

    varying mediump vec2 TexCoord[3]; // left, centre, right

    void main()

    {

        lowp vec4 maxValue = texture2D(sTexture4, TexCoord[0]);

        maxValue = max(maxValue, texture2D(sTexture4, TexCoord[1]));

        gl_FragColor = max(maxValue, texture2D(sTexture4, TexCoord[2]));

    }

    In the third pass you use the three original source textures plus Texture4 and Texture5 to get the maximum of the 26 surrounding pixels, and compare them to the centre pixel.

    Code:
    uniform sampler2D sTexture1, sTexture2, sTexture3, sTexture4, sTexture5;

    varying mediump vec2 TexCoord[5]; // top, bottom, centre, left, right

    void main()

    {

        lowp vec4 maxValue = texture2D(sTexture5, TexCoord[0]);

        maxValue = max(maxValue, texture2D(sTexture5, TexCoord[1]));

        maxValue = max(maxValue, texture2D(sTexture4, TexCoord[3]));

        maxValue = max(maxValue, texture2D(sTexture4, TexCoord[4]));

        maxValue = max(maxValue, texture2D(sTexture1, TexCoord[2]));

        maxValue = max(maxValue, texture2D(sTexture3, TexCoord[2]));

        gl_FragColor = greaterThan(texture2D(sTexture2, TexCoord[2]), maxValue);

    }

    The one pixel offset to some of the texture coordinates required in passes 2 and 3 should be applied in the vertex shader.

    #33310

    hnyk
    Member

    Thanks for the detailed answer. That helped a lot. 🙂

Viewing 9 posts - 1 through 9 (of 9 total)
You must be logged in to reply to this topic.