Sur cette page

QRhi Class

Abstraction accélérée des API graphiques 2D/3D. En savoir plus...

En-tête : #include <rhi/qrhi.h>
CMake : find_package(Qt6 REQUIRED COMPONENTS GuiPrivate)
target_link_libraries(mytarget PRIVATE Qt6::GuiPrivate)
qmake : QT += gui-private
Depuis : Qt 6.6

Types publics

(since 6.10) AdapterList
enum BeginFrameFlag { }
flags BeginFrameFlags
enum EndFrameFlag { SkipPresent }
flags EndFrameFlags
enum Feature { MultisampleTexture, MultisampleRenderBuffer, DebugMarkers, Timestamps, Instancing, …, ShaderDrawParameters }
enum Flag { EnableDebugMarkers, EnableTimestamps, PreferSoftwareRenderer, EnablePipelineCacheDataSave, SuppressSmokeTestWarnings }
flags Flags
enum FrameOpResult { FrameOpSuccess, FrameOpError, FrameOpSwapChainOutOfDate, FrameOpDeviceLost }
enum Implementation { Null, Vulkan, OpenGLES2, D3D11, D3D12, Metal }
enum ResourceLimit { TextureSizeMin, TextureSizeMax, MaxColorAttachments, FramesInFlight, MaxAsyncReadbackFrames, …, ShadingRateImageTileSize }

Fonctions publiques

~QRhi()
void addCleanupCallback(const QRhi::CleanupCallback &callback)
void addCleanupCallback(const void *key, const QRhi::CleanupCallback &callback)
QRhi::Implementation backend() const
const char *backendName() const
QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags = {})
QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags = {})
QMatrix4x4 clipSpaceCorrMatrix() const
int currentFrameSlot() const
QRhiDriverInfo driverInfo() const
QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags = {})
QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags = {})
QRhi::FrameOpResult finish()
bool isClipDepthZeroToOne() const
bool isDeviceLost() const
bool isFeatureSupported(QRhi::Feature feature) const
bool isRecordingFrame() const
bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags = {}) const
bool isYUpInFramebuffer() const
bool isYUpInNDC() const
bool makeThreadLocalNativeContextCurrent()
const QRhiNativeHandles *nativeHandles()
QRhiBuffer *newBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, quint32 size)
QRhiComputePipeline *newComputePipeline()
QRhiGraphicsPipeline *newGraphicsPipeline()
QRhiRenderBuffer *newRenderBuffer(QRhiRenderBuffer::Type type, const QSize &pixelSize, int sampleCount = 1, QRhiRenderBuffer::Flags flags = {}, QRhiTexture::Format backingFormatHint = QRhiTexture::UnknownFormat)
QRhiSampler *newSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter, QRhiSampler::Filter mipmapMode, QRhiSampler::AddressMode addressU, QRhiSampler::AddressMode addressV, QRhiSampler::AddressMode addressW = QRhiSampler::Repeat)
QRhiShaderResourceBindings *newShaderResourceBindings()
(since 6.9) QRhiShadingRateMap *newShadingRateMap()
QRhiSwapChain *newSwapChain()
QRhiTexture *newTexture(QRhiTexture::Format format, const QSize &pixelSize, int sampleCount = 1, QRhiTexture::Flags flags = {})
QRhiTexture *newTexture(QRhiTexture::Format format, int width, int height, int depth, int sampleCount = 1, QRhiTexture::Flags flags = {})
QRhiTexture *newTextureArray(QRhiTexture::Format format, int arraySize, const QSize &pixelSize, int sampleCount = 1, QRhiTexture::Flags flags = {})
QRhiTextureRenderTarget *newTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc, QRhiTextureRenderTarget::Flags flags = {})
QRhiResourceUpdateBatch *nextResourceUpdateBatch()
QByteArray pipelineCacheData()
void releaseCachedResources()
void removeCleanupCallback(const void *key)
int resourceLimit(QRhi::ResourceLimit limit) const
void setPipelineCacheData(const QByteArray &data)
(since 6.9) void setQueueSubmitParams(QRhiNativeHandles *params)
QRhiStats statistics() const
QList<int> supportedSampleCounts() const
(since 6.9) QList<QSize> supportedShadingRates(int sampleCount) const
QThread *thread() const
int ubufAligned(int v) const
int ubufAlignment() const

Membres publics statiques

const char *backendName(QRhi::Implementation impl)
QRhi *create(QRhi::Implementation impl, QRhiInitParams *params, QRhi::Flags flags, QRhiNativeHandles *importDevice, QRhiAdapter *adapter)
QRhi *create(QRhi::Implementation impl, QRhiInitParams *params, QRhi::Flags flags = {}, QRhiNativeHandles *importDevice = nullptr)
(since 6.10) QRhi::AdapterList enumerateAdapters(QRhi::Implementation impl, QRhiInitParams *params, QRhiNativeHandles *nativeHandles = nullptr)
int mipLevelsForSize(const QSize &size)
bool probe(QRhi::Implementation impl, QRhiInitParams *params)
QSize sizeForMipLevel(int mipLevel, const QSize &baseLevelSize)
QRhiSwapChainProxyData updateSwapChainProxyData(QRhi::Implementation impl, QWindow *window)

Description détaillée

L'interface matérielle de rendu Qt est une abstraction des API graphiques à accélération matérielle, telles que OpenGL, OpenGL ES, Direct3D, Metal et Vulkan.

Avertissement : la famille de classes QRhi du module Qt GUI, notamment 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 utilisée pour le développement de l’application. 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.). Pour utiliser ces classes dans une application, liez-vous à Qt::GuiPrivate (si vous utilisez CMake) et incluez les en-têtes portant le préfixe rhi, par exemple #include <rhi/qrhi.h>.

Chaque instance QRhi s’appuie sur un backend dédié à une API graphique spécifique. Le choix du backend s’effectue à l’exécution et relève de l’application ou de la bibliothèque qui crée l’instance QRhi. Certains backends sont disponibles sur plusieurs plateformes (OpenGL, Vulkan, Null), tandis que les API spécifiques à une plateforme donnée ne sont disponibles que lorsqu’on s’exécute sur la plateforme en question (Metal sur macOS/iOS, Direct3D sur Windows).

Les backends actuellement disponibles sont les suivants :

  • OpenGL 2.1 / OpenGL ES 2.0 ou versions plus récentes. Certaines extensions et fonctionnalités récentes de la spécification de base sont utilisées lorsqu’elles sont disponibles, par exemple pour activer les framebuffers à échantillonnage multiple ou les shaders de calcul. Le fonctionnement dans des contextes de profil de base est également pris en charge. Si nécessaire, les applications peuvent interroger l’ feature flags à l’exécution pour vérifier les fonctionnalités qui ne sont pas prises en charge dans le contexte OpenGL sous-jacent au QRhi. Le backend OpenGL s’appuie sur QOpenGLContext, QOpenGLFunctions et l’infrastructure multiplateforme associée du module Qt GUI.
  • Direct3D 11.2 et versions ultérieures (avec DXGI 1.3 et versions ultérieures), utilisant le Shader Model 5.0 ou une version ultérieure. Lorsque le runtime D3D ne prend pas en charge les fonctionnalités de la version 11.2 ou le Shader Model 5.0, l’initialisation à l’aide d’un périphérique graphique accéléré échouera, mais l’utilisation de l’adaptateur logiciel reste possible.
  • Direct3D 12 sous Windows 10 version 1703 et versions ultérieures, avec Shader Model 5.0 ou version ultérieure. Qt nécessite la présence d’ID3D12Device2, d’où l’exigence d’au moins la version 1703 de Windows 10. Le périphérique D3D12 est créé par défaut en spécifiant un niveau de fonctionnalités minimum de D3D_FEATURE_LEVEL_11_0.
  • Metal 1.2 ou version ultérieure.
  • Vulkan 1.0 ou version plus récente, utilisant éventuellement certaines fonctionnalités de niveau Vulkan 1.1.
  • Null, un backend « factice » qui n'émet aucun appel graphique.

Afin de permettre l’écriture unique du code de shader dans les applications et bibliothèques Qt, tous les shaders doivent être écrits dans un langage unique, qui est ensuite compilé en SPIR-V. Des versions pour divers langages de shader sont alors générées à partir de celui-ci, ainsi que des informations de réflexion (entrées, sorties, ressources de shader). Le tout est ensuite regroupé dans des instances d’ QShader s facilement et efficacement sérialisables. Les compilateurs et outils permettant de générer ces shaders ne font pas partie de QRhi ni du module « Qt GUI », mais les classes principales permettant d’utiliser ces shaders, QShader et QShaderDescription, en font partie. Les API et outils permettant d’effectuer la compilation et la traduction font partie du module « Qt Shader Tools ».

Consultez l’exemple « RHI Window » pour découvrir un exemple d’introduction à la création d’une application portable et multiplateforme qui effectue un rendu 3D accéléré sur une carte graphique QWindow à l’aide de QRhi.

Aperçu de l’API

Pour vous donner un aperçu rapide de l’API à l’aide d’un exemple court mais complet ne nécessitant aucune configuration liée aux fenêtres, voici une application multiplateforme complète et exécutable qui effectue le rendu de 20 images hors écran, puis enregistre les images générées dans des fichiers après avoir relu le contenu des textures depuis le GPU. Pour un exemple de rendu à l’écran, qui nécessite la configuration d’une « QWindow » et d’une « swapchain », reportez-vous à l’exemple RHI Window.

Par souci de concision, l’initialisation de QRhi s’effectue en fonction de la plateforme : le code d’exemple présenté ici choisit Direct 3D 12 sous Windows, Metal sous macOS et iOS, et Vulkan dans les autres cas. OpenGL et Direct 3D 11 ne sont jamais utilisés par cette application, mais leur prise en charge pourrait être ajoutée en quelques lignes de code supplémentaires.

#include <QGuiApplication>
#include <QImage>
#include <QFile>
#include <rhi/qrhi.h>

int main(int argc, char**argv)
{
    QGuiApplication app(argc, argv);

#if QT_CONFIG(vulkan)
    QVulkanInstance inst;
#endif
    std::unique_ptr<QRhi> rhi;
#if defined(Q_OS_WIN)
    QRhiD3D12InitParams params;
    rhi.reset(QRhi::create(QRhi::D3D12, &params));
#elif QT_CONFIG(metal)
    QRhiMetalInitParams params;
    rhi.reset(QRhi::create(QRhi::Metal, &params));
#elif QT_CONFIG(vulkan)
    inst.setExtensions(QRhiVulkanInitParams::preferredInstanceExtensions());
    if (inst.create()) {
        QRhiVulkanInitParams params;
        params.inst = &inst;
        rhi.reset(QRhi::create(QRhi::Vulkan, &params));
    } else {
        qFatal("Failed to create Vulkan instance");
    }
#endif
    if (rhi)
        qDebug() << rhi->backendName() << rhi->driverInfo();
   sinon
        qFatal("Failed to initialize RHI");

   float rotation = 0.0f;
    float opacity = 1.0f;
    int opacityDir = 1;

    std::unique_ptr<QRhiTexture> tex(rhi->newTexture(QRhiTexture::RGBA8,
                                                     QSize(1280, 720),
                                                     1,
                                                     QRhiTexture::RenderTarget | QRhiTexture::UsedAsTransferSource));
    tex->create();
    std::unique_ptr<QRhiTextureRenderTarget> rt(rhi->newTextureRenderTarget({ tex.get() }));
    std::unique_ptr<QRhiRenderPassDescriptor> rp(rt->newCompatibleRenderPassDescriptor());
    rt->setRenderPassDescriptor(rp.get());
    rt->create();

    QMatrix4x4 viewProjection = rhi->clipSpaceCorrMatrix();
    viewProjection.perspective(45.0f, 1280 / 720.f, 0.01f, 1000.0f);
    viewProjection.translate(0, 0,-4) ;

    static float vertexData[] = { // Y vers le haut, sens antihoraire
        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,
    };

    std::unique_ptr<QRhiBuffer> vbuf(rhi->newBuffer(QRhiBuffer::Immutable,
                                                    QRhiBuffer::VertexBuffer,
                                                    sizeof(vertexData)));
    vbuf->create();

    std::unique_ptr<QRhiBuffer> ubuf(rhi->newBuffer(QRhiBuffer::Dynamic,
                                                    QRhiBuffer::UniformBuffer,
                                                    64 + 4));
    ubuf->create();

    std::unique_ptr<QRhiShaderResourceBindings> srb(rhi->newShaderResourceBindings());
    srb->setBindings({
        QRhiShaderResourceBinding::uniformBuffer(0,
                                                 QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage,
                                                 ubuf.get())
    });
    srb->create();

    std::unique_trace<QRhiGraphicsPipeline> ps(rhi->newGraphicsPipeline());
    QRhiGraphicsPipeline::TargetBlendpremulAlphaBlend;
    premulAlphaBlend.enable = true;
    ps->setTargetBlends({ premulAlphaBlend });
    static auto getShader = [](const QString&name) {
        QFile f(name);
        return f.open(QIODevice::ReadOnly) ? QShader::fromSerialized(f.readAll()) : QShader();
    };
    ps->setShaderStages({
        { QRhiShaderStage::Vertex, getShader(QLatin1String("color.vert.qsb")) },
        { QRhiShaderStage::Fragment, getShader(QLatin1String("color.frag.qsb")) }
    });
    QRhiVertexInputLayout inputLayout;
    inputLayout.setBindings({
        { 5 * sizeof(float) }
    });
    inputLayout.setAttributes({
        { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
        { 0, 1, QRhiVertexInputAttribute::Float3, 2 * sizeof(float) }
    });
    ps->setVertexInputLayout(inputLayout);
    ps->setShaderResourceBindings(srb.get());
    ps->setRenderPassDescriptor(rp.get());
    ps->create();

    QRhiCommandBuffer*cb;
    for (int frame = 0; frame < 20;++frame) {
        rhi->beginOffscreenFrame(&cb);

        QRhiResourceUpdateBatch*u = rhi->nextResourceUpdateBatch();
        if (frame== 0)
            u->uploadStaticBuffer(vbuf.get(), vertexData);

        QMatrix4x4 mvp = viewProjection;
        mvp.rotate(rotation, 0, 1, 0);
        u->updateDynamicBuffer(ubuf.get(), 0, 64, mvp.constData());
        rotation+= 5.0f;

        u->updateDynamicBuffer(ubuf.get(), 64, 4, &opacity);
        opacity+= opacityDir * 0.2f;
        if (opacity < 0.0f|| opacity > 1.0f) {
            opacityDir*=-1;
            opacity = qBound(0.0f, opacity, 1.0f);
        }

        cb->beginPass(rt.get(), Qt::green, { 1.0f, 0 }, u);
        cb->setGraphicsPipeline(ps.get());
        cb->setViewport({ 0, 0, 1280, 720 });
        cb->setShaderResources();
        const QRhiCommandBuffer::VertexInput vbufBinding(vbuf.get(), 0);
        cb->setVertexInput(0, 1, &vbufBinding);
        cb->draw(3);
        QRhiReadbackResult readbackResult;
        u = rhi->nextResourceUpdateBatch();
        u->readBackTexture({ tex.get() }, &readbackResult);
        cb->endPass(u);

        rhi->endOffscreenFrame();

        QImage image(reinterpret_cast<const uchar*>(readbackResult.data.constData()),
                     readbackResult.pixelSize.width(),
                     readbackResult.pixelSize.height(),
                     QImage::Format_RGBA8888_Premultiplied);
        if (rhi->isYUpInFramebuffer())
            image.flip();
        image.save(QString::asprintf("frame%d.png", frame));
    }

    return 0;
}

L'application génère 20 images de type « PNG » (frame0.png à frame19.png). Celles-ci contiennent un triangle en rotation dont l'opacité varie sur un fond vert.

Les shaders de sommets et de fragments doivent être traités et intégrés dans des fichiers .qsb. Le code source GLSL compatible avec Vulkan est 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;
    float opacity;
};

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;

layout(std140, binding = 0) uniform buf {
    mat4 mvp;
    float opacity;
};

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

Pour compiler et transpilier manuellement ces shaders vers plusieurs cibles (SPIR-V, HLSL, MSL, GLSL) et générer les fichiers d’ .qsb s que l’application charge au moment de l’exécution, exécutez les commandes qsb --qt6 color.vert -o color.vert.qsb et qsb --qt6 color.frag -o color.frag.qsb. Sinon, le module Qt Shader Tools propose une intégration au système de compilation CMake via la fonction CMake qt_add_shaders(), qui permet d’obtenir le même résultat au moment de la compilation.

Considérations de sécurité

Toutes les données utilisées par QRhi et les classes associées, telles que QShader, sont considérées comme du contenu fiable.

Avertissement : il est conseillé aux développeursd’applications d’examiner attentivement les implications potentielles avant d’autoriser l’intégration de contenu fourni par l’utilisateur qui ne fait pas partie de l’application et n’est pas sous leur contrôle. (Cela inclut toutes les données de sommets/index, les shaders, les paramètres de pipeline et d’appels de dessin, etc.)

Principes fondamentaux de conception

Un QRhi ne peut pas être instancié directement. Utilisez plutôt la fonction create(). Supprimez l'instance QRhi de manière normale pour libérer le périphérique graphique.

Ressources

Les instances des classes dérivées de ` QRhiResource`, telles que ` QRhiBuffer`, ` QRhiTexture`, etc., encapsulent zéro, une ou plusieurs ressources graphiques natives. Les instances de ces classes sont toujours créées via les fonctions ` new ` du QRhi, telles que ` newBuffer()`, ` newTexture()`, ` newTextureRenderTarget()` et ` newSwapChain()`.

QRhiBuffer *vbuf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData));
if (!vbuf->create()) { error(); }
// ...
delete vbuf;
  • La valeur renvoyée par des fonctions telles que newBuffer() appartient toujours à l’appelant.
  • La simple création d’une instance d’une sous-classe de ` QRhiResource ` n’alloue ni n’initialise jamais aucune ressource native. Cela ne se produit que lors de l’appel de la fonction ` create() ` d’une sous-classe, par exemple ` QRhiBuffer::create()` ou ` QRhiTexture::create()`.
  • Les exceptions sont QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor(), QRhiSwapChain::newCompatibleRenderPassDescriptor() et QRhiRenderPassDescriptor::newCompatibleRenderPassDescriptor(). Il n’y a pas d’opération create() pour celles-ci et l’objet renvoyé est immédiatement actif.
  • Les objets-ressources eux-mêmes sont traités comme immuables : une fois que la méthode create() a été appelée pour une ressource, la modification de n’importe quel paramètre via les méthodes de configuration, telles que QRhiTexture::setPixelSize(), n’a aucun effet, à moins que la ressource native sous-jacente ne soit libérée et que la méthode create() ne soit à nouveau appelée. Pour en savoir plus sur la réutilisation des ressources, consultez les sections ci-dessous.
  • La libération des ressources natives sous-jacentes est planifiée par le destructeur de ` QRhiResource `, ou par l’appel de ` QRhiResource::destroy()`. Les backends mettent souvent en file d’attente les demandes de libération et reportent leur exécution à un moment indéterminé ; ce processus est masqué aux applications. De cette manière, les applications n’ont pas à se soucier de libérer des ressources natives qui pourraient encore être utilisées par un cadre en cours d’exécution.
  • Notez que cela ne signifie pas qu’un objet ` QRhiResource ` peut être librement détruit via `destroy()` ou supprimé au sein d’un cadre (c’est-à-dire dans une section comprise entre ` beginFrame()` et ` endFrame()`). En règle générale, tous les objets ` QRhiResource ` référencés doivent rester inchangés jusqu’à ce que le cadre soit soumis en appelant ` endFrame()`. Pour faciliter cette opération, la fonction ` QRhiResource::deleteLater()` est fournie à des fins de commodité.

Tampons de commandes et exécution différée des commandes

Quelles que soient la conception et les capacités de l’API graphique sous-jacente, tous les backends QRhi implémentent un certain niveau de tampons de commandes. Aucune fonction d’ QRhiCommandBuffer ation n’émet directement de commande native de liaison ou de dessin (telle que glDrawElements). Les commandes sont toujours enregistrées dans une file d’attente, qu’elle soit native ou fournie par le backend QRhi. Le tampon de commandes est soumis, et son exécution ne démarre donc qu’à l’appel de QRhi::endFrame() ou QRhi::finish().

Ce caractère différé a des conséquences pour certains types d’objets. Par exemple, écrire plusieurs fois dans un tampon dynamique au cours d’une image, dans le cas où ces tampons s’appuient sur de la mémoire visible par l’hôte, aura pour conséquence que les résultats de toutes les écritures seront visibles pour tous les appels de dessin du tampon de commandes de l’image, quel que soit le moment où la mise à jour du tampon dynamique a été enregistrée par rapport à un appel de dessin.

De plus, les instances des sous-classes de QRhiResource doivent être considérées comme immuables au sein d’une trame dans laquelle elles sont référencées de quelque manière que ce soit. Créez toutes les ressources à l’avance, avant de commencer à enregistrer les commandes pour la trame suivante. La réutilisation d’une instance de ` QRhiResource ` au sein d’une trame (en appelant ` create() ` puis en la référençant à nouveau dans la même section ` beginFrame - endFrame `) doit être évitée, car cela peut entraîner des résultats inattendus, selon le backend.

En règle générale, tous les objets ` QRhiResource ` référencés doivent rester valides et inchangés jusqu’à ce que l’image soit soumise en appelant ` endFrame()`. En revanche, l’appel de ` destroy()` ou la suppression de l’ QRhiResource sont toujours sans risque une fois le cadre soumis, quel que soit l’état des ressources natives sous-jacentes (qui peuvent encore être utilisées par le GPU — mais cela est géré en interne).

Contrairement à des API telles qu’OpenGL, les commandes de type « upload » et « copy » ne peuvent pas être mélangées avec des commandes de dessin. Un moteur de rendu classique impliquera une séquence similaire à celle-ci :

  • (re)créer les ressources
  • lancer l’image
  • enregistrer/émettre les chargements et les copies
  • lancer l'enregistrement d'un passage de rendu
  • enregistrer les appels de dessin
  • fin du passage de rendu
  • fin de l'image

L'enregistrement des opérations de type « copie » s'effectue via ` QRhiResourceUpdateBatch`. Ces opérations sont généralement validées par ` beginPass()`.

Lorsqu’on travaille avec des moteurs de rendu hérités conçus pour OpenGL, la migration vers QRhi implique souvent de repenser l’architecture : il faut passer d’une étape unique d’ render (qui effectue les copies et les chargements, efface les tampons et émet les appels de dessin, le tout mélangé) à une configuration clairement séparée, configuration en deux phases prepare - render, où l’étape « render » se contente de lancer un renderpass et d’enregistrer les appels de dessin, tandis que toute la création de ressources et la mise en file d’attente des mises à jour, des chargements et des copies s’effectuent au préalable, lors de l’étape « prepare ».

QRhi ne permet pas pour l’instant de créer et de soumettre librement des tampons de commande. Cette restriction pourrait être assouplie à l’avenir dans une certaine mesure, notamment si la prise en charge des calculs est introduite, mais le modèle reposant sur des points d’ frame-start et d’ frame-end bien définis, combiné à un tampon de commandes dédié par « image », où l’« frame-end » implique l’affichage, restera le mode de fonctionnement principal, car c’est celui qui s’adapte le mieux aux différentes technologies d’interface utilisateur de Qt XML.

Multithreading

Une instance QRhi et les ressources associées peuvent être créées et utilisées sur n’importe quel thread, mais toute utilisation doit être limitée à ce thread unique. Lors du rendu vers plusieurs QWindows au sein d’une application, il est souvent conseillé de disposer d’un thread et d’une instance QRhi dédiés à chaque fenêtre, car cela permet d’éliminer les problèmes de limitation inattendue causés par l’affichage sur plusieurs fenêtres. Conceptuellement, cela correspond au fonctionnement de la boucle de rendu multithread du graphe de scène d’ Qt Quick lorsqu’on travaille directement avec OpenGL : un thread par fenêtre, une instance ` QOpenGLContext ` par thread. Lors du passage à QRhi, ` QOpenGLContext ` est remplacé par QRhi, ce qui rend la migration très simple.

En ce qui concerne les objets natifs créés en externe, tels que les contextes OpenGL transmis via QRhiGles2NativeHandles, il appartient à l’application de s’assurer qu’ils ne sont pas utilisés de manière inappropriée par d’autres threads.

Les ressources ne sont pas partageables entre les instances de QRhi. Il s’agit d’un choix délibéré, car QRhi masque la plupart des tâches liées à la synchronisation des files d’attente, des tampons de commande et des ressources, et ne fournit aucune API à cet effet. L’utilisation simultanée, sûre et efficace des ressources graphiques par plusieurs threads est toutefois liée à ces concepts ; il s’agit donc d’un sujet qui n’est actuellement pas abordé, mais qui pourrait l’être à l’avenir.

Remarque : le backend Metal nécessite qu’un pool d’autorelease soit disponible sur le thread de rendu, idéalement en encapsulant chaque itération de la boucle de rendu. Cela ne nécessite aucune intervention de la part des utilisateurs de QRhi lors du rendu sur le thread principal (GUI), mais devient important lorsqu’un thread de rendu distinct et dédié est utilisé.

Synchronisation des ressources

QRhi ne propose pas d’API pour les barrières de ressources ou les transitions de mise en page d’images. Cette synchronisation est effectuée implicitement par les backends, le cas échéant (par exemple, Vulkan), en suivant l’utilisation des ressources si nécessaire. Les barrières de tampon et d’image sont insérées avant les passes de rendu ou de calcul de manière transparente pour l’application.

Remarque : les ressources au sein d’un passage de rendu ou de calcul sont censées être liées à une seule utilisation pendant ce passage. Par exemple, un tampon peut être utilisé comme tampon de sommets, d’index, uniforme ou de stockage, mais pas comme une combinaison de ceux-ci au sein d’un même passage. Cependant, il est tout à fait possible d’utiliser un tampon comme tampon de stockage lors d’un passage de calcul, puis comme tampon de sommets lors d’un passage de rendu, par exemple, à condition que le tampon ait déclaré ces deux utilisations lors de sa création.

Remarque : cette règle est assouplie dans certains cas pourles textures , car l’utilisation de deux sous-ressources (généralement deux niveaux de mip différents) d’une même texture pour des accès distincts (l’une pour la lecture, l’autre pour l’écriture) est prise en charge, même au sein d’un même passage.

Réutilisation des ressources

Du point de vue de l’utilisateur, une instance de ` QRhiResource ` est réutilisable immédiatement après l’appel à ` QRhiResource::destroy()`. À l’exception des `swapchains`, l’appel à ` create() ` sur un objet déjà créé effectue implicitement un ` destroy()`. Cela offre un raccourci pratique pour réutiliser une instance de ` QRhiResource ` avec des paramètres différents, en s’appuyant sur un nouvel objet graphique natif sous-jacent.

L'importance de réutiliser le même objet réside dans le fait que certains objets font référence à d'autres objets : par exemple, un objet de type ` QRhiShaderResourceBindings ` peut faire référence à des instances de ` QRhiBuffer`, ` QRhiTexture` et ` QRhiSampler `. Si, dans une image ultérieure, l'un de ces tampons doit être redimensionné ou si un paramètre d'échantillonneur doit être modifié, la destruction et la création d'un tout nouvel objet de type ` QRhiBuffer ` ou ` QRhiSampler ` invalideraient toutes les références à l'ancienne instance. En modifiant simplement les paramètres appropriés via ` QRhiBuffer::setSize()` ou une fonction similaire, puis en appelant ` QRhiBuffer::create()`, tout fonctionne comme prévu et il n’est pas nécessaire de toucher à l’ QRhiShaderResourceBindings, même s’il y a de fortes chances qu’en arrière-plan, l’ QRhiBuffer soit désormais adossé à un tout nouveau tampon natif.

QRhiBuffer *ubuf = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 256);
ubuf->create();

QRhiShaderResourceBindings *srb = rhi->newShaderResourceBindings()
srb->setBindings({
    QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, ubuf)
});
srb->create();

// ...

// now in a later frame we need to grow the buffer to a larger size
ubuf->setSize(512);
ubuf->create(); // same as ubuf->destroy(); ubuf->create();

// srb needs no changes whatsoever, any references in it to ubuf
// stay valid. When it comes to internal details, such as that
// ubuf may now be backed by a completely different native buffer
// resource, that is is recognized and handled automatically by the
// next setShaderResources().

QRhiTextureRenderTarget offre le même comportement : l’appel de ` QRhiCommandBuffer::beginPass()` est sans risque même si l’une des textures ou l’un des tampons de rendu associés à la cible de rendu a été reconstruit (en appelant ` create() ` sur celui-ci) depuis la création de l’objet cible de rendu. Cela permet à l’application de redimensionner une texture en définissant une nouvelle taille de pixel sur l’ QRhiTexture et en appelant ` create()`, créant ainsi une toute nouvelle ressource de texture native en arrière-plan, sans avoir à mettre à jour l’ QRhiTextureRenderTarget, car cela sera effectué implicitement dans `beginPass()`.

Objets mis en pool

Outre les ressources, il existe également des objets mis en pool, tels que QRhiResourceUpdateBatch. Une instance est récupérée via une fonction next, telle que nextResourceUpdateBatch(). Dans ce cas, l’appelant n’est pas propriétaire de l’instance renvoyée. La seule manière valable de procéder ici consiste à appeler des fonctions sur l’ QRhiResourceUpdateBatch, puis à le transmettre à QRhiCommandBuffer::beginPass() ou QRhiCommandBuffer::endPass(). Ces fonctions se chargent de renvoyer le lot au pool. Il est également possible d’« annuler » un lot et de le renvoyer au pool sans le traiter en appelant QRhiResourceUpdateBatch::release().

Un schéma type se présente donc comme suit :

QRhiResourceUpdateBatch *resUpdates = rhi->nextResourceUpdateBatch();
// ...
resUpdates->updateDynamicBuffer(ubuf, 0, 64, mvp.constData());
if (!image.isNull()) {
    resUpdates->uploadTexture(texture, image);
    image = QImage();
}
// ...
QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
// note the last argument
cb->beginPass(swapchain->currentFrameRenderTarget(), clearCol, clearDs, resUpdates);

Spécificités des swapchains

QRhiSwapChain présente une sémantique particulière en raison de la nature spécifique des swapchains.

  • Il n’existe pas de fonction ` create() `, mais plutôt une fonction ` QRhiSwapChain::createOrResize()`. Appeler cette fonction à plusieurs reprises n’ équivaut pas à appeler ` QRhiSwapChain::destroy()` puis ` QRhiSwapChain::createOrResize()`. En effet, les swapchains disposent souvent de mécanismes permettant de gérer le redimensionnement des tampons de manière plus efficace qu’une approche « par force brute » consistant à détruire et recréer les tampons à partir de zéro.
  • Une « QRhiSwapChain » active doit être libérée en appelant ` destroy()` ou en détruisant l’objet, avant que la `QPlatformWindow` sous-jacente de ` QWindow` — et donc l’objet de fenêtre natif associé — ne soit détruite. Cette opération ne doit pas être reportée, car la libération de la chaîne d’échange peut poser problème (et est explicitement interdite par certaines API, comme Vulkan) lorsque la fenêtre native n’existe plus, par exemple parce que la QPlatformWindow a été détruite lors de la réception d’un événement « QWindow::close() ». Par conséquent, la libération de la chaîne d’échange doit avoir lieu chaque fois que l’ QWindow e cible envoie l’événement « QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed ». Si l’événement n’arrive pas avant la destruction de l’ QWindow — ce qui peut se produire lors de l’utilisation de ` QCoreApplication::quit()` —, il faut alors vérifier `QWindow::handle()` après la sortie de la boucle d’événements et appeler la libération de la chaîne d’échange si la valeur est non nulle (ce qui signifie que la fenêtre native sous-jacente existe toujours).

Propriété

La règle générale est qu’il n’y a pas de transfert de propriété. La création d’un QRhi avec un périphérique graphique déjà existant ne signifie pas que le QRhi prend possession de l’objet périphérique. De même, la propriété n’est pas cédée lorsqu’un périphérique ou un objet texture est « exporté » via QRhi::nativeHandles() ou QRhiTexture::nativeTexture(). Plus important encore, le passage de pointeurs dans des structures et via des setters n’entraîne pas de transfert de propriété.

Dépannage et profilage

Signalement des erreurs

Des fonctions telles que ` QRhi::create()` et les fonctions membres ` create() ` des classes de ressources (par exemple, ` QRhiBuffer::create()`) signalent un échec via leur valeur de retour (respectivement `nullptr ` ou ` false`). Lorsque l’on utilise ` QShader`, la fonction ` QShader::fromSerialized()` renvoie un ` QShader ` invalide (pour lequel ` isValid()` renvoie ` false`) lorsque les données transmises à la fonction ne peuvent pas être désérialisées correctement. Certaines fonctions, notamment beginFrame(), peuvent parfois signaler des « échecs mineurs », tels que FrameOpSwapChainOutOfDate, qui n’indiquent pas une erreur irrémédiable, mais doivent plutôt être considérés comme une réponse invitant à « réessayer plus tard ».

Des avertissements et des erreurs peuvent être affichés à tout moment dans la sortie de débogage via ` qWarning()`. Il est donc toujours conseillé d’inspecter la sortie de l’application.

Des messages de débogage supplémentaires peuvent être activés via les catégories de journalisation suivantes. Les messages de ces catégories ne sont pas affichés par défaut, sauf s’ils sont explicitement activés via ` QLoggingCategory ` ou la variable d’environnement ` QT_LOGGING_RULES `. Pour une meilleure interopérabilité avec Qt Quick, la variable d’environnement ` QSG_INFO ` active également ces messages de débogage.

  • qt.rhi.general

De plus, les applications peuvent interroger les variables QRhi backend name et graphics device information à partir d’un QRhi correctement initialisé. Ces informations peuvent ensuite être affichées à l’utilisateur ou stockées dans les journaux de l’application, même dans les versions de production, si nécessaire.

