Sur cette page

Manuel QSB

qsb est un outil en ligne de commande fourni par le module Shader Tools Qt. Il intègre des bibliothèques tierces telles que glslang et SPIRV-Cross, appelle éventuellement des outils externes, tels que fxc ou spirv-opt, et génère des fichiers .qsb. De plus, il peut être utilisé pour inspecter le contenu d'un paquet .qsb.

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.

Modes de fonctionnement

Il existe cinq modes de fonctionnement principaux :

  • .qsb génération de fichiers.
  • .qsb Inspection de fichiers. Par exemple, la commande « qsb -d myshader.frag.qsb » affichera les métadonnées de réflexion (au format JSON) ainsi que les shaders inclus.
  • Mode d’extraction. Ce mode permet d’écrire un shader donné, issu d’un fichier .qsb existant, dans un fichier distinct. Par exemple, la commande qsb -x spirv,100 -o myshader.spv myshader.frag.qsb écrit le binaire SPIR-V dans le fichier myshader.spv.
  • Mode « Remplacer ». Ce mode permet de remplacer le contenu d’un ou plusieurs shaders du fichier .qsb par le contenu lu à partir des fichiers spécifiés. De cette manière, du code de shader créé manuellement peut être injecté dans le package .qsb.
  • Mode « Erase » (Effacer). Cette option supprime la variante de shader spécifiée du fichier .qsb.

Exemple

Prenons le shader de fragment suivant :

#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);
}

L'exécution de ` qsb -o shader.frag.qsb shader.frag ` génère le fichier ` shader.frag.qsb`. En inspectant ce fichier avec qsb -d shader.frag.qsb, on obtient :

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

Par défaut, seul le format SPIR-V est généré ; une application utilisant ce paquet de shaders ne fonctionnerait donc qu’avec Vulkan. Rendons-le plus polyvalent :

qsb --glsl "100 es,120,150" --hlsl 50 --msl 12 -o shader.frag.qsb shader.frag

Cela permet de générer un paquet de shaders également compatible avec OpenGL, Direct 3D et Metal. Les fonctionnalités utilisées dans ce shader sont basiques, et même GLSL ES 100 (le langage de shading d’OpenGL ES 2.0) convient.

En examinant le résultat, on constate :

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;
}

************************************

...

Ce paquet peut désormais être utilisé par Qt Quick avec toutes les API graphiques prises en charge : Vulkan, Direct 3D, Metal, OpenGL et OpenGL ES. Au moment de l’exécution, le shader approprié est automatiquement sélectionné par l’interface matérielle de rendu Qt (Qt Rendering Hardware Interface), qui se trouve sous Qt Quick et Qt Quick 3D.

Outre la conversion du bytecode SPIR-V en code source de plus haut niveau, le système prend en charge d’autres problèmes, tels que la garantie d’un mappage correct des numéros de liaison SPIR-V vers les ressources natives. Par exemple, avec HLSL, nous avons vu une section comme celle-ci ci-dessus :

Native resource binding map:
 0 -> [0, -1]
 1 -> [0, 0]

En interne, cela permet de mapper un point de liaison de type SPIR-V 0 au registre HLSL b0 et de lier 1 à t0 et s0. Cela permet de rendre transparentes pour les utilisateurs de l'interface matérielle de rendu (Rendering Hardware Interface) les différences de liaisons de ressources entre les différents langages de shader, et permet à l'ensemble de Qt de fonctionner avec des points de liaison de type Vulkan/SPIR-V, tels qu'ils sont spécifiés dans le code source GLSL d'origine de type Vulkan.

Types de shaders

Le type de shader est déduit de l’extension du fichier d’entrée. Ainsi, l’extension doit être l’une des suivantes :

  • .vert - pour les shaders de sommets
  • .tesc - pour les shaders de contrôle de tessellation
  • .tese - pour les shaders d'évaluation de tessellation
  • .geom - pour les shaders de géométrie
  • .frag - pour les shaders de fragments (pixels)
  • .comp - pour les shaders de calcul

Remarque : les shaders de contrôle et d'évaluationde la tessellation ne sont actuellement pas pris en charge par Direct 3D (HLSL).

Langages de shader et versions

SPIR-V 1.0 est toujours généré. Les éléments supplémentaires générés dépendent des arguments de ligne de commande --glsl, --hlsl et --msl.

Ces paramètres sont tous suivis d’une liste séparée par des virgules. La liste doit inclure des numéros de version au format GLSL, avec un suffixe facultatif (es, indiquant GLSL ES). L’espace entre le suffixe et la version est facultatif (l’absence d’espace peut permettre d’éviter d’avoir à utiliser des guillemets).

Par exemple, les matériaux intégrés de Qt Quick(les shaders sous-jacents à des éléments, tels que Image, Text, Rectangle) préparent tous leurs shaders avec --glsl "100 es,120,150" --hlsl 50 --msl 12. Cela les rend compatibles avec OpenGL ES 2.0 et versions ultérieures, OpenGL 2.1 et versions ultérieures, ainsi qu’avec les contextes OpenGL Core Profile de version 3.2 et versions ultérieures.

Si le shader utilise des fonctions ou des constructions qui n’ont pas d’équivalent dans les cibles spécifiées, l’ qsb échouera. Si tel est le cas, les cibles devront être ajustées, ce qui implique également que la configuration minimale requise pour l’application sera implicitement ajustée. Prenons par exemple la fonction GLSL ` textureLod `, qui n’est disponible qu’avec OpenGL ES 3.0 et versions ultérieures (c’est-à-dire GLSL ES 300 ou supérieur). En demandant l’ 300 es GLSL au lieu de 100 es, qsb s’exécutera correctement, mais l’application utilisant ce fichier .qsb nécessitera désormais OpenGL ES 3.0 ou une version supérieure et ne sera plus compatible avec les systèmes basés sur OpenGL ES 2.0.

Les shaders de calcul constituent un autre exemple évident : les shaders .comp devront spécifier --glsl 310es,430, car les shaders de calcul ne sont disponibles qu’avec OpenGL ES 3.1 ou une version plus récente, ainsi qu’avec OpenGL 4.3 ou une version plus récente.

L’ajustement de la version du Shader Model pour HLSL, ou de la version du Metal Shading Language, ne devrait être nécessaire que rarement. Le Shader Model 5.0 (--hlsl 50) et le MSL 1.2 (--msl 12) seront généralement suffisants.

Qt Quick Regroupement dans le graphe de scène

Le moteur de rendu du graphe de scène Qt Quick prend en charge le regroupement de la géométrie afin de réduire le nombre d’appels de dessin. Consultez les pages consacrées au graphe de scène pour plus de détails. Ce fonctionnement repose sur l’injection de code dans la fonction main() du shader de sommets. Dans Qt 5.x, cela s’effectuait à l’exécution, en modifiant le code GLSL du shader de sommets fourni. Dans Qt 6, cette option n’est plus disponible. À la place, des variantes de shaders de sommets pouvant être traitées par lots peuvent être générées par l’outil qsb. Cette fonctionnalité est activée par l’argument -b. Lorsque l’entrée n’est pas un shader de sommets doté de l’extension « .vert », cet argument n’a aucun effet. Pour les shaders de sommets, cependant, cela entraînera la génération de deux versions pour chaque cible. Qt Quick choisira alors automatiquement la bonne variante (standard ou pouvant être traitée par lots) au moment de l’exécution.

Remarque : les applications n’ont pas à se soucier des détails du traitement par lots. Elles doivent simplement s’assurer que ` -b ` (ou le mot-clé équivalent ` BATCHABLE ` si l’intégration CMake est utilisée) est spécifié lors du traitement des shaders de sommets. Cela ne concerne que les shaders de type « Qt Quick » utilisés avec ` ShaderEffect ` ou ` QSGMaterialShader`.

Prenons l’exemple de shader de sommets suivant :

#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;
}

