2 Replies Latest reply on Mar 6, 2012 6:32 AM by lukcho

    (opengl) bug with separate vertex shaders

    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;
      }
      
      
      
        • Re: (opengl) bug with separate vertex shaders
          gsellers

          Hi Lukcho,

           

          It is necessary when using separable program objects to redeclare the in-use built-in variables inside the gl_PerVertex interface block. Try this in your shader:

           "#version 330\n"  
           "#extension GL_ARB_separate_shader_objects : enable\n"
           "out gl_PerVertex {\n"
           "    vec4 gl_Position;\n"
           "};\n"
           "void main() {\n"  
           "     gl_Position = vec4(0);\n"  
           "}\n";  
          

          From the GLSL spec, "The gl_PerVertex block can be redeclared in a shader to explicitly indicate what subset of the fixed

          pipeline interface will be used.  This is necessary to establish the interface between multiple programs."

           

          This should make your example work. If it does not, or if you still see a compiler warning, let us know and we'll look into it.

           

          Cheers,

           

          Graham