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 kommagetrennten qsb 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 Werkzeug qsb folgt den Versionsnummern im GLSL-Stil, daher entspricht 50 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 ist triangles. Die Option muss angegeben werden, wenn sich ein Tessellation Control Shader in der Liste FILES 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 von VIEW_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-Version 330 und 300 es ist. Für HLSL ist die Mindestversion 61. 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 - Wenn BATCHABLE angegeben ist, wird standardmäßig ein zusätzlicher Scheitelpunkt-Eingang an der Position 7 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 von fxc 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 - Ruft spirv-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, wie FILES, 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 über DEFINES unterschieden wird, kann diese Liste einen Eintrag für jedes Element in FILES 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üsselwort PRECOMPILE angegeben wurde, da fxc 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.