My life as an APE

ゲーム開発、アメリカ生活、その他よしなし事

最近のコメント
へぇ、面白そう。3月21日は土曜日か。日本からだと木曜日に出国しないと出席できないな。ビミョーなスケジュール。(^ ^; NEW (まなか) 当社比3.7xは目を見張るものがありますな。さすが。 (ch3) う~む、以前の Stock Option の税務署との嫌な思い出が脳裏を... 祝、無事乗り切り! P.S. wablog って live.co が禁止ドメインになってるんだ... このコメントにも半角で記入したら弾かれた (- -; ということで、メールアドレスも URLもブランクで失礼 m(_ _)m (まなか) わあ。どきどきした。 勉強になりました。 (ぴらみ) [This is good!] >無事に到着したとしてもCertifiedがついてないと、そのまま闇に葬られることも、時々ある。 いかにもやりそうだよね。USCISとか、IRSとか、DMVとか。 (まる)
最近のトラックバック
米のニュースグループ投稿で井戸の蛙から脱す
前号で、google 検索でニュースグループの投稿記事の探し方を書きました。日本では、ニュースグループはそれほど盛んではありませんが、アメリカでは盛んでメンバーが一万人のもあります。自分が日本である分野でかなりの実力を持ってきたと自負できるようになった、日本...
弁当レシピで楽しい弁当作り
弁当レシピ集-簡単レシピな家庭料理を中心に簡単レシピの弁当レシピを掲載して行く弁当レシピ集です。
子供の権利
この北米コンテキストには共感できる。そしてこの問題は人権の捕らえ方に端を発していると思う。 日本上陸 My life as an APE「何故少女売春がいけないのか、大人がしているのに何故いけないのか?」と子供に聞かれた時に、日本のコンテクストでは「ご両親が悲しむのだ」.....
1 2 次のページ> 1/2page

ゲーム機の技術

コンシューマゲーム機開発&ゲーム開発についての豆知識
Intelの戦略的GPUキラー、Larrabeeの概要がSigraphで発表になるとのことで、Paperが公開された。ライスタライザが手書きできる時代がまた来るとは、目頭があつくなる。

●HW概要
Core2Duo程度のダイ面積(65nmで212平方mm程度)に、Pentium相当のインオーダー・コアを10個集積。各コアには16wayのSIMD-VPUが搭載される。VPU 1エントリあたり最大2flop/サイクルとされる(mad処理)。また、1コアあたり4HWTread。それぞれのHWT毎に独立したレジスタページが用意され、L1キャッシュもおなじくHWT毎に分割される。

それぞれのコアはリングバスで接続され、各コアあたりに256KBのローカルキャッシュが接続される。他コアのローカルキャッシュにはリングバスを経由してアクセスする必要があり、キャッシュ内でのコヒーレンシはHW実装で保たれる。

グラフィクス処理の支援機能として、テクスチャフェッチユニットが搭載され、コプロセッサとして動作する。なお、テクスチャフェッチユニットはL2キャッシュを通して各コアと通信する。テクスチャフェッチの手助けとしてMMUによるPageFault例外がやや唐突にあげられているが、EPICが提唱するMegaTextureとの関連性が伺えて面白い。

と仕様的には、どこのCELL Broadband Engineかと見間違えてしまうような類似性だが、一定のダイ面積にVPUを詰め込むとしたらどうしても似たような設計になってしまうのだろう。私的予想ではPS3のGPUはCELLで来ると思っていたのだけれど、それが実現しなかった(それらしき研究成果は一部に見て取れるが)現在、CELL GPUのあだ花として、是非Larrabeeには花を咲かせてもらいたい。

●コアアーキテクチャについて
基本的にはCBEと同じく良い筋なのでは、と思う。ただこうしたハイパフォーマンスを追求するチップの場合、一点のボトルネックが大きな足かせになることもままあるため、幾つか気になる点を記しておきたい。

基本VPUアーキテクチャについては、Pentium相当のコアを利用するとのこと。この辺はもっと割り切って、Z80移植戦略時代のへその緒のような仕様は切ってしまってもよかったのではないかという気はする。Paper上想定クロックサイクルが1GHzとされているのも、なんとなくPentiumアーキテクチャの所為ではないか、と邪推される。CBEは(多くのものを犠牲にしながらも)3Ghz前後で駆動し、SPUの仕様自体は割り切っていて中々良い。
Larrabeeについても、IA32をベースに大胆にリアーキテクトしてしまうのが清々しい。

VPUが16wayとされているの点は見かけ上のFLOPS値は上昇するが実用上はやや不安だ。HWTが4スレッドとなっている点からも、VPU命令レイテンシが長大であることがみてとれる。HWT数が増えた分、レジスタ数、L1キャッシュエントリが減少するなどの副作用も懸念されるところだ。実運用上、インオーダーコアで複数のHWTが動作しても実行効率はそれほど向上しないのでは、という点も気になる。
追記:Paperでは1コアの理論ピーク値が1GHz駆動時で32GFLOPS(madd換算)とされている。VPU命令は4サイクルに一度しか発行できない、という仕様だろうか?

VPU命令が1エントリあたりmad相当の2flop/cycleというのも、dp3、dp4や...dp16命令が無さそうなことが示唆される。IntelのSIMD系命令セットは代々デベロッパの意見をあえて無視したような実装が多いような印象もあるが、Larrabeeではどうだろうか。

ローカルストアのサイズが256KBというのも実用としては少ない。512KBのローカルストアであれば、アプリケーションの自由度も大幅に上がるのでは、とおもわれる。個人的にはコヒーレンシの管理はなしにして、アドレッシング幅が増えるほうがうれしい。
コヒーレンシの管理にしても、キャッシュアローケーション時にリングバス上でパケットを一周させる必要があり、パケットの流れはEven/Oddサイクルで切り替わるとのことで、バスを一周させるめだけに20サイクル程度のレイテンシがかかってしまうような気もする。また、倍精度処理については「遅くならないとは書いていない」点もみそだ。
なおVPUのアドレッシングについて、レジスタのほかに、L1、L2がアドレッシングできるほか、Scatter.Gather、型変換なども可能で便利にできていそうだ。

●グラフィクス・エンジンについて
Paper後半は、Larrabee上でのグラフィクス・エンジンのリファレンス実装の解説に割かれている。この実装ではタイルベースの描画エンジンで、トライアングル・セットアップの結果をいったんBINに戻して、後のラスタライズパスでBIN毎に描画処理するという実質2パス構成になっている。

この実装による一番のメリットは、通常は描画時に最も帯域を消費する深度バッファとカラーバッファをローカルストアに保持しておける点だろう。通常アプリケーションではバス帯域とシンクロナイゼーションがパフォーマンスを規定するのだが、特にゲームアプリケーションでは帯域がボトルネックになることが多い。このため、バス上の流れを追うことがパフォーマンス向上の第一歩となる。

タイリング処理のメリットによって、アプリケーションで帯域をもっとも消費するのはテクスチャフェッチのアクセスとなる。Paper上ではテクスチャフェッチのレイテンシ(数百サイクルと表記されている)はソフトウェア実装によるファイバのコンテキストスイッチによって補うとされている。気になる点はファイバのコンテキストをローカルストア上におく必要があるため、無尽蔵にコンテキスト保持が行えない、という点だ。

またソフトウェア実装により、パイプライン上のボトルネックやストールをできるだけ減らせている点は非常に好ましい。多くのGPUではトライアングルセットアップやインターポレーションが実用上のボトルネックになるケースもままあるが、そうしたケースを最適化できるというのは心強い。

タイルベースの実装によるデメリットとして、複数タイルにまたがるプリミティブに対して冗長なDataReadが行われる、という点がある。が、Paperによる実装ではタイルサイズが128x128と比較的大きく、またモダンなアプリケーションではプリミティブサイズが細かくなることもあり、タイル分割によるロスは5%前後との計測結果とのことだ。
また、タイルをまたぐMSAA/FSAA処理、フィルタ処理は単一パスで行えない、という点もデメリットとして考えられるが、その辺は実装でどうにでもなる範囲かとは思う。

●実パフォーマンスについて
気になる実パフォーマンスについてだが、シミュレータ上ではほぼ実用的なパフォーマンスが達成され、同程度のダイサイズのHW実装GPUとほぼ同程度と考えてよい雰囲気が醸し出されている。メリットとしては動的にパイプラインを組み替えられるフレキシビリティと、ソフトウェア最適化の余地が大いにあることだろう。

が、前者としてはUnifiedShaderモデルと比較しての優位性はやや立証が難しく、後者に関してはHW実装GPUとのソフトウェア互換性の兼ね合いからあまりに変態的な処理は行えないような気もする。なかなかむずかしいところだ。

●Mike Abrashのこと
ここまでとは全く関係ないが、Paperの執筆者に現RadGameToolsのMike Abrashの名を見て多いに納得してしまった。
Mikeには前職でのチームメイトとして数年お世話になった。当時すでにゲームプログラマ界の大御所でありながら、更に高みを目指し続けるという点で、多いに勉強させてもらったものだ。その後チームを離れてRadGameToolsにうつり、何をしているかというと、7年越しでソフトウェア・レンダリング・パイプラインを実装していると聞いていた。

当時はついにMikeも隠居して趣味のレンダラを書いているのか、と少し寂しく思ったのだが、どうやら全然違ったらしい。お見それしました、申し訳ありません。
なお、彼の他にもLarrabeeのソフトウェア・スタックには界隈のメンバーが続々集結している。この点もありLarrabeeは今後用注目かと思う。

7年越しで物事を遂行できる意思は多いに見習いたい。拙作のスクリプト言語も、7年後には全ての商業ゲームはスクリプト言語でコーディングされることを読んで実装してみた。絶えることなく、細々と続けていきたいものだ。



細々と続けているCriScript(http://www.criscript.com)。
今回はVMの高速化に挑んでみた。高速化は機能実装を進めてから手をつけようと思っていたのだが、魔がさしてちょっと現状を計測してみようと思ってしまったのが運の尽き。

計測に使用したのは↓のサイトにある100x100のマンデルブロート集合を算出するもの。
http://shootout.alioth.debian.org/
こちらのサイトでは各種言語でのベンチマークを比較していて面白い。
C++やJScriptはもちろん、LUAやPython用等等のスクリプトファイルが用意されているのもうれしいところ。

早速Python、LUA(非JIT)と比較計測してみると、、、

Python 2.5.1320msec
LUA 5.1.3190msec
CRIScript 0.9.10690msec
計測環境:WindowsVistaSP1、Core2Duo 2.0Ghz
5回程度計測してベストタイムを採用

遅い、あまりに遅すぎて蝿がとまりそうだ。
これだけ遅いと流石に放置もできないので、予定を繰り上げて最適化することに。

なお、LUA、Pythonと比較しているのは、ゲームエンジンへの組み込み実績としてはダントツLUA、時点Pythonといったところによる。

●準備
最適化環境にはまずはプロファイラが必須。今回はPC上での最適化のためIntelVtuneを使った。
http://www.intel.com/cd/software/products/asmo-na/eng/vtune/239144.htm
Vtuneは30日まで使用可能な評価版が上記リンクからダウンロードできる。
機能的には関数毎の経過時間しかわからないためやや物足りないが、所期の目的としては必要十分だろう。

また、IA32の最適化はPentium3以来なので、マニュアル等も下記から取得。
http://www.intel.com/products/processor/manuals/index.htm
特にOptimizationReferenceManualは有用だ。

●方針
バイトコード実行式のVMの場合、実行時間の最適化を行なう余地は大別して三つ。
1)VM最適化
 VMの実行速度を最適化
2)コード生成最適化
 コンパイラの生成するバイトコード列を最適化
3)元コード
 いわゆる最後の手段としてここでは考えない

汎用性から言うと
VM>>コード生成>>>>>元コード
となるため、このプライオリティで最適化に励むこととする。

IA32は、大抵のコードでIPC(Instruction Per Cycle:1サイクルあたりの命令実行数)が1.0近辺がでるという素晴らしいCPUだ、最高。このため基本的には命令数を削減した分、素直に実行時パフォーマンスが改善すると想定して良いかと思う。(なお、Core2Duoの理論IPCは5だが、理論IPCという場合、命令発行ユニットの幅を示しているだけなので実際の値とは乖離しているのが普通)
一方、例えばIPCが0.2に届かないようなアーキテクチャの場合、パイプライン・ストール/フラッシュをチクチク潰していく様な最適化がより有効になる。

最適化の手順としてはアルゴリズムの最適化が重要と一般に言われる。これは8割5分がた正しく多くのケースでアルゴリズムの最適化がかなり効果的だ。
ただし、残り1割5分のボトルネックを潰していく作業では、アセンブリのリスティング出力を見ながらの最適化がとても重要。とはいえアセンブリを直接、またはインラインアセンブリで書くのではなく、修正はあくまでC++のコード上で行なうのが良い。深いパイプラインを意識した命令並び替えは今日びのコンパイラに任せたほうがずっと楽だし、後述のようにインラインアセンブリコードを含む関数はコンパイラの最適化効率がグッと落ちてしまう。

●最適化作業
まず、VTuneでCRIScriptを計測した場合もほぼ1.0近辺のIPCとなった。いい感じだ。

VMのコードは主に下記のコードに。興味ある方はどうぞ。
ヘッダhttp://criscript.com/trac/browser/inc/cilVm.h
ディスパッチャhttp://criscript.com/trac/browser/src/VM/cil/cilVM.cpp
評価スタックhttp://criscript.com/trac/browser/src/VM/cil/cilVMEvalStack.cpp
変数クラスhttp://criscript.com/trac/browser/src/Parser/variable.cpp
その他大勢http://criscript.com/trac/browser/src/VM/cil/


0)VM処理をswitchからDirectThreadedへ
ContextThreadingの論文を参考にしてswitch処理からDirectThreaded処理へ。

ContextThreading処理を実装するにはJITに近いフレームワークを実装する必要があるため、JIT実装時に先延ばしに。
DirectThreadedにラベルの参照テーブルとテーブル内ラベルへのJumpが必要なためinlineAssemblyを使っている。たいていのコンパイラでInlineAssemblyを使った場合、その関数内の最適化はしないか最低限になるためやや微妙。
果たして、実行速度も変わらず。
なお、GNUの場合はローカルラベルを参照できる&&拡張演算子(この定義は良くないが)が使えるので、もう少し違った結果が出るのかもしれない。

1)バイトコードアクセスをvectorからポインタ経由に
アセンブリ出力をみるとリリースビルドであってもSTLベクタの配列インデックス([])アクセス時に冗長な範囲チェックコードが生成されている。

これはSTL"yvals.h"内の下記定義をコメントアウトすると回避することができる。
#define _SECURE_SCL 1

