PDA

View Full Version : Could some ATI user try this?



Jan
09-25-2003, 07:01 AM
Hi

I need someone with an ATI card who has an app which does multiple passes. All you have to do, is to add 5 lines and test, if your app still does the same thing as it did before. Shouldnīt be much work.

After your app has done at least one of the multiple passes you need to put this in between:

glMatrixMode (GL_PROJECTION);
glPushMatrix ();
glLoadIdentity ();
glPopMatrix ();
glMatrixMode (GL_MODELVIEW);

After that at least one other pass has to be done.

If you now run your app, it should still look as always, because in fact nothing has been done. The projection-matrix has been changed and restored, and nothing should be affected.


On my Geforce 4 this is not the case! After i put this code in between, i got z-fighting in the subsequent passes and there is nothing i can do about this. I wrote to nVidia, but they certainly donīt think this is of any importance.

So, if this works without problems on ATI cards, my next gfx card wonīt be a Geforce.

Thanks in advance,
Jan.

Zengar
09-25-2003, 07:34 AM
Originally posted by Jan2000:
my next gfx card wonīt be a Geforce.


NV40 http://www.opengl.org/discussion_boards/ubb/smile.gif?

Gorg
09-25-2003, 08:16 AM
Maybe it is what you do in the passes that's causing the z-fighting?

Jan
09-25-2003, 08:37 AM
No, i tested everything. In fact, if i remove the glLoadIdentity call, then i donīt get z-fighting.
In my engine everything works pretty fine, but when i add these 5 lines, it does not work anymore. Thatīs doubtlessly a driver or a hardware issue. Therefore iīd like to know, if it makes problems on ATI cards, too. If yes, it might be something, which is not so easy to solve (i am certain the projection matrix is stored in a different precision on the GPU, so maybe this precision gets lost, when the driver tries to store the value).

NV40? Maybe. But nVidia will need a lot of good arguments to convince me for that. At the moment i am really curious to test an ATI card, the hardware seems to be much better.

DopeFish
09-25-2003, 08:38 AM
I get no difference in the test I did... though my test situation may not be beneficial as I just threw the code in the render loop of my lighting code (ppl with volumetric shadows), which has no depth writes enabled and uses GL_EQUAL comparisons

Korval
09-25-2003, 09:45 AM
Actually, you should try this on your machine, Jan.

Before you enter that 5-line code segment, call "glGetDoublev(GL_PROJECTION_MATRIX)" and store the results off. After the segment, do the same call, but to a different location.

Print out the two matrices. If they aren't identical, then the driver is causing the problem. Send nVidia a bug about it.

BTW, question about the GL-spec. Is glPopMatrix guarenteed to restore the matrix precisely as it was before (binary-identical)? I think it should, but I don't know what the spec says about it.

Tom Nuydens
09-25-2003, 10:17 AM
I had the same problem some time ago: http://www.opengl.org/discussion_boards/ubb/Forum3/HTML/009260.html .