L'exécution de ` qsb -b --glsl 330 -o example.vert.qsb example.vert ` donne :

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: {
  ...

Notez que tous les langages et versions cibles existent désormais en deux variantes : Standard et Batchable (légèrement modifiée).

Appel d’outils externes

qsb permet d’appeler certains outils externes. Ceux-ci se répartissent en deux catégories : les outils permettant d’effectuer des optimisations sur le bytecode du shader (SPIR-V), et les outils spécifiques à la plateforme permettant d’effectuer la première phase de compilation du shader, de la source vers un format de bytecode intermédiaire.

Ces outils sont activés par les options de ligne de commande suivantes :

  • -O - appelle spirv-opt comme étape de post-traitement sur le binaire SPIR-V. Le fichier .qsb contiendra la version optimisée. Cela suppose que spirv-opt soit disponible sur le système (par exemple, à partir du SDK Vulkan) et prêt à être appelé.
  • -c ou --fxc - appelle fxc.exe, le compilateur de shaders Direct 3D. Les données DXBC (code octet DirectX) ainsi générées sont stockées dans le fichier .qsb à la place du code HLSL. Qt les récupère automatiquement lors de l’exécution ; c’est donc au créateur du fichier .qsb de décider ce qu’il souhaite inclure : le code source HLSL ou le format intermédiaire. Dans la mesure du possible, privilégiez ce dernier, car il évite d’avoir à analyser un code source HLSL lors de l’exécution, ce qui peut entraîner des gains de performances significatifs lors de la création du pipeline graphique. L’inconvénient est que cet argument ne peut être utilisé que lorsque qsb s’exécute sous Windows.
  • -t ou --metallib - appelle les outils XCode Metal appropriés pour générer un fichier .metallib et l’inclut dans le paquet .qsb à la place du code source MSL. Cette option n’est disponible que lorsque qsb s’exécute sous macOS.

Autres options

  • -D - définit une macro. Cela permet d’utiliser #ifdef et des instructions similaires dans le code source GLSL.
  • -g - active la génération d’informations de débogage complètes pour SPIR-V, permettant ainsi à des outils tels que RenderDoc d’afficher le code source complet lors de l’inspection d’un pipeline ou lors du débogage de sommets ou de fragments. Cela a également un effet sur Direct 3D lorsque l’option « -c » est spécifiée, car fxc reçoit alors pour instruction d’inclure des informations de débogage dans le bytecode intermédiaire généré.
  • --mediump - demande que la précision par défaut des nombres à virgule flottante dans les shaders de fragment GLSL ES soit réglée sur « moyenne ». Ignoré pour toutes les autres cibles, y compris GLSL (non-ES), et pour les shaders autres que de fragment.
  • --orig-file - spécifie le nom de fichier utilisé à la place du fichier source d’entrée lors de la génération des fichiers de dépendances pour CMake (–depfiles). Cela s’avère utile lorsque le fichier transmis à qsb est un fichier source de shader intermédiaire généré. Toutefois, à des fins de suivi des dépendances, c’est souvent le fichier d’origine qui doit être utilisé.

Tessellation

  • --msltess - Indique que le shader de sommets est utilisé dans un pipeline comprenant des étapes de tessellation. N’a aucun effet pour les autres types de shaders, ni lorsque la génération de shaders MSL n’est pas activée. Si cette option n’est pas spécifiée, le shader de sommets ne fonctionnera pas sur Metal en combinaison avec la tessellation.
  • --tess-vertex-count <count> - Spécifie le nombre de sommets en sortie de l'étape de contrôle de tessellation. La spécification de ce paramètre est obligatoire pour les shaders d'évaluation de tessellation utilisés avec Metal. La valeur par défaut est 3. Si elle ne correspond pas à l'étape de contrôle de tessellation, le code MSL généré ne fonctionnera pas comme prévu.
  • --tess-mode <mode> - Cette option spécifie le mode de tessellation. Elle peut prendre l’une des deux valeurs suivantes : triangles ou quads. La valeur par défaut est triangles. Cette spécification est obligatoire pour les shaders de contrôle de tessellation utilisés avec Metal. La valeur doit correspondre à l’étape d’évaluation de la tessellation, sinon le code MSL généré ne fonctionnera pas comme prévu.

Multivue

Prenons le shader de sommets suivant. Il est écrit en GLSL compatible Vulkan, l’extension GL_EXT_multiview étant activée pour permettre l’utilisation de gl_ViewIndex.

#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;
}

