QShaderBaker Class
Kompiliert einen GLSL/Vulkan-Shader in SPIR-V, übersetzt ihn in andere Shading-Sprachen und sammelt Reflection-Metadaten. Mehr...
Header: | #include <QShaderBaker> |
Since: | Qt 6.6 |
Öffentliche Typen
GeneratedShader | |
flags | SpirvOptions |
Öffentliche Funktionen
QShaderBaker() | |
~QShaderBaker() | |
QShader | bake() |
QString | errorMessage() const |
void | setBatchableVertexShaderExtraInputLocation(int location) |
void | setBreakOnShaderTranslationError(bool enable) |
void | setGeneratedShaderVariants(const QList<QShader::Variant> &v) |
void | setGeneratedShaders(const QList<QShaderBaker::GeneratedShader> &v) |
(since 6.7) void | setMultiViewCount(int count) |
void | setPerTargetCompilation(bool enable) |
void | setPreamble(const QByteArray &preamble) |
void | setSourceDevice(QIODevice *device, QShader::Stage stage, const QString &fileName = QString()) |
void | setSourceFileName(const QString &fileName) |
void | setSourceFileName(const QString &fileName, QShader::Stage stage) |
void | setSourceString(const QByteArray &sourceString, QShader::Stage stage, const QString &fileName = QString()) |
void | setTessellationMode(QShaderDescription::TessellationMode mode) |
void | setTessellationOutputVertexCount(int count) |
Detaillierte Beschreibung
Warnung: QShaderBaker, genau wie 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. es wird nur garantiert, dass die API mit der Qt-Version funktioniert, 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 Klasse in einer Anwendung zu verwenden, verlinken Sie auf Qt::ShaderToolsPrivate
(wenn Sie CMake verwenden) und fügen Sie die Header mit dem Präfix rhi
ein, zum Beispiel #include <rhi/qshaderbaker.h>
.
QShaderBaker nimmt einen Grafik- (Vertex, Fragment, etc.) oder Compute-Shader und erzeugt mehrere Varianten davon - entweder im Quell- oder Bytecode - zusammen mit Reflexionsinformationen. Die Ergebnisse werden durch eine QShader -Instanz dargestellt, die auch eine einfache und schnelle Serialisierung und Deserialisierung ermöglicht.
Hinweis: Anwendungen und Bibliotheken wird empfohlen, diese Klasse nicht direkt zu verwenden. Stattdessen wird allen Qt-Benutzern empfohlen, sich auf die Offline-Kompilierung zu verlassen, indem sie das qsb
Kommandozeilen-Tool zur Build-Zeit über CMake aufrufen. Das qsb
Tool verwendet QShaderBaker und schreibt die serialisierte Version der generierten QShader in eine Datei. Die Verwendung dieser Klasse sollte auf Fälle beschränkt werden, in denen eine Kompilierung zur Laufzeit nicht vermieden werden kann, wie z.B. bei der Arbeit mit vom Benutzer bereitgestellten oder dynamisch generierten Shader-Quelltexten.
Als Eingabeformat wird im Moment immer Vulkan-flavored GLSL angenommen. Siehe die GL_KHR_vulkan_glsl-Spezifikation für einen Überblick, wobei zu beachten ist, dass das Qt Shader Tools -Modul für die Verwendung in Kombination mit den QRhi -Klassen des Qt Rendering Hardware Interface-Moduls gedacht ist und daher eine Reihe von Konzepten und Konstrukten (Push-Konstanten, Speicherpuffer, Subpasses usw.) derzeit nicht anwendbar sind. Zusätzliche Optionen können in Zukunft eingeführt werden, zum Beispiel durch die Aktivierung von HLSL als Quellformat, sobald die Kompilierung von HLSL nach SPIR-V als geeignet erachtet wird.
Die Reflection-Metadaten können aus der resultierenden QShader durch Aufruf von QShader::description() abgerufen werden. Dies ist wichtig, um herauszufinden, welche Vertex-Eingänge und Shader-Ressourcen ein Shader erwartet und wie diese aufgebaut sind, da viele moderne Grafik-APIs keine eingebauten Shader-Reflection-Funktionen bieten.
Typischer Arbeitsablauf
Nehmen wir an, eine Anwendung hat einen Vertex- und Fragment-Shader wie den folgenden:
Vertex-Shader:
#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; }
Fragment-Shader:
#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 QShader Instanzen zu erhalten, die als solche an QRhiGraphicsPipeline übergeben werden können, gibt es zwei Möglichkeiten: die Shader-Pack-Generierung kann offline oder zur Laufzeit erfolgen.
Im ersten Fall muss das Tool qsb
ausgeführt werden:
qsb --glsl "100 es,120" --hlsl 50 --msl 12 color.vert -o color.vert.qsb qsb --glsl "100 es,120" --hlsl 50 --msl 12 color.frag -o color.frag.qsb
Das Beispiel verwendet die Übersetzungsziele, die für QRhi geeignet sind. Das bedeutet GLSL/ES 100, GLSL 120, HLSL Shader Model 5.0 und Metal Shading Language 1.2.
Beachten Sie, dass die Befehlszeilenoptionen dem entsprechen, was über setGeneratedShaders() angegeben werden kann. Sobald die resultierenden Dateien verfügbar sind, können sie mit der Anwendung ausgeliefert werden (typischerweise eingebettet in die ausführbare Datei des Qt Resource Systems) und können zur Laufzeit geladen und an QShader::fromSerialized() übergeben werden.
Auch wenn es hier nicht gezeigt wird, kann qsb
mehr tun: es ist auch in der Lage, fxc
unter Windows oder die entsprechenden XCode Tools unter macOS aufzurufen, um den generierten HLSL- oder Metal-Shader-Code in Bytecode zu kompilieren und die kompilierten Versionen in QShader einzubinden. Nachdem ein gebackenes Shader-Paket in eine Datei geschrieben wurde, kann sein Inhalt untersucht werden, indem qsb -d
darauf ausgeführt wird. Führen Sie qsb
mit --help
für weitere Informationen aus.
Der alternative Ansatz besteht darin, das Gleiche zur Laufzeit durchzuführen. Dies beinhaltet das Erstellen einer QShaderBaker-Instanz, den Aufruf von setSourceFileName() und das Einrichten der Übersetzungsziele über setGeneratedShaders():
baker.setGeneratedShaderVariants({ QShader::StandardShader }); QList<QShaderBaker::GeneratedShader> targets; targets.append({ QShader::SpirvShader, QShaderVersion(100) }); targets.append({ QShader::GlslShader, QShaderVersion(100, QShaderVersion::GlslEs) }); targets.append({ QShader::SpirvShader, QShaderVersion(120) }); targets.append({ QShader::HlslShader, QShaderVersion(50) }); targets.append({ QShader::MslShader, QShaderVersion(12) }); baker.setGeneratedShaders(targets); QShader shaders = baker.bake(); if (!shaders.isValid()) qWarning() << baker.errorMessage();
Siehe auch QShader.
Dokumentation der Mitgliedstypen
QShaderBaker::GeneratedShader
Synonym für QPair<QShader::Source, QShaderVersion>.
Dokumentation der Mitgliederfunktionen
QShaderBaker::QShaderBaker()
Konstruiert einen neuen QShaderBaker.
[noexcept]
QShaderBaker::~QShaderBaker()
Zerstörer.
QShader QShaderBaker::bake()
Führt den Kompilierungs- und Übersetzungsprozess durch.
Gibt eine QShader -Instanz zurück. Um zu prüfen, ob der Prozess erfolgreich war, rufen Sie QShader::isValid() auf. Wenn dies false
anzeigt, rufen Sie errorMessage() auf, um das Protokoll abzurufen.
Dies ist eine teure Operation. Wenn Sie dies aus Anwendungen heraus aufrufen, kann es ratsam sein, dies in einem separaten Thread zu tun.
Hinweis: QShaderBaker Instanzen sind wiederverwendbar: Nach dem Aufruf von bake() kann dieselbe Instanz mit anderen Eingaben erneut verwendet werden. Allerdings sollte eine QShaderBaker Instanz während ihrer Lebensdauer nur auf einem einzigen Thread verwendet werden.
QString QShaderBaker::errorMessage() const
Gibt die Fehlermeldung der letzten Ausführung von bake() zurück oder eine leere Zeichenkette, wenn kein Fehler aufgetreten ist.
Hinweis: Zu den Fehlern gehören Fehler beim Lesen von Dateien, bei der Kompilierung und bei der Übersetzung. Keine Ziele oder Varianten anzufordern, zählt nicht als Fehler, auch wenn die resultierende QShader ungültig ist.
void QShaderBaker::setBatchableVertexShaderExtraInputLocation(int location)
Bei der Erzeugung einer QShader::BatchableVertexShader Variante gibt location den Eingabeort für die eingefügte Scheitelpunkt-Eingabe an. Der Wert ist standardmäßig 7 und muss nur überschrieben werden, wenn der Vertex-Shader bereits den Eingabeort 7 verwendet.
void QShaderBaker::setBreakOnShaderTranslationError(bool enable)
Steuert das Verhalten, wenn die Shader-Übersetzung (von SPIR-V nach GLSL/HLSL/MSL) fehlschlägt. Standardmäßig ist diese Einstellung true, was dazu führt, dass bake() mit einem Fehler zurückkehrt, wenn ein angeforderter Shader nicht erzeugt werden kann. Wenn das nicht erwünscht ist und die Absicht ist, das zu erzeugen, was wir können, aber den Rest stillschweigend zu überspringen, dann setzen Sie enable auf false.
Die Ausrichtung auf mehrere GLSL-Versionen kann zu Fehlern führen, wenn ein Feature nicht in eine bestimmte Version übersetzbar ist. Zum Beispiel würde der Versuch, einen Shader mit textureSize() in GLSL ES 100 zu übersetzen, den gesamten bake()-Aufruf mit der Fehlermeldung "textureSize wird in ESSL 100 nicht unterstützt" fehlschlagen lassen. Wenn es akzeptabel ist, keinen GLSL ES 100-Shader im Ergebnis zu haben, obwohl er angefordert wurde, dann führt das Setzen dieses Flags auf false zum Erfolg von bake().
void QShaderBaker::setGeneratedShaderVariants(const QList<QShader::Variant> &v)
Gibt an, welche Shader-Varianten generiert werden. Jede Shader-Version kann mehrere Varianten in der resultierenden QShader haben.
In den meisten Fällen enthält v einen einzigen Eintrag, QShader::StandardShader.
Hinweis: Wenn keine Varianten festgelegt sind, ist die resultierende QShader leer und somit ungültig.
void QShaderBaker::setGeneratedShaders(const QList<QShaderBaker::GeneratedShader> &v)
Gibt an, welche Art von Shadern kompiliert oder übersetzt werden soll. Standardmäßig wird nichts erzeugt, daher ist der Aufruf dieser Funktion vor bake() zwingend erforderlich.
Hinweis: Wenn diese Funktion nicht aufgerufen wird oder v leer ist oder nur ungültige Einträge enthält, wird die resultierende QShader leer und damit ungültig sein.
Das minimal mögliche Backziel ist zum Beispiel SPIR-V, ohne zusätzliche Übersetzungen in andere Sprachen. Um dies anzufordern, tun Sie dies:
baker.setGeneratedShaders({ QShader::SpirvShader, QShaderVersion(100) });
Hinweis: QShaderBaker verarbeitet nur die SPIR-V- und menschenlesbaren Quelltexte. Die weitere Kompilierung in API-spezifische Zwischenformate wie QShader::DxbcShader oder QShader::MetalLibShader wird durch das Befehlszeilenwerkzeug qsb
implementiert und ist nicht Teil der Laufzeit-API QShaderBaker.
[since 6.7]
void QShaderBaker::setMultiViewCount(int count)
Beim Transpilieren von Shadern, die Multiview verwenden (z.B. ein Vertex-Shader, der gl_ViewIndex für einen Renderer verwendet, der auf GL_OVR_multiview2, VK_KHR_multiview usw. basiert), ist es für einige der Ziele notwendig, die Anzahl der Views im Shader zu deklarieren. Dies geschieht nicht im GLSL-Code im Vulkan-Stil und ist für Ziele wie SPIR-V oder HLSL nicht relevant, ist aber für OpenGL und GLSL erforderlich, und daher muss der Wert als zusätzliche Metadaten angegeben werden.
Standardmäßig ist der Wert 0, was das Einfügen der num_views
-Anweisung deaktiviert. Die Einstellung 1 ist nicht sinnvoll, da dies die Standardeinstellung von num_views
ist. Daher sollte count >= 2 sein, um einen Effekt zu erzielen. Wenn der Wert z. B. 2 beträgt, enthält der generierte GLSL-Shader eine layout(num_views = 2) in;
-Anweisung.
Wenn count auf 2 oder höher gesetzt wird, werden auch einige Präprozessoranweisungen eingefügt: QSHADER_VIEW_COUNT
wird auf count gesetzt, während die Erweiterung GL_EXT_multiview
automatisch aktiviert wird. Daher kann die Einstellung von count auch bei anderen Shadertypen von Bedeutung sein, z.B. wenn sich Vertex- und Fragment-Shader einen einheitlichen Puffer teilen und beide Shader in der Lage sein müssen, etwas wie #if QSHADER_VIEW_COUNT >= 2
zu schreiben.
Diese Funktion wurde in Qt 6.7 eingeführt.
void QShaderBaker::setPerTargetCompilation(bool enable)
Setzt die Kompilierung pro Ziel auf enable. Standardmäßig ist dies deaktiviert, was bedeutet, dass der Vulkan/GLSL-Quellcode einmal pro Variante nach SPIR-V kompiliert wird. (also standardmäßig einmal, zweimal, wenn es sich um einen Vertex-Shader handelt, und die Batchable-Variante, wie ebenfalls angefordert). Das resultierende SPIR-V wird dann in die verschiedenen Zielsprachen (GLSL, HLSL, MSL) übersetzt.
Im Modus "Kompilierung pro Zielsprache" gibt es für jedes Ziel einen separaten Kompilierungsschritt von GLSL nach SPIR-V, d. h. für jede GLSL/HLSL/MSL-Version, die über setGeneratedShaders() angefordert wird. Der Eingabe-Quelltext ist derselbe, aber mit zielspezifischen Präprozessor-Definitionen versehen. Dies ist wesentlich zeitaufwändiger, ermöglicht aber Anwendungen, einen einzigen Shader bereitzustellen und #ifdef
Blöcke zur Unterscheidung zu verwenden. Wenn dieser Modus deaktiviert ist, besteht die einzige Möglichkeit, dasselbe zu erreichen, darin, mehrere Versionen der Shader-Datei bereitzustellen, jede separat zu verarbeiten, {.qsb}-Dateien für jede bereitzustellen und die richtige Datei anhand der Laufzeitlogik auszuwählen.
Die folgenden Makros werden in diesem Modus automatisch definiert. Beachten Sie, dass die Makros immer an Shading-Sprachen gebunden sind, nicht an Grafik-APIs.
QSHADER_SPIRV
- definiert, wenn SPIR-V angestrebt wird (und typischerweise von Vulkan verwendet wird).QSHADER_SPIRV_VERSION
- die angestrebte SPIR-V-Versionsnummer, z. B.100
.QSHADER_GLSL
- definiert, wenn GLSL oder GLSL ES verwendet werden soll (in der Regel von OpenGL oder OpenGL ES genutzt)QSHADER_GLSL_VERSION
- die angestrebte GLSL- oder GLSL ES-Versionsnummer, z. B.100
,300
oder330
.QSHADER_GLSL_ES
- nur definiert, wenn GLSL ES als Ziel verwendet wirdQSHADER_HLSL
- definiert, wenn HLSL angestrebt wird (in der Regel von Direct 3D verwendet)QSHADER_HLSL_VERSION
- die angestrebte HLSL-Shader-Modell-Version, z. B.50
QSHADER_MSL
- definiert, wenn es um die Metal Shading Language geht (wird in der Regel von Metal verwendet)QSHADER_MSL_VERSION
- die angestrebte MSL-Version, z. B.12
oder20
.
Dies ermöglicht das Schreiben von Shader-Code wie dem folgenden.
#if QSHADER_HLSL || QSHADER_MSL vec2 uv = vec2(uv_coord.x, 1.0 - uv_coord.y); #else vec2 uv = uv_coord; #endif
Hinweis: Versionsnummern folgen der GLSL-inspirierten QShaderVersion Syntax und sind daher immer eine einzelne ganze Zahl.
Hinweis: Es gibt nur ein QShaderDescription pro QShader, unabhängig davon, wie viele individuelle Ziele es gibt. Daher dürfen Mitglieder von Uniform-Blöcken, Vertex-Eingänge usw. nicht mit den oben beschriebenen Makros konditioniert werden.
Warnung: Beachten Sie die Unterschiede zwischen den Konzepten von Grafik-APIs und Schattierungssprachen. QShaderBaker und die zugehörigen Werkzeuge arbeiten strikt mit dem Konzept der Schattierungssprachen und ignorieren, wie die Ergebnisse anschließend verbraucht werden. Wenn also die höheren Schichten im Qt-Grafikstapel eines Tages anfangen, SPIR-V auch für eine andere API als Vulkan zu verwenden, wird die Annahme, dass QSHADER_SPIRV Vulkan impliziert, nicht mehr gelten.
void QShaderBaker::setPreamble(const QByteArray &preamble)
Gibt eine benutzerdefinierte preamble an, die vor dem normalen Shader-Code verarbeitet wird.
Dies ist mehr als nur das Voranstellen des Quelltextes: die Gültigkeit der GLSL-Versionsanweisung, die vor allem anderen platziert werden muss, wird nicht beeinflusst. Die Zeilennummern in den gemeldeten Fehlermeldungen bleiben ebenfalls unverändert und ignorieren den in preamble angegebenen Inhalt.
Ein Anwendungsfall für Präambeln ist das transparente Einfügen dynamisch erzeugter #define
Anweisungen.
void QShaderBaker::setSourceDevice(QIODevice *device, QShader::Stage stage, const QString &fileName = QString())
Legt die Quelle device fest. Dies ermöglicht die Verwendung beliebiger QIODevice anstelle von Dateien. stage gibt die Shaderstufe an, während das optionale fileName einen Dateinamen enthält, der in den Fehlermeldungen verwendet wird.
void QShaderBaker::setSourceFileName(const QString &fileName)
Setzt den Namen der Shader-Quelldatei auf fileName. Dies ist die Datei, die beim Aufruf von bake() gelesen wird. Die Shader-Stufe wird automatisch aus der Dateierweiterung abgeleitet. Wenn dies nicht gewünscht oder nicht möglich ist, verwenden Sie stattdessen die Überladung mit dem Argument stage.
Die unterstützten Dateierweiterungen sind:
.vert
- Vertex-Shader.frag
- Fragment-Shader (Pixel-Shader).tesc
- Tessellierungssteuerung (Hüllenshader) Shader.tese
- Tesselierungsauswertung (Domäne) Shader.geom
- Geometrie-Shader.comp
- Berechnungs-Shader
void QShaderBaker::setSourceFileName(const QString &fileName, QShader::Stage stage)
Setzt den Namen der Shader-Quelldatei auf fileName. Dies ist die Datei, die beim Aufruf von bake() gelesen wird. Die Shader-Stufe wird durch stage angegeben.
void QShaderBaker::setSourceString(const QByteArray &sourceString, QShader::Stage stage, const QString &fileName = QString())
Setzt den Eingangsshader sourceString. stage spezifiziert die Shaderstufe, während das optionale fileName einen Dateinamen enthält, der in den Fehlermeldungen verwendet wird.
void QShaderBaker::setTessellationMode(QShaderDescription::TessellationMode mode)
Bei der Generierung von MSL-Shader-Code für einen Tesselation Control Shader muss die Tesselation mode (Dreiecke oder Quads) im Voraus bekannt sein. In GLSL wird dies in der Regel im Tessellierungs-Evaluierungs-Shader deklariert, aber für Metal muss es auch bekannt sein, wenn der Berechnungs-Shader aus dem Tessellierungs-Steuerungs-Shader erzeugt wird.
Wenn nicht gesetzt, ist die Vorgabe Dreiecke.
void QShaderBaker::setTessellationOutputVertexCount(int count)
Bei der Generierung von MSL-Shader-Code für einen Tessellation-Evaluierungs-Shader muss die Vertex-Ausgabe count des Tessellation-Control-Shaders im Voraus bekannt sein. In GLSL würde dies typischerweise im Tessellation-Control-Shader deklariert werden, aber für Metal muss es auch bei der Generierung des Vertex-Shaders aus dem Tessellation-Evaluierungs-Shader bekannt sein.
Wenn er nicht gesetzt ist, ist der Standardwert 3.
© 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.