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


Синтаксис переменной

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

[Storage_Class] [Type_Modifier] Имя типа[индекс] [: семантика] [: Packoffset] [: Register]; [Заметки] [= Initial_Value]

Параметры

Storage_Class

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

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

Type_Modifier

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

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

Примечание.

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

Тип

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

Name[Index]

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

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

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

Packoffset

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

Регистр

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

Заметки

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

Initial_Value

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

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

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

Внимание

Поддержка этой функции была удалена в Direct3D 12, включая возможность отражения инициализаторов по умолчанию.

Примеры

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

float fVar;
float4 color;

int iVar[3];

uniform float4 position : SV_POSITION; 

//Default initializers; supported up to Direct3D 11.

float fVar = 3.1f;
int iVar[3] = {1,2,3};
const float4 lightDirection = {0,0,1};

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

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

Примечание.

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

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

В Direct3D 10 синхронизация потоков при записи в группы не выполняется, поэтому это означает, что каждый поток ограничен одним расположением в массиве для записи. Используйте системное значение 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, а не ключевым словом register. В объявлении cbuffer ключевое слово register игнорируется для целевых объектов Direct3D 10, так как предполагается, что оно предназначено для кроссплатформенной совместимости.

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

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

Пример, использующий packoffset: пример HLSLWithoutFX10.