Указание корневых подписей в HLSL
Указание корневых подписей в модели 5.1 шейдера HLSL является альтернативой их указанию в коде C++.
- Пример корневой подписи HLSL
- RootFlags
- Корневые константы
- Видимость
- корневого уровня CBV
- SRV корневого уровня
- корневого уровня беспилотный летательный аппарат
- Таблица дескриптора
- статический пробоотборник
- Компиляция корневой HLSL подписи
- управление корневыми сигнатурами с помощью компилятора FXC
- заметки
- Связанные темы
Пример корневой подписи HLSL
Корневую сигнатуру можно указать в HLSL в виде строки. Строка содержит коллекцию предложений с разделительной запятыми, описывающих компоненты, составляющие корневую подпись. Единая корневая сигнатура должна быть одинаковой для всех шейдеров в любом объекте состояния конвейера (PSO). Ниже приведен пример:
Корневая подпись версии 1.0
#define MyRS1 "RootFlags( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | " \
"DENY_VERTEX_SHADER_ROOT_ACCESS), " \
"CBV(b0, space = 1), " \
"SRV(t0), " \
"UAV(u0, visibility = SHADER_VISIBILITY_GEOMETRY), " \
"DescriptorTable( CBV(b0), " \
"UAV(u1, numDescriptors = 2), " \
"SRV(t1, numDescriptors = unbounded)), " \
"DescriptorTable(Sampler(s0, numDescriptors = 2)), " \
"RootConstants(num32BitConstants=1, b9), " \
"DescriptorTable( UAV(u3), " \
"UAV(u4), " \
"UAV(u5, offset=1)), " \
"StaticSampler(s2)," \
"StaticSampler(s3, " \
"addressU = TEXTURE_ADDRESS_CLAMP, " \
"filter = FILTER_MIN_MAG_MIP_LINEAR )"
Это определение даст следующую корневую сигнатуру, отметив:
- Использование параметров по умолчанию.
- b0 и (b0, space=1) не конфликтуют
- U0 отображается только в шейдере геометрии
- u4 и u5 связаны с одним и тем же дескриптором в куче
Корневая подпись версии 1.1
корневая подпись версии 1.1 позволяет оптимизировать драйверы на дескрипторах и данных корневой подписи.
#define MyRS1 "RootFlags( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | " \
"DENY_VERTEX_SHADER_ROOT_ACCESS), " \
"CBV(b0, space = 1, flags = DATA_STATIC), " \
"SRV(t0), " \
"UAV(u0), " \
"DescriptorTable( CBV(b1), " \
"SRV(t1, numDescriptors = 8, " \
" flags = DESCRIPTORS_VOLATILE), " \
"UAV(u1, numDescriptors = unbounded, " \
" flags = DESCRIPTORS_VOLATILE)), " \
"DescriptorTable(Sampler(s0, space=1, numDescriptors = 4)), " \
"RootConstants(num32BitConstants=3, b10), " \
"StaticSampler(s1)," \
"StaticSampler(s2, " \
"addressU = TEXTURE_ADDRESS_CLAMP, " \
"filter = FILTER_MIN_MAG_MIP_LINEAR )"
Язык корневой подписи HLSL тесно соответствует API корневой подписи C++ и имеет эквивалентную экспрессивную мощность. Корневая сигнатура указывается в виде последовательности предложений, разделенных запятыми. Порядок предложений важен, так как порядок синтаксического анализа определяет позицию слота в корневой сигнатуре. Каждое предложение принимает один или несколько именованных параметров. Однако порядок параметров не важен.
КорневыеФлаги
Необязательное предложение RootFlags принимает значение 0 (значение по умолчанию, указывающее отсутствие флагов), или одно или несколько предопределенных значений корневых флагов, подключенных через оператор OR '|'. Допустимые значения корневого флага определяются D3D12_ROOT_SIGNATURE_FLAGS.
Например:
RootFlags(0) // default value – no flags
RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT)
RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | DENY_VERTEX_SHADER_ROOT_ACCESS)
Корневые константы
Клаузула RootConstants указывает корневые константы в корневой сигнатуре. Два обязательных параметра: num32BitConstants и bReg (регистр, соответствующий BaseShaderRegister в API C++), находящиеся в cbuffer. Пространство (RegisterSpace в API C++) и видимость (ShaderVisibility в C++) являются необязательными параметрами, а значения по умолчанию следующие:
RootConstants(num32BitConstants=N, bReg [, space=0,
visibility=SHADER_VISIBILITY_ALL ])
Например:
RootConstants(num32BitConstants=3, b3)
Видимость
Видимость — это необязательный параметр, который может иметь одно из значений из D3D12_SHADER_VISIBILITY.
SHADER_VISIBILITY_ALL передает корневые аргументы всем шейдерам. На некоторых оборудовании это бесплатно, но на другом оборудовании существует плата за разделение данных на все стадии шейдера. Установка одного из параметров, например SHADER_VISIBILITY_VERTEX, ограничивает корневой аргумент одним этапом шейдера.
Установка корневых аргументов на один этап шейдера позволяет использовать одно и то же имя привязки на разных этапах. Например, допустима привязка SRV t0,SHADER_VISIBILITY_VERTEX
и привязка SRV t0,SHADER_VISIBILITY_PIXEL
. Но если параметр видимости был t0,SHADER_VISIBILITY_ALL
для одной из привязок, корневая подпись будет недопустимой.
CBV корневого уровня
Предложение CBV
(представление буфера констант) указывает на запись буфера констант корневого уровня в b-register Reg. Обратите внимание, что это скалярная запись; Невозможно указать диапазон для корневого уровня.
CBV(bReg [, space=0, visibility=SHADER_VISIBILITY_ALL ]) // Version 1.0
CBV(bReg [, space=0, visibility=SHADER_VISIBILITY_ALL, // Version 1.1
flags=DATA_STATIC_WHILE_SET_AT_EXECUTE ])
SRV корневого уровня
Предложение SRV
(представление ресурсов шейдера) указывает запись SRV t-register Reg на корневом уровне. Обратите внимание, что это скалярная запись; Невозможно указать диапазон для корневого уровня.
SRV(tReg [, space=0, visibility=SHADER_VISIBILITY_ALL ]) // Version 1.0
SRV(tReg [, space=0, visibility=SHADER_VISIBILITY_ALL, // Version 1.1
flags=DATA_STATIC_WHILE_SET_AT_EXECUTE ])
UAV корневого уровня
Предложение UAV
(неупорядоченное представление доступа) указывает запись u-register Reg на уровне корневого уровня. Обратите внимание, что это скалярная запись; Невозможно указать диапазон для корневого уровня.
UAV(uReg [, space=0, visibility=SHADER_VISIBILITY_ALL ]) // Version 1.0
UAV(uReg [, space=0, visibility=SHADER_VISIBILITY_ALL, // Version 1.1
flags=DATA_VOLATILE ])
Например:
UAV(u3)
Таблица дескриптора
Предложение DescriptorTable
— это список предложений таблиц дескриптора с разделителями-запятыми, а также необязательный параметр видимости. Элементы DescriptorTable включают CBV, SRV, UAV и Sampler. Обратите внимание, что их параметры отличаются от параметров предложений корневого уровня.
DescriptorTable( DTClause1, [ DTClause2, … DTClauseN,
visibility=SHADER_VISIBILITY_ALL ] )
Таблица дескриптора CBV
имеет следующий синтаксис:
CBV(bReg [, numDescriptors=1, space=0, offset=DESCRIPTOR_RANGE_OFFSET_APPEND ]) // Version 1.0
CBV(bReg [, numDescriptors=1, space=0, offset=DESCRIPTOR_RANGE_OFFSET_APPEND // Version 1.1
, flags=DATA_STATIC_WHILE_SET_AT_EXECUTE ])
Например:
DescriptorTable(CBV(b0),SRV(t3, numDescriptors=unbounded))
Обязательный параметр bReg указывает начальный регистр диапазона cbuffer. Параметр numDescriptors указывает количество дескрипторов в непрерывном диапазоне cbuffer; Значение по умолчанию равно 1. Запись объявляет диапазон cbuffer [Reg, Reg + numDescriptors - 1]
, когда имеет значение. Если numDescriptors равно "неограниченный", диапазон равен [Reg, UINT_MAX]
, что означает, что приложение должно убедиться, что оно не ссылается на область вне границ. Поле смещение соответствует параметру OffsetInDescriptorsFromTableStart в API C++, то есть смещению (в дескрипторах) от начала таблицы. Если для смещения задано значение DESCRIPTOR_RANGE_OFFSET_APPEND (по умолчанию), это означает, что диапазон находится непосредственно после предыдущего диапазона. Однако при вводе конкретных смещений диапазоны могут пересекаться друг с другом, что позволяет псевдонимизировать регистры.
Таблица дескриптора SRV
имеет следующий синтаксис:
SRV(tReg [, numDescriptors=1, space=0, offset=DESCRIPTOR_RANGE_OFFSET_APPEND ]) // Version 1.0
SRV(tReg [, numDescriptors=1, space=0, offset=DESCRIPTOR_RANGE_OFFSET_APPEND, // Version 1.1
flags=DATA_STATIC_WHILE_SET_AT_EXECUTE ])
Это похоже на запись в таблице дескрипторов CBV
, за исключением того, что указанный диапазон относится к представлениям ресурсов шейдера.
Таблица дескриптора UAV
имеет следующий синтаксис:
UAV(uReg [, numDescriptors=1, space=0, offset=DESCRIPTOR_RANGE_OFFSET_APPEND ]) // Version 1.0
UAV(uReg [, numDescriptors=1, space=0, offset=DESCRIPTOR_RANGE_OFFSET_APPEND, // Version 1.1
flags=DATA_VOLATILE ])
Это похоже на запись таблицы дескрипторов CBV
, за исключением того, что указанный диапазон предназначен для неупорядоченного доступа.
Таблица дескриптора Sampler
имеет следующий синтаксис:
Sampler(sReg [, numDescriptors=1, space=0, offset=DESCRIPTOR_RANGE_OFFSET_APPEND ]) // Version 1.0
Sampler(sReg [, numDescriptors=1, space=0, offset=DESCRIPTOR_RANGE_OFFSET_APPEND, // Version 1.1
flags=0 ])
Это похоже на запись в таблице дескрипторов CBV
, за исключением того, что указанный диапазон предназначен для шейдерных семплеров. Обратите внимание, что сэмплеры не могут использоваться вместе с другими типами дескрипторов в одной и той же таблице дескрипторов, так как они находятся в отдельной куче дескрипторов.
Статический сэмплер
Статический образец представляет структуру D3D12_STATIC_SAMPLER_DESC. Обязательный параметр для StaticSampler — скаляр, сэмплер s-register Reg. Другие параметры необязательны и имеют значения по умолчанию, указанные ниже. Большинство полей принимают набор предопределенных перечислений.
StaticSampler( sReg,
[ filter = FILTER_ANISOTROPIC,
addressU = TEXTURE_ADDRESS_WRAP,
addressV = TEXTURE_ADDRESS_WRAP,
addressW = TEXTURE_ADDRESS_WRAP,
mipLODBias = 0.f,
maxAnisotropy = 16,
comparisonFunc = COMPARISON_LESS_EQUAL,
borderColor = STATIC_BORDER_COLOR_OPAQUE_WHITE,
minLOD = 0.f,
maxLOD = 3.402823466e+38f,
space = 0,
visibility = SHADER_VISIBILITY_ALL ])
Например:
StaticSampler(s4, filter=FILTER_MIN_MAG_MIP_LINEAR)
Варианты параметров очень похожи на вызовы API C++, за исключением borderColor, который ограничен значением из перечисления в HLSL.
Поле фильтра может быть одним из D3D12_FILTER.
Каждое из полей адреса может быть одним из D3D12_TEXTURE_ADDRESS_MODE.
Функция сравнения может быть одной из D3D12_COMPARISON_FUNC.
Поле цвета границы может быть одним из D3D12_STATIC_BORDER_COLOR.
Видимость может быть одной из D3D12_SHADER_VISIBILITY.
Компиляция корневой подписи HLSL
Существует два механизма компиляции корневой подписи HLSL. Во-первых, можно подключить строку корневой подписи к определенному шейдеру через атрибут RootSignature (в следующем примере с помощью точки входа MyRS1):
[RootSignature(MyRS1)]
float4 main(float4 coord : COORD) : SV_Target
{
…
}
Компилятор создаст и проверит корневой blob-объект сигнатуры для шейдера и встроит его вместе с байт-кодом шейдера в blob-объект шейдера. Компилятор поддерживает синтаксис корневой подписи для модели шейдера 5.0 и выше. Если корневая сигнатура внедрена в модель шейдера 5.0 и что шейдер отправляется в среду выполнения D3D11, в отличие от D3D12, корневая часть подписи будет автоматически игнорироваться D3D11.
Другой механизм — создать автономный корневой blob-объект сигнатуры, возможно, повторно использовать его с большим набором шейдеров, экономя место. Средство Effect-Compiler (FXC) поддерживает модели rootsig_1_0 иrootsig_1_1 шейдеров. Имя строки определения указывается с помощью обычного аргумента /E. Например:
fxc.exe /T rootsig_1_1 MyRS1.hlsl /E MyRS1 /Fo MyRS1.fxo
Обратите внимание, что строка корневой подписи также может быть передана в командной строке, например /D MyRS1="...".
Управление корневыми сигнатурами с помощью компилятора FXC
Компилятор FXC создает байт-код шейдера из исходных файлов HLSL. Для этого компилятора существует множество необязательных параметров, обратитесь к Effect-Compiler инструменту.
Для управления корневыми сигнатурами HLSL в следующей таблице приведены примеры использования FXC.
Линия | Командная строка | Описание |
---|---|---|
1 | fxc /T ps_5_1 shaderWithRootSig.hlsl /Fo rs1.fxo |
Компилирует шейдер для целевого объекта пиксельного шейдера 5.1, источник шейдера находится в файле shaderWithRootSig.hlsl, включающем корневую подпись. Шейдер и корневая сигнатура компилируются как отдельные блобы в двоичном файле rs1.fxo. |
2 | fxc /dumpbin rs1.fxo /extractrootsignature /Fo rs1.rs.fxo |
Извлекает корневую подпись из файла, созданного строкой 1, поэтому файл rs1.rs.fxo содержит только корневую подпись. |
3 | fxc /dumpbin rs1.fxo /Qstrip_rootsignature /Fo rs1.stripped.fxo |
Удаляет корневую подпись из файла, созданного строкой 1, поэтому файл rs1.stripped.fxo содержит шейдер без корневой подписи. |
4 | fxc /dumpbin rs1.stripped.fxo /setrootsignature rs1.rs.fxo /Fo rs1.new.fxo |
Объединяет шейдер и корневую сигнатуру, которые находятся в отдельных файлах, в один двоичный файл, содержащий оба блоба. В этом примере rs1.new.fx0 будет идентично rs1.fx0 в строке 1. |
5 | fxc /T rootsig_1_0 rootSigAndMaybeShaderInHereToo.hlsl /E RS1 /Fo rs2.fxo |
Создает автономный двоичный файл сигнатуры корневой подписи из источника, который может содержать больше, чем только корневую подпись. Обратите внимание на целевой объект rootsig_1_0, а RS1 — имя строки макроса корневой подписи (#define) в файле HLSL. |
Функции, доступные через FXC, также доступны программным способом с помощью функции D3DCompile. Этот вызов компилирует шейдер с корневой сигнатурой или автономной корневой сигнатурой (устанавливая цель rootsig_1_0). D3DGetBlobPart и D3DSetBlobPart могут извлекать и присоединять корневые подписи к существующему BLOB-объекту. D3D_BLOB_ROOT_SIGNATURE используется для указания типа части BLOB-объекта корневой подписи. D3DStripShader удаляет корневую подпись (с помощью флага D3DCOMPILER_STRIP_ROOT_SIGNATURE) из блоба.
Примечания
Заметка
В то время как автономная компиляция шейдеров настоятельно рекомендуется, если шейдеры должны быть скомпилированы во время выполнения, обратитесь к замечаниям для D3DCompile2.
Заметка
Существующие ресурсы HLSL не нужно изменять, чтобы использовать их с корневыми сигнатурами.
Связанные разделы