AnsweredAssumed Answered

(opengl) bug with separate vertex shaders

Question asked by lukcho on Mar 5, 2012
Latest reply on Mar 6, 2012 by lukcho

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 but gives warning about re-declaring of built-ins.

If gl_ClipDistances is declared too, the shader compiles and links but does not work.

 

here is simple win32-based example that demonstrates the bug

it should break in the debugger at line 56 where you can examine the shader link log message

(to run the example just create a new empty project in visual c, paste the following code in an .c file, put glext.h in the same directory as the .c file, add the .c file to the project and build project)

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

void separable_vertex_shader_test()
{
 static const char text[] =
 "#version 330\n"
 "#extension GL_ARB_separate_shader_objects : enable\n"
 "void main() {\n"
 "     gl_Position = vec4(0);\n"
 "}\n";
 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(pfd);
 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;
}


Outcomes