簡體   English   中英

將Qt GUI拆分為GUI,模擬和OpenGL的多個線程是否可行?

[英]Is it feasible to split Qt GUI into multiple threads for GUI, simulation, and OpenGL?

我正在試驗Qt的工作中的儀器模擬程序的新布局。 我們當前的sim在一個窗口中運行所有內容(我們使用了glut(舊)和fltk),它使用glViewport(...)glScissor(...)將儀器讀數分成他們自己的視圖,然后它使用某種形式的“ortho2D”調用來創建自己的虛擬像素空間。 模擬器當前更新儀器,然后逐個在各自的視口中繪制每個儀器,所有這些都在同一個線程中。

我們想找到一個更好的方法,我們選擇了Qt。 我正在一些很大的限制下工作:

  1. 每個儀表板仍然需要在其OpenGL視口中。 有很多按鈕和很多樂器。 我的初步解決方案是為每個使用QOpenGLWidget。 我在這方面取得了進展。
  2. SIM不僅僅是一個非常好的讀數,而且還模擬了許多儀器作為儀器設計人員的反饋,因此它有時會有很大的CPU負載。 它不是一個完整的硬件模擬器,但它確實模擬了邏輯。 我不認為告訴儀器在其關聯的小部件的paintEvent(...)方法的開頭更新自己是可行的,所以我希望模擬更新在單獨的線程中運行。
  3. 我們的客戶可能擁有舊計算機,因此排除了更新版本的OpenGL。 我們仍然使用glBegin()glEnd()以及介於兩者之間的所有東西,並且儀器繪制了一堆垃圾變量符號,因此繪制需要花費大量時間,我想將繪制分割成它自己的線程。 我還不知道OpenGL 3是否在桌面上,這對於渲染到屏幕外緩沖區是必要的(我認為)。

問題: QOpenGLWidget沒有可重寫的“update”方法,它只在窗口小部件的paintEvent(...)paintGL(...)調用期間繪制。

暫定解決方案 :將模擬器拆分為三個線程:

  1. GUI:運行用戶輸入, paintEvent(...)paintGL(...)
  2. 模擬器:運行所有儀器邏輯並更新符號系統的值。
  3. 繪圖:將最新的符號系統渲染到屏幕外緩沖區(將使用幀緩沖區對象(FBO))。

在這個設計中,跨線程說話是循環的,單向的,GUI線程提供輸入,模擬器線程在下一個循環中考慮該輸入,繪圖線程讀取最新的符號系統並將其呈現給FBO並設置“下一幀可用”標志為true(或者可能發出信號),然后paintGL(...)方法將該FBO並將其吐出到小部件,從而保持事件處理能力下降和GUI響應能力提高。 繼續這個循環。

底線問題 :我在這里讀到GUI操作無法在單獨的線程中完成,所以我的方法是否可行?

如果可行,任何其他謹慎或建議將不勝感激。

每個OpenGL小部件都有自己的OpenGL上下文 ,這些上下文是QObject ,因此可以移動到其他線程。 與任何其他非線程安全對象一樣,您只應從其thread()訪問它們。

另外 - 這也可以移植到QML - 您可以使用工作器函數來計算顯示列表,然后將其提交到渲染線程以轉換為繪制調用。 渲染線程不做任何邏輯並且不計算任何東西:它接受數據(頂點數組等)並提交它以進行繪制。 工作QtConcurrent::run函數將使用QtConcurrent::run提交在線程池上QtConcurrent::run

因此,您可以擁有一個主線程,一個渲染線程(可能每個小部件一個,但不一定),以及運行模擬步驟的仿函數。

無論如何,卷積邏輯和渲染是一個非常糟糕的主意 無論您是在柵格小部件上使用QPainter進行繪制,還是在QOpenGLWidget上使用QPainter ,或者使用直接OpenGL調用,執行繪圖的線程都不應該計算要繪制的內容。

如果您不想搞亂OpenGL調用,並且您可以將大部分工作表示為基於數組的QPainter調用(例如drawRectsdrawPolygons ),則這些調用幾乎直接轉換為OpenGL繪制調用,而OpenGL后端將使它們呈現為很快,好像你手動編寫了繪制調用。 如果你在QOpenGLWidget上使用它, QPainter會為你做這QOpenGLWidget

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM