On this page

qt_add_shaders

Compiles shaders and adds them to a Qt resource.

The command is defined in the ShaderTools component of the Qt6 package, which can be loaded with:

find_package(Qt6 REQUIRED COMPONENTS ShaderTools)

Synopsis

qt_add_shaders(<target> <name>
               PREFIX <path>
               FILES <file,...>
               [BASE <path>]
               [GLSL <version,...>]
               [NOGLSL]
               [HLSL <version,...>]
               [NOHLSL]
               [MSL <version,...>]
               [NOMSL]
               [BATCHABLE]
               [ZORDER_LOC <number>]
               [PERTARGETCOMPILE]
               [TESSELLATION]
               [TESSELLATION_VERTEX_COUNT <count>]
               [TESSELLATION_MODE <mode>]
               [VIEW_COUNT <count>]
               [MULTIVIEW]
               [PRECOMPILE]
               [OPTIMIZED]
               [DEBUGINFO]
               [QUIET]
               [DEFINES <name=value,...>]
               [OUTPUTS <file,...>]
               [ORIGINAL_FILES <file,...>]
               [OUTPUT_TARGETS <variable>]
               [MEDIUMP])

If versionless commands are disabled, use qt6_add_shaders() instead. It supports the same set of arguments as this command.

Description

Invokes the qsb tool at build time on each shader source file listed in FILES, and adds the resulting .qsb files to the Qt resource system under the resource prefix given by PREFIX.

By default, qt_add_shaders invokes qsb as follows:

qsb --glsl "100 es,120,150" --hlsl 50 --msl 12 -o <output>.qsb <input>

This produces a package containing SPIR-V (for Vulkan 1.0), GLSL ES 100 (for OpenGL ES 2.0 and newer), GLSL 120 (for non-core profile OpenGL), GLSL 150 (for core profile OpenGL), HLSL for Shader Model 5.0 (Direct3D 11.1), and Metal Shading Language 1.2 (Metal).

On WebAssembly, the defaults change to:

qsb --glsl "100 es,300 es" -o <output>.qsb <input>

which generates shaders compatible with WebGL 1 and WebGL 2.

The original shader source files are not embedded in the application's executable and do not need to be shipped. Build errors from the glslang compiler are reported at build time and the build fails. Changes to shader source files are picked up automatically on the next build, like any other source file.

Note: The target passed as the first argument must exist before qt_add_shaders is called.

Note: Multiple qt_add_shaders calls are supported. The name argument must be unique for each call on the same target.

Shader type

The type of shader is deduced from the file extension:

  • .vert — vertex shaders
  • .tesc — tessellation control shaders
  • .tese — tessellation evaluation shaders
  • .geom — geometry shaders
  • .frag — fragment (pixel) shaders
  • .comp — compute shaders

Note: Tessellation control and evaluation shaders are not currently supported with Direct 3D (HLSL). A possible workaround is to manually create hull and domain shaders and inject them via the file substitution syntax in FILES.

Target language options

  • GLSL — Requests GLSL source for the given comma-separated list of versions. For example, a compute shader typically needs "310 es,430" rather than the defaults. The space before the es suffix is optional.
  • NOGLSL — Disables GLSL source generation. Suitable for applications that do not target OpenGL at all.
  • HLSL — Requests HLSL source for the given list of Shader Model versions. qsb uses GLSL-style numbering: 50 is Shader Model 5.0, 51 is 5.1.
  • NOHLSL — Disables HLSL source generation. Suitable for applications that do not target Direct 3D at all.
  • MSL — Requests Metal Shading Language source for the given version. 12 corresponds to MSL 1.2, 20 to 2.0.
  • NOMSL — Disables MSL source generation. Suitable for applications that do not target Metal at all.

Example — raising the GLSL version for shaders that use OpenGL 3.x features:

qt_add_shaders(exampleapp "res_gl3shaders"
    GLSL "300es,330"
    PREFIX
        "/shaders"
    FILES
        shaders/ssao.vert
        shaders/ssao.frag
        shaders/skybox.vert
        shaders/skybox.frag
)

Note: The space before the es suffix is optional.

Qt Quick options

  • BATCHABLE — Required for vertex shaders used with Qt Quick, either in a ShaderEffect or a QSGMaterialShader. Has no effect on fragment or compute shaders; different shader types can safely be mixed in the same FILES list because the keyword is only applied to .vert files. Equivalent to the -b argument of qsb.
  • ZORDER_LOC — When BATCHABLE is specified, an extra vertex input is injected at location 7 by default. Use this keyword to change the location to avoid clashing with an existing input.

Tessellation options

  • TESSELLATION — Indicates that the shaders belong to a tessellation pipeline. Relevant only for vertex shaders when MSL generation is not disabled; enables special processing and translation for those shaders when targeting Metal.

    This option was introduced in Qt 6.5.

  • TESSELLATION_VERTEX_COUNT — Specifies the output vertex count from the tessellation control stage. Mandatory for tessellation evaluation shaders targeting Metal. The default is 3. If the value does not match the control stage, the generated MSL code will not function correctly.

    This option was introduced in Qt 6.5.

  • TESSELLATION_MODE — Specifies the tessellation mode: "triangles" (default) or "quads". Must be set when a tessellation control shader is listed in FILES, and must match the tessellation evaluation stage.

    This option was introduced in Qt 6.5.

Multiview options

  • VIEW_COUNT — Specifies the number of views for multiview rendering (GL_OVR_multiview2, VK_KHR_multiview, D3D12 view instancing, etc.). Set to a value of 2 or greater for the relevant vertex shaders to produce correct GLSL output. Setting VIEW_COUNT injects the QSHADER_VIEW_COUNT preprocessor define and, for values of 2 or greater, automatically adds #extension GL_EXT_multiview : require in vertex shaders. Minimum required language versions when using multiview: GLSL 330 and 300 es, HLSL 61. Avoid setting VIEW_COUNT on vertex shaders that do not use multiview; group them into separate qt_add_shaders() calls instead.

    This option was introduced in Qt 6.7.

  • MULTIVIEW — Generates both a non-multiview and a view-count-2 set of shaders. This is a convenience equivalent to two separate qt_add_shaders() calls with the appropriate GLSL/HLSL/MSL/VIEW_COUNT arguments. The implicit settings for the multiview variants are GLSL 330,300es, HLSL 61, MSL 21, and VIEW_COUNT 2. Multiview variants are stored with a .mv2qsb suffix appended to the .qsb filename.

    This option was introduced in Qt 6.8.

External tool options

  • PRECOMPILE — On Windows (when HLSL is not disabled), invokes fxc from the Windows SDK to compile HLSL source to DXBC bytecode at build time rather than at run time. The resulting .qsb file contains the compiled intermediate bytecode rather than the original HLSL source. Equivalent to the -c argument of qsb. Has no effect on non-Windows platforms.
  • OPTIMIZED — Invokes spirv-opt from the Vulkan SDK to perform optimizations on the SPIR-V bytecode. Equivalent to the -O argument of qsb.

Other options

  • BASE — A path prefix used to compute the alias (in-resource name) of the generated .qsb files. When BASE is set, each output path is made relative to BASE rather than kept as-is. This is analogous to the BASE argument of qt_add_resources.
  • DEFINES — Defines macros active during shader compilation, in the form "name1=value1;name2=value2". Alternatively, entries can be separated by newlines, just like FILES. Equivalent to the -D argument of qsb.
  • OUTPUTS — When the generated .qsb filename must differ from the source filename (for example, when one shader file serves as the source for multiple .qsb files differentiated by DEFINES), provide one output filename per entry in FILES. Each name is passed via the -o argument to qsb instead of appending .qsb to the source filename.
  • ORIGINAL_FILES — When the .qsb files should depend on shader source files different from those in FILES, supply one entry per FILES item here. When present, the corresponding ORIGINAL_FILES entry is written into the CMake dependency file via --orig-file and is added to the DEPENDS clause of the underlying add_custom_command(). This is useful when the files passed to qt_add_shaders() are intermediate generated assets and the final .qsb files should track the original source files.
  • PERTARGETCOMPILE — Compiles to SPIR-V and translates to each output language version separately, once per target language. This is slower than the default single-pass approach but allows conditional compilation via the QSHADER_<LANG>[_VERSION] preprocessor macros. Equivalent to the -p argument of qsb.
  • DEBUGINFO — Generates full debug information for SPIR-V, enabling tools such as RenderDoc to display the full source when inspecting a pipeline or performing vertex/fragment debugging. When PRECOMPILE is also set, instructs fxc to embed debug information in the generated DXBC bytecode. Equivalent to the -g argument of qsb.
  • QUIET — Suppresses debug and warning output from qsb. Only fatal errors are printed. Equivalent to the -s argument of qsb.
  • OUTPUT_TARGETS — When using qt_add_shaders with static libraries, one or more special targets are generated. Pass a variable name to retrieve those targets for further processing.
  • MEDIUMP — Requests medium-precision floats as the default in GLSL ES fragment shaders. Has no effect on other targets, including non-ES GLSL.

Substituting hand-crafted shaders

The FILES list supports a special syntax for replacing a specific shader variant in the .qsb package with a hand-crafted file. This is equivalent to the -r option of qsb:

FILES
    "shaders/externalsampler.frag@glsl,100es,shaders/externalsampler_gles.frag"

A filename may be followed by any number of @-separated replacement specifications. Each specifies the shading language, the version, and the file to read, separated by commas. @ characters within the filename or directory path are handled correctly and do not affect parsing. See the QSB Manual for details.

Examples

Basic usage

find_package(Qt6 COMPONENTS ShaderTools)

qt6_add_executable(exampleapp main.cpp)

qt6_add_shaders(exampleapp "exampleapp_shaders"
    PREFIX
        "/"
    FILES
        "wobble.frag"
)

This makes :/wobble.frag.qsb available at run time. The original wobble.frag source is not included in the executable.

Tessellation

A graphics pipeline with four stages — vertex (vertex.vert), tessellation control (tess.tesc), tessellation evaluation (tess.tese), and fragment (fragment.frag) — can be set up as follows.

The vertex and fragment shaders are compiled first. TESSELLATION enables special Metal translation for the vertex shader, and the GLSL version is raised because tessellation requires OpenGL 4.x or ES 3.2.

qt6_add_shaders(project "shaders_tessellation_part1"
    PREFIX
        "/shaders"
    GLSL
        "410,320es"
    TESSELLATION
    FILES
        "vertex.vert"
        "fragment.frag"
)

The tessellation shaders are listed in a separate call because NOHLSL is needed for them—HLSL tessellation shaders must be written manually and injected. The Metal tessellation parameters are specified explicitly.

qt6_add_shaders(project "shaders_tessellation_part2"
    PREFIX
        "/shaders"
    NOHLSL
    GLSL
        "410,320es"
    TESSELLATION_VERTEX_COUNT
        3
    TESSELLATION_MODE
        "triangles"
    FILES
        "tess.tesc@hlsl,50,tess_hull.hlsl"
        "tess.tese@hlsl,50,tess_domain.hlsl"
)

Note: Writing hull and domain HLSL shaders manually is recommended for advanced users only. Constructs such as constant buffers require special care to keep resource interfaces and layouts compatible with the SPIR-V/GLSL/MSL shaders.

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