2009-02-05 95 views
55

我發現很多時候,OpenGL會通過不繪製任何東西來顯示它失敗。我試圖找到調試OpenGL程序的方法,通過檢查轉換矩陣堆棧等。什麼是調試OpenGL的最佳方式?如果代碼的外觀和感覺像頂點在正確的位置,你怎麼確定它們是?什麼是調試OpenGL的最佳方式?

回答

29

沒有直接的答案。這一切都取決於你想要了解的內容。由於OpenGL是一個狀態機,有時它不會做你期望的,因爲沒有設置所需的狀態或類似的東西。通常,使用glTrace/glIntercept(查看OpenGL調用跟蹤),gDebugger(用於可視化紋理,着色器,OGL狀態等)和紙/鉛筆:)等工具。有時候,這有助於瞭解你如何安裝攝像機以及它正在查看的內容,正在剪輯的內容等。我個人比以前的兩種方法更依賴於最後一個。但是當我可以爭辯深度錯誤的時候,它有助於觀察痕跡。 gDebugger也是唯一的工具,可以有效地用於分析和優化您的OpenGL應用程序。

除了這個工具之外,大部分時間都是人們弄錯了,而且不能用任何工具理解的數學。在OpenGL.org新聞組上發佈代碼特定評論,你永遠不會失望。

+0

有學術許可也是如此,如果你的質量 – Ketan 2009-02-05 22:12:17

+0

由於這個問題仍然流行的了,也許國防部可以對其進行編輯和正確的,現在是免費的? – NoxMortem 2016-03-13 21:31:33

10

GLIntercept是你最好的選擇。從他們的網頁:

  • 將所有OpenGL函數調用保存爲文本或XML格式,並且可以選擇記錄單個幀。
  • 免費攝像頭。圍繞發送到顯卡的幾何圖形飛行,並啓用/禁用線框/背面剔除/視錐體渲染
  • 保存並跟蹤顯示列表。 保存OpenGL幀緩衝區(顏色/深度/模板)前後渲染調用。還可以保存前後圖像的「差異」。
4

對於Mac上的那些人,OpenGL調試器中的buit也很棒。它允許您檢查緩衝區,狀態並幫助查找性能問題。

7

我發現,您可以檢查每一行代碼的犯罪嫌疑人將是錯誤的之後,使用glGetError,但經過這樣做,代碼看起來不是很乾淨,但它的工作原理。

3

gDebugger是一個優秀的免費工具,但不再支持。然而,AMD已經拿起了它的發展,而這個調試器現在被稱爲CodeXL。它既可以作爲獨立應用程序使用,也可以作爲Visual Studio插件使用 - 既可用於本機C++應用程序,也可用於使用OpenGL綁定的Java/Python應用程序,這兩種應用程序均可用於NVidia和AMD GPU。這是一個工具的地獄。

0

Nsight如果你有一個NVidia卡是很好的調試工具。

4

什麼是調試OpenGL的最好方法是什麼?

沒有考慮額外和外部工具(其他答案已經這樣做)。

話,一般的辦法是廣泛地調用glGetError()。然而更好的選擇是使用Debug OutputKHR_debugARB_debug_output)。這爲您提供了爲不同嚴重級別消息設置回調的功能。

爲了使用調試輸出,上下文必須使用WGL/GLX_DEBUG_CONTEXT_BIT標誌創建With GLFW this can be set with the GLFW_OPENGL_DEBUG_CONTEXT window hint

glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE); 

請注意,如果上下文不是調試上下文,則不能保證接收所有甚至任何消息。

無論你是否有一個調試上下文與否可以通過檢查GL_CONTEXT_FLAGS進行檢測:

GLint flags; 
glGetIntegerv(GL_CONTEXT_FLAGS, &flags); 

if (flags & GL_CONTEXT_FLAG_DEBUG_BIT) 
    // It's a debug context 

這樣,你會繼續前進,指定一個回調:

