36

Vertex Buffer Objects (VBO) について何年も聞いた後、最終的にそれらを試してみることにしました (私のものは通常、パフォーマンスが重要ではないことは明らかです...)

以下で私の実験について説明しますが、簡単に言うと、「単純な」ダイレクト モード (glBegin()/glEnd())、頂点配列 (CPU 側)、および VBO (GPU 側) の間で見分けがつかないパフォーマンスが見られます。レンダリング モード。これがなぜなのか、どのような条件下で、VBO が原始的な (しゃれを意図した) 先祖よりもはるかに優れていると期待できるかを理解しようとしています。

実験の詳細

実験のために、多数のポイントからなる (静的) 3D ガウス クラウドを生成しました。各ポイントには、それに関連付けられた頂点と色の情報があります。次に、一連のフレームでカメラを雲の周りで「周回」動作のように回転させました。繰り返しますが、ポイントは静的で、目だけが動きます (gluLookAt() を介して)。データは、レンダリングの前に 1 回生成され、レンダリング ループで使用するために 2 つの配列に格納されます。

直接レンダリングの場合、データセット全体が単一の glBegin()/glEnd() ブロックでレンダリングされ、ループには glColor3fv() と glVertex3fv() への単一の呼び出しが含まれます。

頂点配列と VBO レンダリングの場合、データ セット全体が単一の glDrawArrays() 呼び出しでレンダリングされます。

次に、タイトなループで 1 分程度実行し、高性能タイマーで平均 FPS を測定します。

パフォーマンス結果 ##

前述のように、デスクトップ マシン (XP x64、8 GB RAM、512 MB Quadro 1700) とラップトップ (XP32、4 GB RAM、256 MB Quadro NVS 110) の両方でパフォーマンスに違いはありませんでした。ただし、ポイント数で予想どおりにスケーリングしました。明らかに、vsync も無効にしました。

ラップトップの実行からの特定の結果 (GL_POINTS を使用したレンダリング):

glBegin()/glEnd():

  • 1K ポイント --> 603 FPS
  • 10K ポイント --> 401 FPS
  • 100K ポイント --> 97 FPS
  • 1M ポイント --> 14 FPS

頂点配列 (CPU 側):

  • 1K ポイント --> 603 FPS
  • 10K ポイント --> 402 FPS
  • 100K ポイント --> 97 FPS
  • 1M ポイント --> 14 FPS

頂点バッファ オブジェクト (GPU 側):

  • 1K ポイント --> 604 FPS
  • 10K ポイント --> 399 FPS
  • 100K ポイント --> 95 FPS
  • 1M ポイント --> 14 FPS

GL_TRIANGLE_STRIP を使用して同じデータをレンダリングしたところ、同様に見分けがつきませんでした (ただし、追加のラスタライズにより予想どおり遅くなりました)。誰かがそれらを望むなら、私もそれらの番号を投稿できます. .

質問

  • 何を与える?
  • VBO の約束されたパフォーマンスの向上を実現するには、何をしなければなりませんか?
  • 私は何が欠けていますか?
4

5 に答える 5

28

3D レンダリングの最適化には多くの要因があります。通常、4 つのボトルネックがあります。

  • CPU (頂点の作成、APU 呼び出し、その他すべて)
  • バス (CPU<->GPU 転送)
  • Vertex (固定関数パイプライン実行に対する頂点シェーダー)
  • ピクセル (フィル、フラグメント シェーダーの実行、および rop)

頂点またはピクセルのスループットを最大化しながら多くの CPU (およびバス) を使用しているため、テストの結果が歪んでいます。VBO は、CPU を下げるために使用されます (CPU DMA 転送と並行して API 呼び出しを減らします)。あなたはCPUバウンドではないので、彼らはあなたに何の利益も与えません. これが最適化の 101 です。たとえばゲームでは、大量の API 呼び出しを発行するためだけでなく、AI や物理演算などの他の処理にも CPU が必要になるため、CPU は貴重になります。頂点データ (たとえば 3 つの浮動小数点数) をメモリ ポインターに直接書き込む方が、3 つの浮動小数点数をメモリに書き込む関数を呼び出すよりもはるかに高速であることは容易にわかります。少なくとも、呼び出しのサイクルを節約できます。

于 2009-01-10T05:46:40.217 に答える
10

不足しているものがいくつかあるかもしれません:

  1. 大げさな推測ですが、あなたのラップトップのカードにはこの種の操作 (つまり、エミュレート) がまったくない可能性があります。

  2. データを GPU のメモリにコピーしていますかglBufferData( (またはparam を使用して) またはメモリ内のメイン (GPU 以外の) 配列へのポインターを使用していますか? (フレームごとにコピーする必要があるため、パフォーマンスが低下します)GL_ARRAY_BUFFERGL_STATIC_DRAWGL_DYNAMIC_DRAW

  3. パラメータを介して送信された別のバッファとしてインデックスを渡していますか?glBufferDataGL_ELEMENT_ARRAY_BUFFER

これら 3 つのことを実行すると、パフォーマンスが大幅に向上します。Python (v/pyOpenGl) の場合、数 100 個の要素よりも大きい配列では約 1000 倍、C++ では最大 5 倍高速ですが、50k-10m 頂点の配列では高速です。

c++ (Core2Duo/8600GTS) のテスト結果は次のとおりです。

 pts   vbo glb/e  ratio
 100  3900  3900   1.00
  1k  3800  3200   1.18
 10k  3600  2700   1.33
100k  1500   400   3.75
  1m   213    49   4.34
 10m    24     5   4.80

そのため、10m の頂点でも通常のフレームレートでしたが、glB/e では遅くなりました。

于 2009-02-14T15:14:46.953 に答える
2

レッドブックを読んだことで、ハードウェアによってはVBOの方が高速である可能性があると述べた箇所を覚えています。一部のハードウェアはそれらを最適化しますが、他のハードウェアは最適化しません。ハードウェアがそうではない可能性があります。

于 2009-01-13T19:21:41.753 に答える
1

14Mpoints/s は大した量ではありません。疑わしいです。描画と初期化を行う完全なコードを見ることができますか? (14M/s と Slava Vishnyakov の 240M/s (!) を比較してください)。1K 描画で 640K/s に低下することはさらに疑わしいです (彼の 3.8M/s と比較すると、とにかく ~3800 SwapBuffers によって制限されているように見えます)。

このテストは、あなたが測定していると思うものを測定していないに違いありません。

于 2009-11-19T21:10:05.670 に答える
-3

私がこれを正しく覚えていると仮定すると、OpenGL コミュニティでよく知られている OpenGL の先生は、静的なジオメトリの方が高速であると言いました。これは、テーブルの椅子と小さな静的なエンティティである典型的なゲームで多くの時間をレンダリングします。

于 2009-01-13T19:24:39.877 に答える