Skip to content

Instantly share code, notes, and snippets.

@rygorous
Created February 11, 2023 00:22
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 rygorous/346f0c30b3cb096c6370050d07ce475e to your computer and use it in GitHub Desktop.
Save rygorous/346f0c30b3cb096c6370050d07ce475e to your computer and use it in GitHub Desktop.
Old bug repros from 2014.
#include <stdio.h>
#include <stdlib.h>
#include <GL/gl3w.h>
#include "util.h"
#include "radglx.h"
#define CHECK_RESULTS // turn this off and we'll keep running until the driver crashes.
#define MIN_ALIGN 1 // setting this to 128 (or higher) fixes the bug (both incorrect results and crash)
typedef unsigned char U8;
static GLuint mk_tex_bind( GLenum target )
{
GLuint tex;
glGenTextures( 1, &tex );
glBindTexture( target, tex );
return tex;
}
static GLuint make_gl_tex( GLenum internalformat, GLsizei w, GLsizei h )
{
GLuint tex = mk_tex_bind( GL_TEXTURE_2D );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1 );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
glTexStorage2D( GL_TEXTURE_2D, 1, internalformat, w, h );
return tex;
}
static GLuint make_gl_tex_buf_range( GLuint buffer, GLenum internalformat, GLintptr offset, GLsizeiptr size )
{
GLuint tex = mk_tex_bind( GL_TEXTURE_BUFFER );
glTexBufferRange( GL_TEXTURE_BUFFER, internalformat, buffer, offset, size );
return tex;
}
static const char shader_code[] =
"#version 430 core\n"
"layout(local_size_x=16, local_size_y=16) in;\n"
"layout(binding=0, r8ui) uniform uimage2D o_img;\n"
"void main() {\n"
" imageStore(o_img, ivec2(gl_GlobalInvocationID.xy), uvec4(128));\n"
"}\n";
int main(int argc, char **argv)
{
// Init GL
glx_context * glx = glx_init( "gl_bug", 512, 512 );
// Create our textures
GLuint tex_out = make_gl_tex( GL_R8UI, 8, 8 );
// Determine texture buffer offset alignment and print it
GLint gl_align;
glGetIntegerv( GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT, &gl_align );
printf( "align=%d\n", gl_align );
if ( gl_align < MIN_ALIGN )
gl_align = MIN_ALIGN;
// Create a buffer and corresponding texture buffer.
// Note we specify "gl_align" (i.e. TEXTURE_BUFFER_OFFSET_ALIGNMENT) as offset;
// this should be fine.
GLuint dc_buf = glx_make_buffer( GL_TEXTURE_BUFFER, 64 * 1024, NULL, GL_DYNAMIC_COPY );
GLuint dc_tex = make_gl_tex_buf_range( dc_buf, GL_R16I, gl_align, 1024 );
// Create block programs
GLuint test_prog = glx_compute_program_source( shader_code );
if ( !test_prog )
return 1;
int frame = 0;
while ( glx_handle_events( glx, false ) )
{
glUseProgram( test_prog );
glBindImageTexture( 0, tex_out, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R8UI );
// comment out the next line (unused image unit!) and the bug disappears
glBindImageTexture( 1, dc_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R16I );
glDispatchCompute( 1, 1, 1 );
// make sure texture changes are visible.
glMemoryBarrier( GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_TEXTURE_FETCH_BARRIER_BIT );
glx_swap_buffers( glx );
#ifdef CHECK_RESULTS
U8 * gpu_out = (U8 *)glx_read_texture_level( tex_out, 0 );
int offs;
bool ok = true;
// check against reference
for ( offs = 0 ; offs < 64 ; offs++ )
{
if ( gpu_out[offs] != 128 )
{
printf( "mismatch at offs=%d: is %d, should be 128.\n", offs, gpu_out[offs] );
ok = false;
break;
}
}
free( gpu_out );
if ( !ok )
break;
#endif
if ( ++frame >= 1000 )
break;
}
// clean up
glUseProgram( 0 );
glDeleteBuffers( 1, &dc_buf );
glDeleteTextures( 1, &tex_out );
glDeleteTextures( 1, &dc_tex );
glDeleteProgram( test_prog );
printf("exiting...\n");
glx_shutdown( glx );
return 0;
}
// vim:et:sw=4
// @cdep pre $DefaultsConsoleGL
// @cdep post $BuildConsoleGL( , )
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment