プロフィール

Na-7

Author:Na-7
SE(システムエンジニア)として約15年間システム系ソフト会社を勤めあげ、2008年3月退社。現在、ゲーム制作会社設立を目指して活動中。


アクセスカウンター


最新記事


最新コメント


最新トラックバック


月別アーカイブ


カテゴリ


DATE: CATEGORY:スポンサー広告
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
DATE: CATEGORY:三国志軍記開発
シェーダーインスタンス4000枚
UVアニメサンプル改
UVアニメのサンプルをシェーダーインスタンスに改修中。現時点でのパフォーマンスは上々らしい。



◎訂正

前回の本文に間違いがあり、yohさんからご指摘を頂いたのですが、コメントでもちょっと怪しいことを書いてしまったので、改めて整理します。

HLSLの配列宣言と消費レジスタ数は以下の通りです。

float Params[1000]; // 定数レジスタ1000消費相当
float4 Params[1000]; // 定数レジスタ1000消費相当
float4x4 Params[1000]; // 定数レジスタ4000消費相当

私のメインPCはイレギュラーなシロモノなので、これでも正常に動作します。Intel系チップセット内蔵グラフィックスでは、頂点シェーダーをソフトウェアで対応しているそうですので、定数レジスタも仮想で4000以上実装していると考えれば納得できます。

しかし私のサブPCをはじめ、一般的なシェーダ2.0環境の定数レジスタは256個なので、(コンパイルは通りますが)DrawPrimitives実行時にエラーになります。

描画操作を実行する前に、有効な頂点シェーダーとピクセル シェーダーの両方 (または有効なエフェクト) がデバイスで設定されている必要があります。

以下のように宣言すると、エラーを回避できます。

float4x4 Params[60]; // 定数レジスタ240消費相当

上限が63ではなく60である理由は、World、View、Projection行列の受け渡しに定数レジスタを3×4個消費したため、と考えています。



◎一度に描画するモデル数

yohさんに定数レジスタ数の取得方法を教えて頂いたので、メインPCで実行したら「8192」でした。それなら2000モデルぐらい描画できそうですが、実際には1024以上のモデルを描画するとおかしくなります(前回参照)。原因は不明ですが、ドライバの仕様かバグかもしれません。

で、気になるのはMaxVertexShaderConstantsの返却値をどこまで信用して良いのか?ということです。この返却値を参照して‘一度に描画するモデル数’を決定すれば、グラフィック性能を最大限に引き出せるのですが、メインPCを見る限り、いまいち信用しきれません。今のところ「256固定で組むのが無難かな~」などと考えています。



◎イレギュラーPC

メインPCの他のプロパティも調べてみました。

DeviceType = Hardware
MaxPixelShader30InstructionSlots = 0
MaxPixelShaderProfile = PS_2_0
MaxPrimitiveCount = 65535
MaxSimultaneousRenderTargets = 1
MaxSimultaneousTextures = 8
MaxStreams = 16
MaxTextureWidth = 2048
MaxVertexIndex = 65534
MaxVertexShader30InstructionSlots = 32768
MaxVertexShaderConstants = 8192
MaxVertexShaderProfile = VS_3_0
PixelShaderVersion = 2.0
VertexShaderVersion = 3.0

ちょっと驚きなのが、頂点シェーダとピクセルシェーダのバージョンが違うということです。こういう場合、シェーダモデル2.0扱いなんですかね?

定数レジスタ数だけでなく、命令スロット数も異常ですね。
頂点シェーダ側は32768(VS_3_0規格は512以上)と桁違いに多いのに、ピクセルシェーダ側は0(PS_2_0規格は32 + 64)。
いくらなんでも0はおかしいと思いますが…ますます信用できなくなりました(笑)

PCゲームを開発する人は、こんなPCもあることを頭の片隅にでも入れておいてください。「落ちた」と言われて調べたら、環境の問題だった、なんてことがあるかも。



◎カスタムモデルクラスについて

本題に入る前に、もう1つ余談があります。

ネット上のDrawPrimitives系のサンプルは、どれも頂点データをコード内で自作しています。DrawPrimitivesの使い方に関してはわかりやすいのですが、外部ツールで作成したモデルデータをDrawPrimitivesで表示する方法はわかりません。

結論から言うと、これをやるには予めコンテントパイプラインでカスタムモデルクラスに読み込むのが理想的です。ただ、この方法は標準Modelクラスに読み込んで表示する方法と比べると、複雑で面倒でわかりにくいです。

そこで、先日のUVアニメサンプルは、標準Modelクラスに読み込んだデータをDrawPrimitives系で動かすようにしました。ちょっと実験する程度ならこれでも動くし、初心者にはこの方がわかりやすいと思います。


ですが、今回UVアニメサンプルにシェーダーインスタンスを適用しようとして、そろそろ無理が出てきました。

・メタセコイアモデルを読み込むために、
 カスタム頂点フォーマットAが必要

・シェーダーインスタンスのために、
 フォーマットAに番号を付与したフォーマットBが必要

1つのモデルにカスタム頂点フォーマットが2つ存在したら、わかりやすいプログラムとは言えないですね。

しかし、私の予定ではカスタムモデルに移行するのは公式サンプル解析後ですので、今回は標準Modelクラスを使用する方法で押し通します。



◎Matrixと定数レジスタ

ところで、前回のサンプルでは各インスタンスに(Vector3ではなく)Matrixで移動情報を渡していましたが、何か深い意図があったのでしょうか?

Matrixは定数レジスタを4つ消費するので、頂点座標とテクスチャ座標をMatrixで渡す場合は8つも消費してしまいます。定数レジスタ数が256個のPCでは、一度に30モデル程度しか描画できません。

そこで今回はVector3とVector2を渡すことにします。これで一度に120モデル程度描画できますね。



◎インデックスデータの増分値

で、実際に改修を始めると…やはりちょっと難しいですね。何とかモデルを1つ描画する所まではいきましたが、なかなか複数描画できません。

試行錯誤の末に気付いたのは、インデックスデータの増分値。複製する際に増分値を加算する必要があります(加算しないと頂点データを複製する意味が無い)が、インデックスデータの要素数ではなく、頂点データの要素数を加算する必要があったのですね。

というわけで、ようやく複数描画できるようになりました。

シェーダーインスタンス01



◎Matrixとクォータニオン

お次は板ポリの回転です。

この段階でようやく気付いたのですが、回転データも個別に渡す必要がありますね。前回サンプルがMatrixを使用していた意味がやっと分かりました。Matrixなら移動、回転、スケールをまとめて渡せるからですね。

でもやっぱり定数レジスタ数は節約したいので、回転量だけ渡してシェーダー側で回転させたいものです。しかし、シェーダー側にはMatrix.CreateRotationYのような便利なメソッドが無いので、頂点変換が難しそうですね。

…そういえば、Gamefest2008の解説で、クォータニオンが便利って言ってたなぁ。再度プレゼンを聞いて、デモのエフェクトファイルを覗くと、確かに便利そうな関数がありました。

これを機に、シェーダはデモプログラムのコードをベースに置き換えます。今回は不要のもの(スペキュラとか)もありますが、今後のことを考えて、大部分を取り込みました。

シェーダーインスタンス1000枚

せっかくなので色も付けました。BasicEffectと同等ですね。回転に合わせて光が反射するのでちょっといいかもw



◎パフォーマンスは?

まだ改修中で、頂点座標と回転はインスタンス化しましたが、テクスチャ座標はまだ動的頂点バッファでやってます。
この段階での速度はどんなもんですかね?

1000枚:60fps
1500枚:60fps
2000枚:12fps

なんか以前よりも遅くなってますが…そうか!頂点バッファ書き込みをインスタンス毎にやってましたが、シェーダーインスタンス化したので1フレームに1回やれば十分ですね!



やりました!4000枚60fpsです!

動画取得中でも60fps近く出るなんてスゴイですね~!!



◎次回予告

次回はUVアニメ改修作業の続きです。

・UVアニメをインスタンシングに移行する
・動的頂点バッファを静的頂点バッファとする
・定数レジスタ256に対応する
・プログラムやコメントを整理する
・デバッグモジュールを組み込む
・メインPCとサブPCで測定する

速くなる要素と遅くなる要素があります。
最終的にどうなるか楽しみですね~w

スポンサーサイト

テーマ : ゲーム製作 関連 - ジャンル : ゲーム

コメント

>MaxPixelShader30InstructionSlotsが0

家のノートPCだと、それとMaxVertex~のどちらも0を戻しました。

>512 以上の命令スロットを使用するには、ps_3_0 をサポートするデバイスが必要です。
とマニュアルにありますので、恐らくPS(VS)2.0しかサポートしていないハードだと0を戻す仕様なんでしょうね。


あと個人的な経験ですが、スペキュラは結構重いです。頂点単位で光源計算を行っているため、ピクセルシェーダの負荷が大きいからです。

そちらの環境では頂点シェーダがエミュレートとのことですので一概に言えませんが、GPUの負荷が大きくなったらまずはピクセルシェーダの処理の中で、頂点シェーダでやっても同じ結果になるものがないか確認するのがよいようです。

と言うか、板ポリにはスペキュラ要らないと思いますし(笑)。

おはようございます

>0を戻す仕様
なるほど、そうでしたか。どこまでイレギュラーなのか怪しんでいたのですが、ピクセルシェーダーはわりと普通かもしれませんね。

>スペキュラ
itoさんもプレゼンで重いって言ってましたね。

>GPUの負荷が大きくなったら
頂点シェーダとピクセルシェーダの負荷バランスに注意しろってことですね。以後気を付けますが、測定値などの目安が無いので判断が難しそうです。いろいろ試して経験積むしか無いのでしょうか?

>と言うか、板ポリにはスペキュラ要らないと思いますし(笑)。
全然要らないです(笑)

コメントの投稿


管理者にだけ表示を許可する

トラックバック


この記事にトラックバックする(FC2ブログユーザー)



copyright © ゲーム制作の舞台裏 all rights reserved.Powered by FC2ブログ
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。