2013-07-29 93 views
0

我一直在注意到我的程序中存在一個小內存泄漏,並且我終於能夠找出問題所在。在draw-call中使用glDisable(GL_TEXTURE_2D)時發生內存泄漏

我在做什麼,通過調用這個函數抽出5個矩形屏幕:

bool OpenGlEntity::fillRect(SDL_Rect rect, float R, float G, float B, float A){ 

glPushMatrix(); 

    glDisable(GL_TEXTURE_2D); 

    GLfloat vertices_position[] = { 
    (GLfloat)rect.x, (GLfloat)rect.y, 
    (GLfloat)(rect.x+rect.w), (GLfloat)rect.y, 
    (GLfloat)(rect.x+rect.w), (GLfloat)(rect.y+rect.h), 
    (GLfloat)rect.x, (GLfloat)(rect.y+rect.h), 
    }; 

    glTranslatef(0, 0, 0); 
    //scale 
    glScalef(1,1,1); 
    //set color 
    glColor4f(R, G, B, A); 

    glEnableClientState(GL_VERTEX_ARRAY); 
    glVertexPointer(2, GL_FLOAT, 0, vertices_position); 

    glLockArraysEXT(0, 4); 

    glDrawArrays(GL_QUADS, 0, 4); 

    glUnlockArraysEXT(); 

    glDisableClientState(GL_VERTEX_ARRAY); 

    glEnable(GL_TEXTURE_2D); 
    //reset color 
    glColor4f(1.f, 1.f, 1.f, 1.f); 

glPopMatrix(); 

return true;} 

如果我從來沒有運行「glDisable(GL_TEXTURE_2D);」 (或「glEnable(GL_TEXTURE_2D);」)泄漏不會發生。爲什麼是這樣?

對我來說,它並沒有太多意義,但是我再也沒有那麼經歷過OpenGL渲染。

回答

0

有許多原因可以讓你認識到啓用或禁用特定狀態導致內存「泄漏」。例如,如果在紋理上啓用三線過濾並且紋理不包含mipmap數據,則驅動程序通常會爲mipmap鏈/金字塔(無論是否生成實際的mipmap級別)分配內存。僅僅因爲你改變了紋理過濾器狀態,這會導致內存消耗增加約33%。

順便說一下,繪製調用並不是真正的增加內存的來源。繪製調用通常是驅動程序提交排隊命令的一個點。這就是爲什麼你無法計算glEnable(...)或glDisable(...)的調用持續時間,並獲取更改該狀態的開銷。智能驅動程序將貫穿最後一次繪製調用和當前狀態之間的所有狀態變化請求,這是大多數狀態設置確實發生的時候。因此,在您的情況下,驅動程序可能會推遲一些紋理設置操作,直到紋理單元和/或對象第一次被綁定和啓用。因此,當您發出您的繪圖調用時,驅動程序在執行它的任務清單時爲其分配內存。

想要描繪一個應用程序,看看glDraw(...)看起來是你的瓶頸,並假設你是頂點綁定的,但在很多情況下這不能離真相更遠:)這是隻是需要更多專用工具和API纔能有效調試,跟蹤內存資源分配以及使用GPU的配置文件應用程序的衆多原因之一。

在任何情況下,您所遇到的可能性都是正常行爲,驅動程序必須在多個位置(CPU,GPU等)分配內存來處理「設備丟失」等事件。如果「泄漏」是一次性發生,您可以忽略它並將其記錄到驅動程序內存管理中。

+0

感謝您提供非常詳細的答案。內存泄漏每秒大約100-200kb,只要引起它的東西被吸引,似乎就不會停下來。 我不知道爲什麼會發生這樣的事情。它有助於向您展示我的紋理項目的渲染代碼? – Tallkotten

+0

這是一個很好的問題,實際上......我注意到你根本沒有使用OpenGL的對象模型(並且使用過時的Compiled Vertex Arrays)。也就是說,不是使用頂點緩衝對象和頂點數組對象來永久存儲頂點數據和狀態,而是每幀發送新數據。我不得不懷疑,如果你是以同樣的方式加載紋理數據?順便說一句:如果你使用glScale/glTranslate,你實際上可以在這個函數中爲任何矩形重新使用一組頂點(一個正方形)。 –

+0

是的,你設置紋​​理對象的代碼會很有幫助。 –

相關問題