problem using separate shader programs

I’m trying to play around with separate shader programs. I’ve stepped through with the debugger and verified that I’m doing this exact process:

https://www.opengl.org/wiki/Example/GLSL_Separate_Program_Basics

I get no errors, but my vertex and fragment programs aren’t being compiled/linked properly. What I mean is that when I call glCreateShaderProgramv, no errors are generated, the program logs are empty, and it returns a valid program id (1, 2, etc). However, I can pass it any text for the source (including deliberate syntax errors), and it behaves as if all is well, so I know it’s not actually compiling/linking properly. When I debug the app in CodeXL, it shows this for the pipeline I generated:

Program Pipeline 1
Active Program - No Program
Vertex Shader - Program 1
Tess Control Shader -
Tess Evaluation Shader -
Geometry Shader -
Fragment Shader - Program 2
Compute Shader -
Pipeline Bound - Yes

Both shader programs look like this in CodeXL:

Program 1 (or 2)
Attached Shaders - None
Is Successfully Linked - No
Is Marked for Deletion - No
Used in Last Frame - No
Program Link Log - Empty

I’ve tried two different machines with the same result. Both have nvidia cards (one supporting OGL 4.4 and the other OGL 3.3) with the latest drivers and latest version of glew. Any ideas?

Both have nvidia cards

Does CodeXL work on NVIDIA cards?

I’ve stepped through with the debugger and verified that I’m doing this exact process

Show us the actual code you’re executing.

OpenCL kernel debugging doesn’t, but most everything else does (OGL call history, state debugging, memory inspection, etc). CodeXL issues a warning to this effect when you start debugging.

It’s part of a larger codebase, but I’ve unwrapped the code into a fairly straightforward example that exhibits the same issue. I didn’t bother removing/keeping all the error handling that the actual code does either, but no API calls seem to be failing. Also, ignore the exception safety issues…they’re properly handled outside of the example. I don’t actually try to render or anything in the example since my vertex shader shouldn’t even compile (but I get no compilation errors and a valid ID is returned), so glCreateShaderProgramv() not behaving properly seems to be my issue.


try
{    
    HWND hwnd = *( window.GetSystemHandle() );
    HDC hdc = GetDC( hwnd );


    PIXELFORMATDESCRIPTOR pfd = {};
    pfd.nSize = sizeof( PIXELFORMATDESCRIPTOR );
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
    pfd.dwLayerMask = PFD_MAIN_PLANE;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 32;
    pfd.cDepthBits = 24;
    pfd.cAccumBits = 0;
    pfd.cStencilBits = 8;


    int pixelFormat = ChoosePixelFormat( hdc, &pfd );
    if( !pixelFormat ) 
    {
        throw Win32Error( "ChoosePixelFormat()", allocator );
    }
    if( !SetPixelFormat( hdc, pixelFormat, &pfd) ) 
    {
        throw Win32Error( "SetPixelFormat()", allocator );
    }


    HGLRC oglContext = wglCreateContext( hdc );
    if( !oglContext )
    {
        throw Win32Error( "wglCreateContext()", allocator );
    }


    wglMakeCurrent( hdc, oglContext );


    glewExperimental  = GL_TRUE;
    if( glewInit() != GLEW_OK )
    {
        throw OGLRuntimeError( GL_INVALID_OPERATION );
    }


    int attributes[] =
    {  
        WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
        WGL_CONTEXT_MINOR_VERSION_ARB, 3,
        WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, 
        0
    };


    if( wglewIsSupported( "WGL_ARB_create_context ") )
    {
         wglMakeCurrent( 0, 0 );
         wglDeleteContext( oglContext );
         oglContext = wglCreateContextAttribsARB( hdc, 0, attributes );
         if( !oglContext )
         {
             throw Win32Error( "wglCreateContextAttribsARB()", allocator );
         }
         wglMakeCurrent( hdc, oglContext );
    }
    else
    {
        // doesn't happen so not relevant for example
    }


    const char* vertSource = "\
        #version 430 core\
        deliberate_syntax_error\
        in vec3 inPosition;\
        in vec3 inColor;\
        out vec3 passColor;\
        \
        out gl_PerVertex\
        {\
            vec4 gl_Position;\
        };\
        \
        uniform mat4 modelViewMatrix;\
        uniform mat4 projectionMatrix;\
        \
        void main(void)\
        {\
            gl_Position = projectionMatrix * modelViewMatrix * vec4( inPosition, 1.0 );\
            passColor = inColor;\
        }";


    const char* fragSource = "\
        #version 430 core\
        \
        in vec3 passColor;\
        out vec4 outColor;\
        \
        void main(void)\
        {\
            outColor = vec4( passColor, 1.0 );\
        }\
        \
        void main(void)\
        {\
            gl_Position = projectionMatrix * modelViewMatrix * vec4( inPosition, 1.0 );\
            passColor = inColor;\
        }";


    glGetError();
    GLuint vertProg = glCreateShaderProgramv( GL_VERTEX_SHADER  , 1, &vertSource );
    GLenum errorCode = glGetError();
    if( GL_NO_ERROR != errorCode )
    {
        throw OGLRuntimeError( errorCode ); // not triggered, even with a junk shader
    }


    GLuint fragProg = glCreateShaderProgramv( GL_FRAGMENT_SHADER, 1, &fragSource );
    errorCode = glGetError();
    if( GL_NO_ERROR != errorCode )
    {
        throw OGLRuntimeError( errorCode ); // not triggered, even with a junk shader
    }


    GLuint pipeline;
    glGenProgramPipelines( 1, &pipeline );
    glUseProgramStages( pipeline, GL_VERTEX_SHADER_BIT  , vertProg );
    glUseProgramStages( pipeline, GL_FRAGMENT_SHADER_BIT, fragProg );


    glBindProgramPipeline( pipeline );


    while( true )
    {
        window.Update();
        SwapBuffers( hdc );
    }
}
catch( std::exception& e )
{
    MessageBox( 0, e.what(), "Error", MB_OK );
}


    const char* vertSource = "\
        #version 430 core\
        deliberate_syntax_error\
        in vec3 inPosition;\
        in vec3 inColor;\
        out vec3 passColor;\
        ...