The spec can't convince me 100% that what you're seeing is really invalid behaviour. If possible, I would rewrite the code to draw the stuff that needs a different matrix last (that's what I did).

-- Tom

1234!
09-25-2003, 10:37 AM
Originally posted by Jan2000:



glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glPopMatrix();
glMatrixMode(GL_MODELVIEW);



Some things worth checking.

-Matrix stack overflow or some GL error (putting in some glGetError() wouldnt hurt)
-In the next pass you may assume you are still in projection matrix mode while you are not...

Yeah I know that this is obvious stuff but who knows...


Originally posted by Korval:
BTW, question about the GL-spec. Is glPopMatrix guarenteed to restore the matrix precisely as it was before (binary-identical)? I think it should, but I don't know what the spec says about it.

The spec says it uses IEEE floating point numbers, so if it wouldnt restore them binary-identical, it would violate the IEEE spec for floats'n'doubles.

Jan
09-25-2003, 11:49 AM
@1234!: I check gl errors, there are none.
I also am not a friend of push/pops, itīs the only line of code, where i use it, so stack-overflows are impossible.

@DopeFish: My app disables depth-writes and uses GL_LEQUAL, thatīs absolutely valid. But do you have a Geforce or a Radeon?

@Korval: I will definitly check that tomorrow, good idea.

Jan.

Korval
09-25-2003, 12:26 PM
The spec says it uses IEEE floating point numbers, so if it wouldnt restore them binary-identical, it would violate the IEEE spec for floats'n'doubles.

That's not the point. The question is, does the spec mandate that a push/modify/pop operation result in a matrix that is binary-identical to the original one, or is it just to "within floating-point round-off error"? In short, is a matrix stack implementation required to store each stack position, such that pops do no math, or can an implementation inverse-multiple to retrieve the old matrix on a pop (and accept the floating-point error you get)?

Well, at least this discussion has shown one thing: I should get to building my matrix stack soon, and abandon GL stacks. At least then, I can guarentee particular behavior.

jwatte
09-25-2003, 12:49 PM
You absolutely need to be doing your own matrix math. I was going to suggest you save off a copy when calling glLoadMatrix() into the projection matrix, and then just LoadMatrix() the same data again in the future, but if you build it using GL calls, that may be harder.

1234!
09-25-2003, 01:38 PM
Originally posted by Korval:
That's not the point. The question is, does the spec mandate that a push/modify/pop operation result in a matrix that is binary-identical to the original one, or is it just to "within floating-point round-off error"? In short, is a matrix stack implementation required to store each stack position, such that pops do no math, or can an implementation inverse-multiple to retrieve the old matrix on a pop (and accept the floating-point error you get)?


Huh? Inverse multiply which matrix with what? Dude, no offense but you are getting silly. It's called a STACK for a reason.

Besides from the spec:

The glPushMatrix function pushes the current matrix stack down by one, duplicating the current matrix. That is, after a glPushMatrix call, the matrix on the top of the stack is identical to the one below it. The glPopMatrix function pops the current matrix stack, replacing the current matrix with the one below it on the stack.

I guess its either a driver bug, or a mistake on Jan's side.

Korval
09-25-2003, 02:41 PM
I guess its either a driver bug, or a mistake on Jan's side.

Since Tom got the error too (in the other thread), I would suspect that it's a driver bug.

V-man
09-25-2003, 02:54 PM
Originally posted by 1234!:
Huh? Inverse multiply which matrix with what? Dude, no offense but you are getting silly. It's called a STACK for a reason.

Besides from the spec:

The glPushMatrix function pushes the current matrix stack down by one, duplicating the current matrix. That is, after a glPushMatrix call, the matrix on the top of the stack is identical to the one below it. The glPopMatrix function pops the current matrix stack, replacing the current matrix with the one below it on the stack.

I guess its either a driver bug, or a mistake on Jan's side.

Imagine that the Gf4 is storing the matrix at position 0 as a double and that when you push the stack, it copies [0] to [1] where [1] is stored as floats.
Then, when you pop, you no longer get the original matrix at [0]

That`s what needs to be tested. Use glGetDouble to make sure all is OK on [0].

1234!
09-25-2003, 03:56 PM
Originally posted by V-man:
Imagine that the Gf4 is storing the matrix at position 0 as a double and that when you push the stack, it copies [0] to [1] where [1] is stored as floats.

So you are telling me that somebody would implement a (hardware) stack where an stack entry could consists of floats or doubles? Sure thing!

While we are at it, why would an GF4/FX store matrices with double precision while it can only process float vertices?

You are also forgetting that the duplicate has to be identical as per OpenGL spec.

No dude, I am not convinced by your thoughts.


Originally posted by V-man:
Then, when you pop, you no longer get the original matrix at [0]

Why that? If I "pop" I only change the stack pointer, nothing more nothing less. Even if I have a double/float mixed stack (which would violate the OpenGL spec) it wouldnt change a thing.

Even if the stack is entirely done on the CPU with double precision, and uploaded to the GPU only with float precision it has to give you always the exact same result.

A conversion from double->float always results in the exact same value as it is defined by the IEEE.

In short: The matrix stuff is either entirely done with floats (casting doubles to floats for i.e. glRotated() calls) or done in doubles (converting floats to doubles without loss in precission for i.e. glRotatef() calls)


Originally posted by V-man:
That`s what needs to be tested. Use glGetDouble to make sure all is OK on [0].


I am sure that on current mainstream hardware/implementations its all done with floats and that a glGetDouble only performs a float->double conversion which is rather pointless.

Using your own matrix logic is just a workaround.

After reading Tom's post I 2nd Korval and declare it an driver bug.

DopeFish
09-25-2003, 07:28 PM
Jan, Radeon9800 pro
You asked for someone with a Radeon to test, so if I was using a GeForce it would have been pretty useless of me :P

Jan
09-26-2003, 12:24 AM
Ok, i checked the projection matrix with glGetDouble (...).
The two matrices are absolutely identical. But i assume, that all that is really a CPU <-> GPU issue, and that precision gets lost when the matrices are pushed/popped.

So, either nVidia has a software stack and ATI a hardware stack, or ATI has a software stack, too, but stores the matrices precise to the last bit.

My next gfx card will definitive be an ATI card, iīm fed up with nVidia.

Jan.

zeckensack
09-26-2003, 02:03 AM
There may be issues with some part of your application or the GL driver changing the FPU precision, resulting in different rounding behaviour.

You can monitor this with the following snippet (assuming MSVC).



unsigned short get_fpu_control_word()
{
unsigned short rv;
__asm {
FSTCW [rv]
}
return(rv);
}

Note that there is a seperate control word for SSE/SSE2 operations, this one will only catch x87 FPU.
You can try disabling the usage of instruction set extensions first, IIRC there's an option for this in the control panel.

Jan
09-26-2003, 02:37 AM
I have an Athlon 1.3 GHz (i think thatīs 1500+ or so).

I doubt it has SSE or SSE2 support, does it?

zeckensack
09-26-2003, 02:46 AM
Originally posted by Jan2000:
I have an Athlon 1.3 GHz (i think thatīs 1500+ or so).

I doubt it has SSE or SSE2 support, does it?No. SSE support on AMD started with the AthlonXP line (and Duron >=1GHz).
3DNow doesn't have precision controls.

Can you test the snippet? Get the fpu control world on program startup and after your matrix problem section, and compare.

Jan
09-26-2003, 03:08 AM
Both values are 639.

zeckensack
09-26-2003, 03:37 AM
Then I suppose we can ditch this theory http://www.opengl.org/discussion_boards/ubb/frown.gif

Tom Nuydens
09-26-2003, 04:26 AM
I just coded up a quick test app to do some investigation. I notice the push/modify/pop problem only happens when you do it on the projection matrix. Doing it on the modelview works fine.

I see the spec says that changing the matrix mode is not required to guarantee invariance (although it is on the "strongly suggested" list). Maybe this also applies when changing the matrix mode to something else and back again?

-- Tom

Jan
09-26-2003, 05:25 AM
"I notice the push/modify/pop problem only happens when you do it on the projection matrix."

Yeah, i noticed that too. Maybe the modelview-matrix-stack is in hardware? But if thatīs the case, then i would see no reason, why the projection-matrix-stack shouldnīt be in hardware, too.

vincoof
09-26-2003, 09:09 AM
> My next gfx card will definitive be an ATI
> card, iīm fed up with nVidia.

And what makes you think that it will work on ATi ? http://www.opengl.org/discussion_boards/ubb/smile.gif
You base your opinion on DopeFish's test ?
First, make sure that you're running a similar example. At best, give your program to DopeFish and let him test with multiple screen depth, etc.
Secondly, check the depth buffer bit depth. GeForce1-4 easily use a 16bit depth-buffer if you don't ask for a stencil buffer, so it would not be representative to compare a Z-fighting on a 16-bit nVidia depth buffer with a 24-bit (or more) ATi depth buffer http://www.opengl.org/discussion_boards/ubb/smile.gif

> Yeah, i noticed that too. Maybe the
> modelview-matrix-stack is in hardware?
> But if thatīs the case, then i would see
> no reason, why the projection-matrix-stack
> shouldnīt be in hardware, too.
Well, the projection matrix could be in software and the mvp in hardware.
Since the modelview matrix is changing much more often than the projection matrix (usually) it is more useful to set the modelview and mvp matrices in hardware than, say, the modelview and projection matrices.

Chuck0
09-26-2003, 12:26 PM
as far as i have understood this there shouldnt be any z fighting with any z-buffer-depth since he does multiple passes on the same geometry meaning, that the z-results should be exactely the same.

vincoof
09-26-2003, 12:42 PM
If you mean invariance, that's right that it should be the case when the input data sent to the GL pipeline is exactly the same.
But in this case, a single part of that input data (currenlty, the projection matrix) is not guaranteed to be left unchaged over many frames, so the invariance rule does not apply because a little part of the input data may have changed.

[This message has been edited by vincoof (edited 09-26-2003).]

Cyranose
09-26-2003, 01:08 PM
Originally posted by Jan2000:
No, i tested everything. In fact, if i remove the glLoadIdentity call, then i donīt get z-fighting.
better.

I'm not sure why loading identity would change FPU or FB precision, but I can imagine an "optimization" that kicks in when a matrix is known to be identity or at least non-perspective.

If you haven't tried this, here's a quick set of things to try:

1. replace glLoadIdentity with glMultMatrix(myMat) where the resulting matrix is
a) a perspective matrix
b) an affine matrix
c) the identity matrix

