ハードウェアアクセラレータのGUIデータはGPUに保持されますか


8

ほとんどのハードウェアアクセラレーションGUIライブラリがどのように機能するかについて、いくつかの調査を行っています。ここでは、実際にはそれらのレンダリングバックエンドのみに関心があります。私は、自分自身をある種のサイドプロジェクトとして書き、書くための最良の方法を理解しようとしています。ここでは、過度に凝った機能ではなく、究極のパフォーマンスを目指しています。プリミティブ、テキスト、アニメーションを描けるようになりたいです。

私が知っているいくつかの優れたライブラリーは、Qt、Skia、およびCairoです(ただし、HWAの状況が何であるかはわかりません)。私はまた、きちんとしたフォローがあるように見える小さなライブラリーであるNanoVGを見ました。私はNanoVGでまともなパフォーマンスを達成することができませんでした...

私を驚かせた唯一のことは、これらのライブラリすべてが「ペイント」の概念を利用しているようであり、各プリミティブ形状が最初から何度も描かれているように見えることです。つまり、APIからは、形状がGPUで「オブジェクト」として作成されたかのように表示されず、用語が何であれ、そこに残されて「自動」でレンダリングされるわけではありません。言い換えると、それらは、いくつかの大きなループで再描画されるためにGPUのメモリに残されません。詳しく説明すると、描画する必要がある各ie長方形に対して、その長方形をレンダリングするためだけにOpenGL状態全体が設定され、その後再び破棄されるようです。これらのレンダリングされた形状は、少なくとも最終的な宛先でレンダリングされているように見えますが、GPUはシーン全体を構成できます。

これらのライブラリが機能することを期待していた方法は、実際にシーン全体をGPUに保存することです(恐ろしい用語を除きます)。たとえば、プリミティブは三角測量されてメモリに残され、その後、複雑なプロセスを使用してシーンのメインレンダリングループが作成されます。さらに、属性を更新したり、プリミティブを削除または追加するためのメカニズムが配置されます。これはかなり漠然とした説明ですが、あなたはアイデアを理解していると思います。

私が今聞きたいのは、「保存」アプローチと比較して「ペイント」アプローチにパフォーマンス上の利点があるかどうかです(ここでも、これらに適切な名前があるかどうかわかりません...)。おそらく、ある種の複雑なキャッシングメカニズムですか?それとも、これで作業する方がはるかに簡単ですか?

「保存」アプローチではGPUでより多くのメモリを使用する可能性がありますが、「ペイント」アプローチに必要なすべてのOpenGL呼び出しはそれほど高価ではありませんか?レンダリングされた形状をキャッシュすることでこれを補正できるかもしれないと思いますが、GPUは、特に通信を考慮して、CPUに比べてこのような一度限りの(またはあまり規則的でない)ラスタライゼーションを実行するときに非常に大きなメリットを提供しますオーバーヘッド?また、この通信のオーバーヘッドは、フレームごとに描画を行わなければならないときに、アニメーションに深刻な問題を引き起こしませんか?

NanoVGに内部キャッシングメカニズムがないことは確かであり、これがかなり劣ったパフォーマンスの原因であると思います。一方、Qtは優れたパフォーマンスを持っているように見えるので、正しく動作しているはずです。グーグルもスキアを上手く利用できるようだ。

PS。私はあらゆる種類の専門家ではなく、つい最近OpenGLを学び始めました。

編集:私が考えたもう1つの可能性は、おそらく「描画」アプローチが純粋にメモリの利点のために必要であると考えられたということですか?私が思うのは、これらのすべてのライブラリはもちろん別の時代に始まったものであり、組み込みプラットフォームもターゲットにしているため、GPUメモリはターゲット(ed)プラットフォームでは不足している可能性があり、使用量は可能な限り少ないためです。パフォーマンスよりも重要です。繰り返しになりますが、このような状況では、通信オーバーヘッドがCPUを上回っていることを考えると、フレームごとのGPUラスタライゼーションがCPUよりも優れているとは確信できません。

さらに、http://blog.qt.io/blog/2010/01/06/qt-graphics-and-performance-opengl/を読んだところ、Qtは実行時にプリペイントされたセグメントのシェーダーコードを実行時に「ペイント」する前にブレンドし、次に、OGLコンパイラーが実行時にコードを適切にインライン化することを期待しています。これは、OGLの初期化オーバーヘッドがさらに増えるように思えます...


2
TL; DR; ここでは害にならない
Kromster

回答:


6

ウィンドウ全体を1つのオブジェクトとしてGPUに保存し(VBOとして保存された四角形の束になります)、それを1つのOpenGL描画呼び出しでレンダリングすると高速になりますが、いくつかの欠点があります。

  • ジオメトリ全体を単一のシェーダーを使用してレンダリングする必要があります。個別のシェーダー(不透明コピー、透明コピー、グラデーションなど)を使用すると、さらに便利です。
  • ジオメトリ全体は、限られた量のテクスチャからのみ使用できます。アトラスを使用する場合でも、GUIには多くのテクスチャが必要です。(GUIテーマのピース、アイコン、フォントなど)
  • 変更するたびに、オブジェクト全体を再構築してGPUにリロードする必要があります。
  • すべてのウィジェットは、2Dペインティングよりも抽象化が難しいジオメトリを作成できなければなりません。
  • 一部のGPUでは、3Dパイプラインを使用するよりも高速な2Dコマンドを使用して、2D要素(色で領域を塗りつぶす、画像から画像にコピーするなど)をレンダリングできます。

それをいくつかのオブジェクトに分割すると、最終的にオブジェクトごとに1つまたはいくつかの長方形ができます。オブジェクトを保存せずにレンダリングする方が簡単で高速です。

GUIフレームワークが行うことは、変更されたウィンドウの正確な部分を追跡し、それらのみを再描画することです。古いイメージはGPUにキャッシュされます。このアプローチは、OpenGL / DirectXアクセラレートレンダリングだけでなく、さまざまな描画バックエンドで使用できます。

OpengGL(または別の3D api)にフィードできるジオメトリを生成するGUIライブラリの例を確認したい場合は、librocketをご覧ください。実際には静的なジオメトリを一緒にベイクして1回の描画呼び出しでレンダリングできますが、頻繁に変化する要素や独自のシェーダーでレンダリングする必要のある要素は、別々にしておく必要があります。


わかりました。前のフレーム全体が画像としてキャッシュされていますか、それともすべての要素がアトラスにキャッシュされていますか?私が質問している理由は、フレームのキャッシュが、たとえば単一の要素の変換をどのようにサポートするのかわからないためです。アトラスを維持することはもちろん多くの努力でしょう。
Gerharddc、2015

通常、ウィンドウのコンテンツ全体がキャッシュされます。一部のGUIフレームワークはいくつかの中間ステージもキャッシュするに違いない。スクロール可能なもののコンテンツが良い候補になるだろう。スクロール可能な領域を除いて、翻訳はGUIの一般的な操作だとは思いません。ほとんどの再描画は小さく、ウィジェットのハウやクリックの変更、テキストの変更などによって発生します。ダイアログやメニューなどは技術的に独立したウィンドウであり、最新のウィンドウコンポジターは再描画せずにそれらを移動します。
michalsrb

それは理にかなっていると思います。それは、ボタンのようなものを予期せず動かしたとしても、ウィンドウ全体を再描画する必要があることを意味しますか?
Gerharddc、2015

それは実際には特定のフレームワークがどのように実装されているかに依存します。ただし、ボタンを移動すると何らかのレイアウトの更新がトリガーされ、ウィンドウ全体の大部分を再描画する必要がある可能性があります。
michalsrb 2015
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.