QRhiBuffer Class
Ressource de sommet, d'index ou de tampon uniforme (constant). 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 |
| Hérite : | QRhiResource |
Types publics
| struct | NativeBuffer |
| enum | Type { Immutable, Static, Dynamic } |
| enum | UsageFlag { VertexBuffer, IndexBuffer, UniformBuffer, StorageBuffer } |
| flags | UsageFlags |
Fonctions publiques
| virtual char * | beginFullDynamicBufferUpdateForCurrentFrame() |
| virtual bool | create() = 0 |
| virtual void | endFullDynamicBufferUpdateForCurrentFrame() |
| virtual QRhiBuffer::NativeBuffer | nativeBuffer() |
| void | setSize(quint32 sz) |
| void | setType(QRhiBuffer::Type t) |
| void | setUsage(QRhiBuffer::UsageFlags u) |
| quint32 | size() const |
| QRhiBuffer::Type | type() const |
| QRhiBuffer::UsageFlags | usage() const |
Fonctions publiques réimplémentées
| virtual QRhiResource::Type | resourceType() const override |
Description détaillée
Remarque : il s'agit d'une API RHI avec des garanties de compatibilité limitées, voir QRhi pour plus de détails.
Un QRhiBuffer encapsule zéro, un ou plusieurs objets tampons natifs (tels que VkBuffer ou MTLBuffer). Avec certaines API graphiques et certains backends, certains types de tampons peuvent ne pas utiliser d'objet tampon natif (par exemple, OpenGL si les objets tampons uniformes ne sont pas utilisés), mais cela est transparent pour l'utilisateur de l'API QRhiBuffer. De même, le fait que certains types de tampons puissent utiliser deux ou trois tampons natifs en dessous, afin de permettre une mise à jour efficace du contenu par image sans bloquer le pipeline du GPU, est en grande partie invisible pour les applications et les bibliothèques.
Une instance de QRhiBuffer est toujours créée en appelant the QRhi's newBuffer() function. Cela ne crée aucune ressource graphique native. Pour ce faire, appelez create() après avoir défini les options appropriées, telles que le type, les drapeaux d'utilisation, la taille, bien que dans la plupart des cas, ces options soient déjà définies en fonction des arguments passés à newBuffer().
Exemple d'utilisation
Pour créer un tampon uniforme pour un nuanceur où le bloc uniforme GLSL contient un seul membre mat4, et mettre à jour le contenu :
QRhiBuffer *ubuf = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 64); if (!ubuf->create()) { error(); } QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch(); QMatrix4x4 mvp; // ... set up the modelview-projection matrix batch->updateDynamicBuffer(ubuf, 0, 64, mvp.constData()); // ... commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call
Exemple de création d'un tampon avec des données de vertex :
const float vertices[] = { -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f }; QRhiBuffer *vbuf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertices)); if (!vbuf->create()) { error(); } QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch(); batch->uploadStaticBuffer(vbuf, vertices); // ... commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call
Un tampon d'index :
static const quint16 indices[] = { 0, 1, 2 }; QRhiBuffer *ibuf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::IndexBuffer, sizeof(indices)); if (!ibuf->create()) { error(); } QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch(); batch->uploadStaticBuffer(ibuf, indices); // ... commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call
Modèles courants
Un appel à create() détruit toutes les ressources natives existantes si create() a été appelé avec succès auparavant. Si ces ressources natives sont encore utilisées par une image en vol (c'est-à-dire qu'il y a une chance qu'elles soient encore lues par le GPU), la destruction de ces ressources est automatiquement différée. Ainsi, un modèle très courant et pratique pour augmenter en toute sécurité la taille d'un tampon déjà initialisé est le suivant. En pratique, cette opération fait tomber et crée un tout nouvel ensemble de ressources natives, ce qui n'est pas nécessairement une opération bon marché, mais elle est plus pratique et plus rapide que les autres solutions, car en ne détruisant pas l'objet buf lui-même, toutes les références à cet objet restent valides dans d'autres structures de données (par exemple, dans n'importe quelle QRhiShaderResourceBinding à partir de laquelle le QRhiBuffer est référencé).
if (buf->size() < newSize) { buf->setSize(newSize); if (!buf->create()) { error(); } } // continue using buf, fill it with new data
Lorsque vous travaillez avec des tampons uniformes, il est parfois nécessaire de combiner les données de plusieurs appels de dessin dans un seul tampon pour des raisons d'efficacité. Attention aux exigences d'alignement : avec certaines API graphiques, les décalages d'un tampon uniforme doivent être alignés sur 256 octets. Cela s'applique à la fois à QRhiShaderResourceBinding et aux décalages dynamiques transmis à setShaderResources(). Utilisez les fonctions ubufAlignment() et ubufAligned() pour créer un code portable. À titre d'exemple, voici un schéma permettant d'émettre plusieurs appels de dessin (N) avec le même pipeline et la même géométrie, mais avec des données différentes dans les tampons uniformes exposés au point de liaison 0. Cela suppose que le tampon est exposé via uniformBufferWithDynamicOffset(), ce qui permet de transmettre une liste QRhiCommandBuffer::DynamicOffset à setShaderResources().
const int N = 2; const int UB_SIZE = 64 + 4; // assuming a uniform block with { mat4 matrix; float opacity; } const int ONE_UBUF_SIZE = rhi->ubufAligned(UB_SIZE); const int TOTAL_UBUF_SIZE = N * ONE_UBUF_SIZE; QRhiBuffer *ubuf = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, TOTAL_UBUF_SIZE); if (!ubuf->create()) { error(); } QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch(); for (int i = 0; i < N; ++i) { batch->updateDynamicBuffer(ubuf, i * ONE_UBUF_SIZE, 64, matrix.constData()); batch->updateDynamicBuffer(ubuf, i * ONE_UBUF_SIZE + 64, 4, &opacity); } // ... // beginPass(), set pipeline, etc., and then: for (int i = 0; i < N; ++i) { QRhiCommandBuffer::DynamicOffset dynOfs[] = { { 0, i * ONE_UBUF_SIZE } }; cb->setShaderResources(srb, 1, dynOfs); cb->draw(36); }
Voir aussi QRhiResourceUpdateBatch, QRhi, et QRhiCommandBuffer.
Documentation sur les types de membres
enum QRhiBuffer::Type
Spécifie le type de stockage de la ressource tampon.
| Constante | Valeur | Description |
|---|---|---|
QRhiBuffer::Immutable | 0 | Indique que les données ne sont pas censées changer après le téléchargement initial. Sous le capot, ces ressources tampon sont généralement placées dans la mémoire locale du périphérique (GPU) (sur les systèmes le cas échéant). Le téléchargement de nouvelles données est possible, mais peut être coûteux. Le téléchargement s'effectue généralement par copie dans une mémoire tampon séparée, visible par l'hôte, à partir de laquelle une copie de mémoire tampon à mémoire tampon GPU est effectuée dans la mémoire tampon GPU proprement dite. |
QRhiBuffer::Static | 1 | Indique que les données ne devraient changer que rarement. Généralement placé dans la mémoire locale du périphérique (GPU), le cas échéant. Sur les backends où les tampons de mise en scène visibles par l'hôte sont utilisés pour le téléchargement, les tampons de mise en scène sont conservés pour ce type de données, contrairement à Immutable, de sorte que les téléchargements ultérieurs n'en pâtissent pas en termes de performances. Les mises à jour fréquentes, en particulier les mises à jour dans des cadres consécutifs, doivent être évitées. |
QRhiBuffer::Dynamic | 2 | Indique que les données sont susceptibles de changer fréquemment. Non recommandé pour les tampons de grande taille. Généralement sauvegardé par la mémoire visible de l'hôte en 2 copies afin de permettre des modifications sans bloquer le pipeline graphique. La double mise en mémoire tampon est gérée de manière transparente pour les applications et n'est pas exposée dans l'API sous quelque forme que ce soit. C'est le type recommandé, et, avec certains backends, le seul possible, pour les tampons avec une utilisation de UniformBuffer. |
enum QRhiBuffer::UsageFlag
flags QRhiBuffer::UsageFlags
Valeurs des drapeaux permettant de spécifier la manière dont le tampon sera utilisé.
| Constante | Valeur | Description |
|---|---|---|
QRhiBuffer::VertexBuffer | 1 << 0 | Tampon de sommet. Cela permet d'utiliser QRhiBuffer dans setVertexInput(). |
QRhiBuffer::IndexBuffer | 1 << 1 | Tampon d'index. Permet d'utiliser QRhiBuffer dans setVertexInput(). |
QRhiBuffer::UniformBuffer | 1 << 2 | Tampon uniforme (également appelé tampon constant). Cela permet d'utiliser QRhiBuffer en combinaison avec UniformBuffer. Lorsque NonDynamicUniformBuffers est signalé comme n'étant pas pris en charge, cette utilisation ne peut être combinée qu'avec le type Dynamic. |
QRhiBuffer::StorageBuffer | 1 << 3 | Tampon de stockage. Cela permet à QRhiBuffer d'être utilisé en combinaison avec BufferLoad, BufferStore ou BufferLoadStore. Cette utilisation ne peut être combinée qu'avec les types Immutable ou Static, et n'est disponible que lorsque Compute feature est signalé comme étant pris en charge. |
Le type UsageFlags est un typedef pour QFlags<UsageFlag>. Il stocke une combinaison OR de valeurs UsageFlag.
Documentation des fonctions membres
[virtual] char *QRhiBuffer::beginFullDynamicBufferUpdateForCurrentFrame()
Renvoie un pointeur vers un bloc de mémoire contenant les données du tampon visible de l'hôte.
Il s'agit d'un raccourci pour les tampons uniformes dynamiques de taille moyenne à grande dont le contenu entier (ou au moins toutes les régions qui sont lues par les shaders dans la trame courante) est modifié à chaque trame et le mécanisme de mise à jour basé sur QRhiResourceUpdateBatch est considéré comme trop lourd en raison de la quantité de données copiées impliquées.
L'appel à cette fonction doit être suivi d'un appel à endFullDynamicUniformBufferUpdateForCurrentFrame(), avant d'enregistrer toute passe de rendu ou de calcul qui s'appuie sur ce tampon.
Attention : La mise à jour des données via cette méthode n'est pas compatible avec les mises à jour et les relectures basées sur QRhiResourceUpdateBatch. Un comportement inattendu peut se produire lorsque l'on tente de combiner les deux modèles de mise à jour pour le même tampon. De même, les données mises à jour de cette manière directe peuvent ne pas être visibles par readBackBuffer operations, en fonction du backend.
Attention : Lors de la mise à jour des données de la mémoire tampon par cette méthode, la mise à jour doit être effectuée à chaque image, sinon les backends qui effectuent une double ou triple mise en mémoire tampon des ressources peuvent avoir un comportement inattendu.
Avertissement : Les mises à jour partielles ne sont pas possibles avec cette approche car certains backends peuvent choisir une stratégie où le contenu précédent du tampon est perdu lors de l'appel de cette fonction. Les données doivent être écrites dans toutes les régions qui sont lues par les shaders dans la trame en cours de préparation.
Attention : Cette fonction ne peut être appelée que lors de l'enregistrement d'une image, donc entre QRhi::beginFrame() et QRhi::endFrame().
Attention : Cette fonction ne peut être appelée que sur des tampons dynamiques.
[pure virtual] bool QRhiBuffer::create()
Crée les ressources graphiques natives correspondantes. Si des ressources sont déjà présentes en raison d'un create() antérieur sans destroy() correspondant, alors destroy() est appelé implicitement en premier.
Retourne true en cas de succès, false en cas d'échec de l'opération graphique. Quelle que soit la valeur de retour, l'appel à destroy() est toujours sûr.
[virtual] void QRhiBuffer::endFullDynamicBufferUpdateForCurrentFrame()
À appeler lorsque l'ensemble du contenu des données de la mémoire tampon a été mis à jour dans le bloc de mémoire renvoyé par beginFullDynamicBufferUpdateForCurrentFrame().
[virtual] QRhiBuffer::NativeBuffer QRhiBuffer::nativeBuffer()
Renvoie les ressources natives sous-jacentes pour ce tampon. La valeur renvoyée sera vide si l'exposition des ressources natives sous-jacentes n'est pas prise en charge par le backend.
Un QRhiBuffer peut être soutenu par plusieurs objets tampons natifs, en fonction du type() et du backend QRhi utilisé. Lorsque c'est le cas, ils sont tous renvoyés dans le tableau d'objets de la structure renvoyée, slotCount spécifiant le nombre d'objets tampons natifs. Alors que recording a frame, QRhi::currentFrameSlot() peut être utilisé pour déterminer lequel des tampons natifs QRhi utilise pour les opérations qui lisent ou écrivent à partir de ce QRhiBuffer dans l'image en cours d'enregistrement.
Dans certains cas, un QRhiBuffer n'est pas du tout soutenu par un objet tampon natif. Dans ce cas, slotCount est mis à 0 et aucun objet natif valide n'est renvoyé. Il ne s'agit pas d'une erreur, et c'est parfaitement valable lorsqu'un backend donné n'utilise pas de tampons natifs pour les QRhiBuffers avec certains types ou usages.
Remarque : il faut savoir que les backends QRhi peuvent utiliser diverses stratégies de mise à jour des tampons. Contrairement aux textures, pour lesquelles le téléchargement de données d'image implique toujours l'enregistrement d'une commande de copie de tampon à image (ou similaire) sur le tampon de commande, les tampons, en particulier les tampons Dynamic et UniformBuffer, peuvent fonctionner de nombreuses manières différentes. Par exemple, un site QRhiBuffer avec le type d'utilisation UniformBuffer peut même ne pas être soutenu par un objet tampon natif si les tampons uniformes ne sont pas utilisés ou pris en charge par un backend et une API graphique donnés. Il existe également des différences dans la manière dont les données sont écrites dans le tampon et dans le type de mémoire de sauvegarde utilisé. Pour les tampons soutenus par la mémoire visible de l'hôte, l'appel à cette fonction garantit que les écritures en attente de l'hôte sont exécutées pour tous les tampons natifs renvoyés.
Voir également QRhi::currentFrameSlot() et QRhi::FramesInFlight.
[override virtual] QRhiResource::Type QRhiBuffer::resourceType() const
Réimplémente : QRhiResource::resourceType() const.
Renvoie le type de ressource.
void QRhiBuffer::setSize(quint32 sz)
Fixe la taille du tampon en octets. La taille est normalement spécifiée dans QRhi::newBuffer(), cette fonction n'est donc utilisée que lorsque la taille doit être modifiée. Comme pour les autres paramètres, la taille ne prend effet que lors de l'appel à create(), et pour les tampons déjà créés, cela implique de libérer la ressource native précédente et d'en créer de nouvelles sous le capot.
Les backends peuvent choisir d'allouer des tampons plus grands que sz afin de répondre aux exigences d'alignement. Ceci est caché aux applications et size() indiquera toujours la taille demandée dans sz.
Voir également size().
void QRhiBuffer::setType(QRhiBuffer::Type t)
Définit le type du tampon à t.
Voir aussi type().
void QRhiBuffer::setUsage(QRhiBuffer::UsageFlags u)
Définit les drapeaux d'utilisation du tampon à u.
Voir aussi usage().
quint32 QRhiBuffer::size() const
Renvoie la taille du tampon en octets.
Il s'agit toujours de la valeur passée à setSize() ou QRhi::newBuffer(). En interne, les tampons natifs peuvent être plus grands si l'API graphique sous-jacente l'exige.
Voir aussi setSize().
QRhiBuffer::Type QRhiBuffer::type() const
Renvoie le type de tampon.
Voir aussi setType().
QRhiBuffer::UsageFlags QRhiBuffer::usage() const
Renvoie les drapeaux d'utilisation du tampon.
Voir aussi setUsage().
© 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.