Sur cette page

QRhiWidget Class

La classe QRhiWidget est un widget permettant de générer des graphismes en 3D via une API graphique accélérée, telle que Vulkan, Metal ou Direct 3D. En savoir plus...

En-tête : #include <QRhiWidget>
CMake : find_package(Qt6 REQUIRED COMPONENTS Widgets)
target_link_libraries(mytarget PRIVATE Qt6::Widgets)
qmake : QT += widgets
Depuis : Qt 6.7
Hérite de : QWidget

Types publics

enum class Api { Null, OpenGL, Metal, Vulkan, Direct3D11, Direct3D12 }
enum class TextureFormat { RGBA8, RGBA16F, RGBA32F, RGB10A2 }

Propriétés

Fonctions publiques

QRhiWidget(QWidget *parent = nullptr, Qt::WindowFlags f = {})
virtual ~QRhiWidget() override
QRhiWidget::Api api() const
QRhiWidget::TextureFormat colorBufferFormat() const
QSize fixedColorBufferSize() const
QImage grabFramebuffer() const
bool isDebugLayerEnabled() const
bool isMirrorVerticallyEnabled() const
int sampleCount() const
void setApi(QRhiWidget::Api api)
void setColorBufferFormat(QRhiWidget::TextureFormat format)
void setDebugLayerEnabled(bool enable)
void setFixedColorBufferSize(QSize pixelSize)
void setFixedColorBufferSize(int w, int h)
void setMirrorVertically(bool enabled)
void setSampleCount(int samples)

Signaux

void colorBufferFormatChanged(QRhiWidget::TextureFormat format)
void fixedColorBufferSizeChanged(const QSize &pixelSize)
void frameSubmitted()
void mirrorVerticallyChanged(bool enabled)
void renderFailed()
void sampleCountChanged(int samples)

Fonctions protégées

QRhiTexture *colorTexture() const
QRhiRenderBuffer *depthStencilBuffer() const
virtual void initialize(QRhiCommandBuffer *cb)
QRhiRenderBuffer *msaaColorBuffer() const
virtual void releaseResources()
virtual void render(QRhiCommandBuffer *cb)
QRhiRenderTarget *renderTarget() const
QRhiTexture *resolveTexture() const
QRhi *rhi() const
void setAutoRenderTarget(bool enabled)

Fonctions protégées réimplémentées

virtual bool event(QEvent *e) override
virtual void paintEvent(QPaintEvent *e) override
virtual void resizeEvent(QResizeEvent *e) override

Description détaillée

QRhiWidget offre des fonctionnalités permettant d'afficher du contenu 3D rendu via les API d'QRhi s au sein d'une application basée sur l'QWidget. À bien des égards, il s’agit de l’équivalent portable d’ QOpenGLWidget, qui n’est pas lié à une seule API graphique 3D, mais peut fonctionner avec toutes les API prises en charge par QRhi (telles que Direct 3D 11/12, Vulkan, Metal et OpenGL).

QRhiWidget est destiné à être sous-classé. Pour effectuer un rendu dans la texture 2D implicitement créée et gérée par QRhiWidget, les sous-classes doivent réimplémenter les fonctions virtuelles initialize() et render().

Par défaut, la taille de la texture s'adapte à celle du widget. Si vous préférez une taille fixe, définissez-la en pixels en appelant la fonction setFixedColorBufferSize().

Outre la texture servant de tampon de couleur, un tampon de profondeur/stencil et une cible de rendu reliant ces éléments entre eux sont également gérés de manière implicite.

L’ QRhi pour la fenêtre de niveau supérieur du widget est configuré par défaut pour utiliser un backend et une API graphique spécifiques à la plateforme : Metal sur macOS et iOS, Direct 3D 11 sur Windows, OpenGL dans les autres cas. Appelez la fonction setApi() pour remplacer cette configuration.

Remarque : une fenêtre de widget ne peut utiliser qu’un seul backend d’ QRhi, et donc une seule API graphique 3D. Si deux widgets QRhiWidget ou QQuickWidget dans la hiérarchie des widgets de la fenêtre demandent des API différentes, un seul d’entre eux fonctionnera correctement.

Remarque : bien que QRhiWidget soit une API Qt publique, la famille de classes QRhi du module Qt GUI, comprenant notamment QRhi, QShader et QShaderDescription, n'offre que des garanties de compatibilité limitées. Il n'existe aucune garantie de compatibilité au niveau du code source ou des binaires pour ces classes, ce qui signifie que le fonctionnement de l'API n'est garanti qu'avec la version de Qt sur laquelle l'application a été développée. Les modifications entraînant une incompatibilité au niveau du code source sont toutefois destinées à être réduites au minimum et ne seront apportées que dans les versions mineures (6.7, 6.8, etc.). qrhiwidget.h n’inclut pas directement d’en-têtes liées à QRhi. Pour utiliser ces classes lors de l’implémentation d’une sous-classe de QRhiWidget, liez-vous à Qt::GuiPrivate (si vous utilisez CMake), et incluez les en-têtes appropriés avec le préfixe rhi, par exemple #include <rhi/qrhi.h>.

Voici un exemple de sous-classe simple de QRhiWidget affichant un triangle :

