ATI bug with separable + binary_retrievable progs

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
"
		"#extension GL_ARB_separate_shader_objects : enable
"
		"layout(location = 0) out vec4 c0;
"
		"void main() {
"
		"	c0 = vec4(0);
"
		"}
";
	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 **)&_glCreateShader = (void *)wglGetProcAddress("glCreateShader");
	*(void **)&_glShaderSource = (void *)wglGetProcAddress("glShaderSource");
	*(void **)&_glCompileShader = (void *)wglGetProcAddress("glCompileShader");
	*(void **)&_glGetShaderiv = (void *)wglGetProcAddress("glGetShaderiv");
	*(void **)&_glCreateProgram = (void *)wglGetProcAddress("glCreateProgram");
	*(void **)&_glProgramParameteri = (void *)wglGetProcAddress("glProgramParameteri");
	*(void **)&_glAttachShader = (void *)wglGetProcAddress("glAttachShader");
	*(void **)&_glLinkProgram = (void *)wglGetProcAddress("glLinkProgram");
	*(void **)&_glDetachShader = (void *)wglGetProcAddress("glDetachShader");
	*(void **)&_glGetProgramiv = (void *)wglGetProcAddress("glGetProgramiv");
	
	shader = _glCreateShader(GL_FRAGMENT_SHADER);
	_glShaderSource(shader, 1, &src, &len);
	_glCompileShader(shader);
	_glGetShaderiv(shader, GL_COMPILE_STATUS, &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, &status);
	if (status == GL_FALSE) _asm int 3
	
	_glGetProgramiv(prog, GL_PROGRAM_BINARY_LENGTH, &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(&wc, 0, sizeof(wc));
	wc.hInstance = inst;
	wc.lpfnWndProc = wnd_proc;
	wc.lpszClassName = "_test_class_name";
	RegisterClassA(&wc);
	wnd = CreateWindowExA(0, wc.lpszClassName, NULL, WS_POPUP, 0, 0, 64, 32, NULL, NULL, NULL, NULL);
	dc = GetDC(wnd);
	memset(&pfd, 0, sizeof(pfd));
	pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
	pfd.nVersion = 1;
	pfd.dwFlags = PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DEPTH_DONTCARE;
	pf = ChoosePixelFormat(dc, &pfd);
	SetPixelFormat(dc, pf, NULL);
	rc = wglCreateContext(dc);
	wglMakeCurrent(dc, rc);

	get_program_binary_test();
	
	return 0;
}

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

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.