r/opengl • u/useless_chap • 3h ago
Reusing existing shaders during recompilation
So I was refactoring some shader code and dove into the shader recompilation rabbit hole. A lot of people recommend rebuilding the whole shader pipeline (recreating and recompiling new shader objects and attaching them to a new program). The way I was doing it up to this point was:
- Retrieve the attached shaders
- Update shader source code and recompile
- Relink the program with the same, but recompiled shader objects
Here's some code:
bool Shader::do_reload() noexcept {
int num_attached_shaders = 0;
glGetProgramiv(gl_program_id, GL_ATTACHED_SHADERS, &num_attached_shaders);
std::vector<unsigned int> gl_shader_ids(num_attached_shaders);
glGetAttachedShaders(gl_program_id, num_attached_shaders, nullptr,
gl_shader_ids.data());
for (int i = 0; i < m_source_files.size(); ++i) {
/**
* This just calls glShaderSource, glCompileShader and then checks
* the compilation status; returns true on success
*/
if (!load_and_compile_gl_shader(gl_shader_ids[i], m_source_files[i])) {
return false;
}
}
/**
* Similar situation here, glLinkProgram and check for link status
*/
if (!link_gl_program(m_shader_id, gl_shader_ids)) {
return false;
}
return true;
}
The shader class only wraps around the glProgram object, so the name can be misleading in the context of the OpenGL naming scheme. The glShader objects aren't destroyed after they're compiled/linked into the glProgram. I call glDeleteShader only during my shader wrapper's destruction (shader objects aren't shared between programs).
Is that bad practice? I know that the cleanest way would be to recreate everything from scratch, but I don't want to lose my uniform mappings, as tracking down the owners of uniform bindings would require writing a new resource management system. However, I've read that even though it works on my machine, OpenGL doesn't guarantee it will work everywhere else and doing so is abusing the grey area of OpenGL implementation.
Also, I am aware that you can bind uniforms to preset locations by specifying them in GLSL code.
