Home

Milo的遊戲開發

Larrabee

傳聞聽了很多,但直到最近看了一篇 SIGGRAPH 文章 才真正開始去了解 Intel 的 Larrabee。我的理解還是很淺,有錯請更正。

如果要用一句說話形容我對Larrabee的理解,

把多個順序執行指令(in-order) 的 x86 內核塞進一個芯片,每個內核可執行大部份 x86 指令、16維向量指令及小量新指令,並且有獨立的L2 cache和小量為圖形功能而設的邏輯單元。

對於圖形及高度平行的應用,現時 GPU 比 CPU 更有效率。這是因為這些應用是可以分柝成為較小的獨立工作,分配在 GPU 中的多個硬件單元執行。而在圖形處理上,GPU 加入許多不可編程的圖形功能邏輯硬件,例如紋理取樣 (Texture Sampling)、光柵化 (Rasterization)、內插 (intepolation) 等等。使用數個通用的 CPU 內核去運行,完全不敵數十個為圖形特製的 GPU 內核及圖形功能邏輯硬件。

Larrabee 怎樣挑戰 CPU 和 GPU

Intel 不會輕易言敗,於是發展了 Larrabee。

Larrabee 有多個設計概念:

  1. x86 指令的核心比 GPU 的 shader 指令更普及。只要可編譯成為 x86 指令的程式都可在 Larrabee 上執行,例如目前大量的 C/C++ 程序。
  2. GPU 使用完全獨立的內存,CPU 和 GPU 間的數據流通是不透明的,而且數據的格式很特殊及有限 (例如 vertex/index buffer, texture 等等)。Larrabee 則能直接存取主內存,因此可以使用指針、不同的數據結構、甚至物件導向 (如 virtual function)。
  3. 儘管 DirectX 10 和 11 不斷加入新的 shader 類型,GPU 可編程的地方仍然有限。Larrabee 則希望只有少量的圖形功能邏輯硬件,其餘使用程式,加強可編程性及自由度。
  4. Intel 的 CPU 自 Pentium 4 以來,加入大量非順序 (Out-of-Order, OOO) 執行指令的邏輯,使用電量(熱量!)及晶片面積不斷增加。但數據顯示,一個雙內核 OOO CPU 的晶片面積,其實可以放入 10 個 in-order、每個有 16 維向量處理器的內核。可是,後者的 FLOPS 峰值是前者的 40x 。

Larrabee 和遊戲開發的推測

Larrabee 會對於遊戲開發者有甚麼影響呢?

推測一:無直接影響,Larrabee 只是替代 ATI、NVidia 和 Intel 的 GPU 而已。該文章花了大量的篇幅描述一個在 Larrabee 上執行的渲染軟件 (software renderer)。它是以光柵化 (rasterization) 和目前流行的實時渲染的概念,透過 Larrabee 的各種硬件特性去開發的。最有趣的地方,是他們擷取了 Half-Life2、F.E.A.R.和 Gears of War 的 D3D9 指令及紋理等數據,用 Larrabee 上的軟件渲用。實驗結果是,執行 1600×1200 解像度、60FPS,大概需要 10 至 20 個 1Ghz 的 Larrabee 內核,而且還有非常高的 Scalability。但除了這個結果外,我們可猜測 Intel 有能力及可行性去寫 Larrabee 的 Direct3D 驅動軟件。而且由於 Larrabee 的自由度,Larrabee 可同時支持不同版本甚至不同的圖像API。

推測二: 遊戲用中間件 (middleware) 支持 Larrabee。一些遊戲中間件可以使用 Larrabee 增加效能,例如圖像引擎、物理引擎、人工智能引擎等等。

推測三: 開發者自行編寫為 Larrabee 而設的代碼。從架構上來說,Larrabee 和 Cell 的 SPU 是有相似的地方。開發者可以為遊戲性或特效編寫專用代碼,以製作有獨特遊戲性和特效的遊戲。

推測四: 新的實時圖像渲染時代開始。放棄用了十數年的光柵化式硬體,採用光線追蹤 (Ray tracing) 及其他全局光照 (Global Illumination)。雖然 Larrabee 是第一個試驗品,但若果它成功的話,會完全改寫目前的實時圖像渲染技術,也會帶來很多新的研究。其對實時圖形的影響力可能可以和當年 OpenGL、Direct3D、可編程 GPU 相比。

要做 Visual Studio 樣子的使用者介面? 用 DockPanel Suite 吧!

雖然引擎連1%完成度也沒有,今天開始做遊戲的編輯工具,或者應該說是做工具的原型,一切都當作是實驗吧。

DockPanel Suite 的 Sample Screenshot
(這是 DockPanel Suite 的 Sample,不是 Visual Studio 啊! )

之前已決定採用開源的 DockPanel Suite。它是一個 C# 開源的 .Net 程序庫,基本上做到 Visual Studio.Net 的視窗 docking 功能,包括 tabbed window、split window、float window、docking indicator、auto-hide、讀寫 XML 設定檔等等。我是看到 Cg Composer 的 DLL 才知道有這個 .Net 程序庫,後來也找不到更好的選擇。

繼續閱讀

遊戲開發書庫開張

這幾天花了些時間,整理了一個遊戲開發書庫 (還未完整,有時間會更新及加入短評)。

書對我來說是生活的一部份。自修是最基本的學習方法。有些想讀但未讀,有些讀過又忘記,所以在這個 Blog 裡記錄了一些遊戲相關的書目,方便回顧及展望。當有一天心血來潮,就會重溫過去的書,或者買一些想讀的書回來。

回看這個書目裡面,我第一本買的是 Computer Graphics: Principle and Practice。當時應該就讀高中,書中的內容許多都不能理解。但是一點一滴的累積閱歷,也許可以慢慢地把內容吸收。

在之前數年的工作裡,我可以申請購買許多遊戲相關的書籍(多是頗貴的原文書)。有些讀了一遍,有些我自己沒有讀。現在離開了那些書籍,偶然間,又想重拾起來。

在我這個遊戲書庫內暫時有大約100本書,保守估計平均每本書300頁,而每天能讀 50 頁的話,讀一遍便要 600 天,但這個書庫的內容又會不斷增加…… 突然想起中學讀莊子說的

吾生也有涯,而知也無涯。以有涯隨無涯,殆已!

關於表頭檔的 inline function

閱讀了猴子靈藥《表頭檔要不要?拿速度來換!》後,發覺所言甚是,表頭檔的問題許多時會被忽略。現在寫的代碼,除了考慮執行效率,也應該要考慮編譯效率。

關於在標頭檔寫 inline function 而增加編譯時間,本人有一點看法,就在此和大家分享。

首先,我們知道

Inline function 的目的是增加執行效率,但一般在 debug 版本是不會被展開的,只有在 Release mode 才會用到。

那麼,在編譯 debug 版本中使用 inline function 只會增加編譯的時間。基於這一點,我現時的”引擎” (不知何時才能算是真正的引擎,可以去除引號)的代碼 layout 就使用 macro 去解決這個問題。所有類別的代碼 layout 分為 3 個檔案: header (.h), inline (.inl) 和 implementation (.cpp)。例如:

繼續閱讀

完成 Win32上的OpenGL/Cg

星期六日都坐在家中做 OpenGL/Cg 的移植,比想像中遇到更多問題,但終於在三月最後一個晚上完成。這裡做一個簡單的回顧,希望大家遇到類似的問題時可以減少脫髮。

編譯期選擇圖像 API

之前曾經寫過一篇《跨平台的圖像渲染引擎》,提及使用 abstract factory pattern 或 conditional compilation (macro) 來為圖像 API 抽像化。後者的優點是效能較高 (不需使用 virtual function call),但缺點是代碼難看。為了改善後者的缺點,我想到了使用 inheritance 去避免在 class 的定義裡寫 macros。舉一個例子就會明白。

首先,利用 #include 後可以是一個 macro 的功能 (Visual C++ 裡只可以是一個 macro identifier,而 gcc 可以 expand macro),把平台相關的 header 和 implementation 檔放在同一個地方:

繼續閱讀

新面貌

終於更換了之前的預設 wordpress template。新的 template 維持簡潔風格,字體應該比之前的較容易閱讀。希望大家喜歡。

另外,從上星期日開始做 Linux porting。在 Vmware 上安裝 Ubuntu 來測試。發覺自己完全忘記了 makefile,中途還想放棄去改用 scons。最後還是繼續 GNU make,終於今晚搞定用 makefile 執行 SWIG,不過有點兒 hard code 成份。明天開始做 OpenGL + Cg。

PS. 荷蘭來的舊朋友在我家住了兩天,因他的來到,我們才找附近的好餐廳,吃了兩晚豐富的晚餐。昨晚玩 Wii Sports 和 Wii Fit 玩到一點鐘。
PPS. 問同事借了 PSP 玩 《無限回廊》。這是創意之作,而且我本身又喜愛 M.C. Escher (荷蘭畫家!)。

實時 Radiosity 系統 Enlighten

今天才第一次看到 Geomerics 的 Enlighten 新示範短片(在 GDC2008 發佈),感覺很震撼。雖然在 Radiosity 技術方面和他們一年前的 Tech Demo 的分別可能不大,但結合了 HDR、SSAO 等技術、展示了一些使用者介面即時調效多個光源的設定、人物受到間接光源的效果等等,做出來的整體效果完全不一樣。而且,它說明這技術已實際在 PS3 和 Xbox360 上應用 (雖然沒有影片為證),即是它是可以應用在現今的硬件之上,而不是一些只可期待而不能用的技術。

網站裡介紹了 Enlighten 的工作模式:

  1. 場境需要作一些 pre-processing,但只需要 gemoetry 資料,而不需要 texture、material、lighting 等資料。這和 Precomputed Radiance Transfer (PRT) 的需求一樣。
  2. 使用者的引擎要把場境的 Local Illumination 渲染至 texture space ,交由 Enlighten 計算 Radiosity。
  3. 結合 Radiosity 和 Local Illumination。

使用這種工作模式對美工特別有幫助,因為美工可以即時微調光照效果,而不需使用 Global Illumination 的 Renderer 去花幾十分鐘甚至幾小時去渲染一些只是靜態的 Light Map。我相信除了遊戲之外,電腦動畫及電影特效都應該可以應用這種技術。

要追技術感覺是越來越難。不過我要提醒自己,不要只追求個別的技術,現時需要的應該是做整個遊戲的經驗,gameplay 和相關的工具是我最弱的。

其他類似的技術:

《修改代碼的藝術》

自從看見書評有關一本名為《修改代碼的藝術》(Working Effectively with Legacy Code, by Michael C. Feathers)的書,感覺是工作上很有需要,就急忙走上 amazon訂了這個內地中譯本。昨天收到並讀了幾章,先說一些表面的,看完後再寫讀後感吧。

如同本書的介紹說:

如果不積極地修改、挽救、隨著時間流逝,所有軟件都會不可避免地漸漸變得複雜、難以理解,最終腐化、變質。因此,理解並修改已經寫好的代碼,是每一位程序員每天都要面對的工作,也是開發程序新特性的基楚。

這些話語都像在對我說的。工作上,每天也要去修改一個很大的 code base,看 source code 好像 reverse-engineering 一樣,看到一些代碼甚至會感到沮喪。或許這也是許多這行業的人的經驗吧,可是我卻是非常缺乏這種經驗,因為以前的我比較多是維護自己設計軟件,比較少去修改別人的軟件。

遺留代碼一般所想就是沒有人維護、時代久遠、甚至是很爛的代碼。但作者對遺留代碼的定義和一般所想的很不同:

對我來說,遺留代碼就是沒有編寫相應測試的代碼。

這不是對遺留代碼字面的解釋,而是一個深切的體會。從樂觀的角度看,這定義引申,遺留代碼並不是無藥可救的東西,只是沒有測試程式而已,只要耐心加入測試機制,就可以慢慢地挽救。

