Синтаксис переменных

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

[Storage_Class] [Type_Modifier] Type Name[Index] [: Semantic] [: Packoffset] [: Register]; [Заметки] [= Initial_Value]

Параметры

Storage_Class

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

Значение Описание
extern Пометить глобальную переменную как внешние входные данные для шейдера; Это метка по умолчанию для всех глобальных переменных. Не может сочетаться со статическим.
nointerpolation Не интерполяйте выходные данные вершинного шейдера перед их передачей в пиксельный шейдер.
Точное Точный ключевое слово при применении к переменной ограничивает любые вычисления, используемые для получения значения, присвоенного этой переменной, следующими способами:
  • Отдельные операции хранятся отдельно. Например, если операция mul и add могла быть слита в безумную операцию, точное заставляет операции оставаться отдельными. Вместо этого необходимо явно использовать встроенную функцию mad.
  • Порядок операций поддерживается. Если порядок инструкций мог быть перемешан для повышения производительности, точно гарантирует, что компилятор сохранит порядок записи.
  • Небезопасные операции IEEE ограничены. Если компилятор мог использовать быстрые математические операции, которые не учитывают значения NaN (не число) и INF (бесконечные), то требования IEEE, касающиеся значений NaN и INF, должны соблюдаться. Без точности эти оптимизации и математические операции не являются безопасными ieee.
  • Определение точной переменной не приводит к операциям, которые используют переменную precise. Так как точность распространяется только на операции, которые влияют на значения, присвоенные переменной с точным определением, правильное определение точных вычислений может быть сложной задачей, поэтому рекомендуется пометить выходные данные шейдера точно в том месте, где они объявляются, будь то поле структуры, выходной параметр или тип возвращаемого значения функции входа. Возможность управлять оптимизацией таким образом поддерживает инвариантность результатов для измененной выходной переменной, отключая оптимизации, которые могут повлиять на конечные результаты из-за различий в накопленных различиях точности. Это полезно, если требуется, чтобы шейдеры для тесселяции поддерживали водонепроницаемые патч-швы или соответствовали значениям глубины в течение нескольких проходов. Пример кода:
    g_mWorldViewProjection HLSLmatrix;
    void main(in float3 InPos : Position, out precise float4 OutPos : SV_Position)
    {
    операция является точной, так как она вносит свой вклад в точный параметр OutPos
    OutPos = mul( float4( InPos, 1.0 ), g_mWorldViewProjection );
    }
Общий Пометка переменной для совместного использования между эффектами; это указание для компилятора.
groupshared Пометка переменной для общей памяти группы потоков для вычислительных шейдеров. В D3D10 максимальный общий размер всех переменных с классом хранения groupshared составляет 16 КБ, а в D3D11 — 32 КБ. См. примеры.
static Пометьте локальную переменную так, чтобы она инициализировалась один раз и сохранялась между вызовами функций. Если объявление не включает инициализатор, значение устанавливается равным нулю. Глобальная переменная, помеченная как static , не видна приложению.
Однородный элемент Пометить переменную, данные которой являются постоянными на протяжении всего выполнения шейдера (например, цвет материала в вершинном шейдере); По умолчанию глобальные переменные считаются однородными .
volatile Пометьте переменную, которая часто меняется; это указание для компилятора. Этот модификатор класса хранения применяется только к локальной переменной.
Примечание: В настоящее время компилятор HLSL игнорирует этот модификатор класса хранения.

Type_Modifier

Необязательный модификатор типа переменной.

Значение Описание
const Пометьте переменную, которая не может быть изменена шейдером, поэтому ее необходимо инициализировать в объявлении переменной. Глобальные переменные считаются const по умолчанию (подавляйте это поведение, предоставляя компилятору флаг /Gec).
row_major Пометьте переменную, которая хранит четыре компонента в одной строке, чтобы их можно было хранить в одном регистре констант.
column_major Пометьте переменную, которая хранит 4 компонента в одном столбце, чтобы оптимизировать матричную математику.

Примечание

Если значение модификатора типа не указано, компилятор использует column_major в качестве значения по умолчанию.

Тип

Любой тип HLSL, указанный в разделе Типы данных (DirectX HLSL).

Имя[Индекс]

Строка ASCII, однозначно идентифицирующая переменную шейдера. Чтобы определить необязательный массив, используйте индекс для размера массива, который является положительным целым числом = 1.

