简单的答案是:没关系。您可以在将它们附加到程序后随时删除它们,并且它们将继续保持活动状态,直到不再被引用为止。
着色器生命周期的细节经常被误解。规范中的关键词是:
当着色器对象或程序对象被删除时,它会被标记为删除,但它的名称仍然有效,直到基础对象可以被删除,因为它不再使用。着色器对象在附加到任何程序对象时正在使用。当程序对象是任何上下文中的当前程序时,该程序对象正在使用中。
这位于 GL 4.4 规范的第 5.1.3 节和 GL 3.3 规范的附录 D.1.2 中。
因此与普遍的看法相反,着色器名称仍然有效超过glDeleteShader()
如果当前正在使用,请调用。这与其他对象类型(例如纹理或缓冲区)的名称处理方式不同,其中名称在删除调用后立即变得无效。
这是说明这些规则的调用序列示例:
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.