glDeleteShader - 订单无关紧要?

时间:2014-06-11 21:35:10

标签: c++ opengl

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

4 个答案:

答案 0 :(得分:7)

简单的答案是:没关系。您可以在附加到程序后随时删除它们,并且它们将继续保持活动状态,直到它们不再被引用为止。

着色器生命周期的细节经常被误解。该规范的关键措辞是:

  

当删除着色器对象或程序对象时,会删除它,但它的名称仍然有效,直到可以删除基础对象,因为它已不再使用。着色器对象在附加到任何程序对象时正在使用。程序对象正在使用,而它是任何上下文中的当前程序。

这是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.

答案 1 :(得分:4)

不,您删除着色器的顺序是 主要是 不重要。

我主要是说,因为在将着色器附加到GLSL程序并链接之前删除着色器没有多大意义。但是,一旦链接了程序,您就可以对着色器执行任何操作。

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

当您调用glDelete* (..)时,GL将立即执行的唯一操作是释放对象名称以供glGen* (...)命令重用(并从当前上下文取消绑定)。内存回收不会在将来的某个时刻发生。

答案 2 :(得分:1)

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

答案 3 :(得分:1)

不要赞成,只需经过:)

  

void DeleteShader (uint shader )

     

如果着色器未附加到任何程序对象,则会立即将其删除。否则,着色器将被标记为删除,并且当它不再附加到任何程序对象时将被删除。如果对象被标记为删除,则其布尔状态位DELETE_STATUS将设置为true。

The OpenGL® Graphics System, Version 4.4, Core Profile,2014年3月19日,p。 81. - §7.1着色器对象。