QRhi Class
Beschleunigte 2D/3D-Grafik-API-Abstraktion. Mehr...
Kopfzeile: | #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 |
- Liste aller Mitglieder, einschließlich geerbter Mitglieder
- QRhi ist Teil von Rendering in 3D.
Öffentliche Typen
enum | BeginFrameFlag { } |
flags | BeginFrameFlags |
enum | EndFrameFlag { SkipPresent } |
flags | EndFrameFlags |
enum | Feature { MultisampleTexture, MultisampleRenderBuffer, DebugMarkers, Timestamps, Instancing, …, ResolveDepthStencil } |
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, …, MaxVertexOutputs } |
Öffentliche Funktionen
~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() |
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 | runCleanup() |
void | setPipelineCacheData(const QByteArray &data) |
QRhiStats | statistics() const |
QList<int> | supportedSampleCounts() const |
QThread * | thread() const |
int | ubufAligned(int v) const |
int | ubufAlignment() const |
Statische öffentliche Mitglieder
const char * | backendName(QRhi::Implementation impl) |
QRhi * | create(QRhi::Implementation impl, QRhiInitParams *params, QRhi::Flags flags = {}, QRhiNativeHandles *importDevice = 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) |
Verwandte Nicht-Mitglieder
(since 6.7) | QRhiShaderResourceBindingSet |
Detaillierte Beschreibung
Das Qt Rendering Hardware Interface ist eine Abstraktion für hardwarebeschleunigte Grafik-APIs, wie OpenGL, OpenGL ES, Direct3D, Metal und Vulkan.
Warnung: Die QRhi-Familie von Klassen im Qt Gui-Modul, einschließlich QShader und QShaderDescription, bietet begrenzte Kompatibilitätsgarantien. Es gibt keine Quell- oder Binärkompatibilitätsgarantien für diese Klassen, d. h. die API funktioniert garantiert nur mit der Qt-Version, mit der die Anwendung entwickelt wurde. Quellcode-inkompatible Änderungen sollen jedoch auf ein Minimum beschränkt werden und werden nur in kleineren Versionen (6.7, 6.8 usw.) vorgenommen. Um diese Klassen in einer Anwendung zu verwenden, verlinken Sie auf Qt::GuiPrivate
(wenn Sie CMake verwenden) und fügen Sie die Header mit dem Präfix rhi
ein, zum Beispiel #include <rhi/qrhi.h>
.
Jede QRhi-Instanz wird von einem Backend für eine bestimmte Grafik-API unterstützt. Die Auswahl des Backends ist eine Entscheidung zur Laufzeit und liegt bei der Anwendung oder Bibliothek, die die QRhi-Instanz erstellt. Einige Backends sind auf mehreren Plattformen verfügbar (OpenGL, Vulkan, Null), während APIs, die für eine bestimmte Plattform spezifisch sind, nur verfügbar sind, wenn sie auf der betreffenden Plattform ausgeführt werden (Metal auf macOS/iOS, Direct3D auf Windows).
Die verfügbaren Backends sind derzeit:
- OpenGL 2.1 / OpenGL ES 2.0 oder neuere Versionen. Einige Erweiterungen und neuere Funktionen der Kernspezifikation werden genutzt, wenn sie vorhanden sind, zum Beispiel um Multisample-Framebuffer oder Compute-Shader zu ermöglichen. Der Betrieb in Kernprofilkontexten wird ebenfalls unterstützt. Falls erforderlich, können Anwendungen zur Laufzeit die feature flags abfragen, um nach Funktionen zu suchen, die in dem OpenGL-Kontext, der dem QRhi zugrunde liegt, nicht unterstützt werden. Das OpenGL-Backend baut auf QOpenGLContext, QOpenGLFunctions und der zugehörigen plattformübergreifenden Infrastruktur des Moduls Qt GUI auf.
- Direct3D 11.2 und neuer (mit DXGI 1.3 und neuer), mit Shader Model 5.0 oder neuer. Wenn die D3D-Laufzeitumgebung keine Unterstützung für 11.2-Funktionen oder Shader Model 5.0 bietet, schlägt die Initialisierung mit einem beschleunigten Grafikgerät fehl, aber die Verwendung des Softwareadapters ist immer noch eine Option.
- Direct3D 12 auf Windows 10 Version 1703 und neuer, mit Shader Model 5.0 oder neuer. Qt erfordert das Vorhandensein von ID3D12Device2, daher die Anforderung von mindestens Version 1703 von Windows 10. Das D3D12-Gerät wird standardmäßig mit der Angabe eines Mindest-Feature-Levels von
D3D_FEATURE_LEVEL_11_0
erstellt. - Metal 1.2 oder neuere Version.
- Vulkan 1.0 oder neuer, optional unter Verwendung einiger Funktionen der Stufe Vulkan 1.1.
- Null, ein "Dummy"-Backend, das überhaupt keine Grafikaufrufe ausgibt.
Damit Shader-Code in Qt-Anwendungen und -Bibliotheken einmal geschrieben werden kann, wird erwartet, dass alle Shader in einer einzigen Sprache geschrieben werden, die dann in SPIR-V kompiliert wird. Daraus werden dann Versionen für verschiedene Shading-Sprachen generiert, zusammen mit Reflexionsinformationen (Eingänge, Ausgänge, Shader-Ressourcen). Dies wird dann in einfach und effizient serialisierbare QShader Instanzen gepackt. Die Compiler und Werkzeuge zur Erzeugung solcher Shader sind nicht Teil von QRhi und dem Modul Qt GUI, wohl aber die Kernklassen zur Verwendung solcher Shader, QShader und QShaderDescription. Die APIs und Werkzeuge zur Durchführung der Kompilierung und Übersetzung sind Teil des Qt Shader Tools Moduls.
Im RHI Window Example finden Sie ein einführendes Beispiel für die Erstellung einer portablen, plattformübergreifenden Anwendung, die mit QRhi ein beschleunigtes 3D-Rendering auf einer QWindow durchführt.
Ein Eindruck von der API
Um einen schnellen Einblick in die API anhand eines kurzen, aber vollständigen Beispiels zu geben, das keine fensterbezogene Einrichtung beinhaltet, folgt eine vollständige, lauffähige plattformübergreifende Anwendung, die 20 Bilder außerhalb des Bildschirms rendert und die erzeugten Bilder in Dateien speichert, nachdem sie die Texturinhalte von der GPU zurückgelesen hat. Ein Beispiel, das auf dem Bildschirm gerendert wird und die Einrichtung einer QWindow und einer Swapchain beinhaltet, finden Sie im RHI Window Example.
Der Kürze halber wird die Initialisierung des QRhi plattformabhängig durchgeführt: Der Beispielcode hier wählt Direct 3D 12 unter Windows, Metal unter macOS und iOS und ansonsten Vulkan. OpenGL und Direct 3D 11 werden von dieser Anwendung nie verwendet, aber die Unterstützung dafür könnte mit ein paar zusätzlichen Zeilen eingeführt werden.
#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, ¶ms));#elif QT_CONFIG(metal) QRhiMetalInitParams params; rhi.reset(QRhi::create(QRhi::Metal, ¶ms));#elif QT_CONFIG(vulkan)inst.setExtensions(QRhiVulkanInitParams::preferredInstanceExtensions()); if (inst.create()) { QRhiVulkanInitParams params; params.inst = &inst; rhi.reset(QRhi::create(QRhi::Vulkan, ¶ms)); } else { qFatal("Failed to create Vulkan instance"); }#endif if (rhi) qDebug() << rhi->backendName() << rhi->driverInfo(); sonst qFatal("Failed to initialize RHI"); float rotation = 0.0f; float opacity = 1.0f; int opacityDir = 1; std::unique_ptr<QRhiTexture> tex(rhi->neueTextur(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 up, 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->neuerPuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData))); vbuf->create(); std::unique_ptr<QRhiBuffer> ubuf(rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 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 &name) { QFile f(name); return f.open(QIODevice::ReadOnly) ? QShader::fromSerialized(f.readAll()) : QShader(); }; ps->setShaderStages({ { QRhiShaderStage::Vertex, getShader(QLatin1String("color.vert.qsb")) },{ QRhiShaderStage::Fragment, 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->istYUpInFramebuffer()) image = image.mirrored(); image.save(QString::asprintf("frame%d.png", frame)); } return 0; }
Das Ergebnis der Anwendung sind 20 PNG
Bilder (frame0.png - frame19.png). Diese enthalten ein rotierendes Dreieck mit unterschiedlicher Deckkraft vor einem grünen Hintergrund.
Es wird erwartet, dass die Vertex- und Fragment-Shader verarbeitet und in .qsb
Dateien verpackt werden. Der Vulkan-kompatible GLSL-Quellcode ist der folgende:
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; }
farbe.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); }
Um diese Shader manuell zu kompilieren und in eine Reihe von Zielen (SPIR-V, HLSL, MSL, GLSL) zu transpilieren und die .qsb
Dateien zu erzeugen, die die Anwendung zur Laufzeit lädt, führen Sie qsb --qt6 color.vert -o color.vert.qsb
und qsb --qt6 color.frag -o color.frag.qsb
aus. Alternativ dazu bietet das Qt Shader Tools Modul eine Build-System-Integration für CMake, die qt_add_shaders()
CMake-Funktion, die das Gleiche zur Build-Zeit erreichen kann.
Entwurfsgrundlagen
Ein QRhi kann nicht direkt instanziiert werden. Verwenden Sie stattdessen die Funktion create(). Löschen Sie die QRhi-Instanz normalerweise, um das Grafikgerät freizugeben.
Ressourcen
Instanzen von Klassen, die von QRhiResource abgeleitet sind, wie z. B. QRhiBuffer, QRhiTexture, usw., kapseln null, eine oder mehrere native Grafikressourcen. Instanzen solcher Klassen werden immer über die new
Funktionen von QRhi erstellt, z. B. newBuffer(), newTexture(), newTextureRenderTarget(), newSwapChain().
QRhiBuffer *vbuf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData)); if (!vbuf->create()) { error(); } // ... delete vbuf;
- Der Rückgabewert von Funktionen wie newBuffer() gehört immer dem Aufrufer.
- Bei der Erstellung einer Instanz einer QRhiResource Unterklasse werden niemals eigene Ressourcen zugewiesen oder initialisiert. Dies geschieht nur beim Aufruf der Funktion
create()
einer Unterklasse, zum Beispiel QRhiBuffer::create() oder QRhiTexture::create(). - Die Ausnahmen sind QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor(), QRhiSwapChain::newCompatibleRenderPassDescriptor() und QRhiRenderPassDescriptor::newCompatibleRenderPassDescriptor(). Für diese gibt es keine
create()
Operation und das zurückgegebene Objekt ist sofort aktiv. - Die Ressourcenobjekte selbst werden als unveränderlich behandelt: Sobald eine Ressource create() aufgerufen wurde, hat die Änderung von Parametern über die Setter, wie z. B. QRhiTexture::setPixelSize(), keine Auswirkungen, es sei denn, die zugrunde liegende native Ressource wird freigegeben und
create()
erneut aufgerufen. Weitere Informationen zur Wiederverwendung von Ressourcen finden Sie in den folgenden Abschnitten. - Die zugrundeliegenden nativen Ressourcen werden für die Freigabe durch den QRhiResource destructor oder durch den Aufruf von QRhiResource::destroy() eingeplant. Backends stellen Freigabeanfragen oft in eine Warteschlange und verschieben deren Ausführung auf einen unbestimmten Zeitpunkt, was den Anwendungen verborgen bleibt. Auf diese Weise müssen sich die Anwendungen nicht um die Freigabe nativer Ressourcen kümmern, die möglicherweise noch von einem Frame im Flug verwendet werden.
- Beachten Sie, dass dies nicht bedeutet, dass ein QRhiResource innerhalb eines Frames (d.h. in einem beginFrame() - endFrame() Abschnitt) beliebig zerstört() oder gelöscht werden kann. Generell gilt, dass alle referenzierten QRhiResource Objekte unverändert bleiben müssen, bis der Rahmen durch den Aufruf von endFrame() übergeben wird. Um dies zu erleichtern, wird QRhiResource::deleteLater() als Hilfsmittel bereitgestellt.
Befehlspuffer und verzögerte Befehlsausführung
Unabhängig vom Design und den Fähigkeiten der zugrundeliegenden Grafik-API, implementieren alle QRhi-Backends ein gewisses Maß an Befehlspuffern. Keine QRhiCommandBuffer Funktion gibt einen nativen Bind- oder Zeichenbefehl (wie z.B. glDrawElements
) direkt aus. Befehle werden immer in einer Warteschlange aufgezeichnet, entweder nativ oder durch das QRhi-Backend bereitgestellt. Der Befehlspuffer wird übermittelt, und die Ausführung beginnt erst mit QRhi::endFrame() oder QRhi::finish().
Die aufgeschobene Natur hat Konsequenzen für einige Arten von Objekten. Zum Beispiel führt das mehrfache Schreiben in einen dynamischen Puffer innerhalb eines Frames, falls solche Puffer von einem für den Host sichtbaren Speicher unterstützt werden, dazu, dass die Ergebnisse aller Schreibvorgänge für alle Zeichenaufrufe im Befehlspuffer des Frames sichtbar sind, unabhängig davon, wann die Aktualisierung des dynamischen Puffers relativ zu einem Zeichenaufruf aufgezeichnet wurde.
Außerdem müssen Instanzen von QRhiResource Unterklassen innerhalb eines Rahmens, in dem sie in irgendeiner Weise referenziert werden, als unveränderlich behandelt werden. Erstellen Sie alle Ressourcen im Voraus, bevor Sie mit der Aufzeichnung von Befehlen für das nächste Bild beginnen. Die Wiederverwendung einer Instanz von QRhiResource innerhalb eines Frames (durch Aufruf von create()
und anschließender erneuter Referenzierung im selben Abschnitt von beginFrame - endFrame
) sollte vermieden werden, da dies je nach Backend zu unerwarteten Ergebnissen führen kann.
Als allgemeine Regel gilt, dass alle referenzierten QRhiResource Objekte gültig und unverändert bleiben müssen, bis der Frame durch den Aufruf von endFrame() übermittelt wird. Andererseits sind der Aufruf von destroy() oder das Löschen von QRhiResource immer sicher, sobald der Frame übermittelt wurde, unabhängig vom Status der zugrundeliegenden nativen Ressourcen (die möglicherweise noch von der GPU verwendet werden - aber darum wird sich intern gekümmert).
Im Gegensatz zu APIs wie OpenGL können die Befehle zum Hochladen und Kopieren nicht mit Zeichenbefehlen vermischt werden. Der typische Renderer wird eine Sequenz ähnlich der folgenden beinhalten:
- Ressourcen (neu) erstellen
- Rahmen beginnen
- Uploads und Kopien aufzeichnen/ausgeben
- Beginn der Aufzeichnung eines Rendering-Durchgangs
- Zeichnungsaufrufe aufzeichnen
- Renderdurchgang beenden
- Frame beenden
Die Aufzeichnung von Kopiervorgängen erfolgt über QRhiResourceUpdateBatch. Solche Operationen werden normalerweise auf beginPass() übertragen.
Bei der Arbeit mit älteren Rendering-Engines, die für OpenGL entwickelt wurden, beinhaltet die Umstellung auf QRhi oft die Umgestaltung von einem einzigen render
Schritt (der Kopien und Uploads durchführt, Puffer leert und Zeichenaufrufe ausgibt, alles zusammen) zu einem klar getrennten, zweiphasigen prepare
- render
Setup, bei dem der render
Schritt nur einen Renderpass startet und Zeichenaufrufe aufzeichnet, während alle Ressourcenerstellung und das Einreihen von Updates, Uploads und Kopien vorher im prepare
Schritt geschieht.
QRhi erlaubt im Moment nicht das freie Erstellen und Übermitteln von Befehlspuffern. Dies kann in der Zukunft in gewissem Umfang aufgehoben werden, insbesondere wenn die Unterstützung für Berechnungen eingeführt wird, aber das Modell der gut definierten Punkte frame-start
und frame-end
, kombiniert mit einem dedizierten "Frame"-Befehlspuffer, wobei frame-end
das Präsentieren impliziert, wird die primäre Arbeitsweise bleiben, da dies am besten zu den verschiedenen UI-Technologien von Qt passt.
Threading
Eine QRhi-Instanz und die zugehörigen Ressourcen können auf einem beliebigen Thread erstellt und verwendet werden, aber die gesamte Nutzung muss auf diesen einen Thread beschränkt sein. Beim Rendern in mehreren QWindows in einer Anwendung ist es oft ratsam, einen eigenen Thread und eine QRhi-Instanz für jedes Fenster zu haben, da dies Probleme mit unerwarteter Drosselung durch die Darstellung in mehreren Fenstern vermeiden kann. Vom Konzept her ist das dasselbe, wie die Rendering-Schleife von Qt Quick scene graph, wenn man direkt mit OpenGL arbeitet: ein Thread für jedes Fenster, ein QOpenGLContext für jeden Thread. Bei der Umstellung auf QRhi wird QOpenGLContext durch QRhi ersetzt, was die Migration einfach macht.
Bei extern erstellten nativen Objekten, wie z. B. OpenGL-Kontexten, die über QRhiGles2NativeHandles übergeben werden, muss die Anwendung sicherstellen, dass sie nicht von anderen Threads missbraucht werden.
Ressourcen können nicht zwischen QRhi-Instanzen geteilt werden. Dies ist eine bewusste Entscheidung, da QRhi die meisten Aufgaben im Zusammenhang mit Warteschlangen, Befehlspuffern und Ressourcensynchronisierung verbirgt und keine API dafür bereitstellt. Die sichere und effiziente gleichzeitige Nutzung von Grafikressourcen durch mehrere Threads ist jedoch mit diesen Konzepten verknüpft und ist daher ein Thema, das derzeit außerhalb des Anwendungsbereichs liegt, aber in Zukunft eingeführt werden kann.
Hinweis: Das Metal-Backend setzt voraus, dass ein Autorelease-Pool auf dem Rendering-Thread verfügbar ist, der idealerweise jede Iteration der Rendering-Schleife umschließt. Beim Rendering auf dem Haupt-Thread (GUI) muss der QRhi-Benutzer nichts tun, aber es wird wichtig, wenn ein separater, dedizierter Render-Thread verwendet wird.
Synchronisierung von Ressourcen
QRhi stellt keine APIs für Ressourcen-Barrieren oder Bild-Layout-Übergänge zur Verfügung. Eine solche Synchronisation wird implizit von den Backends durchgeführt, wo dies möglich ist (z. B. Vulkan), indem die Ressourcennutzung bei Bedarf verfolgt wird. Puffer- und Bildbarrieren werden vor Render- oder Berechnungsdurchläufen transparent für die Anwendung eingefügt.
Hinweis: Es wird erwartet, dass Ressourcen innerhalb eines Render- oder Berechnungsdurchgangs an eine einzige Verwendung während dieses Durchgangs gebunden sind. So kann ein Puffer beispielsweise als Vertex-, Index-, Uniform- oder Speicherpuffer verwendet werden, jedoch nicht in einer Kombination aus diesen Funktionen innerhalb eines einzigen Durchgangs. Es ist jedoch völlig in Ordnung, einen Puffer in einem Berechnungsdurchgang als Speicherpuffer und anschließend in einem Rendering-Durchgang als Vertex-Puffer zu verwenden, vorausgesetzt, der Puffer hat bei seiner Erstellung beide Verwendungen angegeben.
Hinweis: Bei Texturen wird diese Regel in bestimmten Fällen gelockert, da die Verwendung von zwei Subressourcen (typischerweise zwei verschiedene Mip-Ebenen) derselben Textur für unterschiedliche Zugriffe (eine zum Laden, eine zum Speichern) sogar innerhalb desselben Durchgangs unterstützt wird.
Wiederverwendung von Ressourcen
Aus der Sicht des Benutzers ist eine QRhiResource unmittelbar nach dem Aufruf von QRhiResource::destroy() wiederverwendbar. Mit Ausnahme von Swapchains führt der Aufruf von create()
für ein bereits erstelltes Objekt eine implizite destroy()
aus. Dies stellt eine praktische Abkürzung dar, um eine QRhiResource Instanz mit anderen Parametern wiederzuverwenden, wobei ein neues natives Grafikobjekt darunter liegt.
Die Bedeutung der Wiederverwendung desselben Objekts liegt in der Tatsache, dass einige Objekte auf andere Objekte verweisen: So kann beispielsweise ein QRhiShaderResourceBindings auf die Instanzen QRhiBuffer, QRhiTexture und QRhiSampler verweisen. Wenn in einem späteren Frame einer dieser Puffer in der Größe verändert werden muss oder ein Sampler-Parameter geändert werden muss, würde das Zerstören und Erzeugen eines völlig neuen QRhiBuffer oder QRhiSampler alle Referenzen auf die alte Instanz ungültig machen. Indem man einfach die entsprechenden Parameter über QRhiBuffer::setSize() o.ä. ändert und dann QRhiBuffer::create() aufruft, funktioniert alles wie erwartet und man muss QRhiShaderResourceBindings überhaupt nicht mehr anfassen, obwohl die Wahrscheinlichkeit groß ist, dass unter der Haube der QRhiBuffer jetzt von einem ganz neuen nativen Puffer unterstützt wird.
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 bietet denselben Vertrag: Der Aufruf von QRhiCommandBuffer::beginPass() ist auch dann sicher, wenn eine der mit dem Rendering-Ziel verbundenen Texturen oder Renderbuffer seit der Erstellung des Rendering-Ziel-Objekts neu erstellt wurde (durch Aufruf von create()
). Dadurch kann die Anwendung die Größe einer Textur ändern, indem sie eine neue Pixelgröße auf QRhiTexture setzt und create() aufruft, wodurch eine völlig neue native Texturressource darunter erzeugt wird, ohne dass QRhiTextureRenderTarget aktualisiert werden muss, da dies implizit in beginPass() geschieht.
Gepoolte Objekte
Zusätzlich zu den Ressourcen gibt es auch gepoolte Objekte, wie z.B. QRhiResourceUpdateBatch. Eine Instanz wird über eine next
Funktion abgerufen, wie z.B. nextResourceUpdateBatch(). In diesem Fall ist der Aufrufer nicht Eigentümer der zurückgegebenen Instanz. Die einzige gültige Möglichkeit, hier zu arbeiten, ist der Aufruf von Funktionen auf QRhiResourceUpdateBatch und die anschließende Übergabe an QRhiCommandBuffer::beginPass() oder QRhiCommandBuffer::endPass(). Diese Funktionen sorgen für die Rückgabe des Stapels an den Pool. Alternativ kann ein Stapel "abgebrochen" und ohne Verarbeitung an den Pool zurückgegeben werden, indem QRhiResourceUpdateBatch::release() aufgerufen wird.
Ein typisches Muster ist dies:
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-Spezifika
QRhiSwapChain weist aufgrund der besonderen Natur von Swapchains eine spezielle Semantik auf.
- Es gibt keine
create()
, sondern eine QRhiSwapChain::createOrResize(). Der wiederholte Aufruf dieser Funktion ist nicht dasselbe wie der Aufruf von QRhiSwapChain::destroy() gefolgt von QRhiSwapChain::createOrResize(). Der Grund dafür ist, dass Swapchains oft über Möglichkeiten verfügen, den Fall zu behandeln, dass Puffer auf eine Art und Weise geändert werden müssen, die effizienter ist als eine rohe Gewalt, bei der sie zerstört und von Grund auf neu erstellt werden. - Ein aktives QRhiSwapChain muss durch Aufruf von destroy() oder durch Zerstörung des Objekts freigegeben werden, bevor das QWindow zugrunde liegende QPlatformWindow und damit das zugehörige native Fensterobjekt zerstört wird. Es sollte nicht aufgeschoben werden, weil das Freigeben der Swapchain problematisch werden kann (und bei einigen APIs, wie Vulkan, explizit nicht erlaubt ist), wenn das native Fenster nicht mehr vorhanden ist, zum Beispiel weil das QPlatformWindow beim Aufruf von QWindow::close() zerstört wurde. Daher muss die Freigabe der Swapchain immer dann erfolgen, wenn das anvisierte QWindow das Ereignis QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed sendet. Wenn das Ereignis nicht vor der Zerstörung von QWindow eintrifft - dies kann bei der Verwendung von QCoreApplication::quit() passieren -, dann prüfen Sie QWindow::handle() nach dem Beenden der Ereignisschleife und rufen Sie die Swapchain-Freigabe auf, wenn sie nicht null ist (was bedeutet, dass das zugrunde liegende native Fenster noch vorhanden ist).
Eigentümerschaft
Die allgemeine Regel ist, dass keine Eigentumsübertragung stattfindet. Das Erstellen eines QRhi mit einem bereits vorhandenen Grafikgerät bedeutet nicht, dass der QRhi das Eigentum an dem Geräteobjekt übernimmt. Ebenso wird das Eigentum nicht weitergegeben, wenn ein Geräte- oder Texturobjekt über QRhi::nativeHandles() oder QRhiTexture::nativeTexture() "exportiert" wird. Am wichtigsten ist, dass die Übergabe von Zeigern in Structs und über Setter keine Eigentumsübertragung bedeutet.
Fehlersuche und Profiling
Fehlerberichterstattung
Funktionen wie QRhi::create() und die Mitgliedsfunktionen der Ressourcenklassen create()
(z. B. QRhiBuffer::create()) zeigen Fehler mit dem Rückgabewert an (nullptr
bzw. false
). Bei der Arbeit mit QShader gibt QShader::fromSerialized() ein ungültiges QShader zurück (wofür isValid() false
zurückgibt), wenn die an die Funktion übergebenen Daten nicht erfolgreich deserialisiert werden können. Einige Funktionen, insbesondere beginFrame(), können manchmal auch "weiche Fehler" melden, wie z. B. FrameOpSwapChainOutOfDate, die nicht auf einen nicht behebbaren Fehler hindeuten, sondern eher als eine "Versuchen Sie es später noch einmal"-Antwort angesehen werden sollten.
Warnungen und Fehler können jederzeit über qWarning() auf der Debug-Ausgabe ausgegeben werden. Es ist daher immer ratsam, die Ausgabe der Anwendung zu überprüfen.
Zusätzliche Debug-Meldungen können über die folgenden Logging-Kategorien aktiviert werden. Meldungen aus diesen Kategorien werden standardmäßig nicht ausgegeben, es sei denn, sie werden explizit über QLoggingCategory oder die Umgebungsvariable QT_LOGGING_RULES
aktiviert. Für ein besseres Zusammenspiel mit Qt Quick aktiviert die Umgebungsvariable QSG_INFO
auch diese Debug-Ausgaben.
qt.rhi.general
Zusätzlich können Anwendungen die QRhi backend name und graphics device information von einem erfolgreich initialisierten QRhi abfragen. Diese können dann an den Benutzer ausgegeben oder in den Anwendungsprotokollen gespeichert werden, sogar in Produktions-Builds, falls gewünscht.
Untersuchen von Rendering-Problemen
Wenn die Rendering-Ergebnisse nicht wie erwartet ausfallen oder die Anwendung Probleme hat, sollten Sie immer die Debug- und Validierungsfunktionen der nativen 3D-APIs nutzen. QRhi selbst bietet nur eine begrenzte Fehlerprüfung, da es nicht sinnvoll ist, die bereits vorhandenen, umfangreichen Funktionen in den darunter liegenden Schichten zu replizieren.
- Bei Vulkan liegt die Steuerung der Vulkan-Validierungsschichten nicht im Aufgabenbereich von QRhi, sondern kann durch die Konfiguration von QVulkanInstance mit den entsprechenden Schichten erreicht werden. Rufen Sie z. B.
instance.setLayers({ "VK_LAYER_KHRONOS_validation" });
auf, bevor Sie create() auf QVulkanInstance aufrufen (beachten Sie, dass dies voraussetzt, dass die Validierungsschichten tatsächlich installiert und verfügbar sind, z. B. aus dem Vulkan-SDK). Standardmäßig leitet QVulkanInstance die Vulkan-Debug-Meldungen bequem an qDebug weiter, d. h. die Validierungsmeldungen werden genauso wie andere Qt-Warnungen ausgegeben. - Bei Direct 3D 11 und 12 kann ein Grafikgerät mit aktivierter Debug-Schicht angefordert werden, indem das
enableDebugLayer
Flag in der entsprechenden init params struct umgeschaltet wird. Die Meldungen erscheinen in der Debug-Ausgabe, die im Meldungsfenster von Qt Creator oder über ein Tool wie DebugView sichtbar ist. - Für Metal liegt die Steuerung der Metal-Validierung außerhalb der Möglichkeiten von QRhi. Um die Validierung zu aktivieren, muss die Anwendung mit der Umgebungsvariablen
METAL_DEVICE_WRAPPER_TYPE=1
ausgeführt werden, oder die Anwendung muss in XCode ausgeführt werden. Es kann auch weitere Einstellungen und Umgebungsvariablen in modernen XCode- und macOS-Versionen geben. Siehe zum Beispiel diese Seite.
Frame-Captures und Performance-Profiling
Eine Qt-Anwendung, die mit QRhi in einem Fenster gerendert wird und dabei auf eine 3D-API unter der Haube zurückgreift, unterscheidet sich zumindest aus Sicht der Fenster- und Grafikpipeline nicht von anderen (Nicht-Qt-)Anwendungen, die dieselbe 3D-API verwenden. Das bedeutet, dass Tools und Praktiken zum Debuggen und Profiling von Anwendungen mit 3D-Grafik, wie z. B. Spiele, auch für eine solche Qt-Anwendung gelten.
Einige Beispiele für Tools, die Einblicke in die Rendering-Interna von Qt-Anwendungen geben können, die QRhi verwenden, was auch Qt Quick und Qt Quick 3D basierte Projekte einschließt:
- RenderDoc ermöglicht die Aufnahme von Frames und die Untersuchung der aufgezeichneten Befehle und des Pipeline-Status auf Windows und Linux für Anwendungen, die OpenGL, Vulkan, D3D11 oder D3D12 verwenden. Wenn man versucht herauszufinden, warum einige Teile der 3D-Szene nicht wie erwartet angezeigt werden, ist RenderDoc oft ein schneller und effizienter Weg, um die Pipeline-Stufen und den zugehörigen Status zu überprüfen und den fehlenden oder falschen Wert zu entdecken. Es ist auch ein Werkzeug, das bei der Entwicklung von Qt selbst aktiv eingesetzt wird.
- Für NVIDIA-basierte Systeme bietet Nsight Graphics ein Grafik-Debugger-Tool für Windows und Linux. Neben der Untersuchung der Befehle im Frame und der Pipeline ermöglichen die herstellerspezifischen Tools auch die Betrachtung von Timings und Hardware-Leistungsinformationen, was mit einfachen Frame-Captures nicht möglich ist.
- Für AMD-basierte Systeme kann der Radeon GPU Profiler verwendet werden, um tiefere Einblicke in das Rendering und die Leistung der Anwendung zu erhalten.
- Da QRhi Direct 3D 12 unterstützt, ist die Verwendung von PIX, einem Performance-Tuning- und Debugging-Tool für DirectX 12-Spiele unter Windows, ebenfalls eine Option.
- Unter macOS kann der XCode-Metal-Debugger verwendet werden, um Frame-Captures aufzunehmen und zu untersuchen, Leistungsdetails zu untersuchen und Shader zu debuggen. In macOS 13 ist es auch möglich, ein Overlay zu aktivieren, das die Framerate und andere Informationen für jedes Metal-basierte Fenster anzeigt, indem man die Umgebungsvariable
MTL_HUD_ENABLED=1
setzt.
Auf mobilen und eingebetteten Plattformen gibt es möglicherweise hersteller- und plattformspezifische Tools, die vom GPU- oder SoC-Anbieter zur Verfügung gestellt werden, um ein Leistungsprofil von Anwendungen zu erstellen, die OpenGL ES oder Vulkan verwenden.
Denken Sie bei der Erfassung von Frames daran, dass Objekte und Gruppen von Befehlen über Debug-Marker benannt werden können, sofern debug markers were enabled für den QRhi und die verwendete Grafik-API dies unterstützen. Um den Befehlsstrom mit Anmerkungen zu versehen, rufen Sie debugMarkBegin(), debugMarkEnd() und/oder debugMarkMsg() auf. Dies kann besonders bei größeren Frames mit mehreren Render-Passes nützlich sein. Ressourcen werden durch den Aufruf von setName() vor create() benannt.
Um grundlegende Timing-Messungen auf der CPU- und GPU-Seite innerhalb der Anwendung durchzuführen, können QElapsedTimer und QRhiCommandBuffer::lastCompletedGpuTime() verwendet werden. Letzteres ist derzeit nur bei ausgewählten Grafik-APIs verfügbar und erfordert die Aktivierung über das Flag QRhi::EnableTimestamps.
Überprüfung von Ressourcenlecks
Wenn ein QRhi-Objekt zerstört wird, ohne dass alle Puffer, Texturen und andere Ressourcen, die von ihm erzeugt wurden, ordnungsgemäß zerstört werden, werden entsprechende Warnungen in die Debug-Ausgabe ausgegeben, wenn die Anwendung ein Debug-Build ist oder wenn die Umgebungsvariable QT_RHI_LEAK_CHECK
auf einen Wert ungleich Null gesetzt ist. Dies ist ein einfacher Weg, um Design-Probleme bei der Handhabung von Ressourcen innerhalb der Rendering-Logik der Anwendung zu entdecken. Beachten Sie jedoch, dass einige Plattformen und zugrundeliegende Grafik-APIs auch ihre eigene Zuweisung und Erkennung von Ressourcenlecks durchführen können, über die Qt keine direkte Kontrolle hat. Bei der Verwendung von Vulkan kann der Speicherallokator beispielsweise in Debug-Builds fehlgeschlagene Assertions auslösen, wenn Ressourcen, die Grafikspeicherzuweisungen besitzen, nicht vor dem QRhi zerstört werden. Darüber hinaus gibt die Vulkan-Validierungsschicht, wenn sie aktiviert ist, Warnungen über native Grafikressourcen aus, die nicht freigegeben wurden. In ähnlicher Weise können bei Direct 3D Warnungen über nicht freigegebene COM-Objekte ausgegeben werden, wenn die Anwendung den QRhi und seine Ressourcen nicht in der richtigen Reihenfolge zerstört.
Siehe auch RHI Window Example, QRhiCommandBuffer, QRhiResourceUpdateBatch, QRhiShaderResourceBindings, QShader, QRhiBuffer, QRhiTexture, QRhiRenderBuffer, QRhiSampler, QRhiTextureRenderTarget, QRhiGraphicsPipeline, QRhiComputePipeline, und QRhiSwapChain.
Dokumentation der Mitgliedstypen
enum QRhi::BeginFrameFlag
flags QRhi::BeginFrameFlags
Flag-Werte für QRhi::beginFrame()
Der Typ BeginFrameFlags ist ein Typedef für QFlags<BeginFrameFlag>. Er speichert eine ODER-Kombination von BeginFrameFlag-Werten.
enum QRhi::EndFrameFlag
flags QRhi::EndFrameFlags
Flag-Werte für QRhi::endFrame()
Konstante | Wert | Beschreibung |
---|---|---|
QRhi::SkipPresent | 1 << 0 | Gibt an, dass kein aktueller Befehl in die Warteschlange gestellt oder kein swapBuffers-Aufruf gemacht werden soll. Auf diese Weise wird kein Bild dargestellt. Es wird nicht empfohlen, mehrere Frames zu erzeugen, die alle dieses Flag gesetzt haben (außer z.B. für Benchmarking-Zwecke - aber bedenken Sie, dass Backends sich unterschiedlich verhalten können, wenn es darum geht, auf die Beendigung eines Befehls zu warten, ohne ein Bild zu präsentieren, so dass die Ergebnisse nicht zwischen ihnen vergleichbar sind) |
Der Typ EndFrameFlags ist ein Typedef für QFlags<EndFrameFlag>. Er speichert eine ODER-Kombination von EndFrameFlag-Werten.
enum QRhi::Feature
Flag-Werte, die angeben, welche Funktionen von dem derzeit verwendeten Backend unterstützt werden.
Konstante | Wert | Beschreibung |
---|---|---|
QRhi::MultisampleTexture | 1 | Zeigt an, dass Texturen mit einer Sampleanzahl größer als 1 unterstützt werden. In der Praxis wird diese Funktion bei OpenGL ES Versionen älter als 3.1 und OpenGL älter als 3.0 nicht unterstützt. |
QRhi::MultisampleRenderBuffer | 2 | Zeigt an, dass Renderbuffer mit einer Sampleanzahl größer als 1 unterstützt werden. In der Praxis wird diese Funktion mit OpenGL ES 2.0 nicht unterstützt und kann auch mit OpenGL 2.x nicht unterstützt werden, wenn die entsprechenden Erweiterungen nicht vorhanden sind. |
QRhi::DebugMarkers | 3 | Zeigt an, dass Debug-Marker-Gruppen (und damit QRhiCommandBuffer::debugMarkBegin()) unterstützt werden. |
QRhi::Timestamps | 4 | Zeigt an, dass Befehlspuffer-Zeitstempel unterstützt werden. Relevant für QRhiCommandBuffer::lastCompletedGpuTime(). Es kann erwartet werden, dass dies auf Metal, Vulkan, Direct 3D 11 und 12 und OpenGL-Kontexten der Version 3.3 oder neuer unterstützt wird. Bei einigen dieser APIs ist die Unterstützung für Zeitstempelabfragen jedoch technisch optional, und daher kann nicht garantiert werden, dass diese Funktion immer bei jeder Implementierung dieser APIs unterstützt wird. |
QRhi::Instancing | 5 | Zeigt an, dass instanziertes Zeichnen unterstützt wird. In der Praxis wird diese Funktion mit OpenGL ES 2.0 und OpenGL 3.2 oder älter nicht unterstützt. |
QRhi::CustomInstanceStepRate | 6 | Zeigt an, dass andere Instanzschrittraten als 1 unterstützt werden. In der Praxis wird diese Funktion bei OpenGL immer nicht unterstützt. Außerdem führt die Ausführung mit Vulkan 1.0 ohne VK_EXT_vertex_attribute_divisor dazu, dass diese Funktion als falsch gemeldet wird. |
QRhi::PrimitiveRestart | 7 | Zeigt an, dass der Neustart des Zusammenbaus von Primitiven bei einem Indexwert von 0xFFFF (IndexUInt16) oder 0xFFFFFFFF (IndexUInt32) aktiviert ist, zumindest für bestimmte Primitivtopologien. QRhi versucht, dies mit allen Backends zu aktivieren, aber in einigen Fällen wird es nicht unterstützt. Eine dynamische Steuerung des primitiven Neustarts ist nicht möglich, da bei einigen APIs der primitive Neustart mit einem festen Index immer aktiviert ist. Anwendungen müssen davon ausgehen, dass immer dann, wenn diese Funktion als unterstützt gemeldet wird, die oben genannten Indexwerte may je nach Topologie besonders behandelt werden. Die einzigen beiden Topologien, bei denen der primitive Neustart sich garantiert in allen Backends identisch verhält, solange diese Funktion als unterstützt gemeldet wird, sind LineStrip und TriangleStrip. |
QRhi::NonDynamicUniformBuffers | 8 | Gibt an, dass die Erstellung von Puffern mit der Verwendung UniformBuffer und den Typen Immutable oder Static unterstützt wird. Wenn es als nicht unterstützt gemeldet wird, müssen einheitliche (konstante) Puffer mit Dynamic erstellt werden (was unabhängig davon empfohlen wird). |
QRhi::NonFourAlignedEffectiveIndexBufferOffset | 9 | Zeigt an, dass effektive Indexpuffer-Offsets (indexOffset + firstIndex * indexComponentSize ), die nicht 4-Byte-ausgerichtet sind, unterstützt werden. Wenn dies nicht unterstützt wird, kann der Versuch, eine drawIndexed() mit einem nicht ausgerichteten effektiven Offset auszuführen, zu einem nicht spezifizierten Verhalten führen. Dies ist insbesondere für Metal relevant, wo dies als nicht unterstützt gemeldet wird. |
QRhi::NPOTTextureRepeat | 10 | Zeigt an, dass die Modi Repeat wrap mode und mipmap filtering für Texturen mit einer Größe, die keine Zweierpotenz ist, unterstützt werden. In der Praxis kann dies nur bei OpenGL ES 2.0 Implementierungen ohne GL_OES_texture_npot falsch sein. |
QRhi::RedOrAlpha8IsRed | 11 | Zeigt an, dass das Format RED_OR_ALPHA8 auf ein einkomponentiges 8-Bit-Format red abgebildet wird. Dies ist der Fall für alle Backends außer OpenGL, wenn entweder OpenGL ES oder ein Nicht-Kernprofil-Kontext verwendet wird. Dort wird GL_ALPHA , ein einkomponentiges 8-Bit-Format alpha , stattdessen verwendet. Die Verwendung des speziellen Texturformats ermöglicht es, einen einzigen Codepfad für die Erstellung von Texturen zu haben und es dem Backend zu überlassen, das tatsächliche Format zu wählen, während das Feature-Flag verwendet werden kann, um die geeignete Shader-Variante für das Sampling der Textur zu wählen. |
QRhi::ElementIndexUint | 12 | Zeigt an, dass 32-bit unsigned integer Elemente im Indexpuffer unterstützt werden. In der Praxis ist dies überall der Fall, außer bei einfachen OpenGL ES 2.0 Implementierungen ohne die notwendige Erweiterung. Wenn false, werden nur 16-Bit-Elemente ohne Vorzeichen im Indexpuffer unterstützt. |
QRhi::Compute | 13 | Zeigt an, dass Compute Shader, Image Load/Store und Storage Buffer unterstützt werden. OpenGL älter als 4.3 und OpenGL ES älter als 3.1 haben keine Unterstützung für Berechnungen. |
QRhi::WideLines | 14 | Zeigt an, dass Linien mit einer anderen Breite als 1 unterstützt werden. Wenn dies als nicht unterstützt gemeldet wird, wird die im Status der Grafikpipeline eingestellte Linienbreite ignoriert. Bei einigen Backends (D3D11, D3D12, Metal) kann dieser Wert immer false sein. Bei Vulkan hängt der Wert von der Implementierung ab. Bei OpenGL werden breite Linien in Kernprofilkontexten nicht unterstützt. |
QRhi::VertexShaderPointSize | 15 | Zeigt an, dass die Größe von gerasterten Punkten, die über gl_PointSize im Vertex-Shader festgelegt wurde, berücksichtigt wird. Wenn dies als nicht unterstützt gemeldet wird, wird das Zeichnen von Punkten mit einer anderen Größe als 1 nicht unterstützt. Die Einstellung gl_PointSize im Shader ist dann immer noch gültig, wird aber ignoriert. (z. B. beim Generieren von HLSL wird die Zuweisung stillschweigend aus dem generierten Code entfernt). Beachten Sie, dass bei einigen APIs (Metal, Vulkan) die Punktgröße im Shader explizit festgelegt werden muss, wenn Punkte gezeichnet werden, selbst wenn die Größe 1 ist, da sie nicht automatisch auf 1 eingestellt sind. |
QRhi::BaseVertex | 16 | Zeigt an, dass drawIndexed() das Argument vertexOffset unterstützt. Wenn es als nicht unterstützt gemeldet wird, wird der vertexOffset-Wert in einer indizierten Zeichnung ignoriert. In der Praxis wird diese Funktion mit OpenGL und OpenGL ES Versionen kleiner als 3.2 und mit Metal auf älteren iOS Geräten, einschließlich dem iOS Simulator, nicht unterstützt. |
QRhi::BaseInstance | 17 | Zeigt an, dass instanzierte Zeichenbefehle das Argument firstInstance unterstützen. Wenn es als nicht unterstützt gemeldet wird, wird der firstInstance-Wert ignoriert und die Instanz-ID beginnt bei 0. In der Praxis wird diese Funktion nicht mit OpenGL und mit Metal auf älteren iOS-Geräten, einschließlich des iOS Simulators, unterstützt. |
QRhi::TriangleFanTopology | 18 | Zeigt an, dass QRhiGraphicsPipeline::setTopology() QRhiGraphicsPipeline::TriangleFan unterstützt. In der Praxis wird diese Funktion von Metal und Direct 3D 11/12 nicht unterstützt. |
QRhi::ReadBackNonUniformBuffer | 19 | Zeigt an, dass reading buffer contents für QRhiBuffer Instanzen mit einer anderen Verwendung als UniformBuffer unterstützt wird. In der Praxis wird diese Funktion nicht von OpenGL ES 2.0 unterstützt. |
QRhi::ReadBackNonBaseMipLevel | 20 | Zeigt an, dass die Angabe eines anderen Mip-Levels als 0 beim Zurücklesen von Texturinhalten unterstützt wird. Wenn es nicht unterstützt wird, führt die Angabe eines Levels ungleich Null in QRhiReadbackDescription zur Rückgabe eines Bildes, das komplett Null ist. In der Praxis wird diese Funktion mit OpenGL ES 2.0 nicht unterstützt. |
QRhi::TexelFetch | 21 | Zeigt an, dass texelFetch() und textureLod() in Shadern verfügbar sind. In der Praxis wird dies als nicht unterstützt mit OpenGL ES 2.0 und OpenGL 2.x Kontexten gemeldet, weil GLSL 100 es und Versionen vor 130 diese Funktionen nicht unterstützen. |
QRhi::RenderToNonBaseMipLevel | 22 | Zeigt an, dass die Angabe eines anderen Mip-Levels als 0 unterstützt wird, wenn ein QRhiTextureRenderTarget mit einem QRhiTexture als Farbanhang erstellt wird. Wenn dies nicht unterstützt wird, schlägt create() fehl, wenn der Ziel-Mip-Level nicht Null ist. In der Praxis wird diese Funktion mit OpenGL ES 2.0 nicht unterstützt. |
QRhi::IntAttributes | 23 | Zeigt an, dass die Angabe von Eingabeattributen mit vorzeichenbehafteten und vorzeichenlosen Ganzzahltypen für eine Shader-Pipeline unterstützt wird. Wenn es nicht unterstützt wird, wird build() erfolgreich sein, aber nur eine Warnmeldung anzeigen und die Werte der Zielattribute werden gebrochen sein. In der Praxis wird diese Funktion mit OpenGL ES 2.0 und OpenGL 2.x nicht unterstützt. |
QRhi::ScreenSpaceDerivatives | 24 | Zeigt an, dass Funktionen wie dFdx(), dFdy(), und fwidth() in Shadern unterstützt werden. In der Praxis wird diese Funktion mit OpenGL ES 2.0 ohne die Erweiterung GL_OES_standard_derivatives nicht unterstützt. |
QRhi::ReadBackAnyTextureFormat | 25 | Zeigt an, dass das Zurücklesen von Texturinhalten für jedes QRhiTexture::Format erwartet werden kann. Von anderen Backends als OpenGL kann erwartet werden, dass sie true für diese Funktion zurückgeben. Wenn false gemeldet wird, was typischerweise bei OpenGL der Fall ist, werden nur die Formate QRhiTexture::RGBA8 und QRhiTexture::BGRA8 garantiert für Rücklesungen unterstützt. Darüber hinaus werden mit OpenGL, aber nicht mit OpenGL ES, auch die 1-Byte-pro-Komponente-Formate QRhiTexture::R8 und QRhiTexture::RED_OR_ALPHA8 zurückgelesen. Das Zurücklesen von Fließkommaformaten QRhiTexture::RGBA16F und RGBA32F kann auch mit OpenGL funktionieren, solange die Implementierung Unterstützung dafür bietet, aber QRhi kann keine Garantien geben, wie durch dieses Flag angezeigt wird. |
QRhi::PipelineCacheDataLoadSave | 26 | Zeigt an, dass die Funktionen pipelineCacheData() und setPipelineCacheData() funktionsfähig sind. Wenn sie nicht unterstützt werden, führen die Funktionen keine Aktion aus, der abgerufene Blob ist immer leer und somit kann kein Nutzen aus dem Abrufen und dem erneuten Laden des Pipeline-Cache-Inhalts bei einem nachfolgenden Lauf der Anwendung erwartet werden. |
QRhi::ImageDataStride | 27 | Gibt an, dass die Angabe eines benutzerdefinierten Stride (Zeilenlänge) für Rohbilddaten in Textur-Uploads unterstützt wird. Wenn dies nicht unterstützt wird (was der Fall sein kann, wenn die zugrunde liegende API OpenGL ES 2.0 ohne Unterstützung für GL_UNPACK_ROW_LENGTH ist), darf QRhiTextureSubresourceUploadDescription::setDataStride() nicht verwendet werden. |
QRhi::RenderBufferImport | 28 | Zeigt an, dass QRhiRenderBuffer::createFrom() unterstützt wird. Für die meisten Grafik-APIs ist dies nicht sinnvoll, da QRhiRenderBuffer Texturobjekte intern kapselt, genau wie QRhiTexture. Bei OpenGL jedoch existieren Renderbuffer-Objekte als separater Objekttyp in der API, und in bestimmten Umgebungen (z.B. wenn man ein Renderbuffer-Objekt mit einem EGLImage-Objekt assoziieren möchte) ist es wichtig, ein bestehendes OpenGL-Renderbuffer-Objekt mit einem QRhiRenderBuffer zu umhüllen. |
QRhi::ThreeDimensionalTextures | 29 | Zeigt an, dass 3D-Texturen unterstützt werden. In der Praxis wird diese Funktion mit OpenGL und OpenGL ES Versionen kleiner als 3.0 nicht unterstützt. |
QRhi::RenderTo3DTextureSlice | 30 | Zeigt an, dass das Rendering auf ein Slice in einer 3D-Textur unterstützt wird. Dies kann mit Vulkan 1.0 nicht unterstützt werden, da es auf VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT beruht, das eine Funktion von Vulkan 1.1 ist. |
QRhi::TextureArrays | 31 | Zeigt an, dass Textur-Arrays unterstützt werden und QRhi::newTextureArray() funktionsfähig ist. Beachten Sie, dass selbst wenn Textur-Arrays nicht unterstützt werden, Arrays von Texturen immer noch verfügbar sind, da dies zwei unabhängige Funktionen sind. |
QRhi::Tessellation | 32 | Zeigt an, dass die Tesselierungssteuerungs- und -bewertungsstufen unterstützt werden. Wenn diese als unterstützt gemeldet werden, kann die Topologie eines QRhiGraphicsPipeline auf Patches eingestellt werden, die Anzahl der Kontrollpunkte kann über setPatchControlPointCount() eingestellt werden und Shader für die Tesselationssteuerung und -auswertung können in der Liste QRhiShaderStage angegeben werden. Bei Tessellationsshadern gibt es Probleme mit der Übertragbarkeit zwischen APIs (z. B. ist die Übersetzung von GLSL/SPIR-V in HLSL aufgrund der Struktur von Hull-Shadern problematisch, während Metal eine etwas andere Tessellierungspipeline als andere verwendet), und daher können unerwartete Probleme auftreten, auch wenn die grundlegende Funktionalität in allen zugrunde liegenden APIs implementiert ist. Insbesondere für Direct 3D müssen handgeschriebene HLSL-Hull- und Domain-Shader in jede QShader für die Tessellierungssteuerung bzw. -auswertung injiziert werden, da qsb diese nicht aus SPIR-V generieren kann. Beachten Sie, dass Isoline-Tesselation vermieden werden sollte, da sie nicht von allen Backends unterstützt wird. Die maximale Anzahl der Patch-Kontrollpunkte, die zwischen den Backends portabel ist, beträgt 32. |
QRhi::GeometryShader | 33 | Zeigt an, dass die Geometrieshader-Stufe unterstützt wird. Wenn unterstützt, kann ein Geometrieshader in der Liste QRhiShaderStage angegeben werden. Geometry Shader werden in QRhi als experimentelles Feature betrachtet und es kann nur erwartet werden, dass sie mit Vulkan, Direct 3D, OpenGL (3.2+) und OpenGL ES (3.2+) unterstützt werden, vorausgesetzt, die Implementierung meldet sie zur Laufzeit als unterstützt. Geometrieshader haben Probleme mit der Portabilität zwischen APIs, daher kann keine Garantie für eine universelle Lösung gegeben werden. Sie werden nie von Metal unterstützt werden. Während bei Direct 3D ein handgeschriebener HLSL-Geometrieshader in jede QShader für die Geometriestufe injiziert werden muss, da qsb diesen nicht aus SPIR-V generieren kann. |
QRhi::TextureArrayRange | 34 | Zeigt an, dass es für texture arrays möglich ist, einen Bereich zu spezifizieren, der den Shadern ausgesetzt wird. Normalerweise sind alle Array-Layer exponiert und es liegt am Shader, den Layer auszuwählen (über die dritte Koordinate, die beim Sampling der sampler2DArray an texture() übergeben wird). Wenn unterstützt, hat der Aufruf von QRhiTexture::setArrayRangeStart() und QRhiTexture::setArrayRangeLength() vor building oder importing der nativen Textur einen Effekt und führt dazu, dass nur der angegebene Bereich aus dem Array ausgewählt wird. Dies ist in speziellen Fällen notwendig, wie z. B. bei der Arbeit mit beschleunigtem Videodecoding und Direct 3D 11, da ein Textur-Array, das sowohl D3D11_BIND_DECODER als auch D3D11_BIND_SHADER_RESOURCE enthält, nur dann als Shader-Ressource verwendet werden kann, wenn eine einzelne Array-Ebene ausgewählt ist. Beachten Sie, dass all dies nur gilt, wenn die Textur als QRhiShaderResourceBinding::SampledTexture oder QRhiShaderResourceBinding::Texture Shader-Ressource verwendet wird, und nicht mit Bild laden/speichern kompatibel ist. Diese Funktion ist nur mit einigen Backends verfügbar, da sie nicht gut auf alle Grafik-APIs abgebildet werden kann, und sie ist ohnehin nur als Unterstützung für spezielle Fälle gedacht. In der Praxis kann erwartet werden, dass das Feature mit Direct3D 11/12 und Vulkan unterstützt wird. |
QRhi::NonFillPolygonMode | 35 | Zeigt an, dass die Einstellung eines anderen PolygonModus als des Standard-Füllmodus für QRhiGraphicsPipeline unterstützt wird. Ein häufiger Anwendungsfall für das Ändern des Modus auf Linie ist das Rendering von Drahtmodellen. Dies ist jedoch nicht als OpenGL ES-Kernfunktion verfügbar und ist bei Vulkan optional, und einige mobile GPUs bieten diese Funktion möglicherweise nicht. |
QRhi::OneDimensionalTextures | 36 | Zeigt an, dass 1D-Texturen unterstützt werden. In der Praxis wird diese Funktion bei OpenGL ES nicht unterstützt. |
QRhi::OneDimensionalTextureMipmaps | 37 | Zeigt an, dass die Erzeugung von 1D-Textur-Mipmaps unterstützt wird. In der Praxis wird diese Funktion auf Backends, die keine Unterstützung für OneDimensionalTextures, Metal und Direct 3D 12 bieten, nicht unterstützt. |
QRhi::HalfAttributes | 38 | Zeigt an, dass die Angabe von Eingabeattributen mit halbpräzisen (16bit) Gleitkommatypen für eine Shader-Pipeline unterstützt wird. Wenn dies nicht der Fall ist, wird build() zwar erfolgreich sein, aber nur eine Warnmeldung anzeigen und die Werte der Zielattribute werden nicht korrekt sein. In der Praxis wird diese Funktion in einigen OpenGL ES 2.0 und OpenGL 2.x Implementierungen nicht unterstützt. Beachten Sie, dass Direct3D 11/12 zwar halbgenaue Eingabeattribute unterstützt, nicht aber den Typ half3. Die D3D Backends übergeben half3 Attribute als half4. Um plattformübergreifende Kompatibilität zu gewährleisten, sollten half3-Eingaben auf 8 Bytes aufgefüllt werden. |
QRhi::RenderToOneDimensionalTexture | 39 | Zeigt an, dass 1D-Textur-Renderziele unterstützt werden. In der Praxis wird diese Funktion von Backends, die keine Unterstützung für OneDimensionalTextures und Metal melden, nicht unterstützt. |
QRhi::ThreeDimensionalTextureMipmaps | 40 | Zeigt an, dass die Erzeugung von 3D-Textur-Mipmaps unterstützt wird. In der Praxis wird diese Funktion mit Direct 3D 12 nicht unterstützt. |
QRhi::MultiView | 41 | Zeigt an, dass Multiview, siehe z.B. VK_KHR_multiview, unterstützt wird. Mit OpenGL ES 2.0, Direct 3D 11 und OpenGL (ES)-Implementierungen ohne GL_OVR_multiview2 wird diese Funktion nicht unterstützt. Mit Vulkan 1.1 und neuer sowie Direct 3D 12 wird Multiview normalerweise unterstützt. Wenn als unterstützt gemeldet wird, ermöglicht das Erstellen eines QRhiTextureRenderTarget mit einem QRhiColorAttachment, der auf ein Textur-Array verweist und multiViewCount eingestellt hat, die Aufzeichnung eines Render-Durchgangs, der Multiview-Rendering verwendet. Darüber hinaus müssen alle QRhiGraphicsPipeline, die in diesem Rendering-Durchgang verwendet werden, the same view count set haben. Beachten Sie, dass Multiview nur in Kombination mit 2D-Textur-Arrays verfügbar ist. Es kann nicht verwendet werden, um das Rendering in einzelne Texturen zu optimieren (z. B. zwei, für das linke und das rechte Auge). Vielmehr ist das Ziel eines Multiview-Rendering-Durchgangs immer ein Textur-Array, das automatisch auf die Ebene (Array-Element) gerendert wird, die jeder Ansicht entspricht. Daher impliziert dieses Feature auch TextureArrays. Multiview-Rendering wird nicht in Kombination mit Tessellation oder Geometrieshadern unterstützt. Siehe QRhiColorAttachment::setMultiViewCount() für weitere Details zum Multiview-Rendering. Dieser Enum-Wert wurde in Qt 6.7 eingeführt. |
QRhi::TextureViewFormat | 42 | Zeigt an, dass das Setzen einer view format auf einer QRhiTexture wirksam ist. Wenn als unterstützt gemeldet, ändert das Setzen des Lese- (Sampling) oder Schreib- (Rendering-Ziel / Bild-Load-Store) Ansichtsmodus das Anzeigeformat der Textur. Wenn es nicht unterstützt wird, hat das Setzen eines Ansichtsformats keinen Effekt. Beachten Sie, dass Qt keine Kenntnis oder Kontrolle über die Formatkompatibilität oder die Regeln für die Ressourcendarstellung in der zugrundeliegenden 3D API und deren Implementierung hat. Die Übergabe von ungeeigneten, inkompatiblen Formaten kann zu Fehlern und nicht spezifiziertem Verhalten führen. Dies wird hauptsächlich zur Verfügung gestellt, um das "Casting" in eine Textur zu ermöglichen, die mit einem sRGB-Format erstellt wurde, um die unerwünschte linear->sRGB-Konvertierung bei Shader-Schreibvorgängen zu vermeiden. Andere Arten des Castings können je nach zugrunde liegender API funktionieren oder auch nicht. Derzeit für Vulkan und Direct 3D 12 implementiert. Mit D3D12 ist die Funktion nur verfügbar, wenn CastingFullyTypedFormatSupported unterstützt wird, siehe https://microsoft.github.io/DirectX-Specs/d3d/RelaxedCasting.html (und beachten Sie, dass QRhi immer vollständig typisierte Formate für Texturen verwendet.) Dieser Enum-Wert wurde in Qt 6.8 eingeführt. |
QRhi::ResolveDepthStencil | 43 | Zeigt an, dass das Auflösen einer Multisample-Tiefen- oder Tiefenschablonen-Textur unterstützt wird. Andernfalls ist setting a depth resolve texture nicht funktionsfähig und muss vermieden werden. Direct 3D 11 und 12 haben keine Unterstützung für die Auflösung von Tiefen-/Tiefenstencil-Formaten und daher wird diese Funktion niemals mit diesen unterstützt. Vulkan 1.0 hat keine API, um die Auflösung eines Tiefenschablonen-Anhangs anzufordern. Daher wird diese Funktion bei Vulkan nur mit Vulkan 1.2 und höher sowie bei 1.1-Implementierungen mit den entsprechenden Erweiterungen unterstützt. Diese Funktion ist für den seltenen Fall vorgesehen, dass die Auflösung in eine nicht-multisample Tiefen-Textur notwendig wird, zum Beispiel beim Rendern in eine von OpenXR bereitgestellte Tiefen-Textur (XR_KHR_composition_layer_depth). Dieser enum-Wert wurde in Qt 6.8 eingeführt. |
enum QRhi::Flag
flags QRhi::Flags
Beschreibt, welche speziellen Funktionen aktiviert werden sollen.
Konstante | Wert | Beschreibung |
---|---|---|
QRhi::EnableDebugMarkers | 1 << 0 | Aktiviert Debug-Marker-Gruppen. Ohne diesen Rahmen sind Debugging-Funktionen wie das Sichtbarmachen von Debug-Gruppen und benutzerdefinierten Ressourcennamen in externen GPU-Debugging-Tools nicht verfügbar und Funktionen wie QRhiCommandBuffer::debugMarkBegin() werden zu No-ops. Vermeiden Sie die Aktivierung in Produktions-Builds, da dies einen kleinen Einfluss auf die Leistung haben kann. Hat keine Auswirkungen, wenn die Funktion QRhi::DebugMarkers nicht als unterstützt gemeldet wird. |
QRhi::EnableTimestamps | 1 << 3 | Aktiviert die GPU-Zeitstempel-Sammlung. Wenn sie nicht gesetzt ist, gibt QRhiCommandBuffer::lastCompletedGpuTime() immer 0 zurück. Aktivieren Sie dies nur, wenn es nötig ist, da es je nach der zugrunde liegenden Grafik-API eine kleine Menge zusätzlicher Arbeit bedeuten kann (z.B. Zeitstempelabfragen). Hat keine Auswirkung, wenn die Funktion QRhi::Timestamps nicht als unterstützt gemeldet wird. |
QRhi::PreferSoftwareRenderer | 1 << 1 | Zeigt an, dass Backends die Wahl eines Adapters oder physischen Geräts bevorzugen sollten, das in Software auf der CPU gerendert wird. Zum Beispiel gibt es bei Direct3D typischerweise einen "Basic Render Driver"-Adapter, der unter DXGI_ADAPTER_FLAG_SOFTWARE verfügbar ist. Das Setzen dieses Flags fordert das Backend auf, diesen Adapter vor allen anderen zu wählen, solange kein bestimmter Adapter durch andere Backend-spezifische Mittel erzwungen wurde. Bei Vulkan entspricht dies der Bevorzugung physischer Geräte mit VK_PHYSICAL_DEVICE_TYPE_CPU . Wenn nicht verfügbar, oder wenn es nicht möglich ist zu entscheiden, ob ein Adapter/Gerät softwarebasiert ist, wird dieses Flag ignoriert. Es kann auch bei Grafik-APIs ignoriert werden, die kein Konzept und keine Mittel zur Aufzählung von Adaptern/Geräten haben. |
QRhi::EnablePipelineCacheDataSave | 1 << 2 | Ermöglicht das Abrufen des Pipeline-Cache-Inhalts, sofern zutreffend. Wenn sie nicht gesetzt ist, gibt pipelineCacheData() immer einen leeren Blob zurück. Bei Backends, bei denen das Abrufen und Wiederherstellen des Pipeline-Cache-Inhalts nicht unterstützt wird, hat das Flag keine Wirkung und die serialisierten Cache-Daten sind immer leer. Das Flag bietet einen Opt-In-Mechanismus, da die Kosten für die Pflege der zugehörigen Datenstrukturen bei einigen Backends nicht unerheblich sind. Bei Vulkan wird diese Funktion direkt auf VkPipelineCache, vkGetPipelineCacheData und VkPipelineCacheCreateInfo::pInitialData abgebildet. Mit Direct3D 11 gibt es keinen echten Pipeline-Cache, aber die Ergebnisse von HLSL->DXBC-Kompilierungen werden gespeichert und können über diesen Mechanismus serialisiert/deserialisiert werden. Dies ermöglicht das Überspringen des zeitaufwendigen D3DCompile() in zukünftigen Durchläufen der Anwendungen für Shader, die mit HLSL-Quellcode statt offline vorkompiliertem Bytecode geliefert werden. Dies kann zu einer enormen Verbesserung der Start- und Ladezeiten führen, wenn viel HLSL-Quellcode kompiliert wird. Bei OpenGL wird der "Pipeline-Cache" durch das Abrufen und Laden von Shader-Programm-Binärdateien simuliert (sofern vom Treiber unterstützt). Bei OpenGL gibt es zusätzliche, festplattenbasierte Caching-Mechanismen für Shader/Programm-Binaries, die von Qt bereitgestellt werden. Das Schreiben in diese kann deaktiviert werden, wenn dieses Flag gesetzt ist, da das Speichern von Programmbinaries in mehreren Caches nicht sinnvoll ist. |
QRhi::SuppressSmokeTestWarnings | 1 << 4 | Gibt an, dass bei Backends, bei denen dies relevant ist, bestimmte, nicht fatale QRhi::create()-Fehler keine qWarning()-Aufrufe erzeugen sollten. Bei D3D11 beispielsweise führt die Übergabe dieses Flags dazu, dass eine Reihe von Warnmeldungen (die aufgrund des Fehlschlagens von QRhi::create() erscheinen) stattdessen als Debug-Ausdrucke unter der allgemein verwendeten Kategorie qt.rhi.general logging kategorisiert werden. Dies kann von Engines wie Qt Quick genutzt werden, die über eine Fallback-Logik verfügen, d.h. sie versuchen den Aufruf von create() mit einem anderen Satz von Flags (z.B. PreferSoftwareRenderer) zu wiederholen, um die unbedingten Warnungen vor der Ausgabe zu verbergen, die ausgegeben werden würde, wenn der erste create()-Versuch fehlgeschlagen ist. |
Der Typ Flags ist ein Typedef für QFlags<Flag>. Er speichert eine ODER-Kombination von Flag-Werten.
enum QRhi::FrameOpResult
Beschreibt das Ergebnis von Vorgängen, die einen weichen Fehler haben können.
Konstante | Wert | Beschreibung |
---|---|---|
QRhi::FrameOpSuccess | 0 | Erfolg |
QRhi::FrameOpError | 1 | Nicht spezifizierter Fehler |
QRhi::FrameOpSwapChainOutOfDate | 2 | Die Swapchain befindet sich intern in einem inkonsistenten Zustand. Dies kann wiederhergestellt werden, indem man versucht, den Vorgang später zu wiederholen (z.B. beginFrame()). |
QRhi::FrameOpDeviceLost | 3 | Das Grafikgerät wurde verloren. Dies kann wiederhergestellt werden, indem Sie versuchen, den Vorgang zu wiederholen (z. B. beginFrame()), nachdem Sie alle von nativen Grafikressourcen unterstützten Objekte freigegeben und neu initialisiert haben. Siehe isDeviceLost(). |
enum QRhi::Implementation
Beschreibt, welches Grafik-API-spezifische Backend von einer QRhi -Instanz verwendet wird.
Konstante | Wert |
---|---|
QRhi::Null | 0 |
QRhi::Vulkan | 1 |
QRhi::OpenGLES2 | 2 |
QRhi::D3D11 | 3 |
QRhi::D3D12 | 5 |
QRhi::Metal | 4 |
enum QRhi::ResourceLimit
Beschreibt das abzufragende Ressourcenlimit.
Konstante | Wert | Beschreibung |
---|---|---|
QRhi::TextureSizeMin | 1 | Minimale Texturbreite und -höhe. Dies ist normalerweise 1. Die minimale Texturgröße wird elegant gehandhabt, d.h. der Versuch, eine Textur mit einer leeren Größe zu erstellen, erzeugt stattdessen eine Textur mit der minimalen Größe. |
QRhi::TextureSizeMax | 2 | Maximale Texturbreite und -höhe. Dies hängt von der Grafik-API und manchmal auch von der Plattform oder Implementierung ab. Normalerweise liegt der Wert im Bereich 4096 - 16384. Der Versuch, Texturen zu erstellen, die größer sind als dieser Wert, wird voraussichtlich fehlschlagen. |
QRhi::MaxColorAttachments | 3 | Die maximale Anzahl von Farbanhängen für ein QRhiTextureRenderTarget, falls mehrere Renderziele unterstützt werden. Wenn MRT nicht unterstützt wird, ist der Wert 1. Ansonsten ist dies typischerweise 8, aber achten Sie auf die Tatsache, dass OpenGL nur 4 als Minimum vorschreibt, und das ist, was einige OpenGL ES-Implementierungen bieten. |
QRhi::FramesInFlight | 4 | Die Anzahl der Frames, die das Backend "im Flug" halten darf: Bei Backends wie Vulkan oder Metal ist es die Aufgabe von QRhi, zu blockieren, wenn ein neues Frame gestartet wird und die CPU bereits N - 1 Frames vor der GPU liegt (weil der in Frame Nr. current - N übermittelte Befehlspuffer noch nicht abgeschlossen ist). Der Wert N ist der Wert, der hier zurückgegeben wird, und ist normalerweise 2. Dies kann für Anwendungen relevant sein, die Rendering direkt mit der Grafik-API integrieren, da ein solcher Rendering-Code möglicherweise die doppelte (wenn der Wert 2 ist) Pufferung für Ressourcen, wie z. B. Puffer, durchführen möchte, ähnlich wie die QRhi Backends selbst. Der aktuelle Frame-Slot-Index (ein Wert, der 0, 1, ..., N-1 durchläuft und dann umläuft) ist über QRhi::currentFrameSlot() abrufbar. Der Wert ist 1 für Backends, bei denen die Grafik-API keine solche Kontrolle auf niedriger Ebene über den Befehlsübermittlungsprozess bietet. Beachten Sie, dass Pipelining auch dann stattfinden kann, wenn dieser Wert 1 ist (einige Backends, wie z.B. D3D11, sind so konzipiert, dass sie versuchen, dies zu ermöglichen, z.B. durch die Verwendung einer Aktualisierungsstrategie für einheitliche Puffer, die die Pipeline nicht abwürgt), aber das wird dann nicht von QRhi kontrolliert und daher hier in der API nicht reflektiert. |
QRhi::MaxAsyncReadbackFrames | 5 | Die Anzahl der submitted Frames (einschließlich des Frames, der die Rücklesung enthält), nach der eine asynchrone Textur- oder Pufferrücklesung auf starting a new frame garantiert abgeschlossen ist. |
QRhi::MaxThreadGroupsPerDimension | 6 | Die maximale Anzahl von Compute-Work/Thread-Gruppen, die abgefertigt werden können. Effektiv der maximale Wert für die Argumente von QRhiCommandBuffer::dispatch(). Normalerweise 65535. |
QRhi::MaxThreadsPerThreadGroup | 7 | Die maximale Anzahl von Aufrufen in einer einzelnen lokalen Arbeitsgruppe, oder in anderer Terminologie, die maximale Anzahl von Threads in einer Thread-Gruppe. Effektiv der maximale Wert für das Produkt aus local_size_x , local_size_y und local_size_z im Compute-Shader. Typische Werte sind 128, 256, 512, 1024 oder 1536. Achten Sie darauf, dass sowohl OpenGL ES als auch Vulkan nur 128 als Mindestgrenze für Implementierungen vorgeben. Während dies für Vulkan unüblich ist, unterstützen einige OpenGL ES 3.1-Implementierungen für mobile/eingebettete Geräte nur den in der Spezifikation festgelegten Mindestwert. |
QRhi::MaxThreadGroupX | 8 | Die maximale Größe einer Work/Thread-Gruppe in der X-Dimension. Effektiv der maximale Wert von local_size_x im Compute-Shader. Normalerweise 256 oder 1024. |
QRhi::MaxThreadGroupY | 9 | Die maximale Größe einer Work/Thread-Gruppe in der Y-Dimension. Effektiv der Maximalwert von local_size_y im Compute-Shader. In der Regel 256 oder 1024. |
QRhi::MaxThreadGroupZ | 10 | Die maximale Größe einer Work/Thread-Gruppe in der Z-Dimension. Effektiv der Maximalwert von local_size_z im Compute-Shader. In der Regel 64 oder 256. |
QRhi::TextureArraySizeMax | 11 | Maximale Textur-Array-Größe. Normalerweise im Bereich 256 - 2048. Der Versuch, create a texture array mit mehr Elementen zu verwenden, wird wahrscheinlich fehlschlagen. |
QRhi::MaxUniformBufferRange | 12 | Die Anzahl der Bytes, die von einem einheitlichen Puffer gleichzeitig an die Shader ausgegeben werden können. Bei OpenGL ES 2.0- und 3.0-Implementierungen kann dieser Wert bis zu 3584 Byte betragen (224 Vektoren mit vier Komponenten und 32 Bit pro Komponente). Andernorts liegt der Wert typischerweise bei 16384 (1024 vec4s) oder 65536 (4096 vec4s). |
QRhi::MaxVertexInputs | 13 | Die Anzahl der Eingabeattribute für den Vertex-Shader. Die Position in einem QRhiVertexInputAttribute muss im Bereich [0, MaxVertexInputs-1] liegen. Der Wert kann bei OpenGL ES 2.0 so niedrig wie 8 sein. Andernorts sind typische Werte 16, 31 oder 32. |
QRhi::MaxVertexOutputs | 14 | Die maximale Anzahl von Ausgaben (4-Komponenten-Vektor-Variablen out ) vom Vertex-Shader. Der Wert kann bei OpenGL ES 2.0 bis zu 8 und bei OpenGL ES 3.0 und einigen Metal-Geräten bis zu 15 betragen. Andernorts ist ein typischer Wert 32. |
Dokumentation der Mitgliedsfunktionen
[noexcept]
QRhi::~QRhi()
Destruktor. Zerstört das Backend und gibt die Ressourcen frei.
void QRhi::addCleanupCallback(const QRhi::CleanupCallback &callback)
Registriert eine callback, die entweder aufgerufen wird, wenn QRhi zerstört wird, oder wenn runCleanup() aufgerufen wird.
Der Callback wird ausgeführt, wenn die Grafikressource noch verfügbar ist, so dass die Anwendung die Möglichkeit hat, QRhiResource Instanzen, die zu QRhi gehören, sauber freizugeben. Dies ist besonders nützlich für die Verwaltung der Lebensdauer von Ressourcen, die in Objekten vom Typ cache
gespeichert sind, wo der Cache QRhiResources oder Objekte enthält, die QRhiResources enthalten.
Siehe auch runCleanup() und ~QRhi().
void QRhi::addCleanupCallback(const void *key, const QRhi::CleanupCallback &callback)
Dies ist eine überladene Funktion.
Registriert callback, um entweder aufgerufen zu werden, wenn QRhi zerstört wird oder wenn runCleanup() aufgerufen wird. Diese Überladung nimmt einen undurchsichtigen Zeiger, key, der verwendet wird, um sicherzustellen, dass ein gegebener Rückruf nur einmal registriert (und somit aufgerufen) wird.
Siehe auch removeCleanupCallback().
QRhi::Implementation QRhi::backend() const
Gibt den Backend-Typ für diese QRhi zurück.
const char *QRhi::backendName() const
Gibt den Backend-Typ als String für dieses QRhi zurück.
[static]
const char *QRhi::backendName(QRhi::Implementation impl)
Gibt einen freundlichen Namen für das Backend impl zurück, normalerweise den Namen der verwendeten 3D-API.
QRhi::FrameOpResult QRhi::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags = {})
Startet einen neuen Frame, der auf den nächsten verfügbaren Puffer von swapChain abzielt.
Ein Frame besteht aus Ressourcenaktualisierungen und einem oder mehreren Render- und Berechnungsdurchläufen.
flags kann auf bestimmte Sonderfälle hinweisen.
Das High-Level-Muster des Renderings in eine QWindow unter Verwendung einer Swapchain:
- Erstellen Sie eine Swapchain.
- Rufen Sie QRhiSwapChain::createOrResize() immer dann auf, wenn die Oberflächengröße anders ist als zuvor.
- Rufen Sie QRhiSwapChain::destroy() auf QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed auf.
- Dann bei jedem 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);
Bei Erfolg wird QRhi::FrameOpSuccess zurückgegeben, bei einem Fehler ein anderer Wert QRhi::FrameOpResult. Einige dieser Fehler sollten als weiche Fehler der Art "Versuchen Sie es später noch einmal" behandelt werden: Wenn QRhi::FrameOpSwapChainOutOfDate zurückgegeben wird, muss die Swapchain durch Aufruf von QRhiSwapChain::createOrResize() in der Größe verändert oder aktualisiert werden. Die Anwendung sollte dann versuchen, einen neuen Frame zu erzeugen. QRhi::FrameOpDeviceLost bedeutet, dass das Grafikgerät verloren ist, aber dies kann auch wiederhergestellt werden, indem alle Ressourcen, einschließlich QRhi selbst, freigegeben werden und dann alle Ressourcen neu erstellt werden. Siehe isDeviceLost() für weitere Informationen.
Siehe auch endFrame(), beginOffscreenFrame(), und isDeviceLost().
QRhi::FrameOpResult QRhi::beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags = {})
Startet einen neuen Offscreen-Frame. Stellt einen Befehlspuffer bereit, der für die Aufzeichnung von Rendering-Befehlen in cb geeignet ist. flags wird verwendet, um bestimmte Sonderfälle anzuzeigen, genau wie bei beginFrame().
Hinweis: Die in *cb gespeicherte QRhiCommandBuffer ist nicht im Besitz des Aufrufers.
Rendering ohne Swapchain ist ebenfalls möglich. Der typische Anwendungsfall ist die Verwendung in Anwendungen außerhalb des Bildschirms, z. B. zum Erzeugen von Bildsequenzen durch Rendering und Rücklesen, ohne jemals ein Fenster anzuzeigen.
Die Verwendung in Onscreen-Anwendungen (also beginFrame, endFrame, beginOffscreenFrame, endOffscreenFrame, beginFrame, ...) ist ebenfalls möglich, reduziert aber die Parallelität und sollte daher nur selten eingesetzt werden.
Offscreen-Frames erlauben es der CPU nicht, einen weiteren Frame zu erzeugen, während die GPU noch den vorherigen verarbeitet. Dies hat den Nebeneffekt, dass die Ergebnisse garantiert zur Verfügung stehen, sobald endOffscreenFrame() zurückkehrt, wenn Readbacks geplant sind. Das ist bei Frames, die auf eine Swapchain abzielen, nicht der Fall: Hier wird die GPU potenziell besser ausgenutzt, aber die Arbeit mit Readback-Operationen erfordert von der Anwendung mehr Sorgfalt, da endFrame() im Gegensatz zu endOffscreenFrame() nicht garantiert, dass die Ergebnisse des Readbacks zu diesem Zeitpunkt verfügbar sind.
Das Grundgerüst für das Rendern eines Frames ohne Swapchain und das anschließende Zurücklesen des Frame-Inhalts könnte wie folgt aussehen:
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
Siehe auch endOffscreenFrame() und beginFrame().
QMatrix4x4 QRhi::clipSpaceCorrMatrix() const
Gibt eine Matrix zurück, die verwendet werden kann, um Anwendungen die Verwendung von OpenGL-gezielten Scheitelpunktdaten und perspektivischen Projektionsmatrizen zu ermöglichen (wie z.B. die, die von QMatrix4x4::perspective() erzeugt werden), unabhängig vom aktiven QRhi Backend.
In einem typischen Renderer können, sobald this_matrix * mvp
anstelle von mvp
verwendet wird, Scheitelpunktdaten mit Y nach oben und Ansichtsfenster mit Tiefenbereich 0 - 1 verwendet werden, ohne zu berücksichtigen, welches Backend (und damit Grafik-API) zur Laufzeit verwendet wird. Auf diese Weise können Verzweigungen, die auf isYUpInNDC() und isClipDepthZeroToOne() basieren, vermieden werden (obwohl eine solche Logik bei der Implementierung bestimmter fortgeschrittener Grafiktechniken dennoch erforderlich sein kann).
Siehe diese Seite für eine Diskussion des Themas aus der Sicht von Vulkan.
[static]
QRhi *QRhi::create(QRhi::Implementation impl, QRhiInitParams *params, QRhi::Flags flags = {}, QRhiNativeHandles *importDevice = nullptr)
Gibt eine neue QRhi -Instanz mit einem Backend für die durch impl angegebene Grafik-API mit dem angegebenen flags zurück. Gibt nullptr
zurück, wenn die Funktion fehlschlägt.
params muss auf eine Instanz einer der Backend-spezifischen Unterklassen von QRhiInitParams verweisen, z. B. QRhiVulkanInitParams, QRhiMetalInitParams, QRhiD3D11InitParams, QRhiD3D12InitParams, QRhiGles2InitParams. Siehe diese Klassen für Beispiele zur Erstellung einer QRhi.
QRhi Die Funktion create() implementiert von Haus aus keine Fallback-Logik: Wenn die angegebene API nicht initialisiert werden kann, schlägt create() fehl und die Backends geben Warnungen in der Debug-Ausgabe aus. Die Clients von QRhi, z. B. Qt Quick, können jedoch zusätzliche Logik bereitstellen, die je nach Plattform einen Rückgriff auf eine andere als die angeforderte API ermöglicht. Wenn die Absicht nur darin besteht, zu testen, ob die Initialisierung erfolgreich ist, wenn man create() zu einem späteren Zeitpunkt aufruft, ist es vorzuziehen, probe() anstelle von create() zu verwenden, weil mit einigen Backends probing in einer leichtgewichtigeren Art und Weise implementiert werden kann, im Gegensatz zu create(), das eine vollständige Initialisierung der Infrastruktur durchführt und verschwenderisch ist, wenn diese QRhi Instanz dann sofort weggeworfen wird.
importDevice erlaubt die Verwendung eines bereits existierenden Grafikgeräts, ohne dass QRhi ein eigenes Gerät erstellt. Wenn nicht null, muss dieser Parameter auf eine Instanz einer der Unterklassen von QRhiNativeHandles zeigen: QRhiVulkanNativeHandles, QRhiD3D11NativeHandles, QRhiD3D12NativeHandles, QRhiMetalNativeHandles, QRhiGles2NativeHandles. Die genauen Details und die Semantik hängen vom Backand und der zugrunde liegenden Grafik-API ab.
Siehe auch probe().
int QRhi::currentFrameSlot() const
Gibt den aktuellen Frame-Slot-Index während der Aufnahme eines Frames zurück. Nicht spezifiziert, wenn der Aufruf außerhalb eines aktiven Frames erfolgt (d.h. wenn isRecordingFrame() false
ist).
Bei Backends wie Vulkan oder Metal liegt es in der Verantwortung des QRhi Backends, zu blockieren, wenn ein neuer Frame gestartet wird und die CPU bereits FramesInFlight - 1
Frames vor der GPU liegt (weil der in Frame Nr. current
- FramesInFlight
übermittelte Befehlspuffer noch nicht abgeschlossen ist).
Ressourcen, die sich von Frame zu Frame ändern können (z. B. das native Pufferobjekt, das ein QRhiBuffer mit dem Typ QRhiBuffer::Dynamic unterstützt), existieren in mehreren Versionen, so dass jeder Frame, der übermittelt werden kann, während ein vorheriger noch verarbeitet wird, mit seiner eigenen Kopie arbeitet, wodurch die Notwendigkeit vermieden wird, die Pipeline bei der Vorbereitung des Frames anzuhalten. (Der Inhalt einer Ressource, die möglicherweise noch in der GPU verwendet wird, sollte nicht angetastet werden, aber einfach immer zu warten, bis das vorherige Bild fertig ist, würde die GPU-Auslastung und letztlich die Leistung und Effizienz verringern).
Vom Konzept her ähnelt dies in gewisser Weise den Copy-on-Write-Schemata, die von einigen C++-Containern und anderen Typen verwendet werden. Es kann auch dem ähneln, was eine OpenGL- oder Direct 3D 11-Implementierung intern für bestimmte Arten von Objekten durchführt.
In der Praxis wird eine solche doppelte (oder dreifache) Pufferung von Ressourcen in den Backends von Vulkan, Metal und ähnlichen QRhi realisiert, indem eine feste Anzahl von nativen Ressourcen (z. B. VkBuffer) slots
hinter einem QRhiResource liegt. Diese können dann durch einen Frame-Slot-Index indiziert werden, der mit 0, 1, ..., FramesInFlight-1 läuft, und dann herumgewickelt werden.
All dies wird für die Benutzer von QRhi transparent gehandhabt. Anwendungen, die das Rendering direkt in die Grafik-API integrieren, möchten jedoch möglicherweise eine ähnliche doppelte oder dreifache Pufferung ihrer eigenen Grafikressourcen durchführen. Das lässt sich am einfachsten erreichen, wenn man die Werte für die maximale Anzahl von Frames während des Fluges (abrufbar über resourceLimit()) und den aktuellen Frame-(Slot-)Index (zurückgegeben von dieser Funktion) kennt.
Siehe auch isRecordingFrame(), beginFrame(), und endFrame().
QRhiDriverInfo QRhi::driverInfo() const
Gibt Metadaten für das von dieser erfolgreich initialisierten QRhi -Instanz verwendete Grafikgerät zurück.
QRhi::FrameOpResult QRhi::endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags = {})
Beendet, überträgt und präsentiert einen Frame, der im letzten beginFrame() auf swapChain begonnen wurde.
Die doppelte (oder dreifache) Pufferung wird intern von QRhiSwapChain und QRhi verwaltet.
flags kann optional verwendet werden, um das Verhalten auf bestimmte Weise zu ändern. Die Übergabe von QRhi::SkipPresent überspringt das Einreihen in die Warteschlange des Present-Befehls oder den Aufruf von swapBuffers.
Gibt bei Erfolg QRhi::FrameOpSuccess oder bei einem Fehler einen anderen Wert QRhi::FrameOpResult zurück. Einige dieser Fehler sollten als weiche Fehler der Art "Versuchen Sie es später noch einmal" behandelt werden: Wenn QRhi::FrameOpSwapChainOutOfDate zurückgegeben wird, muss die Swapchain durch Aufruf von QRhiSwapChain::createOrResize() in der Größe verändert oder aktualisiert werden. Die Anwendung sollte dann versuchen, einen neuen Frame zu erzeugen. QRhi::FrameOpDeviceLost bedeutet, dass das Grafikgerät verloren ist, aber dies kann auch wiederhergestellt werden, indem alle Ressourcen, einschließlich QRhi selbst, freigegeben werden und dann alle Ressourcen neu erstellt werden. Siehe isDeviceLost() für weitere Informationen.
Siehe auch beginFrame() und isDeviceLost().
QRhi::FrameOpResult QRhi::endOffscreenFrame(QRhi::EndFrameFlags flags = {})
Beendet, übergibt und wartet auf den Offscreen-Frame.
flags wird derzeit nicht verwendet.
Siehe auch beginOffscreenFrame().
QRhi::FrameOpResult QRhi::finish()
Wartet auf den Abschluss aller Arbeiten in der Grafikwarteschlange (sofern zutreffend) und führt dann alle aufgeschobenen Vorgänge aus, wie z. B. den Abschluss von Rücklesungen und Ressourcenfreigaben. Kann innerhalb und außerhalb eines Frames aufgerufen werden, jedoch nicht innerhalb eines Passes. Innerhalb eines Frames bedeutet dies, dass die Arbeit am Befehlspuffer abgeschlossen wird.
Hinweis: Vermeiden Sie diese Funktion. Ein Fall, in dem sie benötigt werden kann, ist, wenn die Ergebnisse eines in der Warteschlange stehenden Readbacks in einem Swapchain-basierten Frame zu einem bestimmten Zeitpunkt benötigt werden und daher auf die Ergebnisse gewartet werden soll.
bool QRhi::isClipDepthZeroToOne() const
Gibt true
zurück, wenn die zugrunde liegende Grafik-API den Tiefenbereich [0, 1] im Clip-Raum verwendet.
In der Praxis ist dies false
nur für OpenGL, da OpenGL einen Post-Projection-Tiefenbereich von [-1, 1] verwendet. (nicht zu verwechseln mit der NDC-zu-Fenster-Zuordnung, die von glDepthRange() gesteuert wird, die einen Bereich von [0, 1] verwendet, es sei denn, sie wird von QRhiViewport überschrieben.) In einigen OpenGL-Versionen könnte glClipControl() verwendet werden, um dies zu ändern, aber das OpenGL-Backend von QRhi verwendet diese Funktion nicht, da sie in OpenGL ES oder OpenGL-Versionen kleiner als 4.5 nicht verfügbar ist.
Hinweis: clipSpaceCorrMatrix() enthält die entsprechende Anpassung in der zurückgegebenen Matrix. Daher müssen viele Benutzer von QRhi keine weiteren Maßnahmen ergreifen, abgesehen von der Vormultiplikation ihrer Projektionsmatrizen mit clipSpaceCorrMatrix(). Einige Grafiktechniken, wie z. B. einige Arten der Schattenabbildung, beinhalten jedoch die Arbeit mit und die Ausgabe von Tiefenwerten in den Shadern. Diese müssen gegebenenfalls den Wert dieser Funktion abfragen und berücksichtigen.
bool QRhi::isDeviceLost() const
Gibt true zurück, wenn das Grafikgerät verloren gegangen ist.
Der Verlust des Geräts wird in der Regel in beginFrame(), endFrame() oder QRhiSwapChain::createOrResize() erkannt, je nach Backend und den zugrunde liegenden nativen APIs. Am gebräuchlichsten ist endFrame(), da dort die Präsentation stattfindet. Bei einigen Backends kann QRhiSwapChain::createOrResize() auch aufgrund eines Geräteausfalls fehlschlagen. Daher wird diese Funktion als generische Möglichkeit bereitgestellt, um zu prüfen, ob ein Geräteverlust durch eine frühere Operation erkannt wurde.
Wenn das Gerät verloren gegangen ist, sollten keine weiteren Operationen über QRhi durchgeführt werden. Stattdessen sollten alle QRhi -Ressourcen freigegeben werden, gefolgt von der Zerstörung von QRhi. Anschließend kann versucht werden, ein neues QRhi zu erstellen. Ist dies erfolgreich, müssen alle Grafikressourcen neu initialisiert werden. Wenn nicht, versuchen Sie es später noch einmal, wiederholt.
Während einfache Anwendungen sich nicht um einen Geräteverlust kümmern müssen, kann ein Geräteverlust auf den gängigen Desktop-Plattformen aus verschiedenen Gründen auftreten, z. B. durch physisches Trennen des Grafikadapters, Deaktivieren des Geräts oder des Treibers, Deinstallieren oder Aktualisieren des Grafiktreibers oder aufgrund von Fehlern, die zu einem Reset des Grafikgeräts führen. Einige dieser Gründe können auch unter ganz normalen Umständen auftreten, z.B. ist die Aktualisierung des Grafiktreibers auf eine neuere Version eine übliche Aufgabe, die jederzeit während der Ausführung einer Qt-Anwendung erfolgen kann. Die Benutzer können sehr wohl erwarten, dass die Anwendungen dies überstehen, selbst wenn die Anwendung aktiv eine API wie OpenGL oder Direct3D verwendet.
Von den Qt-eigenen Frameworks, die auf QRhi aufbauen, wie z.B. Qt Quick, kann erwartet werden, dass sie mit einem Geräteverlust umgehen und entsprechende Maßnahmen ergreifen. Wenn die Daten für Grafikressourcen, wie Texturen und Puffer, auf der CPU-Seite noch verfügbar sind, wird ein solches Ereignis auf der Anwendungsebene möglicherweise gar nicht bemerkt, da die Grafikressourcen dann nahtlos neu initialisiert werden können. Von Anwendungen und Bibliotheken, die direkt mit QRhi arbeiten, wird jedoch erwartet, dass sie darauf vorbereitet sind, Geräteverlustsituationen selbst zu überprüfen und zu behandeln.
Hinweis: Bei OpenGL müssen sich Anwendungen möglicherweise für Benachrichtigungen beim Zurücksetzen des Kontexts entscheiden, indem sie QSurfaceFormat::ResetNotification auf QOpenGLContext setzen. Dies geschieht in der Regel durch Aktivierung des Flags in QRhiGles2InitParams::format. Beachten Sie jedoch, dass einige Systeme Kontextrücksetzsituationen erzeugen können, auch wenn dieses Flag nicht gesetzt ist.
bool QRhi::isFeatureSupported(QRhi::Feature feature) const
Gibt true
zurück, wenn die angegebene feature unterstützt wird.
bool QRhi::isRecordingFrame() const
Gibt true zurück, wenn es einen aktiven Frame gibt, d. h. es gab einen beginFrame() (oder beginOffscreenFrame()), dem noch kein endFrame() (oder endOffscreenFrame()) entspricht.
Siehe auch currentFrameSlot(), beginFrame(), und endFrame().
bool QRhi::isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags = {}) const
Gibt true
zurück, wenn die angegebene Textur format modifiziert durch flags unterstützt wird.
Die Abfrage wird sowohl für unkomprimierte als auch für komprimierte Formate unterstützt.
bool QRhi::isYUpInFramebuffer() const
Gibt true
zurück, wenn die zugrunde liegende Grafik-API die Y-Achse in Framebuffern und Bildern nach oben zeigt.
In der Praxis ist dies true
nur für OpenGL.
bool QRhi::isYUpInNDC() const
Gibt true
zurück, wenn die zugrunde liegende Grafik-API die Y-Achse in ihrem normalisierten Gerätekoordinatensystem nach oben zeigt.
In der Praxis ist dies false
nur für Vulkan.
Hinweis: clipSpaceCorrMatrix() enthält die entsprechende Anpassung (damit Y nach oben zeigt) in der zurückgegebenen Matrix.
bool QRhi::makeThreadLocalNativeContextCurrent()
Bei OpenGL wird dadurch der OpenGL-Kontext auf dem aktuellen Thread aktuell. Die Funktion hat keinen Effekt mit anderen Backends.
Der Aufruf dieser Funktion ist typischerweise in Qt-Framework-Code relevant, wenn man sicherstellen muss, dass externer OpenGL-Code, der von der Anwendung bereitgestellt wird, weiterhin wie zuvor mit direkter Verwendung von OpenGL laufen kann, solange QRhi das OpenGL-Backend verwendet.
Gibt false zurück, wenn der Vorgang fehlgeschlagen ist, ähnlich wie QOpenGLContext::makeCurrent(). Wenn die Operation fehlgeschlagen ist, kann isDeviceLost() aufgerufen werden, um festzustellen, ob ein Kontextverlust vorlag. Eine solche Prüfung ist äquivalent zur Prüfung mit QOpenGLContext::isValid().
Siehe auch QOpenGLContext::makeCurrent() und QOpenGLContext::isValid().
[static]
int QRhi::mipLevelsForSize(const QSize &size)
Gibt die Anzahl der mip-Ebenen für eine bestimmte size zurück.
const QRhiNativeHandles *QRhi::nativeHandles()
Gibt einen Zeiger auf die Backend-spezifische Sammlung von nativen Objekten für das Gerät, den Kontext und ähnliche vom Backend verwendete Konzepte zurück.
Cast auf QRhiVulkanNativeHandles, QRhiD3D11NativeHandles, QRhiD3D12NativeHandles, QRhiGles2NativeHandles oder QRhiMetalNativeHandles je nach Bedarf.
Hinweis: Es werden keine Eigentumsrechte übertragen, weder für den zurückgegebenen Zeiger noch für irgendwelche nativen Objekte.
QRhiBuffer *QRhi::newBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, quint32 size)
Gibt einen neuen Puffer mit den angegebenen type, usage, und size zurück.
Hinweis: Einige Kombinationen von usage und type werden möglicherweise nicht von allen Backends unterstützt. Siehe UsageFlags und the feature flags.
Hinweis: Backends können Puffer zuweisen, die größer als size sind. Dies geschieht transparent für Anwendungen, so dass es keine besonderen Einschränkungen für den Wert von size gibt. QRhiBuffer::size() gibt immer den Wert zurück, der in size angefordert wurde.
Siehe auch QRhiResource::destroy().
QRhiComputePipeline *QRhi::newComputePipeline()
Gibt eine neue Compute-Pipeline-Ressource zurück.
Hinweis: Compute ist nur verfügbar, wenn die Funktion Compute als unterstützt gemeldet wird.
Siehe auch QRhiResource::destroy().
QRhiGraphicsPipeline *QRhi::newGraphicsPipeline()
Gibt eine neue Grafik-Pipeline-Ressource zurück.
Siehe auch QRhiResource::destroy().
QRhiRenderBuffer *QRhi::newRenderBuffer(QRhiRenderBuffer::Type type, const QSize &pixelSize, int sampleCount = 1, QRhiRenderBuffer::Flags flags = {}, QRhiTexture::Format backingFormatHint = QRhiTexture::UnknownFormat)
Gibt einen neuen Renderbuffer mit den angegebenen type, pixelSize, sampleCount und flags zurück.
Wenn backingFormatHint auf ein anderes Texturformat als QRhiTexture::UnknownFormat gesetzt ist, kann es vom Backend verwendet werden, um zu entscheiden, welches Format für die Speicherung des Renderbuffers verwendet werden soll.
Hinweis: backingFormatHint wird typischerweise relevant, wenn Multisampling und Fließkomma-Texturformate involviert sind: Rendering in ein Multisample QRhiRenderBuffer und dann Auflösen in ein Nicht-RGBA8 QRhiTexture impliziert (mit einigen Grafik-APIs), dass der Speicher, der den QRhiRenderBuffer unterstützt, das passende Nicht-RGBA8-Format verwendet. Das bedeutet, dass die Übergabe eines Formats wie QRhiTexture::RGBA32F wichtig ist, weil Backends sich typischerweise standardmäßig für QRhiTexture::RGBA8 entscheiden, was dann später beim Versuch, eine RGBA8->RGBA32F Multisample-Auflösung in den Farbanhängen von QRhiTextureRenderTarget einzurichten, scheitern würde.
Siehe auch 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)
Liefert einen neuen Sampler mit dem angegebenen Vergrößerungsfilter magFilter, dem Verkleinerungsfilter minFilter, dem Mipmapping-Modus mipmapMode und den Adressierungsmodi (Wrap) addressU, addressV und addressW.
Hinweis: Wenn Sie mipmapMode auf einen anderen Wert als None
setzen, werden die Bilder für alle relevanten Mip-Levels entweder über texture uploads oder durch den Aufruf von generateMips() für die Textur, die mit diesem Sampler verwendet wird, bereitgestellt. Der Versuch, den Sampler mit einer Textur zu verwenden, die keine Daten für alle relevanten Mip-Level hat, führt zu Rendering-Fehlern, wobei das genaue Verhalten von der zugrunde liegenden Grafik-API abhängt.
Siehe auch QRhiResource::destroy().
QRhiShaderResourceBindings *QRhi::newShaderResourceBindings()
Gibt eine neue Shader-Ressourcenbindungs-Sammlungsressource zurück.
Siehe auch QRhiResource::destroy().
QRhiSwapChain *QRhi::newSwapChain()
Gibt eine neue Swapchain zurück.
Siehe auch QRhiResource::destroy() und QRhiSwapChain::createOrResize().
QRhiTexture *QRhi::newTexture(QRhiTexture::Format format, const QSize &pixelSize, int sampleCount = 1, QRhiTexture::Flags flags = {})
Gibt eine neue 1D- oder 2D-Textur mit den angegebenen format, pixelSize, sampleCount und flags zurück.
Bei einem 1D-Textur-Array muss QRhiTexture::OneDimensional in flags gesetzt sein. Diese Funktion setzt implizit dieses Flag, wenn die pixelSize Höhe 0 ist.
Hinweis: format spezifiziert das angeforderte interne und externe Format, was bedeutet, dass die Daten, die in die Textur hochgeladen werden, in einem kompatiblen Format sein müssen, während die native Textur dieses Format intern verwenden kann (aber nicht muss, zumindest im Falle von OpenGL).
Hinweis: 1D-Texturen sind nur funktionsfähig, wenn die Funktion OneDimensionalTextures zur Laufzeit als unterstützt gemeldet wird. Außerdem sind Mipmaps auf 1D-Texturen nur funktionsfähig, wenn das OneDimensionalTextureMipmaps -Feature zur Laufzeit gemeldet wird.
Siehe auch QRhiResource::destroy().
QRhiTexture *QRhi::newTexture(QRhiTexture::Format format, int width, int height, int depth, int sampleCount = 1, QRhiTexture::Flags flags = {})
Gibt eine neue 1D-, 2D- oder 3D-Textur mit den angegebenen format, width, height, depth, sampleCount und flags zurück.
Diese Überladung ist für 3D-Texturen geeignet, da sie die Angabe von depth ermöglicht. Eine 3D-Textur muss QRhiTexture::ThreeDimensional in flags gesetzt haben, aber mit dieser Überladung kann das weggelassen werden, weil das Flag implizit gesetzt wird, wenn depth größer als 0 ist. Für 1D-, 2D- und Würfeltexturen sollte depth auf 0 gesetzt werden.
Bei einer 1D-Textur muss QRhiTexture::OneDimensional in flags gesetzt sein. Diese Überladung setzt dieses Flag implizit, wenn sowohl height als auch depth 0 sind.
Hinweis: 3D-Texturen sind nur funktionsfähig, wenn die Funktion ThreeDimensionalTextures zur Laufzeit als unterstützt gemeldet wird.
Hinweis: 1D-Texturen sind nur funktionsfähig, wenn das OneDimensionalTextures -Feature zur Laufzeit als unterstützt gemeldet wird. Außerdem sind Mipmaps auf 1D-Texturen nur dann funktionsfähig, wenn das OneDimensionalTextureMipmaps -Feature zur Laufzeit gemeldet wird.
Dies ist eine überladene Funktion.
QRhiTexture *QRhi::newTextureArray(QRhiTexture::Format format, int arraySize, const QSize &pixelSize, int sampleCount = 1, QRhiTexture::Flags flags = {})
Gibt ein neues 1D- oder 2D-Textur-Array mit den angegebenen format, arraySize, pixelSize, sampleCount und flags zurück.
Mit dieser Funktion wird QRhiTexture::TextureArray implizit in flags gesetzt.
Bei einem 1D-Textur-Array muss QRhiTexture::OneDimensional in flags gesetzt sein. Diese Funktion setzt implizit dieses Flag, wenn die Höhe von pixelSize 0 ist.
Hinweis: Verwechseln Sie Textur-Arrays nicht mit Arrays von Texturen. Ein mit dieser Funktion erstelltes QRhiTexture kann mit 1D- oder 2D-Array-Samplern im Shader verwendet werden, zum Beispiel: layout(binding = 1) uniform sampler2DArray texArr;
. Arrays von Texturen bezieht sich auf eine Liste von Texturen, die dem Shader über QRhiShaderResourceBinding::sampledTextures() und einer Anzahl > 1 zugänglich gemacht werden und im Shader z. B. so deklariert sind: layout(binding = 1) uniform sampler2D textures[4];
Hinweis: Dies funktioniert nur, wenn die Funktion TextureArrays zur Laufzeit als unterstützt gemeldet wird.
Hinweis: 1D-Texturen sind nur funktionsfähig, wenn das OneDimensionalTextures -Feature zur Laufzeit als unterstützt gemeldet wird. Außerdem sind Mipmaps auf 1D-Texturen nur dann funktionsfähig, wenn das OneDimensionalTextureMipmaps -Feature zur Laufzeit gemeldet wird.
Siehe auch newTexture().
QRhiTextureRenderTarget *QRhi::newTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc, QRhiTextureRenderTarget::Flags flags = {})
Liefert ein neues Textur-Rendering-Ziel mit der Farbe und den Tiefen-/Schablonenanhängen, die in desc angegeben sind, und mit dem angegebenen flags.
Siehe auch QRhiResource::destroy().
QRhiResourceUpdateBatch *QRhi::nextResourceUpdateBatch()
Gibt einen verfügbaren, leeren Stapel zurück, in dem Kopiervorgänge aufgezeichnet werden können.
Hinweis: Der Rückgabewert ist nicht im Besitz des Aufrufers und darf niemals zerstört werden. Stattdessen wird der Stapel zur Wiederverwendung an den Pool zurückgegeben, indem er an QRhiCommandBuffer::beginPass(), QRhiCommandBuffer::endPass() oder QRhiCommandBuffer::resourceUpdate() übergeben wird, oder indem QRhiResourceUpdateBatch::release() mit ihm aufgerufen wird.
Hinweis: Kann auch außerhalb von beginFrame() - endFrame() aufgerufen werden, da eine Batch-Instanz nur Daten sammelt, aber keine Operationen durchführt.
Da sie nicht an einen aufzuzeichnenden Frame gebunden ist, ist beispielsweise die folgende Sequenz gültig:
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();
Warnung: Die maximale Anzahl von Batches pro QRhi beträgt 64. Wenn diese Grenze erreicht ist, gibt die Funktion null zurück, bis ein Stapel an den Pool zurückgegeben wird.
QByteArray QRhi::pipelineCacheData()
Gibt einen binären Datenblob mit Daten zurück, die von QRhiGraphicsPipeline und QRhiComputePipeline während der Lebensdauer dieses QRhi erfolgreich erstellt wurden.
Durch das Speichern und anschließende erneute Laden der Cache-Daten in späteren Durchläufen derselben Anwendung können die Pipeline- und Shader-Erstellungszeiten potenziell reduziert werden. Was genau der Cache und seine serialisierte Version enthält, ist nicht spezifiziert, ist immer spezifisch für das verwendete Backend und in einigen Fällen auch abhängig von der jeweiligen Implementierung der Grafik-API.
Wenn PipelineCacheDataLoadSave als nicht unterstützt gemeldet wird, ist die zurückgegebene QByteArray leer.
Wenn das Kennzeichen EnablePipelineCacheDataSave beim Aufruf von create() nicht angegeben wurde, kann das zurückgegebene QByteArray leer sein, auch wenn das Merkmal PipelineCacheDataLoadSave unterstützt wird.
Wenn die zurückgegebenen Daten nicht leer sind, sind sie immer spezifisch für die Qt-Version und das QRhi Backend. Darüber hinaus besteht in einigen Fällen eine starke Abhängigkeit vom Grafikgerät und der genauen Treiberversion. QRhi kümmert sich um das Hinzufügen der entsprechenden Header und Schutzmaßnahmen, die sicherstellen, dass die Daten immer sicher an setPipelineCacheData() übergeben werden können.
Hinweis: Der Aufruf von releaseCachedResources() kann, abhängig vom Backend, die gesammelten Pipeline-Daten löschen. Ein anschließender Aufruf dieser Funktion gibt dann möglicherweise keine Daten zurück.
Siehe EnablePipelineCacheDataSave für weitere Einzelheiten zu dieser Funktion.
Hinweis: Minimieren Sie die Anzahl der Aufrufe dieser Funktion. Das Abrufen des Blob ist nicht immer ein billiger Vorgang, und daher sollte diese Funktion nur selten aufgerufen werden, idealerweise nur einmal, z. B. beim Schließen der Anwendung.
Siehe auch setPipelineCacheData(), create(), und isFeatureSupported().
[static]
bool QRhi::probe(QRhi::Implementation impl, QRhiInitParams *params)
Gibt true zurück, wenn zu erwarten ist, dass create() erfolgreich ist, wenn die angegebenen impl und params aufgerufen werden.
Für einige Backends ist dies gleichbedeutend mit dem Aufruf von create(), der Überprüfung des Rückgabewerts und der anschließenden Zerstörung des resultierenden QRhi.
Für andere, insbesondere mit Metal, kann es eine spezielle Probing-Implementierung geben, die das Testen in einer leichtgewichtigeren Weise erlaubt, ohne die Debug-Ausgabe mit Warnungen bei Fehlern zu verschmutzen.
Siehe auch create().
void QRhi::releaseCachedResources()
Versucht, Ressourcen in den Caches des Backends freizugeben. Dies kann sowohl CPU- als auch GPU-Ressourcen umfassen. Nur Speicher und Ressourcen, die automatisch wiederhergestellt werden können, sind im Anwendungsbereich. Wenn zum Beispiel die Backend-Implementierung QRhiGraphicsPipeline einen Cache mit Shader-Kompilierungsergebnissen unterhält, führt der Aufruf dieser Funktion dazu, dass dieser Cache geleert wird, wodurch möglicherweise Speicher und Grafikressourcen freigegeben werden.
Der Aufruf dieser Funktion ist in ressourcenbeschränkten Umgebungen sinnvoll, in denen ab einem bestimmten Punkt eine minimale Ressourcennutzung auf Kosten der Leistung gewährleistet werden muss.
void QRhi::removeCleanupCallback(const void *key)
Deregistriert den Callback mit key. Wenn kein Cleanup-Callback mit key registriert wurde, führt die Funktion nichts aus. Ohne Schlüssel registrierte Rückrufe können nicht entfernt werden.
Siehe auch addCleanupCallback().
int QRhi::resourceLimit(QRhi::ResourceLimit limit) const
Gibt den Wert für die angegebene Ressource limit zurück.
Es wird erwartet, dass die Werte von den Backends bei der Initialisierung abgefragt werden, d. h. der Aufruf dieser Funktion ist eine einfache Operation.
void QRhi::runCleanup()
Ruft alle registrierten Aufräumfunktionen auf. Die Liste der Aufräum-Callbacks wird dann geleert. Normalerweise geschieht dies durch das Zerstören von QRhi automatisch, aber manchmal kann es nützlich sein, die Bereinigung auszulösen, um alle zwischengespeicherten, nicht-essentiellen Ressourcen freizugeben.
Siehe auch addCleanupCallback().
void QRhi::setPipelineCacheData(const QByteArray &data)
Lädt data in den Pipeline-Cache, falls zutreffend.
Wenn PipelineCacheDataLoadSave als nicht unterstützt gemeldet wird, ist der Aufruf der Funktion sicher, hat aber keine Wirkung.
Der von pipelineCacheData() zurückgegebene Blob ist immer spezifisch für die Qt-Version, das QRhi -Backend und in einigen Fällen auch für das Grafikgerät und eine bestimmte Version des Grafiktreibers. QRhi kümmert sich um das Hinzufügen der entsprechenden Header und Schutzmaßnahmen, die sicherstellen, dass die Daten immer sicher an diese Funktion übergeben werden können. Wenn es eine Nichtübereinstimmung gibt, z. B. weil der Treiber auf eine neuere Version aktualisiert wurde oder weil die Daten von einem anderen QRhi Backend generiert wurden, wird eine Warnung ausgegeben und data wird sicher ignoriert.
Bei Vulkan entspricht dies direkt dem VkPipelineCache. Der Aufruf dieser Funktion erstellt ein neues Vulkan-Pipeline-Cache-Objekt, dessen Anfangsdaten von data stammen. Das Pipeline-Cache-Objekt wird dann von allen nachfolgend erstellten QRhiGraphicsPipeline - und QRhiComputePipeline -Objekten verwendet, wodurch die Erstellung der Pipeline potenziell beschleunigt wird.
Bei anderen APIs gibt es keinen echten Pipeline-Cache, aber sie können einen Cache mit Bytecode aus Shader-Kompilierungen (D3D) oder Programmbinärdateien (OpenGL) bereitstellen. Bei Anwendungen, die zur Laufzeit viele Shader-Kompilierungen aus dem Quellcode durchführen, kann dies bei nachfolgenden Durchläufen zu einer erheblichen Verbesserung führen, wenn der "Pipeline-Cache" bei einem früheren Durchlauf mit dieser Funktion vorbesetzt wurde.
Hinweis: QRhi kann nicht garantieren, dass data eine Auswirkung auf die Leistung der Pipeline und der Shader-Erstellung hat. Bei APIs wie Vulkan ist es Sache des Treibers zu entscheiden, ob data für einen bestimmten Zweck verwendet oder ignoriert wird.
Siehe EnablePipelineCacheDataSave für weitere Details zu dieser Funktion.
Hinweis: Dieser von QRhi angebotene Mechanismus ist unabhängig vom internen Caching-Mechanismus des Treibers, falls vorhanden. Das bedeutet, dass je nach Grafik-API und deren Implementierung die genauen Auswirkungen des Abrufs und erneuten Ladens von data nicht vorhersehbar sind. Eine verbesserte Leistung ist möglicherweise überhaupt nicht sichtbar, wenn andere Caching-Mechanismen außerhalb der Kontrolle von Qt bereits aktiv sind.
Hinweis: Minimieren Sie die Anzahl der Aufrufe dieser Funktion. Das Laden des Blob ist nicht immer eine billige Operation, und daher sollte diese Funktion nur selten aufgerufen werden, idealerweise nur einmal, z.B. beim Start der Anwendung.
Siehe auch pipelineCacheData() und isFeatureSupported().
[static]
QSize QRhi::sizeForMipLevel(int mipLevel, const QSize &baseLevelSize)
Gibt die Größe des Texturbildes für eine gegebene mipLevel zurück, berechnet auf der Grundlage der in baseLevelSize angegebenen Größe der Ebene 0.
QRhiStats QRhi::statistics() const
Sammelt und liefert Statistiken über das Timing und die Zuweisungen von Grafikressourcen.
Daten über Speicherzuweisungen sind nur bei einigen Backends verfügbar, bei denen solche Operationen unter der Kontrolle von Qt stehen. Bei Grafik-APIs, bei denen es keine Kontrolle auf unterer Ebene über Speicherzuweisungen gibt, wird dies nie unterstützt und alle relevanten Felder in den Ergebnissen sind 0.
Insbesondere bei Vulkan sind die Werte immer gültig und werden von der zugrunde liegenden Speicherzuweisungsbibliothek abgefragt. Dies gibt Aufschluss über den Speicherbedarf der aktiven Puffer und Texturen.
Das Gleiche gilt für Direct 3D 12. Zusätzlich zu den Statistiken der Speicherzuweisungsbibliothek enthält das Ergebnis hier auch ein Feld totalUsageBytes
, das die Gesamtgröße einschließlich zusätzlicher Ressourcen angibt, die nicht unter der Kontrolle der Speicherzuweisungsbibliothek stehen (Swapchain-Puffer, Deskriptor-Heaps usw.), wie von DXGI gemeldet.
Die Werte entsprechen allen verwendeten Speichertypen in Kombination. (d. h. Video + System im Falle einer diskreten GPU)
Zusätzliche Daten, wie z. B. die Gesamtzeit in Millisekunden, die für die Erstellung von Grafik- und Rechenpipelines aufgewendet wird (was in der Regel Shader-Kompilierung oder Cache-Lookups und potenziell teure Verarbeitung beinhaltet), sind bei den meisten Backends verfügbar.
Hinweis: Die verstrichenen Zeiten für Vorgänge wie die Erstellung von Pipelines können durch verschiedene Faktoren beeinflusst werden. Die Ergebnisse sollten nicht zwischen verschiedenen Backends verglichen werden, da das Konzept der "Pipelines" und was genau unter der Haube passiert, z. B. während eines Aufrufs von QRhiGraphicsPipeline::create(), sich zwischen den Grafik-APIs und ihren Implementierungen stark unterscheiden.
Anmerkung: Zusätzlich werden viele Treiber wahrscheinlich verschiedene Caching-Strategien für Shader, Programme und Pipelines verwenden. (unabhängig von Qt's eigenen ähnlichen Einrichtungen, wie setPipelineCacheData() oder dem OpenGL-spezifischen Programm-Binärdisk-Cache). Da ein solches internes Verhalten für den API-Client transparent ist, haben Qt und QRhi keine Kenntnis oder Kontrolle über die genaue Caching-Strategie, Persistenz, Invalidierung der gecachten Daten usw. Beim Lesen von Zeitangaben, wie z.B. der Zeit für die Erstellung der Pipeline, sollte das mögliche Vorhandensein und nicht spezifizierte Verhalten von Caching-Mechanismen auf Treiberebene berücksichtigt werden.
QList<int> QRhi::supportedSampleCounts() const
Gibt die Liste der unterstützten Stichprobenzahlen zurück.
Ein typisches Beispiel wäre (1, 2, 4, 8).
Bei einigen Backends ist diese Liste der unterstützten Werte im Voraus festgelegt, während bei anderen die (physischen) Geräteeigenschaften angeben, was zur Laufzeit unterstützt wird.
Siehe auch QRhiRenderBuffer::setSampleCount(), QRhiTexture::setSampleCount(), QRhiGraphicsPipeline::setSampleCount(), und QRhiSwapChain::setSampleCount().
QThread *QRhi::thread() const
Gibt den Thread zurück, auf dem die Seite QRhi war initialized.
int QRhi::ubufAligned(int v) const
Gibt den Wert (in der Regel einen Offset) v zurück, der auf die einheitliche Pufferausrichtung ausgerichtet ist, die durch ubufAlignment() angegeben wird.
int QRhi::ubufAlignment() const
Gibt die minimale einheitliche Puffer-Offset-Ausrichtung in Bytes zurück. Dies ist normalerweise 256.
Der Versuch, eine einheitliche Pufferregion mit einem Offset zu binden, der nicht auf diesen Wert ausgerichtet ist, führt je nach Backend und der zugrunde liegenden Grafik-API zu Fehlern.
Siehe auch ubufAligned().
[static]
QRhiSwapChainProxyData QRhi::updateSwapChainProxyData(QRhi::Implementation impl, QWindow *window)
Erzeugt und gibt eine QRhiSwapChainProxyData -Struktur zurück, die undurchsichtige Daten enthält, die spezifisch für das Backend und die Grafik-API sind, die durch impl angegeben werden. window ist die QWindow, auf die eine Swapchain abzielt.
Die zurückgegebene Struktur kann an QRhiSwapChain::setProxyData() übergeben werden. Dies ist bei Rendering-Systemen mit mehreren Threads sinnvoll: Diese statische Funktion sollte im Gegensatz zu allen QRhi Operationen auf dem Haupt-Thread (GUI) aufgerufen und dann an den Thread übertragen werden, der mit QRhi und QRhiSwapChain arbeitet, und an die Swapchain weitergegeben werden. Dies ermöglicht plattformeigene Abfragen, die nur auf dem Haupt-Thread sicher aufgerufen werden können, z.B. die Abfrage des CAMetalLayers von einem NSView, und dann die Weitergabe der Daten an den QRhiSwapChain auf dem Rendering-Thread. Im Metal-Beispiel führt der Zugriff auf view.layer in einem dedizierten Rendering-Thread zu einer Warnung im Xcode Thread Checker. Mit dem Daten-Proxy-Mechanismus wird dies vermieden.
Wenn keine Threads involviert sind, ist das Generieren und Weitergeben von QRhiSwapChainProxyData nicht erforderlich: Backends sind garantiert in der Lage, alles abzufragen, was benötigt wird, und wenn alles auf dem Haupt-(Gui)-Thread läuft, sollte das ausreichend sein.
Hinweis: impl sollte dem entsprechen, mit dem QRhi erstellt wurde. Ein Aufruf mit QRhi::Metal auf einer Nicht-Apple-Plattform wird zum Beispiel keine brauchbaren Daten liefern.
Verwandte Nicht-Mitglieder
[alias, since 6.7]
QRhiShaderResourceBindingSet
Synonym für QRhiShaderResourceBindings.
Dieser Typedef wurde in Qt 6.7 eingeführt.
© 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.