Справочник 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.0.0)
Options:
-?, -h, --help Displays help on commandline options.
--help-all Displays help including Qt specific 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.
-g Generate full debug info for SPIR-V and DXBC
-O Invoke spirv-opt to optimize SPIR-V for
performance
-o, --output <filename> Output file for the shader pack.
-c, --fxc In combination with --hlsl invokes fxc to store
DXBC instead of HLSL.
-t, --metallib In combination with --msl builds a Metal library
with xcrun metal(lib) and stores that instead of
the source.
-D, --define <name[=value]> Define macro
-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>|...
Arguments:
file Vulkan GLSL source file to compile Режимы работы
Существует три основных режима работы:
-
.qsbгенерация файлов. -
.qsbпроверка файлов. Например,qsb -d myshader.frag.qsbвыведет метаданные рефлексии (в формате JSON) и включённые шейдеры. - Режим извлечения. Это позволяет записать заданный шейдер из существующего файла
.qsbв отдельный файл. Например,qsb -x spirv.100 -o myshader.spv myshader.frag.qsbзаписывает двоичный код SPIR-V вmyshader.spv.
Пример
Рассмотрим следующий фрагмент шейдера:
#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: (unordered list)
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: (unordered list)
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 со всеми поддерживаемыми графическими API: Vulkan, Direct 3D, Metal, OpenGL и OpenGL ES. В момент выполнения соответствующий шейдер автоматически выбирается Qt Rendering Hardware Interface, расположенным под Qt Quick и Qt Quick 3D.
Помимо перевода байткода SPIR-V обратно в исходный код высокого уровня, система обрабатывает дополнительные проблемы, например, гарантирует правильное отображение номеров связей SPIR-V на родные ресурсы. Например, с HLSL мы видели такой раздел выше:
Native resource binding map: 0 -> [0, -1] 1 -> [0, 0]
Внутренне это позволяет сопоставить точку привязки в стиле SPIR-V 0 с регистром HLSL b0 и привязку 1 к t0 и s0. Это помогает сделать различия в привязке ресурсов между различными языками шейдинга прозрачными для пользователей Rendering Hardware Interface и позволяет всему в Qt работать с точками привязки в стиле Vulkan/SPIR-V, как они указаны в исходном коде GLSL в стиле Vulkan.
Типы шейдеров
Тип шейдера определяется по расширению входного файла. Таким образом, расширение должно быть одним из следующих:
-
.vert- для вершинных шейдеров -
.frag- для фрагментных (пиксельных) шейдеров -
.comp- для шейдеров вычислений
Языки и версии шейдинга
Всегда генерируется SPIR-V 1.0. Что ещё генерируется, зависит от аргументов командной строки --glsl, --hlsl, и --msl.
Все эти параметры следуют за перечислением, разделённым запятыми. Список должен включать номера версий в стиле GLSL с необязательным суффиксом (es, обозначающим GLSL ES). Пробел между суффиксом и версией необязателен (отсутствие пробела может помочь избежать необходимости в кавычках).
Например, встроенные материалы Qt Quick (шейдеры, лежащие в основе элементов, таких как Image, Text, Rectangle) готовят свои шейдеры с --glsl "100 es,120,150" --hlsl 50 --msl 12. Это делает их совместимыми с OpenGL ES 2.0 и выше, OpenGL 2.1 и выше, и контекстами OpenGL core profile версии 3.2 и выше.
Если шейдер использует функции или конструкции, у которых нет эквивалента в указанных целях, qsb завершится ошибкой. В таком случае потребуется корректировка целевых платформ, что также означает неявную корректировку минимальных системных требований приложения. К примеру, рассмотрите функцию GLSL textureLod доступную только с OpenGL ES 3.0 и выше (что означает GLSL ES 300 или выше). При запросе GLSL 300 es вместо 100 es, qsb выполнится успешно, но приложение, использующее этот файл .qsb будет теперь требовать OpenGL ES 3.0 или выше и не будет совместимо с системами OpenGL ES 2.0.
Ещё один очевидный пример — шейдеры вычислений: шейдеры .comp должны указывать --glsl 310es,430, так как шейдеры вычислений доступны только с OpenGL ES 3.1 или новее и OpenGL 4.3 или новее.
Настройка версии модели шейдера для HLSL или версии языка шейдинга Metal, как правило, требуется редко. Достаточно будет Shader Model 5.0 (--hlsl 50) и MSL 1.2 (--msl 12).
Оптимизация отрисовки сцены Qt Quick
Рендеринг Qt Quick Scene Graph поддерживает пакетную обработку геометрии для уменьшения количества вызовов отрисовки. Подробности см. на страницах Scene Graph. Это основано на вставке кода в функцию main() вершинного шейдера. В Qt 5.x это происходило во время выполнения путём модификации предоставленного кода вершинного шейдера GLSL. В Qt 6 это не вариант. Вместо этого, пакетные варианты вершинных шейдеров могут быть построены инструментом qsb. Это запрашивается аргументом -b. Когда вход не является вершинным шейдером с расширением .vert, он не оказывает влияния. Однако для вершинных шейдеров это приведёт к генерации версий для каждой цели. Qt Quick автоматически выберет правильный вариант (стандартный или пакетный) во время выполнения.
Примечание: Приложениям не нужно беспокоиться о деталях пакетной обработки. Достаточно просто убедиться, что -b (или эквивалентный BATCHABLE ключ, если используется интеграция CMake CMake) указан при обработке вершинных шейдеров. Это актуально только для шейдеров Qt Quick, используемых с ShaderEffect или QSGMaterialShader.
Рассмотрим следующий пример вершинного шейдера:
#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;
out gl_PerVertex { vec4 gl_Position; };
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: (unordered list)
Shader 0: GLSL 330 [Standard]
Shader 1: GLSL 330 [Batchable]
Shader 2: SPIR-V 100 [Standard]
Shader 3: SPIR-V 100 [Batchable]
Reflection info: {
... Обратите внимание, как все языки и версии целей теперь существуют в двух вариантах: Стандартный и слегка изменённый Пакетный.
Вызов внешних инструментов
qsb может вызывать определённые внешние инструменты. Они делятся на две категории: инструменты для оптимизации байткода шейдеров (SPIR-V) и платформо-специфические инструменты для выполнения первой фазы компиляции шейдеров из исходного кода в какой-либо промежуточный байткод-формат.
Они активируются следующими опциями командной строки:
-
-O- вызываетspirv-optв качестве послеобработки двоичного файла SPIR-V. Файл.qsbбудет содержать оптимизированную версию. Предполагается, чтоspirv-optдоступен в системе (например, из Vulkan SDK) и готов к вызову. -
-cили--fxc- вызываетfxc.exe, компилятор шейдеров Direct 3D. Полученные данныеDXBC(DirectX Byte Code) хранятся в файле.qsbвместо HLSL. Qt автоматически подберёт его во время выполнения, поэтому создателю файла.qsbрешать, что включать: исходный код HLSL или промежуточный формат. Всякий раз, когда это возможно, предпочтительнее использовать последний, так как он исключает необходимость парсинга и исходного кода HLSL во время выполнения, что может значительно ускорить создание графического конвейера. Недостаток заключается в том, что этот аргумент может быть использован только при выполненииqsbна Windows. -
-tили--metallib- вызывает соответствующие инструменты XCode Metal для генерации файла .metallib и включает его в пакет.qsbвместо исходного кода MSL. Эта опция доступна только при запускеqsbна macOS.
Другие опции
-
-D- определяет макрос. Это позволяет использовать #ifdef и аналогичные конструкции в исходном коде GLSL. -
-g- включает генерацию полной отладочной информации для SPIR-V, что позволяет инструментам, таким как RenderDoc, отображать полный исходный код при проверке конвейера или при отладке вершинного или фрагментного шейдера. Также оказывает влияние на Direct 3D, когда указан-c, посколькуfxcполучает указание включать отладочную информацию в сгенерированный промежуточный байткод.
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-6.1/qtshadertools-qsb.html