That’s not how you pack a string into C++. When you do that, your string becomes:


    #version 430 core    deliberate_syntax_error    in vec3 inPosition;    in vec3 inColor;    out vec3 passColor;    

The '' in a string at the end of the line doesn’t mean “end of line”. In fact, it means the exact opposite: it tells the tokenizer to ignore the EOL. So it cuts out those pesky end of lines.

Which means all the parser sees is a #version declaration. Why the linker didn’t complain about a lack of a main declaration, or the fact that the #version declaration had a bunch of stuff that’s illegal in a #version declaration is irrelevant. Well, it’s not irrelevant; that should be submitted to NVIDIA as a driver bug.

But I’d bet if you packed your string correctly, it would work. If you have access to C++11 with access to raw string literals, you can use that. If not, then you should use this:


    const char* vertSource = ""
        "#version 430 core
"
        "deliberate_syntax_error
"
        "in vec3 inPosition;
"
        "in vec3 inColor;
"
        "out vec3 passColor;
"
        ...

Sorry, that was just a brainfart on my part when creating the example. The actual code loads the shader source from files…I just used string literals for the example. Anyways, packing the strings correctly doesn’t change anything. It doesn’t seem to matter what source I send to glCreateShaderProgramv()…it just acts as if everything worked properly regardless of whether I sent it valid source or not. CodeXL still displays the same info as my first post.

If you are error-checking like you showed in the example, the program string is correct (try to debug the string and see if it matches the string that CodeXL shows as code), the compile status is fine, then the last thing you can try is instead of using glCreateShaderProgram, use the single step functions like explained here

which is


GLuint vertexShader = glCreateShader( GL_VERTEX_SHADER );

//read your file here


//check gl errors
glShaderSource( vertexShader, 1, &vertexShaderString, NULL );
//check gl errors
glCompileShader( vertexShader );
//check gl errors

GLint compileStatus;
glGetShaderiv( vertexShader, GL_COMPILE_STATUS, &compileStatus );

if( compileStatus == GL_FALSE )
{
    glGetShaderInfoLog( vertexShader, ......);
}

// repeat for pixel shader, then link


GLuint openGLProgram = glCreateProgram();
//check gl errors

glAttachShader( openGLProgram, vertexShader );
//check gl errors

glAttachShader( openGLProgram, pixelShader );
//check gl errors

glLinkProgram( openGLProgram );
//check gl errors

//-- check linking
glGetProgramiv( openGLProgram, GL_LINK_STATUS, &compileStatus );
if( compileStatus == GL_FALSE )
{
    glGetProgramInfoLog( openGLProgram, .... )
}

But it still sounds really weird. You must have something else that is interfering if the shader code is correct as you said.

I had already tried writing my own glCreateShaderProgramv() (including setting the GL_PROGRAM_SEPARABLE flag) since what it does is well documented. If I do that, the shaders do compile and link (and I get compilation errors if I purposely try to compile invalid glsl). CodeXL shows them as successfully linked, but everything else shows the same as above and using them in a pipeline still has no effect (almost as if setting GL_PROGRAM_SEPARABLE didn’t do anything or something).

I shouldn’t have to do that anyways…I want to know why glCreateShaderProgramv() isn’t working. Yes, this is weird, and pretty aggravating too.

So am I to assume that my example code works for everyone else, and nobody has any ideas as to why glCreateShaderProgramv doesn’t work for me (happily swallows invalid glsl, doesn’t result in a properly linked shader program, no errors generated, empty infologs, etc)?