PDA

View Full Version : Serious bug in 8178 driver


undo
02-01-06, 01:22 AM
Hi everybody

I found a serious bug in the 8178 driver that makes it impossible to use my GPU for many general purporse calculations under FreeBSD :(.

What I need to do is to create a framebuffer object (via the "EXT_framebuffer_object" extension, supported by the current driver) and attach a texture of unclamped floating point numbers to it (available via the "NV_float_buffer", "ATI_texture_float" and "ARB_texture_float" extensions, all three of which are supported by the driver).

Unfortunately, every available type of unclamped floating point texture, when attached to a FBO, leads to an error. I have written a little program that, when run, tries all the combinations I can think of and reports whether the driver accepted them or not:

#include <stdio.h>
#include <GL/glew.h>
#include <GL/glut.h>

bool openGLStatus() {
printf(" GL Status: ");

GLenum status = (GLenum)glGetError();
switch(status) {
case GL_NO_ERROR:
printf("OK\n");
return true;
case GL_INVALID_ENUM:
printf("GL_INVALID_ENUM\n");
break;
case GL_INVALID_VALUE:
printf("GL_INVALID_VALUE\n");
break;
case GL_INVALID_OPERATION:
printf("GL_INVALID_OPERATION\n");
break;
case GL_STACK_OVERFLOW:
printf("GL_STACK_OVERFLOW\n");
break;
case GL_STACK_UNDERFLOW:
printf("GL_STACK_UNDERFLOW\n");
break;
case GL_OUT_OF_MEMORY:
printf("GL_OUT_OF_MEMORY\n");
break;
case GL_INVALID_FRAMEBUFFER_OPERATION_EXT:
printf("GL_INVALID_FRAMEBUFFER_OPERATION_EXT\n");
break;
default:
printf("UNKNWON\n");
}

return false;
}

void framebufferStatus() {
printf(" FB Status: ");

GLenum status = (GLenum)glCheckFramebufferStatusEXT(GL_FRAMEBUFFER _EXT);
switch(status) {
case GL_FRAMEBUFFER_COMPLETE_EXT:
printf("<<<< OK >>>>\n");
break;
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
printf("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT\n");
break;
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
printf("GL_FRAMEBUFFER_UNSUPPORTED_EXT\n");
break;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
printf("GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT\n");
break;
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
printf("GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT\n");
break;
case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
printf("GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT\n");
break;
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
printf("GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT\n");
break;
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
printf("GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT\n");
break;
default:
printf("UNKNWON\n");
}
}

void checkComponents(GLenum target, GLint wrap, GLenum format, GLint components) {
// Allocate and bind an OpenGL texture
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(target, texture);

// Set interpolation function to nearest-neighbor
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

// Set desired wrapping type
glTexParameteri(target, GL_TEXTURE_WRAP_S, wrap);
glTexParameteri(target, GL_TEXTURE_WRAP_T, wrap);

// Set texture format and component count
glTexImage2D(target, 0, components, 16, 16, 0, format, GL_FLOAT, 0);

// Check and show the OpenGL status; if no errors occured so far...
if (openGLStatus()) {
// Allocate and bind a framebuffer object
GLuint framebuffer;
glGenFramebuffersEXT(1, &framebuffer);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer);

// Attempt to attach the texture to the framebuffer object
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, target, texture, 0);

// Check and show the framebuffer status
framebufferStatus();

// Detach the texture from the framebuffer object
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, 0, 0, 0);

// Free the framebuffer object
glDeleteFramebuffersEXT(1, &framebuffer);
}

// Free the OpenGL texture
glDeleteTextures(1, &texture);
}

void checkFormat(GLenum target, GLint wrap, GLenum format) {
printf(" Components: GL_FLOAT_R32_NV\n");
checkComponents(target, wrap, format, GL_FLOAT_R32_NV);
printf(" Components: GL_LUMINANCE_FLOAT32_ATI\n");
checkComponents(target, wrap, format, GL_LUMINANCE_FLOAT32_ATI);
printf(" Components: GL_LUMINANCE32F_ARB\n");
checkComponents(target, wrap, format, GL_LUMINANCE32F_ARB);
}

void checkFormat(GLenum target, GLint wrap) {
printf(" Components: GL_FLOAT_RGBA32_NV\n");
checkComponents(target, wrap, GL_RGBA, GL_FLOAT_RGBA32_NV);
printf(" Components: GL_RGBA_FLOAT32_ATI\n");
checkComponents(target, wrap, GL_RGBA, GL_RGBA_FLOAT32_ATI);
printf(" Components: GL_RGBA32F_ARB\n");
checkComponents(target, wrap, GL_RGBA, GL_RGBA32F_ARB);
printf(" Components: GL_RGBA\n");
checkComponents(target, wrap, GL_RGBA, GL_RGBA);
}

