2008年8月2日 星期六

繪圖執行緒的設計

把繪圖功能分離成一個獨立的Rendering Thread一直是我想要做的一種設計,將遊戲程式的執行緒與繪圖的執行緒分開,理論上在多核心的電腦環境中,可以提高不少的運算效能。但在這裡面,還有個問題 -- Race Condition。

這是個很大的困擾。我要怎麼樣避免遊戲邏輯與繪圖功能存取到相同的繪圖資源物件?舉例來說,繪圖功能在讀取Vertex Buffer內容進行繪圖的時候,如何避免遊戲邏輯將資料寫入同一個Vertex Buffer?

不能將Vertex Buffer這些繪圖資源鎖在執行緒裡,繪圖物件很多,存取頻率又很高,這麼頻繁的上鎖解鎖動作,只會耗掉不必要的效能,沒有多少好處。想了很多,卻一直沒有好的方法。


一直到今年的Game Developer Conference,我看到了這張圖。

兩種模式差異並不大。紅色是遊戲邏輯的執行緒,綠色是繪圖執行緒,中間的藍色代表的是繪圖指令。邏輯執行緒將繪圖指令送到佇列中,繪圖執行緒從佇列中取出指令執行。

一個很簡單的架構,就將邏輯執行緒與繪圖執行緒切了開來。

繪圖執行緒擁有繪圖資源物件的存取權,邏輯執行緒不能直接存取繪圖資源物件,只能透過繪圖指令。這麼一來,就沒有兩個執行緒存取相同資源物件的問題,也就能夠避免Race Condition的發生。

當然了,這只是架構設計,實作層面也應該還有很多目前還沒看到與想到的問題,現在正準備寫個程式來實現這樣的架構,看看到底會面臨什麼樣的問題。

等實做程式出來以後,再來做個記錄吧...

PS. 文章中的圖片,取自Intel在GDC 2008發表的演講內容

Update 8/3 : 在Nebula Device這個引擎上,看到Rendering Thread是採用Proxy Pattern的方式來做,邏輯執行緒中用到的物件都只是Proxy物件,真正的繪圖工作是Proxy所指向的物件來實際執行。這方式也不錯,不過我還是 比較喜歡Command Queue的方式。

沒有留言: