web-dev-qa-db-ja.com

OpenGLで間接レンダリングを使用する利点は何ですか?

glDrawElementsIndirectglDrawArraysIndirect のようなAPIが間接レンダリングに役立つことを読みました。間接レンダリングは、「頂点属性の数」、「描画するインスタンスの数」、「バッファオブジェクトから頂点属性を開始する」などのレンダリングパラメータが、GPU自体ではなく、GPU自体によってバッファオブジェクトに提供されるという点で、直接レンダリングとは異なります。ドローコールでCPUによって提供されます。

私は理解した。また、CPUの相互作用がないため、レンダリングが速くなるという利点も説明しました。しかし、待ってください、実際にレンダリング呼び出しを行ったのはCPUではありませんでしたか?それでもレンダリングモードを指定しました(GL_TRIANGLESなど)。また、頂点属性をロードした可能性もあります。

間接レンダリングのすべてのパフォーマンスゲインは、これらの小さな変数を渡す必要がないことによって説明されます: "count"、 "primitive count"、 "最初の頂点属性」、「インスタンス数」?これは私にはあまり意味がありません。 (状態も変化していません)

21
viktorzeid

多くの場合、パフォーマンスの向上は、「count」や「instance count」などの小さな変数を渡すことによるものではなく、knowingによるものです。これらの値を知るには、CPUへのラウンドトリップを実行する必要があります。これは、結果が利用可能になった後、つまりサーバーの同期後にのみ可能です(さらにバスのレイテンシーが追加されます)。

ジオメトリシェーダーで変換フィードバックを使用しているとします。つまり、何をフィードしても、バッチが終了してカウントを照会する前ではなく、相手側で何が出力されるかを本当にわからないということです。 。
間接レンダリングはこれに対処します。知る必要はなく、実際には知りたくありません。情報はバッファオブジェクトに入り、GPUはユーザーの介入なしにそれにアクセスできます。

これは条件付きレンダリングに似ています。実際には、条件付きレンダリングのすべてをスキップすることができますね。実行されない可能性のあるコマンドをコマンドキューに送信する代わりに(非効率的です!)、オクルージョンクエリを実行して、それが成功するかどうかを確認してから、描画するオブジェクトを送信するかどうかを決定できます。
これを除いて、この決定を行う前に、クエリ(したがって前のバッチ)が終了するまで待機し、同期して、PCIe転送を実行する必要があります。この間、GPUがストールする可能性があり、まだ適切なバッファー/テクスチャーをセットアップしておらず、コマンドを送信していません。したがって、実際には、投機的にコマンドを送信し、ドライバー/ GPUにコマンドを破棄するか、描画するかを決定させる方がはるかに効率的です。

これは、クエリ結果をバッファオブジェクトに読み込むことができるARB_query_buffer_objectの背後にある考え方でもあります。

編集:
また、間接レンダリングにより、レンダリングコマンドバッチのより効率的な送信が可能になり(特に永続的なマッピングと組み合わせて)、通常存在するサーバー/クライアントおよびCPU/GPUの同期の多くまたはすべてを回避でき、別の同期から発生する可能性がありますプロセッサコアであり、ドローコールごとの固定オーバーヘッドを節約します。 62ページ以降を参照してください Cass Everittの講演で

22
Damon

直接レンダリングでは、CPUは、GPUへの帯域幅が制限されたバスを介して、自身のメモリからインデックスデータを準備してストリーミングすることに専念します。 GPUの状態をチェックし、同期する必要があります。これらの各ステップには時間がかかります。

間接レンダリングを使用すると、CPUが行うのは、1つの短いコマンドを送信することだけです。これにより、大量の描画操作が開始されます。これにより、バスの帯域幅が節約されます。また、GPUはより長い時間動作するため、CPUが現在実行していることを強制的に停止する中断が少なくなります(コンテキストスイッチ)。つまり、物理シミュレーションなどの複雑な数値タスクの実行パフォーマンスが向上します。

9
datenwolf