Qt Shader Tools Integration des Build-Systems
Kompiliert Shader und fügt sie zu einer Qt-Ressource hinzu
Einführung
Das Qt Shader Tools Modul stellt eine CMake-Makro-Datei zur Verfügung, die nützliche Funktionen bereitstellt, die Anwendungen in ihrem CMakeLists.txt
verwenden können.
Wenn die qt6_add_shaders
Funktion verwendet wird, wird das qsb Tool automatisch vom Build System aufgerufen und die resultierenden .qsb
Dateien werden implizit zum Ressourcensystem hinzugefügt.
Erstes Beispiel
Lassen Sie uns ein einfaches Beispiel betrachten. Nehmen wir an, wir haben eine Qt Quick Anwendung, die ihren eigenen Wobble-Effekt über ShaderEffect bereitstellen möchte. Der Fragment-Shader ist in wobble.frag
implementiert. Die Eigenschaft fragmentShader des Elements ShaderEffect verweist auf wobble.frag.qsb
. Wie stellen wir sicher, dass diese .qsb-Datei zur Build-Zeit erzeugt wird?
... project(exampleapp LANGUAGES CXX) ... find_package(Qt6 COMPONENTS ShaderTools) ... qt6_add_executable(exampleapp main.cpp ) ... qt6_add_resources(exampleapp "exampleapp" PREFIX "/" FILES "main.qml" ) qt6_add_shaders(exampleapp "exampleapp_shaders" PREFIX "/" FILES "wobble.frag" )
Die obigen Angaben reichen aus, damit die Anwendung zur Laufzeit auf :/wobble.frag.qsb
zugreifen kann. Der ursprüngliche GLSL-Quellcode im Vulkan-Stil (wobble.frag) ist nicht in der ausführbaren Datei der Anwendung enthalten und muss nicht ausgeliefert werden. Wenn der Shader-Code Fehler enthält, werden die glslang
Compiler-Meldungen zur Erstellungszeit ausgegeben und die Erstellung schlägt fehl. Wenn die Shader-Quelldatei geändert wird, werden die Änderungen beim nächsten Build automatisch übernommen, wie bei C++ und anderen Quelldateien.
Der Schlüssel ist die Funktion qt6_add_shaders
, die Ähnlichkeit mit qt6_add_resources
hat. Ohne weitere Parameter anzugeben, führt die Funktion dazu, dass qsb mit einem vernünftigen Satz von Standardargumenten ausgeführt wird, die für Fragment-Shader geeignet sind, wenn sie auf Vulkan, Metal, Direct 3D und OpenGL oder OpenGL ES ausgerichtet sind.
Hinweis: Achten Sie auf die Zeile find_package
. Es ist wichtig, find_package
für ShaderTools
einzuschließen, andernfalls wird qt6_add_shaders
nicht verfügbar sein.
Hinweis: Das Ziel, das als erstes Argument der Funktion qt6_add_shaders
übergeben wird, muss vorhanden sein, bevor die Funktion aufgerufen wird.
Hinweis: Es werden mehrere qt6_add_shaders
-Aufrufe unterstützt. In komplexen Anwendungen ist es nicht unwahrscheinlich, dass verschiedene Sätze von Shadern unterschiedliche Einstellungen benötigen. Der Name nach dem Projekt ("exampleapp_shaders"
im obigen Beispiel) muss bei jedem Aufruf eindeutig sein.
Konfiguration
In der Voreinstellung ruft qt6_add_shaders
qsb wie folgt auf:
qsb --glsl "100 es,120,150" --hlsl 50 --msl 12 -o <output>.qsb <input>
Das bedeutet, dass das resultierende Paket SPIR-V (für Vulkan 1.0), GLSL ES 100 (für OpenGL ES 2.0 und neuer), GLSL 120 (für OpenGL-Kontexte ohne Kernprofil), GLSL 150 (für OpenGL-Kontexte mit Kernprofil), HLSL-Quellen für Shader Model 5.0 (für Direct3D 11.1) und Metal Shading Language 1.2-Quellen (für Metal) enthält.
Dies ist ein guter Satz von Vorgaben für Qt Quick und schafft Anwendungen, die in hohem Maße auf eine Vielzahl von Systemen portabel sind. Diese Standardeinstellungen sind jedoch nicht immer geeignet. Wenn der Shader Funktionen oder Konstrukte verwendet, die keine Entsprechung in diesen Targets haben, wird der Prozess und damit der Build fehlschlagen. In diesem Fall müssen die Targets angepasst werden, und das bedeutet auch, dass die minimalen Systemanforderungen der Anwendung implizit angepasst werden. Nehmen wir als Beispiel die GLSL-Funktion textureLod
, die nur mit OpenGL ES 3.0 und höher (d. h. GLSL ES 300 oder höher) verfügbar ist. Wenn Sie GLSL 300 es
anstelle von 100 es
anfordern, wird der Build erfolgreich sein, aber die resultierende Anwendung erfordert nun OpenGL ES 3.0 oder höher und ist nicht mit OpenGL ES 2.0-basierten Systemen kompatibel.
Shader-Typ
Der Typ des Shaders wird aus der Dateierweiterung abgeleitet. Daher muss die Erweiterung eine der folgenden sein:
.vert
- für Vertex-Shader.tesc
- für Tesselationssteuerungs-Shader.tese
- für Tesselationsauswertungs-Shader.frag
- für Fragment-Shader (Pixel-Shader).comp
- für Berechnungs-Shader
Hinweis: Tessellierungssteuerungs- und Evaluierungs-Shader werden derzeit nicht von Direct 3D (HLSL) unterstützt. Eine mögliche Umgehung dieses Problems ist die manuelle Erstellung von Hull- und Domain-Shadern und deren Einbindung über die Dateisubstitutionssyntax im Abschnitt FILES
.
Ziele
Die folgenden Schlüsselwörter sind verfügbar:
GLSL
- Fordert die Generierung von Quellcode für die angegebene Liste von GLSL-Versionen an. Achten Sie darauf, dass die Liste der kommagetrenntenqsb
Syntax folgt. Ein Compute-Shader wird zum Beispiel"310 es,430"
hier angeben wollen, da die Standardwerte für ihn nicht geeignet sind.NOGLSL
- Dieses argumentlose Schlüsselwort deaktiviert die Erzeugung von GLSL-Quellen. Geeignet für Anwendungen, die überhaupt nicht mit OpenGL arbeiten wollen.HLSL
- Fordert die Generierung von Quellcode für die angegebene Liste von HLSL-Versionen (Shader-Modell) an. Das Werkzeugqsb
folgt den Versionsnummern im GLSL-Stil, daher entspricht50
dem Shader Model 5.0,51
ist 5.1.NOHLSL
- Dieses argumentlose Schlüsselwort deaktiviert die Erzeugung von HLSL-Quellen. Geeignet für Anwendungen, die überhaupt nicht mit Direct 3D arbeiten wollen.MSL
- Fordert die Generierung von Quellcode für die angegebene Version der Metal Shading Language an.12
entspricht 1.2,20
entspricht 2.0.NOMSL
- Dieses argumentlose Schlüsselwort deaktiviert die Generierung von MSL-Quellcode. Es eignet sich für Anwendungen, die überhaupt nicht mit Metal arbeiten wollen.
Die am häufigsten außer Kraft gesetzte Einstellung ist GLSL
. Wenn die Shader der Anwendung zum Beispiel OpenGL 3.x-Funktionen verwenden, wird sie wahrscheinlich etwas höheres als 100 es
oder 120
angeben wollen:
qt_add_shaders(exampleapp "res_gl3shaders" GLSL "300es,330" PREFIX "/shaders" FILES shaders/ssao.vert shaders/ssao.frag shaders/skybox.vert shaders/skybox.frag )
Hinweis: Das Leerzeichen vor dem Suffix es
ist optional.
Tesselierung
TESSELLATION
- Dieses argumentlose Schlüsselwort zeigt an, dass die Shader in einer Pipeline verwendet werden, die Tesselation verwendet. Dies ist nur relevant, wenn Vertex-Shader aufgeführt sind und die Metal-Shader-Generierung nicht deaktiviert ist. Siehe dieses Snippet für ein Beispiel.Diese Option wurde in Qt 6.5 eingeführt.
TESSELLATION_VERTEX_COUNT
- Diese Option nimmt eine Zahl an, die die Anzahl der ausgegebenen Vertexe von der Tessellation Control Stage angibt. Die Angabe dieser Zahl ist obligatorisch für Tessellation Evaluation Shader, die mit Metal verwendet werden. Der Standardwert ist 3. Wenn er nicht mit der Tessellation Control Stage übereinstimmt, wird der generierte MSL-Code nicht wie erwartet funktionieren.Diese Option wurde in Qt 6.5 eingeführt.
TESSELLATION_MODE
- Diese Option legt den Tesselierungsmodus fest. Sie kann einen von zwei Werten annehmen:"triangles"
oder"quads"
. Der Standardwert isttriangles
. Die Option muss angegeben werden, wenn sich ein Tessellation Control Shader in der ListeFILES
befindet. Sie muss mit der Tessellationsevaluierungsstufe übereinstimmen.Diese Option wurde in Qt 6.5 eingeführt.
Mehrere Ansichten
VIEW_COUNT
- Diese Option gibt die Anzahl der Ansichten an, mit denen ein Vertex-Shader verwendet wird. Wenn Sie mit Multiview arbeiten (GL_OVR_multiview2, VK_KHR_multiview, D3D12 view instancing, etc.), geben Sie immer den korrekten VIEW_COUNT mit einem Wert >= 2 für die entsprechenden Shader an, um die Generierung von korrektem GLSL Shader Code zu ermöglichen. Beachten Sie jedoch, dass das Setzen von VIEW_COUNT für Vertex-Shader, die nicht auf Multiview angewiesen sind, vermieden werden sollte, da das Setzen des Wertes den generierten GLSL-Code effektiv multiview-abhängig macht. Um dies zu umgehen, gruppieren Sie die Vertex-Shader entsprechend in mehrere qt_add_shaders() Aufrufe. Das Setzen vonVIEW_COUNT
fügt automatisch ein Präprozessor-Definit,QSHADER_VIEW_COUNT
, mit demselben Wert in den Shader-Quellcode ein. Zusätzlich wird die Zeile#extension GL_EXT_multiview : require
automatisch in Vertex-Shadern eingefügt, wenn eine View-Anzahl von 2 oder größer eingestellt ist. Beachten Sie, dass für Multiview die minimale GLSL-Version330
und300 es
ist. Für HLSL ist die Mindestversion61
. Anwendungen wird empfohlen, die Sprachziele entsprechend einzustellen (oder auf neuere Versionen).Diese Option wurde in Qt 6.7 eingeführt.
MULTIVIEW
- Fordert die Generierung sowohl eines Non-Multiview- als auch eines View-Count-2-Shadersatzes an. Dies ist praktisch eine Erleichterung für die manuelle Erstellung von zwei qt_add_shaders()-Aufrufen mit den entsprechenden GLSL/HLSL/MSL/VIEW_COUNT-Argumenten. Diese Option ist in erster Linie für den eigenen Gebrauch von Qt gedacht, aber auch Anwendungen können sie nutzen, solange die impliziten Einstellungen für die Multiview-Varianten für die Shader der Anwendung ausreichend sind; diese sind: GLSL 330.300es HLSL 61 MSL 12. VIEW_COUNT ist für die Multiview-Varianten auf 2 gesetzt. Die Multiview-Varianten werden in Dateien mit dem Suffix.mv2qsb
gespeichert (zusätzlich zu.qsb
).Diese Option wurde in Qt 6.8 eingeführt.
Qt Quick Besonderheiten
BATCHABLE
- Die Angabe dieses einzelnen, argumentlosen Schlüsselworts ist wesentlich für Vertex-Shader, die mit Qt Quick verwendet werden, entweder in einer ShaderEffect oder in einer QSGMaterialShader. Es hat keine Auswirkung auf Fragment- oder Compute-Shader, und verschiedene Typen können sicher in dieselbe Liste aufgenommen werden, da das Schlüsselwort nur für die.vert
-Dateien berücksichtigt wird. Äquivalent zum-b
Argument von qsb.ZORDER_LOC
- WennBATCHABLE
angegeben ist, wird standardmäßig ein zusätzlicher Scheitelpunkt-Eingang an der Position7
injiziert. Dieses Schlüsselwort wird verwendet, um diesen Ort auf einen anderen Wert zu ändern. Dies ist von Bedeutung, wenn der Vertex-Shader viele Eingänge hat und 7 in Gebrauch ist, was zu Konflikten führen würde.
Aufrufen externer Werkzeuge
PRECOMPILE
- Äquivalent zu den Optionen-c
oder-t
von qsb, abhängig von der Plattform. Bei der Erstellung unter Windows führt dies zum Aufruf vonfxc
aus dem Windows SDK, um die erste Phase der Kompilierung (HLSL-Quellcode zu DXBC-Bytecode) zur Erstellungszeit statt zur Laufzeit durchzuführen. Die resultierende Datei.qsb
enthält nur die Kompilierungsergebnisse (das Shader-Zwischenformat), nicht den ursprünglichen Shader-Quellcode.OPTIMIZED
- Ruftspirv-opt
auf (das im Vulkan-SDK oder anderswo verfügbar sein muss), um Optimierungen am SPIR-V-Bytecode vorzunehmen. Äquivalent zum-O
Argument von qsb.
Andere Einstellungen
DEFINES
- Definiert Makros, die während der Shader-Kompilierung aktiv sind. Äquivalent zum-D
Argument von qsb. Die Liste hat die Form von"name1=value1;name2=value2"
. Alternativ kann die Liste, wieFILES
, durch Zeilenumbrüche getrennt werden.OUTPUTS
- Wenn der Name der erzeugten .qsb-Datei sich von der Quelle unterscheiden muss, z.B. weil eine Shader-Datei als Quelle für mehrere .qsb-Dateien dient, weil überDEFINES
unterschieden wird, kann diese Liste einen Eintrag für jedes Element inFILES
enthalten, der einen Dateinamen angibt, der typischerweise mit.qsb
endet. Der angegebene Name wird dann im Argument-o
an qsb übergeben, anstatt nur.qsb
an den Quelldateinamen anzuhängen.DEBUGINFO
- Ermöglicht die Generierung vollständiger Debug-Informationen für SPIR-V, so dass Werkzeuge wie RenderDoc den vollständigen Quelltext anzeigen können, wenn eine Pipeline inspiziert wird oder wenn Vertex- oder Fragment-Debugging durchgeführt wird. Äquivalent zum-g
Argument von qsb. Hat auch Auswirkungen auf Direct 3D, wenn das SchlüsselwortPRECOMPILE
angegeben wurde, dafxc
dann angewiesen wird, Debug-Informationen in den generierten Zwischen-Bytecode aufzunehmen.QUIET
- Unterdrückt Debug- und Warnausgaben von qsb. Nur fatale Fehler werden ausgegeben.OUTPUT_TARGETS
- Wenn qt_add_shaders mit statischen Bibliotheken verwendet wird, werden ein oder mehrere spezielle Ziele erzeugt. Wenn Sie eine zusätzliche Verarbeitung dieser Ziele wünschen, übergeben Sie einen Wert an den Parameter OUTPUT_TARGETS.
Ersetzen von selbst erstellten Shadern
Die CMake-Integration unterstützt auch die Angabe von Ersetzungen für bestimmte Versionen des Shaders in der resultierenden .qsb-Datei. Dies entspricht der Ausführung von qsb mit der Kommandozeilenoption -r
.
Dies wird durch die folgende spezielle Syntax in der FILES-Liste ermöglicht:
FILES "shaders/externalsampler.frag@glsl,100es,shaders/externalsampler_gles.frag"
Dem Dateinamen kann eine beliebige Anzahl von @-getrennten Ersetzungsangaben folgen. Jede dieser Angaben spezifiziert die Schattierungssprache, die Version und die Datei, aus der die Daten gelesen werden sollen, getrennt durch Kommata. Einzelheiten finden Sie im QSB-Handbuch.
Beispiel für Tesselation
Nehmen wir eine Grafik-Pipeline, die aus vier Stufen besteht, der Vertex-Stufe mit dem Shader vertex.vert
, der Tessellierungs-Steuerungsstufe mit dem Shader tess.tesc
, der Tessellierungs-Auswertungsstufe mit dem Shader tess.tese
und der Fragment-Stufe mit dem Shader fragment.frag
.
Um eine vollständig portable Anwendung zu erstellen, die mit allen Vulkan-, OpenGL-, Metal- und Direct 3D-Systemen funktionieren kann, müssen zwei wichtige Dinge beachtet werden: Die HLSL-Versionen der Tessellationsshader müssen manuell erstellt und dann injiziert werden. Bei Metal hingegen muss das entsprechende Schlüsselwort angegeben werden.
Zunächst werden die Vertex- und Fragment-Shader aufgelistet. Um Metal zu unterstützen, wird das Schlüsselwort TESSELLATION
hinzugefügt. Dies ermöglicht eine spezielle Verarbeitung und Übersetzung für vertex.vert
bei der Generierung des Metal-Shader-Codes. Für OpenGL schränken wir die GLSL-Sprachversion ein, da die Tesselation-Unterstützung nur in neueren OpenGL-Versionen verfügbar ist.
qt6_add_shaders(project "shaders_tessellation_part1" PREFIX "/shaders" GLSL "410,320es" TESSELLATION FILES "vertex.vert" "fragment.frag" )
Zweitens werden die Tessellationsshader in einem separaten qt6_add_shaders()-Aufruf aufgeführt. Dies ist auf das Schlüsselwort NOHLSL
zurückzuführen. Die Vertex- und Fragment-Shader sollten weiterhin wie üblich in HLSL übersetzt werden, so dass es nicht möglich ist, alle vier Shader in einem einzigen qt6_add_shaders()-Aufruf unterzubringen. Für Metal werden einige Tessellation-Einstellungen (Output Vertex Count, Mode) angegeben, da diese im Gegensatz zu Vulkan und OpenGL im Voraus bekannt sein müssen.
qt6_add_shaders(project "shaders_tessellation_part2" PREFIX "/shaders" NOHLSL GLSL "410,320es" TESSELLATION_VERTEX_COUNT 3 TESSELLATION_MODE "triangles" FILES "tess.tesc@hlsl,50,tess_hull.hlsl" "tess.tese@hlsl,50,tess_domain.hlsl" )
Hinweis: Das manuelle Schreiben von Hull- und Domain-HLLS-Shadern wird nur für fortgeschrittene Benutzer empfohlen. Bestimmte Konstrukte, wie z. B. konstante Puffer, erfordern besondere Sorgfalt, damit alle Ressourcenschnittstellen und Layouts mit den SPIR-V/GLSL/MSL-Shadern kompatibel bleiben.
© 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.