PDA

View Full Version : Possible Nvidia driver bug?



bakery2k
11-17-2002, 09:11 AM
After a discussion in this thread: http://www.opengl.org/discussion_boards/ubb/Forum3/HTML/007950.html
we came to the conclusion that we had found a possible driver bug. Could someone please confirm/deny this?
Here is a simple test program written with glut. It does not check for NV_vertex_program support for brevity, but demonstrates the bug:




//Possible Nvidia driver bug with NV_vertex_program aliased attributes
#include <stdio.h>
#include <GL/glut.h>
#include <GL/glext.h>

float vertexPositions[]={ -1.0f,-1.0f, 0.0f,
-1.0f, 1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
1.0f,-1.0f, 0.0f};

PFNGLBINDPROGRAMNVPROC glBindProgramNV;
PFNGLGENPROGRAMSNVPROC glGenProgramsNV;
PFNGLVERTEXATTRIBPOINTERNVPROC glVertexAttribPointerNV;
PFNGLLOADPROGRAMNVPROC glLoadProgramNV;
PFNGLTRACKMATRIXNVPROC glTrackMatrixNV;


GLuint vertexProgram;

void init(void)
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glEnable(GL_DEPTH_TEST);

glBindProgramNV = (PFNGLBINDPROGRAMNVPROC)
wglGetProcAddress("glBindProgramNV");
glGenProgramsNV = (PFNGLGENPROGRAMSNVPROC)
wglGetProcAddress("glGenProgramsNV");
glVertexAttribPointerNV = (PFNGLVERTEXATTRIBPOINTERNVPROC)
wglGetProcAddress("glVertexAttribPointerNV");
glLoadProgramNV = (PFNGLLOADPROGRAMNVPROC)
wglGetProcAddress("glLoadProgramNV");
glTrackMatrixNV = (PFNGLTRACKMATRIXNVPROC)
wglGetProcAddress("glTrackMatrixNV");


char * programString="!!VP1.0 \
DP4 o[HPOS].x, c[0], v[OPOS]; \
DP4 o[HPOS].y, c[1], v[OPOS]; \
DP4 o[HPOS].z, c[2], v[OPOS]; \
DP4 o[HPOS].w, c[3], v[OPOS]; \
MOV o[COL0], v[COL0]; \
END";

glGenProgramsNV(1, &amp;vertexProgram);
glBindProgramNV(GL_VERTEX_PROGRAM_NV, vertexProgram);
glLoadProgramNV(GL_VERTEX_PROGRAM_NV, vertexProgram, strlen(programString),
(const unsigned char *)programString);
glTrackMatrixNV(GL_VERTEX_PROGRAM_NV, 0, GL_MODELVIEW_PROJECTION_NV, GL_IDENTITY_NV);

//glVertexPointer(3, GL_FLOAT, 0, vertexPositions);
//glEnableClientState(GL_VERTEX_ARRAY);
glVertexAttribPointerNV(0, 3, GL_FLOAT, 0, vertexPositions);
glEnableClientState(GL_VERTEX_ATTRIB_ARRAY0_NV);
}

void display(void)
{
glEnable(GL_VERTEX_PROGRAM_NV);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_VERTEX_PROGRAM_NV);

glLoadIdentity();

glEnable(GL_VERTEX_PROGRAM_NV);

glTranslatef(0.0f, 0.0f, -5.0f);

static float angle=0.0f;
angle+=0.05f;
glRotatef(angle, 0.0f, 0.0f, 1.0f);

glDrawArrays(GL_QUADS, 0, 4);

glDisable(GL_VERTEX_PROGRAM_NV);

glFinish();
glutSwapBuffers();
glutPostRedisplay();
}

void reshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, 1.0f, 1.0f, 100.0f);
glMatrixMode(GL_MODELVIEW);
}

