Skip to main content
GameDev.net gamedev.net
🔒 Locked

Stupid ATI optimization going wrong?

Started by Int19 Jan 17, 2007 at 10:42 AM 9 replies 1.8k views
Original Post
Int19
Int19
Hi Im having trouble with small meshes (cubes and such) getting screwed up on ATI cards when using VBO:s and glDrawArrays(). My first thought was that it was the size of the VBO that was the problem so i told my vbo manager to make them 4096 bytes for a minimum. This did seem to solve it for the scene i was working with back then. But now i have run into the same problem with my tree rendering. I dont batch trees atm since "pseudo-instancing" and imposters give good enough performance. So this means im rendering meshes with only 4 tris (two crossed quads) over and over (for low lod). It works for the first few frames but then it goes haywire and the vertices seem to get random positions (seems the VBO gets screwed up)... ..im thinking this might be an ATI optimization of some kind that is behaving in the wrong way. Has anyone else had this problem? Greetz David
Squirell
Squirell
I seriously doubt that ATI screwed up something so basic. Have you tried running it on an NVIDIA card and do you get the same results? Also, posting some example code would allow us to help you out much more.
Int19
Int19
It works fine on all nVidia cards ive tried so far (6600 and upwards). And as I said it also works fine for the first few frames and then all of a sudden goes haywire. There is no difference in the api calls made in the working frames and the ones that screw up (i dont move the camera at all).

Here are two screens. I have turned off all shadowing and all specialized shaders (water,cube reflections,hdr etc.) to narrow down the renderpaths. So im down to the single shader (diffuse texture + directional light only).

The flying white stuff in the lower screenshot are my poor trees with screwed up UVs.


http://img295.imageshack.us/img295/4919/smallmeshproblempa6.jpg


Ohh.. and the highres lods of the trees go through the EXACT same path as the lowres ones, and there is no problem with them.
Kazade
Kazade
Its highly unlikely that this is the fault of ATI. My guess is that there is a tiny error in your code somewhere, that the nVidia drivers cope better with than the ATI ones. Perhaps if you post your rendering code we might be able to help some more?
Member of the NeHe team.
GuentherKrass
GuentherKrass
I recomment using glIntercept or geDebugger to log all gl-calls and errors. Compare the log of the correct rendered scene against the incorrect one. This should help you figuring out what's wrong.

Cheers,

GuentherKrass
Int19
Int19
Thx for the replies. I rewrote large parts of my vertexbroker code to make it easier to track down the problem. Unfortunally (or maybe not) it fixed the problem for this specific scene. Im hoping the problem doesnt pop up again in some other one though. Anyways.. ..until it does i guess this thread is dead.

Thx again anyway.. ..now to posting about gl_FragCoord on ati.. .as that is not working either ;)
Int19
Int19
Some good and bad news!

BAD NEWS :

The problem returned when i switched back from debug to release build. This caused me to once again go through all my code looking for places where debug/release differences (mainly pointers not initialized to null correctly) would cause different code branches. Spent 2 days looking for this (doing all sorts of tracking) and could not find a single difference..... grrr!

GOOD NEWS :

I found the solution and it is most definately an ATI issue. The problem turned out to be that i invalidated my buffer before mapping it for an update
(as suggested by nVidia in their VBO paper).

so commenting out

"glBufferDataARB( GL_ARRAY_BUFFER_ARB, _numBytes, NULL, GL_STATIC_DRAW_ARB );"

solved the issue. This ofcourse could come with a performance hit (if buffers are being worked upon). So I might make a "if(gpu.vendor==nVidia)" check for this.

Why this issue only pops up in release mode is still unclear, but most likely its the fact that in debug mode the cpu work being done between render and potential buffer updates just happens to be long enough that the data is not being worked upon, and ATI simply doesnt invalidate the bufferdata when being passed NULL.

Maybe it would be nice with an "ATI issues" sticky thread where these things could be listed, cause its most definately not the first issue ive had with ATI :(

Greetz David
rick_appleton
rick_appleton
Quote:
Original post by Int19
I found the solution and it is most definately an ATI issue. The problem turned out to be that i invalidated my buffer before mapping it for an update
(as suggested by nVidia in their VBO paper).

so commenting out

"glBufferDataARB( GL_ARRAY_BUFFER_ARB, _numBytes, NULL, GL_STATIC_DRAW_ARB );"

solved the issue. This ofcourse could come with a performance hit (if buffers are being worked upon). So I might make a "if(gpu.vendor==nVidia)" check for this.


You might want to check the specs on that. I seem to remember that being valid according to specs, in which case ATI's drivers are faulty, rather than nVidia's being too easy on you.

_the_phantom_
_the_phantom_
iirc (and I don't have time to check) the NULL data buffer thing ISN'T in the spec; it's an extension of sorts which allows for faster updates.

My guess would be that ATI release the buffer as requested however their glMapBuffer() entry point doesn't do the correct work to setup a new one after a null because the common usage is

glBufferData(..., NULL, ...);
glBufferData(..., address, ...);

If I get time later tonight I'll have a poke at the VBO extension and see what I can come up with.

The point being, it's probably not broken wrt the spec as this behaviour might not even be covered.
rick_appleton
rick_appleton
I took a look at the spec, and it seems as I remembered, one of the samples does exactly what you are doing.

OpenGL specs:
Vertex arrays using a mapped buffer object:	// Frame rendering loop	while (...) {            // Define arrays (and create buffer object in first pass)            BindBufferARB(ARRAY_BUFFER_ARB, 1);            VertexPointer(4, FLOAT, 0, BUFFER_OFFSET(0));            ColorPointer(4, UNSIGNED_BYTE, 0, BUFFER_OFFSET(256));            // Enable arrays            EnableClientState(VERTEX_ARRAY);            EnableClientState(COLOR_ARRAY);            // Initialize data store of buffer object            BufferDataARB(ARRAY_BUFFER_ARB, 320, NULL, STREAM_DRAW_ARB);	    // Map the buffer object	    float *p = MapBufferARB(ARRAY_BUFFER_ARB, WRITE_ONLY);            // Compute and store data in mapped buffer object            ...	    // Unmap buffer object and draw arrays	    if (UnmapBufferARB(ARRAY_BUFFER_ARB)) {                DrawArrays(TRIANGLE_STRIP, 0, 16);            }            // Disable arrays            DisableClientState(VERTEX_ARRAY);            DisableClientState(COLOR_ARRAY);            // Other rendering commands            ...	}        // Delete buffer object	int buffer[1] = {1};        DeleteBuffersARB(1, buffer);
Int19
Int19
Yes. The above is exactly what I was doing.

It gets even weirder by the fact that this problem only exists for SMALL (<40 vertex count) meshes. The smallest VBO:s I have are 4096 atm, which would be 128 vertices with a 32byte vertexsize. I am not sure if this problem is dependent on the VBO size or the actual number of bytes being used (uploaded/drawn). I'll look into it once i get a few extra mins.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.