ATI 9600XT Linux Driver bug found?

In another application of mine, strange ATI-linux-related bugs turned up. After much research, I traced back the problem to glDrawArrays.

So I changed a simple 3DS file loader to use GL arrays instead of glVertex3f for each vertex to be a proof of concept using SDL:
http://www.fmf.nl/~orion/3DSFileLoader.tar.gz

(the issue happens in GL without SDL too, but this is just easier to set up)

This displays a face. In default mode, it works great on both ATI and NVidia cards.

When you provide the commandline switch ‘–arraymode’ it will use glDrawArrays. Strange stuff this way comes.

On my NVidia it works fine. (a tad slow, but that’s because of the inefficient coding)

On ATI, on the other hand, enormous display deformations and flickering polygons cover part of the screen. It looks like some kind of memory corruption. (through the madness you can still see something of the original object though)

Derelict code can be found in Main.cpp:
Normal code:

// This determines if we are in wireframe or normal mode
glBegin(g_ViewMode); // Begin drawing with our selected mode (triangles or lines)
// Go through all of the faces (polygons) of the object and draw them
for(int j = 0; j < pObject->numOfFaces; j++)
{
// Go through each corner of the triangle and draw it.
for(int whichVertex = 0; whichVertex < 3; whichVertex++)
{
// Get the index for each point of the face
int index = pObject->pFaces[j].vertIndex[whichVertex];

                // Give OpenGL the normal for this vertex.
                glNormal3f(pObject->pNormals[ index ].x, pObject->pNormals[ index ].y, pObject->pNormals[ index ].z);
            
                // If the object has a texture associated with it, give it a texture coordinate.
                if(pObject->bHasTexture) {

                    // Make sure there was a UVW map applied to the object or else it won't have tex coords.
                    if(pObject->pTexVerts) {
                        glTexCoord2f(pObject->pTexVerts[ index ].x, pObject->pTexVerts[ index ].y);
                    }
                } else {

                    // Make sure there is a valid material/color assigned to this object.
                    // You should always at least assign a material color to an object, 
                    // but just in case we want to check the size of the material list.
                    // if the size is at least one, and the material ID != -1,
                    // then we have a valid material.
                    if(g_3DModel.pMaterials.size() && pObject->materialID >= 0) 
                    {
                        // Get and set the color that the object is, since it must not have a texture
                        BYTE *pColor = g_3DModel.pMaterials[pObject->materialID].color;

                        // Assign the current color to this model
                        glColor3ub(pColor[0], pColor[1], pColor[2]);
                    }
                }

                // Pass in the current vertex of the object (Corner of current face)
                glVertex3f(pObject->pVerts[ index ].x, pObject->pVerts[ index ].y, pObject->pVerts[ index ].z);
            }
        }
    glEnd();                                // End the drawing

Array rendering:

int nvertices = pObject->numOfFaces * 3;
GLfloat vertices[nvertices][3];
GLfloat normals[nvertices][3];
GLfloat texcoords[nvertices][2];
int vptr = 0;

// Go through all of the faces (polygons) of the object and draw them
for(int j = 0; j < pObject->numOfFaces; j++) {
// Go through each corner of the triangle and draw it.
for(int whichVertex = 0; whichVertex < 3; whichVertex++)
{
// Get the index for each point of the face
int index = pObject->pFaces[j].vertIndex[whichVertex];

                	// Give OpenGL the normal for this vertex.
      	normals[vptr][0] = pObject->pNormals[ index ].x;
      	normals[vptr][1] = pObject->pNormals[ index ].y;
      	normals[vptr][2] = pObject->pNormals[ index ].z;

                    // Make sure there was a UVW map applied to the object or else it won't have tex coords.
  	if(pObject->pTexVerts) {
  		texcoords[vptr][0] = pObject->pTexVerts[ index ].x;
  		texcoords[vptr][1] = pObject->pTexVerts[ index ].y;
  	}

  	vertices[vptr][0] = pObject->pVerts[ index ].x;
  	vertices[vptr][1] = pObject->pVerts[ index ].y;
  	vertices[vptr][2] = pObject->pVerts[ index ].z;
      	vptr++;
            }
    }

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

glVertexPointer(3,GL_FLOAT,0,vertices);
glNormalPointer(GL_FLOAT,0,normals);
glTexCoordPointer(2,GL_FLOAT,0,texcoords);

// This determines if we are in wireframe or normal mode
glDrawArrays(g_ViewMode,0,nvertices);
//glFinish();
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);

As you can see, the array code does nothing fancy at all. It should just work.

Can someone please try this out before I submit a bug report to ATI? (it could be an AGP transfer problem here, for example, and work just fine on sane systems)

[This message has been edited by :wumpus: (edited 01-25-2004).]

Turned out to be a faulty AGP bus, which also created crashes onder Windows. Seems to be some KT400 issue, I fixed it by changing the memory clock in the BIOS.

What exactly did you do fix this? I’m seeing the same behavior on a larger variety of machines, including a bunch of Dells with Intel processors and chipsets. We also tried several different versions of RHE and Mandrake with the same results.

Michael

I am also intersested in knowing the solution…

–Rymdninja

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.