2. replace glLoadIdentity with glLoadMatrix(myIdentityMat)

3. replace the glPush/pop pair with a glGetfloatv and direct restore, but keep the glLoadIdentity.

I wouldn't be making wild-ass guesses like this except it would take a minute to test and might confirm the idea of a driver bug.



[This message has been edited by Cyranose (edited 09-26-2003).]

vincoof
09-26-2003, 01:50 PM
Hmm. I wouldn't reckon it as a driver bug, as it is perfectly valid according to the OpenGL specification.

1234!
09-26-2003, 05:04 PM
Originally posted by vincoof:
Hmm. I wouldn't reckon it as a driver bug, as it is perfectly valid according to the OpenGL specification.

And you are backing up your statement with what?

If you think about how you would do an push, pop & loadIdentity its only a memcpy() as anything else would be way slower and makes no mathematical or logical sense.

If you lookup the invariance rules in the spec you will find that "values of matrices other than top-of-stack" is on the required list.

Any thoughts if that error is due to rounding/truncation of floating point values are highly speculative and only shows that this is a driver related problem as the spec is IMHO very clear about it.

I think that the real problem is an wrong/undefined state transistion that results in an undesired state change == driver bug.

Korval
09-26-2003, 06:03 PM
If you lookup the invariance rules in the spec you will find that "values of matrices other than top-of-stack" is on the required list.

But that is countered by:


changing the matrix mode is not required to guarantee invariance

Since the matrix mode was changed to Projection, the GL implementation is not required to be invariant. Now, precisely why it is the glLoadIdentity call that causes the invariance is strange.

You should bring this "problem" up with nVidia. The worst they can say is, "This behavior is allowed by the spec." The best is for them to fix it. If you do nothing, however, then it's never going to be fixed.

vincoof
09-26-2003, 10:44 PM
1234! : Minde me, I know what a memcpy is, and we have all understood why the behaviour looks weird. Nevertheless, this is correct in regard to the specification, as Korval pointed out.
Don't mistake the expected behaviour in regard to human opinion and the required behaviour in regard to the specification.

Jan
09-28-2003, 02:02 AM
"> My next gfx card will definitive be an ATI
> card, iīm fed up with nVidia.
And what makes you think that it will work on ATi ?
You base your opinion on DopeFish's test ?"

There are several things about my Gf 4 i am not satisfied with, which all seem to work perfectly on ATI cards. I never had an ATI card, so i am only speculating here. What i meant with that is, that i am fed up with nVidia, so i will change to ATI and test if they are really better. Itīs still possible, that ATI is even worse, but i canīt say that without testing it.

"First, make sure that you're running a similar example. At best, give your program to DopeFish and let him test with multiple screen depth, etc.
Secondly, check the depth buffer bit depth. GeForce1-4 easily use a 16bit depth-buffer if you don't ask for a stencil buffer, so it would not be representative to compare a Z-fighting on a 16-bit nVidia depth buffer with a 24-bit (or more) ATi depth buffer
"

First of all, this problem should be completely independent from screenresolution, color and/or depth-bits, etc. Second, i am sure i use a 24 Bit depth-buffer with 8 Bits for stencil.

"as far as i have understood this there shouldnt be any z fighting with any z-buffer-depth since he does multiple passes on the same geometry meaning, that the z-results should be exactely the same. "

Thatīs true. I use the same geometry multiple times for per-pixel lighting. There is no single change of the data in between.

"But in this case, a single part of that input data (currenlty, the projection matrix) is not guaranteed to be left unchaged over many frames"

Who was talking about multiple frames? I set my projection matrix at the start of each frame, so it gets "corrected" every frame, but it is not consistent in between a single frame. The z-fighting comes from the multiple "lighting-layers", which should be blended (depth-func: GL_LEQUAL), but donīt get blended, because they get not recognized as "at the same position".

"I'm not sure why loading identity would change FPU or FB precision, but I can imagine an "optimization" that kicks in when a matrix is known to be identity or at least non-perspective."

Itīs possible, but i donīt think so. In my example i used glLoadIdentity. In fact i tried it with glTranslatef and glRotatef, too. I didnīt try it with glMultMatrix, though. However, in my oppinion this should not make a difference, a push/pop operation should not change the matrix.

BTW: I think it is strange, that the matrix does not change when i push/pop WITHOUT changing it in between. I mean, if it really changes because of precision which gets lost when the matrix gets sent somewhere, than this precision should also get lost when no change has been done in between, unless the driver has some optimization, which prevents the pop operation from changing the matrix, if it wasnīt changed in between. However, i am not sure if such an "optimization" really makes sense. I donīt think it would speed up anything.

"I wouldn't be making wild-ass guesses like this except it would take a minute to test and might confirm the idea of a driver bug."

I didnīt "wild-ass guess" anything, i took two or three weeks to make sure it wasnīt my fault.

"You should bring this "problem" up with nVidia. The worst they can say is, "This behavior is allowed by the spec." The best is for them to fix it."

I already sent them a mail. They didnīt bother to reply (and you can be sure, that i was very polite and precise).


Bye then,
Jan.

Cyranose
09-28-2003, 06:05 PM
Originally posted by Jan2000:
"I'm not sure why loading identity would change FPU or FB precision, but I can imagine an "optimization" that kicks in when a matrix is known to be identity or at least non-perspective."