void checkWrap(GLenum target, GLint wrap) {
printf(" Format: GL_LUMINANCE\n");
checkFormat(target, wrap, GL_LUMINANCE);
printf(" Format: GL_RED\n");
checkFormat(target, wrap, GL_RED);
printf(" Format: GL_RGBA\n");
checkFormat(target, wrap);
}

void checkTarget(GLenum target) {
printf(" Wrap: GL_CLAMP\n");
checkWrap(target, GL_CLAMP);
printf(" Wrap: GL_CLAMP_TO_EDGE\n");
checkWrap(target, GL_CLAMP_TO_EDGE);
}

int main(int argumentCount, char **arguments) {
glutInit (&argumentCount, arguments);
glutCreateWindow("");
glewInit();

// Clear OpenGL errors
glGetError();

printf("Target: GL_TEXTURE_RECTANGLE_NV\n");
checkTarget(GL_TEXTURE_RECTANGLE_NV);
printf("Target: GL_TEXTURE_RECTANGLE_ARB\n");
checkTarget(GL_TEXTURE_RECTANGLE_ARB);
printf("Target: GL_TEXTURE_2D\n");
checkTarget(GL_TEXTURE_2D);

return 0;
}

It can be compiled (on FreeBSD) using:

g++ -I/usr/X11R6/include -L/usr/X11R6/include -lGLEW -lglut -o fbo_test fbo_test.cc

On my i386 system running 6-STABLE and equipped with a 6600 GT card, the program's output is:

