Qt Quick シーングラフのデフォルトレンダラー
このドキュメントでは、デフォルトのシーングラフ・レンダラーが内部でどのように動作するかを解説し、パフォーマンスと機能の両面で、これを最適に活用するコードを記述できるようにすることを目的としています。
優れたパフォーマンスを得るために、レンダラーの内部構造を理解する必要はありません。しかし、シーングラフとの統合を行う際や、グラフィックスチップの効率を最大限に引き出せない理由を突き止める際には、理解が役立つ場合があります。
注: すべてのフレームがユニークで、すべてがゼロから読み込まれる場合でも、 デフォルトのレンダラーは良好なパフォーマンスを発揮します。
QMLシーン内のQt Quick アイテムは、QSGNode インスタンスのツリーを構成します。一度作成されると、このツリーは特定のフレームがどのようにレンダリングされるべきかを完全に記述したものとなります。このツリーには、Qt Quick アイテムへの参照は一切含まれておらず、ほとんどのプラットフォームでは別のスレッドで処理およびレンダリングされます。 レンダラーはシーングラフの独立した構成要素であり、QSGNode ツリーを走査し、QSGGeometryNode で定義されたジオメトリと、QSGMaterial で定義されたシェーダー状態を使用して、グラフィックス状態を更新し、描画呼び出しを生成します。
必要に応じて、内部シーングラフバックエンドAPIを使用してレンダラーを完全に置き換えることができます。これは主に、非標準のハードウェア機能を活用したいプラットフォームベンダーにとって有益です。ほとんどのユースケースでは、デフォルトのレンダラーで十分です。
デフォルトのレンダラーは、レンダリングを最適化するために、主に2つの戦略に重点を置いています。それは、ドローコールのバッチ処理と、GPU上でのジオメトリの保持です。
バッチ処理
QPainter 、Cairo、Context2D などの従来の 2D API は、1 フレームあたり数千もの個別のドローコールを処理するように設計されていますが、OpenGL やその他のハードウェアアクセラレーション対応 API は、ドローコールの数が非常に少なく、状態の変化が最小限に抑えられている場合に最高のパフォーマンスを発揮します。
注: 以下のセクションではOpenGL を例として使用していますが 、同じ概念は他のグラフィックス API にも当てはまります。
次のユースケースを考えてみましょう。

このリストを描画する最も単純な方法は、セルごとに処理することです。まず、背景が描画されます。これは特定の色の長方形です。 OpenGLの用語で言えば、これは単色塗りつぶしを行うシェーダープログラムを選択し、塗りつぶし色を設定し、xおよびyのオフセットを含む変換行列を設定し、その後、例えばglDrawArrays を使用して、長方形を構成する2つの三角形を描画することを意味します。次に、アイコンが描画されます。 OpenGLの用語で言えば、これはテクスチャを描画するためのシェーダープログラムを選択し、使用するアクティブなテクスチャを選択し、変換行列を設定し、アルファブレンディングを有効にした上で、例えば `glDrawArrays ` を使用して、アイコンの境界矩形を構成する2つの三角形を描画することを意味します。 テキストやセル間の区切り線も同様のパターンに従います。そして、この処理はリスト内のすべてのセルに対して繰り返されるため、リストが長くなるほど、OpenGLの状態変更や描画呼び出しによって生じるオーバーヘッドが、ハードウェアアクセラレーション対応APIを使用することによるメリットを完全に上回ってしまいます。
個々のプリミティブが大きい場合は、このオーバーヘッドは無視できる程度ですが、一般的なUIの場合、多くの小さな要素が存在するため、それらが積み重なってかなりのオーバーヘッドとなります。
デフォルトのシーングラフ・レンダラーは、これらの制限の範囲内で動作し、視覚的な結果を完全に維持しながら、個々のプリミティブをバッチに統合しようとします。その結果、OpenGLの状態変更が少なくなり、描画呼び出しも最小限に抑えられるため、最適なパフォーマンスが得られます。
不透明プリミティブ
レンダラーは、不透明プリミティブとアルファブレンディングを必要とするプリミティブを区別します。OpenGLのZバッファを使用し、各プリミティブに固有のZ座標を割り当てることで、レンダラーは画面上の位置や、どの要素と重なっているかを一切考慮することなく、不透明プリミティブの順序を自由に並べ替えることができます。 各プリミティブのマテリアル状態を参照することで、レンダラーは不透明なバッチを作成します。Qt Quick のコアアイテムセットでは、これには不透明な色の矩形アイテムや、JPEGやBMPなどの完全に不透明な画像が含まれます。
不透明プリミティブを使用するもう 1 つの利点は、不透明プリミティブでは「GL_BLEND 」を有効にする必要がないことです。この機能の有効化は、特にモバイルや組み込み GPU において、かなりの負荷がかかる場合があります。
不透明プリミティブは、glDepthMask およびGL_DEPTH_TEST が有効な状態で、手前から奥へ向かってレンダリングされます。内部で早期Zチェックを行うGPUでは、これにより、隠れているピクセルやピクセルブロックに対してフラグメントシェーダーを実行する必要がなくなります。 ただし、レンダラーは依然としてこれらのノードを考慮する必要があり、これらのプリミティブ内のすべての頂点に対して頂点シェーダーが実行されることに注意してください。したがって、アプリケーション側で何かが完全に隠れていることが分かっている場合は、Item::visible またはItem::opacity を使用して明示的に非表示にすることが最善の策です。
注: Item::z は 、アイテムの兄弟要素に対する重ね合わせ順序を制御するために使用されます。これは、レンダラーやOpenGLのZバッファとは直接的な関係はありません。
アルファブレンディングされたプリミティブ
不透明なプリミティブの描画が完了すると、レンダラーは `glDepthMask` を無効にし、`GL_BLEND ` を有効にして、すべてのアルファブレンディングされたプリミティブを「後ろから前に」の順序でレンダリングします。
アルファブレンディングされたプリミティブのバッチ処理には、レンダラー側で少し手間がかかります。これは、アルファブレンディングを正しく表示するためには、重なり合う要素を正しい順序でレンダリングする必要があるためです。Zバッファのみに依存するだけでは不十分です。 レンダラーは、すべてのアルファブレンディングされたプリミティブを順に処理し、マテリアル状態に加えてバウンディング矩形を確認することで、どの要素をバッチ処理でき、どの要素ができないかを判断します。

