2011-03-09 101 views
19

本主題與任何優化問題一樣,受到很大沖擊,但我無法找到我想要的東西。OpenGL低級性能問題

很多教程,甚至SO問題都有類似的提示;通常覆蓋:

  • 使用GL面剔除(OpenGL的函數,而不是現場邏輯)
  • 僅發送1點矩陣到GPU(projectionModelView組合),因此每個模型減小MVP計算從每個頂點到一次(因爲它應該是)。
  • 使用交錯頂點
  • 儘量減少多達GL調用越好,一批酌情

,可能幾個/許多其他問題。我(出於好奇的原因)使用幾個頂點緩衝區在我的應用程序中渲染了2800萬個三角形。我已經嘗試了所有上述技術(據我所知),並且幾乎沒有收到性能改變。

雖然我在我的執行過程中接收到大約40FPS的數據,但這並不是問題,我仍然對這些優化的「提示」實際使用的位置感到好奇嗎?

我的CPU在渲染過程中空轉大約20-50%,因此我假設爲我是用GPU來提高性能的。

注:我期待到gDEBugger此刻

跨張貼在Game Development

回答

25

1點是顯而易見的,因爲是節約填充率。如果首先處理物體背面的圖元,則會忽略這些面。然而現代GPU容忍透支相當好。我曾經(GeForce8800 GTX)在重大性能受到影響之前測量了多達20%的透支。但最好將這個儲備保留下來,比如遮擋剔除,混合幾何圖形的渲染等等。

點2是沒有意義的。這些矩陣從未在GPU上計算過 - 如果不計算SGI Onyx的話。矩陣總是隻是在CPU上計算的某種渲染全局參數,然後被推入GPU中的全局寄存器,現在稱爲統一體,所以加入它們只有很小的好處。在只保存一個額外的向量矩陣乘法(歸結爲4條MAD指令)的着色器中,代價是算法靈活性較低。第3點是關於緩存效率。屬於一起的數據應該適合高速緩存行。

第4點是關於防止狀態變化垃圾緩存。但它強烈依賴於GL所稱的他們的意思。改變制服便宜。切換紋理非常昂貴。原因是,一個統一坐在寄存器中,而不是一些緩存的內存。切換着色器價格昂貴,因爲不同的着色器會表現出不同的運行時行爲,因此會破壞流水線執行預定義,更改內存(從而更改緩存訪問模式等)。

但這些都是微觀優化(其中一些具有巨大的影響)。不過,我建議尋求大的影響優化,例如實施早期Z通行證;在Z早期使用遮擋查詢來快速區分整個幾何批次。一個大的影響優化,主要包括總結許多類似微觀優化的Point-4,是通過昂貴的GL狀態來對渲染批次進行排序。所以把所有的東西都用普通的着色器分組,在這些組中按紋理排序等等。此狀態分組只會影響可見的渲染過程。在早期的Z中,你只是在Z緩衝區上測試結果,所以只有幾何變換,碎片着色器纔會通過Z值。

+0

非常好!謝謝。 – 2011-03-09 10:36:25

+1

非常好的答案。有一個問題,在你對第2點的回答中,我有點困惑。我比較了着色器內部具有「model * projection * view」的差異(因爲統一變量,每次模型更改時發送模型視圖);與每個模型更新的單個統一矩陣變量(模型視圖投影)相比較,該模型由CPU而不是每個頂點計算(一次)。當然,這會節省很多計算? – dcousens 2011-03-09 11:25:45

+3

@Daniel:你通常不會在着色器中計算MVP矩陣。你所做的是首先執行計算modelview_position = MV * vertex_position,然後clip_position = P * modelview_position。這背後的原因是,對於某些算法,您需要模型視圖中轉換的頂點位置,而不僅僅是整個投影過程的最終結果。此外,頂點法線僅由MV的逆轉置來轉換,而不是完整的MVP^T^-1,所以這是另一個原因:如果要實現光線良好,則需要這些轉換後的法線。 – datenwolf 2011-03-09 11:33:00

1