int main(int argc, char** argv)
{
glutInit(&amp;argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(256, 256);
glutCreateWindow(argv[0]);
init();

glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}


The program runs fine on my system, displaying a rotating quad as expected.
However, if I remove the Enable/Disable vertex program sandwiching glClear, it crashes the system. It works fine using standard "glVertexPointer" rather than "glVertexAttribPointer(0,"
Is this a driver bug, or have I made a mistake?


[This message has been edited by bakery2k (edited 11-17-2002).]

jra101
11-17-2002, 10:19 AM
Looks like a driver bug, I've filed a bug report on this so hopefully it should get fixed soon.

For now what you can do (and should be doing) is to call glVertexAttribPointerNV and glEnableClientState every frame before calling glDrawArrays instead of just doing it once in your init() function. If you do this the problem goes away.

bakery2k
11-17-2002, 01:03 PM
Originally posted by jra101:
Looks like a driver bug, I've filed a bug report on this so hopefully it should get fixed soon.


OK, Thank you.

pbrown
11-18-2002, 05:43 PM
bakery2k,

This does sound like a driver problem. I even found the bug report from jra101. :-)

One important thing to note is that even though vertex attributes alias in NV_vertex_program, vertex array state does not. So calling VertexAttrib3fv(0,v) and Vertex3f(v) produce identical results. However calling VertexAttribPointer(0,...) and VertexPointer(...) do not -- there is separate array state for generic and conventional attributes.

If your vertex attribute array enables match up with your arrays (as in your example), there generally shouldn't be a problem. The driver will pick the "correct" enabled arrays when VERTEX_PROGRAM is enabled, where generic attribute arrays have priority over their conventional "twins". But note that with NV_vertex_program, generic attribute arrays are ignored if you are not in program mode. In your example, if you rendered with VERTEX_PROGRAM disabled, nothing would happen because the conventional vertex array is disabled.

The ARB_vertex_program model is a little different, as explained below. This is probably way more information than you need, but hopefully it helps someone.

(1) Unlike NV_vertex_program, there is logically separate current state for generic vertex attributes and conventional attributes. glVertexAttrib(3,...) and glColor(...) refer to logically different state, unlike in NV_vertex_program.

(2) Aliasing is permitted, but not required. So if you call glVertexAttrib(3,...), the current color is now undefined. Similarly, if you call glColor(...), the current value for generic attribute 3 is undefined. In practice, one of two things happen -- either the corresponding state is unmodified, or it is changed a la NV_vertex_program.

(3) The previous two points allow different implementations to handle current state along the lines of their HW architecture. NVIDIA will alias state, ATI will apparently not.

(4) ARB_vertex_program rejects programs that refer to two pieces of possibly aliased state. So if your program uses both "vertex.attrib[3]" and "vertex.color", we will reject the program since the attributes' values may not be what you expect.

(5) Vertex attribute 0 and glVertex are "special" in that they have two functions: setting "position" and indicating that a vertex is done. These two calls should effectively alias, as in NV_vertex_program. Specifying vertex attribute 0 is equivalent to glVertex(). Don't try to set both for the same vertex, or you'll get two vertices!

(6) In the aliasing model, the call that gets in last "wins". This is no different from NV_vertex_program.

(7) There is still separate array state for generic and conventional attributes.

(8) When you call DrawElements, DrawArrays, ArrayElement, or friends, ALL enabled arrays are effectively sent ALL the time. Vertex array rendering is defined in terms of immediate mode, and all enabled arrays logically result in corresponding immediate mode calls. (The calls generally don't happen, but the results should be identical to those produced if they did.)

(9) Generic vertex attribute arrays are done last in ArrayElement, so they effectively "win".

(10) Since you don't want to send both generic attribute 0 and glVertex for each array element, only one of these logically results in an immediate mode call. The generic attribute 0 array always "wins" if both array are enabled.

Asgard
11-19-2002, 12:29 AM
Wow, Pat. Thanks for the detailed explanation http://www.opengl.org/discussion_boards/ubb/smile.gif I always thought the aliasing issue was not discussed detailed enough in the spec.
I just copy & pasted that at the end of my local copy of the ARB_v_p spec http://www.opengl.org/discussion_boards/ubb/wink.gif