本页内容

QShaderBaker Class

将 GLSL/Vulkan 着色器编译为 SPIR-V,转换为其他着色语言,并收集反射元数据。更多...

标题: #include <qshaderbaker.h>
CMake: find_package(Qt6 REQUIRED COMPONENTS ShaderTools)
target_link_libraries(mytarget PRIVATE Qt6::ShaderTools)
自: Qt 6.6

公共类型

GeneratedShader
enum class GlslOption { GlslEsFragDefaultFloatPrecisionMedium }
flags GlslOptions
enum class SpirvOption { GenerateFullDebugInfo, StripDebugAndVarInfo }
flags SpirvOptions

公共函数

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.9) void setGlslOptions(QShaderBaker::GlslOptions options)
(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 setSpirvOptions(QShaderBaker::SpirvOptions options)
void setTessellationMode(QShaderDescription::TessellationMode mode)
void setTessellationOutputVertexCount(int count)

详细说明

警告:QShaderBaker与Qt GUI模块中的QRhi 类族(包括QShader 和QShaderDescription )一样,仅提供有限的兼容性保证。这些类不提供源代码或二进制兼容性保证,这意味着该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 规范以获取概述,同时请注意,QtShader Tools 模块旨在与 Qt Rendering Hardware Interface 模块中的QRhi 类结合使用,因此许多概念和结构(如 push 常量、存储缓冲区、子通道、 等)目前尚不适用。未来可能会引入更多选项,例如,一旦确认 HLSL 到 SPIR-V 的编译方案可行,便可启用HLSL作为源格式。

可以通过调用 `QShader::description()` 从生成的 `QShader ` 中检索反射元数据。当需要确定着色器期望的顶点输入和着色器资源集及其布局时,这一点至关重要,因为许多现代图形 API 并不提供内置的着色器反射功能。

典型工作流

假设某个应用程序具有如下所示的顶点着色器和片段着色器:

顶点着色器:

#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 ` 实例,有两种选择:离线生成着色器包,或在运行时生成。

前者需要运行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着色语言1.2。

请注意,命令行选项与通过setGeneratedShaders() 指定的内容相对应。一旦生成的文件准备就绪,即可随应用程序一起发布(通常通过 Qt 资源系统嵌入到可执行文件中),并在运行时加载并传递给QShader::fromSerialized()。

虽然此处未展示,但qsb 还能做更多事情:它还能够调用Windows上的fxc 或macOS上的相应XCode工具,将生成的HLSL或Metal着色器代码编译为字节码,并将编译后的版本包含在QShader 中。将烘焙后的着色器包写入文件后,可通过运行qsb -d 对其内容进行检查。 如需了解更多信息,请运行qsb 并访问--help 。

另一种方法是在运行时执行相同的操作。这需要创建一个 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 。

成员类型文档

[alias] QShaderBaker::GeneratedShader

std::pair<QShader::Source,QShaderVersion> 的同义词。

enum class QShaderBaker::GlslOption
flags QShaderBaker::GlslOptions

常数值描述
QShaderBaker::GlslOption::GlslEsFragDefaultFloatPrecisionMedium0x01在 GLSL ES 的片段着色器中输出 `precision mediump float; `。

GlslOptions 类型是QFlags<GlslOption> 的 typedef。它存储 GlslOption 值的按“或”运算组合。

enum class QShaderBaker::SpirvOption
flags QShaderBaker::SpirvOptions

常数值描述
QShaderBaker::SpirvOption::GenerateFullDebugInfo0x01在 SPIR-V 二进制文件中生成并存储额外的调试信息。
QShaderBaker::SpirvOption::StripDebugAndVarInfo0x02从 SPIR-V 二进制文件中移除所有调试和变量名信息。

SpirvOptions 类型是QFlags<SpirvOption> 的 typedef 定义。它存储 SpirvOption 值的按“或”运算组合。

成员函数文档

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 变体时,location 用于指定插入顶点输入的输入位置。该值默认为7,仅当顶点着色器已使用输入位置7时才需进行覆盖。

void QShaderBaker::setBreakOnShaderTranslationError(bool enable)

控制着当着色器转换(从 SPIR-V 到 GLSL/HLSL/MSL)失败时的行为。 默认情况下,此设置为 true,这意味着如果无法生成请求的着色器,bake() 将返回错误。如果不需要这种行为,而是希望在能够生成时生成,其余部分则静默跳过,请将enable 设置为 false。

当目标为多个 GLSL 版本时,如果某项功能无法转换为给定版本,可能会导致错误。例如,尝试将使用 textureSize() 的着色器转换为 GLSL ES 100 时,整个bake() 调用将因错误消息“textureSize 在 ESSL 100 中不被支持”而失败。 如果即使请求了 GLSL ES 100 着色器,但结果中不包含该着色器也是可以接受的,那么将此标志设置为 false 即可使bake() 调用成功。

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

指定要生成的着色器变体。在生成的QShader 中,每个着色器版本可以包含多个变体。

在大多数情况下,v 包含一个条目:QShader::StandardShader 。

注意:如果 未设置任何变体,生成的QShader 将为空,因此无效。

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

指定要编译或转换为哪种着色器。默认情况下不会生成任何内容,因此必须在调用bake()之前调用此函数

注意:若 未调用此函数,或v 为空,或仅包含无效条目,则生成的QShader 将为空,因而无效。

例如,最简化的烘焙目标是 SPIR-V,不进行任何额外的语言转换。若要请求此目标,请执行:

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

注意: QShaderBaker 仅支持 SPIR-V 和可读源代码目标。进一步编译为特定 API 的中间格式(如QShader::DxbcShader 或QShader::MetalLibShader )由qsb 命令行工具实现,不属于QShaderBaker 运行时 API 的组成部分。

[since 6.9] void QShaderBaker::setGlslOptions(QShaderBaker::GlslOptions options)

为生成的 GLSL 和 GLSL ES 源代码设置额外的options 。默认情况下不设置任何标志。

该函数于 Qt 6.9 中引入。

[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 ”设置为 2 或更大还会注入一些预处理器语句:QSHADER_VIEW_COUNT 将被设置为count ,同时GL_EXT_multiview 扩展会自动启用。因此,设置适当的“count ”对其他类型的着色器也可能很重要,例如当顶点着色器和片段着色器共享一个统一缓冲区,且两个着色器都必须能够写入类似#if QSHADER_VIEW_COUNT >= 2 的内容时。

该函数于 Qt 6.7 中引入。

void QShaderBaker::setPerTargetCompilation(bool enable)

将“按目标编译”设置为enable 。默认情况下此选项处于禁用状态,这意味着Vulkan/GLSL源代码会针对每个变体编译一次为SPIR-V。(即默认情况下编译一次;如果是顶点着色器且按要求还包含Batchable变体,则编译两次)。 生成的 SPIR-V 随后会被翻译成各种目标语言(GLSL、HLSL、MSL)。

在按目标编译模式下,每个目标都有一个独立的 GLSL 到 SPIR-V 编译步骤,这意味着对于通过 `setGeneratedShaders()` 请求的每个 GLSL/HLSL/MSL 版本,都会进行单独编译。输入源代码相同,但会插入针对特定目标的预处理器定义。 虽然这种方式耗时明显更长,但允许应用程序提供单个着色器,并通过#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 着色语言时定义(通常由 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 ,无论其中包含多少个独立目标。因此,uniform 块的成员、顶点输入等不得使用上述宏设置为条件变量。

警告:请 注意图形 API 与着色语言概念之间的差异。QShaderBaker 及其相关工具严格遵循着色语言的概念,忽略后续结果的消费方式。 因此,如果 Qt 图形栈中的更高层某天开始在 Vulkan 以外的 API 中也使用 SPIR-V,那么“QSHADER_SPIRV 即表示 Vulkan”这一假设将不再成立。

void QShaderBaker::setPreamble(const QByteArray &preamble)

指定一个自定义的preamble ,该指令会在常规着色器代码之前进行处理。

这不仅仅是将内容附加到源字符串开头:GLSL版本指令(必须置于所有内容之前)的有效性不会受到影响。错误消息中报告的行号也保持不变,且会忽略preamble 中给定的内容。

前言的一个应用场景是透明地插入动态生成的#define 语句。

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

设置源device 。这允许使用任何QIODevice ,而不仅仅是文件。stage 指定着色器阶段,而可选的fileName 包含一个文件名,该文件名将用于错误消息中。

警告: device 应包含可信内容。建议应用程序开发人员在传递来自应用程序无法控制的来源的用户提供的数据之前,仔细考虑其潜在影响。

void QShaderBaker::setSourceFileName(const QString &fileName)

将着色器源文件的名称设置为fileName 。调用bake()时,系统将读取该文件。着色器阶段会根据文件扩展名自动推断出来。如果不需要或无法这样做,请改用带stage参数的重载版本。

支持的文件扩展名包括:

  • .vert - 顶点着色器
  • .frag - 片段(像素)着色器
  • .tesc - 细分控制(外壳)着色器
  • .tese - 细分评估(域)着色器
  • .geom - 几何着色器
  • .comp - 计算着色器

警告: fileName 应包含可信内容。建议应用程序开发人员在传递不属于应用程序本身的用户提供的源文件之前,仔细考虑其潜在影响。

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

将着色器源文件的名称设置为fileName 。调用bake() 时,系统将读取该文件。着色器阶段由stage 指定。

警告: fileName 应包含可信内容。建议应用程序开发人员在传递不属于应用程序本身的用户提供的源文件之前,仔细考虑其潜在影响。

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

设置输入着色器sourceString 。stage 指定了着色器阶段,而可选参数fileName 包含一个文件名,该文件名将用于错误消息中。

警告: sourceString 应包含可信内容。建议应用程序开发人员在传递来自应用程序无法控制来源的用户提供的数据之前,仔细考虑其潜在影响。

void QShaderBaker::setSpirvOptions(QShaderBaker::SpirvOptions options)

为生成的 SPIR-V 二进制文件设置额外的options 。默认情况下不设置任何标志。

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

在为细分控制着色器生成 MSL 着色器代码时,必须预先确定细分mode (三角形或四边形)。在 GLSL 中,这通常在细分评估着色器中声明,但在 Metal 中,当从细分控制着色器生成计算着色器时,也必须已知该 。

若未设置,默认值为三角形。

void QShaderBaker::setTessellationOutputVertexCount(int count)

在为细分评估着色器生成 MSL 着色器代码时,必须预先知道细分控制着色器的输出顶点count 。在 GLSL 中,该顶点通常会在细分控制着色器中声明,但在 Metal 中,从细分评估着色器生成顶点着色器时,也必须知道该顶点。

若未设置,默认值为 3。

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