class ExampleRhiWidget : public QRhiWidget
{
public:
    ExampleRhiWidget(QWidget *parent = nullptr) : QRhiWidget(parent) { }
    void initialize(QRhiCommandBuffer *cb) override;
    void render(QRhiCommandBuffer *cb) override;
private:
    QRhi *m_rhi = nullptr;
    std::unique_ptr<QRhiBuffer> m_vbuf;
    std::unique_ptr<QRhiBuffer> m_ubuf;
    std::unique_ptr<QRhiShaderResourceBindings> m_srb;
    std::unique_ptr<QRhiGraphicsPipeline> m_pipeline;
    QMatrix4x4 m_viewProjection;
    float m_rotation = 0.0f;
};

float vertexData[] = {
     0.0f,   0.5f,     1.0f, 0.0f, 0.0f,
    -0.5f,  -0.5f,     0.0f, 1.0f, 0.0f,
     0.5f,  -0.5f,     0.0f, 0.0f, 1.0f,
};

QShader getShader(const QString &name)
{
    QFile f(name);
    return f.open(QIODevice::ReadOnly) ? QShader::fromSerialized(f.readAll()) : QShader();
}

void ExampleRhiWidget::initialize(QRhiCommandBuffer *cb)
{
    if (m_rhi != rhi()) {
        m_pipeline.reset();
        m_rhi = rhi();
    }

    if (!m_pipeline) {
        m_vbuf.reset(m_rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData)));
        m_vbuf->create();

        m_ubuf.reset(m_rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 64));
        m_ubuf->create();

        m_srb.reset(m_rhi->newShaderResourceBindings());
        m_srb->setBindings({
            QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage, m_ubuf.get()),
        });
        m_srb->create();

        m_pipeline.reset(m_rhi->newGraphicsPipeline());
        m_pipeline->setShaderStages({
            { QRhiShaderStage::Vertex, getShader(QLatin1String(":/shader_assets/color.vert.qsb")) },
            { QRhiShaderStage::Fragment, getShader(QLatin1String(":/shader_assets/color.frag.qsb")) }
        });
        QRhiVertexInputLayout inputLayout;
        inputLayout.setBindings({
            { 5 * sizeof(float) }
        });
        inputLayout.setAttributes({
            { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
            { 0, 1, QRhiVertexInputAttribute::Float3, 2 * sizeof(float) }
        });
        m_pipeline->setVertexInputLayout(inputLayout);
        m_pipeline->setShaderResourceBindings(m_srb.get());
        m_pipeline->setRenderPassDescriptor(renderTarget()->renderPassDescriptor());
        m_pipeline->create();

        QRhiResourceUpdateBatch *resourceUpdates = m_rhi->nextResourceUpdateBatch();
        resourceUpdates->uploadStaticBuffer(m_vbuf.get(), vertexData);
        cb->resourceUpdate(resourceUpdates);
    }

    const QSize outputSize = colorTexture()->pixelSize();
    m_viewProjection = m_rhi->clipSpaceCorrMatrix();
    m_viewProjection.perspective(45.0f, outputSize.width() / (float) outputSize.height(), 0.01f, 1000.0f);
    m_viewProjection.translate(0, 0, -4);
}

void ExampleRhiWidget::render(QRhiCommandBuffer *cb)
{
    QRhiResourceUpdateBatch *resourceUpdates = m_rhi->nextResourceUpdateBatch();
    m_rotation += 1.0f;
    QMatrix4x4 modelViewProjection = m_viewProjection;
    modelViewProjection.rotate(m_rotation, 0, 1, 0);
    resourceUpdates->updateDynamicBuffer(m_ubuf.get(), 0, 64, modelViewProjection.constData());

    const QColor clearColor = QColor::fromRgbF(0.4f, 0.7f, 0.0f, 1.0f);
    cb->beginPass(renderTarget(), clearColor, { 1.0f, 0 }, resourceUpdates);

    cb->setGraphicsPipeline(m_pipeline.get());
    const QSize outputSize = colorTexture()->pixelSize();
    cb->setViewport(QRhiViewport(0, 0, outputSize.width(), outputSize.height()));
    cb->setShaderResources();
    const QRhiCommandBuffer::VertexInput vbufBinding(m_vbuf.get(), 0);
    cb->setVertexInput(0, 1, &vbufBinding);
    cb->draw(3);

    cb->endPass();

    update();
}

Il s’agit d’un widget qui demande en permanence des mises à jour, limité par la fréquence de rafraîchissement (vsync, en fonction de la fréquence de rafraîchissement de l’écran). Si un rendu continu n’est pas souhaité, l’appel à ` update()` dans ` render()` doit être supprimé et ne doit être effectué que lorsque la mise à jour du contenu affiché est nécessaire. Par exemple, si la rotation du cube doit être liée à la valeur d’un QSlider, il suffit alors de connecter le signal de changement de valeur du curseur à un slot ou à un lambda qui transmet la nouvelle valeur et appelle update().

Les shaders de sommets et de fragments sont fournis au format GLSL de type Vulkan et doivent d’abord être traités par l’infrastructure de shaders Qt. Pour ce faire, il faut soit exécuter manuellement l’outil en ligne de commande ` qsb `, soit utiliser la fonction `qt_add_shaders()` dans CMake. L’implémentation de QRhiWidget charge ces fichiers d’ .qsb prétraités fournis avec l’application. Consultez Qt Shader Tools pour plus d’informations sur l’infrastructure de traduction des shaders de Qt.

Le code source de ces shaders pourrait être le suivant :

color.vert

#version 440
layout(location = 0) in vec4 position;
layout(location = 1) in vec3 color;
layout(location = 0) out vec3 v_color;
layout(std140, binding = 0) uniform buf {
    mat4 mvp;
};

void main()
{
    v_color = color;
    gl_Position = mvp * position;
}

color.frag

#version 440
layout(location = 0) in vec3 v_color;
layout(location = 0) out vec4 fragColor;

void main()
{
    fragColor = vec4(v_color, 1.0);
}

Le résultat est un widget qui affiche ce qui suit :

Triangle multicolore sur fond vert

Pour un exemple complet, minimal et d'introduction, consultez l'exemple de widget RHI simple.

Pour un exemple offrant davantage de fonctionnalités et illustrant d’autres concepts, consultez l’exemple « Cube RHI Widget ».

QRhiWidget implique toujours un rendu dans une texture de support, et non directement dans la fenêtre (la surface ou le calque fourni par le système de fenêtrage pour la fenêtre native). Cela permet de composer correctement le contenu avec le reste de l’interface utilisateur basée sur des widgets, et d’offrir une API simple et compacte, facilitant ainsi la prise en main. Tout cela se fait au prix de ressources supplémentaires et d’un impact potentiel sur les performances. Cela s’avère souvent tout à fait acceptable dans la pratique, mais les utilisateurs avancés doivent garder à l’esprit les avantages et les inconvénients des différentes approches. Reportez-vous à l’exemple de fenêtre RHI et comparez-le à l’exemple de widget RHI simple pour plus de détails sur ces deux approches.

Le fait de replacer un QRhiWidget dans une hiérarchie de widgets appartenant à une autre fenêtre (widget de niveau supérieur), ou de faire du QRhiWidget lui-même un widget de niveau supérieur (en définissant son parent sur ` nullptr`), implique de modifier l’ QRhi associé (et éventuellement de détruire l’ancien) tandis que le QRhiWidget continue d’exister et de fonctionner normalement. Pour prendre en charge cette fonctionnalité, les implémentations robustes de QRhiWidget doivent également réimplémenter la fonction virtuelle releaseResources() et libérer leurs ressources QRhi, comme elles le font dans le destructeur. L’exemple de widget RHI « Cube » illustre cela en pratique.

Bien qu’il ne s’agisse pas d’un cas d’utilisation principal, QRhiWidget permet également d’intégrer du code de rendu utilisant directement une API graphique 3D telle que Vulkan, Metal, Direct 3D ou OpenGL. Consultez QRhiCommandBuffer::beginExternal() pour plus de détails sur l’enregistrement de commandes natives au sein d’un passage de rendu QRhi, ainsi que QRhiTexture::createFrom() pour découvrir comment encapsuler une texture native existante puis l’utiliser avec QRhi lors d’un passage de rendu ultérieur. Notez toutefois que la configurabilité de l’API graphique sous-jacente (ses fonctionnalités de périphérique ou de contexte, ses couches, ses extensions, etc.) sera limitée, car l’objectif principal de QRhiWidget est de fournir un environnement adapté au code de rendu basé sur QRhi, et non de prendre en charge des moteurs de rendu tiers arbitraires et potentiellement complexes.

Voir également QRhi, QShader, QOpenGLWidget, Exemple de widget RHI simple et Exemple de widget RHI « Cube ».

Documentation sur les types de membres

enum class QRhiWidget::Api

Spécifie l'API 3D et le backend d'QRhi à utiliser

ConstanteValeur
QRhiWidget::Api::Null0
QRhiWidget::Api::OpenGL1
QRhiWidget::Api::Metal2
QRhiWidget::Api::Vulkan3
QRhiWidget::Api::Direct3D114
QRhiWidget::Api::Direct3D125

Voir aussi QRhi.

enum class QRhiWidget::TextureFormat

Spécifie le format de la texture vers laquelle l'QRhiWidget effectue le rendu.

ConstanteValeurDescription
QRhiWidget::TextureFormat::RGBA80Voir QRhiTexture::RGBA8.
QRhiWidget::TextureFormat::RGBA16F1Voir « QRhiTexture::RGBA16F ».
QRhiWidget::TextureFormat::RGBA32F2Voir QRhiTexture::RGBA32F.
QRhiWidget::TextureFormat::RGB10A23Voir QRhiTexture::RGB10A2.

Voir également QRhiTexture.

Documentation relative aux propriétés

autoRenderTarget : bool

Paramètre actuel pour la gestion automatique des tampons de profondeur et de stencil ainsi que des cibles de rendu.

Par défaut, la valeur est « true ».

colorBufferFormat : TextureFormat

Cette propriété contrôle le format de la texture (ou du tampon de rendu) utilisée comme tampon de couleur. La valeur par défaut est TextureFormat::RGBA8. QRhiWidget prend en charge le rendu vers un sous-ensemble des formats pris en charge par QRhiTexture. Seuls les formats signalés comme pris en charge par QRhi::isTextureFormatSupported() doivent être spécifiés ; sinon, le rendu ne fonctionnera pas.