Itīs possible, but i donīt think so. In my example i used glLoadIdentity. In fact i tried it with glTranslatef and glRotatef, too. I didnīt try it with glMultMatrix, though. However, in my oppinion this should not make a difference, a push/pop operation should not change the matrix.

BTW: I think it is strange, that the matrix does not change when i push/pop WITHOUT changing it in between ...

"I wouldn't be making wild-ass guesses like this except it would take a minute to test and might confirm the idea of a driver bug."

I didnīt "wild-ass guess" anything, i took two or three weeks to make sure it wasnīt my fault.
Jan.[/B]

Easy, Jan. I wasn't saying you were 'wild-ass guessing.' I was saying I was.

And the kind of "optimization" I was wondering about was based on the projection matrix being perspective or ortho. glTranslate and glRotate wouldn't change that, btw. But I have nothing other than a hunch to go on.

sqrt[-1]
09-28-2003, 06:32 PM
Jan,
Is your app running in fullscreen mode? If so, could you test it again when running in windowed mode? (I experienced a similar bug only on the Geforce 3/4 but only when my app was in fullscreen mode - I was rendering some very close geometry and even though the camera was not moving, the geometry was z-fighting)

If this is the case, I may be able to provide a workaround.

Jan
09-29-2003, 12:30 AM
"Easy, Jan. I wasn't saying you were 'wild-ass guessing.' I was saying I was."

Sorry, i got that wrong.

I tested it in windowed mode, no difference there.

Well, i changed my app to do 2 z-passes instead of 1. Thatīs not the way i like it, but it works then.

Jan.

vincoof
09-29-2003, 01:49 AM
Thatīs true. I use the same geometry multiple times for per-pixel lighting. There is no single change of the data in between.
Do you happen to render at least one of the passes with a vertex program ? If so, do you use the ARB_position_invariant option ?

epajarre
09-29-2003, 02:08 AM
I just wondered could you use the following workaround? Add your mode/push/load/pop/mode snippet also before you render anything (but after you have loaded the correct values to matrices)

My idea here is that if the sequence somehow changes the matrix values, this way you might get the same (changed) values for all passes.

Eero

Tom Nuydens
09-29-2003, 02:27 AM
Originally posted by Jan2000:
Thatīs true. I use the same geometry multiple times for per-pixel lighting. There is no single change of the data in between.

Then why are you changing your projection matrix mid-frame?

-- Tom

Jan
09-29-2003, 05:13 AM
I do use vertex-programs in all passes, all of them use the position-invariant option.

"Then why are you changing your projection matrix mid-frame?"

To do a flare/glare/glow/however-you-want-to-call-it effect. I first render all objects with their "glow"-textures into the framebuffer. After that i change into ortho-mode and blur the image. After that i render the real level and then add the blurred glow-texture. In between i have to change the projection-matrix, but i can keep the depth-buffer-content (in theory).

Maybe i can try to do the same thing in perspective-mode, so i donīt have to change to projection-matrix, but that could be a bit difficult. Or i could use a pbuffer, but i donīt have any experience with them, yet.

Uh, stop! I just understood what Eero meant and tested it.

It works!

I simply put the push/pop stuff after i set my perspective view, but before i fill my z-buffer. After that i can push, modify and pop my projection-matrix as much as i want, itīs always equal to the one, which was used during filling the z-buffer.

Thanks man, great idea! And so simple!

Jan.

V-man
09-29-2003, 07:05 AM
There are some questions still left over:

-So what happens if you don`t use VP at all?

-Why use position invarient in your VP? Are you turning off VP during one of the passes?
Try usig them all the time.

-how are you setting up the projection matrix in the first place? Like this I imagine :

glLoadIdentity
gluPerspective

I think that if you don`t use VPs at all, you won`t see this problem. Cause I have done so while I had a Gf2MX and didn`t have problems back then.

Jan
09-29-2003, 09:06 AM
Yes, i simply use gluPerspective, really nothing special about it.

Itīs possible, that it works, if i donīt use VPs. However right now i donīt have any app with which i could test that easily. In fact, i only have one app, that uses OpenGL http://www.opengl.org/discussion_boards/ubb/wink.gif

Jan.

dorbie
10-03-2003, 11:37 AM
Look the spec states z invariance is guaranteed for identical state. A stack push and pop does NOT constitute a state change, I don't care what you load onto the stack after you push, this is a bug.

vincoof
10-03-2003, 12:14 PM
Originally posted by dorbie:
A stack push and pop does NOT constitute a state change.
Yes it does. It does change the matrix stack depth. And it is only "strongly suggested" that changing "matrix stack depths" has no side effect, so it would be valid not to guarantee invariance after a matrix is pushed / popped, even if I think we do all agree it looks weird.

Or maybe I misunderstood the specification, but in that case I would be very glad if anyone pointed out my error.

[This message has been edited by vincoof (edited 10-03-2003).]

dorbie
10-03-2003, 01:42 PM
No it is not, it is a push followed by a *POP*. The actual stack depth during both rendering passes is the same.

1234!
10-03-2003, 02:33 PM
Yeah, I know most of you are sick of my posts already...


Originally posted by Korval:
"If you lookup the invariance rules in the spec you will find that "values of matrices other than top-of-stack" is on the required
list.

But that is countered by:

changing the matrix mode is not required to guarantee invariance

No its not countered. You are only repeating what someone said before.

The spec says:

That values other then top-of-stack has to be invariant. The spec dosent say anything about the top-of-stack matrix. This is where "matrixmode" is on the suggested
list kicks in.


Originally posted by Korval:
Since the matrix mode was changed to Projection, the GL implementation is not required to be invariant.

Huh? I am a slow reader, could you please point me to the exact places where I will find this? Thx!

Since Jan verivied that if he removes the glLoadIdentity() call everything is fine, you sure agree the the matrixmode change isnt the problem?

You dont say glLoadIdentity causes an invariance, dont you?


Originally posted by Korval:
Now, precisely why it is the glLoadIdentity call that causes the invariance is strange.

Now we talking the same language...


Originally posted by Korval:
You should bring this "problem" up with nVidia. The worst they can say is, "This behavior is allowed by the spec." The best is for them to fix it. If you do nothing, however, then it's never going to be fixed.

Why the hell should I???



[This message has been edited by 1234! (edited 10-03-2003).]

vincoof
10-03-2003, 03:52 PM
>> No it is not, it is a push followed by a *POP*.
>> The actual stack depth during both rendering passes is the same.

