glDeleteShader语言 - 是顺序无关

glDeleteShader - is the order irrelevant?

本文关键字:顺序 语言 glDeleteShader      更新时间:2023-10-16

在OpenGL中,glAttachShader的顺序无关紧要,glDeleteShader的顺序是否相同?如果有一些动态内存分配正在进行,我会说是的,但也许这在opengl上下文中处理得不同。

简单的回答是:没关系。在附加到程序后,您可以随时删除它们,并且它们将继续有效,直到不再被引用。

着色器寿命的细节经常被误解。规范中的关键措辞是:

当一个着色器对象或程序对象被删除时,它被标记为删除,但它的名称仍然有效,直到底层对象可以被删除,因为它不再使用。当着色器对象被附加到任何程序对象时,它正在使用。当程序对象在任何上下文中是当前程序时,它正在被使用。

这在GL 4.4规范的第5.1.3节和GL 3.3规范的附录D.1.2中。

因此,与流行的看法相反,着色器名称仍然有效超出glDeleteShader()调用,如果它目前正在使用。这与其他对象类型(如纹理或缓冲区)的名称处理方式不同,在delete调用后,名称立即失效。

下面是一个示例调用序列来说明这些规则:

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.

不,你删除着色器的顺序是大多数不重要。

我说大多数情况下,因为它不会有太大的意义,删除你的着色器之前,你附加到并链接你的GLSL程序。然而,一旦程序被链接,你可以对着色器做任何你想做的事情。

OpenGL中的

对象删除由驱动程序处理,并不一定立即发生。它必须以这种方式工作,因为OpenGL可能会将仍然引用您试图删除的对象的命令排队。如果它立即删除它们,那么已经发出但尚未完成的命令将具有未定义的结果。相反,GL删除对象内存在之后的某个时间你调用glDelete* (...),当没有其他保存对它的引用。

当您调用glDelete* (..)时,GL将立即做的唯一事情是释放对象名称以供glGen* (...)命令重用(并将其从当前上下文中解绑定)。内存回收将在将来的某个时间点进行。

是-着色器可以按你喜欢的任何顺序删除。Create/Delete遵循与malloc/free相同的语义,用于原始内存块

不要投票,只是路过:)

void DeleteShader (uint shader )

如果shader没有附加到任何程序对象,它将被立即删除。否则,着色器被标记为删除,当它不再附加到任何程序对象时将被删除。如果一个对象被标记为删除,它的布尔状态位DELETE_STATUS被设置为true。

The OpenGL®Graphics System, Version 4.4, Core Profile, 2014年3月19日,第81页。-§7.1 Shader Objects.