Remarque : définir un nouveau format alors que le widget est déjà initialisé et a été rendu implique que tous les objets QRhiGraphicsPipeline créés par le moteur de rendu risquent de devenir inutilisables, si le QRhiRenderPassDescriptor associé est désormais incompatible en raison du format de texture différent. À l’instar d’une modification dynamique de sampleCount, cela signifie que les implémentations de initialize() ou render() doivent alors veiller à libérer les pipelines existants et à en créer de nouveaux.

Fonctions d’accès :

QRhiWidget::TextureFormat colorBufferFormat() const
void setColorBufferFormat(QRhiWidget::TextureFormat format)

Signal de notification :

void colorBufferFormatChanged(QRhiWidget::TextureFormat format)

fixedColorBufferSize : QSize

La taille fixe, en pixels, de la texture associée à l'QRhiWidget. Ce paramètre est pertinent lorsqu'on souhaite une taille de texture fixe qui ne dépende pas de la taille du widget. Cette taille n'a aucun effet sur la géométrie du widget (sa taille et son emplacement dans la fenêtre de niveau supérieur), ce qui signifie que le contenu de la texture apparaîtra étiré (agrandi) ou réduit sur la zone du widget.

Par exemple, définir une taille exactement deux fois supérieure à celle du widget (en pixels) revient à effectuer un suréchantillonnage 2x (rendu à une résolution deux fois supérieure, puis mise à l'échelle implicite vers le bas lors de l'application de la texture au quad correspondant au widget dans la fenêtre). À l’inverse, définir une taille égale à la moitié de celle du widget revient à effectuer un rendu à la moitié de la résolution, puis à agrandir les résultats.

Par défaut, la valeur est une « null- QSize ». Une « null- QSize » ou une « empty- » signifie que la taille de la texture suit celle de l’ QRhiWidget. (texture size = widget size * device pixel ratio).

Remarque : le rapport de pixels de l’appareil (le facteur d’échelle du compositeur système) peut avoir un impact important sur les performances, car un facteur d’échelle de 2 (200 %) implique un rendu à une résolution deux fois supérieure, soit le double de ce que le développeur et le concepteur d’interface perçoivent comme la taille du widget, puis une réduction effective de l’échelle du contenu, de la même manière que ce qui se produit lorsque cette propriété est définie sur le double de la taille en pixels du widget sur un système où le rapport de pixels de l’appareil est égal à 1. Par conséquent, cette propriété ne devrait être que rarement utilisée avec des tailles supérieures à la taille en pixels du widget, car de nombreux systèmes de bureau modernes n’ont ni le besoin ni la marge de performances nécessaires pour cela, lorsque le système utilise de toute façon un rapport de pixels de l’appareil supérieur à 1. Au contraire, le principal cas d’utilisation de cette propriété consiste à définir une taille plus petite, afin d’effectuer le rendu à une résolution raisonnablement inférieure plutôt que de suivre aveuglément la géométrie de la fenêtre, quelle que soit sa taille.

Fonctions d’accès :

QSize fixedColorBufferSize() const
void setFixedColorBufferSize(QSize pixelSize)
void setFixedColorBufferSize(int w, int h)

Signal de notification :

void fixedColorBufferSizeChanged(const QSize &pixelSize)

mirrorVertically : bool

Lorsque cette option est activée, l'image est inversée autour de l'axe X lors de la superposition de la texture de fond de l'QRhiWidget avec le reste du contenu du widget dans la fenêtre de niveau supérieur.

La valeur par défaut est « false ».

Fonctions d'accès :

bool isMirrorVerticallyEnabled() const
void setMirrorVertically(bool enabled)

Signal de notification :

void mirrorVerticallyChanged(bool enabled)

sampleCount : int

Cette propriété contrôle le nombre d'échantillons pour l'anticrénelage multi-échantillon (MSAA). Par défaut, la valeur est « 1 », ce qui signifie que le MSAA est désactivé.

Les valeurs valides sont 1, 4, 8, et parfois 16 et 32. La fonction ` QRhi::supportedSampleCounts()` permet de connaître les nombres d'échantillons pris en charge lors de l'exécution, mais en général, les applications doivent demander 1 (pas de MSAA), 4x (MSAA normal) ou 8x (MSAA élevé).

Remarque : la définition d’une nouvelle valeur implique que tous les objets ` QRhiGraphicsPipeline ` créés par le moteur de rendu doivent désormais utiliser le même nombre d’échantillons. Les objets ` QRhiGraphicsPipeline ` existants créés avec un nombre d’échantillons différent ne doivent plus être utilisés. Lorsque la valeur change, tous les tampons de couleur et de profondeur-stencil sont détruits puis recréés automatiquement, et la fonction ` initialize()` est à nouveau appelée. Cependant, lorsque ` autoRenderTarget ` est défini sur ` false`, il appartient à l’application de gérer cela en ce qui concerne le tampon de profondeur-stencil ou les tampons de couleur supplémentaires.

Modifier le nombre d’échantillons de la valeur par défaut 1 à une valeur supérieure implique que ` colorTexture()` devient ` nullptr ` et que ` msaaColorBuffer()` commence à renvoyer un objet valide. Revenir à 1 (ou 0) implique l’inverse : lors du prochain appel à ` initialize()`, ` msaaColorBuffer()` renverra ` nullptr`, tandis que ` colorTexture()` redevient valide. De plus, la fonction resolveTexture() renvoie une valeur valide (non multi-échantillonnée) QRhiTexture dès lors que le nombre d’échantillons est supérieur à 1 (c’est-à-dire lorsque le MSAA est activé).

