Qt Quick シーングラフ・デフォルト・レンダラ

このドキュメントでは、デフォルトのシーングラフ・レンダラが内部的にどのように動作するかを説明します。

良いパフォーマンスを得るためにレンダラーの内部を理解する必要はありません。しかし、シーングラフと統合するときや、グラフィックチップから最大限の効率を引き出せない理由を解明するときには役立つかもしれない。

注意: すべてのフレームが一意であり、すべてをゼロからアップロードする場合でも、デフォルトのレンダラーは良好なパフォーマンスを発揮します。

QML シーン内の Qt Quick アイテムは、QSGNode インスタンスのツリーを生成します。一度作成されたこのツリーは、あるフレームがどのようにレンダリングされるべきかを完全に記述したものです。このツリーには Qt Quick アイテムへの参照は一切含まれておらず、ほとんどのプラットフォームでは別のスレッドで処理され、レンダリングされます。レンダラーはシーングラフの自己完結した部分で、QSGNode ツリーをトラバースし、QSGGeometryNode で定義されたジオメトリと、QSGMaterial で定義されたシェーダの状態を使用して、グラフィックスの状態を更新し、描画コールを生成します。

必要に応じて、内部シーングラフバックエンドAPIを使用して、レンダラーを完全に置き換えることができる。これは主に、非標準のハードウェア機能を利用したいプラットフォーム・ベンダーにとって興味深い。大半のユースケースでは、デフォルトのレンダラーで十分です。

デフォルトのレンダラーは、レンダリングを最適化するために2つの主要な戦略に重点を置いている:描画呼び出しのバッチ処理と、GPU でのジオメトリの保持です。

バッチ処理

QPainter や Cairo、Context2D などの従来の 2D API は、フレームごとに何千もの個別の描画コールを処理するように記述されていますが、OpenGL やその他のハードウェアアクセラレーション API は、描画コールの数が非常に少なく、状態の変更が最小限に抑えられている場合に、最高のパフォーマンスを発揮します。

注: OpenGL は以下のセクションで例として使用されていますが、同じ概念は他のグラフィックス API にも当てはまります。

次のユースケースを考えてみよう:

このリストを描画する最も単純な方法はセル単位である。まず、背景が描画される。これは特定の色の矩形である。OpenGLの用語では、これはベタ塗りを行うシェーダープログラムを選択し、塗りつぶしの色を設定し、xとyのオフセットを含む変換行列を設定し、例えばglDrawArrays 、矩形を構成する2つの三角形を描画することを意味します。次にアイコンが描画される。OpenGLの用語では、これはテクスチャを描画するシェーダープログラムを選択し、使用するアクティブなテクスチャを選択し、変換行列を設定し、アルファブレンディングを有効にし、そして例えばglDrawArrays 、アイコンの外接矩形を構成する2つの三角形を描画することを意味します。セル間のテキストと区切り線も同様のパターンに従う。このプロセスはリスト内のすべてのセルに対して繰り返されるため、リストが長くなると、OpenGLの状態変更や描画呼び出しによって発生するオーバーヘッドは、ハードウェアアクセラレーションAPIを使用することで得られるメリットを完全に上回ります。

各プリミティブが大きい場合、このオーバーヘッドは無視できますが、典型的なUIの場合、小さなアイテムがたくさんあるので、かなりのオーバーヘッドになります。

デフォルトのシーングラフ・レンダラーは、この制限の中で動作し、まったく同じ視覚的結果を維持しながら、個々のプリミティブをバッチにマージしようとします。その結果、OpenGLの状態変化が少なくなり、描画呼び出しが最小限に抑えられるため、パフォーマンスが最適化されます。

不透明プリミティブ

レンダラーは、不透明プリミティブとアルファブレンディングを必要とするプリミティブを区別します。OpenGLのZバッファを使用し、各プリミティブに固有のZ位置を与えることで、レンダラーは、画面上の位置や他のどの要素と重なるかを考慮せずに、不透明プリミティブを自由に並べ替えることができます。各プリミティブのマテリアルの状態を見ることで、レンダラーは不透明なバッチを作成します。Qt Quick のコア アイテム セットには、不透明な色を持つ Rectangle アイテムと、JPEG や BMP などの完全に不透明なイメージが含まれています。

