このページについて

QSBマニュアル

qsb は、QtのShader Toolsモジュールによって提供されるコマンドラインツールです。glslangや SPIRV-Crossといったサードパーティ製ライブラリを統合し、必要に応じてfxc やspirv-opt などの外部ツールを呼び出し、.qsb ファイルを生成します。さらに、.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.

動作モード

主な動作モードは5つあります:

  • .qsb ファイル生成。
  • .qsb ファイルの検査。例えば、qsb -d myshader.frag.qsb を実行すると、リフレクションのメタデータ(JSON形式)と、含まれているシェーダーが出力されます。
  • 抽出モード。これにより、既存の.qsb ファイルから指定されたシェーダーを別のファイルに書き出すことができます。例えば、qsb -x spirv,100 -o myshader.spv myshader.frag.qsb を実行すると、SPIR-Vバイナリがmyshader.spv に書き出されます。
  • 置換モード。これにより、.qsb ファイル内の1つまたは複数のシェーダーの内容を、指定されたファイルから読み込まれた内容で置き換えることができます。これにより、手作業で作成したシェーダーコードを.qsb パッケージに組み込むことが可能です。
  • 消去モード。これにより、.qsb ファイルから指定されたシェーダーバリアントが削除されます。

例

次のフラグメントシェーダーを例に挙げます:

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

qsb -o shader.frag.qsb shader.frag を実行すると、shader.frag.qsb が生成されます。このファイルをqsb -d shader.frag.qsb で確認すると、次のような内容になります:

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

デフォルトでは SPIR-V のみが生成されるため、このシェーダーパッケージを使用するアプリケーションは Vulkan でのみ動作します。これをより汎用性の高いものにしましょう:

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

これにより、OpenGL、Direct 3D、Metal にも対応したシェーダーパッケージが生成されます。このシェーダーで使用されている機能は基本的なものであり、GLSL ES 100(OpenGL ES 2.0 のシェーディング言語)でも十分に対応可能です。

結果を確認すると、次のようになります:

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

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

...

このパッケージは、Qt Quick によって、Vulkan、Direct 3D、Metal、OpenGL、OpenGL ESといった、サポートされているすべてのグラフィックスAPIで使用できるようになりました。実行時には、Qt Quick およびQt Quick 3Dの下層にあるQt Rendering Hardware Interfaceによって、適切なシェーダーが自動的に選択されます。

このシステムは、SPIR-Vバイトコードをより高レベルのソースコードに変換するだけでなく、SPIR-Vのバインディング番号をネイティブリソースに正しくマッピングすることなど、その他の問題も処理します。例えば、HLSLでは、上記のようなセクションが見られました:

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

内部的には、これにより、SPIR-V 形式のバインディングポイント `0 ` を HLSL レジスタ `b0 ` にマッピングし、`1 ` を `t0 ` および `s0` にバインドすることが可能になります。 これにより、さまざまなシェーディング言語間のリソースバインディングの違いが、レンダリングハードウェアインターフェースのユーザーにとって透明化され、Qt内のすべての要素が、元のVulkanスタイルのGLSLソースコードで指定されている通りのVulkan/SPIR-Vスタイルのバインディングポイントを使用して動作できるようになります。

シェーダーの種類

シェーダーのタイプは、入力ファイルの拡張子から判別されます。したがって、拡張子は以下のいずれかでなければなりません:

  • .vert - 頂点シェーダーの場合
  • .tesc - テッセレーション制御シェーダーの場合
  • .tese - テッセレーション評価シェーダー用
  • .geom - ジオメトリシェーダー用
  • .frag - フラグメント(ピクセル)シェーダー用
  • .comp - コンピュートシェーダー用

注:テッセレーション 制御シェーダーおよび評価シェーダーは、現在 Direct 3D (HLSL) ではサポートされていません。

シェーディング言語とバージョン

SPIR-V 1.0 は常に生成されます。それ以外に何が生成されるかは、コマンドライン引数 `--glsl`、`--hlsl`、および `--msl` によって決まります。

これらのパラメータの後ろには、コンマ区切りのリストが続きます。リストには、GLSL形式のバージョン番号を含める必要があり、オプションで接尾辞(GLSL ESを示す「es 」)を付けることができます。接尾辞とバージョンの間のスペースは任意です(スペースを省略すると、引用符で囲む必要がなくなる場合があります)。

たとえば、Qt Quick の組み込みマテリアル(Image 、Text 、Rectangle などのアイテムを支えるシェーダー)は、すべて--glsl "100 es,120,150" --hlsl 50 --msl 12 でシェーダーを準備しています。これにより、OpenGL ES 2.0 以降、OpenGL 2.1 以降、およびバージョン 3.2 以降の OpenGL コアプロファイルコンテキストとの互換性が確保されます。