一番左のケースでは、テキストは前面に配置された背景としか重なっていないため、青い背景は1回の呼び出しで描画でき、2つのテキスト要素は別の呼び出しで描画できます。 右端のケースでは、「Item 4」の背景が「Item 3」のテキストと重なっているため、この場合は背景とテキストをそれぞれ別々の呼び出しで描画する必要があります。
Z 軸に関しては、アルファプリミティブは不透明なノードとインターリーブされており、利用可能な場合はアーリー 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::createTextureFromImage()` に `QQuickWindow::TextureCanUseAtlas ` を渡すことで作成されます。
注:アトラスベースの テクスチャには、0 から 1 までの範囲のテクスチャ座標はありません。アトラスのテクスチャ座標を取得するには、QSGTexture::normalizedTextureSubRect() を使用してください。
シーングラフは、アトラスの適切なサイズや、アトラスに組み込まれるためのサイズ閾値を決定するためにヒューリスティックを使用します。異なる値が必要な場合は、環境変数QSG_ATLAS_WIDTH=[width] 、QSG_ATLAS_HEIGHT=[height] 、およびQSG_ATLAS_SIZE_LIMIT=[size] を使用して上書きすることができます。これらの値を変更することは、主にプラットフォームベンダーにとって有益です。
バッチのルート
互換性のあるプリミティブをバッチに統合することに加え、デフォルトのレンダラーは、各フレームごとに GPU に送信する必要のあるデータ量を最小限に抑えるよう努めます。 デフォルトのレンダラーは、関連性のあるサブツリーを特定し、それらを別々のバッチにまとめようとします。バッチが特定されると、それらは統合され、アップロードされ、頂点バッファオブジェクト(VBO)を使用してGPUメモリに格納されます。
トランスフォームノード
各Qt Quick アイテムは、そのx、y、スケール、または回転を管理するために、QSGTransformNode をシーングラフツリーに挿入します。 子アイテムはこのトランスフォームノードの下に配置されます。デフォルトのレンダラーは、フレーム間でトランスフォームノードの状態を追跡し、サブツリーを調査して、そのトランスフォームノードが一連のバッチのルートとなる適切な候補かどうかを判断します。フレーム間で変化し、かつ比較的複雑なサブツリーを持つトランスフォームノードは、バッチのルートになる可能性があります。
バッチルートのサブツリー内にある QSGGeometryNodes は、CPU 上でルートに対する変換が事前に適用されます。その後、これらは GPU にアップロードされ、保持されます。変換が変更された場合、レンダラーは個々のアイテムではなくルートの行列のみを更新すればよいため、リストやグリッドのスクロールが非常に高速になります。 連続するフレームにおいて、ノードの追加や削除が行われない限り、リストのレンダリングは実質的に無料となります。新しいコンテンツがサブツリーに追加されると、そのコンテンツを含むバッチは再構築されますが、この処理も比較的高速です。グリッドやリストをパン(スクロール)する際、ノードの追加や削除が行われるフレームごとに、通常は変更のないフレームがいくつか存在します。
トランスフォームノードをバッチルートとして特定することのもう一つの利点は、レンダラーが変更されていないツリーの部分を維持できることです。 例えば、UIがリストとボタンの行で構成されているとします。リストがスクロールされ、デリゲートが追加・削除されている間、UIの残りの部分であるボタンの行は変更されていないため、GPUにすでに保存されているジオメトリを使用して描画できます。
トランスフォームノードがバッチルートになるためのノードおよび頂点の閾値は、環境変数QSG_RENDERER_BATCH_NODE_THRESHOLD=[count] およびQSG_RENDERER_BATCH_VERTEX_THRESHOLD=[count] を使用して上書きできます。これらのフラグを上書きすることは、主にプラットフォームベンダーにとって有用です。
注: バッチルート下では 、マテリアル状態とジオメトリタイプの組み合わせが1つ異なるごとに、1つのバッチが作成されます。
クリッピング
Item::clip を true に設定すると、ジオメトリに長方形を持つQSGClipNode が作成されます。デフォルトのレンダラーは、OpenGL のシザリングを使用してこのクリップを適用します。アイテムが 90 度以外の角度で回転している場合は、OpenGL のステンシルバッファが使用されます。Qt Quick ItemはQML経由での矩形クリップの設定のみをサポートしていますが、シーングラフAPIおよびデフォルトのレンダラーでは、任意の形状をクリッピングに使用できます。
サブツリーにクリップを適用する場合、そのサブツリーは一意の OpenGL 状態でレンダリングされる必要があります。つまり、Item::clip が true の場合、そのアイテムのバッチ処理はその子要素に限定されます。ListView やGridView のように子要素が多い場合や、TextArea のような複雑な子要素がある場合でも、問題はありません。 ただし、より小さなアイテムに対してクリッピングを使用する場合は、バッチ処理が妨げられるため注意が必要です。これには、ボタンラベル、テキストフィールド、リストデリゲート、およびテーブルセルが含まれます。Flickable(またはアイテムビュー)のクリッピングは、不透明なアイテムでFlickableの周囲を覆うようにUIを配置するか、あるいはウィンドウの端を利用して他のすべてをクリップすることで、多くの場合回避できます。
Item::clip をtrue に設定すると、QQuickItem::ItemIsViewport フラグも設定されます。QQuickItem::ItemObservesViewport フラグが設定された子アイテムは、大まかなクリッピング前の処理としてビューポートを使用する場合があります。例えば、Text は、ビューポートの完全に外側にあるテキスト行を省略します。シーングラフノードを省略したり、vertices を制限したりすることは最適化の一環であり、QMLでItem::clip を設定するのではなく、C++でflags を設定することで実現できます。
カスタムアイテムでQQuickItem::updatePaintNode()を実装する際、広範囲の幾何学的領域にわたって多くの詳細をレンダリングできる場合は、グラフィックスをビューポート内に制限することが効率的かどうかを検討する必要があります。効率的である場合は、ItemObservesViewport フラグを設定し、QQuickItem::clipRect()から現在表示されている領域を読み取ることができます。 その結果、updatePaintNode() がより頻繁に呼び出されるようになります(通常、ビューポート内でコンテンツが移動している場合は 1 フレームにつき 1 回)。
頂点バッファ
各バッチは、GPU 上にデータを格納するために頂点バッファオブジェクト (VBO) を使用します。この頂点バッファはフレーム間で保持され、それが表すシーングラフの一部が変更されたときに更新されます。
デフォルトでは、レンダラーはGL_STATIC_DRAW を使用して VBO にデータをアップロードします。環境変数QSG_RENDERER_BUFFER_STRATEGY=[strategy] を設定することで、別のアップロード戦略を選択することができます。有効な値はstream およびdynamic です。この値の変更は、主にプラットフォームベンダーにとって有用です。
アンチエイリアシング
シーングラフは 2 種類のアンチエイリアシングをサポートしています。デフォルトでは、矩形や画像などのプリミティブに対して、エッジに沿って頂点を追加し、エッジが透明にフェードアウトするようにすることでアンチエイリアシングが行われます。 この手法を「頂点アンチエイリアシング」と呼びます。ユーザーが `QQuickWindow::setFormat()` を使用して、QSurfaceFormat を `0 ` より大きいサンプル数に設定し、マルチサンプル OpenGL コンテキストを要求した場合、シーングラフはマルチサンプルベースのアンチエイリアシング(MSAA)を優先します。これら 2 つの手法は、内部でのレンダリング処理に影響を与え、それぞれ異なる制限があります。
また、環境変数QSG_ANTIALIASING_METHOD をvertex またはmsaa に設定することで、使用されるアンチエイリアシング方式を上書きすることも可能です。
頂点アンチエイリアシングでは、たとえ2つのエッジが数学的に同一であっても、隣接するプリミティブのエッジ間に継ぎ目が生じることがあります。一方、マルチサンプル・アンチエイリアシングではそのようなことはありません。
頂点アンチエイリアシング
頂点アンチエイリアシングは、Item::antialiasing プロパティを使用して、アイテムごとに有効または無効に設定できます。これは、基盤となるハードウェアが何をサポートしているかに関係なく機能し、通常レンダリングされたプリミティブだけでなく、例えばShaderEffectSource タイプを使用してフレームバッファオブジェクトに取り込まれたプリミティブに対しても、より高品質なアンチエイリアシングを実現します。
頂点アンチエイリアシングを使用する際のデメリットは、アンチエイリアシングが有効になっている各プリミティブに対してブレンディング処理が必要になることです。 バッチ処理の観点からは、これは、プリミティブをバッチ処理できるかどうかを判断するためにレンダラーがより多くの処理を必要とすることを意味します。また、シーン内の他の要素との重なりにより、バッチ処理の回数が減少する可能性もあり、パフォーマンスに影響を与える恐れがあります。
また、ローエンドのハードウェアでは、ブレンディングの処理負荷がかなり高くなるため、画面の大部分を覆う画像や丸みを帯びた長方形の場合、これらのプリミティブの内部に必要なブレンディングの量によって、プリミティブ全体をブレンディングしなければならなくなり、パフォーマンスが大幅に低下する可能性があります。
マルチサンプルアンチエイリアシング
マルチサンプルアンチエイリアシングは、ハードウェアがプリミティブ内のピクセルごとにカバレッジ値を計算するハードウェア機能です。ハードウェアによっては非常に低いコストでマルチサンプル処理が可能ですが、フレームをレンダリングするために、より多くのメモリとGPUサイクルを必要とするハードウェアもあります。
マルチサンプルアンチエイリアシングを使用することで、角丸矩形や画像要素などの多くのプリミティブに対してアンチエイリアシングを適用しつつ、シーングラフ内では不透明な状態を維持できます。これにより、レンダラーはバッチ作成の負荷が軽減され、オーバードローを回避するためにアーリーZを活用できるようになります。
マルチサンプルアンチエイリアシングを使用する場合、フレームバッファオブジェクトにレンダリングされるコンテンツには、フレームバッファのマルチサンプリングをサポートするための追加の拡張機能が必要となります。 通常はGL_EXT_framebuffer_multisample およびGL_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 を設定してください。
- 上の図のように、重なり合う複合アイテムはバッチ処理できないことに注意してください。
- クリッピングはバッチ処理を中断します。テーブルセル内、アイテムデリゲート内、または同様の場所では、決してアイテム単位でクリッピングを使用しないでください。テキストのクリッピングの代わりに、省略(eliding)を使用してください。画像のクリッピングの代わりに、トリミングされた画像を返すQQuickImageProvider を作成してください。
- バッチ処理は 16 ビットインデックスのみに対応しています。すべての組み込みアイテムは 16 ビットインデックスを使用しますが、カスタムジオメトリでは 32 ビットインデックスを使用することも可能です。
- 一部のマテリアルフラグはバッチ処理を妨げますが、中でも最も制限の厳しいのは「QSGMaterial::RequiresFullMatrix 」であり、これはすべてのバッチ処理を無効にします。
- 背景が単色のアプリケーションでは、トップレベルの Rectangle アイテムを使用するのではなく、QQuickWindow::setColor() を使用して設定する必要があります。QQuickWindow::setColor() は
glClear()の呼び出しで使用され、処理が高速になる可能性があります。 - ミップマップされた Image アイテムはグローバルアトラスには配置されず、バッチ処理の対象にもなりません。
- フレームバッファオブジェクト (FBO) の読み出しに関連する OpenGL ドライバのバグにより、レンダリングされたグリフが破損する可能性があります。
QML_USE_GLYPHCACHE_WORKAROUND環境変数を設定すると、Qt は RAM 内にグリフの追加コピーを保持します。これは、Qt が CPU 経由でその追加コピーにアクセスするため、以前に描画されたことのないグリフを描画する際のパフォーマンスがわずかに低下することを意味します。また、グリフキャッシュが 2 倍のメモリを使用することにもなります。品質には影響しません。
アプリケーションのパフォーマンスが低下している場合は、レンダリングが実際にボトルネックになっているか確認してください。プロファイラを使用しましょう!環境変数QSG_RENDER_TIMING=1 を設定すると、問題の所在を特定するのに役立つ、いくつかの有用なタイミングパラメータが出力されます。
可変性グループ
分析の結果、レンダラーが定期的に更新されるコンテンツと静的なコンテンツをまとめてバッチ処理していることが判明する場合があります。そのような場合は、更新のたびにほとんど変更のないコンテンツを含む大きなバッチをアップロードするよりも、ジオメトリを 2 つの別々のバッチに分割した方が良いでしょう。
次の例を見てみましょう:
Column {
Timer {
interval: 1000
running: true
repeat: true
onTriggered: dynamicText.counter++
}
Text {
id: dynamicText
property int counter: 0
text: counter
mutabilityGroup: Item.DynamicMutabilityGroup
}
Text {
id: staticText1
text: "Static label"
}
Text {
id: staticText2
text: "Static label"
}
}このアプリケーションは、1秒ごとに更新されるdynamicText ラベルで構成されています。さらに、更新されることのない2つの静的なテキストラベルがあります。
この例で明示的な可変性グループが設定されていない場合、静的なテキストラベルのジオメトリは動的なラベルと一緒にバッチ処理されてしまいます。 これは、これらすべてが同じマテリアルと基本プロパティを使用しており、シーングラフのバッチレンダラーが、シーン内のすべてのテキストを表示するために必要なドローコールの数を(一定の制限内で)最小限に抑えようとするためです。その結果、シーン内の静的テキストを表す88個の頂点は、動的テキストが変更されるたびに再アップロードされてしまいます。
dynamicText のmutabilityGroupをItem.DynamicMutabilityGroup に設定することで、ラベルが頻繁に更新されることをレンダラーに示唆します。 その結果、デフォルトのmutabilityグループに属する残りのコンテンツとは決してバッチ処理されなくなります。同じペースで更新されるアイテムが複数ある場合でも、それらを同じグループに割り当てることで、バッチ処理をまとめて行うことができます。
デフォルトのグループ0 を含め、合計 16 の可変性グループが利用可能です。
UI 内のアイテムの大部分については、デフォルトの可変性グループを使用すべきです。主に、大規模な静的ジオメトリの再アップロードによってボトルネックが発生していることが分析で判明した場合に、これを上書きする必要があります。
可視化
シーングラフのデフォルトレンダラーのさまざまな側面を可視化するには、環境変数 `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 に設定しています。

原文
注: 可視化された要素は クリッピングを無視し、レンダリング順序は任意です。
バッチの可視化
QSG_VISUALIZE をbatches に設定すると、レンダラーでバッチが可視化されます。マージされたバッチは単色で描画され、マージされていないバッチは斜線のパターンで描画されます。固有の色が少なければ少ないほど、バッチングが適切に行われています。マージされていないバッチに個別のノードが多く含まれている場合は、バッチングが不適切です。

QSG_VISUALIZE=batches
クリッピングの可視化
QSG_VISUALIZE をclip に設定すると、シーン上に赤い領域が描画され、クリッピングを示します。Qt Quick のアイテムはデフォルトでクリッピングを行わないため、通常はクリッピングは可視化されません。

QSG_VISUALIZE=clip
変更の可視化
QSG_VISUALIZE をchanges に設定すると、レンダラーでの変更が可視化されます。シーングラフでの変更は、ランダムな色の点滅するオーバーレイで可視化されます。プリミティブへの変更は単色で可視化される一方、行列や不透明度の変更など、親要素での変更はパターンで可視化されます。
オーバードローの可視化
QSG_VISUALIZE をoverdraw に設定すると、レンダラー内でオーバードローが可視化されます。すべてのアイテムを3Dで可視化することで、オーバードローを強調表示します。このモードは、ビューポート外のジオメトリをある程度検出するためにも使用できます。不透明なアイテムは緑がかった色で、半透明なアイテムは赤がかった色でレンダリングされます。 ビューポートのバウンディングボックスは青色でレンダリングされます。不透明なコンテンツはシーングラフによる処理が容易であり、通常、レンダリングも高速です。
なお、上記のコードにあるルート矩形は、ウィンドウ自体も白色であるため不要であり、この場合は矩形を描画することはリソースの無駄になります。これを Item に変更することで、パフォーマンスがわずかに向上する可能性があります。


