QtQuick の Scene Graph のレンダラが新しくなります

この記事は Qt Blog に投稿された New Scene Graph Renderer を勝手に翻訳したものです。

ソフトウェアの世界では、SNS 上や、交渉の場での約束時やブログ上などで「次のリリースはさらに素晴らしいものになります!」という言葉をよーく目にしますね。

なので、そういう言い方はやめようと思うのですが…。

Qt 5.2 では Qt Quick のシーングラフのレンダラを刷新します。

3年前にシーングラフの導入を決めた際の私のビジョンの1つは、OpenGL のアドバンテージを最大限に活かし、ゲーム並のパフォーマンスを実現することでした。Qt 5.0 向けに開発したレンダラはゴールへの道のりはまだまだ遠いものでした。透過部分のないコンテンツについては GPU での多重描画を最小限に抑えるため、ステートに応じてソートをし、前面にあるコンテンツから順に描画をするようになっていました。playground/scenegraph というリポジトリでは、似たようなプリミティブをまとめることによって描画回数を減らす(ステートの変更も減る)ようなレンダラを開発していました。

Qt 5.2 のレンダラはこの2つのテクニックを組み合わせ、さらにシーン上で変更のない部分を適切に扱うようにしました。また、playground/scenegraph の customcontext に含まれていたテクスチャアトラスにも対応しました。これによりテクスチャ化されたコンテンツの一括処理の効率があがりました。Qt 5.2 のレンダラは当初のゴールにかなり近いものになったと思います。

好奇心旺盛なみなさんのために、このレンダラの詳細を記したドキュメントも追加しましたが、パフォーマンスのよいアプリケーションを書くためにこれらを理解している必要はありません。とはいえ、多くのみなさんにとって役に立つ記事になっていると思います。

https://doc.qt.io/qt-5/qtquick-visualcanvas-scenegraph-renderer.html

これ以外にも試してみたいアイディアは色々あると思います。もしなにかいい案があれば、IRC 上で “sletta” に ping を送るなり、ソースコードを clone してコーディングをはじめるなりしてください。

それではいくつかのグラフを示しましょう。

以下の3つのベンチマークはこちらにあります: https://github.com/qtproject/playground-scenegraph/tree/master/benchmarks

  • Extreme Table には1つの静的なテーブル上にアニメーションのコンテンツが含まれていて、GPU の状態の維持による効果を表します。
  • List Bench では1列おきに背景色が異なるアイテム上にアイコンと2つのテキストがあるリストを複数同時にスクロールさせています。
  • Flying Icons には 3000 以上のそれぞれアニメーションをする画像が含まれています。

それから、Qt Quick Controls の gallery のサンプルと Samegame の結果も含めることにします。Samegame は Iron Maiden の “Where Eagles Dare” のリズムに合わせて(えぇ、とても科学的に) “Zen” モードで実行しています。

OpenGL の描画の実行回数と転送量は OpenGL の素晴らしいデバッグツールである apitrace を使用して計測しました。緑色の数字が示すとおり、glXxx の実行回数を大幅に減少することができました。これは繰り返しの多いリストやテーブル、グリッドで特に顕著です。

フレーム毎の転送量も大きく改善されました。もっとも効果が大きかったのは “ExtremeTable” と “ListBench” で、デリゲートの生成/破棄がないため、1フレームだけ転送されます。特に “ListFrame” での転送なしのフレームの結果には満足しています。もちろんまったく転送が行われていないわけではなくて、描画の実行自体やいくつかの uniform は転送されていますが、このツールで計測している頂点やテクスチャのデータについてはゼロでした。”FlyingIcons” ではフレーム毎にシーン全体が変化するため結果はほとんど変わりません。”Controls Gallery” はほとんどが静的なのですが、プログレスバーはアニメーションしているためフレーム毎に新しいテクスチャが必要です。これが 20+kb の転送の大半を占めます。”Samegame” の結果が高い理由はパーティクルを多用しているためです。メモリのバスが小さい場合にはパーティクルは控えめにするといいでしょう。

これらは理論上の数字ですが、この新しいレンダラが正しい方向に向かっていることを示しているでしょう。では、ハードウェア上での実行結果を見てみましょう。新しいレンダラの効果が高いところについての比較をしていきます。比較表の完全版はこの記事の一番最後をご覧ください。

ちなみに、これらのベンチマークは V4 ベースではない QML エンジン上で行っています。レンダラの変更の効果を見る際に、V4 化の影響を受けないようにしたかったからです。

描画時間は vsync を有効にして計測していますが、スワップは除いています。このため、MacBook では 16ms で描画していますが、実際には OpenGL コマンドを発行している間は抑制されています。これを Mac OS X の Instruments で見てみると、ドライバが多くの時間を同期待ちに割いていることが分かりました。パイプライン内でストールしているとも言えます。Qt 5.2 の描画では、この描画時の同期待ちはなくなりました。リスト(やリストのようなコンテンツ)は一般的な UI なので、これはとてもいいことです。

チップセットの GPU を使っている MacBook と Nexus で、OpenGL のコマンド発行時間が劇的に削減されています。また、”ExtremeTable” の描画時間が 0 にならないのは https://bugreports.qt.io/browse/QTBUG-32997 だけが原因だということも述べておきます。

“FlyingIcons” の CPU 使用量が多い原因のほとんどは 3000 以上のアニメーションを並列で実行しているためですが、レンダラが消費している時間については大幅に改善がなされました。

それでは最後にすべてのベンチマークの結果を示します。

この結果は最初の方の理論値ととても良くマッチしています。リストやグリッドのような繰り返しのコンテンツについては、Qt 5.2 は Qt 5.1 に比べて大幅な改善がなされました。これら以外の根本的な改善をしなかったケースにおいても、少なくとも改悪はなされていません。

というわけで Qt 5.2 をお楽しみに!

おすすめ