QRhiBuffer Class
頂点、インデックス、またはユニフォーム(定数)バッファリソース。詳細...
Header: | #include <rhi/qrhi.h> |
CMake: | find_package(Qt6 REQUIRED COMPONENTS Gui) target_link_libraries(mytarget PRIVATE Qt6::GuiPrivate) |
qmake: | QT += gui-private |
Since: | Qt 6.6 |
Inherits: | 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 | 頂点バッファ。これにより、QRhiBuffer をsetVertexInput() で使用することができます。 |
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() の間にのみ呼び出すことができます。
警告 この関数は、ダイナミックバッファに対してのみ呼び出すことができます。
[pure virtual]
bool QRhiBuffer::create()
対応するネイティブグラフィックリソースを作成します。対応するdestroy() がない以前の create() によって既にリソースが存在する場合、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() も参照して ください。
©2024The Qt Company Ltd. 本文書に含まれる文書の著作権は、それぞれの所有者に帰属します。 ここで提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。