glsl top weird behavior

Hi,

I need to preface saying I know very little about glsl. Still, I’ve narrowed down a behavior which any of you glsl gurus should be able to spot - and advice - very easily.

I have a glsl top with a 1x1 constant top as input.

this is the fragment shader:

[code]uniform sampler2D sInput1;
uniform vec4 res1;

void main()
{

float stepx = 1.0/res1.x;
float stepy = 1.0/res1.y;
float xc = 0;
float yc = 0;

for(xc=0.0; xc <= 1; xc+=stepx) {
 	for(yc=0.0; yc <= 1; yc+=stepy) {
 	}
}


gl_FragColor = vec4(.1,.2,.3,1);

}
[/code]

don’t worry about the utility of those empty loops (there used to be more… - this is the test case)

basically the issue is that with the above, the output 1x1 image is not .1 .2 .3, but

0, .851, 0, .8784

(keep in mind everything compiles without errors).
but if I comment the inside loop (for y) then the resulting image is correct…

My naive thinking is that the loops should have NO effect on the output image since I’m setting gl_FragColor explicitly…

In an attempt at semplification, I’ve changed the loops to go from 0 to 10 step 1 (instead of using stepx and stepy) and… the output image was correct, without the need to comment out the internal y loop…

I’m lost… how is it possible that even though I set gl_FragColor explicitly, it changes depending on what code I have above it???

Is this my computer, a bug, or…is it me?

d

(btw res1 is a uniform with the first two fields set to 640 480)
(also btw then the image comes out with the “right” values, the values have a .002 precision error).

to better illustrate what I’m seeing look at this image…
basically all I’m doing here is two loops and inside the inner loop I set red = .7;

the output rgba values are beyond my comprehension…

then, if instead of using red in the gl_FragColor assignment I use .1, the result is 0 0 0 0

by if I still use red, but comment out the for y loop, the result is as expected (.7 .2 .3 1) (with the .002 precision error in the red and blue values).

???

It might be the glsl compiler truncating your loop. try setting the step* vars directly (float stepx = 0.0015) without the use of uniforms. does that work?

it’s actually not that (but I’ve tried it anyway, same prob).

the WEIRD thing is that no matter what the loop is doing, I set:

gl_FragColor = vec4(.1,.2,.3,1.0)

at the end, and for example if I use .0015 as increment in the loop,
the resulting rgba (even though I set it as shown above) is: 1 0 0 0

it is beyond me why setting gl_FragColor to constant values as above is affected by
whether or not I have a nested loop above - or below - the statement (that doesn’t do anything except set red = .7 which is not even used later on) should affect the result.

Again and again I try different things and the only one that gives me the result I’d expect is if I comment out the for y nested loop.

I’ve been reading that there’s a maximum number of instructions that can be executed on the GPU for any given shader call, and maybe that has to do with the size of the input image or the geforce 7 card I’m on - or the simple fact that I’m executing ops 640x480 times in a single shader call?

I mean, since input1 is a 1x1 image, there’s only one call to the shader. During that call, I executed a 640x480 loop through input2 (my goal is to find the min/max coords of non zero
values in input2 and store them in the input1 pixel).

I’ve even tried to unroll the loop to no avail.

It’s must be a shader compiler bug (in the driver) that causes it to break with the loops, but its not possible to do such a big loop on such an old card anyway. Unrolling isn’t possible since the size of the code would be massive. The compiler should cut out those loops in normal behavior.

To do full image searching you need to do it iteratively, each time bringing your resolution down by 1/2.
So if your input is 640x480, take that image and output a 320x240 image with your shader doing operations on 2x2 pixel chunks. Then repeat until you are down to a 1x1. For this problem you may need to use multiple output buffers to store the coords and max colors, unless you want to pack data in a 16-bit fixed point buffer.

This is how the Analyze TOP works.

I understand the above.

I’m not sure I understand the above though - although it sounds interesting and I to need to understand it.

How do I output an (320x240) image when the input is 640x480 - and how do I iteratively go through the same image. Pointer to examples of the technique you are talking about would be extremely helpful for one like me who’s jumping into glsl with just but the lightest sprinkle of understanding.

Thanks!
dani

You just set the output resolution to ‘Half’, and you’ll have a chain of GLSL TOP (all using the same shader) until you get to one with a res of 1x1.

Say you have a 2x2 image that you want to find max red value from. You put it into a GLSL TOP with it’s res set to ‘Half’, so it’s outputting 1x1. So in the shader for that one pixel you’ll need to sample all 4 of the pixels in the input and decide on what to output.

The value for gl_TexCoord[0].st will be the texture coordinate of the center of the pixel that is currently drawing (this is true for any res). If you draw a square with a dot in the middle (for the texture coordinate you are given), and then split that square into 4 quadrants (for the 2x2 input pixel), you can see the offsets you need to apply to your texture coordinate to sample at the center of the pixels. The answer is 1/2 the width/height of a pixel from the input image.

vec2 halfPixel = uInputRes1.xy / 2.0;

vec4 upperRightPixel = texture2D(sInput1, gl_TexCoord[0].st + vec2(halfPixel.s, halfPixel.t));
vec4 lowerRightPixel = texture2D(sInput1, gl_TexCoord[0].st + vec2(halfPixel.s, -halfPixel.t));
vec4 lowerLeftPixel = texture2D(sInput1, gl_TexCoord[0].st + vec2(-halfPixel.s, -halfPixel.t));
vec4 upperLeftPixel = texture2D(sInput1, gl_TexCoord[0].st + vec2(-halfPixel.s, halfPixel.t));
// Compare pixels and output result

If you now draw a 2v2 grid (output) and overlay a 4x4 grid (input), you’ll see how this concept scales for any square resolution.

Since your resolution isn’t square, you’ll need to add an if statement that only does 2 samples (left and right) once you reach a height of 1.

If your resolutions weren’t a multiple of 2 things would get a little more complex.

thanks!

btw I’m not trying to find min max rgb values, but the boundaries of the non zero image,
that is the min max xy coordinates that so if I were to crop it I would discard the blank parts of the image.