Driver update: Strange jitter effect with geometry shader

Hi,

for visualizing tetrahedra, I’ve implemented a geometry shader that uses the four indices of GL_LINES_ADJACENCY_EXT to represent and to render one tetrahedron. In the geometry shader I use this information to generate four triangles that represent the boundary of the scaled element.

This worked fine, till the driver update from version 306.97 to 310.7: There, a strange jitter effect came up, which looks like the triangles are bouncing.
This bug is also present with the latest drivers. I tested it on several nVidia cards (Geforce GTX 590, GTX 680, GTX 560Ti …) with same result, but on an ATI/AMD card it is working fine.

Am I doing something, or is it a driver problem? Can someone please have a look into this?

Please find a minimal sample code below. Remark: If you change the value of tetScale to 1.0 the rendering is fine. If you need additional information, please let me know. I could also provide a video showing the effect.

Best regards, thank you!
Daniel

Code:

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#define STRINGIFY(A) #A

static const char * vsCode = STRINGIFY
(

void main()
{
gl_Position = ftransform();
}

);

static const char *fsCode = STRINGIFY
(

void main()
{
	gl_FragColor = vec4(0.5,0.5,0.5,1.0);
}

);

extern const char *gsCode = STRINGIFY
(
#version 120\n
#extension GL_EXT_geometry_shader4 : enable \n

void main()
{
//float tetScale = 1.0;
float tetScale = 0.5;
vec4 vertices[4];
vec4 baryCenter;
for(int i = 0; i < 4; ++i)
{
vertices[i] = gl_PositionIn[i];
baryCenter += vertices[i];
}
baryCenter *= 0.25;
for(int i = 0; i < 4; ++i)
{
vertices[i] = tetScale * vertices[i] + (1.0 - tetScale) * baryCenter;
}

for(int i = 0; i < 4; ++i)
{
	for(int j = 0; j < 3; ++j)
	{
		int modJ = (i % 2 == 1) ? j : 2 - j;
		int index = (i + modJ) % 4;
		gl_Position = vertices[index];
		EmitVertex();	
	}
	EndPrimitive();
}
EndPrimitive();

}
);

GLuint compileProgram(const char *vsource, const char *fsource, const char *gsource)
{

if(GLEW_EXT_geometry_shader4)
{
	GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
	GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
	GLuint geometryShader = glCreateShader(GL_GEOMETRY_SHADER_EXT);

	glShaderSource(vertexShader, 1, &vsource, 0);
	glShaderSource(fragmentShader, 1, &fsource, 0);
	glShaderSource(geometryShader, 1, &gsource, 0);

	glCompileShader(vertexShader);
	glCompileShader(fragmentShader);
	glCompileShader(geometryShader);

	GLuint program = glCreateProgram();

	int error = glGetError();
	glProgramParameteriEXT( program, GL_GEOMETRY_INPUT_TYPE_EXT, GL_LINES_ADJACENCY_EXT);
	error = glGetError();
	glProgramParameteriEXT( program, GL_GEOMETRY_OUTPUT_TYPE_EXT, GL_TRIANGLES);
	error = glGetError();
	glProgramParameteriEXT( program, GL_GEOMETRY_VERTICES_OUT_EXT, 12);
	error = glGetError();

	glAttachShader(program, vertexShader);
	glAttachShader(program, fragmentShader);
	glAttachShader(program, geometryShader);

	glLinkProgram(program);

	glDeleteShader(vertexShader);		// just flagged for deletion
	glDeleteShader(fragmentShader);
	glDeleteShader(geometryShader);

	// check if program linked
	GLint success = 0;
	glGetProgramiv(program, GL_LINK_STATUS, &success);

	if (!success) 
	{   
		glDeleteProgram(program);
		program = 0;
	}
	return program;
}
else
	return 0;

}

int main(void)
{
GLFWwindow* window;

/* Initialize the library */
if (!glfwInit())
    return -1;

/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(640, 480, "TetViewer", NULL, NULL);
if (!window)
{
    glfwTerminate();
    return -1;
}

/* Make the window's context current */
glfwMakeContextCurrent(window);
glewInit();
GLuint tetShaderID = compileProgram(vsCode, fsCode, gsCode);
glUseProgram(tetShaderID);

/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
    /* Render here */
	glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ); //clear background screen to black
	//Clear information from last draw
	glClear( GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);
	glMatrixMode(GL_MODELVIEW); //Switch to the drawing perspective
	glLoadIdentity(); //Reset the drawing perspective			
	glScalef(0.5,0.5,0.5);
	glTranslatef(-0.5,-0.5,0);

	glBegin(GL_LINES_ADJACENCY_EXT);
		glVertex3f(0, 0, 0); 
		glVertex3f(0, 0, 1); 
		glVertex3f(0, 1, 0); 
		glVertex3f(1, 0, 0); 
    glEnd();

    /* Swap front and back buffers */
    glfwSwapBuffers(window);
    /* Poll for and process events */
    glfwPollEvents();
}


glfwDestroyWindow(window);
glfwTerminate();
return 0;

}

Hi Daniel,

that’s a bug in your shader.

vec4 baryCenter; // => Missing initialization
for(int i = 0; i < 4; ++i)
{
  vertices[i] = gl_PositionIn[i];
  baryCenter += vertices[i]; // => Warning "baryCenter used without being initialized". 
  ...

I’ve sent code to your colleague which would have caught this along with some other optimization hints.