Another separable shader-related bug;
A separable vertex shader (that is, a separable program object that only contains a vertex shader) does not recognize the build in variables gl_Position, gl_ClipDistance and gl_PointSize.
The compilation is successful but the link fails with the error:
ERROR: 0:4: error(#143) Undeclared identifier gl_Position
I tried declaring them explicitly. Then it compiles and links ok but gives warning about re-declaring of built-ins.
If gl_ClipDistances is declared too, the shader compiles and links ok but does not work.
here is simple win32-based code that reproduces the bug:
#include <string.h>
#include <windows.h>
#include <GL/gl.h>
#include "glext.h"
void separable_vertex_shader_test()
{
static const char text[] =
"#version 330
"
"#extension GL_ARB_separate_shader_objects : enable
"
"void main() {
"
" gl_Position = vec4(0);
"
"}
";
const char *src = text;
GLint len = sizeof(text);
GLuint shader, prog;
GLenum status;
PFNGLCREATESHADERPROC _glCreateShader;
PFNGLSHADERSOURCEPROC _glShaderSource;
PFNGLCOMPILESHADERPROC _glCompileShader;
PFNGLGETSHADERIVPROC _glGetShaderiv;
PFNGLCREATEPROGRAMPROC _glCreateProgram;
PFNGLPROGRAMPARAMETERIPROC _glProgramParameteri;
PFNGLATTACHSHADERPROC _glAttachShader;
PFNGLLINKPROGRAMPROC _glLinkProgram;
PFNGLGETPROGRAMINFOLOGPROC _glGetProgramInfoLog;
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 **)&_glGetProgramInfoLog = (void *)wglGetProcAddress("glGetProgramInfoLog");
*(void **)&_glGetProgramiv = (void *)wglGetProcAddress("glGetProgramiv");
shader = _glCreateShader(GL_VERTEX_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);
_glAttachShader(prog, shader);
_glLinkProgram(prog);
_glGetProgramiv(prog, GL_LINK_STATUS, &status);
if (status == GL_FALSE) {
char log[65536];
GLint log_size;
_glGetProgramInfoLog(prog, sizeof(log), &log_size, log);
_asm int 3
}
}
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);
separable_vertex_shader_test();
return 0;
}