21

このテーマは、他の最適化問題と同様に、多くの話題に上りますが、私が欲しい (と思う) ものを見つけることができませんでした。

多くのチュートリアル、さらには SO の質問にも同様のヒントがあります。一般的に以下をカバーします:

  • GL 顔カリングを使用する (シーン ロジックではなく、OpenGL 関数)
  • 1 つのマトリックスのみを GPU (projectionModelView の組み合わせ) に送信するため、MVP の計算が頂点ごとからモデルごとに 1 回に減少します (あるべき姿)。
  • インターリーブされた頂点を使用
  • 可能な限り多くの GL 呼び出しを最小限に抑え、必要に応じてバッチ処理します

そしておそらくいくつか/多くの他の人。私は (好奇心のために) いくつかの頂点バッファーを使用して、アプリケーションで 2,800 万個の三角形をレンダリングしています。上記のすべての手法を (私の知る限り) 試しましたが、パフォーマンスの変化はほとんどありませんでした。

私の実装では約 40FPS を受信して​​いますが、これは決して問題ではありませんが、これらの最適化の「ヒント」が実際にどこで使用されるのかについてまだ興味がありますか?

私の CPU はレンダリング中に約 20 ~ 50% アイドル状態になっているため、パフォーマンスを向上させるために GPU に依存していると思います。

注:現在、gDEBugger を調べています。

ゲーム開発に投稿されたクロス

4

4 に答える 4

26

ポイント 1 は明らかで、広告掲載率を節約できます。オブジェクトの裏側のプリミティブが最初に処理される場合、これらの面は省略されます。ただし、最新の GPU はオーバードローに非常によく耐えます。私 (GeForce8800 GTX) は、パフォーマンスが大幅に低下する前に、最大 20% のオーバードローを測定しました。ただし、オクルージョン カリング、ブレンドされたジオメトリのレンダリングなどのために、この予約を保存しておくことをお勧めします。

ポイント2は、まあ無意味です。GPU で行列が計算されたことは一度もありません。行列は常に、CPU で計算され、GPU のグローバル レジスタにプッシュされるレンダリング グローバル パラメーターのようなものであり、現在はユニフォームと呼ばれているため、行列を結合してもメリットはほとんどありません。追加のベクトル行列乗算を 1 つだけ節約するシェーダー (4 つの MAD 命令に要約) では、アルゴリズムの柔軟性が低下します。

ポイント 3 は、すべてキャッシュ効率に関するものです。一緒に属するデータは、キャッシュ ラインに収まる必要があります。

ポイント 4 は、状態の変更によってキャッシュが破棄されるのを防ぐことです。ただし、どの GL 呼び出しが意味するかによって大きく異なります。制服の着替えは安いです。テクスチャの切り替えはコストがかかります。その理由は、ユニフォームはキャッシュされたメモリの一部ではなく、レジスタにあるためです。シェーダーが異なれば実行時の動作も異なるため、シェーダーの切り替えにはコストがかかります。これにより、パイプラインの実行予測が台無しになり、メモリ (したがって) キャッシュ アクセス パターンが変更されます。

しかし、これらはすべてミクロの最適化です (中には大きな影響を与えるものもあります)。ただし、初期の Z パスを実装するなど、影響の大きい最適化を検討することをお勧めします。ジオメトリ バッチ全体をすばやく識別するために、初期の Z でオクルージョン クエリを使用します。ポイント 4 のようなマイクロ最適化のように多くを合計することで本質的に構成される大きな影響の最適化の 1 つは、負荷の高い GL 状態でレンダリング バッチをソートすることです。したがって、すべてを共通のシェーダーでグループ化し、それらのグループ内でテクスチャーなどで並べ替えます。この状態のグループ化は、可視のレンダー パスにのみ影響します。初期の Z では、Z バッファーで結果をテストするだけなので、ジオメトリ変換だけがあり、フラグメント シェーダーは Z 値を渡すだけです。

于 2011-03-09T10:31:46.860 に答える
3

@kvark と @datenwolf の回答に私の 2 セントを追加するために、あなたが言及したポイントは「基本的な」GPU パフォーマンスのヒントですが、より複雑な最適化はアプリケーションに大きく依存していると言いたいです。

ジオメトリが重いテスト ケースでは、既に 2800 万個の三角形を投げています * 40 FPS = 1 秒あたり 11 億 2000 万個の三角形 - これはすでにかなりの数です。ほとんどの (特に Fermi ではなく) GPU の三角形セットアップパフォーマンスは次のとおりです。 GPU クロック サイクルごとに 1 つの三角形。つまり、たとえば 800MHz で動作する GPU は、1 秒あたり 8 億を超える三角形を処理できません。これは、単一のピクセルを描画することさえありません。NVidia Fermi は、クロック サイクルごとに 4 つの三角形を処理できます。

この制限に達している場合 (ハードウェア プラットフォームについて言及していない場合)、OpenGL/GPU レベルでできることはあまりありません。できることは、より効率的なカリング (フラスタムまたはオクルージョン) を介して、または LOD スキームを介して、より少ないジオメトリを送信することだけです。

もう 1 つのことは、ラスタライザーがピクセルの正方形ブロックで並列処理を行うため、小さな三角形がフィルレートを損なうことです。http://www.geeks3d.com/20101201/amd-graphics-blog-tessellation-for-all/を参照してください。

于 2011-03-11T08:06:38.287 に答える
3
  1. はい
  2. ドライバーはこれらのマトリックスを組み合わせることができるため、意味がありません (ドライバーはそれらがユニフォームであることを認識しているため、ドローコール中に変更されません)。
  3. はい
  4. CPU バウンドの場合のみ

最初に知る必要があるのは、ボトルネックが正確にどこにあるかです。GPU は複雑なシステムであるため、答えにはなりません。実際の問題は次のとおりです。

  • シェーダー処理 (頂点/フラグメント/ジオメトリ)
  • フィルレート
  • 抽選番号
  • GPU <-> VMEM (インターリーブと小さなテクスチャが役立つ場所)
  • システムバス (フレームごとにデータをストリーミング?)

問題を確認するには、一連のテストを実行する必要があります。たとえば、すべてをより大きな FBO に引き寄せて、それがフィル レートに問題があるかどうかを確認します (または MSAA の量を増やします)。または、すべてを 2 回描画して、描画呼び出しのオーバーロードの問題を確認します。

于 2011-03-09T23:35:03.703 に答える
1

これは、実行している特定のハードウェアと使用シナリオに大きく依存します。OpenGL のパフォーマンスに関するヒントは、一般的なケースに当てはまります。結局のところ、ライブラリは、さまざまなドライバーの実装を抽象化したものです。ドライバーの作成者は内部で自由に最適化できるため、ユーザーの知らないうちに冗長な状態変更を削除したり、他の最適化を実行したりする可能性があります。別のデバイスでは、そうでない場合があります。さまざまなデバイスで優れたパフォーマンスが得られる可能性を高めるために、ベスト プラクティスに従うことをお勧めします。

于 2011-03-09T11:44:26.327 に答える