不透明のプリミティブを使用するもう一つの利点は、不透明のプリミティブはGL_BLEND を有効にする必要がないことです。

不透明プリミティブは、glDepthMaskGL_DEPTH_TEST を有効にして、フロントツーバック方式でレンダリングされます。内部的に early-z チェックを行う GPU では、これは、不明瞭なピクセルやピクセルのブロッ クに対してフラグメントシェーダを実行する必要がないことを意味します。レンダラはまだこれらのノードを考慮する必要があり、バーテックスシェーダはまだこれらのプリミティブのすべての頂点に対して実行されるので、アプリケーションが何かが完全に隠されていることを知っている場合は、Item::visible またはItem::opacity を使用して明示的に非表示にするのが最善の方法です。

注: Item::z は、Item の兄弟に対する積み重ね順序を制御するために使用されます。レンダラーやOpenGLのZバッファとは直接関係ありません。

アルファブレンドされたプリミティブ

不透明プリミティブが描画されると、レンダラーはglDepthMask を無効にし、GL_BLEND を有効にして、すべてのアルファブレンド プリミティブをバックツーフロント方式でレンダリングします。

アルファブレンドされたプリミティブをバッチ処理すると、アルファブレンドが正しく見えるように、重なり合っている要素を正しい順序でレンダリングする必要があるため、レンダラーに少し手間がかかります。Zバッファだけでは不十分です。レンダラーは、アルファブレンドされたすべてのプリミティブに対してパスを行い、マテリアルの状態に加えてバウンディング矩形を見て、どの要素をバッチ処理できて、どの要素をバッチ処理できないかを判断します。

一番左のケースでは、青い背景は1回の呼び出しで描画でき、2つのテキスト要素は別の呼び出しで描画できます。一番右のケースでは、「アイテム4」の背景が「アイテム3」のテキストに重なっているので、この場合は背景とテキストをそれぞれ別の呼び出しで描画する必要がある。

Z方向では、アルファプリミティブは不透明ノードとインターリーブされ、利用可能な場合はearly-zをトリガーすることがありますが、Item::visible をfalseに設定すると常に高速になります。

3Dプリミティブとの混合

シーングラフは、擬似3Dと適切な3Dプリミティブをサポートすることができます。たとえば、ShaderEffect を使って「ページカール」エフェクトを実装したり、QSGGeometry とカスタムマテリアルを使ってバンプマップされたトーラスを実装したりできます。その際、デフォルトのレンダラーがすでに深度バッファを使用していることを考慮する必要があります。

レンダラは、QSGMaterialShader::vertexShader() から返された頂点シェーダを修正し、モデルビューと投影行列が適用された後に頂点の z 値を圧縮し、z に小さな平行移動を追加して正しい z 位置に配置します。

圧縮は、z値が0から1の範囲にあると仮定します。

テクスチャアトラス

アクティブなテクスチャは一意のOpenGL状態です。これは、異なるOpenGLテクスチャを使用する複数のプリミティブをバッチ処理できないことを意味します。このため、Qt Quick シーングラフでは、複数のQSGTexture インスタンスをより大きなテクスチャの小さなサブ領域として割り当てることができます。

テクスチャアトラスの最大の利点は、複数のQSGTexture インスタンスが同じ OpenGL テクスチャインスタンスを参照することです。これにより、Image アイテム、BorderImage アイテム、ShaderEffect アイテム、またテクスチャを使用するQSGSimpleTextureNode やカスタム QSGGeometryNodes などの C++ タイプなど、テクスチャを使用した描画呼び出しもバッチ処理できるようになります。

注意: 大きなテクスチャはテクスチャアトラスには入りません。

アトラスベースのテクスチャは、QQuickWindow::TextureCanUseAtlasQQuickWindow::createTextureFromImage() に渡すことで作成されます。

注: アトラスベースのテクスチャは、0 から 1 までのテクスチャ座標を持ちません。アトラステクスチャ座標を取得するにはQSGTexture::normalizedTextureSubRect() を使用してください。

シーングラフはヒューリスティックを使って、アトラスのサイズと、アトラスに入るためのサイズのしきい値を決定します。異なる値が必要な場合は、環境変数QSG_ATLAS_WIDTH=[width],QSG_ATLAS_HEIGHT=[height],QSG_ATLAS_SIZE_LIMIT=[size] を使って上書きすることが可能です。これらの値を変更することは、ほとんどの場合、プラットフォーム・ベンダーにとって興味深いことだろう。

バッチルーツ

互換性のあるプリミティブをバッチにマージするだけでなく、デフォルトのレン ダラは、フレームごとに GPU に送信する必要のあるデータ量を最小限に抑え ようとします。デフォルトのレンダラーは、一緒に属するサブツリーを識別し、これらを別々のバ ッチに入れようとします。バッチが識別されると、それらはマージされ、アップロードさ れ、頂点バッファオブジェクトを使って GPU メモリに保存されます。

トランスフォームノード

各 Qt Quick Item は、x、y、スケール、または回転を管理するために、QSGTransformNode をシーングラフ ツリーに挿入します。子アイテムは、このトランスフォーム ノードの下に配置されます。デフォルトのレンダラーは、フレーム間のトランスフォームノードの状態を追跡し、サブツリーを見て、トランスフォームノードが一連のバッチのルートになる良い候補かどうかを判断します。フレーム間で変化し、かなり複雑なサブツリーを持つトランスフォーム ノードは、バッチ ルートになる可能性があります。

バッチルートのサブツリー内の QSGGeometryNodes は、CPU 上でルートに対して事前変換されます。その後、GPU にアップロードされ、保持されます。変換が変更されると、レンダラーが更新する必要があるのはルートの行列だけで、個々のアイテムは更新されないため、リストとグリッドのスクロールが非常に高速になります。連続するフレームでは、ノードが追加または削除されない限り、リストのレンダリングは実質的に無料です。新しいコンテンツがサブツリーに入ると、それを取得するバッチが再構築されるが、それでも比較的高速である。グリッドやリストをパンする場合、ノードが追加または削除されるフレームごとに、変更されないフレームがいくつかあるのが普通です。

トランスフォーム ノードをバッチ ルートとして識別するもう 1 つの利点は、レンダラーがツリーの変更されていない部分を保持できることです。たとえば、UI がリストとボタン行で構成されているとします。リストがスクロールされ、デリゲートが追加および削除され ても、UI の残りの部分であるボタン行は変更されず、GPU にすでに保存されているジオメトリを使用して描画できます。

変換ノードがバッチルートになるためのノードと頂点のしきい値は、環境変数QSG_RENDERER_BATCH_NODE_THRESHOLD=[count]QSG_RENDERER_BATCH_VERTEX_THRESHOLD=[count] を使ってオーバーライドできます。これらのフラグをオーバーライドすることは、主にプラット フォーム・ベンダーにとって有用です。

注意: バッチルート以下では、マテリアルステートとジオメトリタイプの固有セットごとに 1 つのバッチが作成されます。

クリッピング

Item::clip を true に設定すると、ジオメトリに矩形を含むQSGClipNode が作成されます。デフォルトのレンダラーは、OpenGL のシザリングを使用してこのクリップを適用します。アイテムが 90 度以外の角度で回転する場合は、OpenGL のステンシル バッファが使用されます。Qt Quick Item は、QML では矩形をクリップとして設定することしかサポートしていませんが、シーングラフ API とデフォルトのレンダラーでは、どのような形状でもクリップに使用できます。

サブツリーにクリップを適用する場合、そのサブツリーは固有の OpenGL ステートでレンダリングされる必要があります。つまり、Item::clip が true の場合、そのアイテムのバッチ処理はその子に限定されます。ListViewGridView のように子アイテムが多い場合や、TextArea のように複雑な子アイテムがある場合は問題ありません。しかし、より小さな項目でclipを使うと、バッチ処理ができなくなるので、注意が必要です。これには、ボタンラベル、テキストフィールド、リストデリゲート、テーブルセルが含まれます。Flickable(またはアイテムビュー)のクリップは、不透明なアイテムがFlickableの周囲を覆うようにUIを配置し、それ以外はウィンドウの端に頼ってクリップすることで、多くの場合回避できます。

