
- ブック1:概要
- ブック2:問題
- ブック3:ソリューション
- ブック4:結論
2番目の本へようこそ! ここでは、視覚化プロセス中に発生する可能性のある問題のいくつかを調べます。 しかし、まず最初に、少し練習します。
問題について知ることは役に立ちます。 しかし、理解するためには、問題を本当に感じる方がはるかに優れています。 CPU / GPUの代わりに自分を置いてみましょう。
実験
10,000個の小さなファイル(たとえば、それぞれ1 KB)を作成し、それらを1つのハードドライブから別のハードドライブにコピーしてください。 この操作には時間がかかりますが、データサイズはわずか9.7 MBです。

次に、1つの9.7 MBファイルを作成し、同じ方法でコピーします。 この操作ははるかに高速に実行されます!
なんで? 結局のところ、データサイズは同じです!事実ですが、 各コピー操作は、実行する必要がある多くのことで構成されています。たとえば、移動のためのファイルの準備、メモリの割り当て、ドライブの読み取り/書き込みヘッドの前後への移動などです。これは、 各書き込み操作のオーバーヘッドです。 あなた自身の方法で経験したかもしれませんが、多くの小さなファイルをコピーする場合、このオーバーヘッドは莫大です。 多くの多角形グリッドの視覚化(つまり、多くのコマンドの実行)ははるかに複雑ですが、同じように感じます。

次に、視覚化プロセス中に発生する可能性のある最悪のケースを見てみましょう。
最悪の場合
小さなポリゴンメッシュがたくさんあるのは悪いことです。 異なる材料パラメータを使用している場合、すべてがさらに悪化します。 しかし、なぜですか?
1.多くのポリゴンメッシュ
GPUは、コマンドを送信するためにCPUよりも速く描画できます。
Draw Callの数を減らす主な理由は、グラフィックハードウェアが、三角形を転送するよりもはるかに速く修正およびレンダリングできるためです。 各呼び出しに少数の三角形を送信すると、CPUパフォーマンスによって完全に接続され、GPUの大部分がスタンバイモードになります。 CPUはGPUに十分な速度で「フィード」できません。 [ f05 ]
さらに、各Draw Callにはオーバーヘッドが発生します(前述のとおり)。
API呼び出しを行うときは常にドライバーレベルでオーバーヘッドが発生します。それらを減らす最良の方法は、APIをできるだけ少なく呼び出すことです。 [ a02 ]
2.多くのドローコール
このような追加のオーバーヘッドの一例は、命令バッファーです。 CPUが命令バッファーを満たし、GPUがそれを読み取ることを覚えていますか? はい、変更を報告する必要があり、これによりオーバーヘッドも発生します(読み取り/書き込みポインターの変更。詳細はこちらをご覧ください )。 このため、コマンドを一度に1つずつ送信するのではなく、最初にバッファーをいっぱいにしてコマンドのブロック全体をGPUに転送する方がよい場合があります。 これにより、CPUがコマンドブロックの構築を完了するまでGPUが待機するリスクが高まりますが、同時に通信コストが削減されます。
GPUは、(幸いなことに)CPUが新しい命令バッファーを構成している間(たとえば、前のブロックを処理している間)にすべきことがたくさんあります。 最新のプロセッサは、複数のコマンドバッファを互いに独立して一度に埋めてから、GPUに順次転送できます。上記の例は1つだけです。 現実の世界では、CPU、GPU、およびコマンドバッファーだけが互いに通信しません。 API(DirectX、OpenGL)、ドライバー、および他の多くの要素がこのプロセスに含まれていますが、これは簡単ではありません。
同じマテリアル(レンダリング状態)を使用する多くのポリゴンメッシュの場合についてのみ説明しました。 しかし、異なるマテリアルでオブジェクトを視覚化する場合はどうなりますか?
3.多くのポリゴンメッシュとマテリアル
コンベアをリセットします。
状態を変更すると、コンベヤを部分的または完全にリセットしなければならない場合があります。 このため、シェーダーまたはマテリアルパラメーターの変更は非常に高価な操作になる可能性があります[...] [ b01 ]あなたはそれがそれ以上悪くないと思った? そのため、異なるポリゴンメッシュで異なるマテリアルを使用する場合、視覚化コマンドをグループ化することはできません。 最初のグリッドにレンダー状態を設定し、それを表示するコマンドを実行してから、新しいレンダー状態を設定し、次のレンダーコマンドを送信します。
「状態の変更」チームを赤で塗りつぶしました。a)費用がかかり、b)読みやすいからです。レンダー状態の値を設定する場合(常にではありませんが、変更するパラメーターによって異なります)、パイプライン全体をリセットする必要があります。 これは、現在処理されている各ポリゴンメッシュ(現在のレンダリング状態で)を表示してからでないと、次のポリゴンメッシュを(新しいレンダリング状態で)レンダリングできないことを意味します。 上記のビデオのように見えます。
膨大な数の頂点を取得する代わりに(たとえば、複数のグリッドを同じRender Stateに結合します。この最適化については後で説明します)、Render Stateの変更操作の前に少量が表示されます。
ところで、CPUは(ポリゴンメッシュのサイズに関係なく)Draw Callパラメーターを設定するのに最小限の時間しかかからないため、2つまたは200の三角形の表示に違いはないと想定できます。 GPUは非常に高速であり、CPUが新しいDraw Callを準備する間、三角形はすでに画面上で新しく作成されたピクセルになります。 もちろん、この「ルール」は、いくつかの小さなポリゴンメッシュを1つの大きなメッシュに結合することについて話すときに変更されます(これについては後で説明します)。
最新のグラフィックカードで「無料」で視覚化できるポリゴンの数に関する最新のデータが見つかりませんでした。 これについて何か知っているか、最近測定したことがあれば、私に知らせてください!
4.多角形のグリッドとマルチマテリアル
ポリゴンメッシュに1つのマテリアルではなく、2つ以上のマテリアルが割り当てられている場合はどうなりますか? 基本的に、グリッドはいくつかの部分に引き裂かれ、コマンドバッファに部分的に「供給」されます。
もちろん、これには各グリッド要素に追加の描画呼び出しが必要です。
多くのポリゴンメッシュとマテリアルの何が問題なのかを簡単に理解できたと思います。 次の本では、すべてがひどく見えても、いくつかの解決策を見ていきます。 しかし、上記の問題が何らかの形で克服されたことを証明する素晴らしいゲームがあります。
終わり
[a02] GPUプログラミングガイドGeForce 8および9シリーズ
[b01] リアルタイムレンダリング :ページ 711/712
[f05] なぜドローコールが高価なのですか