QRhiResourceUpdateBatch Class

记录上传和复制操作类型。更多

头文件: #include <rhi/qrhi.h>
CMake: find_package(Qt6 REQUIRED COMPONENTS Gui)
target_link_libraries(mytarget PRIVATE Qt6::GuiPrivate)
qmake: QT += gui-private
Qt 6.6

公共函数

void copyTexture(QRhiTexture *dst, QRhiTexture *src, const QRhiTextureCopyDescription &desc = QRhiTextureCopyDescription())
void generateMips(QRhiTexture *tex)
bool hasOptimalCapacity() const
void merge(QRhiResourceUpdateBatch *other)
void readBackBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, QRhiReadbackResult *result)
void readBackTexture(const QRhiReadbackDescription &rb, QRhiReadbackResult *result)
void release()
void updateDynamicBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
void uploadStaticBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
void uploadStaticBuffer(QRhiBuffer *buf, const void *data)
void uploadTexture(QRhiTexture *tex, const QImage &image)
void uploadTexture(QRhiTexture *tex, const QRhiTextureUploadDescription &desc)

详细说明

QRhi 不再可能在任意时间执行复制类型的操作。取而代之的是,所有此类操作都被记录到批次中,然后被传递(最常见的是传递到QRhiCommandBuffer::beginPass() )。随后发生的事情对应用程序是隐藏的:底层实现可以以各种不同的方式推迟和执行这些操作。

资源更新批次不拥有任何图形资源,自身也不执行任何实际操作。它应被视为更新、上传和复制类型命令的命令缓冲区。

要从池中获取可用的空批次,请调用QRhi::nextResourceUpdateBatch() 。

注意: 这是一个 RHI API,具有有限的兼容性保证,详情请参见QRhi

成员函数文档

void QRhiResourceUpdateBatch::copyTexture(QRhiTexture *dst, QRhiTexture *src, const QRhiTextureCopyDescription &desc = QRhiTextureCopyDescription())

desc 所述,从srcdst 中排队进行纹理到纹理的复制操作。

注: 源纹理src 必须通过QRhiTexture::UsedAsTransferSource 创建。

注: 纹理格式必须匹配。在大多数图形 API 中,数据都是按原样复制的,不会进行任何格式转换。如果dstsrc 以不同格式创建,可能会出现不明问题。

void QRhiResourceUpdateBatch::generateMips(QRhiTexture *tex)

为指定的纹理tex 查询 mipmap 生成操作。

支持二维和立方体纹理。

注意: 必须使用QRhiTexture::MipMappedQRhiTexture::UsedWithGenerateMips 创建纹理。

警告: QRhi 不能保证为所有支持的纹理格式生成 mipmap。例如,在 iOS 上的 OpenGL ES 3.0 和 Metal 中,QRhiTexture::RGBA32F 不是filterable 格式,因此 mipmap 生成请求可能会失败。RGBA8 和 RGBA16F 通常可以过滤,因此建议在需要生成 mipmap 时使用这些格式。

bool QRhiResourceUpdateBatch::hasOptimalCapacity() const

返回值为 true,直到在此批次上排队的缓冲区和纹理操作的数量低于合理的限制。

当添加到该批次的缓冲区和/或纹理操作的数量已达到或即将达到某个限制时,返回值为 false。之后,批处理也能正常运行,但可能需要分配额外的内存。因此,如果渲染器在准备帧时在单个批次中收集了大量缓冲区和纹理更新,则可能需要考虑在此函数返回 false 时使用submitting the batchstarting a new one

void QRhiResourceUpdateBatch::merge(QRhiResourceUpdateBatch *other)

other 批次中的所有队列操作复制到此批次中。

注意: 合并操作后,other 可能不再包含有效数据,因此不得提交,但仍需调用release() 将其释放。

这样就形成了一种方便的模式,即在初始化步骤中已经知道的资源更新会被收集到一个批次中,然后在稍后开始第一次渲染时再将其合并到另一个批次中:

void init()
{
    initialUpdates = rhi->nextResourceUpdateBatch();
    initialUpdates->uploadStaticBuffer(vbuf, vertexData);
    initialUpdates->uploadStaticBuffer(ibuf, indexData);
    // ...
}

void render()
{
    QRhiResourceUpdateBatch *resUpdates = rhi->nextResourceUpdateBatch();
    if (initialUpdates) {
        resUpdates->merge(initialUpdates);
        initialUpdates->release();
        initialUpdates = nullptr;
    }
    // resUpdates->updateDynamicBuffer(...);
    cb->beginPass(rt, clearCol, clearDs, resUpdates);
}

void QRhiResourceUpdateBatch::readBackBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, QRhiReadbackResult *result)

排队回读QRhiBuffer buf 中的一个区域。size 指定了区域的大小(以字节为单位),offset 是开始读取的偏移量(以字节为单位)。

回读是异步的。result 包含操作完成后调用的回调。数据在QRhiReadbackResult::data 中提供。成功完成后,QByteArray 的大小将等于size 。失败时,QByteArray 将为空。

注意: 只有在报告支持QRhi::ReadBackNonUniformBuffer 功能时,才支持读取用法与QRhiBuffer::UniformBuffer 不同的缓冲区。

