Sur cette page

Qt Quick Rendu par défaut du graphe de scène

Ce document explique le fonctionnement interne du moteur de rendu par défaut du graphe de scène, de sorte que l'on puisse écrire du code qui l'utilise de manière optimale, à la fois en termes de performances et de fonctionnalités.

Il n'est pas nécessaire de comprendre le fonctionnement interne du moteur de rendu pour obtenir de bonnes performances. Cependant, cela peut être utile lors de l'intégration avec le graphe de scène ou pour comprendre pourquoi il n'est pas possible de tirer le maximum d'efficacité de la puce graphique.

Remarque : même dans le cas où chaque image est unique et où tout est téléchargé à partir de zéro, le moteur de rendu par défaut donnera de bons résultats.

Les éléments Qt Quick d'une scène QML alimentent un arbre d'instances QSGNode. Une fois créé, cet arbre est une description complète de la manière dont une certaine image doit être rendue. Il ne contient aucune référence aux éléments Qt Quick et, sur la plupart des plates-formes, il sera traité et rendu dans un thread séparé. Le moteur de rendu est une partie autonome du graphe de scène qui traverse l'arbre QSGNode et utilise la géométrie définie dans QSGGeometryNode et l'état du shader défini dans QSGMaterial pour mettre à jour l'état graphique et générer des appels de dessin.

Si nécessaire, le moteur de rendu peut être complètement remplacé en utilisant l'API interne du graphe de scène. Cette possibilité est surtout intéressante pour les fournisseurs de plates-formes qui souhaitent tirer parti de caractéristiques matérielles non standard. Pour la majorité des cas d'utilisation, le moteur de rendu par défaut sera suffisant.

Le moteur de rendu par défaut se concentre sur deux stratégies principales pour optimiser le rendu : La mise en lot des appels de dessin et la rétention de la géométrie sur le GPU.

Mise en lots

Alors qu'une API 2D traditionnelle, telle que QPainter, Cairo ou Context2D, est écrite pour gérer des milliers d'appels de dessin individuels par image, OpenGL et d'autres API accélérées par le matériel sont plus performantes lorsque le nombre d'appels de dessin est très faible et que les changements d'état sont réduits au minimum.

Note : Bien que OpenGL soit utilisé comme exemple dans les sections suivantes, les mêmes concepts s'appliquent également à d'autres API graphiques.

Considérons le cas d'utilisation suivant :

La façon la plus simple de dessiner cette liste est de le faire cellule par cellule. On commence par dessiner l'arrière-plan. Il s'agit d'un rectangle d'une couleur spécifique. En termes d'OpenGL, cela signifie qu'il faut sélectionner un programme de nuanceur pour effectuer des remplissages en couleur, configurer la couleur de remplissage, définir la matrice de transformation contenant les décalages x et y, puis utiliser, par exemple, glDrawArrays pour dessiner deux triangles composant le rectangle. L'icône est ensuite dessinée. En termes d'OpenGL, cela signifie qu'il faut sélectionner un programme de nuanceur pour dessiner des textures, sélectionner la texture active à utiliser, définir la matrice de transformation, activer l'alpha-blending, puis utiliser par exemple glDrawArrays pour dessiner les deux triangles constituant le rectangle de délimitation de l'icône. Le texte et la ligne de séparation entre les cellules suivent un schéma similaire. Et ce processus est répété pour chaque cellule de la liste, donc pour une liste plus longue, la surcharge imposée par les changements d'état OpenGL et les appels de dessin l'emporte complètement sur le bénéfice que l'utilisation d'une API accélérée par le matériel pourrait fournir.

Lorsque chaque primitive est grande, ce surcoût est négligeable, mais dans le cas d'une interface utilisateur typique, de nombreux petits éléments s'ajoutent à un surcoût considérable.

Le moteur de rendu de graphe de scène par défaut travaille avec ces limitations et essaiera de fusionner les primitives individuelles en lots tout en préservant exactement le même résultat visuel. Il en résulte moins de changements d'état OpenGL et un nombre minimal d'appels de dessin, ce qui se traduit par des performances optimales.

Primitives opaques

Le moteur de rendu fait la distinction entre les primitives opaques et les primitives nécessitant un mélange alpha. En utilisant le tampon Z d'OpenGL et en donnant à chaque primitive une position z unique, le moteur de rendu peut librement réorganiser les primitives opaques sans tenir compte de leur emplacement à l'écran et des autres éléments avec lesquels elles se superposent. En examinant l'état matériel de chaque primitive, le moteur de rendu créera des lots opaques. Dans le jeu d'éléments de base de Qt Quick, cela inclut les éléments Rectangle avec des couleurs opaques et des images totalement opaques, telles que les JPEG ou les BMP.

Un autre avantage de l'utilisation de primitives opaques est qu'il n'est pas nécessaire d'activer GL_BLEND, ce qui peut être assez coûteux, en particulier sur les GPU mobiles et embarqués.

Les primitives opaques sont rendues d'avant en arrière avec glDepthMask et GL_DEPTH_TEST activés. Sur les GPU qui effectuent en interne des vérifications early-z, cela signifie que le fragment shader n'a pas besoin de s'exécuter pour les pixels ou les blocs de pixels qui sont obscurcis. Attention, le moteur de rendu doit toujours prendre en compte ces nœuds et le nuanceur de vertex est toujours exécuté pour chaque vertex dans ces primitives, donc si l'application sait que quelque chose est complètement obscurci, la meilleure chose à faire est de le cacher explicitement à l'aide de Item::visible ou Item::opacity.

Remarque : Item::z est utilisé pour contrôler l'ordre d'empilement d'un élément par rapport à ses frères et sœurs. Il n'a pas de relation directe avec le moteur de rendu et le tampon Z d'OpenGL.

Primitives à mélange alpha

Une fois que les primitives opaques ont été dessinées, le moteur de rendu désactive glDepthMask, active GL_BLEND et rend toutes les primitives à mélange alpha de manière frontale.

La mise en lots des primitives à mélange alpha nécessite un peu plus d'efforts de la part du moteur de rendu, car les éléments qui se chevauchent doivent être rendus dans le bon ordre pour que le mélange alpha soit correct. S'appuyer uniquement sur le tampon Z n'est pas suffisant. Le moteur de rendu passe en revue toutes les primitives mélangées par alpha et examine leur rectangle de délimitation en plus de l'état de leur matériau pour déterminer quels éléments peuvent être mis en lots et lesquels ne le peuvent pas.

Dans le cas le plus à gauche, les arrière-plans bleus peuvent être dessinés dans un appel et les deux éléments de texte dans un autre appel, car les textes ne recouvrent qu'un arrière-plan devant lequel ils sont empilés. Dans le cas le plus à droite, l'arrière-plan de l'"élément 4" recouvre le texte de l'"élément 3", de sorte que dans ce cas, les arrière-plans et les textes doivent être dessinés à l'aide d'appels distincts.

Dans l'axe Z, les primitives alpha sont entrelacées avec les nœuds opaques et peuvent déclencher l'option early-z lorsqu'elle est disponible, mais là encore, il est toujours plus rapide de définir Item::visible sur false.

Mélange avec des primitives 3D

Le graphe de scène peut prendre en charge des primitives pseudo 3D et des primitives 3D proprement dites. Par exemple, on peut implémenter un effet "page curl" en utilisant ShaderEffect ou implémenter un bumpmapped torus en utilisant QSGGeometry et un matériau personnalisé. Ce faisant, il faut tenir compte du fait que le moteur de rendu par défaut utilise déjà le tampon de profondeur.

Le moteur de rendu modifie le vertex shader renvoyé par QSGMaterialShader::vertexShader() et compresse les valeurs z du vertex après l'application des matrices de vue-modèle et de projection, puis ajoute une petite translation sur le z pour le positionner à la bonne position z. La compression part du principe que les valeurs z du vertex ont été compressées et que les valeurs z du vertex ont été compressées.

La compression suppose que les valeurs z sont comprises entre 0 et 1.

Atlas des textures

La texture active est un état OpenGL unique, ce qui signifie que plusieurs primitives utilisant différentes textures OpenGL ne peuvent pas être regroupées. Le graphe de scène Qt Quick, pour cette raison, permet à de multiples instances QSGTexture d'être allouées en tant que sous-régions plus petites d'une texture plus grande ; un atlas de texture.

Le plus grand avantage des atlas de texture est que plusieurs instances QSGTexture font désormais référence à la même instance de texture OpenGL. Cela permet également de regrouper les appels de dessin de textures, tels que les éléments d'image, les éléments BorderImage, les éléments ShaderEffect et également les types C++ tels que QSGSimpleTextureNode et les QSGGeometryNodes personnalisés utilisant des textures.