Yes the stack depth gets back to its original state. But meanwhile, side effects *may* have occurred because the stack depth *has* changed, even if it was for a microsecond only. And these are those side effects that do not guarantee invariance anymore.

Calling glPushMatrix() immediately followed by glPopMatrix() logically takes the GL state vector back, but the specification does not require that, it strongly suggests it. Am I the only one to read that into the spec ? Man, I need to get more English lessons then http://www.opengl.org/discussion_boards/ubb/smile.gif

I see that problem a bit like calling glScalef(1.f, 1.f, 1.f) or glTranslatef(0.f, 0.f, 0.f) : one may expect that the implementation keeps the GL state vector unchanged, but in fact floating-point precision issues may still cause a little change.

vincoof
10-03-2003, 04:09 PM
Originally posted by 1234!:
That values other then top-of-stack has to be invariant

What you read is that no non-top-of-stack matrices can be affected by any other state change.

What I read is that no change to the non-top-of-stack matrices can affect other state.

IMO, whether you or I is right about that particular point depends on the understanding of that sentence :
"Changes to the following state values have no side effects (the use of any other state value is not affected by the change)"

Korval
10-03-2003, 04:44 PM
A stack push and pop does NOT constitute a state change, I don't care what you load onto the stack after you push, this is a bug.

That's just wrong and you know better.

That's like saying that if you bind a texture, play with it's parameters, and bind the old one, you haven't changed the state. That's false, because you have changed the state. You changed texture state twice. Now, granted, an implementation is able to determine when something like this happens and not go through a texture upload or a page-out, but you have effectively changed the state.

If you put something that is in state A into state X, it's state has changed, even if you then put it back to state A. Especially if the spec says that you can't guarentee that changing from state A to state X can be fully undone, such that the state you return to is the same as state A.


Since Jan verivied that if he removes the glLoadIdentity() call everything is fine, you sure agree the the matrixmode change isnt the problem?

You dont say glLoadIdentity causes an invariance, dont you?


Once he changed to GL_PROJECTION, the implementation is free to do what it wants. The change to GL_PROJECTION doesn't have to cause the invariance itself; switching to GL_PROJECTION is enough to open up the possibility. The fact that, in this implementation's case, calling glLoadIdentity cause the invariance after the change to GL_PROJECTION is immaterial; the implementation is allowed to be arbiturarily invariant once the matrix mode is changed.

If doing a Push/Load/Pop on the modelview stack caused this, I think the spec would say that it is a bug. However, that isn't the case here.


Why the hell should I???

If, as you suggest, it is a bug, you should submit a bug report. Just like if you noticed that your vertex programs weren't doing what they should, or a texture when loaded with a particular state is garbled. You should always report bugs to the developer of the driver, unless you're certain that someone else has done so already. If you don't submit a bug, it'll never get fixed.

It's your drivers; you can try to get them fixed or leave them broken.


Calling glPushMatrix() immediately followed by glPopMatrix() logically takes the GL state vector back, but the specification does not require that, it strongly suggests it.

I thought that the spec required invariance for Push/modify/Pop operations on the same stack, and that invariance was allowed only if you changed matrix stacks.

OldMan
10-04-2003, 11:54 AM
I do have a ti4200 and tried this. No problems here. Tried even two times.. each one interleaving my 3 passes. No problems. But I am using Linux here.

1234!
10-04-2003, 03:01 PM
Originally posted by vincoof:
Yes the stack depth gets back to its original state. But meanwhile, side effects *may* have occurred because the stack depth *has* changed, even if it was for a microsecond only. And these are those side effects that do not guarantee invariance anymore.

Calling glPushMatrix() immediately followed by glPopMatrix() logically takes the GL state vector back, but the specification does not require that, it strongly suggests it. Am I the only one to read that into the spec ? Man, I need to get more English lessons then http://www.opengl.org/discussion_boards/ubb/smile.gif


If you read one of my previous posts you will see that I already mentionted that there maybe a state transition going wrong. This is something I call a bug.


Originally posted by vincoof:

I see that problem a bit like calling glScalef(1.f, 1.f, 1.f) or glTranslatef(0.f, 0.f, 0.f) : one may expect that the implementation keeps the GL state vector unchanged, but in fact floating-point precision issues may still cause a little change.

This is actually a bad example. A multiplication 3.14f * 1.0f is guaranteed to result in 3.14f while a multiplication 3.14f x 0.0f will result in 0.0f (this is covered in the IEEE spec for floating point numbers).

1234!
10-04-2003, 03:06 PM
Originally posted by vincoof:
What you read is that no non-top-of-stack matrices can be affected by any other state change.

What I read is that no change to the non-top-of-stack matrices can affect other state.

IMO, whether you or I is right about that particular point depends on the understanding of that sentence :
"Changes to the following state values have no side effects (the use of any other state value is not affected by the change)"

I agree that people understand the spec in different ways and I dont say that I am right, but so far none of the arguments I heard convinced me that I am totaly wrong.

I mean if the spec would really be that lax, I would run into problems like that every day.

1234!
10-04-2003, 03:27 PM
Originally posted by Korval:

If you put something that is in state A into state X, it's state has changed, even if you then put it back to state A. Especially if the spec says that you can't guarentee that changing from state A to state X can be fully undone, such that the state you return to is the same as state A.

If I have a A->X->A transition state "A" is "A" again unless the state transition goes wrong. I think you mean a A->X->B transition where an "undo" on state "X" leads you to a different state then the original. However you are refering alot to the spec without pointing to the exact place. Your argumentation would be much stronger if you back it up which the real thing instead of your interpretation of what others said before.


Originally posted by Korval:

1234! wrote: "Why the hell should I"

If, as you suggest, it is a bug, you should submit a bug report. Just like if you noticed that your vertex programs weren't doing what they should, or a texture when loaded with a particular state is garbled. You should always report bugs to the developer of the driver, unless you're certain that someone else has done so already. If you don't submit a bug, it'll never get fixed.

It's your drivers; you can try to get them fixed or leave them broken.


Now you are really mixing stuff up. I dont even have a Nvidia board, so there are not "my drivers". I tested it with a 3dlabs wildcat and an Radeon9700 both worked fine. Since I only need to care about the wildcat I dont care about nvidia.

