En esta página

QRhiBuffer Class

Recurso de búfer de vértice, índice o uniforme (constante). Más...

Cabecera: #include <rhi/qrhi.h>
CMake: find_package(Qt6 REQUIRED COMPONENTS GuiPrivate)
target_link_libraries(mytarget PRIVATE Qt6::GuiPrivate)
qmake: QT += gui-private
Desde: Qt 6.6
Hereda: QRhiResource

Tipos Públicos

struct NativeBuffer
enum Type { Immutable, Static, Dynamic }
enum UsageFlag { VertexBuffer, IndexBuffer, UniformBuffer, StorageBuffer }
flags UsageFlags

Funciones Públicas

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

Funciones Públicas Reimplementadas

virtual QRhiResource::Type resourceType() const override

Descripción detallada

Nota: Esta es una API RHI con garantías de compatibilidad limitadas, véase QRhi para más detalles.

Un QRhiBuffer encapsula cero, uno o más objetos buffer nativos (como VkBuffer o MTLBuffer). Con algunas APIs gráficas y backends ciertos tipos de buffers pueden no utilizar un objeto buffer nativo en absoluto (por ejemplo, OpenGL si no se utilizan objetos buffer uniformes), pero esto es transparente para el usuario de la API QRhiBuffer. Del mismo modo, el hecho de que algunos tipos de buffers puedan utilizar dos o tres buffers nativos por debajo, con el fin de permitir una actualización eficiente del contenido por fotograma sin paralizar el pipeline de la GPU, es en su mayoría invisible para las aplicaciones y librerías.

Una instancia de QRhiBuffer se crea siempre llamando a the QRhi's newBuffer() function. Esto no crea recursos gráficos nativos. Para ello, llama a create() después de establecer las opciones apropiadas, como el tipo, las banderas de uso, el tamaño, aunque en la mayoría de los casos éstas ya están establecidas en base a los argumentos pasados a newBuffer().

Ejemplo de uso

Para crear un buffer uniforme para un shader donde el bloque uniforme GLSL contiene un único miembro mat4, y actualizar el contenido:

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

Un ejemplo de creación de un buffer con datos de vértices:

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 buffer de índices:

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

Patrones comunes

Una llamada a create() destruye cualquier recurso nativo existente si antes se llamó con éxito a create(). Si esos recursos nativos todavía están en uso por un fotograma en vuelo (es decir, existe la posibilidad de que todavía sean leídos por la GPU), la destrucción de esos recursos se aplaza automáticamente. Así, un patrón muy común y conveniente para aumentar de forma segura el tamaño de un búfer ya inicializado es el siguiente. En la práctica, esto elimina y crea todo un nuevo conjunto de recursos nativos por debajo, por lo que no es necesariamente una operación barata, pero es más conveniente y aún más rápida que las alternativas, porque al no destruir el objeto buf en sí, todas las referencias a él siguen siendo válidas en otras estructuras de datos (por ejemplo, en cualquier QRhiShaderResourceBinding desde el que se haga referencia al QRhiBuffer).

if (buf->size() < newSize) {
    buf->setSize(newSize);
    if (!buf->create()) { error(); }
}
// continue using buf, fill it with new data

Cuando se trabaja con buffers uniformes, a veces será necesario combinar datos para múltiples llamadas a dibujo en un único buffer por razones de eficiencia. Ten en cuenta los requisitos de alineación: con algunas APIs gráficas, los offsets de un buffer uniforme deben estar alineados a 256 bytes. Esto se aplica tanto a QRhiShaderResourceBinding como a los desplazamientos dinámicos pasados a setShaderResources(). Utilice las funciones ubufAlignment() y ubufAligned() para crear código portable. Como ejemplo, el siguiente es un esquema para emitir múltiples (N) llamadas de dibujo con el mismo pipeline y geometría, pero con diferentes datos en los buffers uniformes expuestos en el punto de enlace 0. Esto asume que el buffer es expuesto vía uniformBufferWithDynamicOffset() que permite pasar una lista QRhiCommandBuffer::DynamicOffset a 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);
}

Véase también QRhiResourceUpdateBatch, QRhi, y QRhiCommandBuffer.

Documentación de tipos de miembros

enum QRhiBuffer::Type

Especifica el tipo de almacenamiento del recurso de memoria intermedia.