が、STLヘッダに手を加えるのも感触が悪いので、STL::vectorの使用をVMコアコードから排除することにした。
まずはバイトコードへのアクセスをポインタ経由で行なうように修正。
結果→648.015 msec

2)0)で行なったDirectThreadedディスパッチャのコード生成が芳しくないため、switch文に戻した
結果→552.092 msec.

この段階で20%削減。
このとき、VM上で実行されているバイトコード命令数は計11312209命令。

3)StaticFieldをベクタ配列としていたものをお取り潰し
結果→532.15 msec.

4)EvalStackをベクタ配列としていたものをお取り潰し
結果→359.839 msec.
一気に33%削減。

5)今度は汎用変数クラスCVariableに手をつける
実行インストラクション数を減らす方向で最適化
結果→303msec

6)一通り煮詰ったため、気分転換にコンパイラ・コード生成の最適化に手をつける


バイトコード生成後のストリームに対してパタンマッチングによる最適化を行なう、Peepholeオプティマイザ用のフレームワークを作成して、いくつかの最適化ルーチンを組み入れてみた

元命令数:11312209 inctructions
・フラグチェック命令と条件分岐命令を合成
 命令数:11017964inctructions
・不要なDUP/POP命令を削除
 命令数:10487276inctructions
・for(;;)条件式の分岐命令を最適化
 命令数:9976788inctructions
・for(;;)条件式の分岐命令をさらに最適化
 命令数:9725506 inctructions
・Logical ORのコード生成を最適化
 命令数:8959774 inctructions
・LOOP末尾に出現するld/inc/st命令の合成
 命令数:8429086 inctructions
上記のようなステップで実行命令数を約25%削減した。
結果→220msec

7)evalStackへのアクセスをインデクス→直接ポインタに
結果→203msec

8)evalStackのPOP時の変数内容クリアを最適化
結果→186msec

と、現状がここまで。当初実行時間の73%を削減できた。
まだ各種オペレータの最適化が手付かずのため、もう少し粘りたい。

●ついでにコンパイラの最適化も
ネストが深いスクリプトのコンパイルが妙に遅いという問題が前々からあったため、こちらもボトルネックを同定して最適化。
ボトルネックは LookUpSymbolInformationでの変数参照時の再帰処理時のstring処理。
(cilSymbolInfo.cpp内のCCilCodeGen::LookUpSymbolInformationSub)

元々手を抜いていた部分だったため驚愕のコードに。すみません治します。
これを修正したところ、体感では特定のスクリプトコンパイル時に10倍以上速くなった。めでたしめでたし。

オープンソースのJavaScript実行環境、CriScriptの配布サイトがオープンしたのでちょびっとお知らせ、というか宣伝。公式サイトは英語のみなので一部を日本語で補足。

●概要
CriScriptはゲーム機で使うことを念頭に置いたECMAScript(JavaScript)の実行環境で、JavaScriptコードをバイトコードにコンパイルして実行するもの。去年の中ごろからスペアタイムで開発していて8割がた実装が済んだので暫定公開した。
現状ではPCとXbox360での動作確認済み(ただしサイトでの配布はXbox360のみ)。
最近の大規模プロジェクトの殆どではスクリプトエンジンを積んでいるが、主にLUA、Python、Scheme等が中心。ではJavaScritはどうだろうか、ということで実装したもの。

●オープンソース
配布形態はライブラリとソース、SVNのリポジトリもアクセス可能。ライセンスはBSDライセンスにごく近い独自規約。詳しくはこちら

●SVNリポジトリ
SVNリポジトリへのアクセスはSVN://criscript.com/
ユーザ名:'guest'
パスワード:なし
上記でリポジトリに読み込み権限アクセスできる。

●バグ報告、サポート等
バグについてはサポートサイト上でチケットを開くのがベスト。またはsupport@criscript.comまでメールを。日本語も可能。

まだまだ未完成ではありますが、よろしくおねがいします。
GDC2008もつつがなく終了。

●所感
全般としては欧米タイトルが見事に収穫期を迎えて良かったね、という点が一番。
自分的隠しミッションのひとつとして、和風ゲーム技術のノウハウ、方法論を広く世界に伝える、ということを考えていたものだが、この点についてはもはや第一部完結した感が強い(実際別に自分がどうこうしたのではなく、同時多発的に起こったこと)。ほんの5,6年前までD3DXとかDMUSICとか腐った仕様のライブラリしかなかった世界に、(技術的には)まともなゲーム機が生まれ、閉ざされていた日本のゲーム機のノウハウが息づいているというのはうれしいことだ。いまや洋風ゲーム産業は独自の方法論を確立できたといってよい。
iPhoneなんかの組み込み機器にも真っ当なユーザ・エクスペリエンスが提供されてきているというのも同じような潮流で、今後組み込み機器の世界でも洋風ゲーム産業のノウハウが生かされていくことだろうと思う。

この先しばらくの世界ゲーム市場での和風ゲーム企業は、「ゲーム製造工場」と化した洋風企業とがっつり渡り合っていくという結構骨が折れる時期が続くだろう。和風メーカーが頑張るキーとしては、四の五の言わずさっさと生産体制を整えて、その先にさらに付加価値をどう作るか、という点かと思う。
コリアン系ゲームなんかはこの点に失敗している印象が強く、システム化は比較的速くすませたが、その先の付加価値が上手く創造できず、妙な洋風デッドコピーが多い印象がある。その点については和風メーカーは器用なので心配ないかとは思う。
そのための方法論は沢山あるだろうが、自分としては和風メーカー間でもノウハウのシェアや人材交流は大分実現できてきているので、一歩進んで実装や成果物自体のシェアを根付かせられると良いのか、と考えている。できれば気前良いメーカーがタイトルのソースツリーをBSDライセンスで公開したりしてくれると、大分状況が良くなるのではないか。
などと思ったGDC2008であった。

●個別セッション
今年はブース警備もありセッションはそれほど回らず。

●Audio Bootcamp / Middleware Panel
同僚のTomさんご出席というのでサクラに出かける。
ここ数年でオーディオツールでもストリーミング+3Dサウンド一辺倒から、インタラクティブミュージックへの回帰がみられ、今年もインタラクティブオーディオのセッションが多く目に付いた気がする。パネル中でもMIDIやインタラクティブオーディオの話題や、プロセッサパワーが沢山って、10年前にも同じ話したよね:) とか、予算がかかるよね、といった話題が聞かれた。
一番驚いたのは前職の知人がフリーランスになったというお知らせ。

●KeyNote:Microsoft
今年唯一のプラットフォーム系キーノート。コンセプトとしては、XNAによる開発者の裾野の広がりとプロフェッショナル開発者も同時にサポートという、なんというかロングテールな展開。
ゲーム市場は昨年売り上げ最高潮だったが、今年は北米の景気後退入りがあり横ばいまたは減速するのではないかと思う。市場のパイが限られるなかで、ユーザーの時間とお財布をロングテールな中で競争する環境というのはちょっと漠然とした不安が残る。今日は快晴だが水平線の彼方に何かいやな予感がするというか。
ZuneにCLRが載ってきたというのも興味深い。ZuneといえばGigaBeatなわけで、GigaBeatといえばToshibaで、ToshibaといえばHDDVDなわけで、今後の展開を固唾を呑んで見守りたい。

●Procedural Data generation in FarCry2
コンテンツパイプライン上でのデータ自動生成に関するお話。ツール上で自動的に木が植林されて道が切り開かれて行くというのは見ていてなかなか楽しい。ツールがSimCityのようだ。とはいえ自動生成したマップ上でのテスト、パフォーマンス等は大分大変とのこと。チェックに際しては、
・人手をかける
・移動パスなどのAIヒントも自動生成
・その他バグチェックも自動でできるところはできるだけ自動で
としているらしい。
また、破壊オブジェクト(殆ど壊せるが)の壊し設定は手付けなど、手作業の余地も残っている。
#オブジェクト破壊については、いくつかマテリアルを見て破壊データを生成するというツール、ミドルウェアもあるのでいずれは自動化されるだろう。
ということでエンジニアこれからもがんばりましょう、なセッション。

●KeyNote:The Next 20 Years Of Gaming
http://en.wikipedia.org/wiki/Ray_Kurzweil
アメリカを代表するサイエンティストRaymondKurzweilによるキーノート。GDCキーノートとしては毛色が変わったもの。メッセージは、個別の事象は予測が難しいが全体のトレンドは予測が可能で、今後もコンピュータサイエンスとその周辺技術は指数的に発展していく、というもの。
#ビジョンとしては数年前のKenKutaragi氏と同じ方向なのだが、説得力が格段に違うのはどうした訳だろう。
未来図として面白いのは2029年にはチューリングテストをパスするだろう、という予測。そうなったら相当に面白い。老後も退屈しなくて済みそうだ。

●The Art And Technology Behind Bioshock's Special Effects
後半だけ聴講。
https://www.cmpevents.com/GD08/a.asp?option=C&V=11&SessID=6918
昨年末のダークホース的なヒット作Bioshockのビジュアル表現について。
Bioshockでは絵的表現の綺麗さが絶賛されたわけだが実装テクニックでは枯れた技術とfakeの多用で上手く見せている。fake多用しましたよ、というのは清清しくてよい。

●The Technology Of FinalFantasy
ファイナルファンタジーの技術面解説セッション。といってもdetailの話ではなく開発プロセス統合、コンテンツパイプライン構築にあたっての思想信条の話が主。コンセプトとして見た目のかっこ良さを重視するというのは良いかと思う。最近は「BioShock」や映画「300」(これは違うか:))など気合の入ったカットシーンが増えてきたが、それでもまだまだ微妙な間や、謎なカットシーンも多いのは、まだまだ改善が必要だろう。
プレゼンの説得力としてはもうひとつ。ツールによる補正の使用前、使用後などを対比して見せるとより深い理解が得られたかと思う。
FF13トレーラーはかなり良かった。期待。

●Adventures In Data Compilation And Scripting for Uncharted
スクリプトセッション第一弾。20分のショートセッション。ショートセッションということで侮っていたが、短い分要点がまとまっていて良い。
Schemeのスクリプティングで静的データ、スクリプティングを生成。
言語の選択はもはや好みの問題でどうでも良いが、Schemeはやや可読性に難有りな気がする(自分的に)。
また、静的データもスクリプトの生成結果を使うというのはちょっとツボがつかめなかった。スクリプトと同じコードが使えるというのが利点? 静的データはツールなりで生成するほうがベターでは、と思われた。
デバッガが無いというのはややつらいか。

●Snakes On a Seamless Living World
第二段。こちらはStacklessPythonの実装例。Pythonは最近の一番のお気に入りLL。言語仕様がシンプル&質実剛健なので、誰が書いても(殆ど)同じコードにしかならない。なんかドイツ語的だ。
これLLにとっては結構重要だと思う。LLに求められる点は、如何に簡単にどうでも良い部分のコードを量産できるか、という点かと考えている。
例えばの目安として、C++でだらだらスクラッチして5日くらいかかるコードがC#だと2日で、Pythonだとリファレンス引きながらでも半日でできる。
Pythonお勧め。
実際のパフォーマンス話、スクリプトVM上での仮想スレッド切り替えに関する話などもあり興味深い。

●Tamarin: A Free, Fast, Open Scripting Runtime
第三弾。こちらはAdobe作成のActionScript/ECMAScript4のランタイムを使いましょう、という話。JITがただでついてくるというのはポイントが高い。具体的な採用タイトルの話ではなかったのでゲーム向けにどれくらい使えるランタイムか、という点はきになる。
Tamarin自体はMPLの支配下に置かれている。このためTamarinコードに手を加えた場合は該当部のコード公開が必要なようだ。

GPUプログラミング時の基本的な要素として、半透明プリミティブ(または半透明トライアングル、トランスルーセンシ・ポリゴン等)の並び替え処理(ソート処理)が挙げられる。図にあるように、半透明プリミティブは描画順序によってブレンド結果が異なってくるため、より良い見た目を醸し出すためにはプリミティブを視点から見て奥側から描画しなくてはならない。これは単純な様子でいて、割り切れば実際に簡単、正しくやろうとするとキリがない類の処理だ。また、あまりに基本的過ぎて注目されることも少ない点でもある。
ここではゲーム機、ゲームプログラムではどのように半透明ソートを行なっているのか、今後どのような手法が期待されているのか、についてさらっとメモ。

●オブジェクトごとにソート
殆どのタイトルでよく見られる現実的な解決策。
キャラクタ単位、壁単位など適当な単位に描画順序を並べ、半透明プリミティブは奥から描画していく。オブジェクト内での破綻については無視してしまう。なお、同じくソートしたオブジェクト内の不透明プリミティブはHi-Zを有効活用するため手前から描画するのが効率よい。

●ソートしない
アルファソートしない、というのも現実的な、そして潔い選択肢だ。
副作用としては、
・カメラの向き等の描画順序に依存して描画結果が変わる
・深度バッファ更新も一緒にしてしまうと、手前の半透明プリミティブに奥のプリミティブが刈り取られることが結構目立つ。
「ファイナルファンタジーX」ではこの点と、モーション圧縮の誤差が結構目立ち惜しまれる。(この後「ファイナルファンタジーX-2」等のエンジンでは改善されている)

●全プリミティブをソート
 半透明プリミティブをいったんバッファリングして、CPUで頑張って全部並び替える。ソートの際には参照点としてプリミティブの重心を使ったり、近傍点を使ったり、いくつかのオプションがある。いずれにしてもプリミティブ同士が交差している場合は破綻する。その際にさらにプリミティブを分割することもオフラインレンダリングなどでは有り得るが、リアルタイム処理ではあまり聞かない。

●AlphaToCoverage
これはもしかすると今後最も有望な解決策だろう。AlphaToCoverageはMSAA/FSAAのカラーバッファに対して、アルファ値に応じたディザパターンを生成してサブピクセルを打ち込む。その結果が描画後段のバッファ・リゾルブ時のブレンド処理され、半透明描画として表示される。サブピクセル毎に深度比較が行なわれるため、(サンプル数が十分であれば)確率的にソートに依存しないプリミティブブレンドが実現できる。サンプル数が少ないとαブレンド階調が少ない、ディザパターンが目立つ、などの副作用が発生してしまう。
4サンプルのMSAA/FSAAではプレステ1相当の4段階でソート不必要なアルファブレンドが実現できる。モダンなGPUでは16サンプル以上のMSAAに対応しており、実用間近だろう。
http://www.humus.ca/index.php?page=3D&ID=61
AlphatoCoverage解説
なお、往年のセガサターンでは50%の半透明プリミティブ(変形スプライト)を実現するのにディザパターン表示を行なっていたが、AlphaToCoverageの原型に近いかもしれない。

●Aバッファ/Rバッファのハードウェア実装
 今後のハードウェア実装が一部で示唆されている手法。
カラーバッファと深度バッファをカスケード的に持たせて最上層からN重ね合わせ(nはバッファ数)を実現というもの。
 現行のDepth/Stencil処理、ラスタオペレーション処理をより発展させたものと言える。希望としては、ラスタオペレーション処理をもっとプログラマブルに、ラスタオペレーションシェーダ的になると嬉しい。

●その他の人たち
・デプス・ピーリング
マルチパス描画を駆使したややトリッキーなソフトウェア実装。感覚としては、キャラクタ・ジェネレータの合成をソフトウェアで実装しました的アルゴリズムといえる。キャラクタジェネレータの半透明合成では、画面最上層、二層目、n層目といった風にブレンド処理を管理する。
アルファソートだけのためにマルチパス描画を行なうのも大変、ということで実際のタイトルで使用されている例はあまり聞かない。

・タイル描画によるアルファソート
往年のDreamcastのPowerPV等、ImaginationTechnology(http://www.imgtec.com/)GPUで実現されていた夢の機能。
原理としては半透明プリミティブ描画を全てバッファリングしておき、GPU内で一気に処理するもの。全画面分の中間バッファを持つことは困難であるため、画面を小矩形のタイルに分割してレンダリングする。
が、実際にはプリミティブの重ねあわせが増すにしたがってO(n^2)的に描画負荷が高くなり、無制限な半透明描画とはならなかった。またディスプレイリストを完全にローカルメモリに置かねばならない点もレイテンシ増大、メモリ負荷、等のデメリットがある。

・カラーバッファ駆使手法
2007年GDCで発表されていた手法で、下記サイトにプレゼン資料が上げられている。
http://www.houmany.com/htmls/grafx.html
結局のところ同時に描画するNプリミティブは選択する必要があるようで、いまひとつ実用度が不明。

ざっとこのような手法が半透明プリミティブ描画に関する現状と今後だろうか。パーティクル全盛の今日、半透明プリミティブのソートはますます重要性を増していくだろう、多分。

追記:
Hiroyuki OgasawaraさんによるDX10シェーダベースの半透明ソート実装
http://wlog.flatlib.jp/?itemid=1098
手法としては浮動小数点MRTにうまくレイヤを畳み込んでくもの
気になるの点としては、RTとSrcTextureが同一となっているため
レンダリング直後にSrcTextureを参照した場合のコヒーレンシがいじされるのかどうか。 HWによって違いそう?
AMD社からDirectX10対応GPU「R600」シリーズ発表ということでスペックを眺めてみる。

ブロック・ダイアグラム
ブロック・ダイアグラムで目を引くのは、
・GraphicRAMを混載にしなかったことで、ColorBuffer、DepthBufferのCompress/Decompress回路が入っている
・L2TextureCacheの存在、L1VertexCacheはL2TextureCacheから引っ張るようだ
・DX10対応ということで当然だがGeometryAssemblerの追加
といった点。
HD 2400のスカスカ感にも、もののあはれを感じさせられる。Hi-Zもなしか~。

スペック上の見所
http://ati.amd.com/products/radeonhd2900/specs.html

Double-sided hierarchical Z/stencil buffer
Early Z test, Re-Z, Z Range optimization, and Fast Z Clear

これはなかなか面白いかと思う。これまで深度比較条件等を変更するとHi-Zは一億総フラッシュする必要があったがそれも不要そう。また最大、最小値を同時に保持することで何かトリッキーなこともできそうだ。

Lossless Z & stencil compression (up to 128:1)
Lossless color compression (up to 8:1)

さらばDoughterDie。

Percentage Closer Filtering (PCF)
nVidia的には今更感があるが、ついにATI系にも実装されたようだ。諸般の事情は解決されたのだろうか。

Spatial/temporal dithering provides 30-bit color quality on 24-bit and 18-bit displays
これも期待。出力段8BPPというのは、もはや少ないだろう。

Integer and Bitwise Operations
Integrated HD audio controller with multi-channel (5.1) AC3 support, enabling a plug-and-play cable-less audio solution

極私的にはこの辺が一番うれしい。

マーケティングHypo
あくまでなんとなくだが、微妙に旧来の「Vertor4+RCPユニット」を「5wayのスーパースカラシェーダプロセッサ+VLIW」と表現しているのかな~、という雰囲気も漂う。違うかもしれないが。確かに、そう表現しようとすればできなくも無い。反応する側も「解っていて釣られている」のだろうな、と想像力を逞しくしてみる。

ベンチマーク結果
http://pc.watch.impress.co.jp/docs/2007/0514/tawada104.htm
特に感慨は無いが、やはりテクスチャフェッチ系はnVidia強しか。

コメントいただいたので、GPUのキャッシュコヒーレンシについてもすこし考えてみる。なお、以下はあくまで勝手な推測なので悪しからずだ。
GPUキャッシュのコヒーレンシを考える際のキーは、
GPU内部でのデータハザード(特にReadAfterWrite/RAW)対策として、ラスタオペレーションの結果を効率よくストアフォワードできるのか、それともそんなの無茶なのか
という点になる。

パイプライン処理、データハザードについてはWikipediaを参照されたい。
キャッシュメモリのコヒーレンシについても同じく

GPU内部にはテクスチャキャッシュ、頂点キャッシュ、変換後頂点キャッシュ等、数種類のキャッシュメモリがある。このうち外部ストレージからのデータフェッチをキャッシュするのはテクスチャ・キャッシュ、頂点キャッシュの二種だ。GPUではパイプラインが非常に深く、回路をシンプルに保つためもあってこれらのキャッシュメモリの不整合に関してはこれまで無視されてきた。この対策として、
  • Destination(カラーバッファ、深度バッファ)はソースとして同時参照できない

  • リソースをCPU側で更新する際にはLock/Unlockを必要とする

  • という制約がAPIレベルで課せられている。
    API設計の面での自由度が格段に高い組み込み機、特に一部のUMA設計なゲーム機では、ソースバッファとデスティネーションを同一アドレスにして描画中のバッファ状態を参照、シェーダ処理に使う、というテクニックが存在したようだ。この場合、データのコヒーレンシは保障されないが、ゲーム機の映像処理ではFake上等、目立た無ければOKな世界なので、案外問題にならかった様子だ。
    また余談だが、モダンなGPUの強力機能の一つHiZ/階層ZはDepthBufferの情報の一部をHiZ用メモリに転送している。が、よくよくベンチマークをとると、Depthバッファの情報がすぐにHiZに反映されておらず、若干のレイテンシがあることが分かる。ここでもコヒーレンシが維持されてなくともパフォーマンスに影響があるだけなので大きな問題がない。

    GPU内部でキャッシュのコヒーレンシを維持したい場合とは、例えば例えば半透明プリミティブの描画順番をうまく解決するために、現時点での(1ないし複数の)カラーバッファ、深度バッファの状態を正しく把握したいケースなどが考えられる。
    この場合、直前の描画プリミティブによって更新されたバッファの内容をシェーダ内で正しく参照できればよいことになる。

    原理的にはプリミティブ描画を行なうごとにキャッシュをフラッシュすれば正しいデータが常に取得できるがパフォーマンス上は大きなペナルティとなり、よろしくない。このため、ラスタオペレーションを行なった後のデータをGPU内部でGPUキャッシュに効率的に反映できる仕組みが必要となる。
    こうした問題に対してCPUではストア・フォワードといわれるバイパス回路で対応している。データがパイプライン内で生成された以降、出来るだけ速いステージでデータ参照ソースに結果を反映させる仕組みで、多くのRisc、Pentium4、Core2アーキテクチャなどで採用されている。
    http://journal.mycom.co.jp/special/2006/conroe/005.html

    ところで、CellBroadbandEngine等に搭載されているPPCコアではストアフォワード無しというかっとんだ 大胆な割り切った仕様になっている。このため(一部には)悪名高いLHS(LoadHitStore)ストール/フラッシュがパフォーマンスに大きな影響を与えている。LHSは、レジスタファイルへの書き込み後読み出しであるReadAfterWrite/RAWとはまた別のもので、STQの長いトンネルを抜けるまで待つ必要がある。
    http://www-306.ibm.com/chips/techlib/techlib.nsf/techdocs/9F820A5FFA3ECE8C8725716A0062585F/$file/BE_Handbook_v1.0_10May2006.pdf
    http://www-03.ibm.com/servers/eserver/pseries/hardware/whitepapers/power4_3.html
    Load Hit Store: A younger load that executes before an older store to the same memory location has written its data to the caches must retrieve the data from the SDQ. As a result, as loads execute they check the SRQ to see if there is any older store to the same memory location with data in the SDQ. If one is found, the data is forwarded from the SDQ rather than from the cache. If the data cannot be forwarded, as will be the case if the load and store instructions operate on overlapping memory locations and the load data is not the same as or contained within the store data, the group containing the load instruction is flushed, that is, it and all younger groups are discarded and refetched from the instruction cache. If we can tell that there is an older store instruction that will write to the same memory location but has yet to write its result to the SDQ, the load instruction is rejected and reissues again waiting for the store instruction to execute.

    さて、GPUでストアフォワードが効果的に実装可能か、という点については、ある一定の制限範囲内で実用になるのではないだろうか、という気がしている。ならないかもしれないが。
    1)GPUでは三角形(ところにより四角形)のプリミティブを描画単位とするが、通常描画時、つまり任意アドレスへのデータエクスポートを行なわないという制限下では、ひとつのプリミティブ内ではデータ重ね書き(WriteAfterWrite/WAW)は起きない。また、データが更新される領域もトライアングルセットアップ時に予測できる。
    このため、GPU内部のキャッシュラインが128バイトといった大きな単位であっても、キャッシュライン単位のダーティビット管理で十分であるし、更新頻度もプリミティブ単位の管理で効率的な動作が予想される。
    #ただし、数ピクセル以下の面積のマイクロプリミティブの描画では大きなオーバーヘッドになる可能性もある。
    2)また、GPUの設計は粒度の低いHWスレッド管理となっており、テクスチャフェッチ、頂点フェッチなどのオペレーション時のレイテンシをある程度許容する設計となっている。ストアフォワード処理に対してテクスチャフェッチと同程度のレイテンシで対応できるのであれば許容範囲と考えられる。

    といった点から、いつか来るべき未来にはGPU内部でのキャッシュコヒーレンシ問題も解決されるのでは、と考えている。
    ただし、キャッシュコヒーレンシを解決する手法以外にも、現行のGPUの制限を撤廃する手法として別のアプローチも考えられる。ありうる方向性としては以下のようなものだろうか。

    Parallel Data Cache@nVidia路線
     Parallel Data Cacheはサイズ16KBのシェーダ全体からアドレッシング可能なレジスタファイルかと思われる。Parallel Data Cache上でのコヒーレンシ維持については不明だが、おそらくはアトミックなアクセス命令が用意されているのではないだろうか?
    Parallel Data Cacheの方向性の行き着く先としては、キャッシュサイズの増大、要するにCELLによく似た思想かと思われる。CELLの256KBのローカルストア内ではGPU処理が難しいことはPS3が身を呈して証明してくれている。今後64MB超の混載RAM容量が可能になれば、あるいは現実的になるのかも。
    ラスタオペレーションのプログラマブル化
    パイプライン後方の アルファ/ステンシル/深度テストからラスタオペレーションに至る道のりを別途プログラマブルにする、という道。A-Buffer/R-Buffer/その他大勢Bufferの方向性といえる。ラスタオペレーション部分だけをDoughterDieにするという(どこかで聞いたような)アプローチにも適用しやすく、結構現実的なソリューションかもしれない。
    GPUキャッシュのコヒーレンシを何とかする
    今回考えてみた道筋。ATI/AMDの汎用演算リソース的なGPUの方向性からすると、こちらのほうが汎用的で良い感じなのではないか。GPUが汎用DSPとして脱皮するためには乗り越えるべきハードルであろう、と勝手に想像する。

    写真は近所のマクドナルドの遊具コーナーと星条旗とマクドナルド旗。
    マクドナルドの遊具コーナーは子連れには重宝する。

    さてGDC2007も無事に終わり、ほっと一息、と二週間くらいのんびりすごす。
    GDCでは多くの知り合いに久々に再開できてうれしい。
    ますます巨大化しているGDCだが、自分としては数年前から、セッションの内容云々よりは社交の場、ヒントをもらう場と割り切っている。書籍コーナーも意外と役立つが。ともあれ、ゲーム開発者の技術共有の場としての初期の目的からはすでに大分変節している感がある。

    本年は次世代機向けのプロジェクト第一世代が一巡したこともあり、巨大or肥大プロジェクトを振り返る的な内容に注目した。
    ほとんどに共通していたのは、より効率的に製作工程の試行錯誤(Iteration)ができるように、環境を整えましょうという点。欧米デベロッパのツール至上主義はずいぶん昔から兆しはあった。8年前に訪問したとある西海岸デベロッパに「ツールプログラマのポジションが一番高い」といわれ「ひょえーそんなもんかいな~」いう印象があった。(当時はアプリケーションのプログラマが花形で、ツール作成チームはちょっと地味な存在だった)。そうした傾向も、ここに来て花開いた感がある。
    今日では大規模チーム内でのエンジニアの役割はほぼツール製作とエンジン製作で、基本的にはゲームコンテンツ作成には携わっていない。内製ツール外販によるエンジンミドルウェアの勃興も基本的には同じバックグラウンドだろう。

    その他聴講したセッションについてつらつらと。
    TR1:C++OntheMove
    聞きたかったセッションだが徹夜明けで寝坊。ガガーン
    仕方がないのでオーディオファイルを入手して聞く。プレゼンがわかりやすいのと、彼は長年のMyボスだったので聞きとりに苦がない(これ大事)。
    話としてはTR1について。Boost系のライブラリをすでに使っている面にはそれほど新規性はないかもしれない。

    http://www.tantalon.com/pete.htm
    ↑のページにあるプレゼン資料も非常に有用。

    From "Ouendan!" to "HELP!": Inside the Elite Beat Agents
    「押忍!闘え!応援団」のローカライズについて。「応援団」は英語ローカライズに際して大胆に内容を変更してスマッシュヒットに成功。こうしたローカライズが可能だったのはチームのバイ・カルチャー性に依存するのかな~、とふと思う。

    Under the Compiler’s Hood: Supercharge Your PLAYSTATION3 Code
    SNSystemのエンジニアのコンパイラ最適化の話。聞くに、かなりバランスの悪いコンパイラという印象が強まる。
    言語仕様向けの汎用的な最適化と、PS3向けの非常に野心的な機能を同時に実装中。「プラットフォーム非依存のコード生成を先になおした方が良いんで無いかなー」という印象。
    http://www.snsys.com/news/23010701.asp

    Designing GEARS OF WAR: Iteration Wins
    Gears Of Warのデザイン時には試行錯誤を繰り返しましたよ、という話

    Developer's Game Choice Award
    http://www.gamechoiceawards.com/
    本年も波乱なく、本命「Gears Of War」がChoceAward取得。「大神」が直接の受賞はなかったが多くにノミネートされていたのが印象的。また、例によってEA系のタイトルがことごとく無視されていたのも印象的。

    Keynote: A Creative Vision - Shigeru Miyamoto (Nintendo)
    宮元茂氏@任天堂のキーノート。詳細は
    http://www.famitsu.com/game/news/2007/03/09/103,1173397229,68263,0,0.html
    等に詳しい。
    「執念」をもって取り組むという点に感銘を受ける。実現したい事柄に関しては決してあきらめずに、10年でも20年でも、実現するか、命果てるまで続けることが必要という点は非常に感銘を受ける。「苔の一年岩をも通す」というか。一歩間違うと人生を棒に振るため万人には推奨されないかとおもうが、そんな生き方もありかと思う。

    Final Fantasy XII Postmortem
    FinalFantasyXIIの開発ツールについて。後で聞くと、去年のCEDECでの講演と同じコンテンツであったらしい。
    会場の反応としてはやや薄い。講演のメッセージとしては、「ツールを整備してIterationできる環境を整えました」という他のセッションと同様なのだが、同通の所為もあり、メッセージがうまく強調できなかった気配。
    社内ツールの命名センスはヒット。「モーションさん」等。

    Real World SPU Usage
    SCEの1stPartyタイトルではSPUをこんなことに使いました、という話。収穫としてはAI等の汎用Scalar処理もガンガンSPUに振っているという点。当たり前といえば当たり前だが、キャッシュミス一発でひたすらストールできるPPE環境よりは、SPU内で無駄は有れどもScalar処理をさせてしまっても幸せになれる、という話。

    Reflections of Zelda
    Zeldaの開発プロセスについて。
    これもまた「試行錯誤の繰り返し」の一言に尽きる
    http://plusd.itmedia.co.jp/games/articles/0703/09/news111.html

    Taking Control of Your Middleware
    ミドルウェアを採用するときには何がポイントか?
    ・全ての利点と欠点を検討して採用を決めましょう
    ・サポート経費を含むトータルコスト、サポートできる質問件数はいくつか、OnSiteサポートを依頼するときの経費、上限は?
     など契約内容を精査しましょう
    ・常に複数の選択肢を持つようにして、バックアッププランを用意しておくこと
    等が語られる。

    Sort-Independent Alpha Blending
    http://www.houmany.com/htmls/grafx.html
    半透明マテリアルのアルファソート無し描画をPixelShaderにて実現しようという試み。原理的には、高Precision(16bit推奨)のカラーバッファにカラー値、Alpha値、コンスタント値をTweakしながらストアし、第二パスでデコードして近似値を求める、というもの。4段階重ね合わせまでのサポート。
    実用的には微妙なところ。
    アルファソート問題の解決については、(次世代GPUでは対応されると思われる)GPU内でのキャッシュコヒーレンシの問題が解決されれば、シェーダ内からのDestBuffer参照によって解決可能な問題だ。(A-Bufferの実装でも対応可能だが、A-BufferのHW実装はややAdhocな感じがする)今後のGPUに期待。

    通常、こうした事柄についてはさり気無くスルーしているのだが、本件については敢えて発言しておきたい。

    Xbox360「Gears of War」が見せた先進の開発力

    まずはじめに断っておきたいが「Gears of War」自体は(趣味は分かれるが)良いゲームであると思うし、新規フランチャイズで200万本以上の売り上げを達成できたことは大変喜ばしく、昨今の閉塞感があった業界にとっても健全なことだ。

    だがその事と、ミドルウェアとしてのUE3に関するMarketing Hyp(売り口上)は分けて考えた方がよい。

    Gears of Warがリリースされた影で、UE3のライセンスタイトルが、多くスケジュール延期、プロジェクトキャンセルとなっているのはなぜだったのだろうか? 本来であれば「ミドルウェア採用によって工数を大幅に短縮し、クリエイターがコンテンツ作成に集中、新機種の立ち上げにタイトルをリリース」できたはずだ。だが結果としてそのゴールは達成されていない。

    ・Gears of Warリリースに向けたデスマーチのために、本来必要なミドルウェア開発、サポートがおろそかになっていなかったか?
    ・ランセンシーに約束していた機能の実装、納期が守られていたのか?
    ・ゲームプラットフォーム上での開発に必要十分な環境が用意されていたのか?

    こうした点を是非とも取材し検証してほしい。
    #そして不幸なプロジェクトを増やすような記事は止してほしい。

    個人的な見解としては、
    ・プラットフォーム立ち上げ時の総合ミドルウェアは丑寅、いわゆる鬼門
    ・PC向けデベロッパとコンソール向けデベロッパの間には深い川が流れている
    ・ミドルウェアで開発力不足を補うという方向性は痛い目をみる
    といった点だが、それはまた別の機会に。

    追記:
    http://www.gamespark.jp/modules/news/index.php?p=3090
    Too Late!開発難航の『Too Human』Silicon KnightsがついにEpicを訴える
    南無三。
    ゲームプラットフォームとしてのPCが日本でも注目されてきているようだ。
    もちろんフリーゲーム、オンラインゲームや特定ジャンルのゲームではPCゲーム市場は十分に存在してきていた。が、最近ではコンシューマ向けゲームを専業としてきたゲーム会社でもPCを含めたマルチプラットフォーム開発が視野に入っているという話を多く聞く。その理由としては下記のような点だろうか。
    ・PCゲームマーケットにベットすることによるリスク分散
     マルチプラットフォーム化の潮流、ロイヤリティフリー等の利点
    ・コンソールゲーム機のSW/HW構成(特にGPU仕様)がPC用SW/HWに近づいてきた点

    また、アーケードゲームシステムでは一足先にPCアーキテクチャを採用したシステムが増えているが、こちらはメンテナンス製、アップグレードのしやすさ、開発工数削減などの要素諸々がアーケードシステムの要求に良くマッチしているからだろう。
    タイトー TypeX
    http://www.typex.taito.jp/topics.html
    SEGA リンドバーグ
    http://www.watch.impress.co.jp/game/docs/20061025/3dvf5.htm
    Namco SystemN2
    http://jp.nvidia.com/object/IO_16001.html

    (パフォーマンスを要求する)PCゲーム開発については、長らく国内市場が存在しなかったこともあって日本国内のゲームデベロッパからは技術が失われて久しい(そうでなかったら御免なさいだ)。ということでコンシューマ機とPCゲームをクロスプラットフォーム開発する上で、個人的に気になる点を記しておきたい。

    コンシューマ機との性能比較
    同程度のHWプロファイルのPCとコンシューマ機を比較した場合、諸々の要素がかさなりあって、PC上で達成可能なパフォーマンスは大体同スペックのコンシューマ機の半分相当と見積もって妥当だ。例えば、Pentium3 733Mhzで動作しているコンシューマ機と同等のパフォーマンスを達成するには、Pentium3 1.5Ghz相当のCPUと(表現が難しいが)倍程度のスペックを持つGPUが必要だ。同様に現在市場に出回っているコンシューマ機相当の実効パフォーマンスを達成するにはもう1~2世代後のハイエンドPC程度があれば十分だ。
    ゲームプラットフォームとしてPCアーキテクチャと専用機を比較した場合、技術面からみて注意が必要な点は
  • ドライバモデル、HW抽象化の必要性によるソフトウェア、APIの負荷

  • バス構成を原因とするメモリ帯域の違い

  • HWプロファイルが一定しないことによる工数の増大と最適化の限界

  • くらいかと思われる。

    ドライバの負荷について
    一般的にPCゲームではCPUがボトルネックになるといわれているが、その原因のほとんどはドライバ、APIの実装が寂しいことによるものだ。
    コンシューマ機では、ドライバ・APIのボトルネックを取り除き、GPU側の最適化を枯らしたうえで、最終的にCPUボトルネックとなる事が多いことを考えると一周分状況が違うといえなくもない。
    DirectX9やOpenGL等のドライバ内部では、主に描画コール発生時に内部で果てしなく、気の遠くなる処理が行われている。HWレジスタに各種レンダステートをマッピングさせるなどは楽なほうで、各種シェーダの入出力を一致させる処理ためにバイトコードをスキャンする等の一連の冗長な処理がHW仕様を隠蔽した分、暗黙のうちに行われている。またカーネルモード、ユーザモードの状態遷移処理もCPUサイクル負荷となる。
    これらを防ぐためにドライバ呼び出しの回数を少なく、つまりBatchサイズを大きくすることが、PC上での最適化の定石とされている。

    バッチサイズ
    PCDirectX上では、バッチ化によってAPI呼び出し回数を少なくすることが常套手段だ。API呼び出し毎での描画プリミティブ数を多くするため、インスタンシングや、マテリアル・テクスチャ単位でのプリミティブソートなどが有効な手段となる。
    PCゲームにおいて一般的な1シーンあたりの描画コール数は目安として~700回前後が適当とされている。一方で、同程度のHW性能を持つゲームコンソールではその5~15倍前後の描画コール発行数が標準的だ。もちろん無駄な描画コール数を減らすことはコンシューマ機でも重要だが、コンシューマ機では描画コール数を減らすことを目的として余分なCPUサイクルを消費しても逆効果なことが多い。

    DX10では
    DX10では、ステートオブジェクトの採用やシェーダへのシグネチャ採用によって、描画コール発行時のCPU負荷をできるだけ無くすために努力している。が、それでも本質的にAPI仕様にあわせたHW抽象化を行うことが必須となるため、ドライバ負荷の問題は今後も存在し続ける。
    たとえば、リソース・マップ時のSwizzle←→LinearView変換など、ドライバが陰ながら努力(CPUサイクルを消費)している冗長な処理はDX10でも存在するし、今後のAPIセットでも残り続けるだろう。
    また構造上APIコールがインライン化できない点もCPU負荷としては無視できない。
    #余談だが、C++ベースのゲームコードではCPUサイクルの10%前後が関数呼び出しの前処理、後処理で消費されていることがザラだ

    D3DXヘルパ関数やD3Dエフェクト等は使わないほうが、かなり良い
    PC上では、ドライバに直接かかわらないその他のソフトウェアコンポーネントについても、パフォーマンス最適化を意識していないものが多く、ゲーム・コア部分への採用には注意が必要だ。D3DX関数の多くは処理内容に比較して過剰のCPUサイクルを消費するため、パフォーマンスクリティカルなコードでは採用しないほうが(とても)良い。またD3DXEffectFramework、cgFx等のエフェクトについても生産性の向上には有用だが、実際のゲームアプリケーションには使わないことを(強く)お勧めしたい。
    DX10のEffect実装については多く改善点が見られるが、仕様を吟味すると、Effect内部にデータをコピーする必要があるなど冗長であることは否めない。
    こうしたドライバ、ソフトウェアのパフォーマンスについては、PC上ではハードウェアを高速化することによる対応(いわゆるフリーランチ)が主であり、ドライバ、APIソフトウェアの最適化によって高速化することに対してはインセンティブはそれほど高くない。ベンダにとって旧世代HWのドライバをチューニングすることは、(顧客サービスではあるが)ハードウェア買い替えを思いとどまらせる負のインセンティブともなりうる。

    バス構成
    PCアーキテクチャのHW構成を見たときに、パフォーマンス上でネックとなるのはAGP8X、PCIExpressなどで結ばれるメインメモリとGPUボード間のバス帯域だ。
    GPU上のバス自体はボード上のローカルメモリとGPU間が広帯域な専用バスによって結ばれているため、大きな問題にならない。またCPU FSBの帯域については、前述のとおりソフトウェアレイヤが、メモリ帯域最適化よりもアルゴリズムが問題な状態なので、あまり意識する必要が無いのが現状だ。

    AGP8Xバスの場合、仕様上は双方向毎秒8GB、片方向で4GBの帯域と定義されている。しかし実効レートではその10%以下、毎秒数百MBが妥当な帯域だ。この場合60Hzで動作するアプリケーションの場合、1フレームあたりで実際に使える有効帯域は3MB程度に制限される。このバスを行き来するデータは
    ・描画コマンドバッファ
    ・動的なコンスタントデータ
    ・パーティクルなどの動的頂点データ
    ・ムービーなどの動的テクスチャデータ
    ・トーンマッピング用データ等のGPUからのリードバック
    等が考えられる。

    このうち、描画コマンド、コンスタント、GPUからのリードバックなどについてはそれほど大きいサイズにはならない(描画コマンドで300KB前後)だろう。ダイナミック頂点、テクスチャを使う場合には帯域を十分に考えて更新する必要がある。
    PCIExpressについては実際にHWを精査したことが無く不明だ。が同じく実効帯域については慎重に検討したほうが良いだろう。

    各種HWへの対応
    とくにパフォーマンスを追及するコードにとっては、多くのHWプロファイルに対応する必要があることは大きな足かせになる。CPUキャッシュのライン幅やキャッシュアルゴリズムを意識したコーディングは、PC上では実質的には難しい。
    とはいえHWプロファイルが違うことに対する対応は、パフォーマンスを重視するコードについては標準的なHW構成ごとに違うソフトウェア実装をすることが標準的な対応だ。
    テスト工数が指数的に増大するため現実的にはすべてのHWプロファイルに対してコードを用意することは不可能だが、CPU、GPUそれぞれ数種についてはそれぞれの組み合わせでプロファイルで下ベンチマークをとったうえで最適なコードパスを作成することが現実的なテクニックだ。

    まとめ
    コンシューマゲーム機のPC移植に当たって思わぬパフォーマンスネックになりがちな点をまとめた。また、こうしたパフォーマンス上の点以外にも、
    ・適当なプロファイル方法&効果測定方法
    ・セキュリティ対策
    ・スレッド粒度やフレームレート等のOSの挙動の違い
    などコンシューマ機と勝手の違う点は多い。
    ともあれ、適切な手順を踏んで地雷を避ければPC上でもコンシューマ機との同時期のクロスプラットフォーム開発が十分可能なことは、多くのゲームベンダーが実証しているところだ。
    1 2 次のページ> 1/2page

    Twitter
    Profile
    Hak
    カルフォルニア在住の最適化エンジニア。ゲーム機開発、ミドルウェア開発に携わる。最近はコンパイラ開発が趣味。子供二人。 Twitter
    RSS 2.0
    RSS 1.0
    ATOM 0.3
    XHTML 1.0
    CSS
    WaBlog