Entalpi
Entalpi

Reputation: 2033

Recompile, relink, vertex shader in shader program

I have in place a system for detecting changes made to my shader files. When a shader is changes, let's say the vertex shader, I want to compile that one and replace it with the old version (while not changing the input/output of the shader and thus reusing the VAO, VBO, etc).

std::pair<bool, std::string> Shader::recompile() {
std::string vertex_src = load_shader_source(vertex_filepath);

glDetachShader(gl_program, vertex_shader); // gl_program is a GLuint for the shader program
glDeleteShader(vertex_shader);

vertex_shader = glCreateShader(GL_VERTEX_SHADER);

auto raw_str = vertex_src.c_str();
glShaderSource(vertex_shader, 1, &raw_str, NULL);

glCompileShader(vertex_shader);

GLint vertex_shader_status;
glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &vertex_shader_status);

GLint fragment_shader_status = 1;

if (vertex_shader_status == 1) {
    glAttachShader(gl_program, vertex_shader);
    // glLinkProgram(gl_program);

    // Logging - mostly irrelevant to the question
    GLint is_linked = 0;
    glGetProgramiv(gl_program, GL_LINK_STATUS, &is_linked);
    SDL_Log("Shader relinking is success: %i", is_linked == GL_TRUE);

    std::string err_log = "";
    GLint max_log_lng = 0;
    glGetProgramiv(gl_program, GL_INFO_LOG_LENGTH, &max_log_lng);
    err_log.reserve(max_log_lng);
    glGetProgramInfoLog(gl_program, max_log_lng, NULL, (char *) err_log.c_str());
    SDL_Log("%s", err_log.c_str());

    return {true, ""};
}

The result when using this approach is that nothing changes, but when I link the program (inside the if-statement) it goes all away. I am assuming this is because the linking changes all the bindings and thus makes the existing ones invalid, resulting in nothing being rendered at all.

So, is this even possible to hotswap the a specific shader like this in a shader program?

Upvotes: 1

Views: 900

Answers (1)

BDL
BDL

Reputation: 22168

Linking does not invalidate any attribute bindings since they are part of the VAO state and not of the program. There are two things that could happpen when relinking the program:

  • The index of an attribute might change. This can be prevented by either fixing them in both shaders (layout (location=...)) or by fixing them between compile and load (glBindAttribLocation​). The same thing might also happen for uniforms and can be handled in the same way.
  • The values of uniforms are lost. This can not simply be prevented, but setting them in each frame should fix the problem.

Upvotes: 2

Related Questions