QShaderBaker Class

GLSL/VulkanシェーダーをSPIR-Vにコンパイルし、他のシェーディング言語に翻訳し、リフレクションのメタデータを収集します。詳細...

Header: #include <QShaderBaker>
Since: Qt 6.6

パブリック型

パブリック関数

QShaderBaker()
~QShaderBaker()
QShader bake()
QString errorMessage() const
void setBatchableVertexShaderExtraInputLocation(int location)
void setBreakOnShaderTranslationError(bool enable)
void setGeneratedShaderVariants(const QList<QShader::Variant> &v)
void setGeneratedShaders(const QList<QShaderBaker::GeneratedShader> &v)
(since 6.7) void setMultiViewCount(int count)
void setPerTargetCompilation(bool enable)
void setPreamble(const QByteArray &preamble)
void setSourceDevice(QIODevice *device, QShader::Stage stage, const QString &fileName = QString())
void setSourceFileName(const QString &fileName)
void setSourceFileName(const QString &fileName, QShader::Stage stage)
void setSourceString(const QByteArray &sourceString, QShader::Stage stage, const QString &fileName = QString())
void setTessellationMode(QShaderDescription::TessellationMode mode)
void setTessellationOutputVertexCount(int count)

詳細説明

警告 QShaderBaker は、QShaderQShaderDescription を含む Qt Gui モジュールのQRhi クラスファミリーと同様に、限られた互換性しか保証していません。つまり、APIはアプリケーションが開発されたQtバージョンでのみ動作することが保証されています。しかし、ソース互換性のない変更は最小限に抑えることを目的としており、マイナーリリース(6.7、6.8など)でのみ行われます。アプリケーションでこのクラスを使用するには、Qt::ShaderToolsPrivate (CMake を使用している場合) にリンクし、rhi のプレフィックスを付けてヘッダをインクルードします。例えば、#include <rhi/qshaderbaker.h> です。

QShaderBaker はグラフィックス(頂点、フラグメントなど)またはコンピュートシェーダを受け取り、その複数の(ソースまたはバイトコードの)バリエーションを、リフレクション情報とともに生成します。結果はQShader インスタンスで表現され、シンプルで高速なシリアライズとデシリアライズも提供します。

注意: アプリケーションやライブラリは、このクラスを直接使用しないことを推奨します。むしろ、すべての Qt ユーザーは、ビルド時に CMake を介してqsb コマンドラインツールを呼び出すことで、オフラインコンパイルに依存することが推奨されます。qsb ツールは QShaderBaker を使用し、生成されたQShader のシリアライズバージョンをファイルに書き込みます。このクラスの使用は、ユーザー提供のシェーダー・ソース文字列や動的に生成されたシェーダー・ソース文字列を扱う場合など、実行時のコンパイルが避けられない場合に限られるべきです。

入力フォーマットは、現時点では常にVulkan風味のGLSLであると仮定されます。概要についてはGL_KHR_vulkan_glsl 仕様を参照してください。Qt Shader Tools モジュールは Qt Rendering Hardware Interface モジュールのQRhi クラスと組み合わせて使用することを想定しているため、多くの概念や構成要素(プッシュ定数、ストレージバッファ、サブパスなど)は現時点では適用できません。将来的には、HLSLからSPIR-Vへのコンパイルが適切と判断された時点で、ソース形式としてHLSLを有効にするなど、追加オプションが導入される可能性があります。

反射メタデータは、QShader::description()を呼び出すことで、結果のQShader から取得できます。これは、シェーダが期待する頂点入力とシェーダリソースのセットと、それらのレイアウトを発見しなければならないときに不可欠です。

典型的なワークフロー

アプリケーションに次のような頂点シェーダとフラグメントシェーダがあると 仮定しましょう:

頂点シェーダ:

#version 440

layout(location = 0) in vec4 position;
layout(location = 1) in vec3 color;
layout(location = 0) out vec3 v_color;

layout(std140, binding = 0) uniform buf {
    mat4 mvp;
    float opacity;
};

void main()
{
    v_color = color;
    gl_Position = mvp * position;
}

フラグメントシェーダ

#version 440

layout(location = 0) in vec3 v_color;
layout(location = 0) out vec4 fragColor;

layout(std140, binding = 0) uniform buf {
    mat4 mvp;
    float opacity;
};

void main()
{
    fragColor = vec4(v_color * opacity, opacity);
}

そのままQRhiGraphicsPipeline に渡せるQShader インスタンスを得るには、シェーダパック生成 をオフラインで行うか、実行時に行うかの 2 つのオプションがあります。

前者ではqsb ツールを実行します:

qsb --glsl "100 es,120" --hlsl 50 --msl 12 color.vert -o color.vert.qsb
qsb --glsl "100 es,120" --hlsl 50 --msl 12 color.frag -o color.frag.qsb

この例ではQRhi に適したトランスレーションターゲットを使用しています。つまり、GLSL/ES 100、GLSL 120、HLSL シェーダモデル 5.0、および Metal Shading Language 1.2 です。

コマンドラインオプションがsetGeneratedShaders() で指定できるものとどのように対応しているかに注意してください。出来上がったファイルが利用可能になると、アプリケーションと一緒に出荷することができ(通常は Qt Resource System の実行ファイルに埋め込まれます)、実行時にロードしてQShader::fromSerialized() に渡すことができます。

qsb fxc 生成された HLSL または Metal シェーダーコードをバイトコードにコンパイルし、コンパイルされたバージョンをQShader に含めることができます。ベイクされたシェーダーパックがファイルに書き込まれた後、qsb -d を実行することで、その内容を調べることができます。詳細については、--help とともにqsb を実行してください。

別の方法は、実行時に同じことを行うことです。これには、QShaderBaker のインスタンスを作成し、setSourceFileName() を呼び出し、setGeneratedShaders() でトランスレーションターゲットを設定します:

baker.setGeneratedShaderVariants({ QShader::StandardShader });
QList<QShaderBaker::GeneratedShader> targets;
targets.append({ QShader::SpirvShader, QShaderVersion(100) });
targets.append({ QShader::GlslShader, QShaderVersion(100, QShaderVersion::GlslEs) });
targets.append({ QShader::SpirvShader, QShaderVersion(120) });
targets.append({ QShader::HlslShader, QShaderVersion(50) });
targets.append({ QShader::MslShader, QShaderVersion(12) });
baker.setGeneratedShaders(targets);
QShader shaders = baker.bake();
if (!shaders.isValid())
    qWarning() << baker.errorMessage();

QShaderも参照してください

メンバ型ドキュメント

QShaderBaker::GeneratedShader

QPair<QShader::Source,QShaderVersion> の同義語。

メンバ関数ドキュメント

QShaderBaker::QShaderBaker()

新しい QShaderBaker を構築します。

[noexcept] QShaderBaker::~QShaderBaker()

デストラクタ。

QShader QShaderBaker::bake()

コンパイルと変換処理を実行します。

QShader インスタンスを返します。処理が成功したかどうかを確認するには、QShader::isValid() を呼び出します。その結果、false が表示されたら、errorMessage() を呼び出してログを取得します。

これは高価な操作である。アプリケーションからこの処理を呼び出す場合は、別のスレッドで実行することをお勧めします。

注: QShaderBaker インスタンスは再利用可能である:bake()を呼び出した後、同じインスタンスを異なる入力で再度使用することができる。ただし、QShaderBaker インスタンスは、その有効期間中、単一のスレッドでのみ使用する必要があります。

QString QShaderBaker::errorMessage() const

最後にbake() を実行したときのエラーメッセージを返すか、エラーがなければ空文字列を返します。

注意: エラーには、ファイルの読み取りエラー、コンパイル、翻訳の失敗が含まれます。結果のQShader が無効であっても、ターゲットやバリアントを要求しなかったことはエラーとしてカウントされません。

void QShaderBaker::setBatchableVertexShaderExtraInputLocation(int location)

QShader::BatchableVertexShader variant を生成するとき、location は挿入される頂点入力の入力位置を指定します。この値はデフォルトで 7 であり、頂点シェーダがすでに入力位置 7 を使用している場合にのみオーバーライドする必要があります。

void QShaderBaker::setBreakOnShaderTranslationError(bool enable)

シェーダの変換(SPIR-V から GLSL/HLSL/MSL)に失敗したときの動作を制御します。デフォルトではこの設定は true で、要求されたシェーダが生成できない場合、bake() がエラーで返されます。これを望まず、生成できるものは生成するが、残りは黙ってスキップすることを意図する場合は、enable を false に設定します。

複数の GLSL バージョンをターゲットにすると、ある機能があるバージョンに翻訳 できないときにエラーになることがあります。たとえば、textureSize() を使用したシェーダを GLSL ES 100 に変換しようとすると、bake() の呼び出し全体が失敗し、"textureSize is not supported in ESSL 100" というエラーメッセージが表示されます。GLSL ES 100 シェーダが要求されたにもかかわらず、結果に GLSL ES 100 シェーダがなくても構わない場合は、このフラグを false に設定すると、bake() は成功します。

void QShaderBaker::setGeneratedShaderVariants(const QList<QShader::Variant> &v)