シェーダーが、指定されたターゲットに相当する機能を持たない関数や構文を使用している場合、qsb は失敗します。その場合はターゲットを調整する必要があり、これはアプリケーションの最小システム要件も暗黙的に調整されることを意味します。 例として、OpenGL ES 3.0 以降(つまり GLSL ES 300 以降)でのみ利用可能な GLSL 関数 `textureLod ` を挙げます。100 es の代わりにGLSLの300 es を要求すると、qsb は成功しますが、その.qsb ファイルを使用するアプリケーションはOpenGL ES 3.0以降を必要とし、OpenGL ES 2.0ベースのシステムとは互換性がなくなります。

この点に関するもう 1 つの明らかな例は、コンピュートシェーダーです。.comp のシェーダーでは、--glsl 310es,430 を指定する必要があります。これは、コンピュートシェーダーが OpenGL ES 3.1 以降および OpenGL 4.3 以降でのみ利用可能であるためです。

HLSLのシェーダーモデルバージョンやMetal Shading Languageのバージョンを調整する必要が生じることは、ほとんどないと思われます。通常、シェーダーモデル5.0(--hlsl 50 )およびMSL 1.2(--msl 12 )で十分です。

Qt Quick シーングラフのバッチ処理

Qt Quick のシーングラフのレンダラーは、描画呼び出しの数を減らすためにジオメトリのバッチ処理をサポートしています。詳細については、シーングラフのページを参照してください。これは、頂点シェーダーのmain()関数にコードを挿入することに依存しています。Qt 5.xでは、これは実行時に、提供されたGLSL頂点シェーダーコードを修正することで行われていました。 Qt 6 では、この方法は利用できません。代わりに、qsb ツールを使用して、バッチ処理可能なバージョンの頂点シェーダーをビルドできます。これは、-b 引数によって指定されます。入力が.vert 拡張子を持つ頂点シェーダーでない場合、この引数は効果を持ちません。 ただし、頂点シェーダーの場合、これにより各ターゲットに対して2つのバージョンが生成されます。その後、Qt Quick が実行時に適切なバリアント(標準またはバッチ可能)を自動的に選択します。

注:アプリケーションは バッチ処理の詳細について気にする必要はありません。頂点シェーダーを処理する際に、-b (または、CMake統合を使用する場合は同等のBATCHABLE キーワード)が指定されていることを確認するだけで十分です。これは、ShaderEffect またはQSGMaterialShader と併用されるQt Quick シェーダーにのみ適用されます。

次の例のような頂点シェーダーを考えてみましょう:

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

qsb -b --glsl 330 -o example.vert.qsb example.vert を実行すると、次のようになります:

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

すべてのターゲット言語およびバージョンが、「Standard」と、わずかに変更された「Batchable」の2つのバリエーションで存在することに注目してください。

外部ツールの呼び出し

qsb を使用すると、特定の外部ツールを呼び出すことができます。これらは2つのカテゴリに分類されます:シェーダーバイトコード(SPIR-V)に対して最適化を行うツール、およびソースから中間バイトコード形式への変換というシェーダーコンパイルの第一段階を実行するプラットフォーム固有のツールです。

これらは以下のコマンドラインオプションによって有効になります:

  • -O - SPIR-Vバイナリに対する後処理ステップとしてspirv-opt を呼び出します。.qsb ファイルには最適化されたバージョンが含まれます。これは、spirv-opt がシステム上で利用可能(例:Vulkan SDKから)であり、呼び出し可能な状態にあることを前提としています。
  • -c または--fxc - Direct 3D シェーダーコンパイラである `fxc.exe` を呼び出します。 結果として生成されるDXBC (DirectXバイトコード)データが、HLSLの代わりに.qsb ファイルに格納されます。Qtは実行時にこれを自動的に読み込むため、HLSLソースと中間形式のどちらを含めるかは、.qsb ファイルの作成者が決定することになります。 可能であれば、後者を優先してください。これにより、実行時にHLSLソースを解析する必要がなくなるため、グラフィックスパイプラインの生成時に大幅なパフォーマンス向上が期待できます。欠点としては、この引数はqsb がWindows上で動作する場合にのみ使用できるという点です。
  • -t または `--metallib ` — 適切な XCode Metal ツールを呼び出して `.metallib` ファイルを生成し、MSL ソースコードの代わりにそれを `.qsb ` パッケージに含めます。このオプションは、qsb が macOS 上で実行されている場合にのみ利用可能です。