作者提供了一連串的修改程式技術,這些技術沒有正統的名稱,所以每個章節的名稱也很長,例如「第22章 要修改一個巨型方法,郤沒法為它編寫測試」。從目錄看到這章的名稱,又令我回想一個月前用了一整天去理解一個幾千行的函數的遭遇。但是,很諷刺地,在這一部份的最後來一章又叫「第24章 當你感到絕望時」。昨天面對代碼而感到無助時,便立刻看了這一章,頓時覺得,我還未到絕望的境地,心態一轉,難題也解決了。

今天讀到 Fake Object 和 Mock Object,開始明白 Edwin 做的 AMOP 有幾偉大。

要寫漂亮的代碼是以往的一個目標,今天覺得,要寫不變成遺留代碼的代碼,是更重要的。如何在遊戲編程中實踐編寫測試是我今天的疑問 (對於圖像、互動的測試等…..),希望看畢本書後有新的體會,再與大家分享。

查看執行文件內容的小工具 Sizer

Sizer 是我無意中發現的一個小工具,可以檢測 EXE 及 DLL 裡的內容,讓你知道裡面的函式和資料各使用了多少空間。

知道了空間的分佈有助優化檔案大小,並且可以找到一些不必要的 dependenices。

使用時,必須生成 PDB 檔,讓那個工具可以取得 symbols。

以下節錄了我現時做的 “引擎”的 DLL 的大小分佈 (佔大部份是 static-link 的 Lua 引擎):

繼續閱讀

使用 Custom Build Tool 執行 SWIG

今晚完成了近期的第三個目標,加入 Script Module 的 Binding (其實只是一個叫 Runtime 的類別),利用 C# 去執行之前的 Lua 的程序 (test1.lua)。

今早 Edwin 的回應啟發了一些想法,所以著手更改 SWIG 在 Visual Studio 的編譯方法。

現在採用了Visual Studio 的 Custom Build Rule。由於 Lua 和 C# 需要不同的規則,所以要兩個 file extensions,我設定 Lua 的 Swig Interface 檔案為 .li,C# 則是 .ci。

Lua

swig
 -c++
 -lua
 -o $(OutDir)/$(InputName)Lua.cxx
 "$(InputPath)"

C#

swig
 -c++
 -csharp
 -o $(OutDir)/$(InputName)Cs.cxx
 -outdir $(OutDir)
 -namespace Mil.$(InputName)
 -dllimport $(TargetName)
 "$(InputPath)"

生成的檔案會放置於 Debug 或 Release 的輸出目錄,解決之前兩個 configuration 會互相影響的問題。

兩個規則分別生成 $(OutDir)/$(InputName)Lua.cxx 和 $(OutDir)/$(InputName)Cs.cxx,這些檔案需要加入 Project 裡。但因為一個項目不應該同時加入 Debug 和 Release 版的這些檔案,我想到的方法是寫一個 .cpp 去 #include 這些檔案,例如:

// MathCs.cpp
#include "stdafx.h"
#include "MathCs.cxx"

之後再把 Project 的 Include path 加入 “$(OutDir)”,那麼,就可以正確地編譯現時 Configuration 的 Swig 生成檔案。

後來再試驗檔案的 Additional Dependencies 屬性,設定單一檔案仍然不成功。之後我把 .li 和 .ci 裡 include 的檔案改名為 .lii 和 .cii,希望只要可設置 dependencies 為 *.lii 和 *.cii 就可以了,但都不成功。或許可以用 Pre-Build Event 去檢查這些檔案,如比輸出檔案新就 touch 那個 .li 或 .ci。不過未嘗試。

最後,還有一個問題是 C# 的 Proxy 需要編譯多個由 SWIG 生成 .cs 檔案。我找了一回才發現 C# 沒有 #include、也似乎沒有機制可以編譯 *.cs 等多個檔案。最後暫時用 C++ Project 的 Post-Build Event 把適當 Configuration 的檔案拷貝到 C# 的項目裡,再人手加入這些檔案。

copy $(OutDir)\*.cs ..\MilCs

Home

Search
Feeds
Meta

Return to page top