どのシェーダバリアントを生成するかを指定します。各シェーダのバージョンは、結果のQShader に複数のバリアントを持つことができます。

たいていの場合、v には単一のエントリQShader::StandardShader が含まれます。

注意: variants が設定されていない場合、結果のQShader は空になり、無効です。

void QShaderBaker::setGeneratedShaders(const QList<QShaderBaker::GeneratedShader> &v)

どのようなシェーダをコンパイルまたは変換するかを指定します。デフォルトでは何も生成されないので、bake() の前にこの関数を呼び出すことが必須です。

注意: この関数が呼び出されなかったり、v が空であったり、無効な項目しか含まれていない場合、結果のQShader は空となり、無効となります。

例えば、最小限のベーキングターゲットはSPIR-Vであり、他の言語への追加翻訳はない。これを要求するには、次のようにする:

baker.setGeneratedShaders({ QShader::SpirvShader, QShaderVersion(100) });

注: QShaderBaker は、SPIR-Vと人間が読めるソース・ターゲットのみを扱う。QShader::DxbcShaderQShader::MetalLibShader のような API 固有の中間フォーマットへのさらなるコンパイルは、qsb コマンドラインツールによって実装され、QShaderBaker ランタイム API の一部ではありません。

[since 6.7] void QShaderBaker::setMultiViewCount(int count)

マルチビューを使用するシェーダをトランスパイルする場合(たとえば、GL_OVR_multiview2、VK_KHR_multiviewなどに依存するレンダラー用にgl_ViewIndexを使用する頂点シェーダ)、一部のターゲットではシェーダ内のビュー数を宣言する必要があります。これは Vulkan スタイルの GLSL コードでは行われず、SPIR-V や HLSL などのターゲットには関係ありませんが、OpenGL や GLSL では必要なため、値を追加のメタデータとして提供する必要があります。

デフォルトでは値は0であり、num_views ステートメントの注入を無効にします。1を設定しても、デフォルトのnum_views になるので意味がありません。したがって、count を有効にするには >= 2 でなければならない。たとえば 2 に設定すると、生成される GLSL シェーダにはlayout(num_views = 2) in; ステートメントが含まれます。

count QSHADER_VIEW_COUNT は に設定されますが、 拡張は自動的に有効になります。例えば、頂点シェーダとフラグメントシェーダの間で均一バッファを共有し、両方のシェーダが のようなものを記述できる必要がある場合などです。count GL_EXT_multiview count #if QSHADER_VIEW_COUNT >= 2

この関数は Qt 6.7 で導入されました。

void QShaderBaker::setPerTargetCompilation(bool enable)

