Maik Klein
Maik Klein

Reputation: 16148

How to use glCreateShaderProgram?

http://docs.gl/gl4/glCreateShaderProgram

Pseudo code:

const GLuint shader = glCreateShader(type);
if (shader) {
    glShaderSource(shader, count, strings, NULL);
    glCompileShader(shader);
    const GLuint program = glCreateProgram();
    if (program) {
        GLint compiled = GL_FALSE;
        glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
        glProgramParameteri(program, GL_PROGRAM_SEPARABLE, GL_TRUE);
        if (compiled) {
            glAttachShader(program, shader);
            glLinkProgram(program);
            glDetachShader(program, shader);
        }
        /* append-shader-info-log-to-program-info-log */
    }
    glDeleteShader(shader);
    return program;
}
else {
    return 0;
}

I didn't know that it is possible to compile several shaders at once. The problem that I have is that the documentation doesn't tell me how to call this.

What type should I specify if I want to compile a vertex + fragment shader? Initially I tried glCreateShader(GL_VERTEX_SHADER | GL_FRAGMENT_SHADER); but then it complained about two main functions. OpenGL probably interpreted two shaders as one shader.

Upvotes: 4

Views: 2558

Answers (3)

Reto Koradi
Reto Koradi

Reputation: 54602

glCreateShaderProgram() only compiles and links a single shader. The last argument is an array of strings just like the corresponding argument for glShaderSource(), which is also used for specifying the source of one shader. Being able to pass multiple strings is just a convenience for both of those calls. For example, if you have your shader code as an array of strings (say one per line), you can directly pass them in, without a need to concatenate them first.

glCreateShaderProgram() is intended to be used in conjunction with program pipeline objects. This mechanism allows you to combine shaders from several programs, without a need to link them. A typical call sequence would look like this:

GLuint vertProgId = glCreateShaderProgram(GL_VERTEX_SHADER, 1, &vertSrc);
GLuint fragProgId = glCreateShaderProgram(GL_FRAGMENT_SHADER, 1, &fragSrc);

GLuint pipelineId = 0;
glGenProgramPipelines(1, &pipelineId);

glUseProgramStages(pipelineId, GL_VERTEX_SHADER_BIT, vertProgId);
glUseProgramStages(pipelineId, GL_FRAGMENT_SHADER_BIT, fragProgId);

glBindProgramPipeline(pipelineId);

Upvotes: 9

didierc
didierc

Reputation: 14730

From the linked documentation:

glCreateShaderProgram creates a program object containing compiled and linked shaders for a single stage specified by type.

[emphasis mine]

What it means is that you cannot use it with a list of shaders targeting different parts of the rendering pipeline.


However, you could perhaps modify the sample implementation to cover that need for you. It would require to change the function signature by replacing the first parameter by an array of GLenum of count elements, then turn the implementation into a loop on each pair shader[i], strings[i] to add them to the generated program, where shader is an array of shader ids associated with each source string separately.

Once each shader has been compiled, the code would then link the whole into a program, release all the shader ids, and return the program id (actual implementation left as an exercise).

Upvotes: 3

Anders Stensaas
Anders Stensaas

Reputation: 749

I don't think it's possible to create multiple shaders at once. glCreateShaderProgram just does everything needed to create a shader for you (create, compile, link).

If you look at the documentation at opengl.org, you will see that you can only create one shader at a time. You can only specify one of the following GLenums: GL_COMPUTE_SHADER, GL_VERTEX_SHADER, GL_TESS_CONTROL_SHADER, GL_TESS_EVALUATION_SHADER, GL_GEOMETRY_SHADER, or GL_FRAGMENT_SHADER.

I think you are right about what you are thinking. OpenGL is probably interpreting two shaders as one and that is not possible.

You can do this:

glCreateShader(GL_VERTEX_SHADER);
glCreateShader(GL_FRAGMENT_SHADER);

Look at the Description field of the source I have provided. It will explain what further to do with the shader objects.

I am not sure why you can pass an array of strings. It could be if you had multiple small snippets of shader code in different source code files.

Source: https://www.opengl.org/sdk/docs/man/html/glCreateShader.xhtml

Upvotes: 1

Related Questions