QSB-Handbuch
qsb ist ein Befehlszeilentool, das vom Qt-Modul „ Shader Tools “ bereitgestellt wird. Es integriert Bibliotheken von Drittanbietern wie glslang und SPIRV-Cross, ruft optional externe Tools wie fxc oder spirv-opt auf und generiert „ .qsb “-Dateien. Darüber hinaus kann es verwendet werden, um den Inhalt eines „ .qsb “-Pakets zu überprüfen.
Usage: qsb [options] file
Qt Shader Baker (using QShader from Qt 6.10.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.
--orig-file <filename> Filename to be be used for dependency tracking
instead of <file>.
--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.
--mediump Default to medium precision for floats in
fragment shaders instead of high. GLSL ES only;
ignored for everything else, including GLSL.
--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, .geom, .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. Geometry shaders are not supported
with Metal.Betriebsmodi
Es gibt fünf Hauptbetriebsmodi:
.qsbDateierzeugung..qsbDateiüberprüfung. Beispielsweise gibt der Befehl „qsb -d myshader.frag.qsb“ die Reflection-Metadaten (im JSON-Format) und die enthaltenen Shader aus.- Extraktionsmodus. Dieser ermöglicht es, einen bestimmten Shader aus einer vorhandenen „
.qsb“-Datei in eine separate Datei zu schreiben. Beispielsweise schreibt „qsb -x spirv,100 -o myshader.spv myshader.frag.qsb“ den SPIR-V-Binärcode in „myshader.spv“. - Ersetzungsmodus. Damit lässt sich der Inhalt eines oder mehrerer Shader innerhalb der Datei „
.qsb“ durch Inhalte ersetzen, die aus den angegebenen Dateien gelesen werden. Auf diese Weise kann handgeschriebener Shader-Code in das „.qsb“-Paket eingefügt werden. - Löschmodus. Hiermit wird die angegebene Shader-Variante aus der Datei „
.qsb“ entfernt.
Beispiel
Nehmen wir 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 Generierung von „ shader.frag.qsb “. Die Überprüfung dieser Datei mit „ qsb -d shader.frag.qsb “ ergibt Folgendes:
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 bytesStandardmäßig wird nur SPIR-V generiert, sodass eine Anwendung, die dieses Shader-Paket verwendet, nur mit Vulkan funktionieren würde. Machen wir es nützlicher:
qsb --glsl "100 es,120,150" --hlsl 50 --msl 12 -o shader.frag.qsb shader.fragDies 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 grundlegend, 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 von der Qt-Rendering-Hardware-Schnittstelle ausgewählt, die unter Qt Quick und Qt Quick 3D zu finden ist.
Neben der Rückübersetzung des SPIR-V-Bytecodes in Quellcode auf höherer Ebene kümmert sich das System auch um weitere Probleme, wie beispielsweise die Gewährleistung einer korrekten Zuordnung von SPIR-V-Bindungsnummern zu nativen Ressourcen. Bei HLSL sahen wir beispielsweise oben einen Abschnitt wie diesen:
Native resource binding map:
0 -> [0, -1]
1 -> [0, 0]Intern ermöglicht dies die Zuordnung eines Bindungspunkts im SPIR-V-Stil 0 zum HLSL-Register b0 sowie die Zuordnung von 1 zu t0 und s0. Dies trägt dazu bei, die Unterschiede bei den Ressourcenbindungen zwischen den verschiedenen Shading-Sprachen für die Nutzer der Rendering-Hardware-Schnittstelle transparent zu machen, und ermöglicht es, dass alles in Qt mit Bindungspunkten im Vulkan/SPIR-V-Stil arbeitet, wie sie im ursprünglichen GLSL-Quellcode im Vulkan-Stil spezifiziert sind.
Shader-Typen
Der Shader-Typ wird aus der Dateiendung der Eingabedatei abgeleitet. Daher muss die Dateiendung eine der folgenden sein:
.vert- für Vertex-Shader.tesc- für Tessellationssteuerungs-Shader.tese- für Tessellationsauswertungs-Shader.geom- für Geometrie-Shader.frag- für Fragment- (Pixel-)Shader.comp- für Compute-Shader
Hinweis: Tessellationssteuerungs- und -auswertungs-Shader werden derzeit von Direct 3D (HLSL) nicht unterstützt.
Shading-Sprachen und -Versionen
SPIR-V 1.0 wird immer generiert. Was zusätzlich generiert wird, hängt von den Befehlszeilenargumenten „ --glsl “, „ --hlsl “ und „ --msl “ ab.
Auf diese Parameter folgt jeweils eine durch Kommas getrennte Liste. Die Liste muss Versionsnummern im GLSL-Stil enthalten, mit einem optionalen Suffix (es, das auf GLSL ES hinweist). Das Leerzeichen zwischen dem Suffix und der Versionsnummer ist optional (das Weglassen des Leerzeichens kann dazu beitragen, die Notwendigkeit von Anführungszeichen zu vermeiden).
Beispielsweise bereiten die integrierten Materialien von „ Qt Quick “ (die Shader, die Elementen zugrunde liegen, wie z. B. „ Image “, „ Text “ und „ Rectangle “) ihre Shader alle 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-Core-Profile-Kontexten der Version 3.2 und höher.
Verwendet der Shader Funktionen oder Konstrukte, für die es in den angegebenen Zielplattformen keine Entsprechung gibt, schlägt ` qsb ` fehl. In diesem Fall müssen die Zielplattformen angepasst werden, was auch bedeutet, dass sich die Mindestsystemanforderungen der Anwendung implizit ändern. Nehmen wir als Beispiel die GLSL-Funktion „ textureLod “, die nur ab OpenGL ES 3.0 (d. h. GLSL ES 300 oder höher) verfügbar ist. Wenn man anstelle von ` 100 es` die GLSL- 300 es -Anforderung stellt, 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 mehr 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 sowie OpenGL 4.3 oder neuer verfügbar sind.
Eine Anpassung der Shader-Modell-Version für HLSL oder der Metal Shading Language-Version dürfte nur selten erforderlich sein. Shader Model 5.0 (--hlsl 50) und MSL 1.2 (--msl 12) sind in der Regel ausreichend.
Qt Quick Batching im Szenengraphen
Der Renderer des Qt Quick -Szenengraphen unterstützt das Batching von Geometrie, um die Anzahl der Draw-Calls zu reduzieren. Weitere Informationen finden Sie auf den Seiten zum Szenengraphen. Dies beruht auf dem Einfügen von Code in die `main()`-Funktion des Vertex-Shaders. In Qt 5.x erfolgte dies zur Laufzeit durch Modifizierung des bereitgestellten GLSL-Vertex-Shader-Codes. In Qt 6 ist dies keine Option mehr. Stattdessen können mit dem Tool „ qsb “ Batch-fähige Varianten von Vertex-Shadern erstellt werden. Dies wird über das Argument „ -b “ angefordert. Wenn die Eingabe kein Vertex-Shader mit der Erweiterung „ .vert “ ist, hat dies keine Auswirkung. Bei Vertex-Shadern führt dies jedoch dazu, dass für jedes Ziel zwei Versionen generiert werden. „ Qt Quick “ wählt dann zur Laufzeit automatisch die richtige Variante (Standard oder „batchable“) aus.
Hinweis: Anwendungen müssen sich nicht mit den Details des Batchings befassen. Sie müssen lediglich sicherstellen, dass bei der Verarbeitung der Vertex-Shader „ -b “ (oder das entsprechende Schlüsselwort „ BATCHABLE “, falls die CMake-Integration verwendet wird) angegeben ist. Dies ist nur für „ Qt Quick “-Shader relevant, die mit „ ShaderEffect “ oder „ QSGMaterialShader “ verwendet werden.
Betrachten 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 folgendem Ergebnis:
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 nun in zwei Varianten vorliegen: „Standard“ und eine leicht modifizierte „Batchable“-Variante.
Aufruf externer Tools
qsb können bestimmte externe Tools aufrufen. Diese lassen sich in zwei Kategorien einteilen: Tools zur Optimierung des Shader-Bytecodes (SPIR-V) und plattformspezifische Tools zur Durchführung der ersten Phase der Shader-Kompilierung, vom Quellcode zu einem Zwischen-Bytecode-Format.
Diese werden durch die folgenden Befehlszeilenoptionen aktiviert:
-O- Ruft „spirv-opt“ als Nachbearbeitungsschritt für die SPIR-V-Binärdatei auf. Die Datei „.qsb“ enthält dann die optimierte Version. Dies setzt voraus, dass „spirv-opt“ auf dem System verfügbar (z. B. aus dem Vulkan-SDK) und bereit zur Ausführung ist.-coder `--fxc` – ruft `fxc.exe` auf, den Direct3D-Shader-Compiler. Die resultierenden „DXBC“-Daten (DirectX-Byte-Code) werden anstelle von HLSL in der Datei „.qsb“ gespeichert. Qt übernimmt diese automatisch zur Laufzeit, sodass es dem Ersteller der Datei „.qsb“ überlassen bleibt, zu entscheiden, was aufgenommen werden soll: HLSL-Quellcode oder das Zwischenformat. Wenn möglich, sollte Letzteres bevorzugt werden, da dadurch das Parsen von HLSL-Quellcode zur Laufzeit entfällt, was zu potenziell erheblichen Leistungssteigerungen beim Aufbau der Grafikpipeline führen kann. Der Nachteil ist, dass dieses Argument nur verwendet werden kann, wenn „qsb“ unter Windows ausgeführt wird.-toder „--metallib“ – ruft die entsprechenden XCode-Metal-Tools auf, um eine .metallib-Datei zu generieren, und fügt diese anstelle des MSL-Quellcodes in das „.qsb“-Paket ein. Diese Option ist nur verfügbar, wenn „qsb“ unter macOS ausgeführt wird.
Weitere Optionen
-D- definiert ein Makro. Dies ermöglicht die Verwendung von #ifdef und Ähnlichem im GLSL-Quellcode.-g- Aktiviert die Generierung vollständiger Debug-Informationen für SPIR-V, wodurch Tools wie RenderDoc den vollständigen Quellcode anzeigen können, wenn eine Pipeline untersucht wird oder beim Debuggen von Vertex- oder Fragment-Shadern. Wirkt sich auch auf Direct 3D aus, wenn „-c“ angegeben ist, da „fxc“ dann angewiesen wird, Debug-Informationen in den generierten Zwischen-Bytecode einzubinden.--mediump- Fordert an, dass für Fließkommazahlen in GLSL-ES-Fragment-Shadern standardmäßig mittlere Genauigkeit verwendet wird. Wird bei allen anderen Zielen, einschließlich (Nicht-ES-)GLSL, sowie bei Nicht-Fragment-Shadern ignoriert.--orig-file- Legt den Dateinamen fest, der anstelle der Eingabequelldatei bei der Generierung von Abhängigkeitsdateien für CMake (–depfiles) verwendet wird. Dies ist nützlich, wenn die an qsb übergebene Datei eine generierte Shader-Quelldatei im Zwischenformat ist. Für die Nachverfolgung von Abhängigkeiten muss jedoch häufig die Originaldatei verwendet werden.
Tessellation
--msltess- Gibt an, dass der Vertex-Shader in einer Pipeline verwendet wird, die Tessellationsstufen enthält. Hat keine Auswirkung auf andere Shader-Typen und wenn die MSL-Shader-Generierung nicht aktiviert ist. Wird dieser Parameter nicht angegeben, ist der Vertex-Shader auf Metal in Kombination mit Tessellation nicht funktionsfähig.--tess-vertex-count <count>- Gibt die Anzahl der Ausgangs-Vertexe aus der Tessellationssteuerungsstufe an. Die Angabe dieses Werts ist für Tessellationsauswertungs-Shader, die mit Metal verwendet werden, zwingend erforderlich. Der Standardwert ist 3. Wenn dieser Wert nicht mit der Tessellationssteuerungsstufe übereinstimmt, funktioniert der generierte MSL-Code nicht wie erwartet.--tess-mode <mode>- Diese Option legt den Tessellationsmodus fest. Sie kann einen von zwei Werten annehmen: „triangles“ oder „quads“. Der Standardwert ist „triangles“. Die Angabe dieser Option ist für Tessellationssteuerungs-Shader, die mit Metal verwendet werden, zwingend erforderlich. Der Wert muss mit der Tessellationsauswertungsstufe übereinstimmen, andernfalls funktioniert der generierte MSL-Code nicht wie erwartet.
Multiview
Betrachten Sie den folgenden Vertex-Shader. Er ist in Vulkan-kompatiblem GLSL geschrieben und aktiviert die Erweiterung „ GL_EXT_multiview “, um die Verwendung von „ gl_ViewIndex “ zu ermöglichen.
#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 an ` qsb` übergebenen Quellcode nicht benötigt, da durch die Übergabe des unten beschriebenen Arguments ` --view-count ` diese Zeile automatisch in den Shader-Quellcode eingefügt wird, bevor dieser zu SPIR-V kompiliert wird.
Für Vulkan funktioniert dies unverändert, solange Vulkan 1.1 zur Laufzeit unterstützt wird. Siehe VK_KHR_multiview für Details.
Um aus dem oben Genannten einen HLSL-Vertex-Shader für Direct 3D 12 zu generieren (Einzelheiten siehe „View Instancing“ ), ist die Mindestversion des Shader-Modells 6.1 erforderlich, was bedeutet, dass „ qsb “ fehlschlägt, wenn beispielsweise „ --hlsl 50 “ angegeben wird. Verwenden Sie bei der Verarbeitung eines Multiview-Vertex-Shaders mindestens „ --hlsl 61 “. Multiview wird unter Direct 3D 11 nicht unterstützt.
Für OpenGL sind zusätzliche Metadaten erforderlich:
--view-count- Beim Transpiling des oben genannten Shaders (nach der Kompilierung zu SPIR-V) in OpenGL-kompatiblen GLSL-Quellcode reicht es nicht aus,gl_ViewIndexaufgl_ViewID_OVRabzubilden, sondern die Anzahl der Ansichten muss ebenfalls im Shader deklariert werden. Die Übergabe des Werts 2 an das Argument „--view-count“ führt dazu, dass eine Anweisung „layout(num_views = 2) in;“ in den generierten GLSL-Quellcode eingefügt wird, wodurch dieser zu einem gültigen (OpenGL-)GLSL-Shader wird. Weitere Informationen finden Sie unter GL_OVR_multiview. Beachten Sie, dass die generierten GLSL-Shader außerdem erfordern, dass GL_OVR_multiview2 zur Laufzeit unterstützt wird, da dies von der Anweisung „#extension“ im generierten Shader-Quellcode benötigt wird.
Bei der Zielausrichtung auf OpenGL (ES) mit einem solchen Vertex-Shader muss die generierte GLSL-Version (--glsl) mindestens 330 oder 300 es betragen. Ersteres wird zwar nicht durch qsb oder QShaderBaker erzwungen, doch in der Praxis ist bekannt, dass OpenGL-Implementierungen solche Shader ablehnen, wenn die GLSL-Version 150 oder kleiner ist. Daher wird empfohlen, bei der bedingten Aktivierung von Vertex-Shadern, die GL_EXT_multiview nutzen, „ --glsl 330,300es “ zu übergeben.
Durch die Angabe von ` --view-count ` wird automatisch eine Präprozessor-Definition generiert und eingefügt: ` #define QSHADER_VIEW_COUNT n `, wobei ` n ` die Anzahl der Ansichten ist. Wird die Anzahl der Ansichten nicht angegeben, wird die Definition überhaupt nicht gesetzt. Dies ermöglicht das Schreiben von Code wie dem folgenden und erlaubt die Verwendung derselben Quelldatei für alle ansichtszahlspezifischen 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;
};Zudem wird die Zeile „ #extension GL_EXT_multiview : require “ automatisch in Vertex-Shadern generiert, sobald eine Ansichtsanzahl von 2 oder mehr festgelegt ist. 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.
Die Festlegung der Ansichtsanzahl kann auch bei anderen Shader-Typen relevant sein. Wenn beispielsweise ein Uniform-Puffer zwischen dem Vertex- und dem Fragment-Shader gemeinsam genutzt wird und beide Shader dasselbe Pufferlayout gewährleisten müssen, kann es nützlich sein, in beiden Quelldateien ` #if QSHADER_VIEW_COUNT >= 2 ` schreiben zu können. Dies lässt sich sicherstellen, indem beim Aufruf von ` qsb` für beide ` --view-count ` angegeben wird.
Hinweis: Diedirekte Verwendung des Schlüsselworts „ gl_ViewIndex “ in einer Nicht-Vertex-Stufe, beispielsweise 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 auf andere Shading-Sprachen, Zwischenformate und Grafik-APIs anwendbar sind.
Die besten Beispiele hierfür sind die externen Texturen und Sampler von OpenGL ES. Die Implementierung der Videowiedergabe oder die Darstellung eines Kamera-Suchers kann je nach Plattform die Arbeit mit OpenGL-Texturobjekten erfordern, die nicht für die Verwendung als reguläre 2D-Texturen vorgesehen sind, sondern vielmehr – mit einem eingeschränkten Funktionsumfang – über den Bindungspunkt `GL_TEXTURE_EXTERNAL_OES ` in der OpenGL-API und den Sampler-Typ ` samplerExternalOES ` in Shadern genutzt werden können. Letzteres stellt bei der Verwendung der SPIR-V-basierten Shader-Pipeline von Qt ein potenzielles Hindernis dar: Die Ausführung eines solchen Shaders über qsb führt zu einem Fehler, da „ samplerExternalOES “ nicht als gültiger Typ akzeptiert wird, da es nicht auf SPIR-V und andere Ziel-Shading-Sprachen abgebildet werden kann.
Um dieses Problem zu lösen, bietet qsb die Möglichkeit, den Inhalt einer beliebigen Shader-Variante in einer .qsb-Datei durch benutzerdefinierte Daten zu ersetzen, die aus einer Datei gelesen werden, wodurch der ursprüngliche, von qsb generierte Shader-Quellcode oder Bytecode vollständig ersetzt wird.
Betrachten Sie den folgenden Fragment-Shader. Beachten Sie den Typ „ tex “. Was passiert, wenn der Typ bei der Ausführung mit OpenGL ES „ samplerExternalOES “ lauten muss?
#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;
}Eine einfache Änderung des Typs von `samplerExternalOES` ist nicht möglich. Dies 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 diese 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 diesen „ shader_gles.frag “. Sobald „ qsb --glsl 100es -o shader.frag.qsb shader.frag “ abgeschlossen ist und uns eine (halbfertige) .qsb-Datei liefert, können wir mit „ qsb -r glsl,100es,shader_gles.frag shader.frag.qsb “ die Datei „ shader.frag.qsb “ aktualisieren, indem wir den Shader für GLSL 100 es durch den Inhalt der angegebenen Datei (shader_gles.frag) ersetzen. Nun ist „ shader.frag.qsb “ bereit, zur Laufzeit mit OpenGL ES verwendet zu werden.
Hinweis: Achten Sie darauf, die Schnittstelle zwischen dem Shader und der Anwendung unverändert zu lassen. Überprüfen Sie immer zuerst den von qsb generierten GLSL-Code, entweder durch Ausgeben des Inhalts der .qsb-Datei über die Option „ -d “ oder durch Extrahieren des GLSL ES 100-Shaders mit dem Befehl „ qsb -x glsl,100es -o gles_shader.frag shader.frag.qsb “. Die Namen der Strukturen, Strukturmitglieder und Uniforms dürfen sich auch in der manuell eingefügten Version nicht unterscheiden.
Hinweis: Die Möglichkeit, Daten aus beliebigen Dateien in das .qsb-Paket einzufügen, kann auch genutzt werden, um manuell erstellte Hull- und Domain-HLSL-Shader einzufügen, damit tessellationsbasierte Grafik-Pipelines auch mit Direct 3D funktionieren.
© 2026 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.