To conclude this, if the spec would be really that lax as you are implying, I wonder why I dont see that kind of problems every day.

I am not saying that I am right, but your argumentation is weak and based only on assumptions that somehow sound desperate.

dorbie
10-04-2003, 04:06 PM
Look this is not a state change w.r.t. the earlier state during the first pass. You can't be serious. Depth invariance for similar state does not mean that you're not allowed to change state. It means that if two passes have the same state they should render with the same depth values.

If I bind a texture draw stuff go off and do anything I please then come back and restore that state and even bind a *different* texture, depth inveriance is guaranteed.

No state was different between the first pass and the second pass. I frankly can't believe we're even having this debate here.

Show me the piece of OpenGL state that is affected by push load pop and I'll buy your theory. But there is no piece of state that has been affected. So it is still a bug IMHO.

side effects be damned, there should be no side effects, that's one of the points of having a state engine in the first place.

:-)



[This message has been edited by dorbie (edited 10-04-2003).]

dorbie
10-04-2003, 04:19 PM
P.S.

If the matrix is losing something in the push/load/pop the simplest solution may be to push/load/pop before the first pass also.

This bug may be caused by the implementation using knowledge of how the matrix is constructed to optimize the transformation for marginally faster results causing rounding differences between a loaded matrix vs a matrix constructed with afine transformations. With a push load pop the optimization is lost and a slightly different path may be implemented. With this implementation a push/pop should probabably also push and pop knowledge used like this.

If this is correct even a loadmatrix of an identity array (not a loadidentity) woudl defeat the optimization and restore depth inveriance.

[This message has been edited by dorbie (edited 10-04-2003).]

1234!
10-04-2003, 04:21 PM
Originally posted by dorbie:
It **IS** a bug.


What I am saying all the time...


Originally posted by dorbie:
side effects be damned, there should be no side effects, that's one of the points of having a state engine in the first place.


Precisely.

Korval
10-04-2003, 08:22 PM
This is something I call a bug.[/qutoe]

Whether you call it a bug or not is immaterial; the question is whether or not the behavior is a bug according to the OpenGL spec.

[quote]Show me the piece of OpenGL state that is affected by push load pop and I'll buy your theory.

My theory is that the changing of the matrix mode allows invariances, regardless of what other function calls actually precipticate those invariances.


But there is no piece of state that has been affected. So it is still a bug IMHO.

One could easily argue that the matrix state has been changed. If the spec doesn't say that Pop must fully undo Push, then state has been changed.

This entire discussion is just another reason to go write a matrix stack of my own.

kansler
10-04-2003, 11:25 PM
Originally posted by Korval:
One could easily argue that the matrix state has been changed. If the spec doesn't say that Pop must fully undo Push, then state has been changed.

Stack: A data structure for storing items which are to be accessed in last-in first-out order.

A stack cannot by definition change it's contents. Therefore, if you push and then pop, state will not have changed for the stack.

Xmas
10-05-2003, 07:32 AM
Originally posted by Jan2000:
Yes, i simply use gluPerspective, really nothing special about it.
I am pretty sure this is the reason why you get different results. Not the matrices might be slightly different after you execute your code snippet, but the znear and zfar values.

There is actually something special about gluPerspective.
When you load the identity matrix, the driver probably sets a "change" flag, so it has to recalculate znear and zfar from the top-of-stack matrix after the pop. This might not be 100% identical to those values passed to gluPerspective.
http://sjbaker.org/steve/omniv/projection_abuse.html

Cyranose
10-05-2003, 09:49 AM
Originally posted by Xmas:
I am pretty sure this is the reason why you get different results. Not the matrices might be slightly different after you execute your code snippet, but the znear and zfar values.

There is actually something special about gluPerspective.
When you load the identity matrix, the driver probably sets a "change" flag, so it has to recalculate znear and zfar from the top-of-stack matrix after the pop. This might not be 100% identical to those values passed to gluPerspective.
http://sjbaker.org/steve/omniv/projection_abuse.html [/B]

That makes some sense, but it still smacks of a bug to me. gluPerspective calls an implicit glMultMatrix (not glLoadMatrix) so there can easily be a non-identity matrix on the top of stack to start with. So for gluPerspective to do any adjusting of depth ranges directly from the given near/far params would seem to be a big mistake. It's also possible that glLoadIdentity has some magic znear/zfar code in it, which would also be a mistake, IMO.

The code which computes the min/max Z (if any) should only extract it from the actual top of projection stack matrix, which should get recalculated or restored with glPop, or set by glMultMatrix or glLoadMatrix using identical math. Maybe I'm being naive, but invariance seems much easier to achieve when you stick to single code paths for these sorts of calculations.

I wonder if Jan can add some glGetDoubles on the depth range in the appropriate places, or just an explicit override of the depth ranges to see if that fixes the zfighting.

Or maybe Jan's already solved this and we're just debating ourselves to death http://www.opengl.org/discussion_boards/ubb/wink.gif

Avi


[This message has been edited by Cyranose (edited 10-05-2003).]

1234!
10-05-2003, 10:45 AM
Originally posted by Xmas:
I am pretty sure this is the reason why you get different results. Not the matrices might be slightly different after you execute your code snippet, but the znear and zfar values.

There is actually something special about gluPerspective.
When you load the identity matrix, the driver probably sets a "change" flag, so it has to recalculate znear and zfar from the top-of-stack matrix after the pop. This might not be 100% identical to those values passed to gluPerspective.


Huh??? You pass fov, aspect, znear and zfar to gluPerspective and it creates you a nice projection matrix.

There is no need to store the values (you would need an extra stack for redundant information), let alone recalculate them (how would someone do that and why?).

This is really getting hilarious!!!

Why cant people accept the simple fact that this is nothing but a bug? I guess its around for ages so everybody takes it for granted and the spec must be at fault.

Even if Nvidia doesnt agree that its a bug, the least they could do is make their implementation more "compatible" with others.

Cheers!

[This message has been edited by 1234! (edited 10-05-2003).]

1234!
10-05-2003, 10:54 AM
Originally posted by Cyranose:
Or maybe Jan's already solved this and we're just debating ourselves to death http://www.opengl.org/discussion_boards/ubb/wink.gif


No, we are not really debating, people come up with thoughts and theories that are uhh shall I say 'creative' to make the OpenGL spec look bad. The spec is not perfect thats for sure, but if it would be as bad/invariant as people are implying, it would be a real mess.

