I have recently encountered an annoying crash problem when using GL_LINEAR_MIPMAP_LINEAR filter to sample texture image(only with my ATI card, my nVidia card works fine), to demonstrate this problem I wrote a sample program to reproduce it, the code snippet is listed below:
static char *g_vertexShader =
"#version 150
"
"uniform mat4 mvp;
"
"in vec2 vertex;
"
"in vec2 texCoord;
"
"out vec2 fragTexCoord;
"
"void main()
"
"{
"
"fragTexCoord = texCoord;
"
"gl_Position = mvp * vec4(vertex, 0, 1);
"
"}
";
static char *g_fragmentShader =
"#version 150
"
"uniform sampler2D texSampler;
"
"in vec2 fragTexCoord;
"
"out vec4 fragColor;
"
"void main()
"
"{
"
"fragColor = texture(texSampler, fragTexCoord);
"
"}
";
struct SVertex {
GLfloat x, y;
GLfloat s, t;
};
static void crash()
{
//
// prepare shader program
//
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
GLint shaderLen = -1;
glShaderSource(vertexShader, 1, (const GLchar **)&g_vertexShader, &shaderLen);
glCompileShader(vertexShader);
GLint compileStatus = GL_FALSE;
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &compileStatus);
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, (const GLchar **)&g_fragmentShader, &shaderLen);
glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &compileStatus);
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
GLint linkStatus = GL_FALSE;
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &linkStatus);
//
// create VAO
//
GLuint vao = 0;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
//
// create VBO
//
GLuint vbo = 0;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
SVertex vtx[4];
vtx[0].x = 0;
vtx[0].y = 1;
vtx[0].s = 0;
vtx[0].t = 1;
vtx[1].x = 0;
vtx[1].y = 0;
vtx[1].s = 0;
vtx[1].t = 0;
vtx[2].x = 1;
vtx[2].y = 1;
vtx[2].s = 1;
vtx[2].t = 1;
vtx[3].x = 1;
vtx[3].y = 0;
vtx[3].s = 1;
vtx[3].t = 0;
glBufferData(GL_ARRAY_BUFFER, sizeof(SVertex) * 4, vtx, GL_STATIC_DRAW);
GLint attribIdx;
attribIdx = glGetAttribLocation(shaderProgram, "vertex");
glEnableVertexAttribArray(attribIdx);
glVertexAttribPointer(attribIdx, 2, GL_FLOAT, GL_TRUE, sizeof(GLfloat) * 4, (const GLvoid *)0);
attribIdx = glGetAttribLocation(shaderProgram, "texCoord");
glEnableVertexAttribArray(attribIdx);
glVertexAttribPointer(attribIdx, 2, GL_FLOAT, GL_TRUE, sizeof(GLfloat) * 4, (const GLvoid *)(sizeof(GLfloat) * 2));
glBindBuffer(GL_ARRAY_BUFFER, 0);
//
// create FBO
//
GLuint fbo = 0;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
//
// create textures
//
GLuint tex[2] = {0, 0};
glGenTextures(2, tex);
glBindTexture(GL_TEXTURE_2D, tex[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1920, 1080, 0, GL_BGRA, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
glBindTexture(GL_TEXTURE_2D, tex[1]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1920, 1080, 0, GL_BGRA, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D, 0);
glViewport(0, 0, 1920, 1080);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex[0], 0);
glClearColor(1, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex[0]);
glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glUseProgram(shaderProgram);
//
// setup uniform
//
GLint uniformLoc = glGetUniformLocation(shaderProgram, "mvp");
// model/view/projection matrix
GLfloat matUniform[16] = {2, 0, 0, 0, 0, 2, 0, 0, 0, 0, -1, 0, -1, -1, 0, 1};
glUniformMatrix4fv(uniformLoc, 1, GL_FALSE, matUniform);
uniformLoc = glGetUniformLocation(shaderProgram, "texSampler");
glUniform1i(uniformLoc, 0);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex[1], 0);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); // crash in this line!
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
glUseProgram(0);
glBindTexture(GL_TEXTURE_2D, 0);
glDeleteTextures(2, tex);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glDeleteFramebuffers(1, &fbo);
glDeleteBuffers(1, &vbo);
glBindVertexArray(0);
glDeleteVertexArrays(1, &vao);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glDeleteProgram(shaderProgram);
}
I run this code in windows 7 x64 and I have an ATI radeon 5770 card with catalyst 11.8 driver installed in my system, It will crash in
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
But this code works fine in my nVidia card. This crash will NOT happen if I don’t use a FBO to draw to the first texture which I will sample later or if I don’t set its filter mode to GL_LINEAR_MIPMAP_LINEAR. Is anything wrong with my code ?