Fonctions d’accès :

int sampleCount() const
void setSampleCount(int samples)

Signal de notification :

void sampleCountChanged(int samples)

Voir également msaaColorBuffer() et resolveTexture().

Documentation des fonctions membres

[explicit] QRhiWidget::QRhiWidget(QWidget *parent = nullptr, Qt::WindowFlags f = {})

Crée un widget qui est un enfant de ` parent`, avec les indicateurs de widget définis sur ` f`.

[override virtual noexcept] QRhiWidget::~QRhiWidget()

Destructeur.

QRhiWidget::Api QRhiWidget::api() const

Renvoie l'API graphique actuellement définie (backend «QRhi »).

Voir aussi setApi().

[protected] QRhiTexture *QRhiWidget::colorTexture() const

Renvoie la texture servant de tampon de couleur pour le widget.

Ne doit être appelée qu’à partir de ` initialize()` et ` render()`.

Contrairement au tampon de profondeur-stencil et à la fonction ` QRhiRenderTarget`, cette texture est toujours disponible et gérée par la fonction ` QRhiWidget`, quelle que soit la valeur de ` autoRenderTarget`.

Remarque : lorsque l’ sampleCount est supérieur à 1, et que l’anticrénelage multi-échantillonnage est donc activé, la valeur renvoyée est nullptr. Il faut alors interroger l’ QRhiRenderBuffer en appelant msaaColorBuffer().

Remarque : la taillede la texture de support et le nombre d’échantillons peuvent également être interrogés via l’ QRhiRenderTarget renvoyé par renderTarget(). Cela peut s’avérer plus pratique et plus concis que d’interroger l’ QRhiTexture ou QRhiRenderBuffer, car cela fonctionne indépendamment du fait que le multisampling soit utilisé ou non.

Voir également msaaColorBuffer(), depthStencilBuffer(), renderTarget() et resolveTexture().

[protected] QRhiRenderBuffer *QRhiWidget::depthStencilBuffer() const

Renvoie le tampon de profondeur-stencil utilisé par le rendu du widget.

Ne doit être appelé qu'à partir de ` initialize()` et ` render()`.

Disponible uniquement lorsque autoRenderTarget est true. Sinon, la valeur renvoyée est nullptr et il appartient à la réimplémentation de initialize() de créer et de gérer un tampon de profondeur-stencil ainsi qu’un QRhiTextureRenderTarget.

Voir également colorTexture() et renderTarget().

[override virtual protected] bool QRhiWidget::event(QEvent *e)

Réimplémente : ` QWidget::event(QEvent *event)`.

[signal] void QRhiWidget::frameSubmitted()

Ce signal est émis une fois que la fenêtre de niveau supérieur du widget a terminé sa composition et qu'elle a atteint l'ét submitted a frame.

QImage QRhiWidget::grabFramebuffer() const

Affiche une nouvelle image, relit le contenu de la texture et le renvoie sous la forme d'un objet ` QImage`.

En cas d’erreur, une instance ` QImage ` nulle est renvoyée.

L’ QImage renvoyé aura un format de type « QImage::Format_RGBA8888 », « QImage::Format_RGBA16FPx4 », « QImage::Format_RGBA32FPx4 » ou « QImage::Format_BGR30 », selon la fonction « colorBufferFormat() ».

QRhiWidget ne connaît pas l’approche du moteur de rendu en matière de fusion et de composition, et ne peut donc pas savoir si la sortie comporte une alpha pré-multipliée dans les valeurs de couleur RVB. Ainsi, les formats _Premultiplied et QImage ne sont jamais utilisés pour la valeur QImage renvoyée, même lorsque cela serait approprié. Il appartient à l’appelant de réinterpréter les données résultantes comme il le juge bon.

Remarque : cette fonction peut également être appelée lorsque le ` QRhiWidget ` n’est pas ajouté à une hiérarchie de widgets appartenant à une fenêtre de niveau supérieur à l’écran. Cela permet de générer une image à partir d’un rendu 3D hors écran.

La fonction est nommée `grabFramebuffer()` par souci de cohérence avec ` QOpenGLWidget ` et ` QQuickWidget`. Ce n’est pas le seul moyen d’extraire des données d’image côté CPU à partir du contenu de ` QRhiWidget` : l’appel de ` QWidget::grab()` sur un ` QRhiWidget`, ou l’un de ses ancêtres, fonctionne également (renvoyant un ` QPixmap`). Outre le fait de fonctionner directement avec QImage, un autre avantage de grabFramebuffer() est qu’il peut être légèrement plus performant, simplement parce qu’il n’a pas besoin de passer par le reste de l’infrastructure QWidget mais peut immédiatement déclencher le rendu d’une nouvelle image, puis effectuer la lecture.

Voir également setColorBufferFormat().

[virtual protected] void QRhiWidget::initialize(QRhiCommandBuffer *cb)

Appelée lors de la première initialisation du widget, lorsque la taille, le format ou le nombre d’échantillons de la texture associée change, ou lorsque l’ QRhi et la texture changent pour quelque raison que ce soit. La fonction doit gérer (créer si ce n’est pas encore fait, ajuster et reconstruire si la taille a changé) les ressources graphiques utilisées par le code de rendu dans render().

