In OpenGL the order for glAttachShader
is irrelevant, is this the same for glDeleteShader
? I would say yes if there is some dynamic memory allocation is going on, but maybe this is handled different in the opengl context.
The simple answer is: It does not matter. You can delete them anytime after they are attached to a program, and they will continue to stay alive until they are no longer referenced.
The details of shader lifetime are often misunderstood. The key wording from the spec is:
When a shader object or program object is deleted, it is flagged for deletion, but its name remains valid until the underlying object can be deleted because it is no longer in use. A shader object is in use while it is attached to any program object. A program object is in use while it is the current program in any context.
This is in section 5.1.3 of the GL 4.4 spec, and appendix D.1.2 of the GL 3.3 spec.
So contrary to popular believe, the shader name remains valid beyond the glDeleteShader()
call if it is currently in use. This is different from how the names are handled for other object types, like textures or buffers, where the name immediately becomes invalid after the delete call.
This is an example sequence of calls to illustrate these rules:
GLuint progA = glCreateProgram();
GLuint vertA = glCreateShader(GL_VERTEX_SHADER);
glAttachShader(progA, vertA);
glDeleteShader(vertA);
// vertA remains alive, since it's attached to progA.
// Set and compile source for vertA.
GLuint fragA = glCreateShader(GL_FRAGMENT_SHADER);
glAttachShader(progA, fragA);
glDeleteShader(fragA);
// fragA remains alive, since it's attached to progA.
// Set and compile source for fragA.
glLinkProgram(progA);
glUseProgram(progA);
GLuint progB = glCreateProgram();
GLuint vertB = glCreateShader(GL_VERTEX_SHADER);
glAttachShader(progB, vertB);
glDeleteShader(vertB);
// vertB remains alive, since it's attached to progB.
// Set and compile source for vertB.
glAttachShader(progB, fragA);
// Even though we called delete for fragA, we can still use it, since the reference in progA kept it alive.
glLinkProgram(progB);
glUseProgram(progB);
// progA, vertA, fragA, progB, and vertB are all still alive.
glDeleteProgram(progA);
// progA is not referenced anywhere, so it is now deleted.
// Since progA contained the last reference to vertA, vertA is now also deleted.
// progB, vertB and fragA are still valid.
glDeleteProgram(progB);
// progB is the current program, so it remains alive, together with both its attached shaders.
GLint deleteStatus = GL_FALSE;
glGetShaderiv(fragA, GL_DELETE_STATUS, &deleteStatus);
// deleteStatus is GL_TRUE. Note that we could legally use fragA as a name, even though we called glDeleteShader() on it long ago.
glUseProgram(0);
// This releases the last reference to progB, so it is now deleted.
// progB being deleted releases the last reference to vertB and fragA, so both of them are now deleted.
glGetShaderiv(fragA, GL_DELETE_STATUS, &deleteStatus);
// This would now be an error, since fragA is not valid anymore.
No, the order that you delete your shaders is mostly unimportant.
I say mostly, because it would not make much sense to delete your shader before you attach it to and link your GLSL program. Once the program is linked, however, you can do anything you want to the shaders.
Object deletion in OpenGL is handled by the driver and does not necessarily happen immediately. It has to work this way because OpenGL may queue up commands that still reference the object you are trying to delete. If it deleted them immediately, then commands that were already issued but not yet complete would have undefined results. Instead, GL deletes object memory at some time after you call glDelete* (...)
when nothing else holds a reference to it.
The only thing GL will immediately do when you call glDelete* (..)
is release the object name for reuse by a glGen* (...)
command (and unbind it from the current context). Memory reclamation will not happen until some point in the future.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With