En esta página

QRhi Class

Abstracción acelerada de la API de gráficos 2D/3D. 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

Tipos Públicos

(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 }

Funciones públicas

~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

Miembros públicos estáticos

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)

Descripción detallada

Qt Rendering Hardware Interface es una abstracción para APIs de gráficos acelerados por hardware, como OpenGL, OpenGL ES, Direct3D, Metal y Vulkan.

Advertencia: La familia de clases QRhi en el módulo Qt Gui, incluyendo QShader y QShaderDescription, ofrecen garantías de compatibilidad limitadas. No existen garantías de compatibilidad binaria o de código fuente para estas clases, lo que significa que sólo se garantiza que la API funcione con la versión de Qt con la que se desarrolló la aplicación. Sin embargo, los cambios incompatibles con el código fuente se mantendrán al mínimo y sólo se realizarán en versiones menores (6.7, 6.8, etc.). Para usar estas clases en una aplicación, enlace a Qt::GuiPrivate (si usa CMake), e incluya las cabeceras con el prefijo rhi, por ejemplo #include <rhi/qrhi.h>.

Cada instancia de QRhi está respaldada por un backend para una API gráfica específica. La selección del backend es una elección en tiempo de ejecución y depende de la aplicación o librería que crea la instancia de QRhi. Algunos backends están disponibles en múltiples plataformas (OpenGL, Vulkan, Null), mientras que las API específicas de una plataforma determinada sólo están disponibles cuando se ejecutan en la plataforma en cuestión (Metal en macOS/iOS, Direct3D en Windows).

Los backends disponibles actualmente son:

  • OpenGL 2.1 / OpenGL ES 2.0 o más recientes. Algunas extensiones y características más recientes de la especificación del núcleo se utilizan cuando están presentes, por ejemplo, para habilitar framebuffers multimuestra o sombreadores de cálculo. También se admite el funcionamiento en contextos de perfil de núcleo. Si es necesario, las aplicaciones pueden consultar feature flags en tiempo de ejecución para comprobar si existen funciones no compatibles con el contexto OpenGL que respalda el QRhi. El backend OpenGL se basa en QOpenGLContext, QOpenGLFunctions, y la infraestructura multiplataforma relacionada del módulo Qt GUI.
  • Direct3D 11.2 o posterior (con DXGI 1.3 o posterior), utilizando Shader Model 5.0 o posterior. Cuando el tiempo de ejecución de D3D no tiene soporte para las características de 11.2 o Shader Model 5.0, la inicialización utilizando un dispositivo gráfico acelerado fallará, pero el uso del adaptador de software sigue siendo una opción.
  • Direct3D 12 en Windows 10 versión 1703 y posterior, con Shader Model 5.0 o posterior. Qt requiere que ID3D12Device2 esté presente, de ahí el requisito de al menos la versión 1703 de Windows 10. El dispositivo D3D12 se crea por defecto especificando un nivel de características mínimo de D3D_FEATURE_LEVEL_11_0.
  • Metal 1.2 o posterior.
  • Vulkan 1.0 o más reciente, utilizando opcionalmente algunas características de nivel Vulkan 1.1.
  • Null, un backend "ficticio" que no emite ninguna llamada gráfica.

Para permitir que el código de sombreado se escriba una vez en las aplicaciones y bibliotecas Qt, se espera que todos los sombreadores se escriban en un único lenguaje que luego se compila en SPIR-V. A partir de ahí se generan versiones para los distintos lenguajes de sombreado, junto con información de reflexión (entradas, salidas, recursos de sombreado). A continuación, todo ello se empaqueta en instancias de QShader fácil y eficientemente serializables. Los compiladores y las herramientas para generar estos sombreadores no forman parte de QRhi ni del módulo Qt GUI, pero sí lo hacen las clases básicas para utilizarlos, QShader y QShaderDescription. Las API y herramientas para realizar la compilación y traducción forman parte del módulo Qt Shader Tools.

Ver el Ejemplo de Ventana RHI para un ejemplo introductorio de creación de una aplicación portable y multiplataforma que realiza renderizado 3D acelerado en un QWindow usando QRhi.

Una impresión de la API

Para proporcionar una visión rápida de la API con un ejemplo breve pero completo que no implique una configuración relacionada con las ventanas, a continuación se muestra una aplicación multiplataforma completa y ejecutable que renderiza 20 fotogramas fuera de la pantalla y, a continuación, guarda las imágenes generadas en archivos después de volver a leer el contenido de las texturas desde la GPU. Para ver un ejemplo de renderizado en pantalla, que incluye la configuración de QWindow y una cadena de intercambio, consulta el ejemplo de ventana RHI.

Para abreviar, la inicialización del QRhi se realiza en función de la plataforma: el código de ejemplo aquí escoge Direct 3D 12 en Windows, Metal en macOS e iOS, y Vulkan en caso contrario. OpenGL y Direct 3D 11 nunca son utilizados por esta aplicación, pero el soporte para ellos podría ser introducido con unas pocas líneas adicionales.

#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();
   si no        qFatal("Failed to initialize RHI");

   float rotación = 0.0f; float opacidad = 1.0f; int opacidadDir = 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 arriba, 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->nuevoBuffer(QRhiBuffer::Inmutable,            QRhiBuffer::VertexBuffer, sizeof(vertexData)));  vbuf->create(); std::unique_ptr<QRhiBuffer> ubuf(rhi->nuevoBuffer(QRhiBuffer::Dinámico,            QRhiBuffer::BufferUniforme, 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 &nombre) { QFile f(nombre); return f.open(QIODevice::ReadOnly) ? QShader::fromSerialized(f.readAll()) : QShader(); };  ps->setShaderStages({ { QRhiShaderStage::Vertex, getShader(QLatin1String("color.vert.qsb")) },{ QRhiShaderStage::Fragmento, getShader(QLatin1String("color.frag.qsb")) } });   QRhiVertexInputLayout inputLayout; inputLayout.setBindings({ { 5 * sizeof(float) } }); inputLayout.setAttributes({ 0, 0, QRhiVertexInputAttribute::Float2, 0 },{ 0, 1, QRhiVertexInputAttribute::Float3, 2 * sizeof(float) } });  ps->setVertexInputLayout(inputLayout);  ps->setShaderResourceBindings(srb.get());  ps->setRenderPassDescriptor(rp.get());  ps->create();    QRhiCommandBuffer *cb; for(int frame = 0; frame < 20; ++frame) {  rhi->beginOffscreenFrame(&cb);        QRhiResourceUpdateBatch * u =  rhi->nextResourceUpdateBatch(); if (frame == 0)  u->uploadStaticBuffer(vbuf.get(), vertexData); QMatrix4x4 mvp = viewProjection; mvp.rotate(rotation, 0, 1, 0);  u->updateDynamicBuffer(ubuf.get(), 0, 64, mvp.constData()); rotation += 5.0f;  u->updateDynamicBuffer(ubuf.get(), 64, 4, &opacity); opacity += opacityDir * 0.2f; if (opacity < 0.0f || opacity > 1.0f) { opacityDir *=-1; opacity = qBound(0.0f, opacity, 1.0f); }  cb->beginPass(rt.get(), Qt::green, { 1.0f, 0 }, u);  cb->setGraphicsPipeline(ps.get());  cb->setViewport({ 0, 0, 1280, 720 });  cb->setShaderResources(); const QRhiCommandBuffer::VertexInput vbufBinding(vbuf.get(), 0);  cb->setVertexInput(0, 1, &vbufBinding);  cb->draw(3);        QRhiReadbackResult readbackResult; u =  rhi->nextResourceUpdateBatch();  u->readBackTexture({ tex.get() }, &readbackResult);  cb->endPass(u);  rhi->endOffscreenFrame();        QImage image(reinterpret_cast<const uchar *>(readbackResult.data.constData()),readbackResult.pixelSize.width(),readbackResult.pixelSize.height(),                     QImage::Format_RGBA8888_Premultiplied); if (rhi->isYUpInFramebuffer()) image.flip(); image.save(QString::asprintf("frame%d.png", frame)); } return 0; }

El resultado de la aplicación son 20 imágenes PNG (frame0.png - frame19.png). Éstas contienen un triángulo giratorio con opacidad variable sobre un fondo verde.

Se espera que los sombreadores de vértices y fragmentos se procesen y empaqueten en archivos .qsb. El código fuente GLSL compatible con Vulkan es el siguiente:

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

Para compilar y transpilar manualmente estos shaders a una serie de objetivos (SPIR-V, HLSL, MSL, GLSL) y generar los archivos .qsb que la aplicación carga en tiempo de ejecución, ejecute qsb --qt6 color.vert -o color.vert.qsb y qsb --qt6 color.frag -o color.frag.qsb. Alternativamente, el módulo Qt Shader Tools ofrece integración del sistema de compilación para CMake, la función qt_add_shaders() CMake, que puede lograr lo mismo en tiempo de compilación.

Consideraciones de seguridad

Todos los datos consumidos por QRhi y las clases relacionadas como QShader se consideran contenido de confianza.

Advertencia: Se aconseja a los desarrolladores de aplicaciones que consideren cuidadosamente las implicaciones potenciales antes de permitir la alimentación de contenido proporcionado por el usuario que no forme parte de la aplicación y no esté bajo el control de los desarrolladores. (esto incluye todos los datos de vértices/índices, shaders, parámetros de pipeline y llamadas a dibujo, etc.)

Fundamentos del diseño

Un QRhi no puede ser instanciado directamente. En su lugar, utiliza la función create(). Borra la instancia QRhi normalmente para liberar el dispositivo gráfico.

Recursos

Las instancias de las clases derivadas de QRhiResource, tales como, QRhiBuffer, QRhiTexture, etc., encapsulan cero, uno o más recursos gráficos nativos. Las instancias de tales clases se crean siempre a través de las funciones new del QRhi, tales como, newBuffer(), newTexture(), newTextureRenderTarget(), newSwapChain().

QRhiBuffer *vbuf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData));
if (!vbuf->create()) { error(); }
// ...
delete vbuf;
  • El valor devuelto por funciones como newBuffer() es siempre propiedad de quien lo llama.
  • La simple creación de una instancia de una subclase de QRhiResource nunca asigna ni inicializa ningún recurso nativo. Eso sólo se hace cuando se llama a la función create() de una subclase, por ejemplo, QRhiBuffer::create() o QRhiTexture::create().
  • Las excepciones son QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor(), QRhiSwapChain::newCompatibleRenderPassDescriptor() y QRhiRenderPassDescriptor::newCompatibleRenderPassDescriptor(). En estos casos no se realiza la operación create() y el objeto devuelto se activa inmediatamente.
  • Los propios objetos recurso se tratan como inmutables: una vez que se ha llamado a un recurso create(), cambiar cualquier parámetro a través de los configuradores, como QRhiTexture::setPixelSize(), no tiene ningún efecto, a menos que se libere el recurso nativo subyacente y se vuelva a llamar a create(). Más información sobre la reutilización de recursos en las secciones siguientes.
  • Los recursos nativos subyacentes son programados para ser liberados por el destructor QRhiResource, o llamando a QRhiResource::destroy(). Los backends a menudo ponen en cola las peticiones de liberación y aplazan su ejecución hasta un momento no especificado, esto se oculta a las aplicaciones. De esta forma las aplicaciones no tienen que preocuparse de liberar recursos nativos que pueden estar todavía en uso por una trama en vuelo.
  • Nótese que esto no significa que un QRhiResource pueda ser libremente destroy()'ed o borrado dentro de un frame (es decir, en una sección beginFrame() - endFrame()). Como regla general, todos los objetos QRhiResource referenciados deben permanecer sin cambios hasta que se envíe el marco llamando a endFrame(). Para facilitar esto, QRhiResource::deleteLater() se proporciona como una conveniencia.

Búferes de comandos y ejecución diferida de comandos

Independientemente del diseño y las capacidades de la API gráfica subyacente, todos los backends de QRhi implementan algún nivel de memoria intermedia de comandos. Ninguna función de QRhiCommandBuffer emite ningún comando nativo de bind o draw (como, glDrawElements) directamente. Los comandos siempre se registran en una cola, ya sea nativa o proporcionada por el backend QRhi. El búfer de comandos se envía, y por lo tanto la ejecución comienza sólo con QRhi::endFrame() o QRhi::finish().

La naturaleza diferida tiene consecuencias para algunos tipos de objetos. Por ejemplo, escribir en un búfer dinámico varias veces dentro de un fotograma, en caso de que dichos búferes estén respaldados por memoria visible por el host, hará que los resultados de todas las escrituras sean visibles para todas las llamadas a dibujo en el búfer de comandos del fotograma, independientemente de cuándo se registró la actualización del búfer dinámico en relación con una llamada a dibujo.

Además, las instancias de las subclases de QRhiResource deben tratarse de forma inmutable dentro de un fotograma en el que se haga referencia a ellas de cualquier forma. Crea todos los recursos por adelantado, antes de empezar a grabar comandos para el siguiente fotograma. La reutilización de una instancia de QRhiResource dentro de un fotograma (llamando a create() y volviendo a referenciarla en la misma sección beginFrame - endFrame ) debe evitarse, ya que puede dar lugar a resultados inesperados, dependiendo del backend.

Como regla general, todos los objetos QRhiResource referenciados deben permanecer válidos y sin modificar hasta que se envíe el marco llamando a endFrame(). Por otro lado, la llamada a destroy() o la eliminación de QRhiResource son siempre seguras una vez que el frame es enviado, independientemente del estado de los recursos nativos subyacentes (que todavía pueden estar en uso por la GPU - pero de eso se encarga internamente).

