2013-11-22 31 views
40

我的應用程序從網絡獲取數據並在場景中繪製它(場景使用手工製作的OpenGL引擎)。X因爲應用程序掛起(使用C++,Qt,OpenGL)

它可以工作幾個小時。當我不使用我的桌面時,由於顯示器電源管理器信號(dpms),我的顯示器關閉。然後,當我觸摸鼠標或鍵盤時,顯示器打開,應用程序掛起(X也掛起)。

如果我做 xset -dmps 操作系統不使用dpms並且應用程序工作穩定。

這些問題發生在Centos 6和Archlinux中,但是當我在Ubuntu 12.10下運行應用程序時,它效果很好!

我嘗試了不同的NVidia驅動程序。沒有效果。

我試圖使用SSH來遠程登錄並使用gdb連接到進程。 打開監視器後,我無法在進程表中找到該應用程序。

如何診斷問題?顯示器關閉/打開時會發生什麼(在OpengGL環境中)?使用dpms時,Ubuntu會做些特別的事嗎?

我們猜測問題的原因! 當顯示器關閉時,我們失去了OpenGL上下文。當監視器喚醒時,應用程序掛起(無上下文)。 由於不同的顯示器連接,因操作系統而異的行爲差異:Kubuntu顯示器連接VGA電纜。所以(可能)它對X行爲沒有影響。

+0

你能添加一些日誌嗎? xorg.log和system log –

+4

Archlinux是一種滾動版本的發行版,CentOS是一個面向服務器的發行版,如果你想要很好的多媒體支持和OpenGL功能而不需要太多的努力,你可能是錯誤的一方。 Archlinux有點像Debian Sid(Debian測試有時甚至是最糟糕的),每次我觸摸這個2發行版時,我都遇到與GPU驅動程序幾乎相同的問題,主要是因爲內核和X總是更新到最後一個版本和GPU司機落後。 – user2485710

+0

@ user2485710:目標操作系統是Centos的問題。我們使用Archlinux(Ubuntu)進行開發。 – poljak181

回答

1

您可以先查看X的日誌,通常位於/ var/log /和〜/ .xsession-errors。 OpenGL正在做一些棘手的事情,因此如果你的應用程序有任何日誌記錄將其打開,那就不是問題了。 運行ulimit -c unlimited啓用核心轉儲。您可以通過在gdb像這樣打開它分析轉儲:

gdb <executable file> <core dump file> 

看看是否能產生有用的東西,然後研究無論是。

1

您是否嘗試過使用GL_ARB_robustness爲OpenGL實現添加健壯性支持?

2.6「圖形重置恢復」可能導致GL上下文的重置

某些事件。這種重置 會導致所有上下文狀態丟失。從這種事件中恢復 需要重新創建受影響的上下文中的所有對象。圖形的 當前狀態復位狀態由

enum GetGraphicsResetStatusARB(); 

符號常量返回返回指示是否因爲對 GetGraphicsResetStatusARB最後一次通話的GL方面一直處於 復位狀態在任何點。 NO_ERROR指示自上次調用以來,GL上下文的 未處於重置狀態。 GUILTY_CONTEXT_RESET_ARB指示已檢測到 歸因於當前GL上下文的重置。INNOCENT_CONTEXT_RESET_ARB 指示檢測到不歸於當前GL上下文的重置。 UNKNOWN_CONTEXT_RESET_ARB指示檢測到的 圖形重置,其原因未知。

此外,確保在初始化上下文時使用調試環境,並使用ARB_debug_output擴展接收日誌輸出。

void DebugMessageControlARB(enum source, 
          enum type, 
          enum severity, 
          sizei count, 
          const uint* ids, 
          boolean enabled); 

void DebugMessageInsertARB(enum source, 
          enum type, 
          uint id, 
          enum severity, 
          sizei length, 
          const char* buf); 

void DebugMessageCallbackARB(DEBUGPROCARB callback, 
          const void* userParam); 

uint GetDebugMessageLogARB(uint count, 
          sizei bufSize, 
          enum* sources, 
          enum* types, 
          uint* ids, 
          enum* severities, 
          sizei* lengths, 
          char* messageLog); 

void GetPointerv(enum pname, 
       void** params); 

例如:

// Initialize GL_ARB_debug_output ASAP 
if (glfwExtensionSupported("GL_ARB_debug_output")) 
{ 
    typedef void APIENTRY (*glDebugMessageCallbackARBFunc) 
      (GLDEBUGPROCARB callback, const void* userParam); 
    typedef void APIENTRY (*glDebugMessageControlARBFunc) 
      (GLenum source, GLenum type, GLenum severity, 
      GLsizei count, const GLuint* ids, GLboolean enabled); 
    auto glDebugMessageCallbackARB = (glDebugMessageCallbackARBFunc) 
      glfwGetProcAddress("glDebugMessageCallbackARB"); 
    auto glDebugMessageControlARB = (glDebugMessageControlARBFunc) 
      glfwGetProcAddress("glDebugMessageControlARB"); 
    glDebugMessageCallbackARB(debugCallback, this); 
    glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, 
      GL_DEBUG_SEVERITY_LOW_ARB, 0, nullptr, GL_TRUE); 
} 

...

std::string GlfwThread::severityString(GLenum severity) 
{ 
    switch (severity) 
    { 
    case GL_DEBUG_SEVERITY_LOW_ARB: return "LOW"; 
    case GL_DEBUG_SEVERITY_MEDIUM_ARB: return "MEDIUM"; 
    case GL_DEBUG_SEVERITY_HIGH_ARB: return "HIGH"; 
    default: return "??"; 
    } 
} 

std::string GlfwThread::sourceString(GLenum source) 
{ 
    switch (source) 
    { 
    case GL_DEBUG_SOURCE_API_ARB: return "API"; 
    case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB: return "SYSTEM"; 
    case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB: return "SHADER_COMPILER"; 
    case GL_DEBUG_SOURCE_THIRD_PARTY_ARB: return "THIRD_PARTY"; 
    case GL_DEBUG_SOURCE_APPLICATION_ARB: return "APPLICATION"; 
    case GL_DEBUG_SOURCE_OTHER_ARB: return "OTHER"; 
    default: return "???"; 
    } 
} 

std::string GlfwThread::typeString(GLenum type) 
{ 
    switch (type) 
    { 
    case GL_DEBUG_TYPE_ERROR_ARB: return "ERROR"; 
    case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB: return "DEPRECATED_BEHAVIOR"; 
    case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB: return "UNDEFINED_BEHAVIOR"; 
    case GL_DEBUG_TYPE_PORTABILITY_ARB: return "PORTABILITY"; 
    case GL_DEBUG_TYPE_PERFORMANCE_ARB: return "PERFORMANCE"; 
    case GL_DEBUG_TYPE_OTHER_ARB: return "OTHER"; 
    default: return "???"; 
    } 
} 

// Note: this is static, it is called from OpenGL 
void GlfwThread::debugCallback(GLenum source, GLenum type, 
           GLuint id, GLenum severity, 
           GLsizei, const GLchar *message, 
           const GLvoid *) 
{ 
    std::cout << "source=" << sourceString(source) << 
       " type=" << typeString(type) << 
       " id=" << id << 
       " severity=" << severityString(severity) << 
       " message=" << message << 
       std::endl; 
    AssertBreak(type != GL_DEBUG_TYPE_ERROR_ARB); 
} 

你幾乎可以肯定有一個體面的OpenGL實現這兩個擴展使用。他們幫助,很多。調試上下文對所有內容進行驗證並向日志投訴。他們甚至在一些OpenGL實現中的日誌輸出中給出性能建議。使用ARB_debug_output使檢查glGetError已過時 - 它會檢查你的每一個電話。

相關問題