Cheers!

Xmas
10-05-2003, 11:19 AM
Originally posted by 1234!:
Huh??? You pass fov, aspect, znear and zfar to gluProject and it creates you a nice projection matrix.

There is no need to store the values (you would need an extra stack for redundant information), let alone recalculate them (how would someone do that and why?).

This is really getting hilarious!!!

Why cant people accept the simple fact that this is nothing but a bug? I guess its around for ages so everybody takes it for granted and the spec must be at fault.

Even if Nvidia doesnt agree that its a bug, the least they could do is make their implementation more "compatible" with others.

Cheers!
Hey, calm down. I agree that it's a bug. I just came up with an idea why this happens.

The reason why you need znear and zfar along with the matrix is that the depth values get scaled before written to the depth buffer so that znear is mapped to the smallest value and zfar is mapped to the largest value representable by the depth buffer format. This way you'll always use the full range of representable numbers. But znear and zfar do not exist as plain values inside the projection matrix. So if you e.g. just load some arbitrary matrix while in PROJECTION matrix mode, the driver needs to obtain the znear and zfar values from that matrix. It's not like you have to call some function you pass znear and zfar to, and they will remain constant.

1234!
10-05-2003, 11:55 AM
Originally posted by Xmas:
Hey, calm down. I agree that it's a bug. I just came up with an idea why this happens.


Hey I am calm! Dunno what gives you the idea I am not.


Originally posted by Xmas:
The reason why you need znear and zfar along with the matrix is that the depth values get scaled before written to the depth buffer so that znear is mapped to the smallest value and zfar is mapped to the largest value representable by the depth buffer format. This way you'll always use the full range of representable numbers.


This is done by the matrix multiplication with the projection matrix, there is NO need to store znear/zfar.


Originally posted by Xmas:
But znear and zfar do not exist as plain values inside the projection matrix. So if you e.g. just load some arbitrary matrix while in PROJECTION matrix mode, the driver needs to obtain the znear and zfar values from that matrix. It's not like you have to call some function you pass znear and zfar to, and they will remain constant.

No offense, but you dont know what you are talking about. There is no need to know about the znear or zfar values after calling gluPerspective. Its all in the projection matrix. The matrix multiplication with the projection matrix will scale the z values within range.

*sights*




void GLAPIENTRY
gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar)
{
GLdouble xmin, xmax, ymin, ymax;

ymax = zNear * tan(fovy * M_PI / 360.0);
ymin = -ymax;
xmin = ymin * aspect;
xmax = ymax * aspect;

/* don't call glFrustum() because of error semantics (covglu) */
frustum(xmin, xmax, ymin, ymax, zNear, zFar);
}

static void
frustum(GLdouble left, GLdouble right,
GLdouble bottom, GLdouble top,
GLdouble nearval, GLdouble farval)
{
GLdouble x, y, a, b, c, d;
GLdouble m[16];

x = (2.0 * nearval) / (right - left);
y = (2.0 * nearval) / (top - bottom);
a = (right + left) / (right - left);
b = (top + bottom) / (top - bottom);
c = -(farval + nearval) / ( farval - nearval);
d = -(2.0 * farval * nearval) / (farval - nearval);

#define M(row,col) m[col*4+row]
M(0,0) = x; M(0,1) = 0.0F; M(0,2) = a; M(0,3) = 0.0F;
M(1,0) = 0.0F; M(1,1) = y; M(1,2) = b; M(1,3) = 0.0F;
M(2,0) = 0.0F; M(2,1) = 0.0F; M(2,2) = c; M(2,3) = d;
M(3,0) = 0.0F; M(3,1) = 0.0F; M(3,2) = -1.0F; M(3,3) = 0.0F;
#undef M

glMultMatrixd(m);
}



This is how MESA (www.mesa3d.org) implements gluPerspective. I am pretty sure that this is the way most others implemtations do it too, because doing it otherwise makes no sence.

Cheers!

zeckensack
10-05-2003, 11:56 AM
Xmas,
hi http://www.opengl.org/discussion_boards/ubb/wink.gif
isn't that rather redundant and cumbersome?

For getting z values into the proper range ([0...1]), the matrix mult/perspective divide is sufficient. glDepthRange is another thing (can be implemented as a simple MAD), but that isn't even involved here.

Going from [0...1] to the numeric range of the z buffer implementation should be handled by the hardware if you ask me. These implicit format conversions work for texture formats after all. Why would it be different for z buffer reads and writes?

Xmas
10-05-2003, 12:41 PM
*bangs his head*
Of course you're right, the matrix multiply is sufficient http://www.opengl.org/discussion_boards/ubb/redface.gif ...guess I should practise some math every once in a while.

Still, that link I provided says: "You *could* use glLoadMatrix to set up your own projection matrix (if you understand the restrictions and consequences) - but I'm told that this can cause problems for some OpenGL implementations which rely on data passed to glFrustum, etc to determine the near and far clip planes"
What does he mean there?

Cyranose
10-05-2003, 02:35 PM
Originally posted by Xmas:
*bangs his head*
Of course you're right, the matrix multiply is sufficient http://www.opengl.org/discussion_boards/ubb/redface.gif ...guess I should practise some math every once in a while.

Still, that link I provided says: "You *could* use glLoadMatrix to set up your own projection matrix (if you understand the restrictions and consequences) - but I'm told that this can cause problems for some OpenGL implementations which rely on data passed to glFrustum, etc to determine the near and far clip planes"
What does he mean there?

Someone can correct me if I misspeak, but an identity projection matrix results in -1 to 1 z values (actually *any* FP value, depending on the input vertices, but we traditionally clip outside the frustum, which would be -1 to +1 in x,y,z by default). But the point is that something maps this back to [0..1] for depth test/write.

I imagine what he means in that excerpt is that glFrustum can set the offset/scale params that set up this mapping.

It sounds like some implementations do it that way and others may derive the info from the top-of-stack projection matrix itself, the latter being the correct method, IMO. But reading the spec, I'm not totally clear of the interaction of the latter approach and glDepthRange.

Avi

[This message has been edited by Cyranose (edited 10-05-2003).]