Remarque : les grandes textures ne sont pas incluses dans l'atlas des textures.

Les textures basées sur l'atlas sont créées en passant QQuickWindow::TextureCanUseAtlas à la fonction QQuickWindow::createTextureFromImage().

Remarque : les textures basées sur l'atlas n'ont pas de coordonnées de texture allant de 0 à 1. Utilisez QSGTexture::normalizedTextureSubRect() pour obtenir les coordonnées de texture de l'atlas.

Le graphe de scène utilise des heuristiques pour déterminer la taille de l'atlas et le seuil d'entrée dans l'atlas. Si des valeurs différentes sont nécessaires, il est possible de les remplacer en utilisant les variables d'environnement QSG_ATLAS_WIDTH=[width], QSG_ATLAS_HEIGHT=[height] et QSG_ATLAS_SIZE_LIMIT=[size]. La modification de ces valeurs sera surtout intéressante pour les fournisseurs de plates-formes.

Racines par lots

En plus de fusionner les primitives compatibles en lots, le moteur de rendu par défaut tente également de minimiser la quantité de données à envoyer au GPU pour chaque image. Le moteur de rendu par défaut identifie les sous-arbres qui vont ensemble et tente de les placer dans des lots séparés. Une fois les lots identifiés, ils sont fusionnés, téléchargés et stockés dans la mémoire du GPU à l'aide d'objets tampons de sommet.

Nœuds de transformation

Chaque élément Qt Quick insère un nœud QSGTransformNode dans l'arbre graphique de la scène pour gérer ses x, y, son échelle ou sa rotation. Les éléments enfants seront peuplés sous ce nœud de transformation. Le moteur de rendu par défaut suit l'état des nœuds de transformation entre les images et examine les sous-arbres pour décider si un nœud de transformation est un bon candidat pour devenir la racine d'un ensemble de lots. Un nœud de transformation qui change entre les images et qui a un sous-arbre assez complexe peut devenir une racine de lot.

Les QSGGeometryNodes dans le sous-arbre d'une racine de lot sont pré-transformés par rapport à la racine sur l'unité centrale. Ils sont ensuite téléchargés et conservés sur le GPU. Lorsque la transformation change, le moteur de rendu ne doit mettre à jour que la matrice de la racine, et non chaque élément individuel, ce qui rend le défilement des listes et des grilles très rapide. Pour les images successives, tant que des nœuds ne sont pas ajoutés ou supprimés, le rendu de la liste est effectivement gratuit. Lorsque du nouveau contenu entre dans le sous-arbre, le lot qui le reçoit est reconstruit, mais cela reste relativement rapide. Il y a généralement plusieurs images inchangées pour chaque image avec des nœuds ajoutés ou supprimés lors d'un balayage panoramique d'une grille ou d'une liste.

Un autre avantage de l'identification des nœuds de transformation en tant que racines de lot est qu'elle permet au moteur de rendu de conserver les parties de l'arbre qui n'ont pas changé. Par exemple, supposons qu'une interface utilisateur se compose d'une liste et d'une rangée de boutons. Lorsque la liste défile et que des délégués sont ajoutés ou supprimés, le reste de l'interface, la rangée de boutons, reste inchangée et peut être dessinée à l'aide de la géométrie déjà stockée sur le GPU.

Le seuil de nœuds et de vertex pour qu'un nœud de transformation devienne une racine de lot peut être surchargé en utilisant les variables d'environnement QSG_RENDERER_BATCH_NODE_THRESHOLD=[count] et QSG_RENDERER_BATCH_VERTEX_THRESHOLD=[count]. La surcharge de ces drapeaux sera principalement utile pour les fournisseurs de plateformes.

Remarque : sous une racine de lot, un lot est créé pour chaque ensemble unique d'état de matériau et de type de géométrie.

Découpage

Lorsque Item::clip est défini sur true, il crée un QSGClipNode avec un rectangle dans sa géométrie. Le moteur de rendu par défaut appliquera ce clip en utilisant le scissoring dans OpenGL. Si l'élément est tourné d'un angle autre que 90 degrés, le tampon stencil d'OpenGL est utilisé. Qt Quick Item ne prend en charge la définition d'un rectangle comme clip que par l'intermédiaire de QML, mais l'API de graphe de scène et le moteur de rendu par défaut peuvent utiliser n'importe quelle forme pour l'écrêtage.

Lors de l'application d'un clip à un sous-arbre, ce sous-arbre doit être rendu avec un état OpenGL unique. Cela signifie que lorsque Item::clip est vrai, la mise en lot de cet élément est limitée à ses enfants. Lorsqu'il y a beaucoup d'enfants, comme ListView ou GridView, ou des enfants complexes, comme TextArea, cela ne pose pas de problème. Il convient toutefois d'utiliser clip avec précaution pour les éléments plus petits, car cela empêche la mise en lot. Il s'agit notamment de l'étiquette d'un bouton, d'un champ de texte ou d'un délégué de liste et des cellules d'un tableau. L'écrêtage d'un Flickable (ou d'une vue d'élément) peut souvent être évité en arrangeant l'interface utilisateur de manière à ce que les éléments opaques couvrent les zones autour du Flickable, et en s'appuyant sur les bords de la fenêtre pour écrêter tout le reste.

La définition de Item::clip à true définit également le drapeau QQuickItem::ItemIsViewport; les éléments enfants avec le drapeau QQuickItem::ItemObservesViewport peuvent utiliser la fenêtre de visualisation pour une étape de pré-clipsage approximative : par exemple, Text omet les lignes de texte qui sont complètement en dehors de la fenêtre de visualisation. L'omission des nœuds du graphe de scène ou la limitation de vertices est une optimisation, qui peut être réalisée en définissant flags en C++ plutôt que Item::clip en QML.

Lors de l'implémentation de QQuickItem::updatePaintNode() dans un élément personnalisé, s'il peut rendre beaucoup de détails sur une grande zone géométrique, vous devez vous demander s'il est efficace de limiter les graphiques à la fenêtre de visualisation ; si c'est le cas, vous pouvez activer le drapeau ItemObservesViewport et lire la zone actuellement exposée à partir de QQuickItem::clipRect(). L'une des conséquences est que updatePaintNode() sera appelée plus souvent (typiquement une fois par image lorsque le contenu se déplace dans la fenêtre de visualisation).

Tampons de sommets

Chaque lot utilise un objet tampon de sommet (VBO) pour stocker ses données sur le GPU. Ce tampon de sommets est conservé entre les images et mis à jour lorsque la partie du graphe de la scène qu'il représente change.

Par défaut, le moteur de rendu télécharge les données dans le VBO à l'aide de GL_STATIC_DRAW. Il est possible de sélectionner une stratégie de téléchargement différente en définissant la variable d'environnement QSG_RENDERER_BUFFER_STRATEGY=[strategy]. Les valeurs valides sont stream et dynamic. La modification de cette valeur est surtout utile pour les fournisseurs de plateformes.

Anti-crénelage

Le graphe de scène prend en charge deux types d'anticrénelage. Par défaut, les primitives telles que les rectangles et les images seront anticrénelées en ajoutant plus de sommets le long du bord des primitives de sorte que les bords deviennent transparents. Nous appelons cette méthode l'anticrénelage des sommets. Si l'utilisateur demande un contexte OpenGL multi-échantillonné, en définissant un QSurfaceFormat avec des échantillons supérieurs à 0 en utilisant QQuickWindow::setFormat(), le graphe de scène préférera l'anticrénelage basé sur des multi-échantillons (MSAA). Les deux techniques affectent la manière dont le rendu est effectué en interne et ont des limites différentes.

Il est également possible de remplacer la méthode d'anticrénelage utilisée en définissant la variable d'environnement QSG_ANTIALIASING_METHOD à vertex ou msaa.

L'anticrénelage des sommets peut produire des coutures entre les bords de primitives adjacentes, même lorsque les deux bords sont mathématiquement identiques. Ce n'est pas le cas de l'anticrénelage multi-échantillon.

Anti-crénelage des sommets

L'anticrénelage des sommets peut être activé et désactivé pour chaque élément à l'aide de la propriété Item::antialiasing. Il fonctionne quel que soit le matériel sous-jacent et produit un anticrénelage de meilleure qualité, à la fois pour les primitives rendues normalement et pour les primitives capturées dans des objets framebuffer, par exemple à l'aide du type ShaderEffectSource.

L'inconvénient de l'utilisation de l'anticrénelage des vertex est que chaque primitive dont l'anticrénelage est activé devra être mélangée. En termes de mise en lots, cela signifie que le moteur de rendu doit faire plus de travail pour déterminer si la primitive peut être mise en lots ou non et, en raison des chevauchements avec d'autres éléments de la scène, il peut également en résulter une mise en lots moins importante, ce qui peut avoir un impact sur les performances.

Sur le matériel bas de gamme, le mélange peut également être assez coûteux. Ainsi, pour une image ou un rectangle arrondi qui couvre la majeure partie de l'écran, la quantité de mélange nécessaire pour l'intérieur de ces primitives peut entraîner une perte de performances significative, car la primitive doit être mélangée dans son intégralité.

Anti-crénelage multi-échantillon

L'anticrénelage multi-échantillon est une fonction matérielle qui permet au matériel de calculer une valeur de couverture par pixel dans la primitive. Certains matériels peuvent effectuer un multi-échantillonnage à un coût très faible, tandis que d'autres matériels peuvent avoir besoin de plus de mémoire et de plus de cycles GPU pour effectuer le rendu d'une image.

Grâce à l'anticrénelage multi-échantillon, de nombreuses primitives, telles que les rectangles arrondis et les éléments d'image, peuvent être anticrénelées tout en restant opaques dans le graphe de la scène. Cela signifie que le moteur de rendu a un travail plus facile lorsqu'il crée des lots et qu'il peut s'appuyer sur le early-z pour éviter le surdessin.

Lorsque l'anticrénelage multi-échantillon est utilisé, le contenu rendu dans les objets framebuffer nécessite des extensions supplémentaires pour prendre en charge le multi-échantillonnage des framebuffers. Typiquement GL_EXT_framebuffer_multisample et GL_EXT_framebuffer_blit. Ces extensions sont présentes dans la plupart des puces d'ordinateur de bureau, mais elles sont moins courantes dans les puces intégrées. Lorsque le multi-échantillonnage des framebuffers n'est pas disponible dans le matériel, le contenu rendu dans les objets framebuffer ne sera pas anticrénelé, y compris le contenu d'un site ShaderEffectSource.

Performance

Comme indiqué au début, il n'est pas nécessaire de comprendre les détails les plus fins du moteur de rendu pour obtenir de bonnes performances. Il est écrit pour optimiser les cas d'utilisation courants et fonctionnera très bien dans presque toutes les circonstances.

  • Les bonnes performances proviennent d'une mise en lot efficace, avec le moins possible de géométrie téléchargée à plusieurs reprises. En définissant la variable d'environnement QSG_RENDERER_DEBUG=render, le moteur de rendu produira des statistiques sur la qualité de la mise en lots, le nombre de lots utilisés, les lots conservés et ceux qui sont opaques ou non. Pour obtenir des performances optimales, les téléchargements ne devraient avoir lieu qu'en cas de réelle nécessité, les lots devraient être inférieurs à 10 et au moins 3 ou 4 d'entre eux devraient être opaques.
  • Le moteur de rendu par défaut n'effectue pas d'écrêtage de la fenêtre côté CPU ni de détection d'occlusion. Si quelque chose n'est pas censé être visible, il ne doit pas l'être. Utilisez Item::visible: false pour les éléments qui ne doivent pas être dessinés. La principale raison de ne pas ajouter une telle logique est qu'elle ajoute un coût supplémentaire qui nuirait également aux applications qui ont pris soin de bien se comporter.
  • Assurez-vous que l'atlas des textures est utilisé. Les éléments Image et BorderImage l'utiliseront à moins que l'image ne soit trop grande. Pour les textures créées en C++, passez QQuickWindow::TextureCanUseAtlas lorsque vous appelez QQuickWindow::createTexture(). En définissant la variable d'environnement QSG_ATLAS_OVERLAY, toutes les textures de l'atlas seront colorisées afin d'être facilement identifiables dans l'application.
  • Utilisez des primitives opaques dans la mesure du possible. Les primitives opaques sont plus rapides à traiter dans le moteur de rendu et plus rapides à dessiner sur le GPU. Par exemple, les fichiers PNG ont souvent un canal alpha, même si chaque pixel est totalement opaque. Les fichiers JPG sont toujours opaques. Lorsque vous fournissez des images à QQuickImageProvider ou que vous créez des images avec QQuickWindow::createTextureFromImage(), faites en sorte que l'image ait QImage::Format_RGB32, dans la mesure du possible.
  • Sachez que les éléments composés qui se chevauchent, comme dans l'illustration ci-dessus, ne peuvent pas être mis en lots.
  • L'écrêtage interrompt la mise en lot. Ne l'utilisez jamais par article, à l'intérieur de cellules de tableau, de délégués d'articles ou d'éléments similaires. Au lieu d'écrêter du texte, utilisez l'élidage. Au lieu de découper une image, créez un site QQuickImageProvider qui renvoie une image recadrée.
  • La mise en lots ne fonctionne que pour les indices de 16 bits. Tous les éléments intégrés utilisent des indices de 16 bits, mais une géométrie personnalisée est libre d'utiliser également des indices de 32 bits.
  • Certains drapeaux de matériaux empêchent la mise en lot, le plus restrictif étant QSGMaterial::RequiresFullMatrix qui empêche toute mise en lot.
  • Les applications ayant un fond monochrome doivent le définir en utilisant QQuickWindow::setColor() plutôt que d'utiliser un élément Rectangle de niveau supérieur. QQuickWindow::setColor() sera utilisé dans un appel à glClear(), ce qui est potentiellement plus rapide.
  • Les éléments Mipmapped Image ne sont pas placés dans l'atlas global et ne seront pas mis en lot.
  • Un bogue dans le pilote OpenGL lié aux lectures d'objets framebuffer (FBO) peut corrompre les glyphes rendus. Si vous définissez la variable d'environnement QML_USE_GLYPHCACHE_WORKAROUND, Qt conserve une copie supplémentaire du glyphe dans la RAM. Cela signifie que les performances sont légèrement inférieures lorsque l'on dessine des glyphes qui n'ont pas été dessinés auparavant, car Qt accède à la copie supplémentaire par l'intermédiaire du CPU. Cela signifie également que le cache des glyphes utilisera deux fois plus de mémoire. La qualité n'en est pas affectée.

