Sergey
Sergey

Reputation: 8238

How to share shader code across shading stages in OpenGL

I have some math functions written in GLSL and I want to use them in TES, geometry and fragment stages of the same shader program. All of them are pretty valid for all these shader types, and for now the code is just copy-pasted across shader files.

I want to extract the functions from the shader files and put them into a separate file, yielding a shader "library". I can see at least two ways to do it:

Is it possible to compile shader source only once (with appropriate restrictions), link it to a shader program and use it in any stage of the pipeline? I mean something like this:

GLuint shaderLib = glCreateShader(GL_LIBRARY_SHADER);
//...add source and compile....
glAttachShader(shProg, vertexShader);
glAttachShader(shProg, tesShader);
glAttachShader(shProg, geomShader);
glAttachShader(shProg, fragShader);
glAttachShader(shProg, shaderLib);
glLinkProgram(shProg); // Links OK; vertex, TES, geom and frag shader successfully use functions from shaderLib.

Of course, library shader should not have in or out global variables, but it may use uniforms. Also, function prototypes should be declared before usage in each shader source, as it is possible to do when linking several shaders of the same type into one program.

And if the above is not possible, then WHY? Such "library" shaders look very logical for the C-like compilation model of GLSL.

Upvotes: 1

Views: 1269

Answers (2)

CaffeinePwrdAl
CaffeinePwrdAl

Reputation: 31

All the high level constructs of structs, functions, linking of modules, etc, are mostly all just niceties that the APIs provide to make your life easier on input. HLSL for example allows you to do use #include's, but to do something similar in GLSL you need to perform that pre-process step yourself.

When the GPU has to execute your shader it is running the same code hundreds, thousands, if not millions of times per frame - the driver will have converted your shader into its own HW specific instruction set and optimised it down to the smallest number of instructions practicable to guarantee best performance of their instruction caches and shader engines.

Upvotes: 0

Nicol Bolas
Nicol Bolas

Reputation: 473407

Is it possible to compile shader source only once (with appropriate restrictions), link it to a shader program and use it in any stage of the pipeline?

No. I'd suggest, if you have to do this, to just add the text to the various shaders. Well, don't add it directly to the actual string; instead, add it to the list of shader strings you provide via glShaderSource/glCreateShaderProgram.

And if the above is not possible, then WHY?

Because each shader stage is separate.

It should be noted that not even Vulkan changes this. Well, not the way you want. It does allows you to have the reverse: multiple shader stages all in a single SPIR-V module. But it doesn't (at the API level) allow you to have multiple modules provide code for a single stage.

Upvotes: 2

Related Questions