A diferencia de APIs como OpenGL, los comandos del tipo cargar y copiar no pueden mezclarse con comandos de dibujar. El renderizador típico implicará una secuencia similar a la siguiente:

  • (re)crear recursos
  • iniciar fotograma
  • grabar/emitir cargas y copias
  • empezar a grabar un pase de render
  • grabar llamadas de dibujo
  • finalizar pase de render
  • finalizar fotograma

La grabación de operaciones de copia se realiza a través de QRhiResourceUpdateBatch. Este tipo de operaciones se realizan normalmente en beginPass().

Cuando se trabaja con motores de renderizado heredados diseñados para OpenGL, la migración a QRhi a menudo implica rediseñar de tener un único paso render (que realiza copias y cargas, limpia buffers, y emite llamadas de dibujo, todo mezclado) a una configuración claramente separada, de dos fases prepare - render donde el paso render sólo inicia un renderpass y registra llamadas de dibujo, mientras que toda la creación de recursos y puesta en cola de actualizaciones, cargas y copias ocurre de antemano, en el paso prepare.

QRhi no permite por el momento crear y enviar libremente buffers de comandos. Esto puede levantarse en el futuro hasta cierto punto, en particular si se introduce el soporte de computación, pero el modelo de puntos frame-start y frame-end bien definidos, combinado con un buffer de comandos dedicado, "frame", donde frame-end implica presentar, va a seguir siendo la principal forma de operar ya que es lo que mejor se adapta a las diversas tecnologías de interfaz de usuario de Qt.

Threading

Una instancia de QRhi y los recursos asociados pueden ser creados y utilizados en cualquier subproceso, pero todo el uso debe limitarse a ese único subproceso. Cuando se renderiza a múltiples QWindows en una aplicación, tener un hilo dedicado y una instancia de QRhi para cada ventana es a menudo aconsejable, ya que esto puede eliminar problemas de ralentización inesperada causada por la presentación a múltiples ventanas. Conceptualmente es lo mismo que el bucle de renderizado de Qt Quick cuando se trabaja directamente con OpenGL: un subproceso para cada ventana, un QOpenGLContext para cada subproceso. Al pasar a QRhi, QOpenGLContext se sustituye por QRhi, lo que facilita la migración.

Cuando se trata de objetos nativos creados externamente, como contextos OpenGL pasados a través de QRhiGles2NativeHandles, depende de la aplicación asegurarse de que no son mal utilizados por otros hilos.

Los recursos no son compartibles entre instancias de QRhi. Esta es una elección intencionada ya que QRhi oculta la mayoría de las tareas relacionadas con la cola, el buffer de comandos y la sincronización de recursos, y no proporciona ninguna API para ellos. El uso concurrente seguro y eficiente de los recursos gráficos de múltiples hilos está ligado a esos conceptos, sin embargo, y es por lo tanto un tema que está actualmente fuera del alcance, pero puede ser introducido en el futuro.

Nota: El backend Metal requiere que un pool de autorelease esté disponible en el hilo de renderizado, idealmente envolviendo cada iteración del bucle de renderizado. Esto no requiere ninguna acción por parte de los usuarios de QRhi cuando se renderiza en el hilo principal (gui), pero se vuelve importante cuando se utiliza un hilo de renderizado separado y dedicado.

Sincronización de recursos

QRhi no expone APIs para barreras de recursos o transiciones de diseño de imagen. Dicha sincronización se realiza implícitamente por los backends, en su caso (por ejemplo, Vulkan), mediante el seguimiento del uso de recursos, según sea necesario. Las barreras de búfer e imagen se insertan antes de los pases de renderizado o cálculo de forma transparente para la aplicación.

Nota: Se espera que los recursos de un pase de renderizado o de cálculo estén vinculados a un único uso durante ese pase. Por ejemplo, un búfer puede utilizarse como búfer de vértices, de índice, uniforme o de almacenamiento, pero no como una combinación de ellos dentro de un mismo pase. Sin embargo, es perfectamente posible utilizar un búfer como búfer de almacenamiento en un pase de cálculo y, a continuación, como búfer de vértices en un pase de renderizado, por ejemplo, suponiendo que el búfer haya declarado ambos usos en el momento de su creación.

Nota: Las texturas tienen esta regla relajada en ciertos casos, porque el uso de dos sub-recursos (típicamente dos niveles mip diferentes) de la misma textura para diferentes accesos (uno para cargar, otro para almacenar) es soportado incluso dentro del mismo pase.

Reutilización de recursos

Desde el punto de vista del usuario, una QRhiResource es reutilizable inmediatamente después de llamar a QRhiResource::destroy(). Con la excepción de las swapchains, llamar a create() sobre un objeto ya creado hace un destroy() implícito. Esto proporciona un atajo práctico para reutilizar una instancia de QRhiResource con diferentes parámetros, con un nuevo objeto gráfico nativo debajo.

La importancia de reutilizar el mismo objeto radica en el hecho de que algunos objetos hacen referencia a otros objetos: por ejemplo, un QRhiShaderResourceBindings puede hacer referencia a instancias de QRhiBuffer, QRhiTexture y QRhiSampler. Si en un fotograma posterior es necesario redimensionar uno de estos buffers o cambiar un parámetro del muestreador, destruir y crear un QRhiBuffer o QRhiSampler completamente nuevo invalidaría todas las referencias a la instancia antigua. Con sólo cambiar los parámetros apropiados a través de QRhiBuffer::setSize() o similar y luego llamar a QRhiBuffer::create(), todo funciona como se esperaba y no hay necesidad de tocar el QRhiShaderResourceBindings en absoluto, a pesar de que hay una buena probabilidad de que bajo el capó el QRhiBuffer está ahora respaldado por un nuevo búfer nativo.

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 ofrece el mismo contrato: llamar a QRhiCommandBuffer::beginPass() es seguro incluso cuando una de las texturas asociadas al render target o renderbuffers ha sido reconstruida (llamando a create() sobre ella) desde la creación del objeto render target. Esto permite a la aplicación redimensionar una textura estableciendo un nuevo tamaño de píxel en QRhiTexture y llamando a create(), creando así un nuevo recurso de textura nativo, sin tener que actualizar QRhiTextureRenderTarget ya que se hará implícitamente en beginPass().

Objetos agrupados

Además de los recursos, también existen objetos agrupados, como QRhiResourceUpdateBatch. Una instancia se recupera a través de una función next, como nextResourceUpdateBatch(). En este caso, la instancia devuelta no pertenece a quien la solicita. La única forma válida de operar aquí es llamar a funciones en QRhiResourceUpdateBatch y luego pasarlas a QRhiCommandBuffer::beginPass() o QRhiCommandBuffer::endPass(). Estas funciones se encargan de devolver el lote al pool. Alternativamente, un lote puede ser "cancelado" y devuelto al pool sin procesar llamando a QRhiResourceUpdateBatch::release().

Un patrón típico es el siguiente:

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

Swapchain specifics

QRhiSwapChain presenta una semántica especial debido a la naturaleza peculiar de las swapchains.

  • No tiene create() sino QRhiSwapChain::createOrResize(). Llamar repetidamente a esta función no es lo mismo que llamar a QRhiSwapChain::destroy() seguido de QRhiSwapChain::createOrResize(). Esto se debe a que las swapchains a menudo tienen formas de manejar el caso en que los buffers necesitan ser redimensionados de una manera que es más eficiente que una fuerza bruta destruyendo y recreando desde cero.
  • Un QRhiSwapChain activo debe ser liberado llamando a destroy(), o destruyendo el objeto, antes de que el QWindow's subyacente QPlatformWindow, y por lo tanto el objeto ventana nativo asociado, sea destruido. No debería posponerse porque liberar la swapchain puede volverse problemático (y con algunas APIs, como Vulkan, está explícitamente prohibido) cuando la ventana nativa ya no existe, por ejemplo porque la QPlatformWindow se destruyó al obtener un QWindow::close(). Por lo tanto, la liberación de la swapchain debe ocurrir siempre que el QWindow objetivo envíe el evento QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed. Si el evento no llega antes de la destrucción de QWindow - esto puede ocurrir cuando se usa QCoreApplication::quit() -, entonces compruebe QWindow::handle() después de que el bucle de eventos salga e invoque la liberación del swapchain cuando no sea nulo (lo que significa que la ventana nativa subyacente sigue existiendo).

Propiedad

La regla general es no transferir la propiedad. Crear un QRhi con un dispositivo gráfico ya existente no significa que el QRhi tome posesión del objeto dispositivo. Del mismo modo, la propiedad no se cede cuando un objeto dispositivo o textura se "exporta" a través de QRhi::nativeHandles() o QRhiTexture::nativeTexture(). Y lo que es más importante, pasar punteros en structs y mediante setters no transfiere la propiedad.

Solución de problemas y perfiles

Notificación de errores

Las funciones como QRhi::create() y las funciones miembro de las clases de recursos create() (por ejemplo, QRhiBuffer::create()) indican el fallo con el valor de retorno (nullptr o false, respectivamente). Cuando se trabaja con QShader, QShader::fromSerialized() devuelve un QShader inválido (para el que isValid() devuelve false) cuando los datos pasados a la función no pueden ser deserializados con éxito. Algunas funciones, beginFrame() en particular, también pueden informar a veces de "fallos suaves", como FrameOpSwapChainOutOfDate, que no indican un error irrecuperable, sino que deben considerarse como una respuesta de "inténtelo de nuevo más tarde".

Las advertencias y los errores pueden imprimirse en cualquier momento en la salida de depuración a través de qWarning(). Por lo tanto, siempre es aconsejable inspeccionar la salida de la aplicación.

Se pueden habilitar mensajes de depuración adicionales a través de las siguientes categorías de registro. Los mensajes de estas categorías no se imprimen por defecto a menos que se habiliten explícitamente a través de QLoggingCategory o la variable de entorno QT_LOGGING_RULES. Para una mejor interoperabilidad con Qt Quick, la variable de entorno QSG_INFO también habilita estas impresiones de depuración.

  • qt.rhi.general

Además, las aplicaciones pueden consultar QRhi backend name y graphics device information desde un QRhi inicializado correctamente. Esto puede ser impreso al usuario o almacenado en los logs de la aplicación incluso en versiones de producción, si se desea.

Investigación de problemas de renderizado

Cuando los resultados de renderizado no son los esperados, o la aplicación está experimentando problemas, siempre considere comprobar con la depuración nativa de las APIs 3D y las facilidades de validación. El propio QRhi presenta una comprobación de errores limitada, ya que no es razonable replicar la gran cantidad de funciones ya existentes en las capas subyacentes.

  • En el caso de Vulkan, el control de las capas de validación de Vulkan no entra dentro del ámbito de QRhi, sino que puede conseguirse configurando QVulkanInstance con las capas adecuadas. Por ejemplo, llame a instance.setLayers({ "VK_LAYER_KHRONOS_validation" }); antes de invocar a create() en QVulkanInstance. (tenga en cuenta que esto supone que las capas de validación están realmente instaladas y disponibles, por ejemplo, desde el SDK de Vulkan) Por defecto, QVulkanInstance redirige convenientemente los mensajes de depuración de Vulkan a qDebug, lo que significa que los mensajes de validación se imprimen igual que otras advertencias de Qt.
  • Con Direct 3D 11 y 12, se puede solicitar un dispositivo gráfico con la capa de depuración habilitada activando la bandera enableDebugLayer en el correspondiente init params struct. Los mensajes aparecen en la salida de depuración, que es visible en el panel de mensajes de Qt Creator o a través de una herramienta como DebugView.
  • Para Metal, el control de la validación de Metal está fuera del alcance de QRhi. En su lugar, para habilitar la validación, ejecute la aplicación con la variable de entorno METAL_DEVICE_WRAPPER_TYPE=1 establecida, o ejecute la aplicación dentro de XCode. También puede haber más ajustes y variables de entorno en las versiones modernas de XCode y macOS. Véase, por ejemplo, esta página.

Capturas de fotogramas y perfiles de rendimiento

Una aplicación Qt que renderiza con QRhi en una ventana y que depende de una API 3D bajo el capó, no es, al menos desde la perspectiva de la canalización de gráficos y ventanas, diferente de cualquier otra aplicación (no Qt) que utilice la misma API 3D. Esto significa que las herramientas y prácticas para la depuración y perfilado de aplicaciones con gráficos 3D, como los juegos, se aplican también a este tipo de aplicaciones Qt.

Algunos ejemplos de herramientas que pueden proporcionar información sobre el renderizado interno de las aplicaciones Qt que utilizan QRhi, que incluye Qt Quick y Qt Quick proyectos basados en 3D también:

  • RenderDoc permite tomar capturas de fotogramas e introspeccionar los comandos grabados y el estado del pipeline en Windows y Linux para aplicaciones que utilizan OpenGL, Vulkan, D3D11 o D3D12. Cuando se trata de averiguar por qué algunas partes de la escena 3D no se muestran como se esperaba, RenderDoc es a menudo una forma rápida y eficaz de comprobar las etapas del pipeline y el estado relacionado y descubrir el valor que falta o es incorrecto. También es una herramienta que se utiliza activamente en el desarrollo del propio Qt.
  • Para los sistemas basados en NVIDIA, Nsight Graphics proporciona una herramienta de depuración de gráficos en Windows y Linux. Además de investigar los comandos del fotograma y el pipeline, las herramientas específicas del fabricante permiten ver los tiempos y la información de rendimiento del hardware, algo que no pueden ofrecer las simples capturas de fotogramas.
  • En el caso de los sistemas basados en AMD, se puede utilizar Radeon GPU Profiler para obtener información más detallada sobre el renderizado de la aplicación y su rendimiento.
  • Las superposiciones que muestran información sobre el rendimiento en tiempo real también pueden ser muy útiles, y a menudo son preferibles a la implementación de simples contadores de fotogramas por segundo dentro de la propia aplicación, ya que son más fiables y muestran más información. Un ejemplo es PresentMon, que soporta hardware gráfico de múltiples fabricantes.
  • Como QRhi soporta Direct 3D 12, usar PIX, una herramienta de ajuste de rendimiento y depuración para juegos DirectX 12 en Windows es también una opción.
  • En macOS, el depurador XCode Metal puede utilizarse para tomar e introspeccionar capturas de fotogramas, investigar detalles de rendimiento y depurar sombreadores. En macOS 13 también es posible activar una superposición que muestra la velocidad de fotogramas y otra información para cualquier ventana basada en Metal mediante la configuración de la variable de entorno MTL_HUD_ENABLED=1.

En plataformas móviles e integradas, puede haber herramientas específicas del fabricante y la plataforma, proporcionadas por el fabricante de la GPU o el SoC, disponibles para realizar perfiles de rendimiento de aplicaciones que utilicen OpenGL ES o Vulkan.

Al capturar fotogramas, recuerda que los objetos y grupos de comandos pueden nombrarse mediante marcadores de depuración, siempre que debug markers were enabled para el QRhi, y la API gráfica en uso lo admitan. Para anotar el flujo de comandos, llama a debugMarkBegin(), debugMarkEnd() y/o debugMarkMsg(). Esto puede ser particularmente útil en fotogramas grandes con múltiples pases de renderizado. Los recursos se nombran llamando a setName() antes de create().

Para realizar mediciones básicas de tiempo en la CPU y la GPU dentro de la aplicación, se pueden utilizar QElapsedTimer y QRhiCommandBuffer::lastCompletedGpuTime(). Por el momento, esta última opción sólo está disponible con algunas API gráficas y requiere la opción QRhi::EnableTimestamps.

Comprobación de fuga de recursos

Cuando se destruye un objeto QRhi sin destruir adecuadamente todos los buffers, texturas y otros recursos creados a partir de él, se imprimen advertencias sobre esto en la salida de depuración siempre que la aplicación sea una compilación de depuración, o cuando la variable de entorno QT_RHI_LEAK_CHECK tenga un valor distinto de cero. Esta es una forma sencilla de descubrir problemas de diseño en torno al manejo de recursos dentro de la lógica de renderizado de la aplicación. Tenga en cuenta, sin embargo, que algunas plataformas y APIs gráficas subyacentes pueden realizar su propia asignación y detección de fugas de recursos, sobre las que Qt no tendrá control directo. Por ejemplo, cuando se utiliza Vulkan, el asignador de memoria puede lanzar aserciones de fallo en las compilaciones de depuración cuando los recursos que poseen asignaciones de memoria gráfica no se destruyen antes del QRhi. Además, la capa de validación de Vulkan, cuando está habilitada, emitirá advertencias sobre recursos gráficos nativos que no fueron liberados. De forma similar, con Direct 3D se pueden imprimir advertencias sobre objetos COM no liberados cuando la aplicación no destruye el QRhi y sus recursos en el orden correcto.

Véase también Ejemplo de ventana RHI, QRhiCommandBuffer, QRhiResourceUpdateBatch, QRhiShaderResourceBindings, QShader, QRhiBuffer, QRhiTexture, QRhiRenderBuffer, QRhiSampler, QRhiTextureRenderTarget, QRhiGraphicsPipeline, QRhiComputePipeline, y QRhiSwapChain.

Documentación de tipos de miembros

[alias, since 6.10] QRhi::AdapterList

Sinónimo de QVector<QRhiAdapter *>.

Este typedef se introdujo en Qt 6.10.

enum QRhi::BeginFrameFlag
flags QRhi::BeginFrameFlags

Valores de bandera para QRhi::beginFrame()

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

enum QRhi::EndFrameFlag
flags QRhi::EndFrameFlags

Valores de bandera para QRhi::endFrame()

ConstanteValorDescripción
QRhi::SkipPresent1 << 0Especifica que no se debe poner en cola ningún comando presente o que no se debe hacer ninguna llamada a swapBuffers. De esta forma no se presenta ninguna imagen. No se recomienda generar múltiples fotogramas con esta bandera activada (excepto, por ejemplo, con fines de benchmarking - pero tenga en cuenta que los backends pueden comportarse de forma diferente cuando se trata de esperar a la finalización del comando sin presentar, por lo que los resultados no son comparables entre ellos).

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

enum QRhi::Feature

Valores de bandera para indicar qué características son compatibles con el backend actualmente en uso.