Remarque : en pratique, la ligne #extension GL_EXT_multiview ne sera pas nécessaire dans le code source transmis à qsb, car le passage de l’argument --view-count décrit ci-dessous injecte automatiquement cette ligne dans le code source du shader avant la compilation en SPIR-V.

Pour Vulkan, cela fonctionne tel quel, à condition que Vulkan 1.1 soit pris en charge lors de l’exécution. Voir VK_KHR_multiview pour plus de détails.

Pour générer un shader de sommets HLSL à partir de ce qui précède pour Direct 3D 12 (voir « instanciation de vues » pour plus de détails), la version minimale du modèle de shader est 6.1, ce qui signifie que la fonction ` qsb ` échouera si l’on spécifie, par exemple, ` --hlsl 50`. Utilisez au moins la version ` --hlsl 61 ` lors du traitement d’un shader de sommets multivue. La fonctionnalité multivue n’est pas prise en charge avec Direct 3D 11.

Pour OpenGL, des métadonnées supplémentaires sont nécessaires :

  • --view-count - Lors de la transcompilation du shader ci-dessus (après compilation en SPIR-V) en code source GLSL compatible OpenGL, il ne suffit pas de mapper gl_ViewIndex vers gl_ViewID_OVR; le nombre de vues doit également être déclaré dans le shader. Le fait de passer la valeur 2 à l’argument « --view-count » entraîne l’insertion d’une instruction « layout(num_views = 2) in; » dans le code source GLSL généré, ce qui en fait un shader GLSL (OpenGL) valide. Voir GL_OVR_multiview pour plus de détails et noter que les shaders GLSL générés nécessitent également la prise en charge de GL_OVR_multiview2 lors de l’exécution, car c’est ce qui sera requis par la directive #extension dans le code source du shader généré.

Lorsque vous ciblez OpenGL (ES) avec un tel shader de sommets, la version GLSL générée (--glsl) doit être au moins 330 ou 300 es. La première n’est pas imposée par qsb ou QShaderBaker, mais dans la pratique, les implémentations OpenGL sont connues pour rejeter de tels shaders si la version GLSL est inférieure ou égale à 150. Il est donc recommandé de passer --glsl 330,300es lors de la conditionnalisation des shaders de sommets activant GL_EXT_multiview.

La spécification de ` --view-count ` génère et injecte automatiquement une définition de préprocesseur : ` #define QSHADER_VIEW_COUNT n `, où ` n ` correspond au nombre de vues. Lorsque le nombre de vues n’est pas fourni, la définition n’est pas définie du tout. Cela permet d’écrire du code tel que celui ci-dessous et d’utiliser le même fichier source pour toutes les variantes du shader spécifiques au nombre de vues.

layout(std140, binding = 0) uniform buf {
#if QSHADER_VIEW_COUNT >= 2
    mat4 matrix[QSHADER_VIEW_COUNT];
#else
    mat4 matrix;
#endif
    float opacity;
};

De plus, la ligne #extension GL_EXT_multiview : require est générée automatiquement dans les shaders de sommets dès qu’un nombre de vues égal ou supérieur à 2 est défini. Cela réduit le nombre de lignes supplémentaires à ajouter pour la prise en charge multi-vues dans un shader de sommets.

La définition du nombre de vues peut également s’avérer pertinente avec d’autres types de shaders. Par exemple, lorsqu’un tampon uniforme est partagé entre le shader de sommets et le shader de fragments, et que les deux shaders doivent garantir la même structure de tampon, il peut être utile de pouvoir écrire ` #if QSHADER_VIEW_COUNT >= 2 ` dans les deux fichiers source. Cela peut être assuré en spécifiant ` --view-count ` pour les deux lors de l’appel de ` qsb`.

