web-dev-qa-db-ja.com

破棄はOpenGLのプログラムパフォーマンスに悪いですか?

私は this の記事を読んでいて、著者は次のように書いています。

2つの簡単なステップで、すべてのプラットフォームで高性能アプリケーションを作成する方法を次に示します。
[...]
ベストプラクティスに従ってください。 AndroidおよびOpenGLの場合、これには「バッチ描画呼び出し」、「フラグメントシェーダーで破棄を使用しない」などが含まれます。

廃棄がパフォーマンスなどに悪影響を与えるとは聞いたことがなく、詳細なアルファが必要ないときにブレンドを回避するために使用してきました。

誰かが廃棄を使用する理由と時期が悪い習慣と見なされる理由と、廃棄+深度テストがアルファ+ブレンドとどのように比較されるかを説明できますか?

編集:この質問に対する回答を受け取った後、その上にテクスチャクワッドを使用して背景グラデーションをレンダリングすることにより、いくつかのテストを行いました。

  • GL_DEPTH_TESTと、行「if( gl_FragColor.a < 0.5 ){ discard; }」で終わるフラグメントシェーダーを使用すると、約32 fpsが得られました。
  • フラグメントシェーダーからif/discardステートメントを削除すると、レンダリング速度が約44 fpsに増加しました。
  • GL_DEPTH_TESTの代わりにブレンド関数 "(GL_SRC_ALPHA、GL_ONE_MINUS_SRC_ALPHA)"でGL_BLENDを使用すると、約44 fpsになります。
22
Jave

ハードウェアに依存します。 PowerVRハードウェアおよびタイルベースのレンダリングを使用するその他のGPUの場合、discardを使用すると、TBRは描画されたすべてのフラグメントがピクセルになると想定できなくなります。この仮定は、TBRがすべての深さを評価できるようにするため重要です最初次に、最上位のフラグメントのフラグメントシェーダーのみを評価します。ハードウェアを除いて、一種の遅延レンダリングアプローチ。

アルファテストをオンにしても同じ問題が発生することに注意してください。

18
Nicol Bolas

「破棄」は、IMR、TBR、TBDRなどのすべての主流のグラフィックアクセラレーション技術にとって悪いことです。これは、フラグメントの可視性(したがって深度)はフラグメント処理後にのみ決定可能であり、Early-ZまたはPowerVRのHSR(隠面消去)などでは決定できないためです。グラフィックスパイプラインのさらに下にあるものは、除去前に何かが影響を示す傾向があります。パフォーマンス;この場合、フラグメントの処理の増加+他のポリゴンの深度処理の中断=悪影響

破棄を使用する必要がある場合は、それを必要とするトリだけがそれを含むシェーダーでレンダリングされることを確認し、全体的なレンダリングパフォーマンスへの影響を最小限に抑えるために、オブジェクトを不透明、破棄、ブレンドの順序でレンダリングします。

ちなみに、PowerVRハードウェアのみが遅延ステップでの可視性を決定します(したがって、「TBDR」と呼ばれる唯一のGPUです)。他のソリューションはタイルベース(TBR)である可能性がありますが、IMRのように、送信順序に応じてEarlyZ手法を使用しています。 TBRとTBDRはオンチップでブレンディングを行うため(メインメモリに移動するよりも高速で電力消費が少ない)、透明性のためにブレンディングを優先する必要があります。ブレンドされたポリゴンを正しくレンダリングするための通常の手順は、深度の書き込みを無効にし(テストではなく)、トリスを前後の深度の順序でレンダリングすることです(ブレンド操作が順序に依存しない場合を除く)。多くの場合、おおよその並べ替えで十分です。ジオメトリは、完全に透明なフラグメントの広い領域が回避されるようなものでなければなりません。この方法でも、ピクセルごとに複数のフラグメントが処理されますが、HW深度の最適化は、破棄されたフラグメントのように中断されません。

20
gmaclachlan

また、フラグメントシェーダーに「if」ステートメントがあるだけで、一部のハードウェアで大幅な速度低下が発生する可能性があります。 (具体的には、パイプラインが多いGPU、または単一の命令/複数のデータを実行するGPUは、ブランチステートメントから大きなパフォーマンスペナルティが発生します。)したがって、テスト結果は、「if」ステートメントと他の人が言及した効果の組み合わせになる可能性があります。

(価値があるのは、Galaxy Nexusでのテストでは、ランダムな順序でレンダリングしてシェーダーでフラグメントを破棄するのではなく、半透明のオブジェクトを深度ソートして前面にレンダリングするように切り替えたときに、大幅なスピードアップが見られました。)

3
Luke

オブジェクトAはオブジェクトBの前にあります。オブジェクトAには、「discard」を使用するシェーダーがあります。そのため、オブジェクトBのどのセクションがオブジェクトAを通して表示されるかを知る必要があるため、「Early-Z」を適切に実行できません。つまり、オブジェクトAは、ほぼ最後まで処理パイプラインを通過する必要があります。オブジェクトBが実際に表示されているかどうかを判断する前の瞬間(フラグメント処理が実行されるまで)。

これは、HSRと「Early-Z」にとっては悪いことです。隠れている可能性のあるオブジェクトは、処理する前に、深度情報が更新されるのを待って待機する必要があるためです。上で述べたように、それは誰にとっても悪いことです。あるいは、もう少し友好的な方法で、「友達は友達に破棄を使わせない」のです。

1
ShriekBob