1. Linux 上でのゲームフレームワーク

       Cerium Task Manager
    Blender / SceneGraph
  2. Cell ってどうなの?

       結局、Video Chip に触れない
    SPUでレンダリング
    ソフトレンダリングにしては速いが...
    新型PS3では、Linux は使えない
    とかいろいろだめ
  3. Cell Architecture

    pipeline

    Linux 側から使える SPE は 6 個
    SPE は 256KB の Local Store (LS)
    SPE からメインメモリへ直接アクセスできない (DMAを使う)
    SPE は 128 ビットレジスタを 128 個持っている

  4. 楽するための並列プログラム

    トリビアルなプログラムでも並列実行する必要がある

    Single Thread でもPPE がクソ遅いので、SPEで実行するべき

    例えば、

        Word Count
  5. プログラムを Task に分割

    Task には依存関係がある

    Open/CL , Spurs Engine

  6. 並列性

  7. 階層的並列プログラミング

          Row Level での並列性 
    Vector/Streaming
    結局、データ並列とパイプライン
    SPE Level での
    データ読み込み、 実行、データ書込
    のパイプライン並列
    High Level での並列性
    Rendering
    Scene Graph
  8. データ読み込み、 実行、データ書込

    pipeline

    パイプラインバッファはいくつ?

  9. Task は良いけど、データはどうするの?

    データを右から左に...
         処理中に必要なデータがメインメモリ上にある
    でも、SPE には、256k しかメモリがない
    メインメモリ(256MB、広くはないが十分)から、256Kに必要なだけキャッシュする
         ハードウェアでやれよ!
    普通の並列ハードウェアはキャッシュになっている
    IBMはそう提案したらしいが、SCEの人が拒否したらしい
    なので、自分でキャッシュする必要がある

  10. Cerium Task Manager

           Open/GL Mesa に Cell driver を書いたが、
    メインメモリに依存しすぎ
    Task base で書く必要がある
    Redering Engine も自前で一つ持っていて良い
    SPEは256Kなのでコード管理も必要
    SPURSは公開されないらしい
    そんな経緯で作成することに...

  11. Crium Task Manager の特徴

           PPU/SPUで、Task の互換性がある
    SPU上の最適化は当面禁止
    OS X 上でも動く
    コードのデバッグはOS X 上でやる
    並列化とチューニングだけPS3上で行なう
    SPU上のメモリをCode と Data を Hash とメモリリストで管理する
    SPUに入り切らない巨大なTaskでも実行できる
  12. ゲームの作り方

           Blender で、3Dモデリング
    階層化、グルーピング
    これを、Blender の Python plugin で XMLに変換
    画像/Texture もXMLに埋め込まれる
    XMLを読み込み SceneGraph を作る
    sg

  13. Blender から SceneGraph 用の xml 生成

    PythonScript の導入


    1. Blender をダウンロードしてインストール

    2. export_xml.py を用意する

    3. "/Applications/blender-version/blender.app/Contens/MacOS/.blender/scripts
      "
                 以下にexport_xml.py をコピー

    4. Blender を起動すると File -> Export に Libps3 (.xml) が追加される


    ゲームの初期化部分でcrateFromXMLfileを呼ぶ


    void
    game_init(TaskManager *manager, int bg)
    {
       sgroot->createFromXMLfile(manager, "xml_file/SG.xml");
    ...

  14. SceneGraph

           階層化された3Dオブジェクト
    子供の向きを決定する変換行列
    Camera
    背景
    入力デバイス
    SceneGraph のノードには、
           MoveTask
    Collision Task
    がある
  15. ゲームとは、

           SceneGraph を
    MoveTask
    CollsionTask
    で書き換えていく
    MoveTask, CollsionTask は、ステートパターンで
    入れ換えられる
    これで、すべて書ける。

  16. つまり、

        SceneGraph の構築
    MoveTask
    CollsionTask
    だけを書けば、あとは、Cell が自動的に並列に実行してくれる

  17. Task の作り方

    SchedTask を継承した class を作る

    class SpeTask : public SchedTask {
        SchedConstructor( SpeTask );
    int run(TaskManager *manager, void *rbuf, void *wbuf);
    };

    run 関数は Task における main 関数のようなもの
    SchedConstructor() で class 名を登録する
    (C++のnew を使うとメモリを食われる...)

    SchedRegisterTask(TASK_SPE, SpeTask) で SpeTask に TASK_SPE という ID をつけて
    登録します

  18. Task の作り方(Con't)


    /* 先ほど登録した 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();


  19. Task の作り方(Con't)

    Task は依存関係を記述する事ができる

    /* taskB は taskA が終わるまで待つ */
    taskB->wait_for(taskA);

    /* taskC は taskB が終わるまで待つ */
    taskC->wait_for(taskB);


  20. 並列アーキテクチャは並列でないと...

    特に、Cell/PS3 は、SPUで実行しないとだめ
         既存のプログラミングでは、まったく歯が立たない
    トリビアルなプログラムでも、並列にする必要がある

  21. WordCount

          Task をグラフ構造的に構築する (SceneGraphのMoveTask)
    File を mmap する
    mmap した部分をTask に割り当て、word countする
    Task の構築
    Task の依存関係
    char *file_mmap = st_mmap.file_mmap;
  22. WordCount

    sg

  23. 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;
    }

  24. WordCount 各SPEの結果を合計


           ....
    /* 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);

  25. やってはいけないこと

          最初に大量のTaskをすべて作る
    Task が自分でデータを拾って来る
    Task 同士が、同期を行なう
  26. Cerium Engine での同期

          Task 内では同期はしない
    Local Storage/専有したメインメモリしか使わない
    Task が終了した時に、Single Thread で動いているPPE
    がデータの整理/同期を行なう
    Task 側では、Task の生成は行なわない
    Task の post_func (continuation) で、Taskを生成する
  27. 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 と互換。メインメモリを自由に参照できる
  28. Fifo TaskManager

    全部、同じCPU上で実行する。

    OS X 上で動作する (Linux でも)

    デバッグ用

  29. MemList と Hash

          get_segment/put_segment/wait_segement
    明示的にキャッシュ制御する必要がある
    特に、

    Dynamic SPE Task

          SPE上に常駐しないTask
    MemList と Hash で管理されている
    256K (GBAと同じ!?) しかメモリがないので重要

  30. SPU上でのコード管理

           GCCのOverlayを使う 
    Overlay では、異なる場所にコードを置けない
    部分的にPICではなく、絶対参照に変更する
    自分自身へは相対参照。ライブラリへは絶対参照
    Perl Script で書き換える
  31. Task list

           task_list にオブジェクト生成するコードを入れる
    オブジェクトが生成されてしまえば、普通に扱える
    task 実行中にコードが追い出されることはない
    現在実行中のコード
    次にロードするコード
    の二つは必ずメモリ上にある
  32. SceneGraph と Rendering Engine

          SceneGraph -> SceneGraph
    SceneGraph -> Polygon
    Polygon -> Span Pack
    Span Pack を Texture を使って Rendering
    これらを大きく並列に実行する
    Rendering は細かく並列に実行する
  33. SceneGraph と Rendering Engine

    1 dot 1 dot SPUが書いていく

    rendering

  34. Rendering Task

    SG2PP
  35. Demo されている Chain

          相互制約が非常に大きい物理シミュレーションの例
    非ホロノミック系なので、単純な積分では力学を決定できない
    SPU上で、すべての要素を同時に計算する必要がある
    (あまり並列計算向きではない...ベクトル向き)
    (地味です...)

  36. まとめ

    Blender/Linux/Cerium を用いたオープンソースなゲームフレームワーク

    SceneGraphを作れば、move/collision を記述するだけで並列に実行される

    ソフトウェアレンダリングなんで、なんでも自分で書ける

  37. 将来的には、