Pour interroger l'QRhi, l'QRhiTexture et d'autres objets associés, appelez rhi(), colorTexture(), depthStencilBuffer() et renderTarget().

Lorsque la taille du widget change, l’objet ` QRhi `, la texture du tampon de couleur et les objets des tampons de profondeur et de stencil sont tous les mêmes instances (les accesseurs renvoient donc les mêmes pointeurs) qu’auparavant, mais les tampons de couleur et de profondeur/stencil auront probablement été reconstruits, ce qui signifie que l’objet ` size ` et la ressource de texture native sous-jacente peuvent être différents de ceux de la dernière invocation.

Les réimplémentations doivent également tenir compte du fait que l’objet ` QRhi ` et la texture du tampon de couleur peuvent changer entre deux appels de cette fonction. Un cas particulier où les objets seront différents se produit lorsqu’on effectue un ` grabFramebuffer()` avec un widget qui n’est pas encore affiché, puis qu’on rend ce widget visible à l’écran au sein d’un widget de niveau supérieur. Dans ce cas, la capture s’effectuera avec une ` QRhi ` dédiée, qui sera ensuite remplacée par la ` QRhi ` associée à la fenêtre de niveau supérieur lors des appels suivants à `initialize()` et ` render()`. Un autre cas, plus courant, se produit lorsque le widget est réaffecté à une nouvelle fenêtre de niveau supérieur. Dans ce cas, l’instance ` QRhi ` et toutes les ressources associées gérées par l’instance ` QRhiWidget ` seront des instances différentes de celles d’auparavant lors de l’appel suivant de cette fonction. Il est alors important que toutes les ressources existantes de type ` QRhi ` créées précédemment par la sous-classe soient détruites, car elles appartiennent à l’instance ` QRhi ` précédente qui ne doit plus être utilisée par le widget.

Lorsque ` autoRenderTarget ` est défini sur ` true` (ce qui est la valeur par défaut), un ` QRhiRenderBuffer ` de profondeur-stencil et un ` QRhiTextureRenderTarget ` associés à ` colorTexture()` (ou ` msaaColorBuffer()`) ainsi que le tampon de profondeur-stencil sont créés et gérés automatiquement. Les réimplémentations de `initialize()` et ` render()` peuvent interroger ces objets via ` depthStencilBuffer()` et ` renderTarget()`. Lorsque ` autoRenderTarget ` est défini sur ` false`, ces objets ne sont plus créés ni gérés automatiquement. C’est alors à l’implémentation de la fonction `initialize()` qu’il reviendra de créer les tampons et de configurer la cible de rendu comme elle le juge opportun. Lors de la gestion manuelle d’attachements de couleur ou de profondeur-stencil supplémentaires pour la cible de rendu, leur taille et leur nombre d’échantillons doivent toujours correspondre à ceux de ` colorTexture()` / ` msaaColorBuffer()`, sous peine de provoquer des erreurs de rendu ou de validation de l’API 3D.

Les ressources graphiques créées par la sous-classe doivent être libérées dans l’implémentation du destructeur de la sous-classe.

cb est l’ QRhiCommandBuffer pour l’image courante du widget. La fonction est appelée lors de l’enregistrement d’une image, mais sans passe de rendu active. Le tampon de commande est principalement fourni pour permettre la mise en file d’attente d’ resource updates s sans passer par render().

Voir également ` render()` ().

bool QRhiWidget::isDebugLayerEnabled() const

Renvoie « true » si une couche de débogage ou de validation sera sollicitée, le cas échéant, pour l'API graphique utilisée.

Voir également setDebugLayerEnabled().

[protected] QRhiRenderBuffer *QRhiWidget::msaaColorBuffer() const

Renvoie le tampon de rendu servant de tampon de couleur multi-échantillonnage pour le widget.

Ne doit être appelée qu’à partir de ` initialize()` et ` render()`.

Lorsque sampleCount est supérieur à 1, et que l’anticrénelage multisample est donc activé, la fonction QRhiRenderBuffer renvoie un nombre d’échantillons correspondant et sert de tampon de couleur. Les pipelines graphiques utilisés pour effectuer le rendu dans ce tampon doivent être créés avec le même nombre d’échantillons, et le nombre d’échantillons du tampon de profondeur-stencil doit également correspondre. Le contenu multi-échantillon doit être résolu dans la texture renvoyée par la fonction ` resolveTexture()`. Lorsque ` autoRenderTarget ` est défini sur ` true`, la fonction ` renderTarget()` est automatiquement configurée pour effectuer cette opération, en définissant `msaaColorBuffer()` comme ` renderbuffer ` de l’attachement de couleur 0 et ` resolveTexture()` comme son ` resolveTexture`.

Lorsque le MSAA n’est pas utilisé, la valeur renvoyée est nullptr. Il convient alors d’utiliser colorTexture() à la place.

Selon l’API graphique 3D sous-jacente, il se peut qu’il n’y ait aucune différence pratique entre les textures multi-échantillonnées et les tampons de rendu de couleur dont le nombre d’échantillons est supérieur à 1 (QRhi peut simplement mapper les deux au même type de ressource native). Certaines API plus anciennes peuvent toutefois faire la distinction entre les textures et les renderbuffers. Afin de prendre en charge OpenGL ES 3.0, où les renderbuffers multi-échantillons sont disponibles, mais pas les textures multi-échantillons, QRhiWidget effectue toujours le MSAA en utilisant une texture multi-échantillon QRhiRenderBuffer comme attachement de couleur (et jamais une texture multi-échantillon QRhiTexture).