Семантические

Необязательные сведения об использовании параметров, используемые компилятором для связывания входных и выходных данных шейдера. Существует несколько предопределенных семантик для вершинных и пиксельных шейдеров. Компилятор игнорирует семантику, если они не объявлены в глобальной переменной или параметре, переданном в шейдер.

Packoffset

Необязательный ключевое слово для упаковки констант шейдера вручную. См. раздел packoffset (DirectX HLSL).

Зарегистрировать

Необязательный ключевое слово для ручного назначения переменной шейдера определенному регистру. См. раздел Register (DirectX HLSL).

Заметки

Необязательные метаданные в виде строки, присоединенные к глобальной переменной. Заметка используется платформой эффектов и игнорируется HLSL; Дополнительные сведения о синтаксисе см. в статье Синтаксис заметки.

Initial_Value

Необязательные начальные значения; Число значений должно совпадать с количеством компонентов в типе. Каждая глобальная переменная, помеченная extern , должна быть инициализирована литеральным значением; Каждая переменная, помеченная как static , должна быть инициализирована константой.

Глобальные переменные, которые не помечены как static или extern , не компилируются в шейдер. Компилятор не устанавливает автоматически значения по умолчанию для глобальных переменных и не может использовать их в оптимизации. Чтобы инициализировать этот тип глобальной переменной, используйте отражение, чтобы получить ее значение, а затем скопируйте значение в буфер констант. Например, можно использовать метод ID3D11ShaderReflection::GetVariableByName для получения переменной, метод ID3D11ShaderReflectionVariable::GetDesc для получения описания переменной шейдера и получить начальное значение из элемента DefaultValueструктуры D3D11_SHADER_VARIABLE_DESC . Чтобы скопировать значение в буфер констант, необходимо убедиться, что буфер был создан с доступом на запись ЦП (D3D11_CPU_ACCESS_WRITE). Дополнительные сведения о создании буфера констант см. в разделе Практическое руководство. Создание буфера констант.

Вы также можете использовать платформу эффектов для автоматической обработки отражения и установки начального значения. Например, можно использовать метод ID3DX11EffectPass::Apply .

Примеры

Ниже приведено несколько примеров объявлений переменных шейдера.

float fVar;
float4 color;
float fVar = 3.1f;

int iVar[3];

int iVar[3] = {1,2,3};

uniform float4 position : SV_POSITION; 
const float4 lightDirection = {0,0,1};
      

Общий доступ к группе

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

Примечание

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

  • Это упущение приводит к неперемечаемому коду, который может не работать на некотором оборудовании и не работает с программными растеризаторами, которые обычно выполняют потоки в небольших группах.
  • Повышение производительности, которое можно достичь с помощью этого упущения, будет незначительным по сравнению с использованием барьера для всех потоков.

В Direct3D 10 не выполняется синхронизация потоков при записи в groupshared, поэтому каждый поток ограничен одним расположением в массиве для записи. Используйте системное значение SV_GroupIndex для индексирования в этом массиве при записи, чтобы гарантировать, что два потока не могут столкнуться. С точки зрения чтения все потоки имеют доступ ко всему массиву для чтения.

struct GSData
{
    float4 Color;
    float Factor;
}

groupshared GSData data[5*5*1];

[numthreads(5,5,1)]
void main( uint index : SV_GroupIndex )
{
    data[index].Color = (float4)0;
    data[index].Factor = 2.0f;
    GroupMemoryBarrierWithGroupSync();
    ...
}

Упаковка

Упаковывать подкомпоненты векторов и скаляров, размер которых достаточно велик, чтобы предотвратить пересечение границ регистра. Например, все они допустимы:

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

Не удается смешивать типы упаковки.

Как и регистр ключевое слово, набор packoffset может быть целевым. Подкомпонентная упаковка доступна только с ключевое слово packoffset, а не с ключевое слово регистра. Внутри объявления cbuffer регистр ключевое слово игнорируется для целевых объектов Direct3D 10, так как это предполагается для кроссплатформенной совместимости.

Упакованные элементы могут перекрываться, и компилятор не выдает ошибок или предупреждений. В этом примере Element2 и Element3 будут перекрываться с Element1.x и Element1.y.

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

Пример использования packoffset: пример HLSLWithoutFX10.

Переменные (DirectX HLSL)