XNA最適化ネタ(id:ABA:20071221#p1)の続き。とりあえず以下のようにしてみた。
- System.Diagnostics.Stopwatch.GetTimestamp()を使ってどこが重いのかを計測
- やはりパーティクルの描画、というかGPUをキックする部分が重いことを確認
- パーティクルのオブジェクトプールを2つに分けてそれぞれ1コアずつに割り振り
- VertexBuffer.SetDataは並行に実行可能なので、パーティクルのUpdate処理内でそこまでやってしまう
- Draw時にはDrawIndexedPrimitivesを蹴るだけ
パーティクルだけで2コア占有(といってもまだぜんぜん占有と呼べるほどは使い切れてないのだが)するようにしてしまったらだいぶましになった。ただこれも後々負荷がかかる場所が変わってくると分散のさせ方を変えなくてはならないから面倒だな。並列化は最後にやれっていうのは定石だが、それでもどこかで並列化によって効果が出るかどうかを確認しておかないと、並列化でどうにかなるレベルの負荷がどうかが分からないからなあ。
あとVertexBuffer.SetData自体があんまり軽い処理じゃない感じもした。まだちゃんと測定してないけど。XNAで大量のプリミティブを動的に生成して描画する場合の最適解はどれなんだろう。今やっているSetDataを別コアでやってそのオーバヘッドを隠蔽してDrawIndexedPrimitivesで描画、ってのよりいい方法があるならそっちに乗り換えたい。マルチコアでオーバヘッドが常に隠蔽できる保障はないからね。
あとSetDataってその書き込む先のVertexBufferがGrapihicsDeviceのVerticesにSetSourceで指定されているとInvalidOperationException吐くのが微妙に使いづらい。まあある意味当たり前なのだが。書き込む前にSetSourceで明示的にnullを放り込めば大丈夫みたいだ。