Item::cliptrue に設定すると、QQuickItem::ItemIsViewport フラグも設定されます。QQuickItem::ItemObservesViewport フラグを持つ子アイテムは、大まかなプリクリッピングのステップにビューポートを使用することがあります: たとえば、Text は、ビューポートの完全に外側にあるテキストの行を省略します。シーングラフノードの省略やvertices の制限は最適化であり、QMLでItem::clip を設定するのではなく、C++でflags を設定することで実現できます。

カスタムアイテムでQQuickItem::updatePaintNode ()を実装する場合、大きなジオメトリ領域で多くの詳細をレンダリングできるのであれば、グラフィックをビューポートに限定することが効率的かどうかを考える必要があります。そうであれば、ItemObservesViewport フラグを設定し、QQuickItem::clipRect ()から現在露出している領域を読み込むことができます。その結果、updatePaintNode()が頻繁に呼び出されるようになります(通常、コンテンツがビューポート内で移動するときは、1フレームにつき1回)。

頂点バッファ

各バッチは頂点バッファオブジェクト(VBO)を使って GPU にデータを保存 します。この頂点バッ ファはフレーム間で保持され、シーングラフの一部が変更されると更新されま す。

デフォルトでは、レンダラーはGL_STATIC_DRAW を使用してデータを VBO にアップロードします。環境変数QSG_RENDERER_BUFFER_STRATEGY=[strategy] を設定することで、異なるアップロード戦略を選択することができます。有効な値はstreamdynamic です。この値を変更することは、主にプラットフォームベンダーにとって有用である。

アンチエイリアス

シーングラフは2種類のアンチエイリアシングをサポートしています。デフォルトでは、矩形や画像のようなプリミティブは、プリミティブのエッジに沿って頂点を追加することで、エッジが透明になるようにアンチエイリアスされます。私たちはこの方法を頂点アンチエイリアシングと呼んでいます。ユーザーがマルチサンプルOpenGLコンテキストを要求する場合、QQuickWindow::setFormat ()を使用して、0 より大きいサンプルでQSurfaceFormat を設定することにより、シーングラフはマルチサンプルベース・アンチエイリアス(MSAA)を優先します。この2つの技法は、レンダリングが内部的にどのように行われるかに影響し、異なる制限があります。

また、環境変数QSG_ANTIALIASING_METHODvertex またはmsaa に設定することで、使用するアンチエイリアシング手法を上書きすることも可能です。

頂点アンチエイリアシングは、2つのエッジが数学的に同じであっても、隣接するプリミティブのエッジ間に継ぎ目を生じさせます。マルチサンプル・アンチエイリアシングでは発生しません。

頂点アンチエイリアス

頂点アンチエイリアシングは、Item::antialiasing プロパティを使用して、アイテムごとに有効/無効にできます。これは、基礎となるハードウェアが何をサポートしているかに関係なく動作し、通常のレンダリングプリミティブと、例えばShaderEffectSource タイプを使用してフレームバッファオブジェクトにキャプチャされたプリミティブの両方に対して、より高品質なアンチエイリアシングを生成します。

頂点アンチエイリアシングを使用することの欠点は、アンチエイリアシングを有効にした各プリミティブをブレンドしなければならないことです。バッチ処理に関しては、これはプリミティブをバッチ処理できるかどうかを判断するためにレンダラーがより多くの作業を行う必要があることを意味し、シーン内の他の要素とのオーバーラップにより、バッチ処理が少なくなり、パフォーマンスに影響する可能性があります。

ローエンドのハードウェアでは、ブレンディングもかなり高価になる可能性があります。そのため、画面の大部分をカバーする画像や丸みを帯びた長方形の場合、これらのプリミティブの内部に必要なブレンディングの量は、プリミティブ全体をブレンドする必要があるため、大幅なパフォーマンスの低下を招く可能性があります。

マルチサンプル・アンチエイリアス

マルチサンプル・アンチエイリアシングは、ハードウェアがプリミティブのピクセルごとにカバレッジ値を計算するハードウェア機能です。ハードウェアによっては、非常に低コストでマルチサンプルできるものもあれば、フレームをレンダリングするために、より多くのメモリとより多くのGPUサイクルの両方を必要とするハードウェアもあります。

マルチサンプルアンチエイリアシングを使用すると、丸みを帯びた長方形や画像要素などの多くのプリミティブは、アンチエイリアスを適用しても、シーングラフでは不透明であることができます。これは、レンダラーがバッチを作成するときに仕事がしやすくなり、過剰描画を避けるためにearly-zに頼ることができることを意味します。

マルチサンプル・アンチエイリアスが使用される場合、フレームバッファオブジェクトにレンダリングされるコンテンツは、フレームバッファのマルチサンプリングをサポートするための追加拡張が必要です。通常、GL_EXT_framebuffer_multisampleGL_EXT_framebuffer_blit 。ほとんどのデスクトップチップにはこれらの拡張がありますが、組み込みチップではあまり一般的ではありません。フレームバッファのマルチサンプリングがハードウェアで利用できない場合、フレームバッファオブジェクトにレンダリングされたコンテンツは、ShaderEffectSource のコンテンツも含めて、アンチエイリアスがかかりません。

パフォーマンス

冒頭で述べたように、良いパフォーマンスを得るためにレンダラーの細かい詳細を理解する必要はありません。これは、一般的なユースケースに最適化するように書かれており、ほとんどどのような状況下でも非常に優れたパフォーマンスを発揮します。

  • 良好なパフォーマンスは、ジオメトリをできるだけ少なくして何度もアップロードする、効果的なバッチ処理から生まれます。環境変数QSG_RENDERER_DEBUG=render を設定することで、レンダラはバッチングがどの程度うまくいったか、いくつのバッチが使用されたか、どのバッチが保持され、どれが不透明でどれが不透明でないかなどの統計を出力します。最適なパフォーマンスを追求する場合、アップロードは本当に必要なときだけ行うべきで、バッチは10未満にし、少なくとも3~4は不透明にすべきである。
  • デフォルトのレンダラーは、CPU側のビューポートクリッピングもオクルージョン検出も行いません。表示されるべきでないものは、表示されるべきではない。描画されるべきでないアイテムには、Item::visible: false 。このようなロジックを追加しない主な理由は、追加コストがかかるため、うまく動作するように気を配っているアプリケーションにも支障が出るからです。
  • テクスチャアトラスが使用されていることを確認してください。ImageとBorderImage の項目は、画像が大きすぎない限り、それを使用します。C++ で作成されたテクスチャの場合、QQuickWindow::createTexture() を呼び出すときにQQuickWindow::TextureCanUseAtlas を渡します。環境変数QSG_ATLAS_OVERLAY を設定することで、すべてのアトラステクスチャがカラー化され、アプリケーション内で簡単に識別できるようになります。
  • 可能な限り不透明なプリミティブを使用してください。不透明プリミティブはレンダラーでの処理が速く、GPU での描画が速くなります。たとえば、PNGファイルは、各ピクセルが完全に不透明であっても、アルファチャンネルを持つことがよくあります。JPG ファイルは常に不透明です。QQuickImageProvider に画像を提供するときや、QQuickWindow::createTextureFromImage() で画像を作成するときは、可能な限り画像にQImage::Format_RGB32 を持たせてください。
  • 上図のような重なり合った複合アイテムは、バッ チできませんので注意してください。
  • クリッピングはバッチングを壊します。項目ごと、表セル内、項目デリゲートなどでは決して使わないでください。テキストをクリッピングする代わりに、エライディングを使う。画像をクリッピングする代わりに、切り取った画像を返すQQuickImageProvider を作成する。
  • バッチ処理は 16 ビット・インデックスに対してのみ機能します。すべての組み込みアイテムは 16 ビット インデックスを使用しますが、カスタム ジオメトリは自由に 32 ビット インデックスを使用できます。
  • いくつかのマテリアルフラグはバッチングを妨げますが、最も制限的なものはQSGMaterial::RequiresFullMatrix で、これはすべてのバッチングを妨げます。
  • モノクロの背景を持つアプリケーションでは、トップレベルの Rectangle アイテムを使用するのではなく、QQuickWindow::setColor() を使用して設定する必要があります。QQuickWindow::setColor() はglClear() への呼び出しで使用され、より高速になる可能性があります。
  • Mipmapped Imageアイテムはグローバルアトラスに配置されず、バッチされません。
  • フレームバッファオブジェクト(FBO)のリードバックに関連する OpenGL ドライバのバグにより、レンダリングされたグリフが破損する可能性があります。QML_USE_GLYPHCACHE_WORKAROUND 環境変数を設定すると、Qt はグリフの追加コピーを RAM に保持します。これは、以前に描画されていないグリフを描画するとき、Qt が CPU 経由で追加のコピーにアクセスするため、パフォーマンスがわずかに低下することを意味します。また、グリフキャッシュが 2 倍のメモリを使うことになります。品質はこの影響を受けません。

アプリケーションのパフォーマンスが悪い場合は、レンダリングがボトルネックになっていることを確認してください。プロファイラを使ってください!環境変数QSG_RENDER_TIMING=1 は多くの有用なタイミングパラメータを出力し、問題がどこにあるかを突き止めるのに役立ちます。

視覚化

シーングラフのデフォルトレンダラーの様々な側面を視覚化するために、QSG_VISUALIZE 環境変数を、以下の各セクションで詳述する値のいずれかに設定することができます。以下のQMLコードを使用して、いくつかの変数の出力例を示します:

import QtQuick 2.2

Rectangle {
    width: 200
    height: 140

    ListView {
        id: clippedList
        x: 20
        y: 20
        width: 70
        height: 100
        clip: true
        model: ["Item A", "Item B", "Item C", "Item D"]

        delegate: Rectangle {
            color: "lightblue"
            width: parent.width
            height: 25

            Text {
                text: modelData
                anchors.fill: parent
                horizontalAlignment: Text.AlignHCenter
                verticalAlignment: Text.AlignVCenter
            }
        }
    }

    ListView {
        id: clippedDelegateList
        x: clippedList.x + clippedList.width + 20
        y: 20
        width: 70
        height: 100
        clip: true
        model: ["Item A", "Item B", "Item C", "Item D"]

        delegate: Rectangle {
            color: "lightblue"
            width: parent.width
            height: 25
            clip: true

            Text {
                text: modelData
                anchors.fill: parent
                horizontalAlignment: Text.AlignHCenter
                verticalAlignment: Text.AlignVCenter
            }
        }
    }
}

左のListView では、clip プロパティをtrue に設定します。また、右側のListView については、クリッピングがバッチングに与える影響 を説明するために、各デリゲートのclip プロパティをtrue に設定しています。

"Original"

オリジナル

注: 視覚化された要素はクリッピングを考慮せず、レンダリングの順序は任意です。

バッチの視覚化

QSG_VISUALIZEbatches に設定すると、レンダラーでバッチが視覚化されます。マージされたバッチはソリッドカラーで描画され、マージされていないバッチは斜めのラインパターンで描画されます。固有の色が少ないということは、良いバッチであることを意味します。マージされていないバッチは、個々のノードを多く含んでいるとよくありません。

"batches"

QSG_VISUALIZE=batches

クリッピングの視覚化

QSG_VISUALIZEclip に設定すると、シーンの上にクリッピングを示す赤い領域が描画されます。Qt Quick Items はデフォルトではクリッピングしないので、通常はクリッピングは表示されません。

QSG_VISUALIZE=clip

変更の視覚化

QSG_VISUALIZE からchanges を設定すると、レンダラーの変更が視覚化されます。シーングラフの変更は、ランダムな色の点滅オーバーレイで視覚化されます。プリミティブ上の変更はベタ塗りで視覚化され、マトリックスや不透明度の変更などの祖先の変更はパターンで視覚化されます。

オーバードローの視覚化

