QSB-Handbuch
qsb
ist ein Kommandozeilenwerkzeug, das vom Qt Shader Tools Modul bereitgestellt wird. Es integriert Bibliotheken von Drittanbietern wie glslang und SPIRV-Cross, ruft optional externe Werkzeuge wie fxc
oder spirv-opt
auf und erzeugt .qsb
Dateien. Zusätzlich kann es verwendet werden, um den Inhalt eines .qsb
Pakets zu untersuchen.
Usage: qsb [options] file Qt Shader Baker (using QShader from Qt 6.8.0) Options: -?, -h, --help Displays help on commandline options. --help-all Displays help, including generic Qt options. -v, --version Displays version information. -b, --batchable Also generates rewritten vertex shader for Qt Quick scene graph batching. --zorder-loc <location> The extra vertex input location when rewriting for batching. Defaults to 7. --glsl <versions> Comma separated list of GLSL versions to generate. (for example, "100 es,120,330") --hlsl <versions> Comma separated list of HLSL (Shader Model) versions to generate. F.ex. 50 is 5.0, 51 is 5.1. --msl <versions> Comma separated list of Metal Shading Language versions to generate. F.ex. 12 is 1.2, 20 is 2.0. --qt6 Equivalent to --glsl "100 es,120,150" --hlsl 50 --msl 12. This set is commonly used with shaders for Qt Quick materials and effects. --msltess Indicates that a vertex shader is going to be used in a pipeline with tessellation. Mandatory for vertex shaders planned to be used with tessellation when targeting Metal (--msl). --tess-vertex-count <count> The output vertex count from the tessellation control stage. Mandatory for tessellation evaluation shaders planned to be used with Metal. The default value is 3. If it does not match the tess.control stage, the generated MSL code will not function as expected. --tess-mode <mode> The tessellation mode: triangles or quads. Mandatory for tessellation control shaders planned to be used with Metal. The default value is triangles. Isolines are not supported with Metal. If it does not match the tess.evaluation stage, the generated MSL code will not function as expected. --view-count <num_views> The number of views the shader is used with. num_views must be >= 2. Mandatory when multiview rendering is used (gl_ViewIndex). Set only for vertex shaders that really do rely on multiview (as the resulting asset is tied to num_views). Can be set for fragment shaders too, to get QSHADER_VIEW_COUNT auto-defined. (useful for ensuring uniform buffer layouts) -g Generate full debug info for SPIR-V and DXBC -O Invoke spirv-opt (external tool) to optimize SPIR-V for performance. -o, --output <filename> Output file for the shader pack. --qsbversion <version> QSB version to use for the output file. By default the latest version is automatically used, use only to bake compatibility versions. F.ex. 64 is Qt 6.4. -c, --fxc In combination with --hlsl invokes fxc (SM 5.0/5.1) or dxc (SM 6.0+) to store DXBC or DXIL instead of HLSL. -t, --metallib In combination with --msl builds a Metal library with xcrun metal(lib) and stores that instead of the source. Suitable only when targeting macOS, not iOS. -T, --metallib-ios In combination with --msl builds a Metal library with xcrun metal(lib) and stores that instead of the source. Suitable only when targeting iOS, not macOS. -D, --define <name[=value]> Define macro. This argument can be specified multiple times. -p, --per-target Enable per-target compilation. (instead of source->SPIRV->targets, do source->SPIRV->target separately for each target) -d, --dump Switches to dump mode. Input file is expected to be a shader pack. -x, --extract <what> Switches to extract mode. Input file is expected to be a shader pack. Result is written to the output specified by -o. Pass -b to choose the batchable variant. <what>=reflect|spirv,<version>|glsl,<version>|... -r, --replace <what> Switches to replace mode. Replaces the specified shader in the shader pack with the contents of a file. This argument can be specified multiple times. Pass -b to choose the batchable variant. Also supports adding a shader for a target/variant that was not present before. <what>=<target>,<filename> where <target>=spirv,<version>|glsl,<version>|... -e, --erase <what> Switches to erase mode. Removes the specified shader from the shader pack. Pass -b to choose the batchable variant. <what>=spirv,<version>|glsl,<version>|... -s, --silent Enables silent mode. Only fatal errors will be printed. --depfile <depfile> Enables generating the depfile for the input shaders, using the #include statements. Arguments: file Vulkan GLSL source file to compile. The file extension determines the shader stage, and can be one of .vert, .tesc, .tese, .frag, .comp. Note: Tessellation control/evaluation is not supported with HLSL, instead use -r to inject handcrafted hull/domain shaders. Some targets may need special arguments to be set, e.g. MSL tessellation will likely need --msltess, --tess-vertex-count, --tess-mode, depending on the stage.
Betriebsarten
Es gibt fünf Hauptbetriebsarten:
.qsb
Dateierzeugung..qsb
Dateiprüfung. Zum Beispiel wirdqsb -d myshader.frag.qsb
die Reflection-Metadaten (in JSON-Form) und die enthaltenen Shader ausgeben.- Extraktionsmodus. Dies ermöglicht das Schreiben eines bestimmten Shaders aus einer bestehenden
.qsb
Datei in eine separate Datei. Zum Beispiel schreibtqsb -x spirv,100 -o myshader.spv myshader.frag.qsb
die SPIR-V-Binärdatei inmyshader.spv
. - Ersetzen-Modus. Dies ermöglicht das Ersetzen des Inhalts eines oder mehrerer Shader in der Datei
.qsb
durch Inhalte, die aus den angegebenen Dateien gelesen wurden. Auf diese Weise kann selbst erstellter Shader-Code in das.qsb
-Paket eingefügt werden. - Modus "Löschen". Damit wird die angegebene Shader-Variante aus der Datei
.qsb
entfernt.
Beispiel
Nehmen Sie den folgenden Fragment-Shader:
#version 440 layout(location = 0) in vec2 v_texcoord; layout(location = 0) out vec4 fragColor; layout(binding = 1) uniform sampler2D tex; layout(std140, binding = 0) uniform buf { float uAlpha; }; void main() { vec4 c = texture(tex, v_texcoord); fragColor = vec4(c.rgb, uAlpha); }
Die Ausführung von qsb -o shader.frag.qsb shader.frag
führt zur Erzeugung von shader.frag.qsb
. Die Überprüfung dieser Datei mit qsb -d shader.frag.qsb
ergibt:
Stage: Fragment QSB_VERSION: 5 Has 1 shaders: Shader 0: SPIR-V 100 [Standard] Reflection info: { "combinedImageSamplers": [ { "binding": 1, "name": "tex", "set": 0, "type": "sampler2D" } ], "inputs": [ { "location": 0, "name": "v_texcoord", "type": "vec2" } ], "localSize": [ 0, 0, 0 ], "outputs": [ { "location": 0, "name": "fragColor", "type": "vec4" } ], "uniformBlocks": [ { "binding": 0, "blockName": "buf", "members": [ { "name": "uAlpha", "offset": 0, "size": 4, "type": "float" } ], "set": 0, "size": 4, "structName": "_27" } ] } Shader 0: SPIR-V 100 [Standard] Entry point: main Contents: Binary of 864 bytes
Standardmäßig wird nur SPIR-V generiert, so dass eine Anwendung, die dieses Shader-Paket verwendet, nur mit Vulkan funktionieren würde. Lassen Sie es uns nützlicher machen:
qsb --glsl "100 es,120,150" --hlsl 50 --msl 12 -o shader.frag.qsb shader.frag
Dies führt zur Generierung eines Shader-Pakets, das auch für OpenGL, Direct 3D und Metal geeignet ist. Die in diesem Shader verwendeten Funktionen sind einfach, und sogar GLSL ES 100 (die Shading-Sprache von OpenGL ES 2.0) ist geeignet.
Ein Blick auf das Ergebnis zeigt:
Stage: Fragment QSB_VERSION: 5 Has 6 shaders: Shader 0: GLSL 120 [Standard] Shader 1: HLSL 50 [Standard] Shader 2: GLSL 100 es [Standard] Shader 3: MSL 12 [Standard] Shader 4: SPIR-V 100 [Standard] Shader 5: GLSL 150 [Standard] Reflection info: { ... <same as above> } Shader 0: GLSL 120 [Standard] Entry point: main Contents: #version 120 struct buf { float uAlpha; }; uniform buf _27; uniform sampler2D tex; varying vec2 v_texcoord; void main() { vec4 c = texture2D(tex, v_texcoord); gl_FragData[0] = vec4(c.xyz, _27.uAlpha); } ************************************ Shader 1: HLSL 50 [Standard] Entry point: main Native resource binding map: 0 -> [0, -1] 1 -> [0, 0] Contents: cbuffer buf : register(b0) { float _27_uAlpha : packoffset(c0); }; Texture2D<float4> tex : register(t0); SamplerState _tex_sampler : register(s0); static float2 v_texcoord; static float4 fragColor; struct SPIRV_Cross_Input { float2 v_texcoord : TEXCOORD0; }; struct SPIRV_Cross_Output { float4 fragColor : SV_Target0; }; void frag_main() { float4 c = tex.Sample(_tex_sampler, v_texcoord); fragColor = float4(c.xyz, _27_uAlpha); } SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input) { v_texcoord = stage_input.v_texcoord; frag_main(); SPIRV_Cross_Output stage_output; stage_output.fragColor = fragColor; return stage_output; } ************************************ ... Shader 3: MSL 12 [Standard] Entry point: main0 Native resource binding map: 0 -> [0, -1] 1 -> [0, 0] Contents: #include <metal_stdlib> #include <simd/simd.h> using namespace metal; struct buf { float uAlpha; }; struct main0_out { float4 fragColor [[color(0)]]; }; struct main0_in { float2 v_texcoord [[user(locn0)]]; }; fragment main0_out main0(main0_in in [[stage_in]], constant buf& _27 [[buffer(0)]], texture2d<float> tex [[texture(0)]], sampler texSmplr [[sampler(0)]]) { main0_out out = {}; float4 c = tex.sample(texSmplr, in.v_texcoord); out.fragColor = float4(c.xyz, _27.uAlpha); return out; } ************************************ ...
Dieses Paket kann nun von Qt Quick mit allen unterstützten Grafik-APIs verwendet werden: Vulkan, Direct 3D, Metal, OpenGL und OpenGL ES. Zur Laufzeit wird der passende Shader automatisch vom Qt Rendering Hardware Interface, das sich unter Qt Quick und Qt Quick 3D befindet, ausgewählt.
Neben der Rückübersetzung des SPIR-V-Bytecodes in höherwertigen Quellcode kümmert sich das System um weitere Probleme, wie z. B. die Gewährleistung der korrekten Zuordnung von SPIR-V-Bindungsnummern zu nativen Ressourcen. Bei HLSL haben wir zum Beispiel einen Abschnitt wie diesen oben gesehen:
Native resource binding map: 0 -> [0, -1] 1 -> [0, 0]
Intern ermöglicht dies die Abbildung eines SPIR-V-Bindungspunkts 0
auf das HLSL-Register b0
und die Bindung 1
an t0
und s0
. Dies trägt dazu bei, die Unterschiede in den Ressourcenbindungen zwischen den verschiedenen Shading-Sprachen für die Benutzer der Rendering-Hardware-Schnittstelle transparent zu machen, und ermöglicht es, dass alles in Qt mit Vulkan/SPIR-V-Stil-Bindungspunkten arbeitet, wie sie im ursprünglichen Vulkan-Stil-GLSL-Quellcode angegeben sind.
Shader-Typen
Der Typ des Shaders wird aus der Erweiterung der Eingabedatei 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 mit Direct 3D (HLSL) unterstützt.
Shading-Sprachen und -Versionen
SPIR-V 1.0 wird immer generiert. Was darüber hinaus generiert wird, hängt von den Befehlszeilenargumenten --glsl
, --hlsl
und --msl
ab.
Diesen Parametern folgt jeweils eine durch Komma getrennte Liste. Die Liste muss Versionsnummern im GLSL-Stil enthalten, mit einem optionalen Suffix (es
, das für GLSL ES steht). Das Leerzeichen zwischen dem Suffix und der Version ist optional (das Fehlen des Leerzeichens kann helfen, die Notwendigkeit von Anführungszeichen zu vermeiden).
Zum Beispiel bereiten die eingebauten Materialien von Qt Quick(die Shader, die Elemente wie Image, Text, Rectangle unterstützen) alle ihre Shader mit --glsl "100 es,120,150" --hlsl 50 --msl 12
vor. Dadurch sind sie kompatibel mit OpenGL ES 2.0 und höher, OpenGL 2.1 und höher sowie OpenGL-Kernprofilkontexten der Version 3.2 und höher.
Wenn der Shader Funktionen oder Konstrukte verwendet, die keine Entsprechung in den angegebenen Zielen haben, schlägt qsb
fehl. In diesem Fall müssen die Ziele angepasst werden, was auch bedeutet, dass die Mindestsystemanforderungen der Anwendung implizit angepasst werden. Nehmen wir als Beispiel die GLSL-Funktion textureLod
, die nur mit OpenGL ES 3.0 und höher verfügbar ist (d. h. GLSL ES 300 oder höher). Wenn die GLSL-Funktion 300 es
anstelle von 100 es
angefordert wird, wird qsb
erfolgreich sein, aber die Anwendung, die diese .qsb
-Datei verwendet, benötigt nun OpenGL ES 3.0 oder höher und ist nicht mit OpenGL ES 2.0-basierten Systemen kompatibel.
Ein weiteres offensichtliches Beispiel hierfür sind Compute-Shader: .comp
Shader müssen --glsl 310es,430
angeben, da Compute-Shader nur mit OpenGL ES 3.1 oder neuer und OpenGL 4.3 oder neuer verfügbar sind.
Die Anpassung der Shader-Modell-Version für HLSL oder die Metal Shading Language-Version wird voraussichtlich nur selten erforderlich sein. Shader Model 5.0 (--hlsl 50
) und MSL 1.2 (--msl 12
) sind normalerweise ausreichend.
Qt Quick Scene Graph Batching
Der Renderer des Qt Quick Scene Graphs unterstützt das Batching von Geometrie, um die Anzahl der Zeichenaufrufe zu reduzieren. Siehe die Scene Graph Seiten für Details. Dies beruht auf dem Einfügen von Code in die main()-Funktion des Vertex-Shaders. In Qt 5.x geschah dies zur Laufzeit, indem der mitgelieferte GLSL-Vertexshader-Code modifiziert wurde. In Qt 6 ist das nicht mehr möglich. Stattdessen können batchfähige Varianten von Vertex-Shadern durch das qsb
Werkzeug erstellt werden. Dies wird durch das Argument -b
angefordert. Wenn es sich bei der Eingabe nicht um einen Vertex-Shader mit der Erweiterung .vert
handelt, hat dies keinen Effekt. Bei Vertex-Shadern führt es jedoch dazu, dass für jedes Ziel zwei Versionen erzeugt werden. Qt Quick wählt dann zur Laufzeit automatisch die richtige Variante (Standard oder Batchable).
Hinweis: Die Anwendungen müssen sich nicht mit den Details des Batching befassen. Sie müssen lediglich sicherstellen, dass -b
(oder das entsprechende BATCHABLE
-Schlüsselwort, wenn sie die CMake-Integration verwenden) bei der Verarbeitung der Vertex-Shader angegeben wird. Dies ist nur für Qt Quick Shader relevant, die mit ShaderEffect oder QSGMaterialShader verwendet werden.
Nehmen Sie den folgenden Beispiel-Vertex-Shader:
#version 440 layout(location = 0) in vec4 position; layout(location = 1) in vec2 texcoord; layout(location = 0) out vec2 v_texcoord; layout(std140, binding = 0) uniform buf { mat4 mvp; } ubuf; void main() { v_texcoord = texcoord; gl_Position = ubuf.mvp * position; }
Die Ausführung von qsb -b --glsl 330 -o example.vert.qsb example.vert
führt zu:
Stage: Vertex QSB_VERSION: 5 Has 4 shaders: Shader 0: GLSL 330 [Standard] Shader 1: GLSL 330 [Batchable] Shader 2: SPIR-V 100 [Standard] Shader 3: SPIR-V 100 [Batchable] Reflection info: { ...
Beachten Sie, dass alle Zielsprachen und -versionen jetzt in zwei Varianten existieren: Standard und ein leicht modifiziertes Batchable.
Aufrufen externer Tools
qsb
kann bestimmte externe Tools aufrufen. Diese fallen in zwei Kategorien: Tools zur Durchführung von Optimierungen am Shader-Bytecode (SPIR-V) und plattformspezifische Tools zur Durchführung der ersten Phase der Shader-Kompilierung, vom Quellcode zu einem Bytecode-Zwischenformat.
Diese werden durch die folgenden Befehlszeilenoptionen aktiviert:
-O
- ruftspirv-opt
als Nachbearbeitungsschritt für die SPIR-V-Binärdatei auf. Die Datei.qsb
wird die optimierte Version enthalten. Dies setzt voraus, dassspirv-opt
auf dem System verfügbar ist (z. B. aus dem Vulkan-SDK) und aufgerufen werden kann.-c
oder--fxc
- ruftfxc.exe
auf, den Direct 3D-Shader-Compiler. Die resultierendenDXBC
(DirectX Byte Code) Daten werden in der.qsb
Datei anstelle von HLSL gespeichert. Qt übernimmt sie zur Laufzeit automatisch, so dass es dem Ersteller der.qsb
Datei überlassen bleibt, ob er den HLSL-Quellcode oder das Zwischenformat einbinden möchte. Wann immer es möglich ist, sollten Sie letzteres bevorzugen, da es die Notwendigkeit des Parsens einer HLSL-Quelle zur Laufzeit eliminiert, was zu potenziell signifikanten Leistungssteigerungen bei der Erstellung der Grafikpipeline führt. Der Nachteil ist, dass dieses Argument nur verwendet werden kann, wennqsb
unter Windows läuft.-t
oder--metallib
- ruft die entsprechenden XCode-Metal-Tools auf, um eine .metallib-Datei zu erzeugen, und fügt diese in das.qsb
-Paket anstelle des MSL-Quellcodes ein. Diese Option ist nur verfügbar, wennqsb
unter macOS ausgeführt wird.
Andere Optionen
-D
- definiert ein Makro. Dies ermöglicht die Verwendung von #ifdef und ähnlichem im GLSL-Quellcode.-g
- ermöglicht es, vollständige Debug-Informationen für SPIR-V zu generieren, so dass Tools wie RenderDoc den vollständigen Quellcode anzeigen können, wenn sie eine Pipeline inspizieren oder Vertex- oder Fragment-Debugging durchführen. Hat auch Auswirkungen auf Direct 3D, wenn-c
angegeben wird, dafxc
dann angewiesen wird, Debug-Informationen in den generierten Zwischen-Bytecode aufzunehmen.
Tesselierung
--msltess
- Zeigt an, dass der Vertex-Shader in einer Pipeline verwendet wird, die Tesselierungsstufen enthält. Hat keine Auswirkung für andere Shadertypen und wenn die MSL-Shader-Generierung nicht aktiviert ist. Wenn nicht angegeben, ist der Vertex-Shader auf Metal in Kombination mit Tesselation nicht funktionsfähig.--tess-vertex-count <count>
- Gibt die Anzahl der Scheitelpunkte an, die von der Tesselation-Steuerungsstufe ausgegeben werden. Diese Angabe ist für Tesselation-Evaluierungs-Shader, die mit Metal verwendet werden, obligatorisch. Der Standardwert ist 3. Wenn er nicht mit der Tessellierungssteuerungsstufe übereinstimmt, funktioniert der generierte MSL-Code nicht wie erwartet.--tess-mode <mode>
- Diese Option gibt den Tesselierungsmodus an. Sie kann einen von zwei Werten annehmen:triangles
oderquads
. Der Standardwert isttriangles
. Die Angabe dieser Option ist für Tessellation Control Shader, die mit Metal verwendet werden, obligatorisch. Der Wert muss mit der Tessellationsevaluierungsstufe übereinstimmen, andernfalls wird der generierte MSL-Code nicht wie erwartet funktionieren.
Multiview
Nehmen Sie den folgenden Vertex-Shader. Er ist als Vulkan-kompatibles GLSL geschrieben, so dass die GL_EXT_multiview
-Erweiterung die Verwendung von gl_ViewIndex
legal macht.
#version 440 #extension GL_EXT_multiview : require layout(location = 0) in vec4 pos; layout(std140, binding = 0) uniform buf { mat4 mvp[2]; }; void main() { gl_Position = mvp[gl_ViewIndex] * pos; }
Hinweis: In der Praxis wird die Zeile #extension GL_EXT_multiview im Quellcode, der an qsb
übergeben wird, nicht benötigt, da die Übergabe des unten beschriebenen Arguments --view-count
diese Zeile automatisch in den Shader-Quellcode injiziert, bevor er nach SPIR-V kompiliert wird.
Für Vulkan funktioniert dies so, wie es ist, solange Vulkan 1.1 zur Laufzeit unterstützt wird. Siehe VK_KHR_multiview für Details.
Um einen HLSL-Vertex-Shader aus dem oben genannten für Direct 3D 12 zu generieren (siehe View Instancing für Details), ist die minimale Shader-Modell-Version 6.1, was bedeutet, dass qsb
fehlschlägt, wenn z.B. --hlsl 50
angegeben wird. Verwenden Sie mindestens --hlsl 61
, wenn Sie einen Multiview-Vertex-Shader verarbeiten. Multiview wird von Direct 3D 11 nicht unterstützt.
Für OpenGL werden zusätzliche Metadaten benötigt:
--view-count
- Wenn obiger Shader (nach der Kompilierung nach SPIR-V) in OpenGL-kompatiblen GLSL-Quellcode transpiliert wird, reicht es nicht aus,gl_ViewIndex
aufgl_ViewID_OVR
zu mappen, sondern die Anzahl der Ansichten muss ebenfalls im Shader deklariert werden. Die Übergabe eines Wertes von 2 an das Argument--view-count
führt dazu, dass einelayout(num_views = 2) in;
-Anweisung in den generierten GLSL-Quellcode eingefügt wird, wodurch dieser zu einem gültigen (OpenGL-)GLSL-Shader wird. Siehe GL_OVR_multiview für Details und beachte, dass die generierten GLSL-Shader auch GL_OVR_multiview2 benötigen, um zur Laufzeit unterstützt zu werden, da es das ist, was von der#extension
Anweisung im generierten Shader-Quellcode benötigt wird.
Wenn man OpenGL (ES) mit einem solchen Vertex-Shader anspricht, muss die generierte GLSL-Version (--glsl
) mindestens 330
oder 300 es
sein. Ersteres wird nicht von qsb
oder QShaderBaker erzwungen, aber in der Praxis sind OpenGL-Implementierungen dafür bekannt, solche Shader abzulehnen, wenn die GLSL-Version 150 oder kleiner ist. Daher wird empfohlen, --glsl 330,300es
zu übergeben, wenn man Vertex-Shader konditioniert, die GL_EXT_multiview aktivieren.
Die Angabe von --view-count
generiert und injiziert automatisch ein Präprozessor-Definition: #define QSHADER_VIEW_COUNT n
, wobei n
die Anzahl der Ansichten ist. Wenn die Anzahl der Ansichten nicht angegeben wird, wird das Define überhaupt nicht gesetzt. Dies ermöglicht das Schreiben von Code wie dem folgenden und die Verwendung der gleichen Quelldatei für alle View Count-spezifischen Varianten des Shaders.
layout(std140, binding = 0) uniform buf { #if QSHADER_VIEW_COUNT >= 2 mat4 matrix[QSHADER_VIEW_COUNT]; #else mat4 matrix; #endif float opacity; };
Darüber hinaus wird die Zeile #extension GL_EXT_multiview : require
in Vertex-Shadern automatisch generiert, wenn ein View-Count von 2 oder mehr festgelegt wird. Dies reduziert die Anzahl der zusätzlichen Zeilen, die für die Unterstützung mehrerer Ansichten in einem Vertex-Shader hinzugefügt werden müssen.
Das Festlegen der Anzahl der Ansichten kann auch bei anderen Shader-Typen von Bedeutung sein. Wenn zum Beispiel der Vertex-Shader und der Fragment-Shader sich einen einheitlichen Puffer teilen und beide Shader das gleiche Pufferlayout sicherstellen müssen, kann es nützlich sein, #if QSHADER_VIEW_COUNT >= 2
in beide Quelldateien schreiben zu können. Dies kann durch die Angabe von --view-count
für beide beim Aufruf von qsb
sichergestellt werden.
Hinweis: Sich direkt auf das Schlüsselwort gl_ViewIndex
in einer Nicht-Vertex-Stufe zu verlassen, zum Beispiel in einem Fragment-Shader, ist derzeit nicht portabel und sollte vermieden werden.
Arbeiten mit GLSL-Funktionen, die spezifisch für OpenGL sind
Manchmal kann es notwendig sein, Shading-Sprachkonstrukte zu verwenden, die spezifisch für OpenGL und GLSL sind und nicht für andere Shading-Sprachen, Zwischenformate und Grafik-APIs gelten.
Das beste Beispiel hierfür sind die externen Texturen und Sampler von OpenGL ES. Bei der Implementierung der Videowiedergabe oder der Anzeige eines Kamerasuchers kann es je nach Plattform erforderlich sein, mit OpenGL-Texturobjekten zu arbeiten, die nicht als reguläre 2D-Texturen verwendet werden sollen, sondern mit einem begrenzten Funktionsumfang über den Bindungspunkt GL_TEXTURE_EXTERNAL_OES in der OpenGL-API und den Sampler-Typ samplerExternalOES
in Shadern nutzbar sind. Letzterer stellt einen potentiellen Showstopper dar, wenn die SPIR-V basierte Shader-Pipeline von Qt verwendet wird: das Ausführen eines solchen Shaders durch qsb wird zu einem Fehler führen, da samplerExternalOES
nicht als gültiger Typ akzeptiert wird, da er nicht auf SPIR-V und andere Shading-Zielsprachen abgebildet werden kann.
Um dies zu umgehen, bietet qsb die Möglichkeit, den Inhalt einer beliebigen Shader-Variante in einer .qsb-Datei durch vom Benutzer bereitgestellte Daten zu ersetzen, die aus einer Datei gelesen werden und den ursprünglichen, von qsb generierten Shader-Quell- oder Bytecode vollständig ersetzen.
Nehmen Sie den folgenden Fragment-Shader. Beachten Sie den Typ von tex
. Was ist, wenn der Typ samplerExternalOES
sein muss, wenn er mit OpenGL ES ausgeführt wird?
#version 440 layout(location = 0) in vec2 texCoord; layout(location = 0) out vec4 fragColor; layout(std140, binding = 0) uniform buf { float opacity; } ubuf; layout(binding = 1) uniform sampler2D tex; void main() { fragColor = texture(tex, texCoord).rgba * ubuf.opacity; }
Einfach den Typ von samplerExternalOES zu ändern ist nicht machbar. Das führt sofort zu Kompilierungsfehlern.
Es gibt jedoch eine einfache Lösung: Man schreibt eine separate, rein auf OpenGL ES ausgerichtete Version des Shaders und fügt sie in die .qsb-Datei ein. Der folgende Shader ist nur mit GLSL ES kompatibel und kann nicht über qsb ausgeführt werden. Wir wissen jedoch, dass er zur Laufzeit von OpenGL ES verarbeitet werden kann.
precision highp float; #extension GL_OES_EGL_image_external : require varying vec2 texCoord; struct buf { float opacity; }; uniform buf ubuf; uniform samplerExternalOES tex; void main() { gl_FragColor = texture2D(tex, texCoord).rgba * ubuf.opacity; }
Nennen wir ihn shader_gles.frag
. Sobald qsb --glsl 100es -o shader.frag.qsb shader.frag
fertig ist und uns eine (halbfertige) .qsb-Datei liefert, können wir qsb -r glsl,100es,shader_gles.frag shader.frag.qsb
ausführen, um shader.frag.qsb
zu aktualisieren, indem wir den Shader für GLSL 100 es durch den Inhalt der angegebenen Datei ersetzen (shader_gles.frag
). Jetzt ist shader.frag.qsb
bereit, zur Laufzeit mit OpenGL ES verwendet zu werden.
Hinweis: Achten Sie darauf, dass die Schnittstelle zwischen dem Shader und der Anwendung unverändert bleibt. Überprüfen Sie immer zuerst den von qsb erzeugten GLSL-Code, entweder durch Ausdrucken des Inhalts der .qsb-Datei über die Option -d
oder durch Extrahieren des GLSL ES 100-Shaders durch Ausführen von qsb -x glsl,100es -o gles_shader.frag shader.frag.qsb
. Die struct-, struct-member- und uniform-Namen dürfen sich auch in der manuell injizierten Version nicht unterscheiden.
Hinweis: Die Möglichkeit, Daten aus beliebigen Dateien in das .qsb-Paket zu platzieren, kann auch dazu verwendet werden, handgefertigte Hull- und Domain-HLSL-Shader zu injizieren, um tesselationsbasierte Grafikpipelines auch mit Direct 3D funktionsfähig zu machen.
© 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.