Search code examples
openglglslvertex-shader

What causes GLSL recompilation of vertex shader based on state?


I am using the ARB_debug_output extension. The driver gives me this warning:

Program/shader state performance warning: Vertex shader in program 16 is being recompiled based on GL state.

So, I tried setting various GL state before I compile my shader, including:

  • GL_BLEND
  • GL_CULL_FACE
  • GL_DEPTH_TEST
  • polygon-offset
  • blendfunc

...but it still recompiles upon first draw.

What are the typical pieces of state that could cause the driver to recompile a vertex shader?


Solution

  • I also got this message and found the solution in a Reddit post. The problem was as follows:

    I am using Direct State Access (DSA) to setup all my VBOs and VAOs. So during the setup process, I never bind anything to the state machine.

    My vertex shader contains some inputs like layout (location=0) in vec3 VertexPosition. But the corresponding attribute wasn't enabled yet in the state machine. So the driver compiles a program version for a state where no Attribute is enabled. Now, if I bind my first VAO for drawing, all the necessary attributes get enabled and the driver detects a mismatch between the state of my first draw call and the state when I compiled the shader. So he has to recompile it.

    In this case, the warning can be fixed by binding a correctly setup VAO before compiling the program (see remarks below). Alternatively, you can just set the state directly by enabling all required attributes with glEnableVertexAttribArray, as suggested in the linked Reddit post.

    Finally, you can decide to ignore or filter the message, if it occurs only once after the first draw call. But I would advise against it, since the warning might also be caused by other problems in your code that can cause serious problems. So fixing it should be the way to go.

    Remarks:

    I am not entirely sure, when the program (not the shaders) is actually compiled (not linked). For me it was sufficient to configure the state machine correctly just before I first called glUseProgram. I don't know if the Spec says something about it or if it is left to the driver to decide it. I had a look at the documentation of glUseProgram, but it only talks about "installing" the program to current state. Maybe someone else can clarify this.