Separate Shader Objects

Hi :slight_smile:

I’m interesting in the features of OpenGL ES 3.1.

Recently, I find out the “Separate Shader Objects” among one of the OpenGL ES 3.1 and OpenGL 4.1 features.

When I write the code like below:


void loadShader() {
  vertexProgram = glCreateShaderProgram(GL_VERTEX_PROGRAM, ...);
  fragmentProgram = glCreateShaderProgram(GL_FRAGMENT_PROGRAM, ...);

  glGenProgramPipelines(1, pipeline);
  glBindProgramPipleline(pipeline);
  glUseProgramStages(pipeline, GL_VERTEX_SHADER_BIT, vertexProgram);
  glUseProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, fragmentProgram);
}

void draw() {
  ...
  glBindProgramPipeline(pipeline);
  ...
}



Are the "Program"s such as vertexProgram and fragmentProgram made by glCreateShaderProgram or “Pipeline” on the GPU?
If my assumption is wrong, what’s the difference from the general way of making and using the Programs?

Thanks. :slight_smile:

The advantage of separate shader objects becomes apparent when you have for a couple of vertex and fragment shaders that can be freely combined with each other - perhaps you have vertex shaders that do/or not do vertex skinning and fragment shaders for a bunch of different types of materials.
In the usual case you would need to link one program object for each combination of vertex + fragment shader and if you make use of additional programmable stages (geometry, tessellation shaders) the number of program objects for all combinations starts to explode.
With separate shader objects you build program objects that each contains just a single shader for a single stage and pick and match them into a pipeline object. You could create multiple pipeline objects (in the extreme case one for each combination of shaders again), but that would be not much different from having a program object for each combination.

I don’t exactly know where shaders are stored, my guess would be that part of them resides on the GPU since it has to execute the contained instructions, but other parts may remain in main memory, where the driver needs to consult them in order to program the GPU in a certain way.

[QUOTE=carsten neumann;1261266]
I don’t exactly know where shaders are stored, my guess would be that part of them resides on the GPU since it has to execute the contained instructions, but other parts may remain in main memory, where the driver needs to consult them in order to program the GPU in a certain way.[/QUOTE]

Thanks for your reply.

I understand that the shaders may be stored that part of resides on the GPU.
By the way, I have one more question.

As I’m understanding,
it’s possible to be stored multiple ProgramPipelines on the GPU side, and bind the shaders (vertex shader, fragment shader) among one of Programs on the GPU when I use “glBindProgramPipeline()”.

Is is right?

Then, aren’t the program objects made in advance stored on the GPU side?
And, what makes the “glLinkProgram()” method so expensive?

Can I ask why you think it’s important to know if the program objects/pipeline objects are stored on the GPU? You can not influence it and have to trust the implementation to make the right decision anyway.

it’s possible to be stored multiple ProgramPipelines on the GPU side, and bind the shaders (vertex shader, fragment shader) among one of Programs on the GPU when I use “glBindProgramPipeline()”.

Yes, you can have multiple pipeline objects in existence, of course only one of them can be active at any given time. I’m afraid I don’t really understand what you are asking in the rest of the above sentence, can you explain it in more detail?

glLinkProgram is (for the non-separable program case) the point in time when the shader compiler has full information about which shader stages are active and what their in/outputs are, so it can do all necessary validation to make sure the stages can work together and also perform optimizations that need knowledge about earlier shader stages.

I really appreciate your help.
And, I’m really sorry for getting my words crossed since I’m a one of the non-English-speaking students.

I just want to verify my assumption, the ProgramPipelines are stored on the GPU sides.
Then, does Separate Shader Object just exist for only reducing initialization time in OpenGL program?

For give reply why I want to know if the program objects/pipeline are stored on the GPU, I think it should be going to important issue for the android graphics framework on OpenGL ES 3.1. I’m also not a expert and just student studying android & graphics programming. So, I’m sorry that I couldn’t give you something more detail.

Thanks. :slight_smile:

I just want to verify my assumption, the ProgramPipelines are stored on the GPU sides.

I do not know the answer, driver implementors should know, but they may not want to say :wink: There may not even be a simple answer, the implementation might move them around based on observing usage patterns of the application - similarly to what is done with buffer objects.

Then, does Separate Shader Object just exist for only reducing initialization time in OpenGL program?

I think they exist to make it easier to mix and match shader objects without requiring the user to create a program object for each combination. As far as I know that has always been a requirement of the OpenGL spec only and the hardware has always been able to do to this - presumable because that is how shaders work in DirectX.
As far as reducing start-up time is concerned I would guess keeping a cache of program binaries (see e.g glProgramBinary) is probably more effective - some drivers even do that behind the scenes for you.

To be more specific, linking shaders to a single “program object” is a GLSL only “feature”: there’s nothing in OpenGL itself that requires it.

The old ARB assembly programs didn’t require it.
Direct 3D doesn’t require it.
The consoles apparently don’t require it.

So it’s an artificial limitation imposed on you by the GLSL interfaces.

The reason for separate shader objects is given in the spec:

While GLSL’s monolithic approach has some advantages for optimizing shaders as a unit that span multiple stages, all existing GPU hardware supports the more flexible mix - and - match approach.

Shaders written for HLSL9, Cg, the prior OpenGL assembly program extensions, and game console favor a more flexible “mix-and-match” approach to specifying shaders independently for these different shader stages.Many developers build their shader content around the mix - and - match approach where they can use a single vertex shader with multiple fragment shaders (or vice versa).

So not only is it an artificial software construct, it’s also one that doesn’t reflect the way GPU hardware actually works.