ConstanteValorDescripción
QRhi::MultisampleTexture1Indica que las texturas con un número de muestras superior a 1 están soportadas. En la práctica esta característica no será soportada con versiones de OpenGL ES anteriores a la 3.1, y OpenGL anterior a la 3.0.
QRhi::MultisampleRenderBuffer2Indica que los renderbuffers con un número de muestras superior a 1 son compatibles. En la práctica, esta función no es compatible con OpenGL ES 2.0 y puede que tampoco lo sea con OpenGL 2.x, a menos que se disponga de las extensiones pertinentes.
QRhi::DebugMarkers3Indica que los grupos de marcadores de depuración (y por tanto QRhiCommandBuffer::debugMarkBegin()) están soportados.
QRhi::Timestamps4Indica que se admiten las marcas de tiempo del búfer de comandos. Relevante para QRhiCommandBuffer::lastCompletedGpuTime(). Es de esperar que esto sea compatible con Metal, Vulkan, Direct 3D 11 y 12, y contextos OpenGL de la versión 3.3 o posteriores. Sin embargo, con algunas de estas APIs el soporte para consultas de timestamp es técnicamente opcional, y por lo tanto no se puede garantizar que esta característica sea siempre soportada con cada implementación de las mismas.
QRhi::Instancing5Indica que se admite el dibujo de instancias. En la práctica, esta función no será compatible con OpenGL ES 2.0 y OpenGL 3.2 o anteriores.
QRhi::CustomInstanceStepRate6Indica que se admiten tasas de paso de instancia distintas de 1. En la práctica, esta función siempre será incompatible con OpenGL. Además, si se ejecuta con Vulkan 1.0 sin VK_EXT_vertex_attribute_divisor también se informará de false para esta característica.
QRhi::PrimitiveRestart7Indica que el reinicio del ensamblaje de primitivas cuando se encuentra un valor de índice de 0xFFFF (IndexUInt16) o 0xFFFFFFFF (IndexUInt32) está habilitado, al menos para ciertas topologías de primitivas. QRhi intentará habilitar esto con todos los backends, pero en algunos casos no será soportado. Controlar dinámicamente el reinicio de primitivas no es posible ya que con algunas APIs el reinicio de primitivas con un índice fijo está siempre activado. Las aplicaciones deben asumir que siempre que esta característica sea reportada como soportada, los valores de índice antes mencionados may serán tratados especialmente, dependiendo de la topología. Las únicas dos topologías en las que se garantiza que el reinicio primitivo se comporta de forma idéntica en todos los backends, siempre que esta característica se informe como soportada, son LineStrip y TriangleStrip.
QRhi::NonDynamicUniformBuffers8Indica que se admite la creación de buffers con el uso UniformBuffer y los tipos Immutable o Static. Si se indica que no se admite, los búferes uniformes (constantes) deben crearse como Dynamic(lo que se recomienda en cualquier caso).
QRhi::NonFourAlignedEffectiveIndexBufferOffset9Indica que se admiten los desplazamientos efectivos del búfer de índice (indexOffset + firstIndex * indexComponentSize) que no están alineados a 4 bytes. Cuando no está soportado, intentar emitir un drawIndexed() con un offset efectivo no alineado puede llevar a un comportamiento no especificado. Relevante en particular para Metal, donde esto será reportado como no soportado.
QRhi::NPOTTextureRepeat10Indica que el modo de envoltura Repeat y los modos de filtrado mipmap están soportados para texturas con un tamaño distinto de potencia-de-dos. En la práctica, esto sólo puede ser falso con implementaciones de OpenGL ES 2.0 sin GL_OES_texture_npot.
QRhi::RedOrAlpha8IsRed11Indica que el formato RED_OR_ALPHA8 se asigna a un formato red de 8 bits y un componente. Este es el caso para todos los backends excepto OpenGL cuando se utiliza OpenGL ES o un contexto de perfil no central. En su lugar se utiliza GL_ALPHA, un formato de 8 bits y un componente alpha. Utilizar el formato de textura especial permite tener una única ruta de código para crear texturas, dejando al backend decidir el formato real, mientras que la bandera de característica puede utilizarse para elegir la variante de shader apropiada para muestrear la textura.
QRhi::ElementIndexUint12Indica que se admiten elementos enteros sin signo de 32 bits en el búfer de índice. En la práctica, esto es cierto en todas partes excepto cuando se ejecuta en implementaciones OpenGL ES 2.0 sin la extensión necesaria. Cuando es falso, sólo se admiten elementos sin signo de 16 bits en el búfer de índice.
QRhi::Compute13Indica que se admiten sombreadores de cálculo, carga/almacenamiento de imágenes y búferes de almacenamiento. OpenGL anterior a la versión 4.3 y OpenGL ES anterior a la versión 3.1 no admiten cálculos.
QRhi::WideLines14Indica que las líneas con una anchura distinta de 1 son compatibles. Cuando se informa de que no se admite, se ignora el ancho de línea establecido en el estado del conducto de gráficos. Esto siempre puede ser falso con algunos backends (D3D11, D3D12, Metal). Con Vulkan, el valor depende de la implementación. Con OpenGL, las líneas anchas no se admiten en contextos de perfil de núcleo.
QRhi::VertexShaderPointSize15Indica que se tiene en cuenta el tamaño de los puntos rasterizados establecidos mediante gl_PointSize en el sombreador de vértices. Si se indica que no se admite, no es posible dibujar puntos con un tamaño distinto de 1. Establecer gl_PointSize en el sombreador sigue siendo válido, pero se ignora. (por ejemplo, cuando se genera HLSL, la asignación se elimina silenciosamente del código generado) Ten en cuenta que algunas APIs (Metal, Vulkan) requieren que el tamaño del punto se establezca explícitamente en el shader siempre que se dibujen puntos, incluso cuando el tamaño es 1, ya que no lo hacen automáticamente por defecto a 1.
QRhi::BaseVertex16Indica que drawIndexed() admite el argumento vertexOffset. Cuando se indica como no soportado, el valor vertexOffset en un dibujo indexado es ignorado. En la práctica, esta función no será compatible con versiones de OpenGL y OpenGL ES inferiores a la 3.2, ni con Metal en dispositivos iOS antiguos, incluido el simulador de iOS.
QRhi::BaseInstance17Indica que los comandos de dibujo con instancias admiten el argumento firstInstance. Cuando se indica que no es compatible, el valor firstInstance se ignora y el ID de instancia comienza en 0. En la práctica, esta función no será compatible con Metal en dispositivos iOS antiguos, incluido el simulador de iOS, y con todas las versiones de OpenGL. Esto último se debe a que OpenGL ES no admite llamadas de dibujo con una instancia base. Actualmente QRhi's OpenGL backend no implementa la funcionalidad para OpenGL (no ES) tampoco, porque las aplicaciones portables no pueden confiar en una instancia base distinta de cero en la práctica debido a GLES. Si la aplicación todavía decide hacerlo, debe ser consciente de la función InstanceIndexIncludesBaseInstance también.
QRhi::TriangleFanTopology18Indica que QRhiGraphicsPipeline::setTopology() es compatible con QRhiGraphicsPipeline::TriangleFan. En la práctica, esta función no será compatible con Metal y Direct 3D 11/12.
QRhi::ReadBackNonUniformBuffer19Indica que reading buffer contents es compatible con las instancias de QRhiBuffer con un uso distinto de UniformBuffer. En la práctica, esta función no es compatible con OpenGL ES 2.0.
QRhi::ReadBackNonBaseMipLevel20Indica que se admite la especificación de un nivel mip distinto de 0 al volver a leer el contenido de la textura. Cuando no está soportado, especificar un nivel distinto de cero en QRhiReadbackDescription lleva a devolver una imagen completamente a cero. En la práctica, esta función no será compatible con OpenGL ES 2.0.
QRhi::TexelFetch21Indica que texelFetch() y textureLod() están disponibles en los sombreadores. En la práctica esto será reportado como no soportado con OpenGL ES 2.0 y OpenGL 2.x contextos, porque GLSL 100 es y versiones antes de 130 no soportan estas funciones.
QRhi::RenderToNonBaseMipLevel22Indica que se admite la especificación de un nivel mip distinto de 0 al crear un QRhiTextureRenderTarget con un QRhiTexture como adjunto de color. Si no se admite, create() fallará siempre que el nivel mip de destino no sea cero. En la práctica, esta función no será compatible con OpenGL ES 2.0.
QRhi::IntAttributes23Indica que se admite la especificación de atributos de entrada con tipos enteros con y sin signo para un canal de sombreado. Cuando no está soportado, build() tendrá éxito pero sólo mostrará un mensaje de advertencia y los valores de los atributos de destino estarán rotos. En la práctica, esta función no será compatible con OpenGL ES 2.0 y OpenGL 2.x.
QRhi::ScreenSpaceDerivatives24Indica que funciones como dFdx(), dFdy() y fwidth() son compatibles con los sombreadores. En la práctica, esta función no estará soportada con OpenGL ES 2.0 sin la extensión GL_OES_standard_derivatives.
QRhi::ReadBackAnyTextureFormat25Indica que se puede esperar que la lectura del contenido de la textura funcione para cualquier QRhiTexture::Format. Se puede esperar que los backends distintos de OpenGL devuelvan true para esta función. Cuando se informa como false, lo que ocurrirá típicamente con OpenGL, sólo se garantiza que los formatos QRhiTexture::RGBA8 y QRhiTexture::BGRA8 sean compatibles con las devoluciones de lectura. Además, con OpenGL, pero no con OpenGL ES, también se admiten los formatos de 1 byte por componente QRhiTexture::R8 y QRhiTexture::RED_OR_ALPHA8. La lectura de los formatos de coma flotante QRhiTexture::RGBA16F y RGBA32F puede funcionar también con OpenGL, siempre que la implementación ofrezca soporte para ellos, pero QRhi no puede dar garantías, como indica esta bandera.
QRhi::PipelineCacheDataLoadSave26Indica que las funciones pipelineCacheData() y setPipelineCacheData() son funcionales. Cuando no son compatibles, las funciones no realizan ninguna acción, el blob recuperado está siempre vacío y, por lo tanto, no se puede esperar ningún beneficio de la recuperación y, durante una ejecución posterior de la aplicación, de la recarga del contenido de la caché de canalización.
QRhi::ImageDataStride27Indica que se admite la especificación de un stride personalizado (longitud de fila) para los datos de imagen sin procesar en las cargas de texturas. Cuando no está soportado (lo que puede ocurrir cuando la API subyacente es OpenGL ES 2.0 sin soporte para GL_UNPACK_ROW_LENGTH), QRhiTextureSubresourceUploadDescription::setDataStride() no debe ser utilizado.
QRhi::RenderBufferImport28Indica que QRhiRenderBuffer::createFrom() es compatible. Para la mayoría de las APIs gráficas esto no es sensato porque QRhiRenderBuffer encapsula objetos de textura internamente, al igual que QRhiTexture. Con OpenGL, sin embargo, el objeto renderbuffer existe como un tipo de objeto separado en la API, y en ciertos entornos (por ejemplo, donde uno puede querer asociar un objeto renderbuffer con un objeto EGLImage) es importante permitir envolver un objeto renderbuffer OpenGL existente con un QRhiRenderBuffer.
QRhi::ThreeDimensionalTextures29Indica que las texturas 3D están soportadas. En la práctica, esta característica no será compatible con versiones de OpenGL y OpenGL ES inferiores a la 3.0.
QRhi::RenderTo3DTextureSlice30Indica que se admite el renderizado en un corte de una textura 3D. Esto puede no estar soportado con Vulkan 1.0 debido a que depende de VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT que es una característica de Vulkan 1.1.
QRhi::TextureArrays31Indica que las matrices de texturas están soportadas y QRhi::newTextureArray() es funcional. Ten en cuenta que incluso cuando las matrices de texturas no están soportadas, las matrices de texturas siguen estando disponibles ya que son dos características independientes.
QRhi::Tessellation32Indica que las etapas de control y evaluación de la teselación son compatibles. Cuando se indica que se admite, la topología de un QRhiGraphicsPipeline puede establecerse en Patches, el número de puntos de control puede establecerse mediante setPatchControlPointCount(), y los sombreadores para el control y la evaluación de la teselación pueden especificarse en la lista QRhiShaderStage. Los shaders de teselación tienen problemas de portabilidad entre APIs (por ejemplo, traducir GLSL/SPIR-V a HLSL es problemático debido a la forma en que están estructurados los shaders de casco, mientras que Metal utiliza un pipeline de teselación algo diferente a los demás), por lo que aún pueden surgir problemas inesperados, aunque la funcionalidad básica esté implementada en todas las APIs subyacentes. En el caso concreto de Direct 3D, los sombreadores de casco y dominio HLSL escritos a mano deben inyectarse en cada QShader para las etapas de control y evaluación del teselado, respectivamente, ya que qsb no puede generarlos a partir de SPIR-V. Tenga en cuenta que la teselación isoline debe evitarse, ya que no será compatible con todos los backends. El número máximo de puntos de control de parcheo que se puede portar entre backends es 32.
QRhi::GeometryShader33Indica que la etapa de sombreado de geometría es compatible. Cuando es compatible, se puede especificar un sombreador de geometría en la lista QRhiShaderStage. Los sombreadores de geometría se consideran una característica experimental en QRhi y sólo se puede esperar que sean compatibles con Vulkan, Direct 3D 11 y 12, OpenGL (3.2+) y OpenGL ES (3.2+), suponiendo que la implementación lo informe como compatible en tiempo de ejecución. A partir de Qt 6.11 los sombreadores de geometría se traducen automáticamente a HLSL, y por lo tanto ya no es necesario inyectar sombreadores de geometría HLSL escritos a mano (pero ten en cuenta que gl_in y expresiones como gl_in[0].gl_Position no están soportadas; en su lugar, pasa la posición como una variable de salida del sombreador de vértices). Los sombreadores de geometría no son compatibles con Metal.
QRhi::TextureArrayRange34Indica que para texture arrays es posible especificar un rango que se expone a los shaders. Normalmente todas las capas del array están expuestas y depende del shader seleccionar la capa (a través de la tercera coordenada pasada a texture() al muestrear la sampler2DArray). Cuando se soporta, llamar a QRhiTexture::setArrayRangeStart() y QRhiTexture::setArrayRangeLength() antes de building o importing la textura nativa tiene un efecto, y lleva a seleccionar sólo el rango especificado del array. Esto será necesario en casos especiales, como cuando se trabaja con decodificación de vídeo acelerada y Direct 3D 11, porque un array de texturas con D3D11_BIND_DECODER y D3D11_BIND_SHADER_RESOURCE en él sólo es utilizable como recurso de shader si se selecciona una única capa del array. Ten en cuenta que todo esto sólo es aplicable cuando la textura se utiliza como recurso de sombreado QRhiShaderResourceBinding::SampledTexture o QRhiShaderResourceBinding::Texture, y no es compatible con la carga/almacenamiento de imágenes. Esta característica sólo está disponible con algunos backends, ya que no se adapta bien a todas las APIs gráficas, y de todos modos sólo está pensada para dar soporte a casos especiales. En la práctica, es de esperar que esta función sea compatible con Direct3D 11/12 y Vulkan.
QRhi::NonFillPolygonMode35Indica que la configuración de un PolygonMode distinto del predeterminado Fill es compatible con QRhiGraphicsPipeline. Un caso de uso común para cambiar el modo a Line es obtener un renderizado wireframe. Sin embargo, esto no está disponible como una característica principal de OpenGL ES, y es opcional con Vulkan, así como algunas GPUs móviles pueden no ofrecer la función.
QRhi::OneDimensionalTextures36Indica que las texturas 1D están soportadas. En la práctica, esta función no está disponible en OpenGL ES.
QRhi::OneDimensionalTextureMipmaps37Indica que se pueden generar mipmaps de texturas 1D. En la práctica, esta función no será compatible con los backends que no admitan OneDimensionalTextures, Metal y Direct 3D 12.
QRhi::HalfAttributes38Indica que se admite la especificación de atributos de entrada con tipos de coma flotante de media precisión (16 bits) para un canal de sombreado. Cuando no está soportado, build() tendrá éxito pero sólo mostrará un mensaje de advertencia y los valores de los atributos de destino estarán rotos. En la práctica esta característica no será soportada en algunas implementaciones de OpenGL ES 2.0 y OpenGL 2.x. Tenga en cuenta que, aunque Direct3D 11/12 admite atributos de entrada de media precisión, no admite el tipo half3. Los backends D3D pasan los atributos half3 como half4. Para garantizar la compatibilidad entre plataformas, las entradas half3 deben rellenarse con 8 bytes.
QRhi::RenderToOneDimensionalTexture39Indica que se admiten objetivos de renderizado de textura 1D. En la práctica, esta función no será compatible con los backends que no informen de la compatibilidad con OneDimensionalTextures y Metal.
QRhi::ThreeDimensionalTextureMipmaps40Indica que es posible generar mipmaps de texturas 3D. Esto es típicamente soportado con todos los backends comenzando con Qt 6.10.
QRhi::MultiView41Indica que se admite la vista múltiple, véase, por ejemplo, VK_KHR_multiview. Con OpenGL ES 2.0, Direct 3D 11, y OpenGL (ES) implementaciones sin GL_OVR_multiview2 esta característica no será soportada. Con Vulkan 1.1 y posteriores, y Direct 3D 12, normalmente se admite multiview. Cuando se informa de que es compatible, la creación de un QRhiTextureRenderTarget con un QRhiColorAttachment que haga referencia a una matriz de texturas y tenga multiViewCount establecido permite grabar un pase de renderizado que utilice el renderizado multivista. Además, cualquier QRhiGraphicsPipeline utilizado en ese pase de render debe tener the same view count set. Ten en cuenta que la vista múltiple sólo está disponible en combinación con matrices de texturas 2D. No puede utilizarse para optimizar el renderizado en texturas individuales (por ejemplo, dos, para los ojos izquierdo y derecho). Más bien, el objetivo de un pase de renderizado multivista es siempre un array de texturas, renderizando automáticamente a la capa (elemento del array) correspondiente a cada vista. Por lo tanto, esta característica implica también TextureArrays. El renderizado multivista no es compatible con la teselación o los sombreadores geométricos. Véase QRhiColorAttachment::setMultiViewCount() para más detalles sobre el renderizado multivista. Este valor enum ha sido introducido en Qt 6.7.
QRhi::TextureViewFormat42Indica que la configuración de view format en QRhiTexture es efectiva. Cuando se informa como soportado, establecer el modo de vista de lectura (muestreo) o escritura (objetivo de renderizado/almacén de carga de imágenes) cambia el formato de visualización de la textura. Cuando no está soportado, establecer un formato de vista no tiene efecto. Tenga en cuenta que Qt no tiene conocimiento o control sobre la compatibilidad de formatos o reglas de vista de recursos en la API 3D subyacente y su implementación. Pasar formatos inadecuados o incompatibles puede provocar errores y comportamientos no especificados. Esto se proporciona principalmente para permitir el "casting" de renderizado en una textura creada con un formato sRGB a no-RGB para evitar la no deseada conversión lineal->sRGB en las escrituras del shader. Otros tipos de casting pueden o no ser funcionales, dependiendo de la API subyacente. Actualmente implementado para Vulkan y Direct 3D 12. Con D3D12 la función sólo está disponible si CastingFullyTypedFormatSupported está soportado, ver https://microsoft.github.io/DirectX-Specs/d3d/RelaxedCasting.html (y tenga en cuenta que QRhi siempre utiliza formatos completamente tipados para texturas.) Este valor enum ha sido introducido en Qt 6.8.
QRhi::ResolveDepthStencil43Indica que la resolución de una profundidad multimuestra o textura depth-stencil está soportada. En caso contrario, setting a depth resolve texture no es funcional y debe evitarse. Direct 3D 11 y 12 no son compatibles con la resolución de formatos de profundidad/profundidad-esténcil, por lo que esta función nunca será compatible con ellos. Vulkan 1.0 no dispone de una API para solicitar la resolución de un archivo adjunto depth-stencil. Por lo tanto, con Vulkan esta característica sólo será compatible con Vulkan 1.2 y superiores, y en implementaciones 1.1 con las extensiones apropiadas presentes. Esta característica se proporciona para el raro caso de que sea necesario resolver en una textura de profundidad no multimuestra, por ejemplo cuando se renderiza en una textura de profundidad proporcionada por OpenXR (XR_KHR_composition_layer_depth). Este valor enum se ha introducido en Qt 6.8.
QRhi::VariableRateShading44Indica que está soportado el sombreado de tasa variable por dibujo (por tubería). Cuando se reporta como soportado, QRhiCommandBuffer::setShadingRate() es funcional y tiene efecto para los objetos QRhiGraphicsPipeline que declararon QRhiGraphicsPipeline::UsesShadingRate en sus flags. Llame a QRhi::supportedShadingRates() para comprobar qué tasas son compatibles. (1x1 siempre está soportado, otros valores típicos son 2x2, 1x2, 2x1, 2x4, 4x2, 4x4). Es de esperar que esta característica sea soportada con Direct 3D 12 y Vulkan, asumiendo que la implementación y la GPU utilizada en tiempo de ejecución soporten VRS. Este valor enum se ha introducido en Qt 6.9.
QRhi::VariableRateShadingMap45Indica que es posible la especificación de la tasa de sombreado basada en imágenes. La "imagen" no es necesariamente una textura, puede ser un objeto nativo de la API 3D, dependiendo del backend subyacente y de la API gráfica en tiempo de ejecución. En la práctica, se puede esperar que esta característica sea compatible con Direct 3D 12, Vulkan y Metal, suponiendo que la GPU sea lo suficientemente moderna como para soportar VRS. Para comprobar si el VRS basado en imágenes al estilo de D3D12/Vulkan está soportado, utiliza VariableRateShadingMapWithTexture en su lugar. Cuando esta característica es reportada como soportada, hay dos posibilidades: cuando VariableRateShadingMapWithTexture es también true, entonces QRhiShadingRateMap consume objetos QRhiTexture a través de la sobrecarga createFrom() tomando un argumento QRhiTexture. Cuando VariableRateShadingMapWithTexture es falso, entonces QRhiShadingRateMap consume algún otro tipo de objeto nativo, por ejemplo un MTLRasterizationRateMap en el caso de Metal. Utiliza la sobrecarga createFrom() tomando un NativeShadingRateMap en este caso. Este valor enum se ha introducido en Qt 6.9.
QRhi::VariableRateShadingMapWithTexture46Indica que la especificación de la tasa de sombreado basada en imágenes está soportada mediante texturas normales. En la práctica esto puede ser soportado con Direct 3D 12 y Vulkan. Este valor enum ha sido introducido en Qt 6.9.
QRhi::PerRenderTargetBlending47Indica que la mezcla por objetivo de render está soportada, es decir, diferentes objetivos de render en el framebuffer MRT pueden tener diferentes modos de mezcla. En la práctica, es de esperar que esto esté soportado en todas partes excepto en OpenGL ES, donde sólo está disponible con implementaciones GLES 3.2. Este valor enum se ha introducido en Qt 6.9.
QRhi::SampleVariables48Indica que las variables gl_SampleID, gl_SamplePosition, gl_SampleMaskIn y gl_SampleMask están disponibles en los fragment shaders. En la práctica, es de esperar que esto esté soportado en todas partes excepto en OpenGL ES, donde sólo está disponible con implementaciones GLES 3.2. Este valor enum se ha introducido en Qt 6.9.
QRhi::InstanceIndexIncludesBaseInstance49Indica que gl_InstanceIndex incluye la instancia base (el argumento firstInstance en las llamadas a dibujo) en su valor. Cuando esta característica no está soportada, pero BaseInstance sí, indica que gl_InstanceIndex siempre empieza en 0, no en el valor base. En la práctica, este será el caso para Direct 3D 11 y 12 por el momento. Con Vulkan y Metal se espera que esta característica sea reportada como soportada siempre. Este valor enum se ha introducido en Qt 6.11.
QRhi::DepthClamp50Indica que la activación de la sujeción de profundidad está soportada. Cuando se informa de que no está soportada, que será el caso de OpenGL ES, versiones de OpenGL anteriores a 3.2 sin la extensión pertinente presente, y Metal en el simulador de iOS, llamar a setDepthClamp() con un argumento de true no tiene ningún efecto. Este valor enum ha sido introducido en Qt 6.11.