這很大程度上取決於您正在運行的特定硬件以及使用場景是什麼。 OpenGL的性能提示對於一般情況是有意義的 - 畢竟,該庫是對許多不同驅動程序實現的抽象。 驅動程序製造商可以自由地進行優化,但是他們希望在引擎蓋下進行優化,以便他們可以在您不知情的情況下移除冗餘狀態更改或執行其他優化。在另一臺設備上,他們可能不會。最好堅持最佳實踐,以便在各種設備上獲得更好的性能。

+0

嗯,我想這可以看作是針對OpenGL的更少的優化,以及更接近圖形編程的良好(和性能獎勵)習慣。 – dcousens 2011-03-09 11:46:50

+0

最佳使用當前硬件加速圖形庫的一些一般經驗法則是:不要經常更改狀態和批量批處理批處理。然而,優化規則並不是在不同代硬件上建立的,現在的情況並非如此,對於所有過去的硬件來說都不是這樣,而且未來的硬件可能並非如此。始終欣賞緩存以及您正在使用的硬件的限制和優勢。 – Luther 2011-03-09 11:55:54

+0

我聽說的理由是,針對特定硬件進行優化是愚蠢的行爲,因爲行爲可能會在硬件世代之間甚至是驅動程序版本之間發生根本變化。您最好對API進行優化(在這種情況下,如前所述,最小狀態變化),並讓硬件趕上無法再優化的地方。 – Jherico 2012-12-27 07:27:51

3
  1. 沒有意義的驅動程序可以結合這些矩陣爲你(它知道他們的制服,所以平局通話過程中不會改變)。
  2. 只有當你的CPU必然

你需要知道的第一件事情就是到底是你的瓶頸。 GPU不是答案,因爲它是一個複雜的系統。實際的問題可能是其中:

  • 着色處理(頂點/片段/幾何)
  • 填充率
  • 繪製調用數
  • GPU < - > VMEM(這其中交織和更小的紋理幫助)
  • 系統總線(流的一些數據的每一幀?)

您需要進行一系列的測試,看看親blem。例如,將所有內容都繪製到更大的FBO上,以查看它是否是填充率問題(或者增加MSAA量)。或者抽出一切兩次來檢查繪製的呼叫超載問題。

+0

你能解釋一下爲什麼你說只有在應用程序被CPU綁定時才應該完成批處理? – ashishsony 2013-02-13 11:18:27

+0

(最初的答案是在2.5年前給出的,所以我試圖回想我在想什麼......)。在GPU方面,單次調用與其中的兩半之間有一點區別。這是在驅動程序方面的調用準備就緒,這是在CPU上完成的。 – kvark 2013-11-14 15:19:10

3

只需將我的2美分添加到@kvark和@datenwolf答案中,我想說的是,儘管您提到的要點是「基本」GPU性能提示,但更多涉及的優化依賴於應用程序。

在你幾何重的測試案例中,你已經投擲了2800萬個三角形* 40 FPS = 1120萬個三角形每秒 - 這已經相當多:大多數(並非所有,尤其是費米)GPU都有一個三角形設置每GPU時鐘週期性能爲1個三角形。這意味着以800MHz運行的GPU不能處理每秒超過8億個三角形;這甚至沒有繪製單個像素。 NVidia Fermi每個時鐘週期可以處理4個三角形。

如果你達到了這個限制(你沒有提到你的硬件平臺),那麼在OpenGL/GPU級別你可以做的不多。您只需發送更少的幾何體,通過更高效的剔除(平截頭體或閉塞)或通過LOD方案。

另一件事是,小的三角形傷害填充率,因爲光柵化器在像素的方塊上進行平行處理;見http://www.geeks3d.com/20101201/amd-graphics-blog-tessellation-for-all/

+0

有趣的鏈接,但它可能已被放大到「三角形和像素降壓」的聲明。而且還主要涉及LOD和其他稍微不同的優化。雖然很好的答案;我沒有指出我的硬件規格,因爲我沒有在尋找硬件的具體提示。 – dcousens 2011-03-11 10:02:23