Jump to content
  • Advertisement
Sign in to follow this  

[SOLVED] GLSL subroutine not getting used

This topic is 2238 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm using a gaussian blur fragment shader. In it, I thought it would be concise to include 2 subroutines: one for selecting the horizontal texture coordinate offsets, and another for the vertical texture coordinate offsets. This way, I just have one gaussian blur shader to manage.

Here is the code for my shader. The {{NAME}} bits are template placeholders that I substitute in at shader compile time:

#version 420

subroutine vec2 sample_coord_type(int i);
subroutine uniform sample_coord_type sample_coord;

in vec2 texcoord;
out vec3 color;

uniform sampler2D tex;
uniform int texture_size;

const float offsets[{{NUM_SAMPLES}}] = float[]({{SAMPLE_OFFSETS}});
const float weights[{{NUM_SAMPLES}}] = float[]({{SAMPLE_WEIGHTS}});

subroutine(sample_coord_type) vec2 vertical_coord(int i) {
return vec2(0.0, offsets / texture_size);

subroutine(sample_coord_type) vec2 horizontal_coord(int i) {
//return vec2(offsets / texture_size, 0.0);
return vec2(0.0, 0.0); // just for testing if this subroutine gets used

void main(void) {
color = vec3(0.0);

for (int i=0; i<{{NUM_SAMPLES}}; i++) {
color += texture(tex, texcoord + sample_coord(i)).rgb * weights;
color += texture(tex, texcoord - sample_coord(i)).rgb * weights;

Here is my code for selecting the subroutine:

blur_program->set_subroutine("sample_coord", "vertical_coord", GL_FRAGMENT_SHADER);
blur_program->set_int("texture_size", width);
blur_program->set_texture("tex", *deferred_output);
blur_program->draw(); // draws a quad for the fragment shader to run on


void ShaderProgram::set_subroutine(constr name, constr routine, GLenum target) {
GLuint routine_index = glGetSubroutineIndex(id, target, routine.c_str());
GLuint uniform_index = glGetSubroutineUniformLocation(id, target, name.c_str());
glUniformSubroutinesuiv(target, 1, &routine_index);

// debugging
int num_subs;
glGetActiveSubroutineUniformiv(id, target, uniform_index, GL_NUM_COMPATIBLE_SUBROUTINES, &num_subs);
std::cout << uniform_index << " " << routine_index << " " << num_subs << "\n";

I've checked for errors, and there are none. When I pass in `vertical_coord` as the routine to use, my scene is blurred vertically, as it should be. The `routine_index` variable is also 1 (which is weird, because `vertical_coord` subroutine is the first listed in the shader code...but no matter, maybe the compiler is switching things around)

However, when I pass in `horizontal_coord`, my scene is STILL blurred vertically, even though the value of `routine_index` is 0, suggesting that a different subroutine is being used. Yet the `horizontal_coord` subroutine explicitly does not blur.

What's more is, whichever subroutine comes first in the shader, is the subroutine that the shader uses permanently. Right now, `vertical_coord` comes first, so the shader blurs vertically always. If I put `horizontal_coord` first, the scene is unblurred, as expected, but then I cannot select the `vertical_coord` subroutine! smile.png

Also, the value of `num_subs` is 2, suggesting that there are 2 subroutines compatible with my `sample_coord` subroutine uniform.

Just to re-iterate, all of my return values are fine, and there are no glGetError() errors happening.

Any ideas?

Share this post

Link to post
Share on other sites
After a lot of pain, I figured out that I was indirectly calling glUseProgram() twice with my framework. The first time, to set the subroutine, the second time, in the draw() method of my shader program object. Apparently subroutine selection *do not* persist in shader program state, so it was being reset on the second call.

Hopefully this saves someone some time! :)

Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!