Analyse des problèmes de rendu

Lorsque les résultats de rendu ne correspondent pas aux attentes ou que l’application rencontre des problèmes, pensez toujours à vérifier à l’aide des outils de débogage et de validation des API 3D natives. QRhi ne dispose lui-même que de fonctionnalités limitées de vérification des erreurs, car il n’est pas raisonnable de reproduire la vaste quantité de fonctionnalités déjà existantes dans les couches sous-jacentes.

  • Pour Vulkan, le contrôle des couches de validation Vulkan n’entre pas dans le champ d’application de QRhi, mais peut être réalisé en configurant l’ QVulkanInstance e avec les couches appropriées. Par exemple, appelez ` instance.setLayers({ "VK_LAYER_KHRONOS_validation" }); ` avant d’invoquer ` create()` sur ` QVulkanInstance`. (Notez que cela suppose que les couches de validation soient effectivement installées et disponibles, par exemple à partir du SDK Vulkan.) Par défaut, ` QVulkanInstance ` redirige de manière pratique les messages de débogage Vulkan vers ` qDebug`, ce qui signifie que les messages de validation s’affichent exactement comme les autres avertissements Qt.
  • Avec Direct 3D 11 et 12, il est possible de demander un périphérique graphique avec la couche de débogage activée en activant le drapeau « enableDebugLayer » dans la fonction appropriée init params struct. Avec Direct 3D 12, les messages sont alors affichés via qDebug, tout comme les messages de validation Vulkan, à condition que la couche de débogage prenne en charge les callbacks de messages. Sinon, et toujours avec Direct 3D 11, les messages apparaissent dans la sortie de débogage, visible dans le panneau de messages d’ Qt Creator ou via un outil tel que DebugView.
  • Pour Metal, le contrôle de la validation Metal ne relève pas du champ d’application de QRhi. Pour activer la validation, exécutez plutôt l’application avec la variable d’environnement METAL_DEVICE_WRAPPER_TYPE=1 définie, ou exécutez l’application dans XCode. Il peut également exister d’autres paramètres et variables d’environnement dans les versions récentes de XCode et de macOS. Consultez par exemple cette page.

Captures d’images et profilage des performances

Une application Qt effectuant un rendu via QRhi dans une fenêtre tout en s’appuyant sur une API 3D en arrière-plan ne diffère pas, du moins du point de vue du pipeline graphique et de gestion des fenêtres, des autres applications (non Qt) utilisant la même API 3D. Cela signifie que les outils et pratiques de débogage et de profilage des applications impliquant des graphismes 3D, tels que les jeux, s’appliquent également à ce type d’application Qt.

Voici quelques exemples d’outils permettant de mieux comprendre le fonctionnement interne du rendu des applications Qt utilisant QRhi, y compris les projets 3D basés sur Qt Quick et Qt Quick:

  • RenderDoc permet de capturer des images et d’analyser les commandes enregistrées ainsi que l’état du pipeline sous Windows et Linux pour les applications utilisant OpenGL, Vulkan, D3D11 ou D3D12. Lorsque l’on cherche à comprendre pourquoi certaines parties de la scène 3D ne s’affichent pas comme prévu, RenderDoc constitue souvent un moyen rapide et efficace de vérifier les étapes du pipeline et l’état associé, et de découvrir la valeur manquante ou erronée. C’est également un outil activement utilisé lors du développement de Qt lui-même.
  • Pour les systèmes basés sur NVIDIA, Nsight Graphics fournit un outil de débogage graphique sous Windows et Linux. Outre l’analyse des commandes contenues dans l’image et du pipeline, ces outils spécifiques au fabricant permettent d’examiner les temps d’exécution et les informations de performances matérielles, ce que de simples captures d’images ne peuvent pas fournir.
  • Pour les systèmes basés sur AMD, le Radeon GPU Profiler peut être utilisé pour obtenir des informations plus approfondies sur le rendu de l’application et ses performances.
  • Les superpositions affichant des informations de performances en temps réel peuvent également s’avérer très utiles et sont souvent préférables à la mise en œuvre de simples compteurs d’images par seconde au sein même de l’application, car elles sont plus fiables et fournissent davantage d’informations. Citons par exemple PresentMon, qui prend en charge le matériel graphique de plusieurs fournisseurs.
  • Comme QRhi prend en charge Direct 3D 12, l’utilisation de PIX, un outil d’optimisation des performances et de débogage pour les jeux DirectX 12 sous Windows, est également une option envisageable.
  • Sous macOS, le débogueur XCode Metal peut être utilisé pour capturer et analyser des images, examiner les détails de performance et déboguer des shaders. Sous macOS 13, il est également possible d’activer une superposition affichant la fréquence d’images et d’autres informations pour toute fenêtre basée sur Metal en définissant la variable d’environnement MTL_HUD_ENABLED=1.

Sur les plateformes mobiles et embarquées, il peut exister des outils spécifiques aux éditeurs et aux plateformes, fournis par le fabricant du GPU ou du SoC, permettant de réaliser un profilage des performances des applications utilisant OpenGL ES ou Vulkan.

Lors de la capture d’images, n’oubliez pas que les objets et les groupes de commandes peuvent être nommés à l’aide de marqueurs de débogage, à condition que la variable d’environnement ` debug markers were enabled ` pour le QRhi et l’API graphique utilisée prennent en charge cette fonctionnalité. Pour annoter le flux de commandes, appelez ` debugMarkBegin()`, ` debugMarkEnd()` et/ou ` debugMarkMsg()`. Cela peut s’avérer particulièrement utile dans les images volumineuses comportant plusieurs passes de rendu. Les ressources sont nommées en appelant setName() avant create().

Pour effectuer des mesures de temps de base côté CPU et GPU au sein de l’application, on peut utiliser QElapsedTimer et QRhiCommandBuffer::lastCompletedGpuTime(). Cette dernière n’est pour l’instant disponible qu’avec certaines API graphiques et nécessite d’être activée via le drapeau QRhi::EnableTimestamps.

Vérification des fuites de ressources

Lors de la destruction d’un objet QRhi sans avoir correctement détruit tous les tampons, textures et autres ressources créés à partir de celui-ci, des avertissements à ce sujet sont affichés dans la sortie de débogage dès lors que l’application est une version de débogage, ou lorsque la variable d’environnement QT_RHI_LEAK_CHECK est définie sur une valeur non nulle. Il s’agit d’un moyen simple de détecter des problèmes de conception liés à la gestion des ressources au sein de la logique de rendu de l’application. Notez toutefois que certaines plateformes et API graphiques sous-jacentes peuvent également effectuer leur propre allocation et détection de fuites de ressources, sur lesquelles Qt n’aura aucun contrôle direct. Par exemple, lors de l’utilisation de Vulkan, l’allocateur de mémoire peut déclencher des assertions échouées dans les versions de débogage lorsque les ressources qui possèdent des allocations de mémoire graphique ne sont pas détruites avant le QRhi. De plus, la couche de validation Vulkan, lorsqu’elle est activée, émettra des avertissements concernant les ressources graphiques natives qui n’ont pas été libérées. De même, avec Direct 3D, des avertissements peuvent s’afficher concernant des objets COM non libérés lorsque l’application ne détruit pas le QRhi et ses ressources dans le bon ordre.

Voir également Exemple de fenêtre RHI, QRhiCommandBuffer, QRhiResourceUpdateBatch, QRhiShaderResourceBindings, QShader, QRhiBuffer, QRhiTexture, QRhiRenderBuffer, QRhiSampler, QRhiTextureRenderTarget, QRhiGraphicsPipeline, QRhiComputePipeline et QRhiSwapChain.

Documentation sur les types de membres

[alias, since 6.10] QRhi::AdapterList

Synonyme de « QVector » <QRhiAdapter *>.

Ce typedef a été introduit dans Qt 6.10.

enum QRhi::BeginFrameFlag
flags QRhi::BeginFrameFlags

Valeurs des indicateurs pour la fonction ` QRhi::beginFrame()`

Le type BeginFrameFlags est un typedef pour QFlags<BeginFrameFlag>. Il stocke une combinaison OR de valeurs BeginFrameFlag.

enum QRhi::EndFrameFlag
flags QRhi::EndFrameFlags

Valeurs des indicateurs pour QRhi::endFrame()

ConstanteValeurDescription
QRhi::SkipPresent1 << 0Spécifie qu'aucune commande de présentation ne doit être mise en file d'attente et qu'aucun appel à swapBuffers ne doit être effectué. De cette manière, aucune image n'est présentée. Il n’est pas recommandé de générer plusieurs images avec ce drapeau activé pour toutes (sauf, par exemple, à des fins de benchmarking — mais gardez à l’esprit que les backends peuvent se comporter différemment lorsqu’il s’agit d’attendre l’exécution de la commande sans affichage, ce qui rend les résultats non comparables entre eux)

Le type `EndFrameFlags` est un `typedef` pour ` QFlags<EndFrameFlag>`. Il stocke une combinaison (ou) de valeurs `EndFrameFlag`.

enum QRhi::Feature

Valeurs d'indicateur permettant de préciser quelles fonctionnalités sont prises en charge par le backend actuellement utilisé.

ConstanteValeurDescription
QRhi::MultisampleTexture1Indique que les textures comportant plus d’un échantillon sont prises en charge. En pratique, cette fonctionnalité ne sera pas prise en charge avec les versions d’OpenGL ES antérieures à la version 3.1, ni avec les versions d’OpenGL antérieures à la version 3.0.
QRhi::MultisampleRenderBuffer2Indique que les tampons de rendu (renderbuffers) comportant plus d’un échantillon sont pris en charge. En pratique, cette fonctionnalité ne sera pas prise en charge par OpenGL ES 2.0 et pourrait également ne pas l’être par OpenGL 2.x, sauf si les extensions correspondantes sont présentes.
QRhi::DebugMarkers3Indique que les groupes de marqueurs de débogage (et donc la fonction ` QRhiCommandBuffer::debugMarkBegin()`) sont pris en charge.
QRhi::Timestamps4Indique que les horodatages des tampons de commande sont pris en charge. Pertinent pour QRhiCommandBuffer::lastCompletedGpuTime(). Cette fonctionnalité devrait être prise en charge sur Metal, Vulkan, Direct 3D 11 et 12, ainsi que dans les contextes OpenGL de version 3.3 ou plus récente. Cependant, avec certaines de ces API, la prise en charge des requêtes d’horodatage est techniquement facultative ; il n’est donc pas garanti que cette fonctionnalité soit toujours prise en charge par toutes leurs implémentations.
QRhi::Instancing5Indique que le dessin instancié est pris en charge. En pratique, cette fonctionnalité ne sera pas prise en charge avec OpenGL ES 2.0 et OpenGL 3.2 ou versions antérieures.
QRhi::CustomInstanceStepRate6Indique que les taux d’incrément d’instance autres que 1 sont pris en charge. En pratique, cette fonctionnalité ne sera jamais prise en charge avec OpenGL. De plus, l’exécution avec Vulkan 1.0 sans VK_EXT_vertex_attribute_divisor entraînera également un résultat « false » pour cette fonctionnalité.
QRhi::PrimitiveRestart7Indique que la réinitialisation de l’assemblage des primitives lors de la rencontre d’une valeur d’index de 0xFFFF (IndexUInt16) ou 0xFFFFFFFF (IndexUInt32) est activée, au moins pour certaines topologies de primitives. La fonction ` QRhi ` tentera d’activer cette fonctionnalité avec tous les backends, mais dans certains cas, elle ne sera pas prise en charge. Il n’est pas possible de contrôler dynamiquement le redémarrage des primitives, car avec certaines API, le redémarrage des primitives avec un index fixe est toujours activé. Les applications doivent partir du principe que, chaque fois que cette fonctionnalité est signalée comme prise en charge, les valeurs d’index mentionnées ci-dessus may doivent faire l’objet d’un traitement particulier, en fonction de la topologie. Les deux seules topologies pour lesquelles le redémarrage des primitives est garanti de se comporter de manière identique sur tous les backends, tant que cette fonctionnalité est signalée comme prise en charge, sont LineStrip et TriangleStrip.
QRhi::NonDynamicUniformBuffers8Indique que la création de tampons avec l’utilisation UniformBuffer et les types Immutable ou Static est prise en charge. Lorsqu’elle est signalée comme non prise en charge, les tampons uniformes (constants) doivent être créés sous la forme Dynamic. (ce qui est de toute façon recommandé)
QRhi::NonFourAlignedEffectiveIndexBufferOffset9Indique que les décalages effectifs des tampons d’index (indexOffset + firstIndex * indexComponentSize) qui ne sont pas alignés sur 4 octets sont pris en charge. Lorsque cette fonctionnalité n’est pas prise en charge, tenter d’appeler une fonction drawIndexed() avec un décalage effectif non aligné peut entraîner un comportement indéfini. Cela concerne en particulier Metal, où cette fonctionnalité sera signalée comme non prise en charge.
QRhi::NPOTTextureRepeat10Indique que le mode de bouclage ` Repeat ` et les modes de filtrage mipmap sont pris en charge pour les textures dont la taille n’est pas une puissance de deux. En pratique, cette valeur ne peut être fausse que dans les implémentations OpenGL ES 2.0 ne prenant pas en charge ` GL_OES_texture_npot`.
QRhi::RedOrAlpha8IsRed11Indique que le format « RED_OR_ALPHA8 » correspond à un format « red » à un composant de 8 bits. C’est le cas pour tous les backends, à l’exception d’OpenGL, lors de l’utilisation d’OpenGL ES ou d’un contexte de profil non « core ». On utilise alors à la place GL_ALPHA, un format alpha à une composante de 8 bits. L’utilisation de ce format de texture spécial permet de disposer d’un chemin de code unique pour la création des textures, laissant au backend le soin de décider du format réel, tandis que l’indicateur de fonctionnalité peut être utilisé pour choisir la variante de shader appropriée pour l’échantillonnage de la texture.
QRhi::ElementIndexUint12Indique que les éléments de type entier non signé 32 bits sont pris en charge dans le tampon d’index. En pratique, cela s’applique partout sauf lors de l’exécution sur des implémentations OpenGL ES 2.0 standard ne disposant pas de l’extension nécessaire. Lorsque cette valeur est fausse, seuls les éléments de type entier non signé 16 bits sont pris en charge dans le tampon d’index.
QRhi::Compute13Indique que les shaders de calcul, le chargement/stockage d’images et les tampons de stockage sont pris en charge. Les versions d’OpenGL antérieures à la version 4.3 et celles d’OpenGL ES antérieures à la version 3.1 ne prennent pas en charge les calculs.
QRhi::WideLines14Indique que les lignes dont la largeur est différente de 1 sont prises en charge. Lorsque cette option est signalée comme non prise en charge, la largeur de ligne définie dans l’état du pipeline graphique est ignorée. Cette valeur peut toujours être « false » avec certains backends (D3D11, D3D12, Metal). Avec Vulkan, la valeur dépend de l’implémentation. Avec OpenGL, les lignes larges ne sont pas prises en charge dans les contextes de profil de base.
QRhi::VertexShaderPointSize15Indique que la taille des points rastérisés définie via ` gl_PointSize ` dans le shader de sommets est prise en compte. Lorsque cette fonctionnalité est signalée comme non prise en charge, le tracé de points d’une taille autre que 1 n’est pas pris en charge. La définition de ` gl_PointSize ` dans le shader reste alors valide, mais est ignorée. (par exemple, lors de la génération de code HLSL, l’affectation est silencieusement supprimée du code généré) Notez que certaines API (Metal, Vulkan) exigent que la taille des points soit explicitement définie dans le shader lors du tracé de points, même lorsque la taille est égale à 1, car elles ne prennent pas automatiquement la valeur par défaut de 1.
QRhi::BaseVertex16Indique que la fonction ` drawIndexed()` prend en charge l’argument ` vertexOffset `. Lorsque cette fonctionnalité est signalée comme non prise en charge, la valeur de `vertexOffset` dans un dessin indexé est ignorée. En pratique, cette fonctionnalité ne sera pas prise en charge avec les versions d’OpenGL et d’OpenGL ES antérieures à la version 3.2, ni avec Metal sur les anciens appareils iOS, y compris le simulateur iOS.
QRhi::BaseInstance17Indique que les commandes de dessin instanciées prennent en charge l’argument ` firstInstance `. Lorsqu’elle est signalée comme non prise en charge, la valeur `firstInstance` est ignorée et l’ID d’instance commence à 0. En pratique, cette fonctionnalité ne sera pas prise en charge avec Metal sur les anciens appareils iOS, y compris le simulateur iOS, ni avec aucune version d’OpenGL. Ce dernier cas s’explique par le fait qu’OpenGL ES ne prend absolument pas en charge les appels de dessin avec une instance de base. Actuellement, le backend OpenGL de QRhi n’implémente pas non plus cette fonctionnalité pour OpenGL (non-ES), car les applications portables ne peuvent pas compter sur une instance de base non nulle en pratique en raison de GLES. Si l’application choisit tout de même de le faire, elle doit également tenir compte de la fonctionnalité InstanceIndexIncludesBaseInstance.
QRhi::TriangleFanTopology18Indique que ` QRhiGraphicsPipeline::setTopology()` prend en charge ` QRhiGraphicsPipeline::TriangleFan`. En pratique, cette fonctionnalité ne sera pas prise en charge avec Metal et Direct 3D 11/12.
QRhi::ReadBackNonUniformBuffer19Indique que la fonction ` reading buffer contents ` est prise en charge pour les instances ` QRhiBuffer ` dont l’utilisation diffère de celle d’un `UniformBuffer`. En pratique, cette fonctionnalité ne sera pas prise en charge avec OpenGL ES 2.0.
QRhi::ReadBackNonBaseMipLevel20Indique que la spécification d’un niveau de mip autre que 0 est prise en charge lors de la relecture du contenu d’une texture. Lorsque cette fonctionnalité n’est pas prise en charge, la spécification d’un niveau non nul dans ` QRhiReadbackDescription ` entraîne le renvoi d’une image composée uniquement de zéros. En pratique, cette fonctionnalité ne sera pas prise en charge avec OpenGL ES 2.0.
QRhi::TexelFetch21Indique que les fonctions `texelFetch()` et `textureLod()` sont disponibles dans les shaders. En pratique, cette fonctionnalité sera signalée comme non prise en charge dans les contextes OpenGL ES 2.0 et OpenGL 2.x, car GLSL 100 es et les versions antérieures à 130 ne prennent pas en charge ces fonctions.
QRhi::RenderToNonBaseMipLevel22Indique que la spécification d’un niveau de mip autre que 0 est prise en charge lors de la création d’un ` QRhiTextureRenderTarget ` avec une ` QRhiTexture ` comme attachement de couleur. Lorsque cette fonctionnalité n’est pas prise en charge, la fonction ` create()` échouera dès lors que le niveau de mip cible n’est pas égal à zéro. En pratique, cette fonctionnalité ne sera pas prise en charge avec OpenGL ES 2.0.
QRhi::IntAttributes23Indique que la spécification d’attributs d’entrée de types entiers signés et non signés pour un pipeline de shaders est prise en charge. Lorsque cette fonctionnalité n’est pas prise en charge, la fonction ` QRhiGraphicsPipeline::create()` aboutira mais affichera un message d’avertissement et les valeurs des attributs cibles seront corrompues. En pratique, cette fonctionnalité ne sera pas prise en charge avec OpenGL ES 2.0 et OpenGL 2.x.
QRhi::ScreenSpaceDerivatives24Indique que des fonctions telles que dFdx(), dFdy() et fwidth() sont prises en charge dans les shaders. En pratique, cette fonctionnalité ne sera pas prise en charge avec OpenGL ES 2.0 sans l’extension GL_OES_standard_derivatives.
QRhi::ReadBackAnyTextureFormat25Indique que la relecture du contenu des textures devrait fonctionner pour n’importe quelle QRhiTexture::Format. On peut s’attendre à ce que les backends autres qu’OpenGL renvoient « true » pour cette fonctionnalité. Lorsqu’elle est signalée comme « false », ce qui est généralement le cas avec OpenGL, seuls les formats QRhiTexture::RGBA8 et QRhiTexture::BGRA8 sont garantis comme étant pris en charge pour les relectures. De plus, avec OpenGL (mais pas avec OpenGL ES), la relecture des formats à 1 octet par composant QRhiTexture::R8 et QRhiTexture::RED_OR_ALPHA8 est également prise en charge. La relecture des formats à virgule flottante QRhiTexture::RGBA16F et RGBA32F peut également fonctionner avec OpenGL, à condition que l’implémentation les prenne en charge, mais QRhi ne peut offrir aucune garantie, comme l’indique cet indicateur.
QRhi::PipelineCacheDataLoadSave26Indique que les fonctions pipelineCacheData() et setPipelineCacheData() sont opérationnelles. Lorsqu’elles ne sont pas prises en charge, ces fonctions n’effectuent aucune action, le blob récupéré est toujours vide, et il ne faut donc pas s’attendre à tirer un quelconque avantage de la récupération, ni du rechargement du contenu du cache du pipeline lors d’une exécution ultérieure de l’application.
QRhi::ImageDataStride27Indique que la spécification d’un pas (longueur de ligne) personnalisé pour les données d’image brutes lors du chargement de textures est prise en charge. Lorsque cette fonctionnalité n’est pas prise en charge (ce qui peut se produire lorsque l’API sous-jacente est OpenGL ES 2.0 sans prise en charge de GL_UNPACK_ROW_LENGTH), la fonction QRhiTextureSubresourceUploadDescription::setDataStride() ne doit pas être utilisée.
QRhi::RenderBufferImport28Indique que la fonction ` QRhiRenderBuffer::createFrom()` est prise en charge. Pour la plupart des API graphiques, cela n’a pas de sens car ` QRhiRenderBuffer ` encapsule les objets de texture en interne, tout comme ` QRhiTexture`. Avec OpenGL, cependant, les objets « renderbuffer » existent en tant que type d’objet distinct dans l’API, et dans certains environnements (par exemple, lorsqu’on souhaite associer un objet « renderbuffer » à un objet EGLImage), il est important de permettre l’encapsulation d’un objet « renderbuffer » OpenGL existant à l’aide d’un QRhiRenderBuffer.
QRhi::ThreeDimensionalTextures29Indique que les textures 3D sont prises en charge. En pratique, cette fonctionnalité ne sera pas prise en charge avec les versions d’OpenGL et d’OpenGL ES antérieures à la version 3.0.
QRhi::RenderTo3DTextureSlice30Indique que le rendu sur une tranche d’une texture 3D est pris en charge. Cette fonctionnalité peut ne pas être prise en charge avec Vulkan 1.0, car elle repose sur VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT, qui est une fonctionnalité de Vulkan 1.1.
QRhi::TextureArrays31Indique que les tableaux de textures sont pris en charge et que la fonction ` QRhi::newTextureArray()` est opérationnelle. Notez que même lorsque les tableaux de textures ne sont pas pris en charge, les tableaux de textures restent disponibles, car il s’agit de deux fonctionnalités indépendantes.
QRhi::Tessellation32Indique que les étapes de contrôle et d’évaluation de la tessellation sont prises en charge. Lorsque cette fonctionnalité est signalée comme prise en charge, la topologie d’un « QRhiGraphicsPipeline » peut être définie via ` Patches`, le nombre de points de contrôle peut être défini via ` setPatchControlPointCount()`, et les shaders pour le contrôle et l’évaluation de la tessellation peuvent être spécifiés dans la liste ` QRhiShaderStage `. Les shaders de tessellation posent des problèmes de portabilité entre les API (par exemple, la conversion de GLSL/SPIR-V en HLSL est problématique en raison de la structure des shaders de coque, tandis que Metal utilise un pipeline de tessellation quelque peu différent de celui des autres) ; par conséquent, des problèmes inattendus peuvent encore survenir, même si les fonctionnalités de base sont implémentées dans toutes les API sous-jacentes. Pour Direct 3D en particulier, des shaders de coque et de domaine HLSL écrits manuellement doivent être injectés dans chaque « QShader » pour les étapes de contrôle et d’évaluation de la tessellation, respectivement, car qsb ne peut pas les générer à partir de SPIR-V. Notez que la tessellation par isolignes doit être évitée, car elle n’est pas prise en charge par tous les backends. Le nombre maximal de points de contrôle de patch transférables d’un backend à l’autre est de 32.
QRhi::GeometryShader33Indique que l’étape du shader de géométrie est prise en charge. Lorsqu’elle est prise en charge, un shader de géométrie peut être spécifié dans la liste des « QRhiShaderStage s ». Les shaders de géométrie sont considérés comme une fonctionnalité expérimentale dans QRhi et ne devraient être pris en charge qu’avec Vulkan, Direct 3D 11 et 12, OpenGL (3.2+) et OpenGL ES (3.2+), à condition que l’implémentation signale cette prise en charge lors de l’exécution. À partir de Qt 6.11, les shaders de géométrie sont automatiquement convertis en HLSL ; il n’est donc plus nécessaire d’injecter manuellement des shaders de géométrie HLSL (mais notez que gl_in et les expressions telles que gl_in[0].gl_Position ne sont pas prises en charge ; il faut plutôt transmettre la position en tant que variable de sortie depuis le shader de sommet). Les shaders de géométrie ne sont pas pris en charge avec Metal.
QRhi::TextureArrayRange34Indique que, pour texture arrays, il est possible de spécifier une plage exposée aux shaders. Normalement, toutes les couches du tableau sont exposées et c’est au shader de sélectionner la couche (via la troisième coordonnée transmise à texture() lors de l’échantillonnage de l’ sampler2DArray). Lorsque cette fonctionnalité est prise en charge, l’appel de QRhiTexture::setArrayRangeStart() et QRhiTexture::setArrayRangeLength() avant building ou importing la texture native a un effet et conduit à la sélection de la plage spécifiée uniquement dans le tableau. Cela s’avère nécessaire dans certains cas particuliers, notamment lors de l’utilisation du décodage vidéo accéléré et de Direct 3D 11, car un tableau de textures comportant à la fois D3D11_BIND_DECODER et D3D11_BIND_SHADER_RESOURCE ne peut être utilisé comme ressource de shader que si une seule couche du tableau est sélectionnée. Notez que tout cela ne s’applique que lorsque la texture est utilisée comme ressource de shader de type « QRhiShaderResourceBinding::SampledTexture » ou « QRhiShaderResourceBinding::Texture », et n’est pas compatible avec le chargement/stockage d’images. Cette fonctionnalité n’est disponible qu’avec certains backends, car elle ne s’adapte pas bien à toutes les API graphiques, et elle est de toute façon uniquement destinée à prendre en charge des cas particuliers. En pratique, cette fonctionnalité devrait être prise en charge par Direct3D 11/12 et Vulkan.
QRhi::NonFillPolygonMode35Indique que la configuration d’un PolygonMode autre que la valeur par défaut Fill est prise en charge pour l’ QRhiGraphicsPipeline. Un cas d’utilisation courant consistant à passer en mode Line est le rendu filaire. Cette fonctionnalité n’est toutefois pas disponible en tant que fonctionnalité de base d’OpenGL ES ; elle est facultative avec Vulkan et certains GPU mobiles peuvent ne pas la proposer.
QRhi::OneDimensionalTextures36Indique que les textures 1D sont prises en charge. En pratique, cette fonctionnalité ne sera pas prise en charge sur OpenGL ES.
QRhi::OneDimensionalTextureMipmaps37Indique que la génération de mipmaps de textures 1D est prise en charge. En pratique, cette fonctionnalité ne sera pas prise en charge sur les backends qui ne signalent pas la prise en charge de OneDimensionalTextures, Metal et Direct 3D 12.
QRhi::HalfAttributes38Indique que la spécification d’attributs d’entrée avec des types à virgule flottante à demi-précision (16 bits) pour un pipeline de shaders est prise en charge. Lorsque cette fonctionnalité n’est pas prise en charge, l’appel ` QRhiGraphicsPipeline::create()` aboutira mais affichera un message d’avertissement, et les valeurs des attributs cibles seront corrompues. En pratique, cette fonctionnalité ne sera pas prise en charge dans certaines implémentations d’OpenGL ES 2.0 et d’OpenGL 2.x. Notez que bien que Direct3D 11/12 prenne en charge les attributs d’entrée en demi-précision, il ne prend pas en charge le type half3. Les backends D3D transmettent les attributs half3 sous la forme half4. Pour garantir la compatibilité multiplateforme, les entrées half3 doivent être complétées à 8 octets.
QRhi::RenderToOneDimensionalTexture39Indique que les cibles de rendu de textures 1D sont prises en charge. En pratique, cette fonctionnalité ne sera pas prise en charge sur les backends qui ne signalent pas la prise en charge de OneDimensionalTextures, ni sur Metal.
QRhi::ThreeDimensionalTextureMipmaps40Indique que la génération de mipmaps de textures 3D est prise en charge. Cette fonctionnalité est généralement prise en charge par tous les backends à partir de Qt 6.10.
QRhi::MultiView41Indique que le mode multivue (voir par exemple VK_KHR_multiview ) est pris en charge. Avec les implémentations OpenGL ES 2.0, Direct 3D 11 et OpenGL (ES) ne disposant pas de la fonction « GL_OVR_multiview2 », cette fonctionnalité ne sera pas prise en charge. Avec Vulkan 1.1 et les versions plus récentes, ainsi qu’avec Direct 3D 12, le multivue est généralement pris en charge. Lorsque cette fonctionnalité est signalée comme prise en charge, la création d’un ` QRhiTextureRenderTarget ` avec un ` QRhiColorAttachment ` faisant référence à un tableau de textures et pour lequel ` multiViewCount ` est défini permet d’enregistrer un passage de rendu utilisant le rendu multivue. De plus, tout « QRhiGraphicsPipeline » utilisé dans ce passage de rendu doit comporter l’attribut « the same view count set ». Notez que le rendu multivue n’est disponible qu’en combinaison avec des tableaux de textures 2D. Il ne peut pas être utilisé pour optimiser le rendu vers des textures individuelles (par exemple deux, pour l’œil gauche et l’œil droit). Au contraire, la cible d’un passage de rendu multivue est toujours un tableau de textures, le rendu s’effectuant automatiquement sur la couche (élément du tableau) correspondant à chaque vue. Cette fonctionnalité implique donc également l’utilisation de tableaux de textures. Le rendu multivue n’est pas pris en charge en combinaison avec la tessellation ou les shaders de géométrie. Voir QRhiColorAttachment::setMultiViewCount() pour plus de détails sur le rendu multivue. Cette valeur d’énumération a été introduite dans Qt 6.7.
QRhi::TextureViewFormat42Indique que la définition d’un format de vue ( view format ) sur un objet de texture ( QRhiTexture ) est effective. Lorsque cette fonctionnalité est signalée comme prise en charge, la définition du mode de vue en lecture (échantillonnage) ou en écriture (cible de rendu / chargement-stockage d’image) modifie le format de visualisation de la texture. Lorsqu’elle n’est pas prise en charge, la définition d’un format de vue n’a aucun effet. Notez que Qt n’a aucune connaissance ni aucun contrôle sur la compatibilité des formats ou les règles d’affichage des ressources dans l’API 3D sous-jacente et son implémentation. Le passage de formats inadaptés ou incompatibles peut entraîner des erreurs et un comportement non spécifié. Cette fonctionnalité est principalement fournie pour permettre de « convertir » le rendu d’une texture créée au format sRGB vers un format non-sRGB, afin d’éviter la conversion indésirable linéaire vers sRGB lors des écritures de shaders. D’autres types de conversion peuvent fonctionner ou non, selon l’API sous-jacente. Actuellement implémenté pour Vulkan et Direct 3D 12. Avec D3D12, cette fonctionnalité n’est disponible que si la prise en charge de « CastingFullyTypedFormatSupported » est assurée ; voir https://microsoft.github.io/DirectX-Specs/d3d/RelaxedCasting.html (et notez que QRhi utilise toujours des formats entièrement typés pour les textures). Cette valeur d’énumération a été introduite dans Qt 6.8.
QRhi::ResolveDepthStencil43Indique que la résolution d’une texture de profondeur ou de profondeur-stencil à échantillonnage multiple est prise en charge. Dans le cas contraire, l’ setting a depth resolve texture n’est pas fonctionnelle et doit être évitée. Direct 3D 11 et 12 ne prennent pas en charge la résolution des formats de profondeur/profondeur-stencil ; cette fonctionnalité ne sera donc jamais prise en charge avec ces versions. Vulkan 1.0 ne dispose d’aucune API permettant de demander la résolution d’une texture de profondeur-stencil. Par conséquent, avec Vulkan, cette fonctionnalité ne sera prise en charge qu’à partir de la version 1.2, ainsi que sur les implémentations 1.1 dotées des extensions appropriées. Cette fonctionnalité est prévue pour les rares cas où la résolution dans une texture de profondeur non multi-échantillonnée s’avère nécessaire, par exemple lors du rendu dans une texture de profondeur fournie par OpenXR (XR_KHR_composition_layer_depth). Cette valeur d’énumération a été introduite dans Qt 6.8.
QRhi::VariableRateShading44Indique que l’ombrage à taux variable par dessin (par pipeline) est pris en charge. Lorsque cette fonctionnalité est signalée comme prise en charge, la fonction ` QRhiCommandBuffer::setShadingRate()` est opérationnelle et a un effet sur les objets ` QRhiGraphicsPipeline ` ayant déclaré ` QRhiGraphicsPipeline::UsesShadingRate ` dans leurs indicateurs. Appelez QRhi::supportedShadingRates() pour vérifier quels taux sont pris en charge. (1x1 est toujours pris en charge ; les autres valeurs courantes sont 2x2, 1x2, 2x1, 2x4, 4x2, 4x4). Cette fonctionnalité devrait être prise en charge par Direct 3D 12 et Vulkan, à condition que l’implémentation et le GPU utilisés au moment de l’exécution prennent en charge le VRS. Cette valeur d’énumération a été introduite dans Qt 6.9.
QRhi::VariableRateShadingMap45Indique qu’il est possible de spécifier le taux d’ombrage à partir d’une image. L’« image » n’est pas nécessairement une texture ; il peut s’agir d’un objet natif de l’API 3D, en fonction du backend sous-jacent et de l’API graphique au moment de l’exécution. En pratique, cette fonctionnalité devrait être prise en charge par Direct 3D 12, Vulkan et Metal, à condition que le GPU soit suffisamment récent pour prendre en charge le VRS. Pour vérifier si le VRS basé sur une image de type D3D12/Vulkan est pris en charge, utilisez plutôt `VariableRateShadingMapWithTexture`. Lorsque cette fonctionnalité est signalée comme prise en charge, deux cas de figure sont possibles : si `VariableRateShadingMapWithTexture` est également vrai, alors ` QRhiShadingRateMap ` utilise des objets ` QRhiTexture ` via la surcharge de la méthode `createFrom()` prenant un argument de type ` QRhiTexture `. Lorsque `VariableRateShadingMapWithTexture` est à `false`, ` QRhiShadingRateMap ` utilise alors d'autres types d'objets natifs, par exemple un `MTLRasterizationRateMap` dans le cas de Metal. Dans ce cas, utilisez la surcharge de `createFrom()` prenant un `NativeShadingRateMap` en paramètre. Cette valeur d'énumération a été introduite dans Qt 6.9.
QRhi::VariableRateShadingMapWithTexture46Indique que la spécification du taux d’ombrage basée sur une image est prise en charge via des textures classiques. En pratique, cela peut être pris en charge avec Direct 3D 12 et Vulkan. Cette valeur d’énumération a été introduite dans Qt 6.9.
QRhi::PerRenderTargetBlending47Indique que le mélange par cible de rendu est pris en charge, c'est-à-dire que différentes cibles de rendu dans le framebuffer MRT peuvent avoir des modes de mélange différents. En pratique, on peut s'attendre à ce que cette fonctionnalité soit prise en charge partout sauf dans OpenGL ES, où elle n'est disponible qu'avec les implémentations GLES 3.2. Cette valeur d'énumération a été introduite dans Qt 6.9.
QRhi::SampleVariables48Indique que les variables gl_SampleID, gl_SamplePosition, gl_SampleMaskIn et gl_SampleMask sont disponibles dans les shaders de fragments. En pratique, cette fonctionnalité devrait être prise en charge partout sauf dans OpenGL ES, où elle n'est disponible qu'avec les implémentations GLES 3.2. Cette valeur d'énumération a été introduite dans Qt 6.9.
QRhi::InstanceIndexIncludesBaseInstance49Indique que la variable ` gl_InstanceIndex ` inclut l’instance de base (l’argument ` firstInstance ` dans les appels de dessin) dans sa valeur. Lorsque cette fonctionnalité n’est pas prise en charge, mais que `BaseInstance` l’est, cela signifie que ` gl_InstanceIndex ` commence toujours à 0, et non à la valeur de base. En pratique, c’est le cas pour Direct 3D 11 et 12 à l’heure actuelle. Avec Vulkan et Metal, cette fonctionnalité devrait toujours être signalée comme prise en charge. Cette valeur d’énumération a été introduite dans Qt 6.11.
QRhi::DepthClamp (since Qt 6.11)50Indique que l’activation du clamping de profondeur est prise en charge. Lorsqu’elle est signalée comme non prise en charge, ce qui sera le cas avec OpenGL ES, les versions d’OpenGL antérieures à la version 3.2 ne disposant pas de l’extension correspondante, et Metal sur le simulateur iOS, l’appel de la fonction ` QRhiGraphicsPipeline::setDepthClamp()` avec l’argument ` true ` n’a aucun effet.
QRhi::DrawIndirect (since Qt 6.12)51Indique que les fonctions ` drawIndirect()` et ` drawIndexedIndirect()` sont disponibles. En pratique, on peut s’attendre à ce que cette fonctionnalité soit prise en charge partout, sauf sur OpenGL ES < 3.1.
QRhi::DrawIndirectMulti (since Qt 6.12)52Indique qu’une valeur de drawCount supérieure à 1 est prise en charge en natif par le backend dans les fonctions drawIndirect() et drawIndexedIndirect(). Dans le cas contraire, plusieurs appels de dessin sont émis sur le processeur par le RHI. En pratique, cette fonctionnalité devrait être prise en charge sur Vulkan 1.1 et versions ultérieures, OpenGL 4.3 et versions ultérieures, ainsi que D3D12.
QRhi::ShaderDrawParameters (since Qt 6.12)53Indique que les variables intégrées gl_BaseInstance, gl_BaseVertex et gl_DrawID sont disponibles dans les shaders. En pratique, cette fonctionnalité devrait être prise en charge par Vulkan 1.1+ et par OpenGL 4.6 ou GL_ARB_shader_draw_parameters sur ordinateur de bureau.

enum QRhi::Flag
flags QRhi::Flags

Décrit les fonctionnalités spéciales à activer.

ConstanteValeurDescription
QRhi::EnableDebugMarkers1 << 0Active les groupes de marqueurs de débogage. Sans cette option, les fonctionnalités de débogage des images, telles que la création de groupes de débogage et l’affichage des noms de ressources personnalisés dans les outils de débogage GPU externes, ne seront pas disponibles, et les fonctions telles que ` QRhiCommandBuffer::debugMarkBegin()` deviendront des opérations sans effet. Évitez de l’activer dans les versions de production, car cela peut entraîner un léger impact sur les performances. N’a aucun effet lorsque la fonctionnalité « QRhi::DebugMarkers » n’est pas signalée comme prise en charge.
QRhi::EnableTimestamps1 << 3Active la collecte des horodatages GPU. Si cette option n’est pas définie, la fonction QRhiCommandBuffer::lastCompletedGpuTime() renvoie toujours 0. N’activez cette option qu’en cas de nécessité, car elle peut entraîner une légère charge de travail supplémentaire (par exemple, des requêtes d’horodatage), en fonction de l’API graphique sous-jacente. N’a aucun effet lorsque la fonctionnalité QRhi::Timestamps n’est pas signalée comme prise en charge.
QRhi::PreferSoftwareRenderer1 << 1Indique que les backends doivent privilégier le choix d’un adaptateur ou d’un périphérique physique effectuant le rendu par logiciel sur le CPU. Par exemple, avec Direct3D, un adaptateur « Basic Render Driver » est généralement disponible via ` DXGI_ADAPTER_FLAG_SOFTWARE`. L’activation de ce drapeau demande au backend de choisir cet adaptateur plutôt que tout autre, à condition qu’aucun adaptateur spécifique n’ait été imposé par d’autres moyens propres au backend. Avec Vulkan, cela correspond à la préférence pour les périphériques physiques via VK_PHYSICAL_DEVICE_TYPE_CPU. Lorsque cette option n’est pas disponible, ou lorsqu’il n’est pas possible de déterminer si un adaptateur/périphérique est de type logiciel, ce drapeau est ignoré. Il peut également être ignoré avec les API graphiques qui ne disposent ni du concept ni des moyens de répertorier les adaptateurs/périphériques.
QRhi::EnablePipelineCacheDataSave1 << 2Permet de récupérer le contenu du cache du pipeline, le cas échéant. Lorsqu’il n’est pas activé, la fonction ` pipelineCacheData()` renvoie toujours un blob vide. Avec les backends qui ne prennent pas en charge la récupération et la restauration du contenu du cache du pipeline, ce drapeau n’a aucun effet et les données sérialisées du cache sont toujours vides. Ce drapeau offre un mécanisme d’activation facultative, car le coût de gestion des structures de données associées n’est pas négligeable avec certains backends. Avec Vulkan, cette fonctionnalité correspond directement à VkPipelineCache, vkGetPipelineCacheData et VkPipelineCacheCreateInfo::pInitialData. Avec Direct3D 11, il n’existe pas de véritable cache de pipeline, mais les résultats des compilations HLSL→DXBC sont stockés et peuvent être sérialisés/désérialisés via ce mécanisme. Cela permet d’éviter l’appel de la fonction D3DCompile(), très chronophage, lors des exécutions ultérieures des applications pour les shaders fournis sous forme de code source HLSL plutôt que sous forme de bytecode précompilé hors ligne. Cela peut considérablement réduire les temps de démarrage et de chargement, si de nombreuses compilations de code source HLSL ont lieu. Avec OpenGL, le « cache de pipeline » est simulé par la récupération et le chargement des binaires des programmes de shaders (si cela est pris en charge par le pilote). Avec OpenGL, Qt fournit des mécanismes de mise en cache supplémentaires, basés sur le disque, pour les binaires de shaders/programmes. L’écriture dans ces caches peut être désactivée lorsque cet indicateur est activé, car il n’est pas judicieux de stocker les binaires de programmes dans plusieurs caches.
QRhi::SuppressSmokeTestWarnings1 << 4Indique que, pour les backends concernés, certaines erreurs non fatales de ` QRhi::create()` ne doivent pas générer d’appels à ` qWarning()`. Par exemple, avec D3D11, le passage de ce drapeau fait en sorte qu’un certain nombre de messages d’avertissement (qui apparaissent en raison de l’échec de ` QRhi::create()`) soient classés comme des messages de débogage dans la catégorie de journalisation couramment utilisée « qt.rhi.general ». Cette fonctionnalité peut être utilisée par des moteurs, tels que Qt Quick, qui intègrent une logique de repli, c’est-à-dire qu’ils réessaient d’appeler ` create()` avec un ensemble différent de drapeaux (comme `PreferSoftwareRenderer), afin de masquer les avertissements inconditionnels de la sortie qui seraient affichés si la première tentative d’appel de ` create()` avait échoué.

Le type Flags est un typedef de QFlags<Flag>. Il stocke une combinaison OR de valeurs Flag.

enum QRhi::FrameOpResult

Décrit le résultat d'opérations pouvant entraîner un échec non fatal.

ConstanteValeurDescription
QRhi::FrameOpSuccess0Succès
QRhi::FrameOpError1Erreur non spécifiée
QRhi::FrameOpSwapChainOutOfDate2La chaîne d'échange se trouve dans un état incohérent en interne. Il est possible de remédier à ce problème en réessayant l'opération (par exemple, beginFrame()) ultérieurement.
QRhi::FrameOpDeviceLost3Le périphérique graphique a été perdu. Il est possible de remédier à ce problème en réessayant l’opération (par exemple, ` beginFrame()`) après avoir libéré et réinitialisé tous les objets s’appuyant sur des ressources graphiques natives. Voir ` isDeviceLost()`.

enum QRhi::Implementation

Indique quel backend spécifique à une API graphique est utilisé par une instance de ` QRhi `.

ConstanteValeur
QRhi::Null0
QRhi::Vulkan1
QRhi::OpenGLES22
QRhi::D3D113
QRhi::D3D125
QRhi::Metal4

enum QRhi::ResourceLimit

Décrit la limite de ressources à interroger.

ConstanteValeurDescription
QRhi::TextureSizeMin1Largeur et hauteur minimales de la texture. Cette valeur est généralement égale à 1. La taille minimale de la texture est gérée de manière souple : ainsi, toute tentative de création d’une texture de taille nulle entraînera la création d’une texture de taille minimale.
QRhi::TextureSizeMax2Largeur et hauteur maximales de la texture. Ces valeurs dépendent de l’API graphique et, parfois, de la plateforme ou de l’implémentation. En général, elles sont comprises entre 4096 et 16384. Toute tentative de création de textures dépassant ces limites échouera.
QRhi::MaxColorAttachments3Nombre maximal de pièces jointes de couleur pour une cible de rendu ( QRhiTextureRenderTarget), dans le cas où plusieurs cibles de rendu sont prises en charge. Lorsque le MRT n’est pas pris en charge, la valeur est 1. Sinon, elle est généralement de 8, mais il faut noter qu’OpenGL n’impose que 4 comme minimum, et c’est ce que fournissent certaines implémentations d’OpenGL ES.
QRhi::FramesInFlight4Le nombre d’images que le backend peut conserver « en cours de traitement » : avec des backends tels que Vulkan ou Metal, il incombe à l’ QRhi de se bloquer chaque fois qu’il démarre une nouvelle image et constate que le CPU a déjà une avance d’ N - 1 s d’images sur le GPU (car le tampon de commandes soumis dans l’image n° current - N n’est pas encore terminé). La valeur N est celle renvoyée par cette fonction ; elle est généralement égale à 2. Cela peut s’avérer pertinent pour les applications qui intègrent un rendu effectué directement via l’API graphique, car ce code de rendu peut nécessiter une double mise en mémoire tampon (si la valeur est égale à 2) pour les ressources, telles que les tampons, à l’instar des backends QRhi eux-mêmes. L’index de l’emplacement de l’image en cours (une valeur allant de 0, 1, …, N-1, puis recommençant depuis le début) peut être récupéré via ` QRhi::currentFrameSlot()`. La valeur est égale à 1 pour les backends où l’API graphique n’offre pas un tel contrôle de bas niveau sur le processus de soumission des commandes. Notez que le pipelining peut tout de même se produire même lorsque cette valeur est égale à 1 (certains backends, tels que D3D11, sont conçus pour tenter de l’activer, par exemple en utilisant une stratégie de mise à jour des tampons uniformes qui ne bloque pas le pipeline), mais cela n’est alors pas contrôlé par QRhi et n’est donc pas pris en compte ici dans l’API.
QRhi::MaxAsyncReadbackFrames5Nombre d’images d’ submitted (y compris celle contenant la relecture) après lequel une relecture asynchrone de texture ou de tampon est garantie d’être terminée lors de l’appel ` starting a new frame`.
QRhi::MaxThreadGroupsPerDimension6Le nombre maximal de groupes de travail de calcul/de threads pouvant être répartis. Il s’agit en fait de la valeur maximale pour les arguments de QRhiCommandBuffer::dispatch(). Généralement 65 535.
QRhi::MaxThreadsPerThreadGroup7Nombre maximal d’invocations dans un même groupe de travail local ou, en d’autres termes, nombre maximal de threads dans un groupe de threads. Il s'agit en réalité de la valeur maximale du produit de local_size_x, local_size_y et local_size_z dans le shader de calcul. Les valeurs courantes sont 128, 256, 512, 1 024 ou 1 536. Attention : OpenGL ES et Vulkan spécifient tous deux 128 comme limite minimale requise pour les implémentations. Bien que cela soit rare pour Vulkan, certaines implémentations d’OpenGL ES 3.1 destinées aux appareils mobiles ou embarqués ne prennent en charge que la valeur minimale imposée par la spécification.
QRhi::MaxThreadGroupX8La taille maximale d’un groupe de travail/de threads dans la dimension X. Il s’agit en fait de la valeur maximale de ` local_size_x ` dans le shader de calcul. Généralement 256 ou 1 024.
QRhi::MaxThreadGroupY9La taille maximale d’un groupe de travail/de threads dans la dimension Y. Il s’agit en fait de la valeur maximale de ` local_size_y ` dans le shader de calcul. Généralement 256 ou 1 024.
QRhi::MaxThreadGroupZ10Taille maximale d’un groupe de travail/de threads dans la dimension Z. Il s’agit en fait de la valeur maximale de ` local_size_z ` dans le shader de calcul. Généralement 64 ou 256.
QRhi::TextureArraySizeMax11Taille maximale du tableau de textures. Elle se situe généralement entre 256 et 2048. Toute tentative d’ create a texture array ation d’un nombre d’éléments supérieur à cette limite échouera probablement.
QRhi::MaxUniformBufferRange12Nombre d’octets pouvant être exposés simultanément depuis un tampon uniforme vers les shaders. Dans les implémentations OpenGL ES 2.0 et 3.0, cette valeur peut être aussi faible que 3 584 octets (224 vecteurs à quatre composantes, 32 bits par composante). Ailleurs, la valeur est généralement de 16 384 (1 024 vec4) ou de 65 536 (4 096 vec4).
QRhi::MaxVertexInputs13Nombre d’attributs d’entrée vers le shader de sommets. L’emplacement dans une QRhiVertexInputAttribute doit se situer dans l’intervalle [0, MaxVertexInputs-1]. La valeur peut être aussi faible que 8 avec OpenGL ES 2.0. Ailleurs, les valeurs courantes sont 16, 31 ou 32.
QRhi::MaxVertexOutputs14Nombre maximal de sorties (variables d’ out à vecteur à 4 composantes) du shader de sommets. La valeur peut être aussi faible que 8 avec OpenGL ES 2.0, et 15 avec OpenGL ES 3.0 et certains périphériques Metal. Dans les autres cas, la valeur typique est 32.
QRhi::ShadingRateImageTileSize15La taille de tuile pour les textures de taux d’ombrage. 0 si la fonctionnalité d’ QRhi::VariableRateShadingMapWithTexture n n’est pas prise en charge. Sinon, une valeur telle que 16, indiquant, par exemple, une taille de tuile de 16x16. Chaque octet de la texture de taux d’ombrage (R8UI) définit alors le taux d’ombrage pour une tuile de 16x16 pixels. Voir QRhiShadingRateMap pour plus de détails.

Documentation des fonctions membres

[noexcept] QRhi::~QRhi()

Destructeur. Détruit le backend et libère les ressources.

void QRhi::addCleanupCallback(const QRhi::CleanupCallback &callback)

Enregistre une fonction ` callback ` qui sera appelée lors de la destruction de l'QRhi.

La fonction de rappel s’exécutera alors que la ressource graphique est encore disponible, ce qui permet à l’application de libérer proprement les instances de ` QRhiResource ` appartenant à l’ QRhi. Ceci est particulièrement utile pour gérer la durée de vie des ressources stockées dans des objets de type ` cache `, où le cache contient des `QRhiResources` ou des objets contenant des `QRhiResources`.

Voir également ~QRhi().

void QRhi::addCleanupCallback(const void *key, const QRhi::CleanupCallback &callback)

Enregistre la fonction de rappel callback, qui sera appelée lors de la destruction de l'QRhi. Cette surcharge prend un pointeur opaque, key, qui sert à garantir qu'un rappel donné ne soit enregistré (et donc appelé) qu'une seule fois.

Il s'agit d'une fonction surchargée.

Voir également removeCleanupCallback().

QRhi::Implementation QRhi::backend() const

Renvoie le type de backend associé à cette QRhi.

const char *QRhi::backendName() const

Renvoie le type du backend sous forme de chaîne de caractères pour cette QRhi.

[static] const char *QRhi::backendName(QRhi::Implementation impl)

Renvoie un nom descriptif pour le backend impl, généralement le nom de l'API 3D utilisée.

QRhi::FrameOpResult QRhi::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags = {})

Lance une nouvelle image en ciblant le prochain tampon disponible de swapChain.

Une trame se compose de mises à jour des ressources et d’un ou plusieurs passages de rendu et de calcul.

flags peut indiquer certains cas particuliers.

Le schéma général du rendu dans une chaîne de swap ( QWindow ) à l’aide d’une swapchain :

  • Créez une chaîne d’échange.
  • Appeler ` QRhiSwapChain::createOrResize()` chaque fois que la taille de la surface diffère de la précédente.
  • Appeler ` QRhiSwapChain::destroy()` sur ` QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed`.
  • Puis, à chaque image :
    beginFrame(sc);
    updates = nextResourceUpdateBatch();
    updates->...
    QRhiCommandBuffer *cb = sc->currentFrameCommandBuffer();
    cb->beginPass(sc->currentFrameRenderTarget(), colorClear, dsClear, updates);
    ...
    cb->endPass();
    ... // more passes as necessary
    endFrame(sc);

Renvoie ` QRhi::FrameOpSuccess ` en cas de succès, ou une autre valeur de ` QRhi::FrameOpResult ` en cas d’échec. Certaines de ces erreurs doivent être considérées comme des erreurs « légères », du type « réessayer plus tard » : lorsque ` QRhi::FrameOpSwapChainOutOfDate ` est renvoyé, la swapchain doit être redimensionnée ou mise à jour en appelant ` QRhiSwapChain::createOrResize()`. L’application doit alors tenter de générer une nouvelle image. La valeur « QRhi::FrameOpDeviceLost » signifie que le périphérique graphique est perdu, mais il est parfois possible de le récupérer en libérant toutes les ressources, y compris l’ QRhi e lui-même, puis en recréant toutes les ressources. Voir isDeviceLost() pour plus de détails.

Voir également endFrame(), beginOffscreenFrame() et isDeviceLost().

QRhi::FrameOpResult QRhi::beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags = {})

Lance une nouvelle image hors écran. Fournit un tampon de commandes permettant d’enregistrer les commandes de rendu dans ` cb`. La valeur ` flags ` est utilisée pour signaler certains cas particuliers, tout comme avec la fonction ` beginFrame()`.

Remarque : l’ QRhiCommandBuffer stockée dans *cb n’appartient pas à l’appelant.

Le rendu sans swapchain est également possible. Le cas d’utilisation typique consiste à l’utiliser dans des applications entièrement hors écran, par exemple pour générer des séquences d’images en effectuant un rendu puis une relecture sans jamais afficher de fenêtre.

L’utilisation dans des applications à l’écran (c’est-à-dire beginFrame, endFrame, beginOffscreenFrame, endOffscreenFrame, beginFrame, etc.) est également possible.

Lorsqu’une lecture texture ou buffer est programmée, les images hors écran empêchent le processeur de générer une autre image pendant que le GPU traite encore la précédente. Cela a pour effet secondaire que, si des lectures sont programmées, les résultats sont garantis d’être disponibles dès que endOffscreenFrame() renvoie une valeur. Ce n’est pas le cas avec les images ciblant une chaîne d’échange : dans ce cas, le GPU est potentiellement mieux exploité, mais l’utilisation des opérations de relecture nécessite davantage de précautions de la part de l’application, car la fonction endFrame(), contrairement à endOffscreenFrame(), ne garantit pas que les résultats de la relecture soient disponibles à ce moment-là.

Le schéma de base pour afficher une image sans swapchain, puis relire son contenu, pourrait ressembler à ceci :

QRhiReadbackResult rbResult;
QRhiCommandBuffer *cb;
rhi->beginOffscreenFrame(&cb);
cb->beginPass(rt, colorClear, dsClear);
// ...
u = nextResourceUpdateBatch();
u->readBackTexture(rb, &rbResult);
cb->endPass(u);
rhi->endOffscreenFrame();
// image data available in rbResult

Voir également endOffscreenFrame() et beginFrame().

QMatrix4x4 QRhi::clipSpaceCorrMatrix() const

Renvoie une matrice permettant aux applications de continuer à utiliser des données de sommets et des matrices de projection en perspective destinées à OpenGL (telles que celles générées par QMatrix4x4::perspective()), quel que soit le backend QRhi actif.

Dans un moteur de rendu classique, dès lors que ` this_matrix * mvp ` est utilisé à la place de ` mvp`, les données de sommets avec l’axe Y vers le haut et les fenêtres d’affichage avec une plage de profondeur comprise entre 0 et 1 peuvent être utilisées sans se soucier du backend (et donc de l’API graphique) qui sera utilisé lors de l’exécution. De cette manière, on peut éviter les branchements basés sur isYUpInNDC() et isClipDepthZeroToOne() (même si une telle logique peut encore s’avérer nécessaire lors de la mise en œuvre de certaines techniques graphiques avancées).

Consultez cette page pour une analyse de ce sujet du point de vue de Vulkan.

[static] QRhi *QRhi::create(QRhi::Implementation impl, QRhiInitParams *params, QRhi::Flags flags, QRhiNativeHandles *importDevice, QRhiAdapter *adapter)

Renvoie une nouvelle instance de ` QRhi ` avec un backend pour l’API graphique spécifiée par ` impl `, ainsi que le ` flags` indiqué. Renvoie ` nullptr ` en cas d’échec de la fonction.

params doit pointer vers une instance de l’une des sous-classes spécifiques au backend de ` QRhiInitParams`, telles que ` QRhiVulkanInitParams`, ` QRhiMetalInitParams`, ` QRhiD3D11InitParams`, ` QRhiD3D12InitParams` ou ` QRhiGles2InitParams`. Consultez ces classes pour obtenir des exemples de création d’un ` QRhi`.

QRhi Par conception, aucune logique de repli n’est implémentée : si l’API spécifiée ne peut pas être initialisée, la méthode create() échouera et des avertissements seront affichés dans la sortie de débogage par les backends. Les clients de QRhi, par exemple Qt Quick, peuvent toutefois fournir une logique supplémentaire permettant de se rabattre sur une API différente de celle qui a été demandée, en fonction de la plateforme. Si l’intention est simplement de tester si l’initialisation aboutirait en appelant `create()` ultérieurement, il est préférable d’utiliser ` probe()` plutôt que `create()`, car avec certains backends, la détection peut être implémentée de manière plus légère, contrairement à `create()`, qui effectue une initialisation complète de l’infrastructure et constitue un gaspillage si cette instance de ` QRhi ` est ensuite immédiatement supprimée.

importDevice Permet d’utiliser un périphérique graphique déjà existant, sans que ` QRhi ` ne crée le sien. Lorsqu’il n’est pas nul, ce paramètre doit pointer vers une instance de l’une des sous-classes de ` QRhiNativeHandles` : ` QRhiVulkanNativeHandles`, ` QRhiD3D11NativeHandles`, ` QRhiD3D12NativeHandles`, ` QRhiMetalNativeHandles`, ` QRhiGles2NativeHandles`. Les détails précis et la sémantique dépendent du backend et de l’API graphique sous-jacente.

La spécification d’un « QRhiAdapter » dans ` adapter ` offre une alternative transparente et indépendante de l’API au passage d’un « VkPhysicalDevice » via ` QRhiVulkanNativeHandles` ou d’un «adapter LUID» via ` QRhiD3D12NativeHandles`. La propriété de ` adapter ` n’est pas prise en charge. Voir ` enumerateAdapters()` pour plus d’informations sur cette approche.

Remarque : il n'est pas possible de spécifier à la foisimportDevice et adapter.

Voir également probe().

[static] QRhi *QRhi::create(QRhi::Implementation impl, QRhiInitParams *params, QRhi::Flags flags = {}, QRhiNativeHandles *importDevice = nullptr)

Équivalent à create(impl, params, flags, importDevice, nullptr).

Il s'agit d'une fonction surchargée.

int QRhi::currentFrameSlot() const

Renvoie l'index de l'emplacement de l'image en cours lors de l'enregistrement d'une image. Non spécifié lorsqu'il est appelé en dehors d'une image active (c'est-à-dire lorsque isRecordingFrame() est false).

Avec des backends tels que Vulkan ou Metal, il incombe au backend QRhi de se bloquer chaque fois qu’une nouvelle image est lancée et qu’il constate que le CPU a déjà FramesInFlight - 1 d’images d’avance sur le GPU (car le tampon de commandes soumis dans l’image n° current - FramesInFlight n’est pas encore terminé).

Les ressources susceptibles de changer d’une image à l’autre (telles que l’objet tampon natif sous-jacent à un QRhiBuffer de type QRhiBuffer::Dynamic) existent en plusieurs versions, de sorte que chaque image, qui peut être soumise alors qu’une précédente est encore en cours de traitement, fonctionne avec sa propre copie, évitant ainsi de bloquer le pipeline lors de la préparation de l’image. (Le contenu d’une ressource pouvant encore être utilisée par le GPU ne doit pas être modifié, mais se contenter d’attendre systématiquement la fin de l’image précédente réduirait l’utilisation du GPU et, en fin de compte, les performances et l’efficacité.)

D’un point de vue conceptuel, cela s’apparente quelque peu aux mécanismes de « copie à l’écriture » (copy-on-write) utilisés par certains conteneurs C++ et d’autres types de données. Cela peut également s’apparenter à ce qu’une implémentation OpenGL ou Direct 3D 11 effectue en interne pour certains types d’objets.

En pratique, ce double (ou triple) tampon de ressources est mis en œuvre dans les backends Vulkan, Metal et d’ QRhi s similaires en plaçant un nombre fixe d’ slots s de ressources natives (telles que VkBuffer) derrière une QRhiResource. Celles-ci peuvent ensuite être indexées par un index de créneau d’image allant de 0, 1, …, FramesInFlight-1, puis recommençant depuis le début.

Tout cela est géré de manière transparente pour les utilisateurs de QRhi. Cependant, les applications qui intègrent un rendu effectué directement via l’API graphique peuvent souhaiter mettre en place un double ou triple buffering similaire pour leurs propres ressources graphiques. Le moyen le plus simple d’y parvenir consiste à connaître le nombre maximal d’images en cours de traitement (accessible via resourceLimit()) et l’index de l’image (emplacement) actuelle (renvoyé par cette fonction).

Voir également isRecordingFrame(), beginFrame() et endFrame().

QRhiDriverInfo QRhi::driverInfo() const

Renvoie les métadonnées relatives au périphérique graphique utilisé par cette instance d'QRhi, dont l'initialisation a réussi.

QRhi::FrameOpResult QRhi::endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags = {})

Termine, valide et présente un cadre qui avait été lancé lors du dernier appel à beginFrame() sur swapChain.

La gestion de la mise en mémoire tampon double (ou triple) est assurée en interne par les fonctions QRhiSwapChain et QRhi.

flags peut être utilisé de manière facultative pour modifier le comportement de certaines façons. Le passage de QRhi::SkipPresent permet d’éviter la mise en file d’attente de la commande Present ou l’appel de swapBuffers.

Renvoie QRhi::FrameOpSuccess en cas de succès, ou une autre valeur QRhi::FrameOpResult en cas d’échec. Certaines de ces valeurs doivent être considérées comme des erreurs « légères », du type « réessayer plus tard » : lorsque QRhi::FrameOpSwapChainOutOfDate est renvoyé, la chaîne de swap doit être redimensionnée ou mise à jour en appelant QRhiSwapChain::createOrResize(). L’application doit alors tenter de générer une nouvelle image. La valeur « QRhi::FrameOpDeviceLost » signifie que le périphérique graphique est perdu, mais il est parfois possible de le récupérer en libérant toutes les ressources, y compris l’ QRhi e elle-même, puis en recréant toutes les ressources. Voir isDeviceLost() pour plus de détails.

Voir également beginFrame() et isDeviceLost().

QRhi::FrameOpResult QRhi::endOffscreenFrame(QRhi::EndFrameFlags flags = {})

Termine, envoie et attend éventuellement l'image hors écran.

Contrairement à ` endFrame()`, cette fonction se bloque et attend la fin du travail côté GPU lorsqu'il y a des relectures actives de tampons ou de textures.

flags N’est pas utilisée actuellement.

Voir également beginOffscreenFrame().

[static, since 6.10] QRhi::AdapterList QRhi::enumerateAdapters(QRhi::Implementation impl, QRhiInitParams *params, QRhiNativeHandles *nativeHandles = nullptr)

Renvoie la liste des adaptateurs (périphériques physiques) présents, ou une liste vide lorsque cette fonctionnalité n'est pas disponible avec l'API graphique donnée.

Dans les backends où ce niveau de contrôle n'est pas disponible, la liste renvoyée est toujours vide. Ainsi, une liste vide n'indique pas qu'il n'y a pas de périphériques graphiques dans le système, mais que le contrôle fin permettant de sélectionner celui à utiliser n'est pas disponible.

On peut s'attendre à ce que les backends pour Direct 3D 11, Direct 3D 12 et Vulkan prennent entièrement en charge l'énumération des adaptateurs. Ce n'est pas forcément le cas des autres. Le backend est spécifié par ` impl`. Un objet ` QRhiAdapter ` renvoyé par cette fonction ne doit être utilisé que dans un appel à ` create()` avec le même ` impl`. Certaines API sous-jacentes peuvent présenter des limitations supplémentaires ; avec Vulkan en particulier, l’ QRhiAdapter est spécifié par ` QVulkanInstance ` (VkInstance).

L’appelant est censé détruire les objets QRhiAdapter figurant dans la liste. Hormis l’interrogation de info(), le seul but de ces objets est d’être transmis à create(), ou aux fonctions correspondantes dans les couches supérieures telles que Qt Quick.

L’extrait de code suivant, écrit spécifiquement pour Vulkan, montre comment énumérer les périphériques physiques disponibles et demander la création d’un ` QRhi ` pour celui choisi. En pratique, cela revient à transmettre un ` VkPhysicalDevice ` via un ` QRhiVulkanNativeHandles ` à ` create()`, mais cela implique moins de code spécifique à l’API du côté de l’application :

QRhiVulkanInitParams initParams;
initParams.inst = &vulkanInstance;
QRhi::AdapterList adapters = QRhi::enumerateAdapters(QRhi::Vulkan, &initParams);
QRhiAdapter*chosenAdapter = nullptr;
for (QRhiAdapter*adapter: adapters) {
    if (looksGood(adapter->info())) {
        chosenAdapter = adapter;
        break;
    }
}
QRhi*rhi = QRhi::create(QRhi::Vulkan, &initParams, {}, nullptr, chosenAdapter);
qDeleteAll(adapters);

La transmission d'un objet ` params ` est obligatoire en raison de la conception de certaines API graphiques sous-jacentes. Avec Vulkan en particulier, l'QVulkanInstance doit être fourni, car l'énumération n'est pas possible sans lui. Les autres champs de l'params, spécifiques au backend, ne seront en réalité pas utilisés par cette fonction.

nativeHandles est facultatif. Lorsqu’il est spécifié, il doit s’agir d’un QRhiD3D11NativeHandles, d’un QRhiD3D12NativeHandles ou d’un QRhiVulkanNativeHandles valide, de la même manière que pour la fonction create(). Cependant, contrairement à la fonction create(), seuls les champs relatifs au périphérique physique (dans le cas de Vulkan) ou au LUID de l’adaptateur (dans le cas de D3D) sont utilisés ; tous les autres champs sont ignorés. Cela permet de limiter les résultats à un adaptateur donné. Dans ce cas, la liste renvoyée contiendra 1 ou 0 élément.

Notez que, dans l’extrait de code précédent, l’implémentation de la fonction looksGood() ne peut effectuer aucun filtrage spécifique à la plateforme basé sur l’identité réelle de l’adaptateur ou du périphérique physique, telle que le LUID de l’adaptateur sous Windows ou le VkPhysicalDevice avec Vulkan. En effet, la fonction QRhiDriverInfo ne contient pas de données spécifiques à la plateforme. Utilisez plutôt ` nativeHandles ` pour obtenir des résultats déjà filtrés au sein même de la fonction `enumerateAdapters()`.

Les deux extraits de code suivants, qui prennent Direct 3D 12 comme exemple, sont équivalents en pratique :

// Approche basée sur `enumerateAdapters` à partir de Qt 6.10
QRhiD3D12InitParams initParams;
QRhiD3D12NativeHandles nativeHandles;
nativeHandles.adapterLuidLow = luid.LowPart; // LUID récupéré ailleurs, à transmettre maintenant à Qt
nativeHandles.adapterLuidHigh = luid.HighPart;
QRhi::AdapterList adapters = QRhi::enumerateAdapters(QRhi::D3D12, &initParams, &nativeHandles);
if (adapters.isEmpty()) { qWarning("L'adaptateur demandé est introuvable"); }
QRhi*rhi = QRhi::create(QRhi::D3D12, &initParams, {}, nullptr, adapters[0]);
qDeleteAll(adapters);
// traditional approach, more lightweight
QRhiD3D12InitParams initParams;
QRhiD3D12NativeHandles nativeHandles;
nativeHandles.adapterLuidLow = luid.LowPart; // retrieved a LUID from somewhere, now pass it on to Qt
nativeHandles.adapterLuidHigh = luid.HighPart;
QRhi *rhi = QRhi::create(QRhi::D3D12, &initParams, {}, &nativeHandles, nullptr);

Cette fonction a été introduite dans Qt 6.10.

Voir également create().

QRhi::FrameOpResult QRhi::finish()

Attend que toutes les tâches de la file d'attente graphique (le cas échéant) soient terminées, puis exécute toutes les opérations différées, telles que la finalisation des relectures et la libération des ressources. Peut être appelée à l'intérieur ou à l'extérieur d'une image, mais pas à l'intérieur d'un passage. À l'intérieur d'une image, cela implique la soumission de toutes les tâches présentes dans le tampon de commandes.

Remarque : évitez d’utiliser cette fonction. Elle peut s’avérer nécessaire dans un cas précis : lorsque les résultats d’une relecture mise en file d’attente dans une trame basée sur une chaîne d’échange (swapchain) sont requis à un moment donné et fixe, et qu’il est donc souhaitable d’attendre ces résultats.

bool QRhi::isClipDepthZeroToOne() const

Renvoie true si l'API graphique sous-jacente utilise une plage de profondeur [0, 1] dans l'espace de découpage.

En pratique, cette valeur est false uniquement pour OpenGL, car OpenGL utilise une plage de profondeur post-projection comprise entre [-1, 1]. (À ne pas confondre avec le mappage NDC-fenêtre contrôlé par glDepthRange(), qui utilise une plage comprise entre [0, 1], sauf si elle est redéfinie par l’ QRhiViewport.) Dans certaines versions d’OpenGL, la fonction glClipControl() pouvait être utilisée pour modifier cela, mais le backend OpenGL de QRhi n’utilise pas cette fonction, car elle n’est pas disponible dans OpenGL ES ni dans les versions d’OpenGL antérieures à la version 4.5.

Remarque : la fonction ` clipSpaceCorrMatrix()` inclut l’ajustement correspondant dans la matrice qu’elle renvoie. Par conséquent, la plupart des utilisateurs de QRhi n’ont pas besoin de prendre d’autres mesures que de pré-multiplier leurs matrices de projection par clipSpaceCorrMatrix(). Cependant, certaines techniques graphiques, telles que certains types de shadow mapping, impliquent de manipuler et de générer des valeurs de profondeur dans les shaders. Celles-ci devront interroger cette fonction et prendre en compte sa valeur de manière appropriée.

bool QRhi::isDeviceLost() const

Renvoie « true » si le périphérique graphique a été perdu.

La perte du périphérique est généralement détectée dans ` beginFrame()`, ` endFrame()` ou ` QRhiSwapChain::createOrResize()`, selon le backend et les API natives sous-jacentes. Le cas le plus courant est ` endFrame()`, car c’est là que s’effectue l’affichage. Avec certains backends, ` QRhiSwapChain::createOrResize()` peut également échouer en raison d’une perte de périphérique. Cette fonction est donc fournie comme moyen générique de vérifier si une perte de périphérique a été détectée par une opération précédente.

Lorsque le périphérique est perdu, aucune autre opération ne doit être effectuée via ` QRhi`. Il convient plutôt de libérer toutes les ressources ` QRhi `, puis de détruire ` QRhi`. On peut alors tenter de créer un nouveau ` QRhi `. En cas de succès, toutes les ressources graphiques doivent être réinitialisées. Dans le cas contraire, réessayer plus tard, à plusieurs reprises.

Si les applications simples peuvent choisir de ne pas tenir compte de la perte d’un périphérique, sur les plateformes de bureau couramment utilisées, une telle perte peut survenir pour diverses raisons, notamment la déconnexion physique de la carte graphique, la désactivation du périphérique ou du pilote, la désinstallation ou la mise à jour du pilote graphique, ou encore à la suite d’erreurs entraînant une réinitialisation du périphérique graphique. Certaines de ces situations peuvent également se produire dans des circonstances tout à fait normales ; par exemple, la mise à jour du pilote graphique vers une version plus récente est une opération courante qui peut survenir à tout moment pendant l’exécution d’une application Qt. Les utilisateurs sont tout à fait en droit de s’attendre à ce que les applications puissent résister à cela, même lorsque l’application utilise activement une API telle qu’OpenGL ou Direct3D.

On peut s’attendre à ce que les frameworks propres à Qt, basés sur QRhi, tels que Qt Quick, gèrent ces situations et prennent les mesures appropriées en cas de perte d’un périphérique. Si les données relatives aux ressources graphiques, telles que les textures et les tampons, sont toujours disponibles côté CPU, un tel événement peut ne pas être perceptible du tout au niveau de l’application, car les ressources graphiques peuvent alors être réinitialisées de manière transparente. Cependant, les applications et bibliothèques fonctionnant directement avec QRhi doivent être préparées à vérifier et à gérer elles-mêmes les situations de perte de périphérique.

Remarque : avec OpenGL, les applications peuvent avoir besoin d’activer les notifications de réinitialisation de contexte en définissant ` QSurfaceFormat::ResetNotification ` sur ` QOpenGLContext`. Cela s’effectue généralement en activant l’indicateur dans ` QRhiGles2InitParams::format`. Gardez toutefois à l’esprit que certains systèmes peuvent générer des situations de réinitialisation de contexte même lorsque cet indicateur n’est pas activé.

bool QRhi::isFeatureSupported(QRhi::Feature feature) const

Renvoie « true » si l'feature spécifiée est prise en charge

bool QRhi::isRecordingFrame() const

Renvoie « true » lorsqu'il existe une trame active, ce qui signifie qu'un appel à ` beginFrame()` (ou ` beginOffscreenFrame()`) a été effectué sans qu'il y ait encore d'appel correspondant à ` endFrame()` (ou ` endOffscreenFrame()`).

Voir également currentFrameSlot(), beginFrame() et endFrame().

bool QRhi::isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags = {}) const

Renvoie « true » si la texture spécifiée format, modifiée par flags, est prise en charge.

La requête est prise en charge aussi bien pour les formats non compressés que pour les formats compressés.

bool QRhi::isYUpInFramebuffer() const

Renvoie « true » si l'API graphique sous-jacente fait pointer l'axe Y vers le haut dans les tampons d'image et les images.

En pratique, cette valeur est « true » uniquement pour OpenGL.

bool QRhi::isYUpInNDC() const

Renvoie « true » si, dans le système de coordonnées normalisées du périphérique de l'API graphique sous-jacente, l'axe Y est orienté vers le haut.

En pratique, cette fonction renvoie « false » uniquement pour Vulkan.

Remarque : la fonction ` clipSpaceCorrMatrix()` inclut l'ajustement correspondant (pour que l'axe Y soit orienté vers le haut) dans la matrice qu'elle renvoie.

bool QRhi::makeThreadLocalNativeContextCurrent()

Avec OpenGL, cela rend le contexte OpenGL actif sur le thread actuel. La fonction n'a aucun effet avec d'autres backends.

L'appel de cette fonction est généralement pertinent dans le code du framework Qt, lorsqu'il faut s'assurer que le code OpenGL externe fourni par l'application puisse continuer à s'exécuter comme auparavant avec une utilisation directe d'OpenGL, tant que l'QRhi utilise le backend OpenGL.

Renvoie `false` en cas d'échec, de la même manière que ` QOpenGLContext::makeCurrent()`. Lorsque l'opération a échoué, on peut appeler ` isDeviceLost()` pour déterminer s'il y a eu perte de contexte. Une telle vérification équivaut à celle effectuée via ` QOpenGLContext::isValid()`.

Voir également QOpenGLContext::makeCurrent() et QOpenGLContext::isValid().

[static] int QRhi::mipLevelsForSize(const QSize &size)

Renvoie le nombre de niveaux de mip pour une ` size` donnée.

const QRhiNativeHandles *QRhi::nativeHandles()

Renvoie un pointeur vers la collection, spécifique au backend, d'objets natifs correspondant au périphérique, au contexte et aux concepts similaires utilisés par le backend.

Effectuez un transtypage vers QRhiVulkanNativeHandles, QRhiD3D11NativeHandles, QRhiD3D12NativeHandles, QRhiGles2NativeHandles ou QRhiMetalNativeHandles selon le cas.

Remarque : aucun transfert de propriété n’a lieu, ni pour le pointeur renvoyé, ni pour les objets natifs.

QRhiBuffer *QRhi::newBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, quint32 size)

Renvoie un nouveau tampon avec les paramètres type, usage et size spécifiés.

Remarque : certaines combinaisons de usage et type peuvent ne pas être prises en charge par tous les backends. Voir UsageFlags et the feature flags.

Remarque : les backends peuvent choisir d’allouer des tampons plus grands que size. Cela se fait de manière transparente pour les applications ; il n’y a donc aucune restriction particulière concernant la valeur de size. La fonction QRhiBuffer::size() renvoie toujours la valeur qui a été demandée dans size.

Voir également QRhiResource::destroy().

QRhiComputePipeline *QRhi::newComputePipeline()

Renvoie une nouvelle ressource de pipeline de calcul.

Remarque : la fonctionnalité « Compute » n'est disponible que lorsque la fonctionnalité « Compute » est signalée comme prise en charge.

Voir également QRhiResource::destroy().

QRhiGraphicsPipeline *QRhi::newGraphicsPipeline()

Renvoie une nouvelle ressource de pipeline graphique.

Voir aussi QRhiResource::destroy().

QRhiRenderBuffer *QRhi::newRenderBuffer(QRhiRenderBuffer::Type type, const QSize &pixelSize, int sampleCount = 1, QRhiRenderBuffer::Flags flags = {}, QRhiTexture::Format backingFormatHint = QRhiTexture::UnknownFormat)

Renvoie un nouveau tampon de rendu avec les paramètres suivants : ` type`, ` pixelSize`, ` sampleCount` et ` flags`.

Lorsque ` backingFormatHint ` est défini sur un format de texture autre que ` QRhiTexture::UnknownFormat`, il peut être utilisé par le backend pour déterminer le format à utiliser pour le support de stockage du tampon de rendu.

Remarque : backingFormatHint prend généralement toute son importance lorsque le multisampling et les formats de texture en virgule flottante sont impliqués : effectuer un rendu dans une texture multisample QRhiRenderBuffer puis la résoudre en une texture non-RGBA8 QRhiTexture implique (avec certaines API graphiques) que le support de stockage sous-jacent à l'QRhiRenderBuffer utilise le format non-RGBA8 correspondant. Cela signifie qu’il est important de passer un format tel que QRhiTexture::RGBA32F, car les backends opteront généralement par défaut pour QRhiTexture::RGBA8, ce qui entraînerait ensuite des dysfonctionnements en raison de la tentative de configuration d’une résolution multisample RGBA8->RGBA32F dans la ou les annexes de couleur de la QRhiTextureRenderTarget.

Voir également QRhiResource::destroy().

QRhiSampler *QRhi::newSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter, QRhiSampler::Filter mipmapMode, QRhiSampler::AddressMode addressU, QRhiSampler::AddressMode addressV, QRhiSampler::AddressMode addressW = QRhiSampler::Repeat)

Renvoie un nouvel échantillonneur avec le filtre de grossissement spécifié magFilter, le filtre de réduction minFilter, le mode de mipmapping mipmapMode, ainsi que les modes d'adressage (bouclage) addressU, addressV et addressW.

Remarque : définir ` mipmapMode ` sur une valeur autre que ` None ` implique que les images pour tous les niveaux de mip pertinents seront fournies soit via ` texture uploads `, soit en appelant ` generateMips()` sur la texture utilisée avec cet échantillonneur. Tenter d’utiliser l’échantillonneur avec une texture ne disposant pas de données pour tous les niveaux de mip pertinents entraînera des erreurs de rendu, le comportement exact dépendant de l’API graphique sous-jacente.

Voir également QRhiResource::destroy().

QRhiShaderResourceBindings *QRhi::newShaderResourceBindings()

Renvoie une nouvelle ressource de collection de liaisons de ressources de shaders.

Voir également QRhiResource::destroy().

[since 6.9] QRhiShadingRateMap *QRhi::newShadingRateMap()

Renvoie un nouvel objet « shading rate map ».

Cette fonction a été introduite dans Qt 6.9.

QRhiSwapChain *QRhi::newSwapChain()

Renvoie une nouvelle chaîne d'échange.

Voir également QRhiResource::destroy() et QRhiSwapChain::createOrResize().

QRhiTexture *QRhi::newTexture(QRhiTexture::Format format, const QSize &pixelSize, int sampleCount = 1, QRhiTexture::Flags flags = {})

Renvoie une nouvelle texture 1D ou 2D avec les paramètres spécifiés pour ` format`, ` pixelSize`, ` sampleCount` et ` flags`.

Une texture 1D doit avoir l'QRhiTexture::OneDimensional défini dans flags. Cette fonction définit implicitement cet indicateur si la hauteur pixelSize est égale à 0.

Remarque : format spécifie le format interne et externe requis, ce qui signifie que les données à charger dans la texture devront être dans un format compatible, tandis que la texture native peut (mais ce n’est pas garanti, du moins dans le cas d’OpenGL) utiliser ce format en interne.

Remarque : les textures1D ne fonctionnent que si la fonctionnalité OneDimensionalTextures est signalée comme prise en charge lors de l’exécution. De plus, les mipmaps sur les textures 1D ne fonctionnent que si la fonctionnalité OneDimensionalTextureMipmaps est signalée lors de l’exécution.

Voir également QRhiResource::destroy().

QRhiTexture *QRhi::newTexture(QRhiTexture::Format format, int width, int height, int depth, int sampleCount = 1, QRhiTexture::Flags flags = {})

Renvoie une nouvelle texture 1D, 2D ou 3D avec les paramètres spécifiés : format, width, height, depth, sampleCount et flags.

Cette surcharge est adaptée aux textures 3D car elle permet de spécifier l’ depth. Une texture 3D doit avoir l’ QRhiTexture::ThreeDimensional défini dans flags, mais avec cette surcharge, cela peut être omis car l’indicateur est défini implicitement dès lors que depth est supérieur à 0. Pour les textures 1D, 2D et cubiques, depth doit être défini sur 0.

Une texture 1D doit avoir le paramètre QRhiTexture::OneDimensional défini dans flags. Cette surcharge définira implicitement ce drapeau si height et depth sont tous deux égaux à 0.

Remarque : les textures3D ne fonctionnent que si la fonctionnalité « ThreeDimensionalTextures » est signalée comme prise en charge lors de l’exécution.

Remarque : les textures1D ne fonctionnent que si la fonctionnalité « OneDimensionalTextures » est signalée comme prise en charge lors de l’exécution. De plus, les mipmaps sur les textures 1D ne fonctionnent que si la fonctionnalité « OneDimensionalTextureMipmaps » est signalée lors de l’exécution.

Il s’agit d’une fonction surchargée.

QRhiTexture *QRhi::newTextureArray(QRhiTexture::Format format, int arraySize, const QSize &pixelSize, int sampleCount = 1, QRhiTexture::Flags flags = {})

Renvoie un nouveau tableau de textures 1D ou 2D avec les paramètres suivants : format, arraySize, pixelSize, sampleCount et flags.

Cette fonction définit implicitement ` QRhiTexture::TextureArray ` dans ` flags`.

Un tableau de textures 1D doit avoir le drapeau « QRhiTexture::OneDimensional » activé dans « flags ». Cette fonction activera implicitement ce drapeau si la hauteur de l'pixelSize est égale à 0.

Remarque : ne confondez pas les tableaux de textures avec les tableaux de textures. Un indicateur « QRhiTexture » créé par cette fonction est utilisable avec des échantillonneurs de tableaux 1D ou 2D dans le shader, par exemple : layout(binding = 1) uniform sampler2DArray texArr;. Les tableaux de textures font référence à une liste de textures exposées au shader via QRhiShaderResourceBinding::sampledTextures() avec un nombre > 1, et déclarées dans le shader, par exemple comme ceci : layout(binding = 1) uniform sampler2D textures[4];

Remarque : cette fonctionnalité n’est disponible que si la prise en charge de la fonction « TextureArrays » est signalée comme disponible lors de l’exécution.

Remarque : les textures1D ne fonctionnent que si la fonctionnalité « OneDimensionalTextures » est signalée comme prise en charge lors de l'exécution. De plus, les mipmaps sur les textures 1D ne fonctionnent que si la fonctionnalité « OneDimensionalTextureMipmaps » est signalée lors de l'exécution.

Voir également ` newTexture()`.

QRhiTextureRenderTarget *QRhi::newTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc, QRhiTextureRenderTarget::Flags flags = {})

Renvoie une nouvelle cible de rendu de texture avec les annexes de couleur et de profondeur/stencil spécifiées dans ` desc`, ainsi que l'flags` indiquée.

Voir également QRhiResource::destroy().

QRhiResourceUpdateBatch *QRhi::nextResourceUpdateBatch()

Renvoie un lot disponible et vide dans lequel des opérations de type « copie » peuvent être enregistrées.

Remarque : la valeur renvoyée n'appartient pas à l'appelant et ne doit en aucun cas être détruite. Le lot doit être restitué au pool pour être réutilisé, soit en le transmettant aux fonctions QRhiCommandBuffer::beginPass(), QRhiCommandBuffer::endPass() ou QRhiCommandBuffer::resourceUpdate(), soit en appelant la méthode QRhiResourceUpdateBatch::release() sur celui-ci.

Remarque : peut également être appelé en dehors de beginFrame() - endFrame(), car une instance de lot se contente de collecter des données de manière autonome ; elle n’effectue aucune opération.

Comme elle n’est pas liée à une image en cours d’enregistrement, la séquence suivante est valide, par exemple :

rhi->beginFrame(swapchain);
QRhiResourceUpdateBatch *u = rhi->nextResourceUpdateBatch();
u->uploadStaticBuffer(buf, data);
// ... do not commit the batch
rhi->endFrame();
// u stays valid (assuming buf stays valid as well)
rhi->beginFrame(swapchain);
swapchain->currentFrameCommandBuffer()->resourceUpdate(u);
// ... draw with buf
rhi->endFrame();

Avertissement : le nombre maximal de lots par QRhi est de 64. Lorsque cette limite est atteinte, la fonction renvoie null jusqu’à ce qu’un lot soit renvoyé au pool.

QByteArray QRhi::pipelineCacheData()

Renvoie un blob de données binaires contenant les données collectées à partir des objets ` QRhiGraphicsPipeline ` et ` QRhiComputePipeline ` créés avec succès pendant la durée de vie de cet objet ` QRhi`.

En enregistrant puis, lors des exécutions suivantes de la même application, en rechargeant les données mises en cache, il est possible de réduire les temps de création des pipelines et des shaders. Le contenu exact du cache et de sa version sérialisée n’est pas spécifié ; il dépend toujours du backend utilisé et, dans certains cas, de l’implémentation particulière de l’API graphique.

Lorsque l’ PipelineCacheDataLoadSave est signalé comme non pris en charge, l’ QByteArray renvoyé est vide.

Si l’indicateur d’ EnablePipelineCacheDataSave n’a pas été spécifié lors de l’appel de create(), l’ QByteArray renvoyé peut être vide, même lorsque la fonctionnalité d’ PipelineCacheDataLoadSave est prise en charge.

Lorsque les données renvoyées ne sont pas vides, elles sont toujours spécifiques à la version de Qt et au backend QRhi. De plus, dans certains cas, il existe une forte dépendance vis-à-vis du périphérique graphique et de la version exacte du pilote utilisé. La fonction ` QRhi ` se charge d’ajouter l’en-tête approprié et les mesures de sécurité garantissant que les données puissent toujours être transmises en toute sécurité à ` setPipelineCacheData()` ; ainsi, toute tentative de chargement de données provenant d’une exécution sur une autre version d’un pilote sera gérée de manière sûre et sans heurts.

Remarque : l’appel à releaseCachedResources() peut, selon le backend, effacer les données collectées dans le pipeline. Un appel ultérieur à cette fonction peut alors ne renvoyer aucune donnée.

Voir EnablePipelineCacheDataSave pour plus de détails sur cette fonctionnalité.

Remarque : réduisez au minimum le nombre d’appels à cette fonction. La récupération du blob n’est pas toujours une opération peu coûteuse ; cette fonction ne doit donc être appelée qu’à faible fréquence, idéalement une seule fois, par exemple lors de la fermeture de l’application.

Voir également setPipelineCacheData(), create() et isFeatureSupported().

[static] bool QRhi::probe(QRhi::Implementation impl, QRhiInitParams *params)

Renvoie « true » si l'on peut s'attendre à ce que la fonction create() aboutisse lorsqu'elle est appelée avec les paramètres impl et params fournis.

Pour certains backends, cela équivaut à appeler ` create()`, à vérifier sa valeur de retour, puis à détruire l’ QRhi résultant.

Pour d’autres, en particulier avec Metal, il peut exister une implémentation de sondage spécifique, qui permet d’effectuer des tests de manière plus légère sans polluer la sortie de débogage avec des avertissements en cas d’échec.

Voir également create().

void QRhi::releaseCachedResources()

Tente de libérer des ressources dans les caches du backend. Cela peut concerner aussi bien les ressources CPU que GPU. Seules la mémoire et les ressources pouvant être recréées automatiquement sont concernées. Par exemple, si l'implémentation de ` QRhiGraphicsPipeline ` du backend gère un cache des résultats de compilation des shaders, l'appel de cette fonction entraîne le vidage de ce cache, ce qui peut potentiellement libérer de la mémoire et des ressources graphiques.

L'appel de cette fonction est pertinent dans les environnements aux ressources limitées, où il devient nécessaire, à un certain moment, de garantir une utilisation minimale des ressources, au détriment des performances.

void QRhi::removeCleanupCallback(const void *key)

Désenregistre la fonction de rappel via key. Si aucune fonction de rappel de nettoyage n'a été enregistrée via key, la fonction ne fait rien. Les fonctions de rappel enregistrées sans clé ne peuvent pas être supprimées.

Voir également addCleanupCallback().

int QRhi::resourceLimit(QRhi::ResourceLimit limit) const

Renvoie la valeur de la ressource spécifiée limit.

Les valeurs sont censées être récupérées par les backends lors de l'initialisation, ce qui signifie que l'appel de cette fonction est une opération légère.

void QRhi::setPipelineCacheData(const QByteArray &data)

Charge la fonction data dans le cache du pipeline, le cas échéant.

Lorsque l'PipelineCacheDataLoadSave est signalée comme non prise en charge, la fonction peut être appelée en toute sécurité, mais n'a aucun effet.

Le blob renvoyé par ` pipelineCacheData()` est toujours spécifique à la version de Qt, au backend ` QRhi ` et, dans certains cas, également au périphérique graphique et à une version donnée du pilote graphique. ` QRhi ` se charge d’ajouter l’en-tête approprié et les mesures de sécurité garantissant que les données puissent toujours être transmises en toute sécurité à cette fonction. En cas d'incompatibilité, par exemple parce que le pilote a été mis à jour vers une version plus récente ou parce que les données ont été générées à partir d'un autre backend QRhi, un avertissement est affiché et data est ignorée en toute sécurité.

Avec Vulkan, cela correspond directement à `VkPipelineCache`. L’appel de cette fonction crée un nouvel objet de cache de pipeline Vulkan, dont les données initiales proviennent de ` data`. L’objet de cache de pipeline est ensuite utilisé par tous les objets ` QRhiGraphicsPipeline ` et ` QRhiComputePipeline ` créés par la suite, ce qui peut potentiellement accélérer la création du pipeline.

D'autres API ne disposent pas de véritable cache de pipeline, mais peuvent fournir un cache contenant du bytecode issu de la compilation de shaders (D3D) ou des binaires de programme (OpenGL). Dans les applications qui effectuent de nombreuses compilations de shaders à partir du code source lors de l’exécution, cela peut apporter un gain de performance significatif lors des exécutions suivantes si le « cache de pipeline » est prérempli à partir d’une exécution antérieure à l’aide de cette fonction.

Remarque : QRhi ne peut garantir que la fonction ` data ` ait un effet sur les performances de création du pipeline et des shaders. Avec des API telles que Vulkan, c’est au pilote de décider si la fonction ` data ` est utilisée à des fins spécifiques ou si elle est ignorée.

Consultez EnablePipelineCacheDataSave pour plus de détails sur cette fonctionnalité.

Remarque : ce mécanisme proposé par QRhi est indépendant du mécanisme de mise en cache interne propre au pilote, le cas échéant. Cela signifie que, selon l’API graphique et son implémentation, les effets exacts de la récupération puis du rechargement de data ne sont pas prévisibles. L’amélioration des performances peut ne pas être perceptible du tout si d’autres mécanismes de mise en cache, hors du contrôle de Qt, sont déjà actifs.

Remarque : réduisez au minimum le nombre d'appels à cette fonction. Le chargement du blob n'est pas toujours une opération peu coûteuse ; cette fonction ne doit donc être appelée qu'à faible fréquence, idéalement une seule fois, par exemple au démarrage de l'application.

Avertissement : les donnéessérialisées du cache du pipeline sont considérées comme du contenu fiable. Qt effectue une analyse rigoureuse de l’en-tête et des métadonnées incluses dans ` data` ; il est toutefois conseillé aux développeurs d’applications de ne jamais transmettre de données provenant de sources non fiables.

Voir également pipelineCacheData() et isFeatureSupported().

[since 6.9] void QRhi::setQueueSubmitParams(QRhiNativeHandles *params)

Avec les backends et les API graphiques concernés, cette fonction permet de fournir des arguments supplémentaires lors de la prochaine soumission de commandes à la file d’attente des commandes graphiques.

En particulier, avec Vulkan, cela permet de transmettre une liste d’objets sémaphores Vulkan que l’ vkQueueSubmit() doit signaler et sur lesquels elle doit attendre. params doit alors être un QRhiVulkanQueueSubmitParams. Cela s’avère essentiel dans certains cas d’utilisation avancés, par exemple lors de l’exécution d’appels Vulkan natifs impliquant de devoir attendre et signaler des VkSemaphores gérés par le code de rendu ou de calcul Vulkan personnalisé de l’application. De plus, cela permet également de spécifier des sémaphores supplémentaires sur lesquels attendre lors de la prochaine vkQueuePresentKHR().

Remarque : cette fonction n’affecte que la prochaine soumission à la file d’attente, qui aura lieu dans ` endFrame()`, ` endOffscreenFrame()` ou ` finish()`. La mise en file d’attente de `present` s’effectue dans ` endFrame()`.

Avec de nombreux autres backends, l’implémentation de cette fonction est une opération sans effet.

Cette fonction a été introduite dans Qt 6.9.

[static] QSize QRhi::sizeForMipLevel(int mipLevel, const QSize &baseLevelSize)

Renvoie la taille de l'image de texture pour un ` mipLevel` donné, calculée à partir de la taille de niveau 0 indiquée dans ` baseLevelSize`.

QRhiStats QRhi::statistics() const

Collecte et renvoie des statistiques sur les durées et les allocations des ressources graphiques.

Les données relatives aux allocations de mémoire ne sont disponibles qu'avec certains backends, où ces opérations sont contrôlées par Qt. Avec les API graphiques ne permettant pas de contrôle de bas niveau sur les allocations de mémoire des ressources, cette fonctionnalité ne sera jamais prise en charge et tous les champs concernés dans les résultats seront à 0.

Avec Vulkan en particulier, les valeurs sont toujours valides et sont extraites de la bibliothèque d’allocation de mémoire sous-jacente. Cela permet d’avoir un aperçu des besoins en mémoire des tampons et textures actifs.

Il en va de même pour Direct 3D 12. Outre les statistiques de la bibliothèque d’allocation de mémoire, le résultat inclut ici également un champ « totalUsageBytes » qui indique la taille totale, y compris les ressources supplémentaires qui ne relèvent pas du contrôle de la bibliothèque d’allocation de mémoire (tampons de swapchain, tas de descripteurs, etc.), telles que rapportées par DXGI.

Les valeurs correspondent à l’ensemble des types de mémoire utilisés (c’est-à-dire mémoire vidéo + mémoire système dans le cas d’un GPU discret).

Des données supplémentaires, telles que le temps total en millisecondes consacré à la création des pipelines graphiques et de calcul (ce qui implique généralement la compilation de shaders ou des recherches dans le cache, ainsi que des traitements potentiellement coûteux), sont disponibles avec la plupart des backends.

Remarque : les durées écoulées pour des opérations telles que la création de pipelines peuvent être influencées par divers facteurs. Les résultats ne doivent pas être comparés entre différents backends, car le concept de « pipelines » et ce qui se passe exactement en arrière-plan lors, par exemple, d’un appel à ` QRhiGraphicsPipeline::create()` diffèrent considérablement d’une API graphique à l’autre et selon leurs implémentations.

Remarque : de plus , de nombreux pilotes sont susceptibles d’employer diverses stratégies de mise en cache pour les shaders, les programmes et les pipelines (indépendamment des fonctionnalités similaires propres à Qt, telles que ` setPipelineCacheData()` ou le cache disque binaire de programmes spécifique à OpenGL). Ce comportement interne étant transparent pour le client de l’API, ni Qt ni QRhi n’ont connaissance ni contrôle sur la stratégie exacte de mise en cache, la persistance ou l’invalidation des données mises en cache, etc. Lors de l’analyse des temps d’exécution, tels que le temps passé à la création du pipeline, il convient de garder à l’esprit la présence potentielle et le comportement non spécifié des mécanismes de mise en cache au niveau du pilote.

QList<int> QRhi::supportedSampleCounts() const

Renvoie la liste des nombres d'échantillons pris en charge.

Un exemple typique serait (1, 2, 4, 8).

Avec certains backends, cette liste de valeurs prises en charge est définie à l’avance, tandis qu’avec d’autres, ce sont les propriétés (physiques) du périphérique qui indiquent ce qui est pris en charge au moment de l’exécution.

Voir également QRhiRenderBuffer::setSampleCount(), QRhiTexture::setSampleCount(), QRhiGraphicsPipeline::setSampleCount() et QRhiSwapChain::setSampleCount().

[since 6.9] QList<QSize> QRhi::supportedShadingRates(int sampleCount) const

Renvoie la liste des taux d'ombrage variables pris en charge pour l'sampleCount spécifiée.

La valeur 1x1 est toujours prise en charge.

Cette fonction a été introduite dans Qt 6.9.

QThread *QRhi::thread() const

Renvoie le thread sur lequel l'QRhi a été initialized.

int QRhi::ubufAligned(int v) const

Renvoie la valeur (généralement un décalage) v alignée selon l'alignement uniforme du tampon spécifié par ubufAlignment().

int QRhi::ubufAlignment() const

Renvoie l'alignement minimal en octets d'un tampon uniforme. Cette valeur est généralement de 256.

Toute tentative de liaison d'une région de tampon uniforme avec un décalage non aligné sur cette valeur entraînera des échecs, selon le backend et l'API graphique sous-jacente.

Voir également ubufAligned().

[static] QRhiSwapChainProxyData QRhi::updateSwapChainProxyData(QRhi::Implementation impl, QWindow *window)

Génère et renvoie une structure ` QRhiSwapChainProxyData ` contenant des données opaques spécifiques au backend et à l’API graphique spécifiés par ` impl`. ` window ` correspond à l’ QWindow e ciblée par une swapchain.

La structure renvoyée peut être transmise à ` QRhiSwapChain::setProxyData()` (). Cela s’avère utile dans les systèmes de rendu multithread : cette fonction statique est censée être appelée sur le thread principal (GUI), contrairement à toutes les opérations ` QRhi `, puis transférée au thread travaillant avec ` QRhi ` et ` QRhiSwapChain `, avant d’être transmise à la swapchain. Cela permet d’effectuer des requêtes natives de la plateforme qui ne peuvent être appelées en toute sécurité que sur le thread principal, par exemple pour interroger la CAMetalLayer à partir d’une NSView, puis de transmettre les données à l’ QRhiSwapChain, qui réside sur le thread de rendu. Dans l’exemple Metal, l’accès à view.layer sur un thread de rendu dédié déclenche un avertissement dans le Thread Checker de Xcode. Grâce au mécanisme de proxy de données, ce problème est évité.

Lorsque les threads ne sont pas impliqués, il n’est pas nécessaire de générer et de transmettre l’ QRhiSwapChainProxyData: les backends sont garantis de pouvoir interroger eux-mêmes tout ce qui est nécessaire, et si tout réside sur le thread principal (GUI), cela devrait suffire.

Remarque : l’ impl doit correspondre à ce avec quoi l’ QRhi a été créé. Par exemple, un appel à ` QRhi::Metal ` sur une plateforme non Apple ne générera aucune donnée utile.

Éléments non membres associés

[alias, since 6.7] QRhiShaderResourceBindingSet

Synonyme de « QRhiShaderResourceBindings ».

Ce typedef a été introduit dans Qt 6.7.

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