その他のオプション

  • -D - マクロを定義します。これにより、GLSLソースコード内で#ifdefなどを使用できるようになります。
  • -g - SPIR-V用の完全なデバッグ情報の生成を有効にします。これにより、RenderDocなどのツールが、パイプラインを検査したり、頂点やフラグメントのデバッグを行ったりする際に、完全なソースを表示できるようになります。また、-c が指定されている場合、fxc は生成される中間バイトコードにデバッグ情報を含めるよう指示されるため、Direct 3Dに対しても効果があります。
  • --mediump - GLSL ES フラグメントシェーダーにおいて、浮動小数点数の精度をデフォルトで「中精度」にするよう要求します。(非ES)GLSLを含むその他のターゲットや、フラグメントシェーダー以外では無視されます。
  • --orig-file - CMake用の依存関係ファイルを生成する際(–depfiles)、入力ソースファイルの代わりに使用するファイル名を指定します。これは、qsbに渡されるファイルが中間的な生成済みシェーダーソースファイルである場合に役立ちます。ただし、依存関係の追跡目的では、多くの場合、元のファイルを使用する必要があります。

テッセレーション

  • --msltess - 頂点シェーダーがテッセレーションステージを含むパイプラインで使用されることを示します。他の種類のシェーダーや、MSLシェーダー生成が有効になっていない場合には効果はありません。指定しない場合、Metal上でテッセレーションと組み合わせて使用した際、頂点シェーダーは機能しません。
  • --tess-vertex-count <count> - テッセレーション制御ステージからの出力頂点数を指定します。Metalで使用されるテッセレーション評価シェーダーでは、この指定が必須です。デフォルト値は3です。テッセレーション制御ステージと一致しない場合、生成されたMSLコードは期待どおりに機能しません。
  • --tess-mode <mode> - このオプションは、テッセレーションモードを指定します。triangles またはquads のいずれかの値を指定できます。デフォルト値はtriangles です。Metal で使用されるテッセレーション制御シェーダーでは、この指定が必須です。この値はテッセレーション評価ステージと一致している必要があり、一致しない場合、生成された MSL コードは期待どおりに機能しません。

マルチビュー

次の頂点シェーダーを例に挙げます。これはVulkan互換のGLSLで記述されており、GL_EXT_multiview 拡張機能を有効にすることで、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;
}

注:実際には、 qsb に渡されるソースコードに`#extension GL_EXT_multiview`行を記述する必要はありません。これは、後述する--view-count 引数を渡すことで、SPIR-Vへのコンパイル前にその行が自動的にシェーダーソースコードに挿入されるためです。

Vulkan の場合、実行時に Vulkan 1.1 がサポートされていれば、このままで動作します。詳細についてはVK_KHR_multiview を参照してください。

Direct 3D 12 向けに上記から HLSL 頂点シェーダーを生成する場合(詳細はビューインスタンス化を参照)、必要なシェーダーモデルバージョンは 6.1 以上です。つまり、例えば--hlsl 50 を指定すると、qsb は失敗します。マルチビュー頂点シェーダーを処理する際は、少なくとも--hlsl 61 を使用してください。 Direct 3D 11 ではマルチビューはサポートされていません。

OpenGL の場合、追加のメタデータが必要です:

  • --view-count - 上記のシェーダーを(SPIR-V へコンパイルした後)、OpenGL 互換の GLSL ソースコードへトランスパイルする場合、gl_ViewIndex をgl_ViewID_OVR にマッピングするだけでは不十分であり、シェーダー内でビューの数を宣言する必要があります。--view-count 引数に値2を渡すと、生成されたGLSLソースコードにlayout(num_views = 2) in; ステートメントが挿入され、これにより(OpenGL)GLSLシェーダーとして有効なものとなります。 詳細についてはGL_OVR_multiview を参照してください。また、生成された GLSL シェーダーでは、実行時にGL_OVR_multiview2 がサポートされている必要がある点に注意してください。これは、生成されたシェーダーソースコード内の#extension ディレクティブによって要求されるためです。

このような頂点シェーダーで OpenGL (ES) をターゲットとする場合、生成される GLSL バージョン(--glsl )は、少なくとも330 または300 es でなければなりません。前者はqsb やQShaderBaker によって強制されるものではありませんが、実際には、GLSL バージョンが 150 以下の場合、OpenGL 実装ではそのようなシェーダーが拒否されることが知られています。 したがって、GL_EXT_multiview を有効にする頂点シェーダーを条件付きで実行する際は、--glsl 330,300es を渡すことが推奨されます。