enum QRhi::Flag
flags QRhi::Flags

Describe qué características especiales habilitar.

ConstanteValorDescripción
QRhi::EnableDebugMarkers1 << 0Habilita los grupos de marcadores de depuración. Sin este marco las características de depuración como hacer visibles los grupos de depuración y el nombre de recurso personalizado en herramientas de depuración GPU externas no estarán disponibles y funciones como QRhiCommandBuffer::debugMarkBegin() se convertirán en no-ops. Evita habilitarlo en compilaciones de producción ya que puede suponer un pequeño impacto en el rendimiento. No tiene ningún efecto cuando la función QRhi::DebugMarkers no está soportada.
QRhi::EnableTimestamps1 << 3Activa la recogida de marcas de tiempo en la GPU. Si no está activada, QRhiCommandBuffer::lastCompletedGpuTime() siempre devuelve 0. Actívela sólo cuando sea necesario, ya que puede suponer una pequeña cantidad de trabajo adicional (por ejemplo, consultas de marcas de tiempo), dependiendo de la API gráfica subyacente. No tiene efecto cuando la función QRhi::Timestamps no está soportada.
QRhi::PreferSoftwareRenderer1 << 1Indica que los backends deberían preferir elegir un adaptador o dispositivo físico que renderice por software en la CPU. Por ejemplo, con Direct3D suele haber un adaptador "Basic Render Driver" disponible con DXGI_ADAPTER_FLAG_SOFTWARE. Si se activa esta opción, el backend elegirá ese adaptador en lugar de cualquier otro, siempre que no se haya forzado ningún adaptador específico por otros medios específicos del backend. Con Vulkan, esto equivale a preferir dispositivos físicos con VK_PHYSICAL_DEVICE_TYPE_CPU. Cuando no está disponible, o cuando no es posible decidir si un adaptador/dispositivo está basado en software, esta bandera se ignora. También puede ser ignorada con APIs gráficas que no tengan el concepto y los medios de enumerar adaptadores/dispositivos.
QRhi::EnablePipelineCacheDataSave1 << 2Permite recuperar el contenido de la caché de canalización, si procede. Si no se define, pipelineCacheData() devolverá siempre un blob vacío. Con backends donde la recuperación y restauración de los contenidos de la caché del pipeline no es soportada, la bandera no tiene efecto y los datos serializados de la caché están siempre vacíos. El indicador proporciona un mecanismo de opción porque el coste de mantener las estructuras de datos relacionadas no es insignificante con algunos backends. Con Vulkan esta característica se asigna directamente a VkPipelineCache, vkGetPipelineCacheData y VkPipelineCacheCreateInfo::pInitialData. Con Direct3D 11 no hay caché pipline real, pero los resultados de las compilaciones HLSL->DXBC se almacenan y pueden ser serializados/deserializados a través de este mecanismo. Esto permite saltarse la lenta D3DCompile() en futuras ejecuciones de las aplicaciones para shaders que vienen con fuente HLSL en lugar de bytecode precompilado offline. Esto puede proporcionar un gran impulso en los tiempos de arranque y carga, si hay una gran cantidad de compilación de código fuente HLSL sucediendo. Con OpenGL, la "caché de canalización" se simula recuperando y cargando los binarios del programa de sombreado (si el controlador lo admite). Con OpenGL hay mecanismos adicionales de caché basados en disco para binarios de shaders/programas proporcionados por Qt. Escribir en ellos puede quedar deshabilitado cuando este indicador está activado, ya que almacenar binarios de programa en múltiples cachés no es sensato.
QRhi::SuppressSmokeTestWarnings1 << 4Indica que, con backends donde esto es relevante, ciertos fallos no fatales de QRhi::create() no deberían producir llamadas a qWarning(). Por ejemplo, con D3D11, pasar esta bandera hace que una serie de mensajes de advertencia (que aparecen debido a QRhi::create() fallando) se conviertan en impresiones de depuración categorizadas en su lugar bajo la categoría de registro qt.rhi.general comúnmente utilizada. Esto puede ser utilizado por los motores, como Qt Quick, que cuentan con la lógica de fallback, es decir, que vuelva a intentar llamar a create() con un conjunto diferente de banderas (por ejemplo, PreferSoftwareRenderer), con el fin de ocultar las advertencias incondicionales de la salida que se imprimiría cuando el primer create() intento había fracasado.

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

enum QRhi::FrameOpResult

Describe el resultado de las operaciones que pueden tener un fallo suave.

ConstanteValorDescripción
QRhi::FrameOpSuccess0Éxito
QRhi::FrameOpError1Error no especificado
QRhi::FrameOpSwapChainOutOfDate2La swapchain está en un estado inconsistente internamente. Esto puede ser recuperable intentando repetir la operación (como, beginFrame()) más tarde.
QRhi::FrameOpDeviceLost3Se ha perdido el dispositivo gráfico. Esto puede recuperarse intentando repetir la operación (como, beginFrame()) después de liberar y reinicializar todos los objetos respaldados por recursos gráficos nativos. Véase isDeviceLost().

enum QRhi::Implementation

Describe qué backend específico de la API de gráficos utiliza una instancia de QRhi.

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

enum QRhi::ResourceLimit

Describe el límite de recursos a consultar.

ConstanteValorDescripción
QRhi::TextureSizeMin1Ancho y alto mínimo de la textura. Esto es típicamente 1. El tamaño mínimo de la textura se maneja con gracia, lo que significa que intentar crear una textura con un tamaño vacío creará en su lugar una textura con el tamaño mínimo.
QRhi::TextureSizeMax2Anchura y altura máximas de la textura. Depende de la API gráfica y, a veces, también de la plataforma o la implementación. Normalmente, el valor está entre 4096 y 16384. Se espera que los intentos de crear texturas mayores que este valor fallen.
QRhi::MaxColorAttachments3El número máximo de anexos de color para un QRhiTextureRenderTarget, en caso de que se soporten múltiples objetivos de renderizado. Cuando MRT no está soportado, el valor es 1. De lo contrario, este es típicamente 8, pero ten cuidado con el hecho de que OpenGL sólo ordena 4 como mínimo, y eso es lo que algunas implementaciones de OpenGL ES proporcionan.
QRhi::FramesInFlight4El número de fotogramas que el backend puede mantener "en vuelo": con backends como Vulkan o Metal, es responsabilidad de QRhi bloquearse siempre que se inicie un nuevo fotograma y se encuentre con que la CPU ya está N - 1 fotogramas por delante de la GPU (porque el buffer de comandos enviado en el fotograma nº current - N aún no se ha completado). El valor N es lo que se devuelve desde aquí, y es típicamente 2. Esto puede ser relevante para aplicaciones que integran renderizado hecho directamente con la API gráfica, ya que dicho código de renderizado puede querer realizar doble (si el valor es 2) buffering para recursos, tales como, buffers, de forma similar a los propios backends de QRhi. El índice de la ranura del fotograma actual (un valor que va de 0, 1, .., N-1, y luego se va envolviendo) se puede recuperar desde QRhi::currentFrameSlot(). El valor es 1 para los backends en los que la API gráfica no ofrece un control de bajo nivel sobre el proceso de envío de comandos. Tenga en cuenta que el pipelining puede seguir ocurriendo incluso cuando este valor es 1 (algunos backends, como D3D11, están diseñados para intentar permitir esto, por ejemplo, mediante el uso de una estrategia de actualización para buffers uniformes que no detiene el pipeline), pero eso no está controlado por QRhi y por lo tanto no se refleja aquí en la API.
QRhi::MaxAsyncReadbackFrames5El número de fotogramas de submitted (incluido el que contiene la lectura) tras los cuales se garantiza que se completa una lectura asíncrona de textura o búfer en starting a new frame.
QRhi::MaxThreadGroupsPerDimension6El número máximo de grupos de trabajo/hilos de computación que pueden ser despachados. Efectivamente el valor máximo para los argumentos de QRhiCommandBuffer::dispatch(). Normalmente 65535.
QRhi::MaxThreadsPerThreadGroup7El número máximo de invocaciones en un único grupo de trabajo local, o en otra terminología, el número máximo de hilos en un grupo de hilos. Efectivamente, el valor máximo para el producto de local_size_x, local_size_y, y local_size_z en el sombreador de cálculo. Los valores típicos son 128, 256, 512, 1024 o 1536. Ten en cuenta que tanto OpenGL ES como Vulkan especifican sólo 128 como límite mínimo requerido para las implementaciones. Aunque no es habitual en Vulkan, algunas implementaciones de OpenGL ES 3.1 para dispositivos móviles o integrados sólo admiten el valor mínimo exigido por las especificaciones.
QRhi::MaxThreadGroupX8El tamaño máximo de un grupo de trabajo/hilo en la dimensión X. Efectivamente, el valor máximo de local_size_x en el sombreador de cálculo. Normalmente 256 o 1024.
QRhi::MaxThreadGroupY9El tamaño máximo de un grupo de trabajo/hilo en la dimensión Y. Efectivamente, el valor máximo de local_size_y en el sombreador de cálculo. Normalmente 256 o 1024.
QRhi::MaxThreadGroupZ10El tamaño máximo de un grupo de trabajo/hilo en la dimensión Z. Efectivamente, el valor máximo de local_size_z en el sombreador de cálculo. Normalmente 64 o 256.
QRhi::TextureArraySizeMax11Tamaño máximo de la matriz de texturas. Típicamente en el rango 256 - 2048. Intentar create a texture array con más elementos probablemente fallará.
QRhi::MaxUniformBufferRange12El número de bytes que pueden ser expuestos desde un buffer uniforme a los shaders a la vez. En implementaciones OpenGL ES 2.0 y 3.0 este valor puede ser tan bajo como 3584 bytes (224 vectores de cuatro componentes, 32 bits por componente). En otros casos, el valor suele ser 16384 (1024 vec4s) o 65536 (4096 vec4s).
QRhi::MaxVertexInputs13El número de atributos de entrada al sombreador de vértices. La ubicación en un QRhiVertexInputAttribute debe estar en el rango [0, MaxVertexInputs-1]. El valor puede ser tan bajo como 8 con OpenGL ES 2.0. En otros casos, los valores típicos son 16, 31 o 32.
QRhi::MaxVertexOutputs14El número máximo de salidas (variables de vector de 4 componentes out ) del sombreador de vértices. El valor puede ser tan bajo como 8 con OpenGL ES 2.0, y 15 con OpenGL ES 3.0 y algunos dispositivos Metal. En otros casos, el valor típico es 32.
QRhi::ShadingRateImageTileSize15El tamaño de mosaico para texturas de tasa de sombreado. 0 si no se admite la función QRhi::VariableRateShadingMapWithTexture. En caso contrario, un valor como 16, que indica, por ejemplo, un tamaño de mosaico de 16x16. Cada byte en la textura de tasa de sombreado (R8UI) define entonces la tasa de sombreado para un tile de 16x16 pixels. Ver QRhiShadingRateMap para más detalles.

Documentación de la Función Miembro

[noexcept] QRhi::~QRhi()

Destructor. Destruye el backend y libera recursos.

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

Registra un callback que se invoca cuando se destruye el QRhi.

La llamada de retorno se ejecutará con el recurso gráfico aún disponible, por lo que esto proporciona una oportunidad para que la aplicación libere limpiamente las instancias de QRhiResource pertenecientes a QRhi. Esto es particularmente útil para gestionar el tiempo de vida de los recursos almacenados en objetos de tipo cache, donde la caché contiene QRhiResources u objetos que contienen QRhiResources.

Véase también ~QRhi().

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

Registra callback para ser invocado cuando se destruya QRhi. Esta sobrecarga toma un puntero opaco, key, que se utiliza para asegurar que una llamada de retorno dada se registra (y así se llama) sólo una vez.

Se trata de una función sobrecargada.

Véase también removeCleanupCallback().

QRhi::Implementation QRhi::backend() const