Target: GL_TEXTURE_RECTANGLE_NV
Wrap: GL_CLAMP
Format: GL_LUMINANCE
Components: GL_FLOAT_R32_NV
GL Status: OK
FB Status: GL_FRAMEBUFFER_UNSUPPORTED_EXT
Components: GL_LUMINANCE_FLOAT32_ATI
GL Status: GL_INVALID_ENUM
Components: GL_LUMINANCE32F_ARB
GL Status: OK
FB Status: GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT
Format: GL_RED
Components: GL_FLOAT_R32_NV
GL Status: GL_INVALID_ENUM
Components: GL_LUMINANCE_FLOAT32_ATI
GL Status: OK
FB Status: GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT
Components: GL_LUMINANCE32F_ARB
GL Status: GL_INVALID_ENUM
Format: GL_RGBA
Components: GL_FLOAT_RGBA32_NV
GL Status: OK
FB Status: GL_FRAMEBUFFER_UNSUPPORTED_EXT
Components: GL_RGBA_FLOAT32_ATI
GL Status: GL_INVALID_ENUM
Components: GL_RGBA32F_ARB
GL Status: OK
FB Status: GL_FRAMEBUFFER_UNSUPPORTED_EXT
Components: GL_RGBA
GL Status: GL_INVALID_ENUM
Wrap: GL_CLAMP_TO_EDGE
Format: GL_LUMINANCE
Components: GL_FLOAT_R32_NV
GL Status: OK
FB Status: GL_FRAMEBUFFER_UNSUPPORTED_EXT
Components: GL_LUMINANCE_FLOAT32_ATI
GL Status: GL_INVALID_ENUM
Components: GL_LUMINANCE32F_ARB
GL Status: OK
FB Status: GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT
Format: GL_RED
Components: GL_FLOAT_R32_NV
GL Status: GL_INVALID_ENUM
Components: GL_LUMINANCE_FLOAT32_ATI
GL Status: OK
FB Status: GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT
Components: GL_LUMINANCE32F_ARB
GL Status: GL_INVALID_ENUM
Format: GL_RGBA
Components: GL_FLOAT_RGBA32_NV
GL Status: OK
FB Status: GL_FRAMEBUFFER_UNSUPPORTED_EXT
Components: GL_RGBA_FLOAT32_ATI
GL Status: GL_INVALID_ENUM
Components: GL_RGBA32F_ARB
GL Status: OK
FB Status: GL_FRAMEBUFFER_UNSUPPORTED_EXT
Components: GL_RGBA
GL Status: GL_INVALID_ENUM
Target: GL_TEXTURE_RECTANGLE_ARB
Wrap: GL_CLAMP
Format: GL_LUMINANCE
Components: GL_FLOAT_R32_NV
GL Status: OK
FB Status: GL_FRAMEBUFFER_UNSUPPORTED_EXT
Components: GL_LUMINANCE_FLOAT32_ATI
GL Status: GL_INVALID_ENUM
Components: GL_LUMINANCE32F_ARB
GL Status: OK
FB Status: GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT
Format: GL_RED
Components: GL_FLOAT_R32_NV
GL Status: GL_INVALID_ENUM
Components: GL_LUMINANCE_FLOAT32_ATI
GL Status: OK
FB Status: GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT
Components: GL_LUMINANCE32F_ARB
GL Status: GL_INVALID_ENUM
Format: GL_RGBA
Components: GL_FLOAT_RGBA32_NV
GL Status: OK
FB Status: GL_FRAMEBUFFER_UNSUPPORTED_EXT
Components: GL_RGBA_FLOAT32_ATI
GL Status: GL_INVALID_ENUM
Components: GL_RGBA32F_ARB
GL Status: OK
FB Status: GL_FRAMEBUFFER_UNSUPPORTED_EXT
Components: GL_RGBA
GL Status: GL_INVALID_ENUM
Wrap: GL_CLAMP_TO_EDGE
Format: GL_LUMINANCE
Components: GL_FLOAT_R32_NV
GL Status: OK
FB Status: GL_FRAMEBUFFER_UNSUPPORTED_EXT
Components: GL_LUMINANCE_FLOAT32_ATI
GL Status: GL_INVALID_ENUM
Components: GL_LUMINANCE32F_ARB
GL Status: OK
FB Status: GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT
Format: GL_RED
Components: GL_FLOAT_R32_NV
GL Status: GL_INVALID_ENUM
Components: GL_LUMINANCE_FLOAT32_ATI
GL Status: OK
FB Status: GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT
Components: GL_LUMINANCE32F_ARB
GL Status: GL_INVALID_ENUM
Format: GL_RGBA
Components: GL_FLOAT_RGBA32_NV
GL Status: OK
FB Status: GL_FRAMEBUFFER_UNSUPPORTED_EXT
Components: GL_RGBA_FLOAT32_ATI
GL Status: GL_INVALID_ENUM
Components: GL_RGBA32F_ARB
GL Status: OK
FB Status: GL_FRAMEBUFFER_UNSUPPORTED_EXT
Components: GL_RGBA
GL Status: GL_INVALID_ENUM
Target: GL_TEXTURE_2D
Wrap: GL_CLAMP
Format: GL_LUMINANCE
Components: GL_FLOAT_R32_NV
GL Status: GL_INVALID_OPERATION
Components: GL_LUMINANCE_FLOAT32_ATI
GL Status: OK
FB Status: GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT
Components: GL_LUMINANCE32F_ARB
GL Status: GL_INVALID_ENUM
Format: GL_RED
Components: GL_FLOAT_R32_NV
GL Status: GL_INVALID_OPERATION
Components: GL_LUMINANCE_FLOAT32_ATI
GL Status: OK
FB Status: GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT
Components: GL_LUMINANCE32F_ARB
GL Status: GL_INVALID_ENUM
Format: GL_RGBA
Components: GL_FLOAT_RGBA32_NV
GL Status: GL_INVALID_OPERATION
Components: GL_RGBA_FLOAT32_ATI
GL Status: OK
FB Status: GL_FRAMEBUFFER_UNSUPPORTED_EXT
Components: GL_RGBA32F_ARB
GL Status: GL_INVALID_ENUM
Components: GL_RGBA
GL Status: OK
FB Status: <<<< OK >>>>
Wrap: GL_CLAMP_TO_EDGE
Format: GL_LUMINANCE
Components: GL_FLOAT_R32_NV
GL Status: GL_INVALID_ENUM
Components: GL_LUMINANCE_FLOAT32_ATI
GL Status: OK
FB Status: GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT
Components: GL_LUMINANCE32F_ARB
GL Status: GL_INVALID_ENUM
Format: GL_RED
Components: GL_FLOAT_R32_NV
GL Status: GL_INVALID_OPERATION
Components: GL_LUMINANCE_FLOAT32_ATI
GL Status: OK
FB Status: GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT
Components: GL_LUMINANCE32F_ARB
GL Status: GL_INVALID_ENUM
Format: GL_RGBA
Components: GL_FLOAT_RGBA32_NV
GL Status: GL_INVALID_OPERATION
Components: GL_RGBA_FLOAT32_ATI
GL Status: OK
FB Status: GL_FRAMEBUFFER_UNSUPPORTED_EXT
Components: GL_RGBA32F_ARB
GL Status: GL_INVALID_ENUM
Components: GL_RGBA
GL Status: OK
FB Status: <<<< OK >>>>

As you see, the only case in which the attach results in "<<<< OK >>>>" is when I use a texture with internal format GL_RGBA. However, this is not an unclamped floating point type.

On the *same* machine, under Kubuntu GNU/Linux and using the 8178 driver as well, I get many combinations that work. So clearly, this is a bug in the FreeBSD driver. It is a *serious* bug because many GPGPU algorithms depend on multipass rendering into floating point textures. I myself need this for my thesis and am forced to switch to Linux until this is fixed :(.

The only other version of the driver available directly from ports is 7174 - but this version is so old that it does not support the "EXT_framebuffer_object", so it is of no use in this case.