Si une application fonctionne mal, assurez-vous que le rendu est bien le goulot d'étranglement. Utilisez un profileur ! La variable d'environnement QSG_RENDER_TIMING=1 fournira un certain nombre de paramètres de synchronisation utiles pour déterminer où se situe le problème.

Visualisation

Pour visualiser les différents aspects du moteur de rendu par défaut du graphe de scène, la variable d'environnement QSG_VISUALIZE peut être réglée sur l'une des valeurs détaillées dans chaque section ci-dessous. Nous donnons des exemples de la sortie de certaines variables à l'aide du code QML suivant :

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
            }
        }
    }
}

Pour le site ListView à gauche, nous définissons sa propriété clip sur true. Pour le ListView de droite, nous définissons également la propriété clip de chaque délégué à true afin d'illustrer les effets de l'écrêtage sur la mise en lots.

Original

Original

Note : Les éléments visualisés ne respectent pas le découpage, et l'ordre de rendu est arbitraire.

Visualisation des lots

La définition de QSG_VISUALIZE à batches permet de visualiser les lots dans le moteur de rendu. Les lots fusionnés sont dessinés avec une couleur unie et les lots non fusionnés sont dessinés avec un motif de lignes diagonales. Peu de couleurs uniques signifient que les lots sont de bonne qualité. Les lots non fusionnés sont mauvais s'ils contiennent de nombreux nœuds individuels.

lots

QSG_VISUALIZE=batches

Visualisation de l'écrêtage

En réglant QSG_VISUALIZE sur clip, des zones rouges sont tracées sur le dessus de la scène pour indiquer l'écrêtage. Comme les éléments de Qt Quick ne sont pas coupés par défaut, aucun écrêtage n'est généralement visualisé.

QSG_VISUALIZE=clip

Visualisation des changements

Le réglage de QSG_VISUALIZE à changes permet de visualiser les changements dans le moteur de rendu. Les changements dans le graphe de scène sont visualisés par un recouvrement clignotant d'une couleur aléatoire. Les modifications apportées à une primitive sont visualisées par une couleur unie, tandis que les modifications apportées à un ancêtre, telles que les changements de matrice ou d'opacité, sont visualisées à l'aide d'un motif.

Visualisation de l'overdraw

