2014-06-11 17 views

回答

3

不,您刪除着色器的順序是主要是不重要。

我說的主要是因爲在附加到GLSL程序並鏈接GLSL程序之前刪除着色器沒什麼意義。然而,一旦程序被鏈接,你可以做任何你想要的着色器。

OpenGL中的對象刪除由驅動程序處理,並不一定立即發生。它必須以這種方式工作,因爲OpenGL可能會對仍然引用您要刪除的對象的命令進行排隊。如果它立即刪除它們,那麼已經發布但尚未完成的命令將會有未定義的結果。相反,GL會在某個時間刪除對象內存之後,如果沒有其他人持有引用,則調用glDelete* (...)

當您撥打glDelete* (..)時,GL立即執行的唯一操作是釋放對象名稱,以便glGen* (...)命令重新使用(並從當前上下文中解除綁定)。內存回收不會發生,直到將來某個時候。

+0

這些額外的信息是非常有益的理解。 thx – user1767754

1

是 - 着色器可以按您喜歡的任何順序刪除。 Create/Delete遵循與原始內存塊相同的語義,如malloc/free

1

不要給予好評的是,僅僅通過:)

voidDeleteShader(uintshader)

傳遞如果着色器沒有連接到任何程序對象,它是立即刪除。否則,着色器被標記爲刪除,並且在不再附加到任何程序對象時將被刪除。如果某個對象被標記爲刪除,則其布爾狀態位DELETE_STATUS設置爲true。

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

4

簡單的答案是:沒關係。您可以在任何時候將它們刪除,然後它們將繼續保持活動狀態,直到它們不再被引用爲止。

着色器生命週期的細節經常被誤解。規範中的關鍵字是:

當着色器對象或程序對象被刪除時,它會被刪除,但其名稱保持有效,直到基礎對象可以被刪除,因爲它不再被使用。着色器對象在附加到任何程序對象時正在使用。程序對象在任何情況下都是當前程序使用。

這在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. 
+0

事實上,這就是爲什麼3D實驗室可能是唯一真正認爲將着色器對象稱爲「對象」的人首先是一個好主意= P附加和分離是(*或者至少是這樣,直到FBO出現並重新用*)與其他所有對象完全不同,就像刪除時的行爲一樣。它們完全僞裝成GL對象;他們不適合。 –

+0

所以它就像一個智能指針,在那裏你可以釋放引用,但是當沒有對象指向它並且glDeleteShader被調用時,刪除將會發生? – user1767754

+0

@ user1767754或多或少。順便說一句,非常好的答案,'+ 1'。 –