Sur cette page

QRhi Class

Abstraction de l'API graphique 2D/3D accélérée. Plus d'informations...

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, …, DepthClamp }
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 pour les API graphiques accélérées par le matériel, telles que, OpenGL, OpenGL ES, Direct3D, Metal, et Vulkan.

Avertissement : La famille de classes QRhi dans le module Qt GUI, y compris QShader et QShaderDescription, offre des garanties de compatibilité limitées. Il n'existe aucune garantie de compatibilité source ou binaire pour ces classes, ce qui signifie que l'API est uniquement garantie pour fonctionner avec la version de Qt avec laquelle l'application a été développée. Les changements incompatibles avec le code source sont toutefois réduits au minimum et ne seront apportés que dans les versions mineures (6.7, 6.8, etc.). Pour utiliser ces classes dans une application, créez un lien vers Qt::GuiPrivate (si vous utilisez CMake), et incluez les en-têtes avec le préfixe rhi, par exemple #include <rhi/qrhi.h>.

Chaque instance de QRhi est soutenue par un backend pour une API graphique spécifique. La sélection du backend est un choix au moment de l'exécution et dépend 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'elles sont exécutées sur la plateforme en question (Metal sur macOS/iOS, Direct3D sur Windows).

Les backends disponibles sont actuellement :

  • OpenGL 2.1 / OpenGL ES 2.0 ou plus récent. Certaines extensions et fonctionnalités plus récentes de la spécification de base sont utilisées lorsqu'elles sont présentes, par exemple pour activer les framebuffers multi-échantillons 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 le site feature flags au moment de l'exécution pour vérifier les fonctionnalités qui ne sont pas prises en charge dans le contexte OpenGL qui soutient le QRhi. Le backend OpenGL s'appuie sur QOpenGLContext, QOpenGLFunctions et l'infrastructure multiplateforme du module Qt GUI.
  • Direct3D 11.2 ou plus récent (avec DXGI 1.3 ou plus récent), utilisant Shader Model 5.0 ou plus récent. Lorsque le runtime D3D ne prend pas en charge les fonctionnalités 11.2 ou le Shader Model 5.0, l'initialisation à l'aide d'un périphérique graphique accéléré échoue, mais l'utilisation de l'adaptateur logiciel reste possible.
  • Direct3D 12 sur Windows 10 version 1703 ou plus récente, avec Shader Model 5.0 ou plus récent. Qt exige que ID3D12Device2 soit présent, d'où la nécessité d'avoir 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é minimum de D3D_FEATURE_LEVEL_11_0.
  • Metal 1.2 ou plus récent.
  • Vulkan 1.0 ou plus récent, utilisant éventuellement certaines fonctionnalités de niveau Vulkan 1.1.
  • Null, un backend "factice" qui n'émet aucun appel graphique.

Afin que le code des shaders puisse être écrit une seule fois dans les applications et les bibliothèques Qt, tous les shaders doivent être écrits dans un seul langage qui est ensuite compilé dans SPIR-V. Les versions des différents langages d'ombrage sont ensuite générées à partir de ce langage, avec les informations de réflexion (entrées, sorties, ressources d'ombrage). Ces informations sont ensuite regroupées dans des instances QShader facilement et efficacement sérialisables. Les compilateurs et les outils permettant de générer ces shaders ne font pas partie de QRhi et du module Qt GUI, mais les classes de base permettant d'utiliser ces shaders, QShader et QShaderDescription, en font partie. Les API et les outils de compilation et de traduction font partie du module Qt Shader Tools.

Voir l'exemple de fenêtre RHI pour un exemple d'introduction à la création d'une application portable et multiplateforme qui effectue un rendu 3D accéléré sur un site QWindow à l'aide de QRhi.

Une impression de l'API

Pour donner un aperçu rapide de l'API à l'aide d'un exemple court mais complet qui n'implique pas de configuration liée à la fenêtre, voici une application multiplateforme complète et exécutable qui effectue un 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 à partir du GPU. Pour un exemple de rendu à l'écran, qui implique la mise en place d'une QWindow et d'une swapchain, reportez-vous à l'exemple de fenêtre RHI.

Par souci de concision, l'initialisation du QRhi se fait en fonction de la plateforme : le code d'exemple ici choisit Direct 3D 12 sur Windows, Metal sur macOS et iOS, et Vulkan dans les autres cas. OpenGL et Direct 3D 11 ne sont jamais utilisés par cette application, mais leur support pourrait être introduit avec quelques lignes 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 ;#endifstd::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();
   autre        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 up, CCW0. 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::Dynamique,            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_ptr<QRhiGraphicsPipeline> ps(rhi->newGraphicsPipeline()) ; QRhiGraphicsPipeline::TargetBlend premulAlphaBlend ; 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(QLatin1Stringing("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_Premultiplié) ; if (rhi->isYUpInFramebuffer()) image.flip() ; image.save(QString::asprintf("frame%d.png", frame)) ; } return 0; }

Le résultat de l'application est 20 images PNG (frame0.png - frame19.png). Celles-ci contiennent un triangle en rotation avec une opacité variable sur un fond vert.

Les vertex et fragment shaders sont censés être traités et empaqueté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 transpiler manuellement ces shaders vers un certain nombre de cibles (SPIR-V, HLSL, MSL, GLSL) et générer les fichiers .qsb que l'application charge au moment de l'exécution, exécutez qsb --qt6 color.vert -o color.vert.qsb et qsb --qt6 color.frag -o color.frag.qsb. Alternativement, le module Qt Shader Tools offre une intégration du système de construction pour CMake, la fonction CMake qt_add_shaders(), qui peut réaliser la même chose au moment de la construction.

Considérations de sécurité

Toutes les données consommées par QRhi et les classes associées telles que QShader sont considérées comme des contenus de confiance.

Avertissement : Il est conseillé aux développeurs d'applications d'examiner attentivement les implications potentielles avant d'autoriser l'alimentation de contenu fourni par l'utilisateur qui ne fait pas partie de l'application et n'est pas sous le contrôle des développeurs. (Cela inclut toutes les données de vertex/index, les shaders, les paramètres de pipeline et d'appel de dessin, etc.)

Principes de conception

Un QRhi ne peut pas être instancié directement. Utilisez plutôt la fonction create(). Supprimez l'instance QRhi normalement 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 de QRhi, telles que newBuffer(), newTexture(), newTextureRenderTarget(), 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.
  • Le simple fait de créer une instance d'une sous-classe de QRhiResource n'alloue ni n'initialise aucune ressource native. Cela ne se fait que lors de l'appel à 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 ces fonctions et l'objet retourné est immédiatement actif.
  • Les objets ressources eux-mêmes sont considérés comme immuables : une fois qu'une ressource a été appelée par create(), la modification de tout paramètre via les setters, comme QRhiTexture::setPixelSize(), n'a aucun effet, à moins que la ressource native sous-jacente ne soit libérée et que create() ne soit appelée à nouveau. Pour en savoir plus sur la réutilisation des ressources, voir les sections ci-dessous.
  • Les ressources natives sous-jacentes sont programmées pour être libérées par le destructeur QRhiResource ou en appelant QRhiResource::destroy(). Les backends mettent souvent en file d'attente les demandes de libération et reportent leur exécution à un moment non spécifié, ce qui est caché aux applications. De cette manière, les applications n'ont pas à se soucier de libérer des ressources natives qui peuvent encore être utilisées par une trame en vol.
  • Il convient de noter que cela ne signifie pas qu'une page QRhiResource peut être librement détruite() ou supprimée à l'intérieur d'une trame (c'est-à-dire dans une section beginFrame() - 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 tâche, QRhiResource::deleteLater() est fourni à titre de commodité.

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

Indépendamment de la conception et des capacités de l'API graphique sous-jacente, tous les backends QRhi implémentent un certain niveau de tampons de commande. Aucune fonction QRhiCommandBuffer 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, soit native, soit fournie par le backend QRhi. Le tampon de commande est soumis, et l'exécution ne commence donc qu'à partir de QRhi::endFrame() ou QRhi::finish().

La nature différée a des conséquences pour certains types d'objets. Par exemple, écrire dans un tampon dynamique plusieurs fois dans un cadre, dans le cas où de tels tampons sont soutenus par une mémoire visible par l'hôte, aura pour conséquence de rendre les résultats de toutes les écritures visibles pour tous les appels de dessin dans le tampon de commande du cadre, indépendamment du moment où la mise à jour du tampon dynamique a été enregistrée par rapport à un appel de dessin.

En outre, les instances des sous-classes de QRhiResource doivent être considérées comme immuables dans un cadre dans lequel elles sont référencées de quelque manière que ce soit. Créez toutes les ressources en amont, avant de commencer à enregistrer les commandes pour la trame suivante. La réutilisation d'une instance de QRhiResource dans un cadre (en appelant create() puis en la référençant à nouveau dans la même section beginFrame - endFrame ) doit être évitée car elle peut conduire à des résultats inattendus, en fonction du backend.

En règle générale, tous les objets QRhiResource référencés doivent rester valides et non modifiés jusqu'à ce que le cadre soit soumis en appelant endFrame(). D'autre part, l'appel à destroy() ou la suppression de QRhiResource sont toujours sûrs une fois que la trame est soumise, quel que soit l'état des ressources natives sous-jacentes (qui peuvent encore être utilisées par le GPU - mais cela est pris en charge en interne).

Contrairement à des API comme OpenGL, les commandes de type téléchargement et copie ne peuvent pas être mélangées avec les commandes de dessin. Le moteur de rendu typique implique une séquence similaire à la suivante :

  • (re)créer des ressources
  • début de l'image
  • enregistrer/émettre des téléchargements et des copies
  • début de l'enregistrement d'une passe de rendu
  • enregistrer les appels de dessin
  • fin de la passe de rendu
  • fin de l'image

L'enregistrement des opérations de type copie se fait via QRhiResourceUpdateBatch. Ces opérations sont généralement validées sur beginPass().

Lorsque l'on travaille avec d'anciens moteurs de rendu conçus pour OpenGL, la migration vers QRhi implique souvent de passer d'une seule étape render (qui effectue des copies et des téléchargements, vide les tampons et émet des appels de dessin, le tout mélangé) à une configuration clairement séparée, en deux phases prepare - render où l'étape render ne fait que démarrer un passage de rendu et enregistrer les appels de dessin, tandis que toute la création de ressources et la mise en file d'attente des mises à jour, des téléchargements et des copies se font avant, dans l'étape prepare.

QRhi ne permet pas pour l'instant de créer et de soumettre librement des tampons de commande. Cela pourrait être levé à l'avenir dans une certaine mesure, en particulier si la prise en charge du calcul est introduite, mais le modèle des points frame-start et frame-end bien définis, combiné à un tampon de commande dédié, "frame", où frame-end implique la présentation, va rester le principal mode de fonctionnement car c'est ce qui correspond le mieux aux différentes technologies d'interface utilisateur de Qt.

Filière

Une instance de 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 seul thread. Lorsque le rendu est effectué sur plusieurs QWindows dans une application, il est souvent conseillé d'avoir un thread et une instance QRhi dédiés à chaque fenêtre, car cela permet d'éliminer les problèmes d'étranglement inattendus causés par la présentation à plusieurs fenêtres. D'un point de vue conceptuel, c'est la même chose que la boucle de rendu threadée de Qt Quick scene graph lorsqu'on travaille directement avec OpenGL : un thread pour chaque fenêtre, un QOpenGLContext pour chaque thread. Lorsque l'on passe à QRhi, QOpenGLContext est remplacé par QRhi, ce qui rend la migration simple.

En ce qui concerne les objets natifs créés en externe, tels que les contextes OpenGL transmis via QRhiGles2NativeHandles, c'est à l'application de s'assurer qu'ils ne sont pas utilisés à mauvais escient par d'autres threads.

Les ressources ne sont pas partageables entre les instances de QRhi. Il s'agit d'un choix intentionnel puisque QRhi cache la plupart des tâches liées à la synchronisation des files d'attente, des tampons de commande et des ressources, et ne fournit pas d'API pour celles-ci. L'utilisation concurrente sûre et efficace des ressources graphiques par plusieurs threads est cependant liée à ces concepts, et c'est donc un sujet qui est actuellement hors de portée, mais qui pourrait être introduit à l'avenir.

Note : Le backend Metal exige qu'un pool de libération automatique soit disponible sur le thread de rendu, idéalement en enveloppant chaque itération de la boucle de rendu. Cela ne nécessite aucune action de la part des utilisateurs de QRhi lorsque le rendu est effectué sur le thread principal (gui), mais devient important lorsqu'un thread de rendu séparé et dédié est utilisé.

Synchronisation des ressources

QRhi n'expose pas d'API pour les barrières de ressources ou les transitions de disposition d'image. Une telle 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 d'une passe de rendu ou de calcul sont censées être liées à une seule utilisation pendant cette passe. Par exemple, un tampon peut être utilisé comme tampon de vertex, d'index, d'uniforme ou de stockage, mais pas comme une combinaison de ces fonctions au sein d'une même passe. Cependant, il est tout à fait possible d'utiliser un tampon comme tampon de stockage dans une passe de calcul, puis comme tampon de sommet dans une passe de rendu, par exemple, en supposant que le tampon ait déclaré les deux utilisations lors de sa création.

Remarque : cette règle est assouplie dans certains cas pour les textures, car l'utilisation de deux sous-ressources (typiquement deux niveaux de mip différents) de la même texture pour des accès différents (un pour le chargement, un pour le stockage) est supportée même au cours de la même passe.

Réutilisation des ressources

Du point de vue de l'utilisateur, une page QRhiResource est réutilisable immédiatement après l'appel à QRhiResource::destroy(). À l'exception des chaînes d'échange, l'appel à create() sur un objet déjà créé effectue un destroy() implicite. Il s'agit d'un raccourci pratique pour réutiliser une instance de QRhiResource avec des paramètres différents, avec un nouvel objet graphique natif en dessous.

L'importance de la réutilisation d'un même objet réside dans le fait que certains objets font référence à d'autres objets : par exemple, un QRhiShaderResourceBindings peut faire référence aux instances QRhiBuffer, QRhiTexture et QRhiSampler. Si, dans une image ultérieure, l'un de ces tampons doit être redimensionné ou si un paramètre de l'échantillonneur doit être modifié, la destruction et la création d'un tout nouveau QRhiBuffer ou QRhiSampler invalideraient toutes les références à l'ancienne instance. En modifiant simplement les paramètres appropriés via QRhiBuffer::setSize() ou similaire et en appelant ensuite QRhiBuffer::create(), tout fonctionne comme prévu et il n'est pas nécessaire de toucher à QRhiShaderResourceBindings, même s'il y a de fortes chances que, sous le capot, QRhiBuffer soit maintenant soutenu par 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 contrat : l'appel à QRhiCommandBuffer::beginPass() est sûr 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() ) 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 QRhiTexture et en appelant create(), créant ainsi une toute nouvelle ressource de texture native en dessous, sans avoir à mettre à jour QRhiTextureRenderTarget puisque cela sera fait implicitement dans beginPass().

Objets mis en commun

Outre les ressources, il existe également des objets mis en commun, 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 d'opérer ici est d'appeler des fonctions sur QRhiResourceUpdateBatch et de les passer ensuite à QRhiCommandBuffer::beginPass() ou QRhiCommandBuffer::endPass(). Ces fonctions se chargent de renvoyer le lot dans le pool. Il est également possible d'"annuler" un lot et de le renvoyer au pool sans traitement en appelant QRhiResourceUpdateBatch::release().

Voici un schéma typique :

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);

Les spécificités de Swapchain

QRhiSwapChain La chaîne de swap présente une sémantique particulière due à la nature spécifique des chaînes de swap.

  • Il n'y a pas de create() mais plutôt une QRhiSwapChain::createOrResize(). L'appel répété de cette fonction n'est pas la même chose que l'appel de QRhiSwapChain::destroy() suivi de QRhiSwapChain::createOrResize(). En effet, les chaînes d'échange ont souvent des moyens de gérer le cas où les tampons doivent être redimensionnés d'une manière plus efficace qu'une destruction par force brute et une recréation à partir de zéro.
  • Un QRhiSwapChain actif doit être libéré en appelant destroy(), ou en détruisant l'objet, avant que la QPlatformWindow sous-jacente de QWindow, et donc l'objet fenêtre natif associé, ne soit détruite. Elle ne doit pas être reportée car la libération de la chaîne d'échange peut devenir problématique (et avec certaines API, comme Vulkan, est explicitement interdite) lorsque la fenêtre native n'existe plus, par exemple parce que la QPlatformWindow a été détruite lors de l'obtention d'un QWindow::close(). Par conséquent, la libération de la chaîne d'échange doit avoir lieu chaque fois que le QWindow ciblé envoie l'événement QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed. Si l'événement n'arrive pas avant la destruction de QWindow - ce qui peut arriver lors de l'utilisation de QCoreApplication::quit() -, vérifiez QWindow::handle() après la sortie de la boucle d'événement et invoquez la libération de la chaîne d'échange si elle n'est pas 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 existant ne signifie pas que le QRhi devient propriétaire de l'objet périphérique. De même, la propriété n'est pas cédée lorsqu'un objet de périphérique ou de texture est "exporté" via QRhi::nativeHandles() ou QRhiTexture::nativeTexture(). Plus important encore, le fait de passer des pointeurs dans des structures et par l'intermédiaire de setters ne transfère pas la propriété.

Dépannage et profilage

Signalement des erreurs

Les fonctions telles que QRhi::create() et les fonctions membres create() des classes de ressources (par exemple, QRhiBuffer::create()) indiquent l'échec avec la valeur de retour (nullptr ou false, respectivement). Lorsque l'on travaille avec QShader, 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 avec succès. Certaines fonctions, notamment beginFrame(), peuvent aussi parfois signaler des "échecs légers", tels que FrameOpSwapChainOutOfDate, qui n'indiquent pas une erreur irrécupérable, mais doivent plutôt être considérés comme une réponse du type "réessayez plus tard".

Les avertissements et les erreurs peuvent être affichés à tout moment sur 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 imprimés par défaut, à moins qu'ils ne soient 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 impressions de débogage.

  • qt.rhi.general

En outre, les applications peuvent interroger QRhi backend name et graphics device information à partir d'un QRhi initialisé avec succès. Ces informations peuvent alors être imprimées pour l'utilisateur ou stockées dans les journaux d'application, même dans les versions de production, si vous le souhaitez.

Investigation des problèmes de rendu

Lorsque les résultats du rendu ne sont pas conformes aux attentes ou que l'application rencontre des problèmes, il faut toujours envisager de vérifier les installations de débogage et de validation des API 3D natives. QRhi lui-même propose un contrôle d'erreur limité, car il n'est pas raisonnable de reproduire la grande 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 le site QVulkanInstance 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 sont effectivement installées et disponibles, par exemple à partir du SDK Vulkan). Par défaut, QVulkanInstance redirige commodément les messages de débogage Vulkan vers qDebug, ce qui signifie que les messages de validation sont imprimés comme d'autres avertissements Qt.
  • Avec Direct 3D 11 et 12, un périphérique graphique dont la couche de débogage est activée peut être demandé en activant le drapeau enableDebugLayer dans le site init params struct approprié. Les messages apparaissent sur la sortie de débogage, qui est visible dans le panneau de messages de Qt Creator ou via un outil tel que DebugView.
  • Pour Metal, le contrôle de la validation de Metal n'entre pas dans le champ d'application de QRhi. Pour activer la validation, il faut plutôt exécuter l'application avec la variable d'environnement METAL_DEVICE_WRAPPER_TYPE=1, ou exécuter l'application dans XCode. Il peut également y avoir d'autres paramètres et variables d'environnement dans les versions modernes de XCode et de macOS. Voir par exemple cette page.

Captures d'images et profilage des performances

Une application Qt effectuant un rendu avec QRhi dans une fenêtre tout en s'appuyant sur une API 3D sous le capot, n'est, du point de vue du fenêtrage et du pipeline graphique au moins, pas différente des autres applications (non Qt) utilisant la même API 3D. Cela signifie que les outils et les pratiques de débogage et de profilage des applications impliquant des graphiques 3D, telles que les jeux, s'appliquent également à une telle application Qt.

Voici quelques exemples d'outils qui peuvent donner un aperçu du rendu interne des applications Qt qui utilisent QRhi, ce qui inclut Qt Quick et Qt Quick projets basés sur la 3D également :

  • RenderDoc permet de faire des captures d'images et d'inspecter les commandes enregistrées et l'état du pipeline sous Windows et Linux pour les applications utilisant OpenGL, Vulkan, D3D11 ou D3D12. Lorsque vous essayez de comprendre pourquoi certaines parties de la scène 3D ne s'affichent pas comme prévu, RenderDoc est 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 incorrecte. C'est également un outil qui est 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'examen des commandes dans la trame et le pipeline, les outils spécifiques au fournisseur permettent d'examiner les délais et les informations sur les performances du matériel, ce que de simples captures de trame 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 incrustations affichant des informations sur les performances en direct peuvent également être très utiles et sont souvent préférables à l'implémentation de simples compteurs d'images par seconde dans l'application elle-même, car elles sont plus fiables et affichent plus d'informations. PresentMon, qui prend en charge le matériel graphique de plusieurs fournisseurs, en est un exemple.
  • QRhi prenant en charge Direct 3D 12, il est également possible d'utiliser PIX, un outil de réglage des performances et de débogage pour les jeux DirectX 12 sous Windows.
  • Sur macOS, le débogueur XCode Metal peut être utilisé pour prendre et introspecter des captures d'images, pour étudier les détails des performances et pour déboguer les shaders. Dans macOS 13, il est également possible d'activer une superposition qui affiche 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 y avoir des outils spécifiques au fournisseur et à la plateforme, fournis par le fournisseur du GPU ou du SoC, disponibles pour effectuer le profilage des performances de l'application 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 via des marqueurs de débogage, à condition que debug markers were enabled pour le QRhi et l'API graphique utilisée le supportent. Pour annoter le flux de commandes, appelez debugMarkBegin(), debugMarkEnd() et/ou debugMarkMsg(). Cela peut s'avérer particulièrement utile dans les grandes images avec plusieurs passes de rendu. Les ressources sont nommées en appelant setName() avant create().

Pour effectuer des mesures de synchronisation de base du côté du CPU et du GPU dans l'application, QElapsedTimer et QRhiCommandBuffer::lastCompletedGpuTime() peuvent être utilisés. Ce dernier n'est pour l'instant disponible qu'avec certaines API graphiques et nécessite l'utilisation de l'option QRhi::EnableTimestamps.

Vérification des fuites de ressources

Lors de la destruction d'un objet QRhi sans détruire correctement tous les tampons, textures et autres ressources créés à partir de cet objet, des avertissements à ce sujet sont affichés sur la sortie de débogage lorsque l'application est une version de débogage, ou lorsque la variable d'environnement QT_RHI_LEAK_CHECK est définie à une valeur non nulle. Il s'agit d'un moyen simple de découvrir les problèmes de conception liés à la gestion des ressources dans la logique de rendu de l'application. Notez cependant 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 pas de contrôle direct. Par exemple, lors de l'utilisation de Vulkan, l'allocateur de mémoire peut soulever des assertions d'échec dans les constructions de débogage lorsque les ressources qui possèdent des allocations de mémoire graphique ne sont pas détruites avant le QRhi. En outre, la couche de validation Vulkan, lorsqu'elle est activée, émet des avertissements concernant les ressources graphiques natives qui n'ont pas été libérées. De la même manière, avec Direct 3D, des avertissements peuvent être émis 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 l'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 drapeaux pour QRhi::beginFrame()

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

enum QRhi::EndFrameFlag
flags QRhi::EndFrameFlags

Valeurs des drapeaux pour QRhi::endFrame()

ConstanteValeurDescription
QRhi::SkipPresent1 << 0Spécifie qu'aucune commande présente ne doit être mise en file d'attente ou qu'aucun appel à swapBuffers ne doit être effectué. Ainsi, aucune image n'est présentée. Il n'est pas recommandé de générer plusieurs trames ayant toutes ce drapeau activé (sauf, par exemple, à des fins d'analyse comparative - mais gardez à l'esprit que les backends peuvent se comporter différemment lorsqu'il s'agit d'attendre la fin d'une commande sans présenter d'image, de sorte que les résultats ne sont pas comparables entre eux).

Le type EndFrameFlags est un typedef pour QFlags<EndFrameFlag>. Il stocke une combinaison OU de valeurs EndFrameFlag.

enum QRhi::Feature

Valeurs des drapeaux indiquant les fonctionnalités prises en charge par le backend actuellement utilisé.

ConstanteValeurDescription
QRhi::MultisampleTexture1Indique que les textures dont le nombre d'échantillons est supérieur à 1 sont prises en charge. En pratique, cette fonctionnalité ne sera pas supportée avec les versions d'OpenGL ES antérieures à 3.1, et d'OpenGL antérieures à 3.0.
QRhi::MultisampleRenderBuffer2Indique que les renderbuffers avec un nombre d'échantillons supérieur à 1 sont supportés. En pratique, cette fonctionnalité ne sera pas supportée avec OpenGL ES 2.0, et peut également ne pas être supportée avec OpenGL 2.x à moins que les extensions appropriées ne soient présentes.
QRhi::DebugMarkers3Indique que les groupes de marqueurs de débogage (et donc QRhiCommandBuffer::debugMarkBegin()) sont supportés.
QRhi::Timestamps4Indique que les horodatages du tampon de commande sont pris en charge. Concerne QRhiCommandBuffer::lastCompletedGpuTime(). On peut s'attendre à ce que cela soit pris en charge sur Metal, Vulkan, Direct 3D 11 et 12, et les contextes OpenGL de la 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, et il n'est donc pas possible de garantir que cette fonctionnalité est toujours prise en charge dans toutes les implémentations de ces API.
QRhi::Instancing5Indique que le dessin instancié est pris en charge. En pratique, cette fonctionnalité ne sera pas supportée avec OpenGL ES 2.0 et OpenGL 3.2 ou plus ancien.
QRhi::CustomInstanceStepRate6Indique que les taux de pas d'instance autres que 1 sont supportés. 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 conduira également à signaler false pour cette fonctionnalité.
QRhi::PrimitiveRestart7Indique que le redémarrage de l'assemblage des primitives lors de la rencontre d'une valeur d'index de 0xFFFF (IndexUInt16) ou 0xFFFFFF (IndexUInt32) est activé, pour certaines topologies de primitives au moins. QRhi essaiera d'activer cela avec tous les backends, mais dans certains cas, cela ne sera pas pris en charge. Il n'est pas possible de contrôler dynamiquement le redémarrage des primitives, car certaines API activent toujours le redémarrage des primitives avec un index fixe. Les applications doivent partir du principe que lorsque cette fonctionnalité est signalée comme étant prise en charge, les valeurs d'index susmentionnées may font l'objet d'un traitement spécial, en fonction de la topologie. Les deux seules topologies où le redémarrage primitif est garanti pour se comporter de manière identique entre les backends, tant que cette fonctionnalité est signalée comme étant prise en charge, sont LineStrip et TriangleStrip.
QRhi::NonDynamicUniformBuffers8Indique que la création de tampons avec l'usage UniformBuffer et les types Immutable ou Static est prise en charge. Lorsque cette fonctionnalité est signalée comme n'étant pas prise en charge, les tampons uniformes (constants) doivent être créés comme Dynamic(ce qui est recommandé quoi qu'il en soit).
QRhi::NonFourAlignedEffectiveIndexBufferOffset9Indique que les décalages de tampons d'index effectifs (indexOffset + firstIndex * indexComponentSize) qui ne sont pas alignés sur 4 octets sont pris en charge. Lorsqu'ils ne sont pas pris en charge, les tentatives d'émission de drawIndexed() avec un décalage effectif non aligné peuvent entraîner un comportement non spécifié. Ce point est particulièrement important pour Metal, où il sera signalé comme n'étant pas pris en charge.
QRhi::NPOTTextureRepeat10Indique que le mode d'enveloppement Repeat et les modes de filtrage mipmap sont pris en charge pour les textures dont la taille n'est pas une puissance deux. En pratique, cela ne peut être faux qu'avec les implémentations d'OpenGL ES 2.0 sans GL_OES_texture_npot.
QRhi::RedOrAlpha8IsRed11Indique que le format RED_OR_ALPHA8 correspond à un format red 8 bits à une composante. C'est le cas pour tous les backends à l'exception d'OpenGL lorsque l'on utilise OpenGL ES ou un contexte de profil non-core. Le format GL_ALPHA, un format 8 bits à un composant alpha, est utilisé à la place. L'utilisation du format de texture spécial permet d'avoir un seul chemin de code pour créer des textures, laissant au backend le soin de décider du format réel, tandis que le drapeau 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 entiers non signés de 32 bits sont pris en charge dans le tampon d'index. En pratique, c'est vrai partout sauf lorsque l'on utilise des implémentations OpenGL ES 2.0 sans l'extension nécessaire. Lorsqu'il est faux, seuls les éléments non signés de 16 bits sont pris en charge dans le tampon d'index.
QRhi::Compute13Indique que les shaders de calcul, les tampons de chargement/stockage d'images et les tampons de stockage sont supportés. Les versions d'OpenGL antérieures à 4.3 et d'OpenGL ES antérieures à 3.1 ne prennent pas en charge le calcul.
QRhi::WideLines14Indique que les lignes d'une largeur différente de 1 sont prises en charge. Lorsqu'elle est signalée comme n'étant pas supportée, la largeur de ligne définie dans l'état du pipeline graphique est ignorée. Cette valeur peut toujours être fausse 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 tramés définie via gl_PointSize dans le vertex shader est prise en compte. Lorsqu'il est indiqué qu'il n'est pas pris en charge, le dessin de points d'une taille différente de 1 n'est pas pris en charge. Le réglage de gl_PointSize dans le nuanceur est toujours valable, mais il est ignoré. (par exemple, lors de la génération de 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 définie explicitement dans le shader lorsque des points sont dessinés, même si la taille est de 1, car elles ne prennent pas automatiquement la valeur 1 par défaut.
QRhi::BaseVertex16Indique que drawIndexed() prend en charge l'argument vertexOffset. Lorsqu'elle est signalée comme n'étant pas prise en charge, la valeur vertexOffset dans un dessin indexé est ignorée. En pratique, cette fonctionnalité ne sera pas supportée avec les versions d'OpenGL et d'OpenGL ES inférieures à 3.2, et avec Metal sur les anciens appareils iOS, y compris le simulateur iOS.
QRhi::BaseInstance17Indique que les commandes de dessin instancié supportent l'argument firstInstance. Lorsqu'elle est signalée comme n'étant pas prise en charge, la valeur firstInstance est ignorée et l'ID de l'instance commence à 0. En pratique, cette fonctionnalité ne sera pas prise en charge par Metal sur les anciens appareils iOS, y compris le simulateur iOS, et par toutes les versions d'OpenGL. Cette dernière est due au fait qu'OpenGL ES ne supporte pas du tout les appels de dessin avec une instance de base. Actuellement, le backend OpenGL de QRhi n'implémente pas non plus la fonctionnalité pour OpenGL (non-ES), parce que les applications portables ne peuvent pas s'appuyer sur une instance de base non nulle en pratique à cause de GLES. Si l'application choisit quand même de le faire, elle doit être consciente de la fonctionnalité InstanceIndexIncludesBaseInstance.
QRhi::TriangleFanTopology18Indique que QRhiGraphicsPipeline::setTopology() supporte QRhiGraphicsPipeline::TriangleFan. Dans la pratique, cette fonctionnalité ne sera pas prise en charge avec Metal et Direct 3D 11/12.
QRhi::ReadBackNonUniformBuffer19Indique que reading buffer contents est pris en charge pour les instances QRhiBuffer dont l'utilisation est différente de 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 mip différent de 0 est supportée lors de la relecture du contenu des textures. Lorsqu'il n'est pas supporté, le fait de spécifier un niveau non nul dans QRhiReadbackDescription conduit à renvoyer une image entièrement nulle. En pratique, cette fonctionnalité ne sera pas supportée par OpenGL ES 2.0.
QRhi::TexelFetch21Indique que texelFetch() et textureLod() sont disponibles dans les shaders. En pratique, cela sera signalé comme non supporté avec les contextes OpenGL ES 2.0 et OpenGL 2.x, parce que GLSL 100 es et les versions antérieures à 130 ne supportent pas ces fonctions.
QRhi::RenderToNonBaseMipLevel22Indique que la spécification d'un niveau mip différent de 0 est prise en charge lors de la création d'un QRhiTextureRenderTarget avec un QRhiTexture comme attachement de couleur. S'il n'est pas pris en charge, create() échouera si le niveau de mip cible n'est pas zéro. En pratique, cette fonctionnalité ne sera pas supportée par OpenGL ES 2.0.
QRhi::IntAttributes23Indique que la spécification d'attributs d'entrée avec des types d'entiers signés et non signés pour un pipeline de shaders est supportée. Si ce n'est pas le cas, build() réussira mais affichera juste un message d'avertissement et les valeurs des attributs cibles seront cassées. En pratique, cette fonctionnalité ne sera pas supportée avec OpenGL ES 2.0 et OpenGL 2.x.
QRhi::ScreenSpaceDerivatives24Indique que les fonctions telles que dFdx(), dFdy(), et fwidth() sont supportées dans les shaders. En pratique, cette fonctionnalité ne sera pas supportée avec OpenGL ES 2.0 sans l'extension GL_OES_standard_derivatives.
QRhi::ReadBackAnyTextureFormat25Indique que la relecture du contenu des textures peut fonctionner pour n'importe quelle QRhiTexture::Format. Les backends autres qu'OpenGL devraient renvoyer true pour cette fonctionnalité. Lorsqu'elle est signalée comme étant fausse, ce qui se produit généralement avec OpenGL, seuls les formats QRhiTexture::RGBA8 et QRhiTexture::BGRA8 sont garantis d'être 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 supportée. La relecture des formats à virgule flottante QRhiTexture::RGBA16F et RGBA32F peut également fonctionner avec OpenGL, tant que l'implémentation fournit un support pour ceux-ci, mais QRhi ne peut donner aucune garantie, comme l'indique ce drapeau.
QRhi::PipelineCacheDataLoadSave26Indique que les fonctions pipelineCacheData() et setPipelineCacheData() sont fonctionnelles. Lorsqu'elles ne sont pas prises en charge, les fonctions n'effectuent aucune action, le blob récupéré est toujours vide et il n'y a donc aucun avantage à récupérer et, lors d'une exécution ultérieure de l'application, à recharger le contenu du cache du pipeline.
QRhi::ImageDataStride27Indique que la spécification d'une longueur de ligne (stride) personnalisée pour les données d'images brutes dans les téléchargements de textures est prise en charge. Si elle 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), QRhiTextureSubresourceUploadDescription::setDataStride() ne doit pas être utilisé.
QRhi::RenderBufferImport28Indique que QRhiRenderBuffer::createFrom() est pris 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, l'objet renderbuffer existe comme un type d'objet séparé dans l'API, et dans certains environnements (par exemple, où l'on peut vouloir associer un objet renderbuffer avec un objet EGLImage), il est important de permettre l'encapsulation d'un objet renderbuffer OpenGL existant avec un QRhiRenderBuffer.
QRhi::ThreeDimensionalTextures29Indique que les textures 3D sont prises en charge. En pratique, cette fonctionnalité ne sera pas supportée avec les versions d'OpenGL et d'OpenGL ES inférieures à la version 3.0.
QRhi::RenderTo3DTextureSlice30Indique que le rendu d'une tranche dans une texture 3D est pris en charge. Cela peut ne pas être pris en charge avec Vulkan 1.0 car cette fonctionnalité 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 QRhi::newTextureArray() est fonctionnel. Notez que même si les tableaux de textures ne sont pas pris en charge, les tableaux de textures sont toujours 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 la prise en charge est signalée, la topologie d'un site QRhiGraphicsPipeline peut être définie à l'adresse Patches, le nombre de points de contrôle peut être défini via setPatchControlPointCount() et les nuanceurs pour le contrôle et l'évaluation de la tessellation peuvent être spécifiés dans la liste QRhiShaderStage. Les nuanceurs de tessellation présentent des problèmes de portabilité entre les API (par exemple, la traduction de GLSL/SPIR-V en HLSL est problématique en raison de la manière dont les nuanceurs de coque sont structurés, tandis que Metal utilise un pipeline de tessellation quelque peu différent des autres), et des problèmes inattendus peuvent donc encore survenir, même si la fonctionnalité de base est mise en œuvre dans toutes les API sous-jacentes. Pour Direct 3D en particulier, les shaders de domaine et de coque HLSL écrits à la main doivent être injectés dans chaque site 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 isolée doit être évitée car elle ne sera pas supportée par tous les backends. Le nombre maximum de points de contrôle de patchs portables entre les backends est de 32.
QRhi::GeometryShader33Indique que l'étape du nuanceur géométrique est prise en charge. Lorsqu'il est pris en charge, un shader géométrique peut être spécifié dans la liste QRhiShaderStage. Les nuanceurs géométriques sont considérés comme une fonctionnalité expérimentale sur QRhi et ne devraient être pris en charge qu'avec Vulkan, Direct 3D 11 et 12, OpenGL (3.2+) et OpenGL ES (3.2+), en supposant que l'implémentation les signale comme étant pris en charge au moment de l'exécution. À partir de Qt 6.11, les shaders géométriques sont automatiquement traduits en HLSL, et donc aucune injection de shaders géométriques HLSL écrits à la main n'est plus nécessaire (mais notez que gl_in et les expressions telles que gl_in[0].gl_Position ne sont pas prises en charge ; passez plutôt la position en tant que variable de sortie du vertex shader). Les nuanceurs de géométrie ne sont pas pris en charge par Metal.
QRhi::TextureArrayRange34Indique que pour texture arrays, il est possible de spécifier une plage exposée aux nuanceurs. Normalement, toutes les couches du tableau sont exposées et c'est au nuanceur de sélectionner la couche (via la troisième coordonnée transmise à texture() lors de l'échantillonnage de sampler2DArray). Lorsqu'il est pris en charge, l'appel à QRhiTexture::setArrayRangeStart() et QRhiTexture::setArrayRangeLength() avant building ou importing la texture native a un effet et permet de sélectionner uniquement la plage spécifiée dans le tableau. Cela sera nécessaire dans des cas particuliers, comme lorsque vous travaillez avec le décodage vidéo accéléré et Direct 3D 11, parce qu'un tableau de textures contenant à la fois D3D11_BIND_DECODER et D3D11_BIND_SHADER_RESOURCE n'est utilisable comme ressource de shader que si une seule couche du tableau est sélectionnée. Notez que tout ceci n'est applicable que lorsque la texture est utilisée comme ressource de shader 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 n'est pas adaptée à toutes les API graphiques, et elle n'est destinée qu'à fournir un support pour des cas particuliers. En pratique, on peut s'attendre à ce que cette fonctionnalité soit prise en charge par Direct3D 11/12 et Vulkan.
QRhi::NonFillPolygonMode35Indique que la définition d'un PolygonMode autre que le mode Fill par défaut est prise en charge pour QRhiGraphicsPipeline. Un cas d'utilisation courant pour changer le mode en Ligne est d'obtenir un rendu filaire. Cependant, ceci n'est pas disponible en tant que fonctionnalité principale d'OpenGL ES, et est optionnel avec Vulkan ainsi que certains GPUs mobiles peuvent ne pas offrir cette fonctionnalité.
QRhi::OneDimensionalTextures36Indique que les textures 1D sont supportées. En pratique, cette fonctionnalité n'est pas supportée par 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 par les backends qui ne déclarent pas prendre en charge OneDimensionalTextures, Metal et Direct 3D 12.
QRhi::HalfAttributes38Indique que la spécification d'attributs d'entrée avec des types de demi précision (16 bits) en virgule flottante pour un pipeline de shaders est prise en charge. Si ce n'est pas le cas, build() réussira mais affichera un message d'avertissement et les valeurs des attributs cibles seront cassées. En pratique, cette fonctionnalité ne sera pas supportée dans certaines implémentations d'OpenGL ES 2.0 et d'OpenGL 2.x. Notez que si Direct3D 11/12 supporte les attributs d'entrée en demi-précision, il ne supporte pas le type half3. Les backends D3D transmettent les attributs half3 comme half4. Pour assurer la compatibilité entre les plates-formes, les entrées de type half3 doivent être complétées par 8 octets.
QRhi::RenderToOneDimensionalTexture39Indique que les cibles de rendu de texture 1D sont prises en charge. Dans la pratique, cette fonctionnalité ne sera pas prise en charge par les backends qui ne signalent pas la prise en charge des OneDimensionalTextures et du 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 multiview, voir par exemple VK_KHR_multiview est supporté. Avec OpenGL ES 2.0, Direct 3D 11, et les implémentations OpenGL (ES) sans GL_OVR_multiview2, cette fonctionnalité ne sera pas supportée. Avec Vulkan 1.1 et les versions plus récentes, et Direct 3D 12, le multiview est généralement pris en charge. Lorsqu'elle est signalée comme étant prise en charge, la création d'un site QRhiTextureRenderTarget avec un site QRhiColorAttachment qui fait référence à un tableau de textures et dont le site multiViewCount est défini permet d'enregistrer une passe de rendu qui utilise le rendu multivue. En outre, tout QRhiGraphicsPipeline utilisé dans cette passe de rendu doit avoir the same view count set. Notez que le multiview n'est disponible qu'en combinaison avec des tableaux de textures 2D. Il ne peut pas être utilisé pour optimiser le rendu en textures individuelles (par exemple, deux pour les yeux gauche et droit). Au contraire, la cible d'une passe de rendu multivue est toujours un tableau de textures, dont le rendu est automatiquement effectué sur la couche (élément du tableau) correspondant à chaque vue. Par conséquent, cette fonctionnalité implique également les TextureArrays. Le rendu multivues n'est pas pris en charge en combinaison avec la tessellation ou les nuanceurs géométriques. Voir QRhiColorAttachment::setMultiViewCount() pour plus de détails sur le rendu multi-vues. Cette valeur enum a été introduite dans Qt 6.7.
QRhi::TextureViewFormat42Indique que la définition de view format sur QRhiTexture est effective. Lorsqu'il est signalé comme étant pris en charge, le fait de définir le mode d'affichage en lecture (échantillonnage) ou en écriture (cible de rendu / magasin de chargement d'images) modifie le format d'affichage de la texture. S'il n'est pas pris en charge, la définition d'un format d'affichage n'a aucun effet. Notez que Qt n'a aucune connaissance ou contrôle sur la compatibilité des formats ou les règles d'affichage des ressources dans l'API 3D sous-jacente et sa mise en œuvre. Le fait de transmettre des formats inadaptés ou incompatibles peut entraîner des erreurs et un comportement non spécifié. Ceci est fourni principalement pour permettre le rendu "casting" dans une texture créée avec un format sRGB en non-sRGB pour éviter la conversion linéaire->sRGB non désirée lors de l'écriture des shaders. D'autres types d'incrustation peuvent être fonctionnels ou non, en fonction de l'API sous-jacente. Actuellement implémenté pour Vulkan et Direct 3D 12. Avec D3D12, la fonctionnalité n'est disponible que si CastingFullyTypedFormatSupported est pris en charge, 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 enum a été introduite dans Qt 6.8.
QRhi::ResolveDepthStencil43Indique que la résolution d'une profondeur multi-échantillon ou d'une texture profondeur-stencil est prise en charge. Dans le cas contraire, setting a depth resolve texture n'est pas fonctionnel et doit être évité. Direct 3D 11 et 12 ne prennent pas en charge la résolution des formats de profondeur/profondeur-crayon, et cette fonctionnalité ne sera donc jamais prise en charge avec ces formats. Vulkan 1.0 n'a pas d'API pour demander la résolution d'un attachement de crayon de profondeur. Par conséquent, avec Vulkan, cette fonctionnalité ne sera supportée qu'avec Vulkan 1.2 et plus, et sur les implémentations 1.1 avec les extensions appropriées présentes. Cette fonctionnalité est fournie pour les rares cas où la résolution dans une texture de profondeur sans multi-échantillon devient nécessaire, par exemple lors du rendu dans une texture de profondeur fournie par OpenXR (XR_KHR_composition_layer_depth). Cette valeur a été introduite dans Qt 6.8.
QRhi::VariableRateShading44Indique que l'ombrage à taux variable par dessin (par pipeline) est pris en charge. Lorsqu'il est signalé comme étant pris en charge, QRhiCommandBuffer::setShadingRate() est fonctionnel et a un effet sur les objets QRhiGraphicsPipeline qui ont déclaré QRhiGraphicsPipeline::UsesShadingRate dans leurs drapeaux. Appelez QRhi::supportedShadingRates() pour vérifier quels taux sont pris en charge. (1x1 est toujours supporté, les autres valeurs typiques sont 2x2, 1x2, 2x1, 2x4, 4x2, 4x4). On peut s'attendre à ce que cette fonctionnalité soit prise en charge avec Direct 3D 12 et Vulkan, en supposant que l'implémentation et le GPU utilisés au moment de l'exécution prennent en charge le VRS. Cette valeur 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 moderne pour prendre en charge VRS. Pour vérifier si le VRS basé sur l'image de type D3D12/Vulkan est pris en charge, utilisez plutôt VariableRateShadingMapWithTexture. Lorsque cette fonctionnalité est signalée comme étant prise en charge, il existe deux possibilités : lorsque VariableRateShadingMapWithTexture est également vrai, QRhiShadingRateMap consomme des objets QRhiTexture via la surcharge createFrom() qui prend un argument QRhiTexture. Lorsque VariableRateShadingMapWithTexture est faux, QRhiShadingRateMap consomme un autre type d'objets natifs, par exemple une MTLRasterizationRateMap dans le cas de Metal. Utilisez la surcharge createFrom() qui prend une NativeShadingRateMap dans ce cas. 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 l'image est prise en charge par des textures régulières. En pratique, cela peut être pris en charge avec Direct 3D 12 et Vulkan. Cette valeur enum 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 différents modes de mélange. En pratique, on peut s'attendre à ce que cela soit supporté partout sauf avec OpenGL ES, où cela 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 nuanceurs de fragments. Dans la pratique, on peut s'attendre à ce que cela soit supporté partout sauf avec OpenGL ES, où cela 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 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 indique que gl_InstanceIndex commence toujours à 0, et non à la valeur de base. En pratique, c'est le cas pour Direct 3D 11 et 12 pour le moment. Avec Vulkan et Metal, cette fonctionnalité devrait être signalée comme étant toujours prise en charge. Cette valeur d'énumération a été introduite dans Qt 6.11.
QRhi::DepthClamp50Indique que l'activation du serrage en profondeur est prise en charge. Lorsqu'elle est signalée comme non supportée, ce qui sera le cas avec OpenGL ES, les versions d'OpenGL antérieures à 3.2 sans l'extension correspondante, et Metal sur le simulateur iOS, appeler setDepthClamp() avec un argument de true n'a pas d'effet. Cette valeur a été introduite dans Qt 6.11.

enum QRhi::Flag
flags QRhi::Flags

Décrit les fonctions spéciales à activer.

ConstanteValeurDescription
QRhi::EnableDebugMarkers1 << 0Active les groupes de marqueurs de débogage. Sans ce cadre, les fonctionnalités de débogage telles que les groupes de débogage et le nom des ressources personnalisées visibles dans les outils de débogage GPU externes ne seront pas disponibles et les fonctions telles que QRhiCommandBuffer::debugMarkBegin() deviendront inopérantes. Évitez de l'activer dans les versions de production car cela peut avoir un léger impact sur les performances. N'a aucun effet lorsque la fonctionnalité QRhi::DebugMarkers n'est pas signalée comme étant prise en charge.
QRhi::EnableTimestamps1 << 3Active la collecte de l'horodatage par le GPU. Si cette option n'est pas activée, QRhiCommandBuffer::lastCompletedGpuTime() renvoie toujours 0. N'activez cette option qu'en cas de besoin, car il peut y avoir une petite quantité de travail supplémentaire (par exemple, les 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 étant prise en charge.
QRhi::PreferSoftwareRenderer1 << 1Indique que les backends devraient préférer choisir un adaptateur ou un périphérique physique qui effectue le rendu de manière logicielle sur l'unité centrale. Par exemple, avec Direct3D, il existe généralement un adaptateur "Basic Render Driver" disponible sur DXGI_ADAPTER_FLAG_SOFTWARE. L'activation de ce drapeau demande au backend de choisir cet adaptateur plutôt qu'un autre, tant qu'aucun adaptateur spécifique n'a été forcé par d'autres moyens spécifiques au backend. Avec Vulkan, cela revient à préférer les périphériques physiques avec VK_PHYSICAL_DEVICE_TYPE_CPU. Lorsqu'il n'est pas disponible, ou lorsqu'il n'est pas possible de décider si un adaptateur/dispositif est basé sur un logiciel, ce drapeau est ignoré. Il peut également être ignoré avec les API graphiques qui n'ont pas de concept ni de moyen d'énumérer les adaptateurs/périphériques.
QRhi::EnablePipelineCacheDataSave1 << 2Permet de récupérer le contenu du cache du pipeline, le cas échéant. S'il n'est pas défini, pipelineCacheData() renverra toujours un blob vide. Avec les backends où la récupération et la restauration du contenu du cache du pipeline n'est pas supportée, l'indicateur n'a aucun effet et les données du cache sérialisé sont toujours vides. L'indicateur fournit un mécanisme opt-in car le coût de maintenance des structures de données associées n'est pas négligeable avec certains backends. Avec Vulkan, cette fonctionnalité est directement liée à VkPipelineCache, vkGetPipelineCacheData et VkPipelineCacheCreateInfo::pInitialData. Avec Direct3D 11, il n'y a pas de véritable cache pipline, 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'ignorer la fonction D3DCompile(), qui prend du temps, dans les futures exécutions des applications pour les shaders qui sont livrés avec la source HLSL au lieu du bytecode précompilé hors ligne. Cela peut améliorer considérablement les temps de démarrage et de chargement, s'il y a beaucoup de compilations de sources HLSL en cours. Avec OpenGL, le "pipeline cache" est simulé en récupérant et en chargeant les binaires des programmes de shaders (s'ils sont pris en charge par le pilote). Avec OpenGL, il y a des mécanismes supplémentaires de cache sur disque pour les binaires de shaders/programmes fournis par Qt. L'écriture dans ces mécanismes peut être désactivée lorsque ce drapeau est activé, car il n'est pas judicieux de stocker les binaires de programmes dans plusieurs caches.
QRhi::SuppressSmokeTestWarnings1 << 4Indique que, avec les backends où cela est pertinent, certains échecs non fatals de QRhi::create() ne devraient pas produire d'appels à qWarning(). Par exemple, avec D3D11, le passage de ce drapeau fait qu'un certain nombre de messages d'avertissement (qui apparaissent en raison de l'échec de QRhi::create()) deviennent des impressions de débogage catégorisées à la place dans la catégorie de journalisation qt.rhi.general couramment utilisée. Cela peut être utilisé par des moteurs, tels que Qt Quick, qui disposent d'une logique de repli, c'est-à-dire qu'ils réessayent d'appeler create() avec un ensemble différent de drapeaux (tels que PreferSoftwareRenderer), afin de masquer les avertissements inconditionnels de la sortie qui serait imprimée lorsque la première tentative de create() a échoué.

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

enum QRhi::FrameOpResult

Décrit le résultat des opérations qui peuvent avoir une défaillance légère.

ConstanteValeurDescription de l'opération
QRhi::FrameOpSuccess0Réussite
QRhi::FrameOpError1Erreur non spécifiée
QRhi::FrameOpSwapChainOutOfDate2La chaîne d'échange est dans un état incohérent en interne. Cela peut être récupéré en essayant de répéter l'opération (comme beginFrame()) plus tard.
QRhi::FrameOpDeviceLost3Le périphérique graphique a été perdu. Ceci peut être récupéré en essayant de répéter l'opération (comme beginFrame()) après avoir libéré et réinitialisé tous les objets soutenus par les ressources graphiques natives. Voir isDeviceLost().

enum QRhi::Implementation

Décrit quel backend spécifique à l'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. La taille minimale de la texture est gérée de manière élégante, ce qui signifie qu'une tentative de création d'une texture avec une taille vide entraînera la création d'une texture avec la taille minimale.
QRhi::TextureSizeMax2Largeur et hauteur maximales de la texture. Cela dépend de l'API graphique et parfois de la plateforme ou de l'implémentation. En général, la valeur est comprise entre 4096 et 16384. Toute tentative de création de textures plus grandes que cette valeur est vouée à l'échec.
QRhi::MaxColorAttachments3Le nombre maximum d'attachements de couleur pour une QRhiTextureRenderTarget, dans le cas où plusieurs cibles de rendu sont prises en charge. Lorsque le MRT n'est pas supporté, la valeur est 1. Sinon, c'est typiquement 8, mais attention au fait qu'OpenGL n'impose que 4 comme minimum, et c'est ce que certaines implémentations d'OpenGL ES fournissent.
QRhi::FramesInFlight4Le nombre de frames que le backend peut garder "en vol" : avec des backends comme Vulkan ou Metal, il est de la responsabilité de QRhi de bloquer chaque fois que l'on démarre une nouvelle frame et que l'on découvre que le CPU a déjà N - 1 frames d'avance sur le GPU (parce que le tampon de commande soumis dans la frame no. current - N n'est pas encore terminé). La valeur N est ce qui est renvoyé ici, et est typiquement 2. Cela peut être pertinent pour les applications qui intègrent le rendu effectué directement avec l'API graphique, car un tel code de rendu peut vouloir effectuer une double (si la valeur est 2) mise en mémoire tampon pour les ressources, telles que les tampons, de la même manière que les backends QRhi eux-mêmes. L'index du frame slot actuel (une valeur allant de 0, 1, ..., N-1, puis s'enroulant autour) peut être récupéré à partir de QRhi::currentFrameSlot(). La valeur est 1 pour les backends où l'API graphique n'offre pas de contrôle de bas niveau sur le processus de soumission des commandes. Notez que le pipelining peut toujours se produire même lorsque cette valeur est 1 (certains backends, tels que D3D11, sont conçus pour tenter de l'activer, par exemple, en utilisant une stratégie de mise à jour pour les tampons uniformes qui ne bloque pas le pipeline), mais cela n'est pas contrôlé par QRhi et n'est donc pas reflété ici dans l'API.
QRhi::MaxAsyncReadbackFrames5Le nombre d'images submitted (y compris celle qui contient la lecture) après lequel une texture asynchrone ou une lecture de tampon est garantie de se terminer sur starting a new frame.
QRhi::MaxThreadGroupsPerDimension6Le nombre maximum de groupes de travail/threads de calcul qui peuvent être distribués. Il s'agit en fait de la valeur maximale des arguments de QRhiCommandBuffer::dispatch(). Généralement 65535.
QRhi::MaxThreadsPerThreadGroup7Le nombre maximal d'invocations dans un seul groupe de travail local ou, dans une autre terminologie, le nombre maximal de threads dans un groupe de threads. Il s'agit en fait de la valeur maximale du produit de local_size_x, local_size_y et local_size_z dans le nuanceur de calcul. Les valeurs typiques sont 128, 256, 512, 1024 ou 1536. Attention, OpenGL ES et Vulkan ne spécifient que 128 comme limite minimale requise pour les implémentations. Bien que cela ne soit pas courant pour Vulkan, certaines implémentations d'OpenGL ES 3.1 pour les appareils mobiles/embedded ne supportent que la valeur minimale imposée par la spécification.
QRhi::MaxThreadGroupX8La taille maximale d'un groupe de travail/thread dans la dimension X. En fait, la valeur maximale de local_size_x dans le shader de calcul. Typiquement 256 ou 1024.
QRhi::MaxThreadGroupY9Taille maximale d'un groupe de travail/thread dans la dimension Y. Il s'agit en fait de la valeur maximale de local_size_y dans le nuanceur de calcul. Typiquement 256 ou 1024.
QRhi::MaxThreadGroupZ10Taille maximale d'un groupe de travail/thread dans la dimension Z. Il s'agit de la valeur maximale de local_size_z dans le nuanceur de calcul. Généralement 64 ou 256.
QRhi::TextureArraySizeMax11Taille maximale du tableau de textures. Généralement comprise entre 256 et 2048. Une tentative de create a texture array avec plus d'éléments échouera probablement.
QRhi::MaxUniformBufferRange12Le nombre d'octets qui peuvent être exposés d'un tampon uniforme aux nuanceurs en une seule fois. Sur les implémentations OpenGL ES 2.0 et 3.0, cette valeur peut être aussi basse que 3584 octets (224 vecteurs à quatre composants, 32 bits par composant). Ailleurs, la valeur est typiquement de 16384 (1024 vec4s) ou 65536 (4096 vec4s).
QRhi::MaxVertexInputs13Nombre d'attributs en entrée du vertex shader. L'emplacement dans QRhiVertexInputAttribute doit être compris dans l'intervalle [0, MaxVertexInputs-1]. La valeur peut être aussi basse que 8 avec OpenGL ES 2.0. Ailleurs, les valeurs typiques sont 16, 31 ou 32.
QRhi::MaxVertexOutputs14Le nombre maximum de sorties (vecteur à 4 composants out variables) du vertex shader. La valeur peut être aussi basse que 8 avec OpenGL ES 2.0, et 15 avec OpenGL ES 3.0 et certains dispositifs Metal. Ailleurs, la valeur typique est de 32.
QRhi::ShadingRateImageTileSize15La taille des tuiles pour les textures de taux d'ombrage. 0 si la fonctionnalité QRhi::VariableRateShadingMapWithTexture n'est pas supportée. 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 un callback qui est invoqué lorsque le QRhi est détruit.

Le rappel sera exécuté alors que la ressource graphique est toujours disponible, ce qui permet à l'application de libérer proprement les instances QRhiResource appartenant à QRhi. Cela est particulièrement utile pour gérer la durée de vie des ressources stockées dans des objets de type cache, lorsque 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 callback pour qu'il soit invoqué lorsque QRhi est détruit. Cette surcharge prend un pointeur opaque, key, qui est utilisé pour s'assurer qu'un rappel donné n'est enregistré (et donc appelé) qu'une seule fois.

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

Voir aussi removeCleanupCallback().

QRhi::Implementation QRhi::backend() const

Retourne le type de backend pour cette QRhi.

const char *QRhi::backendName() const

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

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

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

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

Démarre une nouvelle trame ciblant le prochain tampon disponible sur swapChain.

Une trame se compose de mises à jour de ressources et d'une ou plusieurs passes de rendu et de calcul.

flags peut indiquer certains cas particuliers.

Le modèle de haut niveau du rendu dans un site QWindow à l'aide d'une chaîne d'échange :

  • Créez une chaîne d'échange.
  • Appelez QRhiSwapChain::createOrResize() chaque fois que la taille de la surface est différente de la précédente.
  • Appelez QRhiSwapChain::destroy() sur QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed.
  • Ensuite, à 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 QRhi::FrameOpResult en cas d'échec. Certains de ces échecs doivent être traités comme des erreurs légères, du type "réessayez plus tard" : Lorsque QRhi::FrameOpSwapChainOutOfDate est renvoyé, la chaîne d'échange doit être redimensionnée ou mise à jour en appelant QRhiSwapChain::createOrResize(). L'application doit ensuite essayer de générer une nouvelle image. QRhi::FrameOpDeviceLost signifie que le périphérique graphique est perdu, mais cela peut également être récupéré en libérant toutes les ressources, y compris le QRhi 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 = {})

Démarre une nouvelle image hors écran. Fournit un tampon de commande adapté à l'enregistrement des commandes de rendu dans cb. flags est utilisé pour indiquer certains cas particuliers, tout comme avec beginFrame().

Note : Le QRhiCommandBuffer stocké dans *cb n'appartient pas à l'appelant.

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

L'utilisation dans des applications à l'écran (donc beginFrame, endFrame, beginOffscreenFrame, endOffscreenFrame, beginFrame, ...) est également possible, mais elle réduit le parallélisme et ne devrait donc être utilisée que rarement.

Les images hors écran ne permettent pas au CPU de générer potentiellement une autre image alors que le GPU est toujours en train de traiter l'image précédente. Cela a pour effet secondaire que si des retours en arrière sont planifiés, les résultats sont garantis d'être disponibles une fois que endOffscreenFrame() est retourné. Ce n'est pas le cas avec les trames ciblant une chaîne d'échange : là, le GPU est potentiellement mieux utilisé, mais le travail avec les opérations de relecture nécessite plus d'attention de la part de l'application car endFrame(), contrairement à endOffscreenFrame(), ne garantit pas que les résultats de la relecture sont disponibles à ce moment-là.

Le squelette du rendu d'un cadre sans chaîne d'échange, puis de la lecture du contenu du cadre, pourrait ressembler à ce qui suit :

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 qui peut être utilisée pour permettre aux applications de continuer à utiliser les données de vertex et les matrices de projection de perspective ciblées par OpenGL (telles que celles générées par QMatrix4x4::perspective()), quel que soit le backend QRhi actif.

Dans un moteur de rendu typique, une fois que this_matrix * mvp est utilisé au lieu de mvp, les données de vertex avec Y up et les perspectives avec une profondeur de 0 à 1 peuvent être utilisées sans tenir compte du backend (et donc de l'API graphique) qui sera utilisé au moment de l'exécution. De cette manière, les branchements basés sur isYUpInNDC() et isClipDepthZeroToOne() peuvent être évités (bien qu'une telle logique puisse encore être nécessaire lors de la mise en œuvre de certaines techniques graphiques avancées).

Voir cette page pour une discussion sur le 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 QRhi avec un backend pour l'API graphique spécifiée par impl avec le flags spécifié. Retourne nullptr si la fonction échoue.

params doit pointer vers une instance de l'une des sous-classes de QRhiInitParams spécifiques au backend, telles que QRhiVulkanInitParams, QRhiMetalInitParams, QRhiD3D11InitParams, QRhiD3D12InitParams, QRhiGles2InitParams. Voir ces classes pour des exemples de création de QRhi.

QRhi ne met en œuvre aucune logique de repli : si l'API spécifiée ne peut pas être initialisée, create() échouera, avec des avertissements imprimés sur 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 revenir à une API différente de celle demandée, en fonction de la plate-forme. Si l'intention est simplement de tester si l'initialisation réussira lors d'un appel ultérieur à create(), il est préférable d'utiliser probe() au lieu de create(), parce qu'avec certains backends, le sondage peut être mis en œuvre d'une manière plus légère que create(), qui effectue une initialisation complète de l'infrastructure et constitue un gaspillage si l'instance de QRhi est ensuite immédiatement jetée.

importDevice permet d'utiliser un périphérique graphique déjà existant, sans que QRhi ne crée son propre périphérique. 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 exacts et la sémantique dépendent du backand et de l'API graphique sous-jacente.

La spécification d'un QRhiAdapter dans adapter offre une alternative transparente et inter-API à la transmission d'un VkPhysicalDevice via QRhiVulkanNativeHandles, ou d'un LUID d'adaptateur via QRhiD3D12NativeHandles. La propriété de adapter n'est pas prise en compte. Voir enumerateAdapters() pour plus d'informations sur cette approche.

Remarque : importDevice et adapter ne peuvent pas être spécifiés tous les deux.

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 la trame en cours d'enregistrement d'une trame. 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 lorsqu'il démarre une nouvelle image et constate que le CPU a déjà FramesInFlight - 1 images d'avance sur le GPU (parce que le tampon de commande soumis dans l'image n° current - FramesInFlight ne s'est pas encore achevé).

Les ressources qui ont tendance à changer entre les images (telles que l'objet tampon natif soutenant un QRhiBuffer de type QRhiBuffer::Dynamic) existent en plusieurs versions, de sorte que chaque image, qui peut être soumise alors qu'une image précédente est encore en cours de traitement, fonctionne avec sa propre copie, ce qui évite de bloquer le pipeline lors de la préparation de l'image. (Le contenu d'une ressource encore en cours d'utilisation dans le GPU ne doit pas être touché, mais le fait de toujours attendre que l'image précédente soit terminée réduirait l'utilisation du GPU et, en fin de compte, les performances et l'efficacité).

D'un point de vue conceptuel, ce système est quelque peu similaire aux schémas de copie sur écriture utilisés par certains conteneurs C++ et d'autres types. Il peut également être similaire à ce qu'une implémentation OpenGL ou Direct 3D 11 effectue en interne pour certains types d'objets.

En pratique, cette double (ou triple) mise en mémoire tampon est réalisée dans les backends Vulkan, Metal et autres QRhi similaires en ayant un nombre fixe de ressources natives (telles que VkBuffer) slots derrière un QRhiResource qui peut ensuite être indexé par un index de frame slot allant de 0, 1, ... à FramesInFlight-1, puis en s'enroulant autour de lui.

Tout cela est géré de manière transparente pour les utilisateurs de QRhi. Cependant, les applications qui intègrent le rendu effectué directement avec l'API graphique peuvent vouloir effectuer un double ou triple tamponnage similaire de leurs propres ressources graphiques. Il est alors plus facile d'y parvenir en connaissant les valeurs du nombre maximal de trames en vol (récupérable via resourceLimit()) et l'index de la trame courante (slot) (retourné par cette fonction).

Voir aussi isRecordingFrame(), beginFrame() et endFrame().

QRhiDriverInfo QRhi::driverInfo() const

Renvoie les métadonnées du périphérique graphique utilisé par cette instance QRhi initialisée avec succès.

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

Termine, valide et présente une trame qui a été commencée dans le dernier beginFrame() sur swapChain.

La double (ou triple) mise en mémoire tampon est gérée en interne par les serveurs QRhiSwapChain et QRhi.

flags peut être utilisé de manière optionnelle pour modifier le comportement de certaines manières. Passer QRhi::SkipPresent évite de mettre en file d'attente la commande Present ou d'appeler swapBuffers.

Renvoie QRhi::FrameOpSuccess en cas de succès, ou une autre valeur QRhi::FrameOpResult en cas d'échec. Certaines de ces erreurs doivent être traitées comme des erreurs légères, du type "réessayez plus tard" : Lorsque QRhi::FrameOpSwapChainOutOfDate est renvoyé, la chaîne d'échange doit être redimensionnée ou mise à jour en appelant QRhiSwapChain::createOrResize(). L'application doit ensuite essayer de générer une nouvelle image. QRhi::FrameOpDeviceLost signifie que le périphérique graphique est perdu, mais cela peut également être récupéré en libérant toutes les ressources, y compris le QRhi lui-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, soumet et attend le cadre hors écran.

flags n'est pas utilisé actuellement.

Voir aussi 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 si un tel contrôle n'est pas disponible avec une API graphique donnée.

Pour les backends où un tel 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 qu'il n'y a pas de contrôle fin sur le choix du périphérique à utiliser.

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. D'autres peuvent ne pas le faire. Le backend est spécifié par impl. Un 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 d'autres limitations ; avec Vulkan en particulier, QRhiAdapter est spécifié à QVulkanInstance (VkInstance).

L'appelant est censé détruire les objets QRhiAdapter de la liste. Outre 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 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 le périphérique choisi. En pratique, cela équivaut à 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 de params est nécessaire en raison de la conception de certaines API graphiques sous-jacentes. Avec Vulkan en particulier, QVulkanInstance doit être fourni, car l'énumération n'est pas possible sans lui. D'autres champs dans le params spécifique au backend ne seront pas réellement 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, comme pour create(). Cependant, contrairement à create(), seuls les champs du périphérique physique (dans le cas de Vulkan) ou du LUID de l'adaptateur (dans le cas de D3D) sont utilisés, tous les autres champs sont ignorés. Ceci peut être utilisé pour restreindre les résultats à un adaptateur donné. La liste renvoyée contiendra 1 ou 0 éléments dans ce cas.

Notez que dans l'extrait de code précédent, l'implémentation de la fonction looksGood() ne peut pas effectuer de filtrage spécifique à la plateforme basé sur la véritable identité de l'adaptateur / du périphérique physique, comme le LUID de l'adaptateur sous Windows ou le VkPhysicalDevice avec Vulkan. En effet, QRhiDriverInfo ne contient pas de données spécifiques à la plate-forme. Au lieu de cela, utilisez nativeHandles pour obtenir les résultats filtrés déjà à l'intérieur de enumerateAdapters().

Les deux extraits suivants, qui utilisent Direct 3D 12 comme exemple, sont équivalents dans la pratique :

// approche basée sur l'énumération des adaptateurs depuis Qt  6.10QRhiD3D12InitParams initParams ; QRhiD3D12NativeHandles nativeHandles ; nativeHandles.adapterLuidLow = luid.LowPart ; // a récupéré un LUID quelque part, le transmet maintenant à QtnativeHandles.adapterLuidHigh = luid.HighPart ;QRhi::AdapterList adapters = QRhi::enumerateAdapters(QRhi::D3D12, &initParams, &nativeHandles) ;if (adapters.isEmpty()) { qWarning("Requested adapter was not found") ; }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 aussi create().

QRhi::FrameOpResult QRhi::finish()

Attend que le travail sur la file d'attente graphique (le cas échéant) soit terminé, puis exécute toutes les opérations différées, comme l'achèvement des relectures et des libérations de ressources. Peut être appelé à l'intérieur et à l'extérieur d'une trame, mais pas à l'intérieur d'une passe. À l'intérieur d'une trame, elle implique la soumission de tout travail sur le tampon de commande.

Note : Évitez cette fonction. Un cas où elle peut être nécessaire est lorsque les résultats d'une lecture en file d'attente dans une trame basée sur une chaîne d'échange sont nécessaires à un moment donné fixe et qu'il est donc souhaitable d'attendre les résultats.

bool QRhi::isClipDepthZeroToOne() const

Renvoie true si l'API graphique sous-jacente utilise la plage de profondeur [0, 1] dans l'espace clip.

En pratique, c'est false pour OpenGL uniquement, car OpenGL utilise une plage de profondeur post-projection de [-1, 1]. (à ne pas confondre avec la correspondance NDC-fenêtre contrôlée par glDepthRange(), qui utilise une plage de [0, 1], à moins qu'elle ne soit remplacée par QRhiViewport) Dans certaines versions d'OpenGL, glClipControl() pourrait être utilisé pour changer cela, mais le backend OpenGL de QRhi n'utilise pas cette fonction car elle n'est pas disponible dans OpenGL ES ou dans les versions d'OpenGL inférieures à la version 4.5.

Remarque : clipSpaceCorrMatrix() inclut l'ajustement correspondant dans la matrice renvoyée. Par conséquent, de nombreux utilisateurs de QRhi n'ont pas besoin de prendre d'autres mesures que de prémultiplier leurs matrices de projection avec clipSpaceCorrMatrix(). Cependant, certaines techniques graphiques, telles que certains types de mappage d'ombres, impliquent l'utilisation et la sortie de valeurs de profondeur dans les nuanceurs. Ces derniers devront interroger et prendre en compte la valeur de cette fonction le cas échéant.

bool QRhi::isDeviceLost() const

Retourne vrai 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(), en fonction du backend et des API natives sous-jacentes. Le plus courant est endFrame() car c'est là que la présentation a lieu. Avec certains backends, QRhiSwapChain::createOrResize() peut également échouer en raison d'une perte de périphérique. C'est pourquoi cette fonction est fournie comme un 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 par l'intermédiaire de QRhi. Au contraire, toutes les ressources de QRhi doivent être libérées, suivies de la destruction de QRhi. Un nouveau QRhi peut alors être tenté d'être créé. En cas de succès, toutes les ressources graphiques doivent être réinitialisées. Dans le cas contraire, il faut réessayer plus tard, à plusieurs reprises.

Alors que les applications simples peuvent décider de ne pas se préoccuper de la perte de périphérique, sur les plates-formes de bureau couramment utilisées, une perte de périphérique peut se produire pour diverses raisons, notamment la déconnexion physique de l'adaptateur graphique, la désactivation du périphérique ou du pilote, la désinstallation ou la mise à jour du pilote graphique, ou des erreurs qui entraînent une réinitialisation du périphérique graphique. Par exemple, la mise à jour du pilote graphique vers une version plus récente est une tâche courante qui peut se produire à tout moment lorsqu'une application Qt est en cours d'exécution. Les utilisateurs peuvent très bien s'attendre à ce que les applications soient capables de survivre à cela, même lorsque l'application utilise activement une API comme OpenGL ou Direct3D.

On peut s'attendre à ce que les propres cadres de Qt construits sur QRhi, tels que Qt Quick, gèrent et prennent les mesures appropriées lorsqu'une perte de périphérique se produit. Si les données relatives aux ressources graphiques, telles que les textures et les tampons, sont toujours disponibles du côté de l'unité centrale, un tel événement peut ne pas être perceptible au niveau de l'application puisque les ressources graphiques peuvent être réinitialisées de manière transparente à ce moment-là. Cependant, les applications et les bibliothèques qui travaillent directement avec QRhi doivent être préparées à vérifier et à gérer elles-mêmes les situations de perte de périphérique.

Note : Avec OpenGL, les applications peuvent avoir besoin d'accepter les notifications de réinitialisation du contexte en activant QSurfaceFormat::ResetNotification sur le site QOpenGLContext. Cela se fait généralement en activant le drapeau dans QRhiGles2InitParams::format. Il faut toutefois garder à l'esprit que certains systèmes peuvent générer des situations de réinitialisation du contexte même si ce drapeau n'est pas activé.

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

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

bool QRhi::isRecordingFrame() const

Retourne vrai s'il y a un cadre actif, ce qui signifie qu'il y a eu un beginFrame() (ou beginOffscreenFrame()) sans endFrame() (ou endOffscreenFrame()) correspondant.

Voir aussi 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 à la fois pour les formats non compressés et compressés.

bool QRhi::isYUpInFramebuffer() const

Renvoie true si l'API graphique sous-jacente fait pointer l'axe Y vers le haut dans les framebuffers et les images.

En pratique, il s'agit de true pour OpenGL uniquement.

bool QRhi::isYUpInNDC() const

Renvoie true si l'API graphique sous-jacente a l'axe Y orienté vers le haut dans son système de coordonnées normalisé.

En pratique, il s'agit de false pour Vulkan uniquement.

Remarque : clipSpaceCorrMatrix() inclut l'ajustement correspondant (pour faire pointer Y vers le haut) dans la matrice renvoyée.

bool QRhi::makeThreadLocalNativeContextCurrent()

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

L'appel à cette fonction est typiquement pertinent dans le code du cadre Qt XML, quand on doit s'assurer que le code OpenGL externe fourni par l'application peut toujours fonctionner comme avant avec l'utilisation directe d'OpenGL, aussi longtemps que QRhi utilise le backend OpenGL.

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

Voir aussi QOpenGLContext::makeCurrent() et QOpenGLContext::isValid().

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

Renvoie le nombre de niveaux de mip pour un size donné.

const QRhiNativeHandles *QRhi::nativeHandles()

Renvoie un pointeur vers la collection d'objets natifs spécifiques au backend pour l'appareil, le contexte et les concepts similaires utilisés par le backend.

Le pointeur peut être converti en QRhiVulkanNativeHandles, QRhiD3D11NativeHandles, QRhiD3D12NativeHandles, QRhiGles2NativeHandles, ou QRhiMetalNativeHandles, selon le cas.

Remarque : aucun droit de propriété n'est transféré, ni pour le pointeur retourné, ni pour les objets natifs.

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

Renvoie un nouveau tampon avec les adresses type, usage et size spécifiées.

Note : Certaines combinaisons de usage et type peuvent ne pas être supportées par tous les backends. Voir UsageFlags et the feature flags.

Note : Les backends peuvent choisir d'allouer des tampons plus grands que size. Ceci est fait de manière transparente pour les applications, il n'y a donc pas de restrictions particulières sur la valeur de size. QRhiBuffer::size() renverra 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 : Compute n'est disponible que lorsque la fonctionnalité Compute est signalée comme étant 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 valeurs spécifiées 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écider du format à utiliser pour le stockage du tampon de rendu.

Remarque : backingFormatHint devient pertinent lorsque des formats de texture à multi-échantillonnage et à virgule flottante sont impliqués : le rendu dans un multi-échantillon QRhiRenderBuffer puis la résolution dans un non-RGBA8 QRhiTexture impliquent (avec certaines API graphiques) que le stockage qui soutient le 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 pour QRhiTexture::RGBA8 par défaut, ce qui entraînera des problèmes plus tard en raison d'une tentative de résolution RGBA8->RGBA32F multi-échantillon dans les pièces jointes de couleur de QRhiTextureRenderTarget.

Voir aussi 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 d'agrandissement spécifié magFilter, le filtre de minimisation minFilter, le mode mipmapping mipmapMode, et les modes d'adressage (wrap) addressU, addressV, et addressW.

Remarque : le fait de donner à mipmapMode 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. Toute tentative d'utilisation de l'échantillonneur avec une texture ne contenant 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 liaison de ressources de shaders.

Voir aussi QRhiResource::destroy().

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

Renvoie un nouvel objet de carte de taux d'ombrage.

Cette fonction a été introduite dans Qt 6.9.

QRhiSwapChain *QRhi::newSwapChain()

Renvoie une nouvelle chaîne d'échange.

Voir aussi 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 valeurs spécifiées format, pixelSize, sampleCount, et flags.

Pour un tableau de textures 1D, QRhiTexture::OneDimensional doit être défini dans flags. Cette fonction active implicitement ce drapeau si la hauteur de pixelSize est égale à 0.

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

Remarque : les textures 1D ne sont fonctionnelles que lorsque la fonctionnalité OneDimensionalTextures est signalée comme étant prise en charge au moment de l'exécution. De plus, les mipmaps sur les textures 1D ne sont fonctionnelles que lorsque la fonctionnalité OneDimensionalTextureMipmaps est signalée au moment 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 valeurs spécifiées format, width, height, depth, sampleCount, et flags.

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

Pour une texture 1D, QRhiTexture::OneDimensional doit être défini dans flags. Cette surcharge activera implicitement ce drapeau si height et depth valent tous deux 0.

Remarque : les textures 3D ne sont fonctionnelles que si la fonctionnalité ThreeDimensionalTextures est signalée comme étant prise en charge au moment de l'exécution.

Remarque : les textures 1D ne sont fonctionnelles que si la fonctionnalité OneDimensionalTextures est signalée comme étant prise en charge au moment de l'exécution. En outre, les mipmaps sur les textures 1D ne sont fonctionnels que si la fonctionnalité OneDimensionalTextureMipmaps est signalée comme étant prise en charge au moment 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 valeurs spécifiées format, arraySize, pixelSize, sampleCount, et flags.

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

Pour un tableau de textures 1D, QRhiTexture::OneDimensional doit être défini dans flags. Cette fonction définira implicitement cet indicateur si la hauteur de pixelSize est égale à 0.

Remarque : ne confondez pas les tableaux de textures avec les tableaux de textures. Un site 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 qui sont exposées au shader via QRhiShaderResourceBinding::sampledTextures() et un nombre > 1, et déclarées dans le shader, par exemple comme ceci : layout(binding = 1) uniform sampler2D textures[4];

Remarque : ceci n'est fonctionnel que lorsque la fonctionnalité TextureArrays est signalée comme étant prise en charge au moment de l'exécution.

Remarque : les textures 1D ne sont fonctionnelles que si la fonctionnalité OneDimensionalTextures est déclarée comme étant prise en charge au moment de l'exécution. De plus, les mipmaps sur les textures 1D ne sont fonctionnels que lorsque la fonctionnalité OneDimensionalTextureMipmaps est signalée comme étant prise en charge au moment 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 attachements de couleur et de profondeur/stencil donnés dans desc, et avec la valeur spécifiée flags.

Voir aussi QRhiResource::destroy().

QRhiResourceUpdateBatch *QRhi::nextResourceUpdateBatch()

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

Remarque : la valeur de retour n'appartient pas à l'appelant et ne doit jamais être détruite. Au contraire, le lot est retourné au pool pour être réutilisé en le passant à QRhiCommandBuffer::beginPass(), QRhiCommandBuffer::endPass(), ou QRhiCommandBuffer::resourceUpdate(), ou en appelant QRhiResourceUpdateBatch::release() dessus.

Remarque : elle peut également être appelée en dehors de beginFrame() - endFrame(), car une instance de lot ne fait que collecter des données, elle n'effectue aucune opération.

Comme elle n'est pas liée à une image en cours d'enregistrement, la séquence suivante est valable à titre d'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 maximum de lots par QRhi est de 64. Lorsque cette limite est atteinte, la fonction renvoie la valeur null jusqu'à ce qu'un lot soit renvoyé au pool.

QByteArray QRhi::pipelineCacheData()

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

En sauvegardant puis en rechargeant les données du cache lors des exécutions ultérieures de la même application, il est possible de réduire les temps de création des pipelines et des shaders. Ce que le cache et sa version sérialisée comprennent exactement n'est pas spécifié, est toujours spécifique au backend utilisé et, dans certains cas, dépend également de l'implémentation particulière de l'API graphique.

Lorsque PipelineCacheDataLoadSave est signalé comme n'étant pas pris en charge, le fichier QByteArray renvoyé est vide.

Lorsque l'indicateur EnablePipelineCacheDataSave n'a pas été spécifié lors de l'appel à create(), la page QByteArray renvoyée peut être vide, même si la fonctionnalité PipelineCacheDataLoadSave est prise en charge.

Lorsque les données renvoyées sont non vides, elles sont toujours spécifiques à la version de Qt et au backend QRhi. En outre, dans certains cas, il existe une forte dépendance à l'égard du périphérique graphique et de la version exacte du pilote utilisé. QRhi se charge d'ajouter l'en-tête approprié et les sauvegardes qui garantissent que les données peuvent toujours être transmises en toute sécurité à setPipelineCacheData(), de sorte que les tentatives de chargement de données à partir d'une exécution sur une autre version d'un pilote seront traitées en toute sécurité et avec élégance.

Note : L'appel à releaseCachedResources() peut, en fonction du 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 : minimisez le nombre d'appels à cette fonction. La récupération du blob n'est pas toujours une opération bon marché, et cette fonction ne doit donc être appelée qu'à une faible fréquence, idéalement une seule fois, par exemple lors de la fermeture de l'application.

Voir aussi setPipelineCacheData(), create() et isFeatureSupported().

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

Retourne vrai si create() est susceptible de réussir lorsqu'il est appelé avec impl et params.

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

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

Voir aussi create().

void QRhi::releaseCachedResources()

Tente de libérer des ressources dans les caches du backend. Il peut s'agir des ressources du processeur et du processeur graphique. Seules la mémoire et les ressources qui peuvent être recréées automatiquement sont concernées. Par exemple, si l'implémentation QRhiGraphicsPipeline du backend maintient un cache des résultats de la compilation des shaders, l'appel à cette fonction conduit à vider ce cache, libérant ainsi potentiellement de la mémoire et des ressources graphiques.

L'appel à cette fonction est utile dans les environnements où les ressources sont limitées et où, à un certain moment, il est nécessaire d'assurer une utilisation minimale des ressources, au détriment des performances.

void QRhi::removeCleanupCallback(const void *key)

Désenregistre le rappel auprès de key. Si aucun rappel de nettoyage n'a été enregistré auprès de key, la fonction ne fait rien. Les rappels enregistrés sans clé ne peuvent pas être supprimés.

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 demandées par les backends lors de l'initialisation, ce qui signifie que l'appel à cette fonction est une opération légère.

void QRhi::setPipelineCacheData(const QByteArray &data)

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

Lorsque PipelineCacheDataLoadSave est signalé comme n'étant pas pris 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 XML, 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 sauvegardes qui garantissent que les données peuvent toujours être transmises en toute sécurité à cette fonction. En cas de non-concordance, par exemple parce que le pilote a été mis à niveau vers une version plus récente ou parce que les données ont été générées à partir d'un backend QRhi différent, un avertissement est imprimé et data est ignoré en toute sécurité.

Avec Vulkan, cela correspond directement à VkPipelineCache. L'appel à 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 ultérieurement, ce qui accélère potentiellement la création du pipeline.

Avec d'autres API, il n'y a pas de véritable cache de pipeline, mais elles peuvent fournir un cache avec du bytecode provenant de compilations de shaders (D3D) ou de binaires de programmes (OpenGL). Dans les applications qui compilent beaucoup de shaders à partir des sources au moment de l'exécution, cela peut donner un coup de pouce significatif lors des exécutions suivantes si le "pipeline cache" est pré-alimenté à partir d'une exécution antérieure à l'aide de cette fonction.

Remarque : QRhi ne peut pas garantir que data a un effet sur les performances du pipeline et de la création de shaders. Avec des API comme Vulkan, c'est au pilote de décider si data est utilisé dans un certain but, ou s'il est ignoré.

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

Remarque : ce mécanisme offert par QRhi est indépendant du mécanisme de mise en cache interne des pilotes, 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 visible du tout dans le cas où d'autres mécanismes de mise en cache hors du contrôle de Qt sont déjà actifs.

Remarque : minimisez le nombre d'appels à cette fonction. Le chargement du blob n'est pas toujours une opération bon marché, et cette fonction ne devrait donc être appelée qu'à une faible fréquence, idéalement une seule fois, par exemple au démarrage de l'application.

Attention : Les données sérialisées du cache du pipeline sont supposées être un contenu fiable. Qt XML effectue une analyse robuste de l'en-tête et des métadonnées incluses dans data, il est cependant 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, le cas échéant, cette fonction permet de fournir des arguments supplémentaires à la prochaine soumission de commandes à la file d'attente des commandes graphiques.

En particulier, avec Vulkan, elle permet de transmettre une liste d'objets sémaphores Vulkan que vkQueueSubmit() doit signaler et sur lesquels il doit attendre. params doit alors être un QRhiVulkanQueueSubmitParams. Cela devient essentiel dans certains cas d'utilisation avancés, comme lors de l'exécution d'appels Vulkan natifs qui impliquent d'attendre et de signaler des sémaphores VkSemaphores que le code de rendu ou de calcul Vulkan personnalisé de l'application gère. En outre, cette fonction permet également de spécifier des sémaphores supplémentaires sur lesquels attendre dans la prochaine vkQueuePresentKHR().

Remarque : cette fonction n'affecte que la soumission de la file d'attente suivante, qui se produira dans endFrame(), endOffscreenFrame() ou finish(). La mise en file d'attente du présent se produit dans endFrame().

Avec de nombreux autres backends, l'implémentation de cette fonction n'est pas nécessaire.

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 site mipLevel donné, calculée sur la base de la taille du niveau 0 indiquée dans baseLevelSize.

QRhiStats QRhi::statistics() const

Rassemble et renvoie des statistiques sur les délais et les allocations des ressources graphiques.

Les données sur les allocations de mémoire ne sont disponibles qu'avec certains backends, où de telles opérations sont sous le contrôle de Qt. Avec les API graphiques où il n'y a pas de contrôle de niveau inférieur sur les allocations de mémoire des ressources, cela ne sera jamais pris en charge et tous les champs pertinents dans les résultats sont à 0.

Avec Vulkan en particulier, les valeurs sont toujours valides et sont demandées à la bibliothèque d'allocation de mémoire sous-jacente. Cela donne un aperçu des besoins en mémoire des tampons actifs et des textures.

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 comprend également un champ totalUsageBytes qui indique la taille totale, y compris les ressources supplémentaires qui ne sont pas sous le contrôle de la bibliothèque d'allocation de mémoire (tampons de la chaîne de swap, tas de descripteurs, etc.), comme indiqué par DXGI.

Les valeurs correspondent à tous les types de mémoire utilisés, combinés. (c'est-à-dire vidéo + système dans le cas d'un GPU discret).

Des données supplémentaires, telles que le temps total en millisecondes passé dans la création du pipeline graphique et de calcul (qui implique généralement la compilation des shaders ou la consultation du cache, et un traitement potentiellement coûteux) sont disponibles avec la plupart des backends.

Remarque : les temps écoulés pour des opérations telles que la création d'un pipeline peuvent être influencés par divers facteurs. Les résultats ne doivent pas être comparés entre différents backends, car le concept de "pipeline" et ce qui se passe exactement sous le capot lors, par exemple, d'un appel à QRhiGraphicsPipeline::create(), diffèrent grandement entre les API graphiques et leurs implémentations.

Note : En outre, de nombreux pilotes utiliseront probablement diverses stratégies de mise en cache pour les shaders, les programmes, les pipelines. (indépendamment des facilités similaires propres à Qt, telles que setPipelineCacheData() ou le cache de disque binaire de programme spécifique à OpenGL). Parce que ce comportement interne est transparent pour le client de l'API, Qt et QRhi n'ont aucune connaissance ou contrôle sur la stratégie exacte de mise en cache, la persistance, l'invalidation des données mises en cache, etc. Lors de la lecture des temps, tels que le temps passé sur la création du pipeline, la présence potentielle et le comportement non spécifié des mécanismes de cache au niveau du pilote doivent être gardés à l'esprit.

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 backend, cette liste de valeurs supportées est fixée à l'avance, tandis qu'avec d'autres, les propriétés (physiques) du périphérique indiquent ce qui est supporté au moment de l'exécution.

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

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

Retourne la liste des taux d'ombrage variables pris en charge pour le site sampleCount spécifié.

1x1 est toujours pris en charge.

Cette fonction a été introduite dans Qt 6.9.

QThread *QRhi::thread() const

Renvoie le fil de discussion sur lequel QRhi a été initialized.

int QRhi::ubufAligned(int v) const

Renvoie la valeur (typiquement un offset) v alignée sur l'alignement uniforme du tampon donné par ubufAlignment().

int QRhi::ubufAlignment() const

Renvoie l'alignement minimum du tampon uniforme en octets. Cette valeur est généralement de 256.

Tenter de lier une région de tampon uniforme avec un décalage non aligné sur cette valeur conduira à des échecs en fonction du backend et de l'API graphique sous-jacente.

Voir aussi 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 est le QWindow ciblé par une chaîne d'échange.

La structure renvoyée peut être passée à QRhiSwapChain::setProxyData(). Cela a du sens dans les systèmes de rendu threadés : 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 et transmise à la chaîne d'échange. Cela permet d'effectuer des requêtes sur la plateforme native qui ne peuvent être appelées que sur le thread principal, par exemple pour interroger la CAMetalLayer à partir d'une NSView, puis de transmettre les données à QRhiSwapChain qui se trouve sur le thread de rendu. Avec l'exemple de Metal, l'accès à view.layer sur un thread de rendu dédié provoque un avertissement dans le Thread Checker de Xcode. Avec le mécanisme de proxy de données, ce problème est évité.

Lorsque les threads ne sont pas impliqués, la génération et la transmission de QRhiSwapChainProxyData ne sont pas nécessaires : les backends sont garantis d'être en mesure d'interroger tout ce qui est nécessaire par eux-mêmes, et si tout vit sur le thread principal (gui), cela devrait être suffisant.

Note : impl doit correspondre à ce avec quoi QRhi est créé. Par exemple, l'appel à QRhi::Metal sur une plateforme autre qu'Apple ne générera aucune donnée utile.

Non-membres apparenté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.