1234!
10-05-2003, 03:02 PM
Originally posted by Cyranose:
Someone can correct me if I misspeak, but an identity projection matrix results in -1 to 1 z values (actually *any* FP value, depending on the input vertices, but we traditionally clip outside the frustum, which would be -1 to +1 in x,y,z by default). But the point is that something maps this back to [0..1] for depth test/write.

I imagine what he means in that excerpt is that glFrustum can set the offset/scale params that set up this mapping.

It sounds like some implementations do it that way and others may derive the info from the top-of-stack projection matrix itself, the latter being the correct method, IMO. But reading the spec, I'm not totally clear of the interaction of the latter approach and glDepthRange.

Avi

[This message has been edited by Cyranose (edited 10-05-2003).]

Dude, why dont you do us all a favour and actually read the OpenGL spec before you post crap like this?

glLoadIdentity() is defined as:

1.0, 0.0, 0.0, 0.0
0.0, 1.0, 0.0, 0.0
0.0, 0.0, 1.0, 0.0
0.0, 0.0, 0.0, 1.0

You will find this in the OpenGL spec if you bother to look at it.

http://www.opengl.org/discussion_boards/ubb/rolleyes.gif

[This message has been edited by 1234! (edited 10-05-2003).]

Cyranose
10-05-2003, 04:57 PM
Originally posted by 1234!:
Dude, why dont you do us all a favour and actually read the OpenGL spec before you post crap like this?

glLoadIdentity() is defined as:

You will find this in the OpenGL spec if you bother to look at it.

http://www.opengl.org/discussion_boards/ubb/rolleyes.gif




If you think there's a mistake in my post, feel free to point it out, but preferably without resorting to infantilism, dude.

I've read the spec many times, as well as the man pages. I've been using OpenGL professionally for over ten years. Thank you. Doesn't mean I don't mistakes, but I'd appreciate it if you a) read my post first and b) didn't act like an ass.

And frankly, I don't see how stating the obvious definition of glLoadIdentity has anything to do with my post.

Avi


[This message has been edited by Cyranose (edited 10-05-2003).]

1234!
10-05-2003, 07:18 PM
Originally posted by Cyranose:

If you think there's a mistake in my post, feel free to point it out, but preferably without resorting to infantilism, dude.

It's a mistake in your post.


Originally posted by Cyranose:

I've read the spec many times, as well as the man pages.

You may have read the man pages, but it sure doesnt look like you have read the spec.


Originally posted by Cyranose:

I've been using OpenGL professionally for over ten years. Thank you. Doesn't mean I don't mistakes, but I'd appreciate it if you a) read my post first and b) didn't act like an ass.

Using OpenGL and understand the spec are two very different things.

a.) I even re-read your post, its still makes no-sence.
b.) If people would stop posting half assed assumptions, I dont have to prove them wrong.


Originally posted by Cyranose:

And frankly, I don't see how stating the obvious definition of glLoadIdentity has anything to do with my post.


Your post about an identity perspective matrix (-1 to 1.0 or "any other value", was the worst crap of 3d math I ever read.

Cheers!

Cyranose
10-05-2003, 08:43 PM
Originally posted by 1234!:
Your post about an identity perspective matrix (-1 to 1.0 or "any other value", was the worst crap of 3d math I ever read.

Cheers!

Maybe because that's not what I said and I didn't post 3D math, I posted words to get to a later point. I have to wonder if you used your real name and email if you'd be acting like such an ass in public.

But assuming I wasn't clear, I'll clarify:

I said: "an identity projection matrix results in -1 to 1 z values (actually *any* FP value, depending on the input vertices, but we traditionally clip outside the frustum, which would be -1 to +1 in x,y,z by default)."

I'll stipulate that's at least overly terse and possibly confusing (hint: ask for clarification). My point is that if you multiply a 3D point (any X,Y,Z in valid FP range) by an identity transform (assume both perspective and modelview are identity for simplicity), you'll get those same X,Y,Z values after transform. Basic clipping will clip the homogenous coords to +/- w (w=1) on the 3 original axes, which means the output x,y,z values will be in the -1 to 1 range (ignoring the complexities of optimized clipping w/ scissoring). Dividing by w (still =1) yields values still in the -1 to 1 range. So we get values in the +/-1 range for X,Y, and Z, or, ignoring clipping, we can get *any* FP value depending on the original point and other factors. In other words, the division by w does not guarantee a [0..1] mapping, not even for a perspective projection matrix I believe (unless that matrix expliclty maps z to [0..1]).

Nothing in the pipeline so far has explicitly mapped z to [0..1]. In fact, if you look at the spec, you'll see that this mapping is supposed to happen in the viewport transformation phase. (see p32 in the 1.4 spec). There is an effective scale and bias (z = ((f-n)/2)*zd + (n+f)/2), whereby the znear and zfar must be known. These can be derived from the projection matrix beforehand, knowing the post-transformed-clipped-normalized vertex will have one range and the FB has another. And glDepthRange can further refine this.

Now, I've used about ten times as many words and I hope it's clearer for you, but my point is the same. gluPerspective, glFrustum, or even glLoadIdentity in that implementation may be setting (or restoring) the z-near and z-far inappropriately.

I'm happy to be corrected by the pros on this board if I state something incorrectly. But 1234! or whatever your name is, until you can act like an adult, please shut up.

Avi


[This message has been edited by Cyranose (edited 10-05-2003).]

vincoof
10-06-2003, 01:58 AM
Originally posted by dorbie:
If the matrix is losing something in the push/load/pop the simplest solution may be to push/load/pop before the first pass also.

This has already been proposed in earlier posts, and it seemed to work so far.

dorbie
10-06-2003, 02:11 AM
I'd still like to hear if a load of an identity array instead of a loadidentity works when building the matrix in the first place without a push/pop. I like that one, it'd also save the push pop and would put a little flesh on the bones of theories about optimized vertex transform.

1234!
10-07-2003, 02:55 PM
Originally posted by Cyranose:
I have to wonder if you used your real name and email if you'd be acting like such an ass in public.


Why dont we start with you showing us that you can act like an adult and refrain from calling me names (the 2nd time)? I cant recall that I did that to you, did I?

As for my email/real name, I get enough spam already, I dont need you to put me on even more spam lists, thank you.

Ok you have read the spec's, I take that back.

As for your assumption, I have to admit, its interessting, but I also think it violates other rules of the spec. I will think it over.



[This message has been edited by 1234! (edited 10-07-2003).]