Константы шейдера (HLSL)

В Shader Model 4 константы шейдеров хранятся в одном или нескольких буферных ресурсах в памяти. Они могут быть организованы в два типа буферов: постоянные буферы (cbuffer) и буферы текстур (tbuffer). Буферы констант оптимизированы для использования переменных с постоянными переменными, которые характеризуются доступом к меньшим задержкам и чаще обновляются из ЦП. По этой причине к этим ресурсам применяются дополнительные ограничения на размер, макет и доступ. Доступ к текстурным буферам осуществляется как к текстурам, что обеспечивает лучшую производительность при произвольном индексировании данных. Независимо от того, какой тип ресурса вы используете, не существует ограничения на количество буферов констант или буферов текстуры, которые может создать приложение.

Объявление буфера константы или буфера текстуры во многом похоже на объявление структуры в языке C с добавлением ключевых слов Register и паккоффсет для назначения регистров или данных упаковки вручную.

Буффертипе [ Имя ] [: Register(b # ) ] { вариабледекларатион [ : паккоффсет(c # . ксизв) ] ; ... };

Параметры

буффертипе

[в ] буфере типа.

буффертипе Описание
кбуффер буфер констант
тбуффер буфер текстуры

Безымян

[в ] необязательной строке ASCII, содержащей уникальное имя буфера.

Регистрация(b # )

[]ключевое слово Optional используется для упаковки постоянных данных вручную. Константы можно упаковывать в регистр только в буфере констант, где начальная регистр задается номером регистра ( # ).

вариабледекларатион

[в ] объявлении переменной аналогично объявлению члена структуры. Это может быть любой тип HLSL или объект Effect (за исключением текстуры или объекта образца).

паккоффсет(c # . ксизв)

[]ключевое слово Optional используется для упаковки постоянных данных вручную. Константы можно упаковывать в любой буфер констант, где номер регистра предоставляется ( # ). Упаковка вложенных компонентов (с помощью ксизв группирующие) доступна для констант, размер которых умещается в пределах одного регистра (не пересекают границу регистра). Например, float4 не может быть упакован в один регистр, начиная с компонента y, так как он не умещается в регистре из четырех компонентов.

Комментарии

Буферы констант уменьшают пропускную способность, необходимую для обновления констант шейдера, позволяя сгруппировать и обработать их одновременно, без отдельных вызовов для обработки каждой константы.

Постоянный буфер — это специализированный буферный ресурс, доступ к которому осуществляется как к буферу. Каждый буфер константы может содержать до 4096 векторов; Каждый вектор содержит до 4 32-битных значений. Можно выполнить привязку до 14 буферов констант на стадию конвейера (2 дополнительных слотов зарезервированы для внутреннего использования).

Буфер текстуры — это специализированный буферный ресурс, доступ к которому осуществляется как к текстуре. Доступ к текстуре (по сравнению с доступом к буферу) может повысить производительность для произвольно индексированных данных. Для каждого этапа конвейера можно привязать до 128 буферов текстуры.

Ресурс буфера предназначен для снижения издержек на установку констант шейдера. Платформа эффектов (см. интерфейс ID3D10Effect) будет управлять обновлением буферов констант и текстур, а также использовать API Direct3D для обновления буферов (см. Дополнительные сведения о копировании и доступе к данным ресурсов (Direct3D 10) ). Приложение также может копировать данные из другого буфера (например, целевого объекта прорисовки или целевого объекта вывода потока) в буфер констант.

Дополнительные сведения об использовании буферов констант в приложении D3D10 см. в разделе типы ресурсов (Direct3D 10) и Создание ресурсов буфера (Direct3D 10).

Сведения о том, как использовать буферы констант в приложении D3D11, см. в статьях Введение в буферы в Direct3D 11 и инструкции: Создание буфера констант.

Для буфера констант не требуется, чтобы представление было привязано к конвейеру. Буфер текстуры, однако, требует представления и должен быть привязан к слоту текстуры (или должен быть связан с сеттекстуребуффер при использовании этого действия).

Существует два способа упаковки данных с константами: с помощью ключевых слов Register (DirectX HLSL) и ПАККОФФСЕТ (DirectX HLSL) .

Различия между Direct3D 9 и Direct3D 10 и 11:

  • В отличие от автоматического выделения констант в Direct3D 9, которые не выполняли упаковку и назначают каждую переменную набору регистров float4, переменные константы HLSL следуют правилам упаковки в Direct3D 10 и 11.

Организация постоянных буферов

Буферы констант уменьшают пропускную способность, необходимую для обновления констант шейдера, позволяя сгруппировать и обработать их одновременно, без отдельных вызовов для обработки каждой константы.

Лучшим способом эффективного использования буферов констант является упорядочение переменных шейдера в буферах констант согласно частоте их обновления. Это позволяет приложению максимально снизить пропускную способность, необходимую для обновления констант шейдера. Например, шейдер может объявлять два буфера констант и упорядочивать данные по частоте обновления: данные, которые необходимо обновить для каждого объекта (например, матрица мира), группируются в буфер констант, который может быть обновлен для каждого объекта. Это отдельно от данных, которые характеризуют сцену и, следовательно, часто обновляются гораздо реже (при изменении сцены).

cbuffer myObject
{       
    float4x4 matWorld;
    float3   vObjectPosition;
    int      arrayIndex;
}
 
cbuffer myScene
{
    float3   vSunPosition;
    float4x4 matView;
}
        

Буферы констант по умолчанию

Доступны два буфера констант по умолчанию: $Global и $Param. Переменные, помещаемые в глобальную область, добавляются неявно в $Global кбуффер с использованием того же метода упаковки, который используется для cbuffer. Универсальные параметры в списке параметров функции отображаются в буфере констант $Param, когда шейдер компилируется за пределами платформы Effects. При компиляции внутри платформы Effects все универсальные значения должны разрешаться в переменные, определенные в глобальной области.

Примеры

Ниже приведен пример из примера Skinning10 , который представляет собой буфер текстуры, состоящие из массива матриц.

tbuffer tbAnimMatrices
{
    matrix g_mTexBoneWorld[MAX_BONE_MATRICES];
};
      

В этом примере объявление вручную назначает буфер константы для запуска с определенным регистром, а также упаковывает определенные элементы по подкомпонентам.

cbuffer MyBuffer : register(b3)
{
    float4 Element1 : packoffset(c0);
    float1 Element2 : packoffset(c1);
    float1 Element3 : packoffset(c1.y);
}
      

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