QRhiBuffer Class
Vertex-, Index- oder Uniform- (konstante) Pufferressource. Mehr...
| Header: | #include <rhi/qrhi.h> |
| CMake: | find_package(Qt6 REQUIRED COMPONENTS GuiPrivate) target_link_libraries(mytarget PRIVATE Qt6::GuiPrivate) |
| qmake: | QT += gui-private |
| Seit: | Qt 6.6 |
| Erbt von: | QRhiResource |
Öffentliche Typen
| struct | NativeBuffer |
| enum | Type { Immutable, Static, Dynamic } |
| enum | UsageFlag { VertexBuffer, IndexBuffer, UniformBuffer, StorageBuffer, IndirectBuffer } |
| flags | UsageFlags |
Öffentliche Funktionen
| 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 |
Neu implementierte öffentliche Funktionen
| virtual QRhiResource::Type | resourceType() const override |
Ausführliche Beschreibung
Hinweis: Dies ist eine RHI-API mit eingeschränkten Kompatibilitätsgarantien. Weitere Informationen finden Sie unter QRhi.
Ein QRhiBuffer kapselt null, ein oder mehrere native Pufferobjekte (wie z. B. ein „ VkBuffer “ oder „ MTLBuffer “). Bei einigen Grafik-APIs und Backends verwenden bestimmte Puffertypen möglicherweise überhaupt kein natives Pufferobjekt (z. B. OpenGL, wenn keine Uniform-Pufferobjekte verwendet werden), was für den Nutzer der QRhiBuffer-API jedoch transparent ist. Ebenso bleibt die Tatsache, dass manche Puffertypen im Hintergrund zwei oder drei native Puffer verwenden, um eine effiziente Aktualisierung des Inhalts pro Frame zu ermöglichen, ohne die GPU-Pipeline zu blockieren, für die Anwendungen und Bibliotheken weitgehend unsichtbar.
Eine QRhiBuffer-Instanz wird immer durch den Aufruf von ` the QRhi's newBuffer() function` erstellt. Dabei werden keine nativen Grafikressourcen angelegt. Um dies zu tun, rufen Sie ` create()` auf, nachdem Sie die entsprechenden Optionen wie Typ, Verwendungsflags und Größe festgelegt haben, obwohl diese in den meisten Fällen bereits auf der Grundlage der an ` newBuffer()` übergebenen Argumente festgelegt sind.
Anwendungsbeispiel
So erstellen Sie einen Uniform-Puffer für einen Shader, bei dem der GLSL-Uniform-Block ein einzelnes „ mat4 “-Element enthält, und aktualisieren den Inhalt:
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() callEin Beispiel für die Erstellung eines Puffers mit Vertex-Daten:
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() callEin Index-Puffer:
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() callHäufige Muster
Ein Aufruf von ` create()` zerstört alle vorhandenen nativen Ressourcen, sofern zuvor ` create()` erfolgreich aufgerufen wurde. Wenn diese nativen Ressourcen noch von einem laufenden Frame genutzt werden (d. h., es besteht die Möglichkeit, dass sie noch von der GPU gelesen werden), wird die Löschung dieser Ressourcen automatisch aufgeschoben. Daher ist das folgende Muster sehr verbreitet und praktisch, um die Größe eines bereits initialisierten Puffers sicher zu vergrößern. In der Praxis werden dabei die zugrunde liegenden nativen Ressourcen verworfen und ein komplett neuer Satz erstellt; es handelt sich also nicht unbedingt um einen ressourcenschonenden Vorgang, aber er ist praktischer und immer noch schneller als die Alternativen, da durch das Nicht-Löschen des „ buf “-Objekts selbst alle Verweise darauf in anderen Datenstrukturen gültig bleiben (z. B. in jedem „ QRhiShaderResourceBinding “, von dem aus auf den „QRhiBuffer“ verwiesen wird).
if (buf->size() < newSize) {
buf->setSize(newSize);
if (!buf->create()) { error(); }
}
// continue using buf, fill it with new dataBei der Arbeit mit Uniform-Buffern ist es aus Effizienzgründen manchmal erforderlich, Daten für mehrere Draw-Aufrufe in einem einzigen Buffer zu kombinieren. Beachten Sie dabei die Ausrichtungsanforderungen: Bei einigen Grafik-APIs müssen Offsets für einen Uniform-Buffer auf 256 Byte ausgerichtet sein. Dies gilt sowohl für ` QRhiShaderResourceBinding ` als auch für die dynamischen Offsets, die an ` setShaderResources()` übergeben werden. Verwenden Sie die Funktionen ` ubufAlignment()` und ` ubufAligned()`, um portablen Code zu erstellen. Als Beispiel folgt hier ein Entwurf für die Ausgabe mehrerer (N) Draw-Calls mit derselben Pipeline und Geometrie, jedoch mit unterschiedlichen Daten in den Uniform-Buffern, die am Bindepunkt 0 bereitgestellt werden. Dabei wird davon ausgegangen, dass der Buffer über ` uniformBufferWithDynamicOffset()` bereitgestellt wird, was die Übergabe einer ` QRhiCommandBuffer::DynamicOffset `-Liste an ` setShaderResources()` ermöglicht.
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);
}Siehe auch QRhiResourceUpdateBatch, QRhi und QRhiCommandBuffer.
Dokumentation zu Mitgliedstypen
enum QRhiBuffer::Type
Legt den Speichertyp der Pufferressource fest.
| Konstante | Wert | Beschreibung |
|---|---|---|
QRhiBuffer::Immutable | 0 | Gibt an, dass sich die Daten nach dem ersten Upload voraussichtlich nie mehr ändern werden. Im Hintergrund werden solche Pufferressourcen in der Regel im gerätelokalen (GPU-)Speicher abgelegt (auf Systemen, auf denen dies möglich ist). Das Hochladen neuer Daten ist möglich, kann jedoch rechenintensiv sein. Der Upload erfolgt in der Regel durch Kopieren in einen separaten, für den Host sichtbaren Staging-Puffer, von dem aus eine GPU-Puffer-zu-Puffer-Kopie in den eigentlichen, ausschließlich auf der GPU befindlichen Puffer durchgeführt wird. |
QRhiBuffer::Static | 1 | Gibt an, dass sich die Daten voraussichtlich nur selten ändern werden. Wird in der Regel im geräteinternen (GPU-)Speicher abgelegt, sofern dies möglich ist. Auf Backends, auf denen für das Hochladen für den Host sichtbare Staging-Puffer verwendet werden, bleiben die Staging-Puffer für diesen Typ – anders als bei „Immutable“ – erhalten, sodass nachfolgende Uploads keine Leistungseinbußen erleiden. Häufige Aktualisierungen, insbesondere in aufeinanderfolgenden Frames, sollten vermieden werden. |
QRhiBuffer::Dynamic | 2 | Gibt an, dass sich die Daten voraussichtlich häufig ändern werden. Nicht empfohlen für große Puffer. Wird in der Regel durch zwei Kopien im für den Host sichtbaren Speicher abgesichert, um Änderungen zu ermöglichen, ohne die Grafikpipeline zu blockieren. Die Doppelpufferung wird für die Anwendungen transparent verwaltet und wird hier in der API in keiner Form offengelegt. Dies ist der empfohlene und bei einigen Backends der einzig mögliche Typ für Puffer mit „ UniformBuffer “-Verwendung. |
enum QRhiBuffer::UsageFlag
flags QRhiBuffer::UsageFlags
Flag-Werte zur Festlegung, wie der Puffer verwendet werden soll.
| Konstante | Wert | Beschreibung |
|---|---|---|
QRhiBuffer::VertexBuffer | 1 << 0 | Vertex-Puffer. Dies ermöglicht die Verwendung des „ QRhiBuffer “ in „ setVertexInput()“. |
QRhiBuffer::IndexBuffer | 1 << 1 | Indexpuffer. Dies ermöglicht die Verwendung des „ QRhiBuffer “ in der Funktion „ setVertexInput()“. |
QRhiBuffer::UniformBuffer | 1 << 2 | Uniform-Puffer (auch als Konstantenpuffer bezeichnet). Damit kann „ QRhiBuffer “ in Kombination mit „ UniformBuffer “ verwendet werden. Wenn „ NonDynamicUniformBuffers “ als nicht unterstützt gemeldet wird, kann diese Verwendung nur mit dem Typ „Dynamic“ kombiniert werden. |
QRhiBuffer::StorageBuffer | 1 << 3 | Speicherpuffer. Dies ermöglicht die Verwendung des „ QRhiBuffer “ in Kombination mit „ BufferLoad “, „ BufferStore “ oder „ BufferLoadStore “. Diese Verwendung kann nur mit den Typen „Immutable“ oder „Static“ kombiniert werden und ist nur verfügbar, wenn der „ Compute feature “ als unterstützt gemeldet wird. |
QRhiBuffer::IndirectBuffer (since Qt 6.12) | 1 << 4 | Indirekter Zeichnungspuffer. Dies ermöglicht die Verwendung von ` QRhiBuffer ` in ` drawIndirect()` und ` drawIndexedIndirect()`. Diese Verwendung kann mit den Typen „Immutable“ oder „Static“ kombiniert werden. Die Kombination mit „Dynamic“ wird unter D3D11 nicht unterstützt, wo ` create()` fehlschlägt. Diese Verwendung kann auf Backends, die „ compute shaders “ unterstützen, auch mit „StorageBuffer“ kombiniert werden, wodurch indirekte Zeichnungsbefehle von Compute-Shadern generiert und von indirekten Zeichnungsaufrufen verwendet werden können. |
Der Typ „UsageFlags“ ist ein typedef für „QFlags<UsageFlag>“. Er speichert eine OR-Kombination von „UsageFlag“-Werten.
Dokumentation der Mitgliedsfunktionen
[virtual] char *QRhiBuffer::beginFullDynamicBufferUpdateForCurrentFrame()
Gibt einen Zeiger auf einen Speicherblock mit den für den Host sichtbaren Pufferdaten zurück.
Dies ist eine Abkürzung für mittelgroße bis große dynamische Uniform-Puffer, deren gesamter Inhalt (oder zumindest alle Bereiche, die von den Shadern im aktuellen Frame gelesen werden) in jedem Frame geändert wird und bei denen der auf „ QRhiResourceUpdateBatch “ basierende Aktualisierungsmechanismus aufgrund des damit verbundenen Datenkopieraufwands als zu ressourcenintensiv angesehen wird.
Auf den Aufruf dieser Funktion muss schließlich ein Aufruf von `endFullDynamicUniformBufferUpdateForCurrentFrame()` folgen, bevor ein Render- oder Compute-Pass aufgezeichnet wird, der auf diesem Puffer basiert.
Warnung: Die Aktualisierung von Daten über diese Methode ist nicht kompatibel mit auf „ QRhiResourceUpdateBatch “ basierenden Aktualisierungen und Rücklesevorgängen. Beim Versuch, die beiden Aktualisierungsmodelle für denselben Puffer zu kombinieren, kann es zu unerwartetem Verhalten kommen. Ebenso sind die auf diese direkte Weise aktualisierten Daten je nach Backend möglicherweise für „ readBackBuffer operations “ nicht sichtbar.
Warnung: Bei der Aktualisierung von Pufferdaten über diese Methode muss die Aktualisierung in jedem Frame erfolgen; andernfalls kann es bei Backends, die eine doppelte oder dreifache Pufferung von Ressourcen durchführen, zu unerwartetem Verhalten kommen.
Warnung: Teilaktualisierungen sind bei diesem Ansatz nicht möglich, da manche Backends eine Strategie verfolgen, bei der der bisherige Inhalt des Puffers beim Aufruf dieser Funktion verloren geht. Daten müssen in alle Bereiche geschrieben werden, die von Shadern in dem gerade vorbereiteten Frame gelesen werden.
Warnung: Diese Funktion kann nur während der Aufzeichnung eines Frames aufgerufen werden, also zwischen ` QRhi::beginFrame()` und ` QRhi::endFrame()`.
Warnung: Diese Funktion kann nur für dynamische Puffer aufgerufen werden.
[pure virtual] bool QRhiBuffer::create()
Erstellt die entsprechenden nativen Grafikressourcen. Wenn aufgrund eines früheren Aufrufs von `create()` bereits Ressourcen vorhanden sind, für die kein entsprechender Aufruf von ` destroy()` vorliegt, wird zunächst implizit ` destroy()` aufgerufen.
Gibt bei Erfolg ` true ` zurück, bei einem Fehler bei einer Grafikoperation ` false `. Unabhängig vom Rückgabewert ist der Aufruf von ` destroy()` immer sicher.
[virtual] void QRhiBuffer::endFullDynamicBufferUpdateForCurrentFrame()
Wird aufgerufen, wenn der gesamte Inhalt der Pufferdaten in dem von ` beginFullDynamicBufferUpdateForCurrentFrame()` zurückgegebenen Speicherblock aktualisiert wurde.
[virtual] QRhiBuffer::NativeBuffer QRhiBuffer::nativeBuffer()
Gibt die zugrunde liegenden nativen Ressourcen für diesen Puffer zurück. Der zurückgegebene Wert ist leer, wenn das Backend die Offenlegung der zugrunde liegenden nativen Ressourcen nicht unterstützt.
Ein „ QRhiBuffer “ kann von mehreren nativen Pufferobjekten gestützt werden, abhängig von der verwendeten Funktion „ type()“ und dem Backend „ QRhi “. Ist dies der Fall, werden alle diese Objekte im Array „objects“ der zurückgegebenen Struktur zurückgegeben, wobei „slotCount“ die Anzahl der nativen Pufferobjekte angibt. Mit „ recording a frame “ und „ QRhi::currentFrameSlot()“ lässt sich ermitteln, welche der nativen Puffer „ QRhi “ für Lese- oder Schreibvorgänge an diesem „ QRhiBuffer “ innerhalb des gerade aufgezeichneten Frames verwendet.
In einigen Fällen wird ein ` QRhiBuffer ` überhaupt nicht durch ein natives Pufferobjekt gestützt. In diesem Fall wird `slotCount` auf 0 gesetzt und es werden keine gültigen nativen Objekte zurückgegeben. Dies ist kein Fehler und völlig zulässig, wenn ein bestimmtes Backend für `QRhiBuffers` mit bestimmten Typen oder Verwendungszwecken keine nativen Puffer verwendet.
Hinweis: Beachten Sie , dass „ QRhi “-Backends verschiedene Strategien zur Pufferaktualisierung verwenden können. Im Gegensatz zu Texturen, bei denen das Hochladen von Bilddaten immer bedeutet, dass ein Befehl zum Kopieren vom Puffer ins Bild (oder ähnliches) in den Befehlspuffer geschrieben wird, können Puffer – insbesondere „Dynamic“- und „ UniformBuffer “-Puffer – auf viele verschiedene Arten funktionieren. Beispielsweise wird ein „ QRhiBuffer “ mit dem Verwendungszweck „ UniformBuffer “ möglicherweise gar nicht von einem nativen Pufferobjekt gestützt, wenn Uniform-Puffer von einem bestimmten Backend und einer bestimmten Grafik-API nicht verwendet oder unterstützt werden. Es gibt zudem Unterschiede hinsichtlich der Art und Weise, wie Daten in den Puffer geschrieben werden, sowie hinsichtlich der Art des verwendeten Speichermediums. Bei Puffern, die durch für den Host sichtbaren Speicher gestützt werden, garantiert der Aufruf dieser Funktion, dass ausstehende Schreibvorgänge des Hosts für alle zurückgegebenen nativen Puffer ausgeführt werden.
Siehe auch QRhi::currentFrameSlot() und QRhi::FramesInFlight.
[override virtual] QRhiResource::Type QRhiBuffer::resourceType() const
Implementiert neu: ` QRhiResource::resourceType()` const.
Gibt den Ressourcentyp zurück.
void QRhiBuffer::setSize(quint32 sz)
Legt die Größe des Puffers in Byte fest. Die Größe wird normalerweise in ` QRhi::newBuffer()` angegeben, sodass diese Funktion nur verwendet wird, wenn die Größe geändert werden muss. Wie bei anderen Setter-Funktionen wird die Größe erst beim Aufruf von ` create()` wirksam; bei bereits erstellten Puffern bedeutet dies, dass die bisherige native Ressource freigegeben und im Hintergrund eine neue erstellt wird.
Backends können Puffer zuweisen, die größer sind als in ` sz ` angegeben, um Ausrichtungsanforderungen zu erfüllen. Dies bleibt für die Anwendungen verborgen, und ` size()` meldet stets die in ` sz` angeforderte Größe.
Siehe auch ` size()`.
void QRhiBuffer::setType(QRhiBuffer::Type t)
Setzt den Typ des Puffers auf „ t “.
Siehe auch ` type()`.
void QRhiBuffer::setUsage(QRhiBuffer::UsageFlags u)
Setzt die Nutzungsflags des Puffers auf „ u “.
Siehe auch ` usage()`.
quint32 QRhiBuffer::size() const
Gibt die Größe des Puffers in Byte zurück.
Dies ist immer der Wert, der an ` setSize()` oder ` QRhi::newBuffer()` übergeben wurde. Intern können die nativen Puffer größer sein, wenn dies von der zugrunde liegenden Grafik-API gefordert wird.
Siehe auch ` setSize()`.
QRhiBuffer::Type QRhiBuffer::type() const
Gibt den Puffertyp zurück.
Siehe auch „ setType()“.
QRhiBuffer::UsageFlags QRhiBuffer::usage() const
Gibt die Nutzungsflags des Puffers zurück.
Siehe auch ` setUsage()`.
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.