ConstanteValorDescripción
QRhiBuffer::Immutable0Indica que no se espera que los datos cambien nunca después de la carga inicial. Bajo el capó, tales recursos de búfer se colocan típicamente en la memoria local del dispositivo (GPU) (en sistemas donde sea aplicable). La carga de nuevos datos es posible, pero puede resultar costosa. Por lo general, la carga se realiza copiando a un búfer separado, visible para el host, desde el cual se emite una copia de búfer a búfer de la GPU al búfer real exclusivo de la GPU.
QRhiBuffer::Static1Indica que se espera que los datos cambien con poca frecuencia. Normalmente se coloca en la memoria local del dispositivo (GPU), si procede. En los backends en los que se utilizan memorias intermedias visibles desde el host para la carga, las memorias intermedias se mantienen para este tipo, a diferencia de Immutable, por lo que el rendimiento de las cargas posteriores no se ve afectado. Deben evitarse las actualizaciones frecuentes, especialmente las actualizaciones en tramas consecutivas.
QRhiBuffer::Dynamic2Indica que se espera que los datos cambien con frecuencia. No se recomienda para buffers grandes. Normalmente se almacenan en la memoria visible del host en 2 copias para permitir cambios sin que se detenga el canal de gráficos. La doble memoria intermedia se gestiona de forma transparente para las aplicaciones y no se expone de ninguna forma en la API. Este es el tipo recomendado, y con algunos backends, el único posible, para buffers con uso de UniformBuffer.

enum QRhiBuffer::UsageFlag
flags QRhiBuffer::UsageFlags

Valores de bandera para especificar cómo se va a utilizar el buffer.

ConstanteValorDescripción
QRhiBuffer::VertexBuffer1 << 0Búfer de vértices. Permite utilizar QRhiBuffer en setVertexInput().
QRhiBuffer::IndexBuffer1 << 1Búfer de índice. Permite utilizar QRhiBuffer en setVertexInput().
QRhiBuffer::UniformBuffer1 << 2Memoria intermedia uniforme (también llamada memoria intermedia constante). Permite utilizar QRhiBuffer en combinación con UniformBuffer. Cuando NonDynamicUniformBuffers se notifica como no compatible, este uso sólo puede combinarse con el tipo Dynamic.
QRhiBuffer::StorageBuffer1 << 3Búfer de almacenamiento. Permite utilizar QRhiBuffer en combinación con BufferLoad, BufferStore, o BufferLoadStore. Este uso sólo puede combinarse con los tipos Inmutable o Estático, y sólo está disponible cuando se indica que Compute feature es compatible.

El tipo UsageFlags es un typedef para QFlags<UsageFlag>. Almacena una combinación OR de valores UsageFlag.

Documentación de las funciones miembro

[virtual] char *QRhiBuffer::beginFullDynamicBufferUpdateForCurrentFrame()

Devuelve un puntero a un bloque de memoria con los datos del búfer visible del host.

Este es un atajo para buffers uniformes dinámicos de tamaño medio-grande cuyo contenido completo (o al menos todas las regiones que son leídas por los shaders en el frame actual) cambia en cada frame y el mecanismo de actualización basado en QRhiResourceUpdateBatch se ve demasiado pesado debido a la cantidad de copia de datos que implica.

La llamada a esta función debe ser eventualmente seguida por una llamada a endFullDynamicUniformBufferUpdateForCurrentFrame(), antes de grabar cualquier render o compute pass que dependa de este buffer.

Advertencia: La actualización de datos a través de este método no es compatible con las actualizaciones y readbacks basados en QRhiResourceUpdateBatch. Puede producirse un comportamiento inesperado al intentar combinar los dos modelos de actualización para el mismo búfer. Del mismo modo, los datos actualizados de esta forma directa pueden no ser visibles para readBackBuffer operations, dependiendo del backend.

Advertencia: Cuando se actualizan los datos del buffer a través de este método, la actualización debe realizarse en cada frame, de lo contrario los backends que realizan doble o triple buffering de recursos pueden terminar en un comportamiento inesperado.

Advertencia: Las actualizaciones parciales no son posibles con este método ya que algunos backends pueden elegir una estrategia en la que el contenido anterior del buffer se pierde al llamar a esta función. Los datos deben escribirse en todas las regiones que son leídas por los shaders en el fotograma que se está preparando.

Advertencia: Esta función sólo puede ser llamada cuando se está grabando un frame, es decir, entre QRhi::beginFrame() y QRhi::endFrame().

Atención: Esta función sólo puede ser llamada en buffers dinámicos.

[pure virtual] bool QRhiBuffer::create()

Crea los recursos gráficos nativos correspondientes. Si ya hay recursos presentes debido a un create() anterior sin destroy() correspondiente, entonces destroy() se llama implícitamente primero.

Devuelve true en caso de éxito, false en caso de fallo de la operación gráfica. Independientemente del valor de retorno, la llamada a destroy() es siempre segura.

[virtual] void QRhiBuffer::endFullDynamicBufferUpdateForCurrentFrame()

Se llamará cuando se haya actualizado todo el contenido de los datos del búfer en el bloque de memoria devuelto por beginFullDynamicBufferUpdateForCurrentFrame().

[virtual] QRhiBuffer::NativeBuffer QRhiBuffer::nativeBuffer()

Devuelve los recursos nativos subyacentes para este búfer. El valor devuelto estará vacío si el backend no admite la exposición de los recursos nativos subyacentes.

Un QRhiBuffer puede estar respaldado por múltiples objetos de búfer nativos, dependiendo del type() y del backend QRhi en uso. Cuando este es el caso, todos ellos se devuelven en la matriz de objetos de la estructura devuelta, con slotCount especificando el número de objetos de búfer nativos. Mientras que recording a frame, QRhi::currentFrameSlot() se puede utilizar para determinar cuál de los búferes nativos QRhi está utilizando para las operaciones que leen o escriben desde este QRhiBuffer dentro del fotograma que se está grabando.

En algunos casos un QRhiBuffer no estará respaldado por un objeto buffer nativo en absoluto. En este caso slotCount se pondrá a 0 y no se devolverá ningún objeto nativo válido. Esto no es un error, y es perfectamente válido cuando un backend dado no utiliza buffers nativos para QRhiBuffers con ciertos tipos o usos.

Nota: Ten en cuenta que los backends de QRhi pueden emplear varias estrategias de actualización de buffers. A diferencia de las texturas, en las que cargar datos de imagen siempre significa grabar un comando de copia de búfer a imagen (o similar) en el búfer de comandos, los búferes, en particular los dinámicos y UniformBuffer, pueden funcionar de muchas formas distintas. Por ejemplo, un QRhiBuffer con el tipo de uso UniformBuffer puede incluso no estar respaldado por un objeto de búfer nativo en absoluto si los búferes uniformes no se utilizan o no son compatibles con un backend y una API de gráficos determinados. También hay diferencias en cómo se escriben los datos en el búfer y el tipo de memoria de respaldo utilizado. Para buffers respaldados por memoria visible del host, llamar a esta función garantiza que las escrituras pendientes del host se ejecuten para todos los buffers nativos devueltos.

Véase también QRhi::currentFrameSlot() y QRhi::FramesInFlight.

[override virtual] QRhiResource::Type QRhiBuffer::resourceType() const

Reimplementa: QRhiResource::resourceType() const.

Devuelve el tipo de recurso.

void QRhiBuffer::setSize(quint32 sz)

Establece el tamaño del búfer en bytes. El tamaño se especifica normalmente en QRhi::newBuffer() por lo que esta función sólo se utiliza cuando hay que cambiar el tamaño. Al igual que con otros setters, el tamaño sólo tiene efecto cuando se llama a create(), y para los buffers ya creados esto implica liberar el recurso nativo anterior y crear nuevos bajo el capó.

Los backends pueden optar por asignar buffers mayores que sz para cumplir con los requisitos de alineación. Esto se oculta a las aplicaciones y size() siempre informará del tamaño solicitado en sz.

Véase también size().

void QRhiBuffer::setType(QRhiBuffer::Type t)

Establece el tipo del búfer en t.

Véase también type().

void QRhiBuffer::setUsage(QRhiBuffer::UsageFlags u)

Establece los indicadores de uso del búfer en u.

Véase también usage().

quint32 QRhiBuffer::size() const

Devuelve el tamaño del búfer en bytes.

Este es siempre el valor que se pasó a setSize() o QRhi::newBuffer(). Internamente, los buffers nativos pueden ser mayores si así lo requiere la API gráfica subyacente.

Véase también setSize().

QRhiBuffer::Type QRhiBuffer::type() const

Devuelve el tipo de búfer.

Véase también setType().

QRhiBuffer::UsageFlags QRhiBuffer::usage() const

Devuelve los indicadores de uso del búfer.

Véase también 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.