void debugMessage(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, 
        const GLchar *message, const void *userParam) 
{ 
    // Print, log, whatever based on the enums and message 
} 

的枚舉can be seen on here每個可能值。特別要記住要檢查嚴重性,因爲有些消息可能只是通知而不是錯誤。

您現在可以提前完成註冊回調。

glEnable(GL_DEBUG_OUTPUT); 
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); 
glDebugMessageCallback(debugMessage, NULL); 

glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE); 

你甚至可以使用glDebugMessageInsert()注入自己的消息。

glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, 
        GL_DEBUG_SEVERITY_NOTIFICATION, -1, "Vary dangerous error"); 

當涉及到着色器和程序,你總是希望被檢查GL_COMPILE_STATUSGL_LINK_STATUSGL_VALIDATE_STATUS。如果他們中的任何一個反映出有問題,那麼另外總是檢查glGetShaderInfoLog()/glGetProgramInfoLog()

GLint linkStatus; 
glGetProgramiv(program, GL_LINK_STATUS, &linkStatus); 

if (!linkStatus) 
{ 
    GLchar *infoLog = new GLchar[infoLogLength + 1]; 
    glGetProgramInfoLog(program, infoLogLength * sizeof(GLchar), NULL, infoLog); 

    ... 

    delete[] infoLog; 
} 

通過glGetProgramInfoLog()返回的字符串將空終止。


你也可以去多一點極端,利用在調試版本的幾個調試宏。因此,使用glIs*()函數來檢查預期類型是否也是實際類型。

assert(glIsProgram(program) == GL_TRUE); 
glUseProgram(program); 

如果調試輸出是不可用,你只是想用glGetError(),那麼你當然可以這樣做。

GLenum err; 
while ((err = glGetError()) != GL_NO_ERROR) 
    printf("OpenGL Error: %u\n", err); 

因爲一個數字錯誤代碼是不是有幫助的,我們可以把它多一點人類可讀通過映射的數字錯誤代碼的消息。

const char* glGetErrorString(GLenum error) 
{ 
    switch (error) 
    { 
    case GL_NO_ERROR:   return "No Error"; 
    case GL_INVALID_ENUM:  return "Invalid Enum"; 
    case GL_INVALID_VALUE:  return "Invalid Value"; 
    case GL_INVALID_OPERATION: return "Invalid Operation"; 
    case GL_INVALID_FRAMEBUFFER_OPERATION: return "Invalid Framebuffer Operation"; 
    case GL_OUT_OF_MEMORY:  return "Out of Memory"; 
    case GL_STACK_UNDERFLOW: return "Stack Underflow"; 
    case GL_STACK_OVERFLOW: return "Stack Overflow"; 
    case GL_CONTEXT_LOST:  return "Context Lost"; 
    default:     return "Unknown Error"; 
    } 
} 

然後檢查它是這樣的:

printf("OpenGL Error: [%u] %s\n", err, glGetErrorString(err)); 

那還不是很有益的或更好的直觀的說,好像你已經撒了幾glGetError()在這裏和那裏。然後找到哪一個記錄錯誤可能會很麻煩。

再次宏來救援。

void _glCheckError(const char *filename, int line) 
{ 
    GLenum err; 
    while ((err = glGetError()) != GL_NO_ERROR) 
     printf("OpenGL Error: %s (%d) [%u] %s\n", filename, line, err, glGetErrorString(err)); 
} 

現在只需像這樣定義一個宏:

#define glCheckError() _glCheckError(__FILE__, __LINE__) 

,瞧,現在你可以選擇你想要的一切後打電話glCheckError(),並在錯誤的情況下,它會告訴你確切的文件和行是檢測到。

0

動態更新窗口標題對我來說很方便。

示例(使用GLFW,C++ 11):

glfwSetWindowTitle(window, ("Now Time is " + to_string(glfwGetTime())).c_str()); 
相關問題