4
votes

I'm trying to get my head around the following:

I've an object that I want to be able to render with two different sets of vertex/fragment shaders, that each have their uniforms and textures, and go back and forth between those two settings. (I know in this case I could have just one shader with a uniform dictating which logic to run, but this is part of a larger things where I can't do that)

  • Should I use one or two gl programs (created by glCreateProgram())?
  • If I use two programs, is it fine to discard the one not being used, and rebuild it if need later on? Or is it too slow?
  • If I use just one program:
    • can I compile shaders just once at the beginning?
    • when switching should I detach old shaders, attach new ones and link the program again?
    • should I recompute all uniforms locations after linking?
    • should I rebind array buffers after linking?
    • should I do something to remove previously attached textures?
1
Creating and linking shaders is usally a very slow operation. I would recommend simply creating two programs in the beginning and using them if necessary. For more infos, you would have to provide more details on your usage scenario. For example, how often the shader has to be changed.BDL

1 Answers

4
votes

Should I use one or two gl programs (created by glCreateProgram())?

It depends on the case. A general rule could be avoid branching inside shader code. So if you have 2 different shaders, for 2 different effects, just compile 2 programs and bind the desired one.

If I use two programs, is it fine to discard the one not being used, and rebuild it if need later on? Or is it too slow?

This is generally not needed and wrong (maybe unless you have huge memory issues). Shader compilation is a slow process.

It's more common to compile all the necessary resources once, at the application startup or the first time needed, and leave them allocated and ready to use.

can I compile shaders just once at the beginning?

Yes.

For all the remaining questions: I think you are taking the wrong approach.

I'd say:

  • Compile all shader variants at the beginning (or when you need a program)
  • Bind a shader and the relative resources, set uniforms before drawing with that shader.
  • When change shader, re-bind the resources or update uniform values only if different and needed
  • Release resources and programs at the end of the application