Le fait de régler QSG_VISUALIZE sur overdraw permet de visualiser l'overdraw dans le moteur de rendu. Visualisez tous les éléments en 3D pour mettre en évidence les surdébits. Ce mode peut également être utilisé pour détecter la géométrie en dehors de la fenêtre de visualisation dans une certaine mesure. Les éléments opaques sont rendus avec une teinte verte, tandis que les éléments translucides sont rendus avec une teinte rouge. Le cadre de la fenêtre de visualisation est rendu en bleu. Le contenu opaque est plus facile à traiter par le scenegraph et est généralement plus rapide à rendre.

Notez que le rectangle racine dans le code ci-dessus est superflu car la fenêtre est également blanche, donc dessiner le rectangle est un gaspillage de ressources dans ce cas. Le fait de le remplacer par un élément peut améliorer légèrement les performances.

retrait - 1

retrait - 2

QSG_VISUALIZE=overdraw

Rendu via l'interface matérielle de rendu Qt

À partir de Qt 6.0, l'adaptation par défaut effectue toujours le rendu via une couche d'abstraction graphique, l'interface matérielle de rendu Qt (RHI), fournie par le module Qt GUI . Cela signifie que, contrairement à Qt Graphs 5, aucun appel direct à OpenGL n'est effectué par le graphe de scène. Au lieu de cela, il enregistre les commandes de ressources et de dessin en utilisant les API RHI, qui traduisent ensuite le flux de commandes en appels OpenGL, Vulkan, Metal ou Direct 3D. La gestion des shaders est également unifiée en écrivant le code des shaders une seule fois, en le compilant dans SPIR-V, puis en le traduisant dans le langage approprié pour les différentes API graphiques.

Pour contrôler le comportement, les variables d'environnement suivantes peuvent être utilisées :

Variable d'environnementValeurs possiblesDescription
QSG_RHI_BACKENDvulkan, metal, opengl, d3d11, d3d12Demande le backend RHI spécifique. Par défaut, l'API graphique ciblée est choisie en fonction de la plateforme, sauf si cette variable ou les API C++ équivalentes l'emportent. Les valeurs par défaut sont actuellement Direct3D 11 pour Windows, Metal pour macOS, OpenGL ailleurs.
QSG_INFO1Comme pour le chemin de rendu basé sur OpenGL, le paramétrage de cette variable permet d'imprimer les informations système lors de l'initialisation du graphe de scène Qt Quick. Cela peut être très utile pour le dépannage.
QSG_RHI_DEBUG_LAYER1Le cas échéant (Vulkan, Direct3D), active les couches de débogage ou de validation de l'implémentation de l'API graphique, si elles sont disponibles, soit sur le périphérique graphique, soit sur l'objet d'instance. Pour Metal sur macOS, définissez la variable d'environnement METAL_DEVICE_WRAPPER_TYPE=1 à la place.
QSG_RHI_PREFER_SOFTWARE_RENDERER1Demande de choisir un adaptateur ou un périphérique physique qui utilise la rastérisation logicielle. Applicable uniquement lorsque l'API sous-jacente prend en charge l'énumération des adaptateurs (par exemple, Direct3D ou Vulkan), et est ignorée dans le cas contraire.

Les applications qui souhaitent toujours fonctionner avec une seule API graphique donnée peuvent également le demander via C++. Par exemple, l'appel suivant effectué au début de main(), avant la construction de QQuickWindow, force l'utilisation de Vulkan (et échouera dans le cas contraire) :

QQuickWindow::setGraphicsApi(QSGRendererInterface::Vulkan);

Voir QSGRendererInterface::GraphicsApi. Les valeurs de l'énumération OpenGL, Vulkan, Metal, Direct3D11, Direct3D12 sont équivalentes à l'exécution de QSG_RHI_BACKEND avec la clé de chaîne équivalente.

Tous les backends QRhi choisiront l'adaptateur GPU ou le périphérique physique par défaut du système, à moins qu'ils ne soient remplacés par QSG_RHI_PREFER_SOFTWARE_RENDERER ou une variable spécifique au backend, telle que QT_D3D_ADAPTER_INDEX ou QT_VK_PHYSICAL_DEVICE_INDEX. Aucune autre possibilité de configuration de l'adaptateur n'est fournie pour le moment.

À partir de Qt 6.5, certains des paramètres qui n'étaient auparavant exposés que sous forme de variables d'environnement sont disponibles sous forme d'API C++ dans QQuickGraphicsConfiguration. Par exemple, le réglage de QSG_RHI_DEBUG_LAYER et l'appel de setDebugLayer(true) sont équivalents.

© 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.