テクスチャの変更(その上でのペイント)は、「状態変化」と見なされますか?


11

グラフィックスの慣例では、状態変更をより少なく実行する方が、より多くの状態変更を実行するよりも優れています(シェーダーの切り替え、バッファーのバインド、テクスチャのバインドなど)。テクスチャの場合、(スプライト/テキストをレンダリングするために)1つのアトラスを使用して多くのポリゴンをレンダリングする方が、各ポリゴンに新しいテクスチャを個別にバインドするよりも高速です。

継続的にテクスチャにペイントしている場合、これは当てはまりglTexSubImage2Dますか?(ネットワークを介して)入ってくるデータのストリームがあり、処理を経て、一度に1行ずつテクスチャーにペイントされます。データは視覚的に無限のスクロールで表示されます。

1つの大きな長方形にレンダリングされた1つのテクスチャにペイントする方がよいでしょうか(ペイントされたデータをスクロールして表示します)。ここでのアイデアは、ペイントを続けている間、いつでも1つまたは2つのテクスチャをバインドすることです。

または、たくさんの小さな長方形をペイントする必要がありますか(ペイントが完了すると長方形のみが表示されます)。長方形ごとに1つのテクスチャをバインドするとします。

回答:


11

グラフィックスデバイスのメモリ領域(テクスチャ、バッファなど)の更新は、レンダリング状態の変更とはまったく異なります。

レンダリング状態の変更に負荷がかかるのは、新しい状態を検証してパイプラインを並べ替えるためにドライバーが実行しなければならない作業量です。これにより、CPUとグラフィックスデバイス間の同期も発生します。ただし、デバイス間で転送されるデータの量は、状態の変化(おそらく数個のコマンドのみ)に対しては小さくなければなりません。

一方、テクスチャ/バッファの更新の場合、主なコストはデータ転送自体にあります。理論的には、更新後にテクスチャデータをCPUに読み戻さない限り、同期やパイプラインのストールはありません。ただし、別の側面を考慮する必要があります:APIオーバーヘッド。グラフィックデバイスに送信するデータの量が少ない場合でも、それを頻繁に行うと、ドライバー/デバイスとの通信コストがデータ転送のコストよりも高くなります。これが、レンダラーを最適化するときにバッチ処理が非常に重要であるもう1つの理由です。

したがって、あなたの場合、最良のアプローチは、私には、新しいデータが到着したときに更新するテクスチャのシステムメモリコピーを保持することです。ダーティフラグを設定し、できるだけ多くの更新をglTexSubImageテクスチャ全体(またはその連続する大部分)の1つに統合します。ピクセルバッファーオブジェクトとできるだけパイプラインのストールを減らすために、非同期データ転送を実行しよう。ある種のダブルバッファリングを実装できる場合は、テクスチャの1つのコピーに書き込み、もう1つのコピーを使用してレンダリングできます。このチュートリアルを使って遊ぶこともできます。それが私の直感的なアプローチです。API呼び出しの数を減らして、テクスチャの更新を「バッチ処理」しようとします。そうは言っても、これは非常に推論的であり、プロファイリングして、いくつかの小さな更新を行うなど、他のアプローチと比較して、使用例で最もパフォーマンスが高いものを確認する必要があります。

補足として、NVidiaによるこのプレゼンテーションは関連性があり、多くの優れた洞察を提供します:OpenGLでのゼロドライバーオーバーヘッドへのアプローチ


5
確かなことはわかりませんが、最後のフレームでレンダリングされたテクスチャのglTexSubImageがパイプラインを停止させることが確実に疑われます。小さな更新のため、テクスチャ全体のコピーを作成したい。したがって、最大のパフォーマンスを得るには、テクスチャ(またはピクセルバッファオブジェクト)をダブルまたはトリプルバッファリングする必要があると思います。
John Calsbeek、2015
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.