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


Определение корневых подписей в HLSL

Указание корневых подписей в модели шейдеров HLSL 5.1 является альтернативой их указанию в коде 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, пробел=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

Необязательное предложение 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. Параметры space (RegisterSpace в API C++) и visibility (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 привязка t0,SHADER_VISIBILITY_PIXEL SRV для . Но если для одной из привязок задан t0,SHADER_VISIBILITY_ALL параметр видимости, корневая подпись будет недопустимой.

CbV корневого уровня

Предложение CBV (представление буфера констант) указывает запись reg буфера констант корневого уровня b-register. Обратите внимание, что это скалярная запись; Невозможно указать диапазон для корневого уровня.

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 (представление ресурсов шейдера) указывает запись reg t-register корневого уровня SRV. Обратите внимание, что это скалярная запись; Невозможно указать диапазон для корневого уровня.

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 (представление неупорядоченного доступа) указывает запись регистра UAV корневого уровня. Обратите внимание, что это скалярная запись; Невозможно указать диапазон для корневого уровня.

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 указывает начальный reg диапазона cbuffer. Параметр numDescriptors указывает количество дескрипторов в непрерывном диапазоне cbuffer; значение по умолчанию — 1. Запись объявляет диапазон [Reg, Reg + numDescriptors - 1] cbuffer, если numDescriptors является числом. Если аргументы 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. Другие параметры являются необязательными со значениями по умолчанию, показанными ниже. Большинство полей принимают набор предопределенных перечислений.

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
{
…
}

Компилятор создаст и проверит большой двоичный объект корневой сигнатуры для шейдера и внедряет его вместе с кодом байтов шейдера в большой двоичный объект шейдера. Компилятор поддерживает синтаксис корневой сигнатуры для модели шейдера 5.0 и более поздних версий. Если корневая сигнатура внедрена в шейдер модели 5.0 и этот шейдер отправляется в среду выполнения D3D11, в отличие от D3D12, часть корневой сигнатуры будет автоматически игнорироваться D3D11.

Другой механизм заключается в создании автономного большого двоичного объекта корневой сигнатуры, возможно, для повторного использования его с большим набором шейдеров, экономя место. Средство компилятора эффектов (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 Tool.

Для управления корневыми подписями, созданными HLSL, в следующей таблице приведены некоторые примеры использования FXC.

График Командная строка Описание
1 fxc /T ps_5_1 shaderWithRootSig.hlsl /Fo rs1.fxo Компилирует шейдер для целевого объекта шейдера пикселей 5.1, источник шейдера находится в файле shaderWithRootSig.hlsl, который содержит корневую сигнатуру. Шейдер и корневая сигнатура компилируются в виде отдельных BLOB-объектов в двоичном файле 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 Объединяет шейдер и корневую сигнатуру, которые находятся в отдельных файлах, в двоичный файл, содержащий оба BLOB-объекта. В этом примере 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 могут извлекать и присоединять корневые подписи к существующему большому двоичному объекту.  D3D_BLOB_ROOT_SIGNATURE используется для указания типа части большого двоичного объекта корневой сигнатуры. D3DStripShader удаляет корневую сигнатуру (с помощью флага D3DCOMPILER_STRIP_ROOT_SIGNATURE) из большого двоичного объекта.

Примечания

Примечание

В то время как автономная компиляция шейдеров настоятельно рекомендуется, если шейдеры должны компилироваться во время выполнения, обратитесь к замечаниям для D3DCompile2.

 

Примечание

Существующие ресурсы HLSL не нужно изменять для обработки корневых сигнатур для использования с ними.

 

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

Возможности шейдера HLSL Model 5.1 для Direct3D 12

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

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

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

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

Контрольное значение трафарета в шейдере

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