QSG_VISUALIZEoverdraw に設定すると、レンダラーでオーバードローが視覚化されます。3D のすべてのアイテムを視覚化して、オーバー ドローを強調表示します。このモードは、ビューポートの外にあるジオメトリをある程度検出するためにも使用できます。不透明なアイテムは緑の色合いでレンダリングされ、半透明のアイテムは赤の色合いでレンダリングされます。ビューポートのバウンディングボックスは青でレンダリングされます。不透明なコンテンツは、シーングラフが処理しやすく、通常、レンダリングが速くなります。

上のコードのルート矩形は、ウィンドウも白いので余計であり、この場合、矩形の描画はリソースの無駄であることに注意してください。この矩形をアイテムに変更すると、パフォーマンスが少し向上します。

"overdraw-1"

"overdraw-2"

QSG_VISUALIZE=overdraw

Qt レンダリングハードウェアインタフェースによるレンダリング

Qt 6.0 以降では、デフォルトのアダプテーションは常にQt GUIモジュールによって提供されるグラフィックスの抽象化レイヤ、Qt Rendering Hardware Interface (RHI) を介してレンダリングされます。つまり、Qt 5とは異なり、シーングラフが直接OpenGLを呼び出すことはありません。むしろ、RHI APIを使用してリソースと描画コマンドを記録し、RHI APIがコマンドストリームをOpenGL、Vulkan、Metal、またはDirect 3Dの呼び出しに変換します。シェーダー処理も、シェーダーコードを一度書いてからSPIR-Vにコンパイルし、さまざまなグラフィックスAPIに適した言語に変換することで統一されています。

動作を制御するために、以下の環境変数を使用することができる:

環境変数可能な値説明
QSG_RHI_BACKENDvulkan metal, , 、opengl d3d11 d3d12特定のRHIバックエンドを要求する。デフォルトでは、この変数または同等のC++ APIによって上書きされない限り、ターゲットとなるグラフィックスAPIがプラットフォームに基づいて選択されます。現在のデフォルトは、WindowsではDirect3D 11、macOSではMetal、それ以外ではOpenGLです。
QSG_INFO1OpenGL ベースのレンダリングパスと同様に、これを設定すると、Qt Quick のシーングラフを初期化するときにシステム情報が表示されます。これはトラブルシューティングに非常に役立ちます。
QSG_RHI_DEBUG_LAYER1該当する場合(Vulkan、Direct3D)、グラフィックス API 実装のデバッグまたは検証レイヤーを有効にします。macOS上のMetalの場合は、代わりに環境変数METAL_DEVICE_WRAPPER_TYPE=1
QSG_RHI_PREFER_SOFTWARE_RENDERER1ソフトウェアベースのラスタライズを使用するアダプタまたは物理デバイスの選択を要求します。基礎となる API にアダプタを列挙するサポートがある場合にのみ適用され (たとえば Direct3D や Vulkan)、それ以外の場合は無視されます。

常に単一のグラフィックスAPIで実行したいアプリケーションは、C++でもこれを要求できます。たとえば、main() の初期に、QQuickWindow を構築する前に、以下の呼び出しを行うと、Vulkan の使用が強制されます(そうでない場合は失敗します):

QQuickWindow::setGraphicsApi(QSGRendererInterface::Vulkan);

QSGRendererInterface::GraphicsApi を参照してください。列挙値OpenGL,Vulkan,Metal,Direct3D11,Direct3D12 は、QSG_RHI_BACKEND を同等の文字列キーに設定して実行するのと実質的に同等です。

すべてのQRhi バックエンドは、QSG_RHI_PREFER_SOFTWARE_RENDERERQT_D3D_ADAPTER_INDEXQT_VK_PHYSICAL_DEVICE_INDEX のようなバックエンド固有の変数で上書きされない限り、システムデフォルトの GPU アダプタや物理デバイスを選択します。

Qt 6.5 から、以前は環境変数としてのみ公開されていた設定の一部が、QQuickGraphicsConfiguration の C++ API として利用できるようになりました。例えば、QSG_RHI_DEBUG_LAYER を設定することと、setDebugLayer(true) を呼び出すことは等価です。

本書に含まれる文書の著作権は、それぞれの所有者に帰属します。 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。