Skip to content

Instantly share code, notes, and snippets.

Created December 7, 2013 03:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/7837036 to your computer and use it in GitHub Desktop.
Save anonymous/7837036 to your computer and use it in GitHub Desktop.
Minimal code example to re-produce a glGenerateTextureMipmapEXT related bug found in the AMD OpenGL driver.
// Minimal code example to re-produce a bug found in the AMD OpenGL driver.
// The problem occurs when using glGenerateTextureMipmapEXT in conjunction
// with glTextureStorage2DEXT, which results in no mip maps being generated
// and no errors being captured by glGetError or ARB_debug_output.
// This program should produce a red screen if there is no driver bug.
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define GLSL(src) "#version 430 core\n" #src
enum VERTEX_ATTRIB
{
POSITION_ATTRIB,
TEXCOORD_ATTRIB
};
void debug_callback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *msg, GLvoid *data)
{
printf("OpenGL debug: %s\n", msg);
}
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
}
void init_debug()
{
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
glDebugMessageCallback(debug_callback, NULL);
glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
const char debug_message[] = "Debug output enabled.";
glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_OTHER, 0, GL_DEBUG_SEVERITY_LOW, sizeof(debug_message), debug_message);
}
GLuint create_program(const char *vertex_source, const char *fragment_source)
{
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, &vertex_source, NULL);
glCompileShader(vs);
unsigned int fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, &fragment_source, NULL);
glCompileShader(fs);
GLuint shader_program = glCreateProgram();
glAttachShader(shader_program, fs);
glAttachShader(shader_program, vs);
glLinkProgram(shader_program);
return shader_program;
}
const char* vertex_shader = GLSL(
layout(location = 0) in vec3 vertex_position;
layout(location = 1) in vec2 vertex_tex_coord;
out vec2 tex_coord;
void main()
{
tex_coord = vertex_tex_coord;
gl_Position = vec4(vertex_position, 1.0);
}
);
const char* fragment_shader = GLSL(
layout(location = 0) uniform sampler2D texture;
in vec2 tex_coord;
out vec4 frag_color;
void main()
{
frag_color = textureLod(texture, tex_coord, tex_coord.x * 9.0);
}
);
int main(int argc, char *argv[])
{
if(!glfwInit())
exit(EXIT_FAILURE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);
GLFWwindow* window = glfwCreateWindow(512, 512, "OpenGL", NULL, NULL);
if(!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwSetKeyCallback(window, key_callback);
glfwMakeContextCurrent(window);
GLenum glewError = glewInit();
if(glewError != GLEW_OK)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
printf("OpenGL version: %s\n", glGetString(GL_VERSION));
init_debug();
float position[] =
{
1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
-1.0f, -1.0f, 0.0f
};
float texcoord[] =
{
1.0f, 0.0f,
0.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f
};
unsigned short indices[] =
{
1, 0, 2,
3, 1, 2
};
GLuint index_buffer = 0;
GLuint vertex_buffers[2] = {0};
glGenBuffers(1, &index_buffer);
glGenBuffers(2, vertex_buffers);
glNamedBufferDataEXT(index_buffer, sizeof(indices), &indices, GL_STATIC_DRAW);
glNamedBufferDataEXT(vertex_buffers[POSITION_ATTRIB], sizeof(position), &position, GL_STATIC_DRAW);
glNamedBufferDataEXT(vertex_buffers[TEXCOORD_ATTRIB], sizeof(texcoord), &texcoord, GL_STATIC_DRAW);
GLuint vao = 0;
glGenVertexArrays(1, &vao);
glVertexArrayVertexAttribOffsetEXT(vao, vertex_buffers[POSITION_ATTRIB], POSITION_ATTRIB, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexArrayAttribEXT(vao, POSITION_ATTRIB);
glVertexArrayVertexAttribOffsetEXT(vao, vertex_buffers[TEXCOORD_ATTRIB], TEXCOORD_ATTRIB, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexArrayAttribEXT(vao, TEXCOORD_ATTRIB);
glBindVertexArray(vao);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
GLuint shader_program = create_program(vertex_shader, fragment_shader);
glUseProgram(shader_program);
glProgramUniform1i(shader_program, 0, 0);
// Set up a buffer for an all red 512x512 RBGA image
unsigned int* image_buffer = (unsigned int*)malloc(512*512*4);
unsigned int i;
for(i = 0; i < 512*512; i++)
image_buffer[i] = 0xFF0000FF;
/* ######################## HERE BE DRAGONS ######################## */
GLuint texture = 0;
glGenTextures(1, &texture);
glTextureStorage2DEXT(texture, GL_TEXTURE_2D, 10, GL_RGBA8, 512, 512);
glTextureSubImage2DEXT(texture, GL_TEXTURE_2D, 0, 0, 0, 512, 512, GL_RGBA, GL_UNSIGNED_BYTE, image_buffer);
// if we add glBindTexture(GL_TEXTURE_2D, texture); here it will work for some odd reason
glGenerateTextureMipmapEXT(texture, GL_TEXTURE_2D);
glBindMultiTextureEXT(GL_TEXTURE0, GL_TEXTURE_2D, texture);
/* ######################## HERE BE DRAGONS ######################## */
free(image_buffer);
GLuint trilinear = 0;
glGenSamplers(1, &trilinear);
glSamplerParameteri(trilinear, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glSamplerParameteri(trilinear, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glSamplerParameteri(trilinear, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glSamplerParameteri(trilinear, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindSampler(0, trilinear);
while(!glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, NULL);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment