Mercurial > hg > Events > OSC2010
view presen/osc2010.ind @ 0:9887d6547572
presen not done.
author | tkaito |
---|---|
date | Wed, 29 Sep 2010 22:55:09 +0900 |
parents | |
children |
line wrap: on
line source
-title: 2009-09-26 (土) Cerium を用いた PS3 でのゲームの作り方 --Linux 上でのゲームフレームワーク Cerium Task Manager Blender / SceneGraph --Cell ってどうなの? 結局、Video Chip に触れない SPUでレンダリング ソフトレンダリングにしては速いが... 新型PS3では、Linux は使えない とかいろいろだめ --Cell Architecture <img src="photo/Cell-main2.png" alt="pipeline" height="200"> Linux 側から使える SPE は 6 個 SPE は 256KB の Local Store (LS) SPE からメインメモリへ直接アクセスできない (DMAを使う) SPE は 128 ビットレジスタを 128 個持っている --楽するための並列プログラム トリビアルなプログラムでも並列実行する必要がある Single Thread でもPPE がクソ遅いので、SPEで実行するべき 例えば、 Word Count --プログラムを Task に分割 Task には依存関係がある Open/CL , Spurs Engine --並列性 データ並列 パイプライン 結局、これしかないらしい。 --階層的並列プログラミング Row Level での並列性 Vector/Streaming 結局、データ並列とパイプライン SPE Level での データ読み込み、 実行、データ書込 のパイプライン並列 High Level での並列性 Rendering Scene Graph -- データ読み込み、 実行、データ書込 <img src="photo/pipeline.jpg" alt="pipeline" height="300"> パイプラインバッファはいくつ? --Task は良いけど、データはどうするの? データを右から左に... 処理中に必要なデータがメインメモリ上にある でも、SPE には、256k しかメモリがない メインメモリ(256MB、広くはないが十分)から、256Kに必要なだけキャッシュする ハードウェアでやれよ! 普通の並列ハードウェアはキャッシュになっている IBMはそう提案したらしいが、SCEの人が拒否したらしい なので、自分でキャッシュする必要がある --Cerium Task Manager Open/GL Mesa に Cell driver を書いたが、 メインメモリに依存しすぎ Task base で書く必要がある Redering Engine も自前で一つ持っていて良い SPEは256Kなのでコード管理も必要 SPURSは公開されないらしい そんな経緯で作成することに... --Crium Task Manager の特徴 PPU/SPUで、Task の互換性がある SPU上の最適化は当面禁止 OS X 上でも動く コードのデバッグはOS X 上でやる 並列化とチューニングだけPS3上で行なう SPU上のメモリをCode と Data を Hash とメモリリストで管理する SPUに入り切らない巨大なTaskでも実行できる --ゲームの作り方 Blender で、3Dモデリング 階層化、グルーピング これを、Blender の Python plugin で XMLに変換 画像/Texture もXMLに埋め込まれる XMLを読み込み SceneGraph を作る <img src="photo/cerium_sg_tree.jpg" alt="sg" > --Blender から SceneGraph 用の xml 生成 PythonScript の導入 <ol> <li> Blender をダウンロードしてインストール</li> <li> export_xml.py を用意する</li> <li>"/Applications/blender-version/blender.app/Contens/MacOS/.blender/scripts " 以下にexport_xml.py をコピー</li> <li>Blender を起動すると File -> Export に Libps3 (.xml) が追加される</li> </ol> ゲームの初期化部分でcrateFromXMLfileを呼ぶ <font size="4"><pre> void game_init(TaskManager *manager, int bg) { sgroot->createFromXMLfile(manager, "xml_file/SG.xml"); ... </pre></font> --SceneGraph 階層化された3Dオブジェクト 子供の向きを決定する変換行列 Camera 背景 入力デバイス SceneGraph のノードには、 MoveTask Collision Task がある --ゲームとは、 SceneGraph を MoveTask CollsionTask で書き換えていく MoveTask, CollsionTask は、ステートパターンで 入れ換えられる これで、すべて書ける。 --つまり、 SceneGraph の構築 MoveTask CollsionTask だけを書けば、あとは、Cell が自動的に並列に実行してくれる --Task の作り方 SchedTask を継承した class を作る <pre> class SpeTask : public SchedTask { SchedConstructor( SpeTask ); int run(TaskManager *manager, void *rbuf, void *wbuf); }; </pre> run 関数は Task における main 関数のようなもの SchedConstructor() で class 名を登録する (C++のnew を使うとメモリを食われる...) SchedRegisterTask(TASK_SPE, SpeTask) で SpeTask に TASK_SPE という ID をつけて 登録します --Task の作り方(Con't) <pre> /* 先ほど登録した ID を指定して Task を生成 */ HTaskPtr task = manager->create_task(TASK_SPE); /* 入出力先の指定 */ task->add_inData(rbuff, rbuff_SIZE); task->add_outData(wbuff, wbuff_SIZE); /* CPU の指定 */ task->set_cpu(SPE_ANY); /* Task の投入 */ task->spawn(); </pre> --Task の作り方(Con't) Task は依存関係を記述する事ができる <pre> /* taskB は taskA が終わるまで待つ */ taskB->wait_for(taskA); /* taskC は taskB が終わるまで待つ */ taskC->wait_for(taskB); </pre> --並列アーキテクチャは並列でないと... 特に、Cell/PS3 は、SPUで実行しないとだめ 既存のプログラミングでは、まったく歯が立たない トリビアルなプログラムでも、並列にする必要がある --WordCount Task をグラフ構造的に構築する (SceneGraphのMoveTask) File を mmap する mmap した部分をTask に割り当て、word countする Task の構築 Task の依存関係 char *file_mmap = st_mmap.file_mmap; --WordCount <img src="photo/wc_graf1.jpg" alt="sg" height="300"> --WordCount int word_flag = 0; int i; for (i = 0; i < task_num; i++) { t_exec = manager->create_task(TASK_EXEC); t_exec->add_inData(file_mmap + i*division_size, division_size); t_exec->add_outData(o_data + i*status_num, division_out_size); t_exec->add_param(division_size); t_exec->add_param(word_flag); t_exec->set_cpu(SPE_ANY); t_print->wait_for(t_exec); t_exec->spawn(); word_flag = ((file_mmap[(i+1)*division_size-1] != 0x20) && (file_mmap[(i+ 1)*division_size-1] != 0x0A)); size -= division_size; } </pre> --WordCount 各SPEの結果を合計 <pre> .... /* taskの数 */ int task_num = size / division_size; int out_task_num = task_num + (division_size*task_num < size); t_print = manager->create_task(TASK_PRINT); t_print->add_inData(o_data, out_size); t_print->add_param(out_task_num); t_print->add_param(status_num); </pre> --やってはいけないこと 最初に大量のTaskをすべて作る Task が自分でデータを拾って来る Task 同士が、同期を行なう --Cerium Engine での同期 Task 内では同期はしない Local Storage/専有したメインメモリしか使わない Task が終了した時に、Single Thread で動いているPPE がデータの整理/同期を行なう Task 側では、Task の生成は行なわない Task の post_func (continuation) で、Taskを生成する --SPE Task, PPE Task Task 内で生成しても即座には実行されない Task 終了時に、SPEに送る Task List が作られる Task List のアドレスがSPEにメールされる SPEがメールを見て、Task List を読み込み実行する Task List の読み込みとSPEのTaskの実行は並列 Task List がなくなる(なくなりそうになると)と、 PPEにメールで要求する PPE Task SPE Task と互換。メインメモリを自由に参照できる --Fifo TaskManager 全部、同じCPU上で実行する。 OS X 上で動作する (Linux でも) デバッグ用 --MemList と Hash get_segment/put_segment/wait_segement 明示的にキャッシュ制御する必要がある 特に、 Dynamic SPE Task SPE上に常駐しないTask MemList と Hash で管理されている 256K (GBAと同じ!?) しかメモリがないので重要 --SPU上でのコード管理 GCCのOverlayを使う Overlay では、異なる場所にコードを置けない 部分的にPICではなく、絶対参照に変更する 自分自身へは相対参照。ライブラリへは絶対参照 Perl Script で書き換える --Task list task_list にオブジェクト生成するコードを入れる オブジェクトが生成されてしまえば、普通に扱える task 実行中にコードが追い出されることはない 現在実行中のコード 次にロードするコード の二つは必ずメモリ上にある --SceneGraph と Rendering Engine SceneGraph -> SceneGraph SceneGraph -> Polygon Polygon -> Span Pack Span Pack を Texture を使って Rendering これらを大きく並列に実行する Rendering は細かく並列に実行する --SceneGraph と Rendering Engine 1 dot 1 dot SPUが書いていく <td><img src="photo/rendering.png" alt="rendering" ></td> --Rendering Task SG2PP SceneGraph を操作後、ポリゴンに変換し PolygonPack (ポリゴンの集合)を生成する PP2SP ポリゴンの中から、Span (ポリゴン内にあるx軸に水平な線分) を抽出し、 SpanPack (Span の集合)を生成する DrawSpan Span を使って 1 ラインずつ FrameBuffer に描画していく --Demo されている Chain 相互制約が非常に大きい物理シミュレーションの例 非ホロノミック系なので、単純な積分では力学を決定できない SPU上で、すべての要素を同時に計算する必要がある (あまり並列計算向きではない...ベクトル向き) (地味です...) --まとめ Blender/Linux/Cerium を用いたオープンソースなゲームフレームワーク SceneGraphを作れば、move/collision を記述するだけで並列に実行される ソフトウェアレンダリングなんで、なんでも自分で書ける --将来的には、 C++ やめたい。悪いことばかり。メモリ食い。 CbC (Continuatin based C)で書き直す予定。 Cell は、やばそうなので、新しい並列アーキテクチャとか。 Open Scene Graph, Open/CLとの関係とか。