Remarque : la taillede la texture de support et le nombre d’échantillons peuvent également être interrogés via l’ QRhiRenderTarget renvoyé par renderTarget(). Cette méthode peut s’avérer plus pratique et plus concise que l’interrogation à partir de QRhiTexture ou QRhiRenderBuffer, car elle fonctionne indépendamment du fait que le multisampling soit utilisé ou non.

Voir également colorTexture(), depthStencilBuffer(), renderTarget() et resolveTexture().

[override virtual protected] void QRhiWidget::paintEvent(QPaintEvent *e)

Réimplémente : ` QWidget::paintEvent(QPaintEvent *event)`.

Gère les événements de dessin.

L'appel de ` QWidget::update()` entraîne l'envoi d'un événement de dessin ` e`, ce qui provoque l'appel de cette fonction. L'envoi de l'événement est asynchrone et se produira à un moment donné après le retour de ` update()`. Cette fonction appellera alors, après quelques préparatifs, la fonction virtuelle ` render()` pour mettre à jour le contenu de la texture associée au ` QRhiWidget`. La fenêtre de niveau supérieur du widget effectuera ensuite la composition de la texture avec le reste de la fenêtre.

[virtual protected] void QRhiWidget::releaseResources()

Appelée lorsqu'il est nécessaire de libérer prématurément les ressources graphiques.

Cela ne se produit généralement pas pour un « QRhiWidget » ajouté à la hiérarchie des enfants d’un widget de niveau supérieur, car il y reste alors jusqu’à la fin de sa durée de vie et de celle du widget de niveau supérieur. Ainsi, dans de nombreux cas, il n’est pas nécessaire de réimplémenter cette fonction, par exemple parce que l’application ne comporte qu’un seul widget de niveau supérieur (fenêtre native). Cependant, en cas de changement de parent du widget (ou d’un de ses ancêtres), la réimplémentation de cette fonction deviendra nécessaire dans des sous-classes d’ QRhiWidget s robustes et bien écrites.

Lorsque cette fonction est appelée, l’implémentation doit détruire toutes les ressources de type ` QRhi ` (objets `QRhiBuffer`, ` QRhiTexture`, etc.), de la même manière qu’elle est censée le faire dans le destructeur. Il sera également nécessaire de mettre à zéro les pointeurs, d’utiliser un pointeur intelligent ou de définir un indicateur « resources-invalid », car la fonction ` initialize()` finira par être appelée par la suite. Notez toutefois qu’il est incorrect de reporter la libération des ressources à l’appel ultérieur de ` initialize()`. Si cette fonction est appelée, la ressource doit être libérée avant le retour. Notez également que l’implémentation de cette fonction ne remplace pas le destructeur de la classe (ni les pointeurs intelligents) : les ressources graphiques doivent toujours être libérées dans les deux cas.

Consultez l’exemple du widget Cube RHI pour voir cela en action. Dans cet exemple, le bouton qui fait basculer l’ QRhiWidget entre le statut de widget enfant (lorsqu’il possède un widget parent) et celui de widget de niveau supérieur (lorsqu’il n’a pas de widget parent) déclenchera l’appel de cette fonction, car le widget de niveau supérieur associé, la fenêtre native, et l’ QRhi changent tous au cours du cycle de vie de l’ QRhiWidget, l’ QRhi précédemment utilisé étant détruit, ce qui implique une libération anticipée des ressources associées gérées par l’ QRhiWidget toujours actif.

Cette fonction est également appelée lorsque ` grabFramebuffer()` est utilisée avec un ` QRhiWidget ` qui n’est pas ajouté à une fenêtre visible, c’est-à-dire que le rendu est effectué hors écran. Si, par la suite, cet QRhiWidget est rendu visible ou ajouté à une hiérarchie de widgets visible, l’ QRhi associé passera de celui utilisé temporairement pour le rendu hors écran à celui dédié à la fenêtre, ce qui déclenchera également cette fonction.

Voir également initialize().

[virtual protected] void QRhiWidget::render(QRhiCommandBuffer *cb)

