PDA

View Full Version : ATI bug with separable + binary_retrievable progs



l_belev
11-21-2011, 07:56 AM
if a separable program object (with single shader) that was successfully linked and the shader detached is asked about it's GL_PROGRAM_BINARY_LENGTH, it returns 0.
If the shader was not detached, GL_PROGRAM_BINARY_LENGTH looks valid (not 0).

here is a minimal win32-based code that reproduces the bug:


#include <string.h>
#include <windows.h>
#include <GL/gl.h>
#include "glext.h"

void get_program_binary_test()
{
static const char fs_text[] =
"#version 330\n"
"#extension GL_ARB_separate_shader_objects : enable\n"
"layout(location = 0) out vec4 c0;\n"
"void main() {\n"
" c0 = vec4(0);\n"
"}\n";
const char *src = fs_text;
GLint len = sizeof(fs_text);
GLuint shader, prog;
GLenum status;
GLint bsize;

PFNGLCREATESHADERPROC _glCreateShader;
PFNGLSHADERSOURCEPROC _glShaderSource;
PFNGLCOMPILESHADERPROC _glCompileShader;
PFNGLGETSHADERIVPROC _glGetShaderiv;
PFNGLCREATEPROGRAMPROC _glCreateProgram;
PFNGLPROGRAMPARAMETERIPROC _glProgramParameteri;
PFNGLATTACHSHADERPROC _glAttachShader;
PFNGLLINKPROGRAMPROC _glLinkProgram;
PFNGLDETACHSHADERPROC _glDetachShader;
PFNGLGETPROGRAMIVPROC _glGetProgramiv;

*(void **)&amp;_glCreateShader = (void *)wglGetProcAddress("glCreateShader");
*(void **)&amp;_glShaderSource = (void *)wglGetProcAddress("glShaderSource");
*(void **)&amp;_glCompileShader = (void *)wglGetProcAddress("glCompileShader");
*(void **)&amp;_glGetShaderiv = (void *)wglGetProcAddress("glGetShaderiv");
*(void **)&amp;_glCreateProgram = (void *)wglGetProcAddress("glCreateProgram");
*(void **)&amp;_glProgramParameteri = (void *)wglGetProcAddress("glProgramParameteri");
*(void **)&amp;_glAttachShader = (void *)wglGetProcAddress("glAttachShader");
*(void **)&amp;_glLinkProgram = (void *)wglGetProcAddress("glLinkProgram");
*(void **)&amp;_glDetachShader = (void *)wglGetProcAddress("glDetachShader");
*(void **)&amp;_glGetProgramiv = (void *)wglGetProcAddress("glGetProgramiv");

shader = _glCreateShader(GL_FRAGMENT_SHADER);
_glShaderSource(shader, 1, &amp;src, &amp;len);
_glCompileShader(shader);
_glGetShaderiv(shader, GL_COMPILE_STATUS, &amp;status);
if (status == GL_FALSE) _asm int 3

prog = _glCreateProgram();
_glProgramParameteri(prog, GL_PROGRAM_SEPARABLE, GL_TRUE);
_glProgramParameteri(prog, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE);
_glAttachShader(prog, shader);
_glLinkProgram(prog);
_glDetachShader(prog, shader); // if this is commented out the program binary length is not 0
_glGetProgramiv(prog, GL_LINK_STATUS, &amp;status);
if (status == GL_FALSE) _asm int 3

_glGetProgramiv(prog, GL_PROGRAM_BINARY_LENGTH, &amp;bsize);
if (bsize == 0) _asm int 3 // bug!!!!
}

LRESULT CALLBACK wnd_proc(HWND wnd, UINT msg, WPARAM wp, LPARAM lp)
{
switch (msg) {
case WM_NCCREATE: return 1;
case WM_PAINT: ValidateRect(wnd, NULL);
default: return 0;
}
}

int CALLBACK WinMain(HINSTANCE inst, HINSTANCE prev_inst, char *cl, int cs)
{
WNDCLASSA wc;
HWND wnd;
HDC dc;
PIXELFORMATDESCRIPTOR pfd;
int pf;
HGLRC rc;

memset(&amp;wc, 0, sizeof(wc));
wc.hInstance = inst;
wc.lpfnWndProc = wnd_proc;
wc.lpszClassName = "_test_class_name";
RegisterClassA(&amp;wc);
wnd = CreateWindowExA(0, wc.lpszClassName, NULL, WS_POPUP, 0, 0, 64, 32, NULL, NULL, NULL, NULL);
dc = GetDC(wnd);
memset(&amp;pfd, 0, sizeof(pfd));
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DEPTH_DO NTCARE;
pf = ChoosePixelFormat(dc, &amp;pfd);
SetPixelFormat(dc, pf, NULL);
rc = wglCreateContext(dc);
wglMakeCurrent(dc, rc);

get_program_binary_test();

return 0;
}

l_belev
11-28-2011, 05:23 AM
actually this is not related to the separate shaders, it happens with non-separable too

it's just that GL_PROGRAM_BINARY_LENGTH for a successfully linked program object is zero if the shader objects were already detached.

This is definitely a bug since GL_PROGRAM_BINARY_LENGTH has nothing to do with any attached shaders, it only depends on whether the program is successfully linked or not.

A possible workaround would be to keep the shaders attached unless that messes up the application structure too much