Поделиться через


Указание корневых подписей в HLSL

Указание корневых подписей в модели 5.1 шейдера HLSL является альтернативой их указанию в коде C++.

Пример корневой подписи 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 не нужно изменять, чтобы использовать их с корневыми сигнатурами.

 

динамическое индексирование с помощью HLSL 5.1

Функции шейдерной модели HLSL 5.1 для Direct3D 12

привязка ресурсов

привязка ресурсов в HLSL

Корневые подписи

модель шейдера 5.1

Значение ссылки на трафарет, указанное в шейдере

Загрузка типизированного неупорядоченного представления доступа