注意: 异步回读保证在满足以下条件之一时完成:finish() 已被调用;或者,至少有N 帧已被submitted ,包括发出回读操作的帧,并且recording of a new frame 已被启动,其中NQRhi::MaxAsyncReadbackFrames 返回的resource limit value

另请参阅 readBackTexture()、QRhi::isFeatureSupported() 和QRhi::resourceLimit()。

void QRhiResourceUpdateBatch::readBackTexture(const QRhiReadbackDescription &rb, QRhiReadbackResult *result)

根据rb 的描述,启动纹理到主机的复制操作。

通常情况下,rb 会指定一个QRhiTexture 作为源。不过,如果当前帧中的交换链是通过QRhiSwapChain::UsedAsTransferSource 创建的,那么它也可以作为回读的源。为此,请在rb 中将纹理设置为空。

与其他操作不同,这里的结果需要由应用程序处理。因此,result 不仅提供数据,还提供回调,因为对批处理的操作本质上是异步的:

rhi->beginFrame(swapchain);
cb->beginPass(swapchain->currentFrameRenderTarget(), colorClear, dsClear);
// ...
QRhiReadbackResult *rbResult = new QRhiReadbackResult;
rbResult->completed = [rbResult] {
    {
        const QImage::Format fmt = QImage::Format_RGBA8888_Premultiplied; // fits QRhiTexture::RGBA8
        const uchar *p = reinterpret_cast<const uchar *>(rbResult->data.constData());
        QImage image(p, rbResult->pixelSize.width(), rbResult->pixelSize.height(), fmt);
        image.save("result.png");
    }
    delete rbResult;
};
QRhiResourceUpdateBatch *u = nextResourceUpdateBatch();
QRhiReadbackDescription rb; // no texture -> uses the current backbuffer of sc
u->readBackTexture(rb, rbResult);
cb->endPass(u);
rhi->endFrame(swapchain);

注: 必须使用QRhiTexture::UsedAsTransferSource 创建纹理。

注意: 不能回读多采样纹理。

注意: 回读会返回原始字节数据,以便应用程序以自己认为合适的方式进行解释。请注意渲染代码的混合设置:如果混合设置依赖于预乘法 alpha,则回读结果也必须解释为预乘法。

注意: 在解释生成的原始数据时,请注意回读是以字节有序格式进行的。因此,RGBA8 纹理映射为字节有序的QImage 格式,如QImage::Format_RGBA8888

注意: 当满足以下条件之一时,异步回读将保证完成:finish() 已被调用;或者,至少有N 帧已被submitted ,包括发出回读操作的帧,并且recording of a new frame 已被启动,其中N 是为QRhi::MaxAsyncReadbackFrames 返回的resource limit value

单次回读操作一次复制一个层(立方体贴图面或三维切片或纹理阵列元素)的一个 mip 层。级别和层由rb 中的相应字段指定。

另请参阅 readBackBuffer() 和QRhi::resourceLimit()。

void QRhiResourceUpdateBatch::release()

将批处理返回到池中。只有当批处理未传递给QRhiCommandBuffer::beginPass(),QRhiCommandBuffer::endPass(), 或QRhiCommandBuffer::resourceUpdate() 时才可使用,因为这些函数会隐式调用 destroy()。

注意: QRhiResourceUpdateBatch 实例绝不能被应用程序deleted

void QRhiResourceUpdateBatch::updateDynamicBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)

排队更新用QRhiBuffer::Dynamic 类型创建的QRhiBuffer buf 的一个区域。

区域由offsetsize 指定。要写入的实际字节由data 指定,而 必须至少有size 字节可用。一旦此函数返回,data 可以安全地销毁或更改。

注意: 如果涉及主机写入(updateDynamicBuffer()就是这种情况,因为大多数后端缓冲区都是由主机可见内存支持的),它们可能会在一帧内累积。因此,传递 1 在读取传递 2 的批处理所更改的区域时,可能会看到传递 2 的更新批处理中指定的更改。

注意: QRhi 会透明地管理双重缓冲,以防止图形流水线停滞。在使用QRhiQRhiResourceUpdateBatch 时,可以安全地忽略QRhiBuffer 下面可能有多个本地缓冲区对象这一事实。

void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)

排队更新以QRhiBuffer::ImmutableQRhiBuffer::Static 类型创建的QRhiBuffer buf 的一个区域。

区域由offsetsize 指定。要写入的实际字节由data 指定,而 必须至少有size 字节可用。一旦此函数返回,data 可以安全地销毁或更改。

void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, const void *data)

这是一个重载函数。

对以QRhiBuffer::ImmutableQRhiBuffer::Static 类型创建的整个QRhiBuffer buf 进行排队更新。

void QRhiResourceUpdateBatch::uploadTexture(QRhiTexture *tex, const QImage &image)

为纹理tex 第 0 层的第 0 mip 层上传图像数据。

tex 必须是未压缩格式。其格式还必须与 的 () 兼容。源数据在 中给出。image QImage::format image

void QRhiResourceUpdateBatch::uploadTexture(QRhiTexture *tex, const QRhiTextureUploadDescription &desc)

为纹理tex 的一个或多个层中的一个或多个 mip 层上传图像数据排队。

复制的详细信息(源QImage 或压缩纹理数据、区域、目标图层和图层)请参阅desc

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