Devuelve el tipo de backend para este QRhi.

const char *QRhi::backendName() const

Devuelve el tipo de backend como cadena para este QRhi.

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

Devuelve un nombre amigable para el backend impl, normalmente el nombre de la API 3D en uso.

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

Inicia un nuevo fotograma en el siguiente búfer disponible de swapChain.

Un fotograma se compone de actualizaciones de recursos y uno o más pases de renderizado y cálculo.

flags puede indicar ciertos casos especiales.

El patrón de alto nivel de renderizado en un QWindow utilizando una swapchain:

  • Crear una swapchain.
  • Llamar a QRhiSwapChain::createOrResize() siempre que el tamaño de la superficie sea diferente al anterior.
  • Llama a QRhiSwapChain::destroy() en QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed.
  • Luego en cada frame:
    beginFrame(sc);
    updates = nextResourceUpdateBatch();
    updates->...
    QRhiCommandBuffer *cb = sc->currentFrameCommandBuffer();
    cb->beginPass(sc->currentFrameRenderTarget(), colorClear, dsClear, updates);
    ...
    cb->endPass();
    ... // more passes as necessary
    endFrame(sc);

Devuelve QRhi::FrameOpSuccess en caso de éxito, u otro valor QRhi::FrameOpResult en caso de fallo. Algunos de estos deben ser tratados como errores suaves, del tipo "inténtelo de nuevo más tarde": Cuando se devuelve QRhi::FrameOpSwapChainOutOfDate, la swapchain debe ser redimensionada o actualizada llamando a QRhiSwapChain::createOrResize(). La aplicación debería entonces intentar generar un nuevo frame. QRhi::FrameOpDeviceLost significa que el dispositivo gráfico se pierde pero esto también puede ser recuperable liberando todos los recursos, incluyendo el propio QRhi, y luego recreando todos los recursos. Véase isDeviceLost() para más información.

Véase también endFrame(), beginOffscreenFrame(), y isDeviceLost().

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

Inicia un nuevo fotograma fuera de pantalla. Proporciona un búfer de comandos adecuado para grabar comandos de renderizado en cb. flags se utiliza para indicar ciertos casos especiales, al igual que con beginFrame().

Nota: El QRhiCommandBuffer almacenado en *cb no es propiedad de quien lo llama.

También es posible renderizar sin swapchain. El caso de uso típico es usarlo en aplicaciones completamente fuera de pantalla, por ejemplo, para generar secuencias de imágenes renderizando y volviendo a leer sin mostrar nunca una ventana.

El uso en aplicaciones en pantalla ( beginFrame, endFrame, beginOffscreenFrame, endOffscreenFrame, beginFrame, ...) también es posible, pero reduce el paralelismo, por lo que sólo debería hacerse con poca frecuencia.

Los fotogramas fuera de pantalla no permiten a la CPU generar potencialmente otro fotograma mientras la GPU sigue procesando el anterior. Esto tiene el efecto secundario de que si se programan lecturas posteriores, se garantiza que los resultados estarán disponibles una vez que vuelva endOffscreenFrame(). Este no es el caso de los fotogramas dirigidos a una swapchain: ahí la GPU está potencialmente mejor utilizada, pero trabajar con operaciones de readback requiere más cuidado por parte de la aplicación porque endFrame(), a diferencia de endOffscreenFrame(), no garantiza que los resultados del readback estén disponibles en ese momento.

El esqueleto de renderizar un cuadro sin una cadena de intercambio y luego volver a leer el contenido del cuadro podría parecerse a lo siguiente:

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

Véase también endOffscreenFrame() y beginFrame().

QMatrix4x4 QRhi::clipSpaceCorrMatrix() const

Devuelve una matriz que se puede utilizar para permitir que las aplicaciones sigan utilizando datos de vértices orientados a OpenGL y matrices de proyección de perspectiva (como, por ejemplo, las generadas por QMatrix4x4::perspective()), independientemente del backend QRhi activo.

En un renderizador típico, una vez que se utiliza this_matrix * mvp en lugar de sólo mvp, los datos de vértices con Y hacia arriba y los viewports con rango de profundidad 0 - 1 pueden utilizarse sin tener en cuenta qué backend (y por tanto API gráfica) se va a utilizar en tiempo de ejecución. De esta forma se pueden evitar las bifurcaciones basadas en isYUpInNDC() y isClipDepthZeroToOne() (aunque dicha lógica puede seguir siendo necesaria al implementar ciertas técnicas gráficas avanzadas).

Véase esta página para una discusión del tema desde la perspectiva de Vulkan.

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

Devuelve una nueva instancia de QRhi con un backend para la API de gráficos especificada por impl con el flags especificado. Devuelve nullptr si la función falla.

params debe apuntar a una instancia de una de las subclases específicas de backend de QRhiInitParams, como, QRhiVulkanInitParams, QRhiMetalInitParams, QRhiD3D11InitParams, QRhiD3D12InitParams, QRhiGles2InitParams. Consulte estas clases para ver ejemplos de creación de un QRhi.

QRhi by design no implementa ninguna lógica fallback: si la API especificada no puede ser inicializada, create() fallará, con advertencias impresas en la salida debug por los backends. Los clientes de QRhi, por ejemplo Qt Quick, pueden sin embargo proporcionar una lógica adicional que permita volver a una API diferente de la solicitada, dependiendo de la plataforma. Si la intención es sólo probar si la inicialización tendría éxito al llamar a create() en un momento posterior, es preferible utilizar probe() en lugar de create(), porque con algunos backends el sondeo puede ser implementado de una manera más ligera en oposición a create(), que realiza la inicialización completa de la infraestructura y es un desperdicio si esa instancia QRhi es luego desechada inmediatamente.

importDevice permite utilizar un dispositivo gráfico ya existente, sin que QRhi cree uno propio. Cuando no es nulo, este parámetro debe apuntar a una instancia de una de las subclases de QRhiNativeHandles: QRhiVulkanNativeHandles, QRhiD3D11NativeHandles, QRhiD3D12NativeHandles, QRhiMetalNativeHandles, QRhiGles2NativeHandles. Los detalles exactos y la semántica dependen del backand y de la API gráfica subyacente.

Especificar un QRhiAdapter en adapter ofrece una alternativa transparente y multiAPI a pasar un VkPhysicalDevice a través de QRhiVulkanNativeHandles, o un LUID de adaptador a través de QRhiD3D12NativeHandles. No se toma la propiedad de adapter. Véase enumerateAdapters() para más información sobre este enfoque.

Nota: importDevice y adapter no pueden ser ambos especificados.

Véase también probe().

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

Equivale a create(impl, params, flags, importDevice, nullptr).

Se trata de una función sobrecargada.

int QRhi::currentFrameSlot() const

Devuelve el índice de la ranura de fotograma actual mientras se graba un fotograma. No se especifica cuando se llama fuera de un fotograma activo (es decir, cuando isRecordingFrame() es false).

Con backends como Vulkan o Metal, es responsabilidad del backend QRhi bloquearse cada vez que se inicia un nuevo frame y se encuentra que la CPU ya está FramesInFlight - 1 frames por delante de la GPU (porque el buffer de comandos enviado en el frame no. current - FramesInFlight aún no se ha completado).

Los recursos que tienden a cambiar entre fotogramas (como, por ejemplo, el objeto de búfer nativo que respalda un QRhiBuffer con tipo QRhiBuffer::Dynamic) existen en múltiples versiones, de modo que cada fotograma, que puede ser enviado mientras uno anterior todavía está siendo procesado, funciona con su propia copia, evitando así la necesidad de detener el pipeline al preparar el fotograma. (El contenido de un recurso que aún pueda estar en uso en la GPU no debe tocarse, pero esperar siempre a que termine el fotograma anterior reduciría la utilización de la GPU y, en última instancia, el rendimiento y la eficiencia).

Conceptualmente, esto es algo similar a los esquemas copy-on-write utilizados por algunos contenedores C++ y otros tipos. También puede ser similar a lo que una implementación de OpenGL o Direct 3D 11 realiza internamente para cierto tipo de objetos.

En la práctica, estos recursos de doble (o triple) buffering se realizan en los backends Vulkan, Metal, y similares QRhi teniendo un número fijo de recursos nativos (como, VkBuffer) slots detrás de un QRhiResource. Que luego pueden ser indexados por un índice de ranura de fotograma que corre 0, 1, .., FramesInFlight-1, y luego se envuelve alrededor.

Todo esto se gestiona de forma transparente para los usuarios de QRhi. Sin embargo, las aplicaciones que integran el renderizado realizado directamente con la API gráfica pueden querer realizar un doble o triple buffering similar de sus propios recursos gráficos. Esto se consigue más fácilmente conociendo los valores del número máximo de fotogramas en vuelo (recuperable a través de resourceLimit()) y el índice del fotograma (slot) actual (devuelto por esta función).

Véase también isRecordingFrame(), beginFrame() y endFrame().

QRhiDriverInfo QRhi::driverInfo() const

Devuelve los metadatos del dispositivo gráfico utilizado por esta instancia de QRhi inicializada correctamente.

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

Finaliza, confirma y presenta una trama iniciada en el último beginFrame() en swapChain.

El doble (o triple) almacenamiento en búfer es gestionado internamente por QRhiSwapChain y QRhi.

flags se puede utilizar opcionalmente para cambiar el comportamiento de ciertas maneras. Pasando QRhi::SkipPresent se omite poner en cola el comando Presentar o llamar a swapBuffers.

Devuelve QRhi::FrameOpSuccess en caso de éxito, u otro valor QRhi::FrameOpResult en caso de fallo. Algunos de estos deben tratarse como errores suaves del tipo "inténtelo de nuevo más tarde": Cuando se devuelve QRhi::FrameOpSwapChainOutOfDate, la swapchain debe ser redimensionada o actualizada llamando a QRhiSwapChain::createOrResize(). La aplicación debería entonces intentar generar un nuevo frame. QRhi::FrameOpDeviceLost significa que el dispositivo gráfico se pierde pero esto también puede ser recuperable liberando todos los recursos, incluyendo el propio QRhi, y luego recreando todos los recursos. Véase isDeviceLost() para más información.

Véase también beginFrame() y isDeviceLost().

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

Finaliza, envía y espera el fotograma fuera de pantalla.

flags no se utiliza actualmente.

Véase también beginOffscreenFrame().

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

Devuelve la lista de adaptadores (dispositivos físicos) presentes, o una lista vacía cuando dicho control no está disponible con una API gráfica determinada.

En los backends en los que dicho nivel de control no está disponible, la lista devuelta está siempre vacía. Por lo tanto, una lista vacía no indica que no haya dispositivos gráficos en el sistema, sino que no está disponible un control detallado para seleccionar cuál utilizar.

Es de esperar que los backends para Direct 3D 11, Direct 3D 12 y Vulkan soporten completamente la enumeración de adaptadores. Es posible que otros no. El backend se especifica en impl. Un QRhiAdapter devuelto por esta función sólo debe utilizarse en una llamada a create() con el mismo impl. Algunas APIs subyacentes pueden presentar limitaciones adicionales, con Vulkan en particular el QRhiAdapter se especifica al QVulkanInstance (VkInstance).

Se espera que el llamante destruya los objetos QRhiAdapter de la lista. Aparte de consultar info(), el único propósito de estos objetos es pasarlos a create(), o a las funciones correspondientes en capas superiores como Qt Quick.

El siguiente fragmento, escrito específicamente para Vulkan, muestra cómo enumerar los dispositivos físicos disponibles y solicitar la creación de un QRhi para el elegido. En la práctica, esto equivale a pasar un VkPhysicalDevice a través de un QRhiVulkanNativeHandles a create(), pero implica menos código específico de la API en el lado de la aplicación:

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

Es necesario pasar params debido al diseño de algunas de las API de gráficos subyacentes. Con Vulkan en particular, se debe proporcionar QVulkanInstance, ya que la enumeración no es posible sin él. Otros campos del backend específico params no serán utilizados por esta función.

nativeHandles es opcional. Cuando se especifica, debe ser un QRhiD3D11NativeHandles, QRhiD3D12NativeHandles o QRhiVulkanNativeHandles válido, de forma similar a create(). Sin embargo, a diferencia de create(), sólo se utilizan los campos del dispositivo físico (en el caso de Vulkan) o el LUID del adaptador (en el caso de D3D), todos los demás campos se ignoran. Esto puede utilizarse para restringir los resultados a un adaptador determinado. La lista devuelta contendrá 1 o 0 elementos en este caso.

Observe cómo en el fragmento de código anterior la implementación de la función looksGood() no puede realizar ningún filtrado específico de plataforma basado en la verdadera identidad del adaptador / dispositivo físico, como el LUID del adaptador en Windows o el VkPhysicalDevice con Vulkan. Esto se debe a que QRhiDriverInfo no contiene datos específicos de la plataforma. En su lugar, utiliza nativeHandles para obtener los resultados filtrados ya dentro de enumerateAdapters().

Los dos fragmentos siguientes, utilizando Direct 3D 12 como ejemplo, son equivalentes en la práctica:

// Enfoque basado en enumerateAdapters desde Qt 6.10 enQRhiD3D12InitParams initParams; QRhiD3D12NativeHandles nativeHandles; nativeHandles.adapterLuidLow = luid.LowPart; // recuperado un LUID de algún sitio, ahora pásalo a QtnativeHandles.adapterLuidHigh = luid.HighPart;QRhi::AdapterList adaptadores = QRhi::enumerateAdapters(QRhi::D3D12, &initParams, &nativeHandles);if (adapters.isEmpty()) { qWarning("No se encontró el adaptador solicitado"); }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);

Esta función se introdujo en Qt 6.10.

