QRhiBuffer 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 |
継承: | QRhiResource |
パブリックな型
struct | NativeBuffer |
enum | Type { Immutable, Static, Dynamic } |
enum | UsageFlag { VertexBuffer, IndexBuffer, UniformBuffer, StorageBuffer } |
flags | UsageFlags |
パブリック関数
virtual char * | beginFullDynamicBufferUpdateForCurrentFrame() |
virtual bool | create() = 0 |
virtual void | endFullDynamicBufferUpdateForCurrentFrame() |
virtual QRhiBuffer::NativeBuffer | nativeBuffer() |
void | setSize(quint32 sz) |
void | setType(QRhiBuffer::Type t) |
void | setUsage(QRhiBuffer::UsageFlags u) |
quint32 | size() const |
QRhiBuffer::Type | type() const |
QRhiBuffer::UsageFlags | usage() const |
再実装されたパブリック関数
virtual QRhiResource::Type | resourceType() const override |
詳細説明
注: これは互換性保証に制限のあるRHI APIです。詳細はQRhi を参照してください。
QRhiBufferは、0個、1個、またはそれ以上のネイティブ・バッファ・オブジェクト(VkBuffer
やMTLBuffer
など)をカプセル化します。いくつかのグラフィックスAPIやバックエンドでは、ある種のバッファはネイティブバッファオブジェクトを全く使用しないかもしれません(例えば、ユニフォームバッファオブジェクトが使用されないOpenGLなど)が、これはQRhiBuffer APIのユーザには透過的です。同様に、バッファの種類によっては、GPUパイプラインをストールさせることなくフレームごとのコンテンツ更新を効率的に行うために、2つまたは3つのネイティブバッファを使用することがありますが、アプリケーションやライブラリからはほとんど見えません。
QRhiBufferインスタンスは常にthe QRhi's newBuffer() function 。これにより、ネイティブ・グラフィックス・リソースは作成されません。これを行うには、タイプ、使用フラグ、サイズなどの適切なオプションを設定した後、create ()を呼び出しますが、ほとんどの場合、これらはnewBuffer ()に渡された引数に基づいてすでに設定されています。
使用例
GLSL ユニフォームブロックが単一のmat4
メンバを含むシェーダ用のユニフォームバッファを作成し、その内容を更新する:
QRhiBuffer *ubuf = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 64); if (!ubuf->create()) { error(); } QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch(); QMatrix4x4 mvp; // ... set up the modelview-projection matrix batch->updateDynamicBuffer(ubuf, 0, 64, mvp.constData()); // ... commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call
頂点データでバッファを作成する例:
const float vertices[] = { -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f }; QRhiBuffer *vbuf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertices)); if (!vbuf->create()) { error(); } QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch(); batch->uploadStaticBuffer(vbuf, vertices); // ... commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call
インデックスバッファ:
static const quint16 indices[] = { 0, 1, 2 }; QRhiBuffer *ibuf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::IndexBuffer, sizeof(indices)); if (!ibuf->create()) { error(); } QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch(); batch->uploadStaticBuffer(ibuf, indices); // ... commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call
よくあるパターン
create() の呼び出しは、create() が以前に正常に呼び出された場合、既存のネイティブリソースを破壊します。これらのネイティブリソースがまだインフライトフレームで使用されている場合(つまり、GPUによってまだ読み込まれている可能性がある場合)、これらのリソースの破棄は自動的に延期されます。このように、すでに初期化されたバッファのサイズを安全に増やすための、 非常に一般的で便利なパターンは次のようなものです。なぜなら、buf
オブジェクト自体を破棄しないことで、他のデータ構造(たとえば、QRhiBufferが参照されるQRhiShaderResourceBinding )において、そのオブジェクトへの参照はすべて有効なままだからです。
if (buf->size() < newSize) { buf->setSize(newSize); if (!buf->create()) { error(); } } // continue using buf, fill it with new data
ユニフォームバッファを使用する場合、効率上の理由から、複数の描画呼び出しのデータを1つのバッファにまとめることが必要になることがあります。いくつかのグラフィックスAPIでは、ユニフォームバッファのオフセットは256バイトにアライメントされなければなりません。これは、QRhiShaderResourceBinding と、setShaderResources() に渡される動的オフセットの両方に適用されます。移植可能なコードを作成するには、ubufAlignment ()とubufAligned ()関数を使用します。例として、同じパイプラインとジオメトリで、バインディングポイント 0 で公開されるユニフォームバッファ内のデータが異なる複数の (N
) 描画コールを発行するアウトラインを以下に示します。これは、uniformBufferWithDynamicOffset() を介してバッファが公開され、QRhiCommandBuffer::DynamicOffset リストをsetShaderResources() に渡すことができると仮定しています。
const int N = 2; const int UB_SIZE = 64 + 4; // assuming a uniform block with { mat4 matrix; float opacity; } const int ONE_UBUF_SIZE = rhi->ubufAligned(UB_SIZE); const int TOTAL_UBUF_SIZE = N * ONE_UBUF_SIZE; QRhiBuffer *ubuf = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, TOTAL_UBUF_SIZE); if (!ubuf->create()) { error(); } QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch(); for (int i = 0; i < N; ++i) { batch->updateDynamicBuffer(ubuf, i * ONE_UBUF_SIZE, 64, matrix.constData()); batch->updateDynamicBuffer(ubuf, i * ONE_UBUF_SIZE + 64, 4, &opacity); } // ... // beginPass(), set pipeline, etc., and then: for (int i = 0; i < N; ++i) { QRhiCommandBuffer::DynamicOffset dynOfs[] = { { 0, i * ONE_UBUF_SIZE } }; cb->setShaderResources(srb, 1, dynOfs); cb->draw(36); }
QRhiResourceUpdateBatch,QRhi,QRhiCommandBufferも参照 。
メンバ型ドキュメント
enum QRhiBuffer::Type
バッファリソースのストレージタイプを指定します。
定数 | 値 | 説明 |
---|---|---|
QRhiBuffer::Immutable | 0 | 最初のアップロード以降、データが変更されないことを示します。このようなバッファリソースは通常、デバイスのローカル(GPU)メモリに置かれます(該当するシステム上)。新しいデータをアップロードすることは可能ですが、コストがかかる場合があります。アップロードは通常、別個の、ホストから見えるステージング・バッファにコピーすることで行われ、そこからGPUバッファ間のコピーが実際のGPU専用バッファに発行されます。 |
QRhiBuffer::Static | 1 | データ変更頻度が低いことを示します。通常、該当する場合、デバイスローカル(GPU)メモリに置かれます。ホストから見えるステージングバッファがアップロードに使用されるバックエンドでは、ステージングバッファは、Immutableの場合とは異なり、このタイプのために保持されます。頻繁な更新、特に連続したフレームでの更新は避けるべきです。 |
QRhiBuffer::Dynamic | 2 | データが頻繁に変更されることを示します。大きなバッファには推奨されない。通常、グラフィックスパイプラインを停止させることなく変更できるようにするために、2つのコピーでホストの可視メモリによってバックアップされます。二重バッファリングはアプリケーションに対して透過的に管理され、APIではいかなる形でも公開されない。これは、UniformBuffer を使用するバッファに推奨される型であり、バックエンドによっては唯一可能な型でもあります。 |
enum QRhiBuffer::UsageFlag
flags QRhiBuffer::UsageFlags
バッファの使用方法を指定するフラグ。
定数 | 値 | 説明 |
---|---|---|
QRhiBuffer::VertexBuffer | 1 << 0 | 頂点バッファ。これにより、setVertexInput() でQRhiBuffer を使用できる。 |
QRhiBuffer::IndexBuffer | 1 << 1 | インデックスバッファ。これにより、QRhiBuffer をsetVertexInput() で使用できます。 |
QRhiBuffer::UniformBuffer | 1 << 2 | ユニフォーム・バッファ(コンスタント・バッファとも呼ばれる)。これにより、QRhiBuffer をUniformBuffer と組み合わせて使用することができる。NonDynamicUniformBuffers がサポートされていないと報告された場合、この使用法は Dynamic 型との組み合わせのみ可能です。 |
QRhiBuffer::StorageBuffer | 1 << 3 | ストレージバッファ。これにより、QRhiBuffer をBufferLoad 、BufferStore 、BufferLoadStore と組み合わせて使用することができます。この使用法は、Immutable または Static タイプと組み合わせることができ、Compute feature がサポートされていると報告された場合にのみ使用できます。 |
UsageFlags型はQFlags<UsageFlag>のtypedefである。UsageFlagの値のORの組み合わせを格納する。
メンバ関数のドキュメント
[virtual]
char *QRhiBuffer::beginFullDynamicBufferUpdateForCurrentFrame()
ホスト可視バッファデータを持つメモリブロックへのポインタを返します。
これは、フレームごとにその内容全体(または、少なくとも現在のフレームでシェーダによって読み取られるすべての領域)が変更され、QRhiResourceUpdateBatch-ベースの更新メカニズムがデータコピーの量のために重すぎると見られる中型から大型のダイナミックユニフォームバッファのためのショートカットです。
このバッファに依存するレンダーまたは計算パスを記録する前に、この関数の呼び出しに続いて、最終的に endFullDynamicUniformBufferUpdateForCurrentFrame() を呼び出す必要があります。
警告 このメソッドによるデータの更新は、QRhiResourceUpdateBatch ベースの更新およびリードバックとは互換性がありません。同じバッファに対して2つの更新モデルを組み合わせようとすると、予期しない動作が発生する可能性があります。同様に、この直接の方法で更新されたデータは、バックエンドによってはreadBackBuffer operations から見えないかもしれません。
警告 そうでない場合、リソースの2重または3重のバッファリングを行うバックエンドは、予期しない動作になる可能性があります。
警告 バックエンドによっては、この関数を呼び出すとバッファの以前の内容が失われる戦略を選択する場合があるためです。データは、現在準備中のフレームでシェーダによって読み込まれるすべての領域に書き込まれなければなりません。
警告 この関数は、フレームを記録するとき、つまりQRhi::beginFrame() とQRhi::endFrame() の間にのみ呼び出すことができます。
警告 この関数はDynamicバッファでのみ呼び出すことができます。
[pure virtual]
bool QRhiBuffer::create()
対応するネイティブ・グラフィックス・リソースを作成する。以前の create() で対応するdestroy() がなかったためにすでにリソースが存在する場合は、destroy() が暗黙的に最初に呼び出されます。
グラフィックス操作に成功した場合はtrue
を、失敗した場合はfalse
を返します。返り値に関係なく、destroy() を呼び出すことは常に安全です。
[virtual]
void QRhiBuffer::endFullDynamicBufferUpdateForCurrentFrame()
beginFullDynamicBufferUpdateForCurrentFrame() から返されたメモリ・ブロックのバッファ・データの内容がすべて更新されたときに呼び出される。
[virtual]
QRhiBuffer::NativeBuffer QRhiBuffer::nativeBuffer()
このバッファの基盤となるネイティブリソースを返します。基盤となるネイティブリソースの公開がバックエンドでサポートされていない場合、返される値は空になります。
QRhiBuffer は、type() やQRhi バックエンドによって、複数のネイティブバッファオブジェクトを持つことがあります。この場合、返される構造体のobjects配列に、ネイティブバッファオブジェクトの数を指定するslotCountとともに、それらすべてが返されます。recording a frame,QRhi::currentFrameSlot() を使用することで、記録中のフレーム内でこのQRhiBuffer から読み書きする操作に対して、QRhi がどのネイティブバッファを使用しているかを判断することができます。
場合によっては、QRhiBuffer はネイティブバッファオブジェクトにまったくバックアップされません。この場合、slotCountは0に設定され、有効なネイティブオブジェクトは返されません。これはエラーではなく、特定のバックエンドが特定の型や用途のQRhiBuffersに対してネイティブバッファを使用しない場合に完全に有効です。
注意: QRhi バックエンドは様々なバッファ更新ストラテジを採用している可能性があることに注意してください。画像データのアップロードが常にコマンドバッファにバッファから画像への(または類似の)コピーコマンドを記録することを意味するテクスチャとは異なり、バッファ、特にDynamicおよびUniformBuffer ものは、多くの異なる方法で動作することができます。例えば、UniformBuffer の使用タイプを持つQRhiBuffer は、ユニフォームバッファが使用されていないか、特定のバックエンドやグラフィックAPIでサポートされていない場合、ネイティブバッファオブジェクトにまったくバックアップされていない可能性があります。また、データがバッファに書き込まれる方法や、使用されるバッキングメモリのタイプにも違いがあります。ホストの可視メモリでバックアップされたバッファの場合、この関数を呼び出すと、保留中のホストからの書き込みが、返されたすべてのネイティブバッファに対して実行されることが保証されます。
QRhi::currentFrameSlot() およびQRhi::FramesInFlightも参照のこと 。
[override virtual]
QRhiResource::Type QRhiBuffer::resourceType() const
再実装:QRhiResource::resourceType() const.
リソース型を返します。
void QRhiBuffer::setSize(quint32 sz)
バッファのサイズをバイト単位で設定する。サイズは通常QRhi::newBuffer() で指定されるので、この関数はサイズを変更する必要がある場合にのみ使用される。他のセッターと同様に、サイズの変更はcreate() を呼び出したときにのみ有効になります。すでに作成されているバッファについては、以前のネイティブリソースを解放し、新しいバッファを作成することになります。
バックエンドは、アライメント要件を満たすために、sz より大きなバッファを割り当てることができます。これはアプリケーションからは見えないようになっており、size() は常にsz で要求されたサイズを報告する。
size()も参照のこと 。
void QRhiBuffer::setType(QRhiBuffer::Type t)
バッファの型をt に設定する。
type()も参照のこと 。
void QRhiBuffer::setUsage(QRhiBuffer::UsageFlags u)
バッファの使用フラグをu に設定する。
usage()も参照のこと 。
quint32 QRhiBuffer::size() const
バッファのサイズをバイト数で返す。
これは常にsetSize() またはQRhi::newBuffer() に渡された値である。内部的には、基礎となるグラフィックス API が要求する場合は、ネイティブバッファの方が大きくなることがあります。
setSize()も参照 。
QRhiBuffer::Type QRhiBuffer::type() const
バッファの型を返す。
setType()も参照 。
QRhiBuffer::UsageFlags QRhiBuffer::usage() const
バッファの使用フラグを返す。
setUsage()も参照 。
© 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.