OpenGLの低レベルパフォーマンスに関する質問 質問する

OpenGLの低レベルパフォーマンスに関する質問 質問する

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

多くのチュートリアル、さらには SO の質問にも同様のヒントがあり、一般的には次の内容がカバーされています。

  • GL フェイス カリングを使用する (シーン ロジックではなく OpenGL 機能)
  • GPU に 1 つのマトリックスのみを送信する (projectionModelView の組み合わせ) ため、MVP 計算が頂点ごとに 1 回からモデルごとに 1 回に減ります (これが正しい方法です)。
  • インターリーブ頂点を使用する
  • GL呼び出しを可能な限り最小限に抑え、適切な場合はバッチ処理する

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

私の実装では約 40 FPS を実現していますが、これは決して問題ではありませんが、これらの最適化の「ヒント」が実際にどこで役立つのかはまだわかりません。

レンダリング中はCPUが20~50%程度アイドル状態になるので、仮定するパフォーマンスを向上させるために GPU を使用しています。

注記:現在gDEBuggerを検討中です

クロスポストゲーム開発

ベストアンサー1

ポイント 1 は明らかで、フィル レートを節約します。オブジェクトの裏側のプリミティブが最初に処理される場合、これらの面は省略されます。ただし、最新の GPU はオーバードローをかなりうまく許容します。私はかつて (GeForce8800 GTX)、パフォーマンスが大幅に低下する前に、最大 20% のオーバードローを測定しました。ただし、この余裕は、オクルージョン カリング、ブレンドされたジオメトリのレンダリングなどのために取っておく方がよいでしょう。

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

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

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

しかし、これらはすべてマイクロ最適化です (大きな影響を持つものもあります)。ただし、早期 Z パスの実装、早期 Z でのオクルージョン クエリを使用したジオメトリ バッチ全体の迅速な判別など、影響の大きい最適化を検討することをお勧めします。基本的に Point-4 のようなマイクロ最適化を多数まとめたもので構成される、影響の大きい最適化の 1 つは、レンダリング バッチをコストの高い GL 状態で並べ替えることです。つまり、すべてを共通のシェーダーでグループ化し、それらのグループ内でテクスチャなどで並べ替えます。この状態のグループ化は、表示されているレンダリング パスにのみ影響します。早期 Z では、Z バッファーの結果のみをテストするため、ジオメトリ変換のみがあり、フラグメント シェーダーは Z 値のみを渡します。

おすすめ記事