Véase también create().

QRhi::FrameOpResult QRhi::finish()

Espera a que se complete cualquier trabajo en la cola de gráficos (cuando corresponda) y, a continuación, ejecuta todas las operaciones diferidas, como completar las devoluciones de lectura y las liberaciones de recursos. Puede invocarse dentro y fuera de un cuadro, pero no dentro de un pase. Dentro de un frame implica enviar cualquier trabajo en el buffer de comandos.

Nota: Evite esta función. Un caso en el que puede ser necesaria es cuando los resultados de una lectura en cola en un marco basado en swapchain se necesitan en un punto dado fijo y por lo tanto se desea esperar a los resultados.

bool QRhi::isClipDepthZeroToOne() const

Devuelve true si la API gráfica subyacente utiliza el rango de profundidad [0, 1] en el espacio de clip.

En la práctica esto es false sólo para OpenGL, porque OpenGL utiliza un rango de profundidad post-proyección de [-1, 1]. (no confundir con el mapeo NDC-a-ventana controlado por glDepthRange(), que usa un rango de [0, 1], a menos que sea sobreescrito por QRhiViewport) En algunas versiones de OpenGL glClipControl() podría usarse para cambiar esto, pero el backend OpenGL de QRhi no usa esa función ya que no está disponible en OpenGL ES o versiones de OpenGL inferiores a 4.5.

Nota: clipSpaceCorrMatrix() incluye el ajuste correspondiente en su matriz devuelta. Por lo tanto, muchos usuarios de QRhi no necesitan tomar ninguna otra medida aparte de premultiplicar sus matrices de proyección con clipSpaceCorrMatrix(). Sin embargo, algunas técnicas gráficas, como algunos tipos de mapeado de sombras, implican trabajar con valores de profundidad en los sombreadores. Estos deberán consultar y tener en cuenta el valor de esta función según corresponda.

bool QRhi::isDeviceLost() const

Devuelve true si se ha perdido el dispositivo gráfico.

La pérdida del dispositivo se detecta normalmente en beginFrame(), endFrame() o QRhiSwapChain::createOrResize(), dependiendo del backend y de las API nativas subyacentes. La más común es endFrame() porque es donde ocurre la presentación. Con algunos backends QRhiSwapChain::createOrResize() también puede fallar debido a una pérdida de dispositivo. Por lo tanto, esta función se proporciona como una forma genérica de comprobar si una pérdida de dispositivo fue detectada por una operación anterior.

Cuando se pierde el dispositivo, no se deben realizar más operaciones a través de QRhi. En su lugar, se deben liberar todos los recursos de QRhi, seguido de la destrucción de QRhi. A continuación, se puede intentar crear un nuevo QRhi. Si tiene éxito, todos los recursos gráficos deben ser reinicializados. Si no, hay que volver a intentarlo más tarde, repetidamente.

Mientras que las aplicaciones simples pueden decidir no preocuparse por la pérdida del dispositivo, en las plataformas de escritorio de uso común una pérdida del dispositivo puede ocurrir debido a una variedad de razones, incluyendo la desconexión física del adaptador gráfico, la desactivación del dispositivo o controlador, la desinstalación o actualización del controlador gráfico, o debido a errores que conducen a un reinicio del dispositivo gráfico. Algunos de estos pueden ocurrir en circunstancias perfectamente normales también, por ejemplo, la actualización del controlador de gráficos a una versión más reciente es una tarea común que puede ocurrir en cualquier momento mientras se ejecuta una aplicación Qt. Los usuarios pueden muy bien esperar que las aplicaciones sean capaces de sobrevivir a esto, incluso cuando la aplicación está utilizando activamente una API como OpenGL o Direct3D.

Se puede esperar que los propios frameworks de Qt construidos sobre QRhi, como, Qt Quick, manejen y tomen las medidas apropiadas cuando se produce una pérdida de dispositivo. Si los datos para los recursos gráficos, tales como texturas y buffers, están todavía disponibles en la CPU, tal evento puede no ser perceptible en el nivel de aplicación ya que los recursos gráficos pueden ser reinicializados sin problemas. Sin embargo, se espera que las aplicaciones y bibliotecas que trabajan directamente con QRhi estén preparadas para comprobar y gestionar por sí mismas las situaciones de pérdida de dispositivos.

Nota: Con OpenGL, es posible que las aplicaciones tengan que optar por recibir notificaciones de reinicio de contexto configurando QSurfaceFormat::ResetNotification en QOpenGLContext. Esto se hace normalmente activando la bandera en QRhiGles2InitParams::format. Sin embargo, hay que tener en cuenta que algunos sistemas pueden generar situaciones de restablecimiento de contexto incluso cuando este indicador no está activado.

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

Devuelve true si el feature especificado es compatible

bool QRhi::isRecordingFrame() const

Devuelve true cuando hay un marco activo, lo que significa que hubo un beginFrame() (o beginOffscreenFrame()) sin el correspondiente endFrame() (o endOffscreenFrame()) todavía.

Véase también currentFrameSlot(), beginFrame() y endFrame().

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

Devuelve true si la textura especificada format modificada por flags es compatible.

La consulta es compatible tanto para formatos sin comprimir como comprimidos.

bool QRhi::isYUpInFramebuffer() const

Devuelve true si la API gráfica subyacente tiene el eje Y apuntando hacia arriba en framebuffers e imágenes.

En la práctica esto es true sólo para OpenGL.

bool QRhi::isYUpInNDC() const

Devuelve true si la API gráfica subyacente tiene el eje Y apuntando hacia arriba en su sistema de coordenadas de dispositivo normalizado.

En la práctica esto es false sólo para Vulkan.

Nota: clipSpaceCorrMatrix() incluye el ajuste correspondiente (para hacer que Y apunte hacia arriba) en su matriz devuelta.

bool QRhi::makeThreadLocalNativeContextCurrent()

Con OpenGL, esto hace que el contexto OpenGL se actualice en el subproceso actual. La función no tiene efecto con otros backends.

Llamar a esta función es relevante típicamente en el código del framework Qt, cuando uno tiene que asegurarse de que el código OpenGL externo proporcionado por la aplicación puede seguir ejecutándose como lo hacía antes con el uso directo de OpenGL, siempre y cuando QRhi esté usando el backend OpenGL.

Devuelve false cuando falla, de forma similar a QOpenGLContext::makeCurrent(). Cuando la operación falla, se puede llamar a isDeviceLost() para determinar si hubo una situación de pérdida de contexto. Esta comprobación es equivalente a la realizada mediante QOpenGLContext::isValid().

Véase también QOpenGLContext::makeCurrent() y QOpenGLContext::isValid().

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

Devuelve el número de niveles mip para un determinado size.

const QRhiNativeHandles *QRhi::nativeHandles()

Devuelve un puntero a la colección de objetos nativos específicos del backend para el dispositivo, el contexto y conceptos similares utilizados por el backend.

Cast to QRhiVulkanNativeHandles, QRhiD3D11NativeHandles, QRhiD3D12NativeHandles, QRhiGles2NativeHandles, or QRhiMetalNativeHandles as appropriate.

Nota: No se transfiere la propiedad, ni del puntero devuelto ni de ningún objeto nativo.

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

Devuelve un nuevo búfer con los datos especificados type, usage, y size.

Nota: Algunas combinaciones de usage y type pueden no estar soportadas por todos los backends. Véase UsageFlags y the feature flags.

Nota: Los backends pueden optar por asignar buffers mayores que size. Esto se hace de forma transparente para las aplicaciones, por lo que no hay restricciones especiales en el valor de size. QRhiBuffer::size() siempre devolverá el valor que se solicitó en size.

Véase también QRhiResource::destroy().

QRhiComputePipeline *QRhi::newComputePipeline()

Devuelve un nuevo recurso de canalización de cálculo.

Nota: Compute sólo está disponible cuando la función Compute está soportada.

Véase también QRhiResource::destroy().

QRhiGraphicsPipeline *QRhi::newGraphicsPipeline()

Devuelve un nuevo recurso de canalización gráfica.

Véase también QRhiResource::destroy().

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

Devuelve un nuevo renderbuffer con los formatos type, pixelSize, sampleCount, y flags especificados.

Cuando backingFormatHint se establece en un formato de textura distinto de QRhiTexture::UnknownFormat, puede ser utilizado por el backend para decidir qué formato utilizar para el almacenamiento que respalda el renderbuffer.

Nota: backingFormatHint se vuelve relevante típicamente cuando se involucran formatos de textura multimuestreo y de punto flotante: renderizar en un multimuestreo QRhiRenderBuffer y luego resolver en un QRhiTexture no RGBA8 implica (con algunas APIs gráficas) que el almacenamiento que respalda el QRhiRenderBuffer utiliza el formato no RGBA8 correspondiente. Esto significa que pasar un formato como QRhiTexture::RGBA32F es importante, porque los backends normalmente optarán por QRhiTexture::RGBA8 por defecto, lo que se rompería más tarde debido al intento de configurar la resolución multimuestra RGBA8->RGBA32F en el adjunto(s) de color de QRhiTextureRenderTarget.

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

Devuelve un nuevo muestreador con el filtro de ampliación especificado magFilter, el filtro de minimización minFilter, el modo mipmapping mipmapMode, y los modos de direccionamiento (wrap) addressU, addressV, y addressW.

Nota: Establecer mipmapMode a un valor distinto de None implica que las imágenes para todos los niveles mip relevantes se proporcionarán a través de texture uploads o llamando a generateMips() en la textura que se utiliza con este muestreador. Si se intenta utilizar el muestreador con una textura que no tiene datos para todos los niveles mip relevantes, se producirán errores de renderizado, y el comportamiento exacto dependerá de la API gráfica subyacente.

Véase también QRhiResource::destroy().

QRhiShaderResourceBindings *QRhi::newShaderResourceBindings()

Devuelve un nuevo recurso de colección de vinculación de recursos de sombreado.

Véase también QRhiResource::destroy().

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

Devuelve un nuevo objeto de mapa de sombreado.

Esta función se introdujo en Qt 6.9.

QRhiSwapChain *QRhi::newSwapChain()

Devuelve una nueva swapchain.

Véase también QRhiResource::destroy() y QRhiSwapChain::createOrResize().

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

Devuelve una nueva textura 1D o 2D con los valores especificados format, pixelSize, sampleCount, y flags.

Una matriz de textura 1D debe tener QRhiTexture::OneDimensional establecido en flags. Esta función establecerá implícitamente esta bandera si la altura de pixelSize es 0.

Nota: format especifica el formato interno y externo solicitado, lo que significa que los datos que se carguen en la textura deberán estar en un formato compatible, mientras que la textura nativa puede (aunque no está garantizado, al menos en el caso de OpenGL) utilizar este formato internamente.

Nota: Las texturas 1D sólo son funcionales cuando la característica OneDimensionalTextures se reporta como soportada en tiempo de ejecución. Además, los mipmaps en texturas 1D sólo son funcionales cuando la función OneDimensionalTextureMipmaps se indica en tiempo de ejecución.

Véase también QRhiResource::destroy().

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

Devuelve una nueva textura 1D, 2D o 3D con los valores especificados format, width, height, depth, sampleCount, y flags.

Esta sobrecarga es adecuada para texturas 3D porque permite especificar depth. Una textura 3D debe tener QRhiTexture::ThreeDimensional establecido en flags, pero usando esta sobrecarga eso puede omitirse porque la bandera se establece implícitamente siempre que depth sea mayor que 0. Para texturas 1D, 2D y cubos depth debe establecerse en 0.

Una textura 1D debe tener QRhiTexture::OneDimensional fijado en flags. Esta sobrecarga fijará implícitamente esta bandera si tanto height como depth son 0.

Nota: Las texturas 3D sólo son funcionales cuando la característica ThreeDimensionalTextures es reportada como soportada en tiempo de ejecución.

Nota: Las texturas 1D sólo son funcionales cuando la característica OneDimensionalTextures es reportada como soportada en tiempo de ejecución. Además, los mipmaps de las texturas 1D sólo son funcionales cuando la función OneDimensionalTextureMipmaps se indica en tiempo de ejecución.

Se trata de una función sobrecargada.

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

Devuelve una nueva matriz de texturas 1D o 2D con los valores especificados format, arraySize, pixelSize, sampleCount, y flags.

Esta función establece implícitamente QRhiTexture::TextureArray en flags.

Una matriz de texturas 1D debe tener QRhiTexture::OneDimensional en flags. Esta función fijará implícitamente esta bandera si la altura de pixelSize es 0.

Nota: No confunda las matrices de texturas con las matrices de texturas. Un QRhiTexture creado por esta función es utilizable con muestreadores de arrays 1D o 2D en el shader, por ejemplo: layout(binding = 1) uniform sampler2DArray texArr;. Arrays de texturas se refiere a una lista de texturas que están expuestas al shader a través de QRhiShaderResourceBinding::sampledTextures() y un count > 1, y declaradas en el shader por ejemplo así: layout(binding = 1) uniform sampler2D textures[4];

Nota: Esto sólo es funcional cuando la característica TextureArrays es reportada como soportada en tiempo de ejecución.

Nota: Las texturas 1D sólo son funcionales cuando la característica OneDimensionalTextures es reportada como soportada en tiempo de ejecución. Además, los mipmaps en texturas 1D sólo son funcionales cuando la función OneDimensionalTextureMipmaps se indica en tiempo de ejecución.

Véase también newTexture().

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

Devuelve un nuevo objetivo de renderizado de textura con los anexos de color y profundidad/esténcil dados en desc, y con el flags especificado.

Véase también QRhiResource::destroy().

QRhiResourceUpdateBatch *QRhi::nextResourceUpdateBatch()