QSG_VISUALIZE=overdraw
Qt Rendering Hardware Interface によるレンダリング
Qt 6.0 以降、デフォルトの適応では常に、 Qt GUI モジュールによって提供されるグラフィックス抽象化レイヤーであるQt Rendering Hardware Interface(RHI)を介して常にレンダリングされます。つまり、Qt 5とは異なり、シーングラフによる直接的なOpenGL呼び出しは行われません。その代わりに、RHI APIを使用してリソースおよび描画コマンドを記録し、RHIがコマンドストリームをOpenGL、Vulkan、Metal、またはDirect 3Dの呼び出しに変換します。 シェーダーの処理も統一されており、シェーダーコードを一度記述してSPIR-Vにコンパイルした後、各種グラフィックスAPIに適した言語に変換されます。
動作を制御するには、以下の環境変数を使用できます:
| 環境変数 | 有効な値 | 説明 |
|---|---|---|
QSG_RHI_BACKEND | vulkan,metal,opengl,d3d11,d3d12 | 特定の RHI バックエンドを指定します。この変数または同等の C++ API によって上書きされない限り、デフォルトではプラットフォームに基づいて対象のグラフィックス API が選択されます。現在のデフォルトは、Windows では Direct3D 11、macOS では Metal、その他のプラットフォームでは OpenGL です。 |
QSG_INFO | 1 | OpenGLベースのレンダリングパスと同様に、これを設定すると、Qt Quick シーングラフの初期化時にシステム情報が出力されます。これはトラブルシューティングに非常に役立ちます。 |
QSG_RHI_DEBUG_LAYER | 1 | 該当する場合(Vulkan、Direct3D)、グラフィックスデバイスまたはインスタンスオブジェクト上で、利用可能なグラフィックスAPI実装のデバッグ層または検証層を有効にします。macOS上のMetalについては、代わりに環境変数METAL_DEVICE_WRAPPER_TYPE=1 を設定してください。 |
QSG_RHI_PREFER_SOFTWARE_RENDERER | 1 | ソフトウェアベースのラスタライゼーションを使用するアダプタまたは物理デバイスの選択を要求します。これは、基盤となる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_RENDERER またはQT_D3D_ADAPTER_INDEX やQT_VK_PHYSICAL_DEVICE_INDEX といったバックエンド固有の変数によって上書きされない限り、システムのデフォルトの GPU アダプタまたは物理デバイスを選択します。現時点では、これ以上のアダプタの設定機能は提供されていません。
Qt 6.5 以降、以前は環境変数としてのみ公開されていた設定の一部が、QQuickGraphicsConfiguration 内の C++ API として利用可能になりました。たとえば、QSG_RHI_DEBUG_LAYER を設定することと、setDebugLayer(true) を呼び出すことは同等です。
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.