Sets per-target compilation toenable. デフォルトではこれは無効になっており、Vulkan/GLSL ソースはバリアントごとに 1 回 SPIR-V にコンパイルされます。(つまり、Vulkan/GLSL ソースは、バリアントごとに 1 回、SPIR-V にコンパイルされます(デフォルトでは 1 回、バーテックスシェーダの場合は 2 回、Batchable バリアントの場合は要求に応じて 2 回)。その結果、SPIR-V はさまざまなターゲット言語(GLSL、HLSL、MSL)に翻訳されます。

ターゲットごとのコンパイルモードでは、各ターゲット、つまりsetGeneratedShaders() を介して要求された GLSL/HLSL/MSL バージョンごとに、個別の GLSL から SPIR-V へのコンパイルステップがあります。入力ソースは同じですが、ターゲット固有のプリプロセッサ定義が挿入されます。これはかなり時間がかかりますが、アプリケーションが単一のシェーダを提供し、#ifdef ブロックを使用して区別することができます。このモードが無効な場合、同じことを達成する唯一の方法は、シェーダ ファイルの複数のバージョンを提供し、それぞれを別々に処理し、{.qsb} ファイルをそれぞれ出荷し、ランタイムロジックに基づいて正しいファイルを選択することです。

このモードでは、以下のマクロが自動的に定義されます。マクロはグラフィック API ではなく、常にシェーディング言語に関連付け られていることに注意してください。

  • QSHADER_SPIRV - SPIR-Vをターゲットとする場合に定義されます(通常、Vulkanによって消費されます)。
  • QSHADER_SPIRV_VERSION - ターゲットとする SPIR-V のバージョン番号、例えば 。100
  • QSHADER_GLSL - GLSLまたはGLSL ES(通常、OpenGLまたはOpenGL ESによって消費される)をターゲットとする場合に定義されます。
  • QSHADER_GLSL_VERSION - ターゲットとする GLSL または GLSL ES バージョン番号。 、 、 など。100 300 330
  • QSHADER_GLSL_ES - GLSL ESをターゲットとする場合のみ定義されます。
  • QSHADER_HLSL - HLSL をターゲットとする場合に定義されます(通常、Direct 3D によって消費されます)。
  • QSHADER_HLSL_VERSION - など、ターゲットとする HLSL シェーダモデルバージョン。50
  • QSHADER_MSL - Metal Shading Language をターゲットとするときに定義される(通常、Metal によって消費される)。
  • QSHADER_MSL_VERSION - ターゲットとする MSL バージョン、たとえば や など。12 20

これにより、次のようなシェーダコードを書くことができます。

#if QSHADER_HLSL || QSHADER_MSL
vec2 uv = vec2(uv_coord.x, 1.0 - uv_coord.y);
#else
vec2 uv = uv_coord;
#endif

注意: バージョン番号は GLSL にインスパイアされたQShaderVersion 構文に従っ ているため、常に単一の整数です。

注意 :QShader あたりQShaderDescription は、個々のターゲットがいくつあろうとも 1 つだけです。したがって、ユニフォームブロックのメンバーや頂点入力などは、上記のマクロを使って条件付きにしてはいけません。

警告 グラフィックスAPIとシェーディング言語のコンセプトの違いに注意してください。QShaderBaker と関連ツールは、シェーディング言語のコンセプトで厳密に動作し、その後に結果がどのように消費されるかは無視されます。したがって、Qt グラフィックススタックの上位レイヤーが、ある日突然、Vulkan 以外の API でも SPIR-V を使用し始めた場合、QSHADER_SPIRV が Vulkan を意味するという仮定はもはや成り立たなくなります。

void QShaderBaker::setPreamble(const QByteArray &preamble)

通常のシェーダコードの前に処理されるカスタムpreamble を指定します。

これは単にソース文字列の前に追加するだけではありません: GLSL version 指令の有効性は影響を受けません。報告されるエラーメッセージの行番号も、preamble で指定された内容を無視して変更されません。

プリアンブルの使用例の1つは、動的に生成された#define ステートメントを透過的に挿入することです。

void QShaderBaker::setSourceDevice(QIODevice *device, QShader::Stage stage, const QString &fileName = QString())

ソースdevice を設定する。QIODevice stage はシェーダステージを指定し、オプションのfileName にはエラーメッセージで使用されるファイル名を指定します。

void QShaderBaker::setSourceFileName(const QString &fileName)

シェーダ・ソース・ファイルの名前をfileName に設定します。これは、bake() を呼び出すときに読み込まれるファイルです。シェーダ・ステージはファイル拡張子から自動的に推測されます。これが不要な場合や不可能な場合は、代わりに stage 引数を指定してオーバーロードを使用します。

サポートされているファイル拡張子は

  • .vert - 頂点シェーダ
  • .frag - フラグメント(ピクセル)シェーダ
  • .tesc - テッセレーション制御(ハル)シェーダ
  • .tese - テッセレーション評価(ドメイン)シェーダ
  • .geom - ジオメトリ・シェーダ
  • .comp - 計算シェーダ

void QShaderBaker::setSourceFileName(const QString &fileName, QShader::Stage stage)

シェーダソースファイルの名前をfileName に設定します。 これはbake() を呼び出すときに読み込まれるファイルです。シェーダのステージはstage で指定します。

void QShaderBaker::setSourceString(const QByteArray &sourceString, QShader::Stage stage, const QString &fileName = QString())

入力シェーダを設定しますsourceString.stage はシェーダステージを指定し、オプションのfileName にはエラーメッセージで使用されるファイル名が含まれます。

void QShaderBaker::setTessellationMode(QShaderDescription::TessellationMode mode)

テッセレーション制御シェーダ用の MSL シェーダコードを生成する場合、テッセレーショ ンmode (三角形または四角形)を前もって知っておく必要があります。GLSLでは、これは通常テッセレーション評価シェーダで宣言されますが、Metalの場合は、テッセレーション・コントロール・シェーダから計算シェーダを生成するときにも知っておく必要があります。

設定されていない場合、デフォルトは三角形です。

void QShaderBaker::setTessellationOutputVertexCount(int count)

テセレーション評価シェーダ用の MSL シェーダコードを生成するとき、テセレーション制御シェーダの出力頂点count を前もって知っておく必要があります。GLSL では、これは通常テセレーション制御シェーダで宣言されますが、Metal の場合は、テセレーション評価シェーダから頂点シェーダを生成するときにも知っておく必要があります。

設定されていない場合、デフォルト値は3です。

本ドキュメントに含まれる文書の著作権は、それぞれの所有者に帰属します。 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。