--view-count を指定すると、プリプロセッサ定義#define QSHADER_VIEW_COUNT n が自動的に生成・挿入されます。ここで、n はビューの数です。ビュー数が指定されていない場合、この定義はまったく設定されません。これにより、次のようなコードを記述でき、ビュー数に応じたシェーダのすべてのバリエーションに対して同じソースファイルを使用できるようになります。

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

さらに、ビュー数が 2 以上に設定されている場合、頂点シェーダー内では#extension GL_EXT_multiview : require という行が自動的に生成されます。これにより、頂点シェーダーでマルチビューに対応するために追加する必要のある行数が削減されます。

ビューカウントの設定は、他の種類のシェーダーでも関連する場合があります。例えば、頂点シェーダーとフラグメントシェーダー間でユニフォームバッファを共有し、両方のシェーダーが同じバッファレイアウトを保証する必要がある場合、両方のソースファイルに `#if QSHADER_VIEW_COUNT >= 2 ` を記述できると便利です。これは、qsb を呼び出す際に、両方に `--view-count ` を指定することで保証できます。

注: 頂点ステージ以外(例えばフラグメントシェーダー内)でgl_ViewIndex キーワードに直接 依存することは、現時点では移植性が保証されておらず、避けるべきです。

OpenGL に固有の GLSL 機能の取り扱い

OpenGL や GLSL に固有で、他のシェーディング言語、中間フォーマット、およびグラフィックス API には適用できないシェーディング言語の構文を使用する必要がある場合があります。

その代表的な例が、OpenGL ES の外部テクスチャおよびサンプラーです。ビデオ再生の実装やカメラのファインダー表示では、プラットフォームによっては、通常の 2D テクスチャとして使用されることを意図していない OpenGL テクスチャオブジェクトを扱う必要がありますが、 OpenGL APIのGL_TEXTURE_EXTERNAL_OESバインディングポイントや、シェーダー内のsamplerExternalOES サンプラータイプを通じて、機能セットは限定的ながらも利用可能です。 後者は、QtのSPIR-Vベースのシェーダーパイプラインを使用する際に、重大な障害となる可能性があります。qsbを通じてこのようなシェーダーを実行すると、samplerExternalOES がSPIR-Vやその他のターゲットシェーディング言語にマッピングできないため、有効な型として受け入れられず、エラーが発生します。

この問題を解決するため、qsb では、.qsb ファイル内の任意のシェーダーバリアントの内容を、ファイルから読み込んだユーザー指定のデータで置き換えるオプションを提供しています。これにより、qsb によって生成された元のシェーダーソースまたはバイトコードが完全に置き換えられます。

次のフラグメントシェーダーを例に挙げてみましょう。tex の型に注目してください。OpenGL ESで実行する際に、この型をsamplerExternalOES に変更する必要がある場合はどうすればよいでしょうか?

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

単に samplerExternalOES の型を変更するだけでは実現できません。そうすると、すぐにコンパイルエラーが発生してしまいます。

しかし、簡単な解決策があります。それは、OpenGL ES専用に最適化された別のシェーダーを作成し、それを.qsbファイルに埋め込むことです。以下のシェーダーはGLSL ESとのみ互換性があり、qsbを通じて実行することはできません。しかし、実行時にOpenGL ESによって処理できることはわかっています。

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

これをshader_gles.frag と呼びましょう。qsb --glsl 100es -o shader.frag.qsb shader.frag が完了し、(半完成状態の).qsbファイルが得られたら、qsb -r glsl,100es,shader_gles.frag shader.frag.qsb を実行して、shader.frag.qsb を更新します。この際、GLSL 100 es用のシェーダーを指定されたファイル(shader_gles.frag )の内容に置き換えます。これで、shader.frag.qsb はOpenGL ESで実行時に使用できるようになります。

注: シェーダーとアプリケーション間のインターフェースを変更しないよう注意してください 。 常に、まず qsb によって生成された GLSL コードを点検してください。これには、-d オプションを使用して .qsb ファイルの内容を出力するか、qsb -x glsl,100es -o gles_shader.frag shader.frag.qsb を実行して GLSL ES 100 シェーダーを抽出する方法があります。手動で挿入したバージョンにおいても、構造体、構造体のメンバ、およびユニフォームの名前が異なってはなりません。

注: 任意のファイルからのデータを .qsb パッケージに配置する機能は 、手作りのハルおよびドメイン HLSL シェーダーを挿入するためにも使用でき、これによりテッセレーションベースのグラフィックスパイプラインを 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.