Appelée lorsque le contenu du widget (c'est-à-dire le contenu de la texture) doit être mis à jour.

Il y a toujours au moins un appel à ` initialize()` avant que cette fonction ne soit appelée.

Pour demander des mises à jour, appelez ` QWidget::update()`. L'appel de ` update()` depuis l'intérieur de `render()` entraînera une mise à jour continue, limitée par la synchronisation verticale (vsync).

cb est la fonction ` QRhiCommandBuffer ` pour l’image actuelle du widget. La fonction est appelée alors qu’une image est en cours d’enregistrement, mais sans passe de rendu active.

Voir également initialize().

[signal] void QRhiWidget::renderFailed()

Ce signal est émis chaque fois que le widget est censé effectuer un rendu sur sa texture de support (soit à la suite d’un appel à ` widget update `, soit à la suite d’un appel à ` grabFramebuffer()`), mais qu’aucune texture de support ( QRhi ) n’est disponible pour le widget, probablement en raison de problèmes liés à la configuration graphique.

Ce signal peut être émis plusieurs fois lorsqu’un problème survient. Ne partez pas du principe qu’il n’est émis qu’une seule fois. Utilisez ` Qt::SingleShotConnection ` si le code de gestion des erreurs ne doit être notifié qu’une seule fois.

[protected] QRhiRenderTarget *QRhiWidget::renderTarget() const

Renvoie l'objet cible de rendu qui doit être utilisé avec la fonction ` QRhiCommandBuffer::beginPass()` dans les réimplémentations de la fonction ` render()`.

Ne doit être appelée qu’à partir de ` initialize()` et ` render()`.

Disponible uniquement lorsque autoRenderTarget est true. Sinon, la valeur renvoyée est nullptr et il appartient à la réimplémentation de initialize() de créer et de gérer un tampon de profondeur-stencil ainsi qu’un QRhiTextureRenderTarget.

Lors de la création d’ graphics pipelines, un QRhiRenderPassDescriptor est nécessaire. Celui-ci peut être obtenu à partir de l’ QRhiTextureRenderTarget renvoyé en appelant renderPassDescriptor().

Voir également colorTexture() et depthStencilBuffer().

[override virtual protected] void QRhiWidget::resizeEvent(QResizeEvent *e)

Réimplémente : QWidget::resizeEvent(QResizeEvent *event).

Gère les événements de redimensionnement transmis via le paramètre d'événement e. Appelle la fonction virtuelle initialize().

Remarque : Évitez de redéfinir cette fonction dans les classes dérivées. Si cela n'est pas possible, assurez-vous que l'implémentation de ` QRhiWidget` soit également appelée. Sinon, l'objet texture sous-jacent et les ressources associées ne seront pas redimensionnés correctement, ce qui entraînera un rendu incorrect.

[protected] QRhiTexture *QRhiWidget::resolveTexture() const

Renvoie la texture non multisample vers laquelle le contenu multisample est converti.

Le résultat est « nullptr » lorsque l'anticrénelage multisample n'est pas activé.

Ne doit être appelée qu’à partir de ` initialize()` et ` render()`.

Lorsque le MSAA est activé, il s’agit de la texture qui est composée avec le reste du contenu de l’ QWidget à l’écran. Cependant, le rendu de QRhiWidget doit cibler l’ QRhiRenderBuffer (multi-échantillon) renvoyée par msaaColorBuffer(). Lorsque autoRenderTarget est true, cela est géré par l’ QRhiRenderTarget renvoyée par renderTarget(). Sinon, il appartient au code de la sous-classe de configurer correctement un objet cible de rendu avec à la fois le tampon de couleur et les textures de résolution.

Voir également colorTexture().

[protected] QRhi *QRhiWidget::rhi() const

Renvoie l'objet ` QRhi ` actuel.

Ne doit être appelé qu'à partir des méthodes initialize() et render().

void QRhiWidget::setApi(QRhiWidget::Api api)

Définit l'API graphique et le backend d'QRhi ation à utiliser sur api.

Avertissement : cette fonction doit être appelée suffisamment tôt, avant que le widget ne soit ajouté à une hiérarchie de widgets et affiché à l’écran. Par exemple, veillez à appeler la fonction dans le constructeur de la sous-classe. Si elle est appelée trop tard, la fonction n’aura aucun effet.

La valeur par défaut dépend de la plateforme : Metal sur macOS et iOS, Direct 3D 11 sur Windows, OpenGL dans les autres cas.

L’ api ne peut être définie qu’une seule fois pour le widget et sa fenêtre de niveau supérieur ; une fois cette opération effectuée et prise en compte, la fenêtre ne peut utiliser que cette API et ce backend QRhi pour le rendu. Tenter de définir une autre valeur ou d’ajouter une autre QRhiWidget avec une api différente ne fonctionnera pas comme prévu.

Voir également setColorBufferFormat(), setDebugLayerEnabled() et api().

[protected] void QRhiWidget::setAutoRenderTarget(bool enabled)

Détermine si le widget crée et gère automatiquement un tampon de profondeur-stencil ( QRhiRenderBuffer ) et un tampon de texture de couleur ( QRhiTextureRenderTarget ). La valeur par défaut est « true ».

En mode automatique, la taille et le nombre d’échantillons du tampon de profondeur-stencil suivent les paramètres de la texture du tampon de couleur. En mode non automatique, les fonctions ` renderTarget()` et ` depthStencilBuffer()` renvoient toujours ` nullptr ` ; il appartient alors à l’implémentation de la fonction ` initialize()` de l’application de se charger de la configuration et de la gestion de ces objets.

Appelez cette fonction en définissant enabled sur false dès le début, par exemple dans le constructeur de la classe dérivée, afin de désactiver le mode automatique.

void QRhiWidget::setDebugLayerEnabled(bool enable)

Appelle la couche de débogage ou de validation de l'API graphique sous-jacente lorsque la valeur de « enable » est « true ».

Avertissement : cette fonction doit être appelée suffisamment tôt, avant que le widget ne soit ajouté à une hiérarchie de widgets et affiché à l'écran. Par exemple, veillez à appeler la fonction dans le constructeur de la sous-classe. Si elle est appelée trop tard, la fonction n'aura aucun effet.

Applicable à Vulkan et Direct 3D.

Par défaut, cette fonction est désactivée.

Voir également ` setApi()` et ` isDebugLayerEnabled()`.

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