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
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?
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
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:
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.
Hi,
Thanks for the tips.
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.
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
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.
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.
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
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:
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 3x3 pixels from the original textures:
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.
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.
Thanks for the detailed answer. That helped a lot.