Devuelve un lote disponible y vacío en el que se pueden registrar operaciones de tipo copia.

Nota: el valor devuelto no es propiedad de quien lo llama y nunca debe ser destruido. En su lugar, el lote se devuelve al pool para su reutilización pasándolo a QRhiCommandBuffer::beginPass(), QRhiCommandBuffer::endPass(), o QRhiCommandBuffer::resourceUpdate(), o llamando a QRhiResourceUpdateBatch::release() sobre él.

Nota: También se puede llamar fuera de beginFrame() - endFrame() ya que una instancia de lote sólo recoge datos por sí misma, no realiza ninguna operación.

Al no estar ligada a un fotograma que se esté grabando, la siguiente secuencia es válida por ejemplo:

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

Advertencia: El número máximo de lotes por QRhi es 64. Cuando se alcance este límite, la función devolverá null hasta que se devuelva un lote al pool.

QByteArray QRhi::pipelineCacheData()

Devuelve un blob de datos binarios con los datos recogidos de QRhiGraphicsPipeline y QRhiComputePipeline creados con éxito durante la vida de este QRhi.

Al guardar y luego, en posteriores ejecuciones de la misma aplicación, recargar los datos de la caché, se pueden reducir potencialmente los tiempos de creación de pipelines y shaders. Lo que incluye exactamente la caché y su versión serializada no está especificado, es siempre específico del backend utilizado, y en algunos casos también depende de la implementación particular de la API gráfica.

Cuando el PipelineCacheDataLoadSave es reportado como no soportado, el QByteArray devuelto está vacío.

Cuando no se ha especificado el indicador EnablePipelineCacheDataSave al llamar a create(), el archivo QByteArray devuelto puede estar vacío, incluso si la función PipelineCacheDataLoadSave está soportada.

Cuando los datos devueltos no están vacíos, siempre son específicos de la versión de Qt y del backend QRhi. Además, en algunos casos existe una fuerte dependencia con el dispositivo gráfico y la versión exacta del driver utilizado. QRhi se encarga de añadir la cabecera apropiada y las salvaguardas que aseguran que los datos siempre pueden ser pasados de forma segura a setPipelineCacheData(), por lo tanto, intentar cargar datos desde una ejecución en otra versión de un driver será manejado de forma segura y con gracia.

Nota: La llamada a releaseCachedResources() puede, dependiendo del backend, borrar los datos recogidos del pipeline. Una llamada posterior a esta función puede entonces no devolver ningún dato.

Véase EnablePipelineCacheDataSave para más detalles sobre esta función.

Nota: Reduzca al mínimo el número de llamadas a esta función. Recuperar el blob no siempre es una operación barata, y por lo tanto esta función sólo debe ser llamada con poca frecuencia, idealmente sólo una vez, por ejemplo, al cerrar la aplicación.

Véase también setPipelineCacheData(), create(), y isFeatureSupported().

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

Devuelve true si se puede esperar que create() tenga éxito cuando se llama a los dados impl y params.

Para algunos backends, esto equivale a llamar a create(), comprobar su valor de retorno y, a continuación, destruir el QRhi resultante.

Para otros, en particular con Metal, puede haber una implementación de sondeo específica, que permite realizar pruebas de una manera más ligera sin contaminar la salida de depuración con advertencias en caso de fallo.

Véase también create().

void QRhi::releaseCachedResources()

Intenta liberar recursos en las cachés del backend. Esto puede incluir tanto recursos de CPU como de GPU. Sólo la memoria y los recursos que pueden ser recreados automáticamente están dentro del alcance. Por ejemplo, si la implementación de QRhiGraphicsPipeline del backend mantiene una caché de resultados de compilación de sombreadores, la llamada a esta función lleva a vaciar esa caché, liberando así potencialmente memoria y recursos gráficos.

Llamar a esta función tiene sentido en entornos con recursos limitados, donde en un momento dado es necesario garantizar un uso mínimo de recursos, a expensas del rendimiento.

void QRhi::removeCleanupCallback(const void *key)

Cancela el registro de la llamada de retorno con key. Si no se registró ninguna llamada de retorno de limpieza con key, la función no hace nada. Las retrollamadas registradas sin clave no pueden ser eliminadas.

Véase también addCleanupCallback().

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

Devuelve el valor del recurso especificado limit.

Se espera que los valores sean consultados por los backends en el momento de la inicialización, lo que significa que llamar a esta función es una operación ligera.

void QRhi::setPipelineCacheData(const QByteArray &data)

Carga data en la caché de canalización, si procede.

Cuando el PipelineCacheDataLoadSave es reportado como no soportado, la función es segura de llamar, pero no tiene ningún efecto.

El blob devuelto por pipelineCacheData() es siempre específico para la versión de Qt, el backend QRhi, y, en algunos casos, también para el dispositivo gráfico, y una versión dada del controlador gráfico. QRhi se encarga de añadir la cabecera apropiada y las salvaguardas que aseguran que los datos siempre pueden ser pasados de forma segura a esta función. Si hay un desajuste, por ejemplo, porque el controlador se ha actualizado a una versión más reciente, o porque los datos se generaron a partir de un backend QRhi diferente, se imprime una advertencia y data se ignora de forma segura.

Con Vulkan, esto se asigna directamente a VkPipelineCache. Al llamar a esta función se crea un nuevo objeto de caché de canalización Vulkan, con sus datos iniciales procedentes de data. El objeto de caché de canalización es utilizado entonces por todos los objetos QRhiGraphicsPipeline y QRhiComputePipeline creados posteriormente, acelerando así, potencialmente, la creación de canalizaciones.

Con otras APIs no existe una caché de pipeline real, pero pueden proporcionar una caché con bytecode de compilaciones de shaders (D3D) o binarios de programa (OpenGL). En aplicaciones que realizan muchas compilaciones de sombreadores desde el código fuente en tiempo de ejecución, esto puede proporcionar un aumento significativo en las ejecuciones posteriores si la "caché de canalización" se preconfigura desde una ejecución anterior utilizando esta función.

Nota: QRhi no puede dar ninguna garantía de que data tenga un efecto sobre el pipeline y el rendimiento de la creación de shaders. Con APIs como Vulkan, depende del driver decidir si data se utiliza para algún propósito, o si se ignora.

Consulta EnablePipelineCacheDataSave para más detalles sobre esta característica.

Nota: Este mecanismo ofrecido por QRhi es independiente del propio mecanismo de caché interno de los controladores, si lo hubiera. Esto significa que, dependiendo de la API gráfica y su implementación, los efectos exactos de recuperar y luego recargar data no son predecibles. La mejora del rendimiento puede no ser visible en absoluto en caso de que otros mecanismos de almacenamiento en caché fuera del control de Qt ya estén activos.

Nota: Minimice el número de llamadas a esta función. Cargar el blob no siempre es una operación barata, y por lo tanto esta función sólo debería ser llamada con poca frecuencia, idealmente sólo una vez, por ejemplo, al iniciar la aplicación.

Advertencia: Se asume que los datos serializados de la caché de canalización son contenido de confianza. Qt realiza un análisis robusto de la cabecera y los metadatos incluidos en data, sin embargo, se recomienda a los desarrolladores de aplicaciones que nunca pasen datos de fuentes no fiables.

Véase también pipelineCacheData() y isFeatureSupported().

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

Con backends y APIs gráficas donde sea aplicable, esta función permite proporcionar argumentos adicionales al siguiente envío de comandos a la cola de comandos gráficos.

En particular, con Vulkan esto permite pasar una lista de objetos semáforo Vulkan para que vkQueueSubmit() señale y espere. params debe ser entonces un QRhiVulkanQueueSubmitParams. Esto se vuelve esencial en ciertos casos de uso avanzado, como cuando se realizan llamadas Vulkan nativas que implican tener que esperar y señalar VkSemaphores que el código de renderizado o computación Vulkan personalizado de la aplicación gestiona. Además, esto también permite especificar semáforos adicionales en los que esperar en la siguiente vkQueuePresentKHR().

Nota: Esta función afecta únicamente al envío a la siguiente cola, que ocurrirá en endFrame(), endOffscreenFrame(), o finish(). La puesta en cola de presentes ocurre en endFrame().

Con muchos otros backends la implementación de esta función es un no-op.

Esta función se introdujo en Qt 6.9.

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

Devuelve el tamaño de la imagen de textura para un determinado mipLevel, calculado a partir del tamaño del nivel 0 dado en baseLevelSize.

QRhiStats QRhi::statistics() const

Recopila y devuelve estadísticas sobre los tiempos y las asignaciones de recursos gráficos.

Los datos sobre las asignaciones de memoria sólo están disponibles con algunos backends, donde tales operaciones están bajo el control de Qt. Con APIs gráficas donde no hay control de nivel inferior sobre las asignaciones de memoria de recursos, esto nunca será soportado y todos los campos relevantes en los resultados son 0.

Con Vulkan en particular, los valores son válidos siempre, y se consultan desde la biblioteca de asignación de memoria subyacente. Esto permite conocer los requisitos de memoria de los búferes activos y las texturas.

Lo mismo ocurre con Direct 3D 12. Además de las estadísticas de la biblioteca asignadora de memoria, aquí el resultado también incluye un campo totalUsageBytes que informa del tamaño total incluyendo los recursos adicionales que no están bajo el control de la biblioteca asignadora de memoria (buffers swapchain, heaps de descriptores, etc.), tal y como informa DXGI.

Los valores corresponden a todos los tipos de memoria utilizados, combinados. (es decir, vídeo + sistema en el caso de una GPU discreta).

En la mayoría de los backends se dispone de datos adicionales, como el tiempo total en milisegundos empleado en la creación de canalizaciones gráficas y de cálculo (que suele implicar la compilación de shaders o búsquedas en caché, y un procesamiento potencialmente costoso).

Nota: los tiempos transcurridos en operaciones como la creación de pipelines pueden verse afectados por diversos factores. Los resultados no deben compararse entre diferentes backends, ya que el concepto de "pipelines" y lo que ocurre exactamente durante, por ejemplo, una llamada a QRhiGraphicsPipeline::create(), difieren mucho entre las APIs gráficas y sus implementaciones.

Nota: Además, es probable que muchos controladores empleen diversas estrategias de almacenamiento en caché para shaders, programas, pipelines. (independientemente de las facilidades similares propias de Qt, como setPipelineCacheData() o la caché de disco binaria de programas específica de OpenGL). Dado que este comportamiento interno es transparente para el cliente de la API, Qt y QRhi no tienen conocimiento ni control sobre la estrategia exacta de almacenamiento en caché, persistencia, invalidación de los datos almacenados en caché, etc. Al leer los tiempos, como el tiempo empleado en la creación de pipelines, debe tenerse en cuenta la presencia potencial y el comportamiento no especificado de los mecanismos de caché a nivel de controlador.

QList<int> QRhi::supportedSampleCounts() const

Devuelve la lista de recuentos de muestras admitidos.

Un ejemplo típico sería (1, 2, 4, 8).

Con algunos backend esta lista de valores soportados está fijada de antemano, mientras que con otros las propiedades (físicas) del dispositivo indican lo que está soportado en tiempo de ejecución.

Véase también QRhiRenderBuffer::setSampleCount(), QRhiTexture::setSampleCount(), QRhiGraphicsPipeline::setSampleCount() y QRhiSwapChain::setSampleCount().

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

Devuelve La lista de tasas de sombreado variables admitidas para la dirección sampleCount especificada.

Siempre se admite 1x1.

Esta función se introdujo en Qt 6.9.

QThread *QRhi::thread() const

Devuelve el hilo en el que se QRhi initialized .

int QRhi::ubufAligned(int v) const

Devuelve el valor (normalmente un desplazamiento) v alineado con la alineación uniforme del búfer dada por ubufAlignment().

int QRhi::ubufAlignment() const

Devuelve la alineación mínima uniforme del desplazamiento del búfer en bytes. Normalmente es 256.

Intentar enlazar una región de búfer uniforme con un desplazamiento no alineado con este valor provocará fallos dependiendo del backend y de la API gráfica subyacente.

Véase también ubufAligned().

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

Genera y devuelve una estructura QRhiSwapChainProxyData que contiene datos opacos específicos de la API de backend y gráficos especificada por impl. window es la QWindow a la que se dirige una swapchain.

La estructura devuelta puede pasarse a QRhiSwapChain::setProxyData(). Esto tiene sentido en sistemas de renderizado con hilos: se espera que esta función estática sea llamada en el hilo principal (gui), a diferencia de todas las operaciones QRhi, luego transferida al hilo que trabaja con QRhi y QRhiSwapChain y pasada a la swapchain. Esto permite hacer consultas nativas de la plataforma que sólo son seguras para ser llamadas en el hilo principal, por ejemplo para consultar la CAMetalLayer desde una NSView, y luego pasar los datos a la QRhiSwapChain que vive en el hilo de renderizado. Con el ejemplo de Metal, hacer el acceso a view.layer en un hilo de renderizado dedicado causa una advertencia en el Thread Checker de Xcode. Con el mecanismo de proxy de datos, esto se evita.

Cuando no hay hilos involucrados, no es necesario generar y pasar el QRhiSwapChainProxyData: se garantiza que los backends pueden consultar lo que sea necesario por sí mismos, y si todo vive en el hilo principal (gui), eso debería ser suficiente.

Nota: impl debe coincidir con lo que se crea en QRhi. Por ejemplo, una llamada con QRhi::Metal en una plataforma que no sea Apple no generará ningún dato útil.

No miembros relacionados

[alias, since 6.7] QRhiShaderResourceBindingSet

Sinónimo de QRhiShaderResourceBindings.

Este typedef se introdujo en 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.