Remarque : le recoursdirect au mot-clé ` gl_ViewIndex ` dans un étage autre que celui des sommets, par exemple dans un shader de fragments, n’est pour l’instant pas portable et doit être évité.

Utilisation des fonctionnalités GLSL spécifiques à OpenGL

Il peut parfois s’avérer nécessaire d’utiliser des constructions du langage de shader spécifiques à OpenGL et GLSL, qui ne s’appliquent pas à d’autres langages de shader, formats intermédiaires et API graphiques.

Les textures externes et les échantillonneurs d’OpenGL ES en sont les principaux exemples. La mise en œuvre de la lecture vidéo ou l’affichage du viseur d’une caméra peut impliquer, selon la plateforme, d’utiliser des objets de texture OpenGL qui ne sont pas destinés à être utilisés comme des textures 2D classiques, mais qui peuvent toutefois être utilisés, avec un ensemble de fonctionnalités limité, via le point de liaison GL_TEXTURE_EXTERNAL_OES de l’API OpenGL et le type d’échantillonneur « samplerExternalOES » dans les shaders. Ce dernier point constitue un obstacle potentiel lors de l’utilisation du pipeline de shaders basé sur SPIR-V de Qt : l’exécution d’un tel shader via qsb entraînera un échec, car le type « samplerExternalOES » n’est pas accepté comme type valide, faute de pouvoir être mappé vers SPIR-V et d’autres langages de shading cibles.

Pour remédier à cela, qsb offre la possibilité de remplacer le contenu de n’importe quelle variante de shader d’un fichier .qsb par des données fournies par l’utilisateur et lues à partir d’un fichier, remplaçant ainsi intégralement le code source ou le bytecode du shader généré à l’origine par qsb.

Prenons l’exemple du shader de fragment suivant. Notez le type de ` tex`. Que se passe-t-il si ce type doit être ` samplerExternalOES ` lors de l’exécution avec OpenGL ES ?

#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;
}

Il n’est pas possible de se contenter de modifier le type de `samplerExternalOES`. Cela entraînerait immédiatement des erreurs de compilation.

Il existe toutefois une solution simple : écrire une version distincte du shader, ciblant exclusivement OpenGL ES, et l’injecter dans le fichier .qsb. Le shader suivant est uniquement compatible avec GLSL ES et ne peut pas être exécuté via qsb. Cependant, nous savons qu’il peut être traité par OpenGL ES lors de l’exécution.

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;
}

Appelons-le « shader_gles.frag ». Une fois l’opération « qsb --glsl 100es -o shader.frag.qsb shader.frag » terminée, ce qui nous donne un fichier .qsb (à moitié prêt), nous pouvons exécuter « qsb -r glsl,100es,shader_gles.frag shader.frag.qsb » pour mettre à jour « shader.frag.qsb » en remplaçant le shader pour GLSL 100 es par le contenu du fichier spécifié (shader_gles.frag). À présent, « shader.frag.qsb » est prêt à être utilisé en exécution avec OpenGL ES.

Remarque : veillez à ne pas modifier l’interface entre le shader et l’application. Vérifiez toujours au préalable le code GLSL généré par qsb, soit en affichant le contenu du fichier .qsb via l’option « -d », soit en extrayant le shader GLSL ES 100 à l’aide de la commande « qsb -x glsl,100es -o gles_shader.frag shader.frag.qsb ». Les noms des structures, des membres de structure et des uniformes ne doivent pas non plus différer dans la version injectée manuellement.

Remarque : la possibilité d’intégrer des données provenant de fichiers arbitraires dans le paquet .qsb peut également être utilisée pour injecter des shaders HLSL « hull » et « domain » créés manuellement, afin de rendre les pipelines graphiques basés sur la tessellation également fonctionnels avec Direct 3D.

© 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.