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


Клонирование эффекта

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

Так как контексты устройств также не являются потокобезопасными, разные потоки должны передавать разные контексты устройства в метод ID3DX11EffectPass::Apply.

Эффект можно клонировать с помощью следующего синтаксиса:

ID3DX11Effect* pClonedEffect = NULL;
UINT Flags = D3DX11_EFFECT_CLONE_FORCE_NONSINGLE;
HRESULT hr = pEffect->CloneEffect( Flags, &pClonedEffect );

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

  1. Если pEffect оптимизирован, то оптимизирован эффект pCloned.
  2. Если pEffect имеет некоторые управляемые пользователем переменные, pCloned Effect будет иметь те же переменные, управляемые пользователем (см. одно описание ниже).
  3. Все ожидающие обновления переменных (до тех пор, пока не будет применен вызов обновляет состояние устройства) в pEffect будут находиться в состоянии pClonedEffect.

Следующие объекты устройств Direct3D 11 неизменяемы или никогда не обновляются платформой эффектов, поэтому клонированный эффект будет указывать на те же объекты, что и исходный эффект:

  1. Объекты блоков состояния (ID3D11BlendState, ID3D11RasterizerState, ID3D11DepthStencilState, ID3D11SamplerState)
  2. Шейдеры
  3. Экземпляры класса
  4. Текстуры (не включая буферы текстур)
  5. Неупорядоченные представления доступа

Следующие объекты устройств Direct3D 11 являются как неизменяемыми, так и изменены средой выполнения эффекта (если только не управляемые пользователем или одиночные объекты в клонированном эффекте); новые копии этих объектов создаются, если они не являются отдельными:

  1. Буферы констант
  2. Буферы текстур

Буферы отдельных констант и буферы текстур

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

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

Существует два способа достижения желаемого результата:

  1. Используйте ID3DX11EffectConstantBuffer::SetConstantBuffer для клонированного эффекта, чтобы сделать его управляемым пользователем
  2. Пометьте буфер констант как "single" в коде HLSL, заставляя среду выполнения эффекта обрабатывать как управляемый пользователем после клонирования.

Существует два различия между двумя приведенными выше методами. Во-первых, в методе 1 будет создан новый ID3D11Buffer и пользователь до вызова SetConstantBuffer. Кроме того, после вызова UndoSetConstantBuffer в клонированных эффектах переменная в методе 1 будет указывать на вновь созданный буфер (который будет обновляться при применении), в то время как переменная в методе 2 будет по-прежнему указывать на исходный буфер (не обновляя его при применении).

См. следующий пример в HLSL:

cbuffer ObjectData
{
    float4 Position;
};
single cbuffer ViewData
{
    float4x4 ViewMatrix;
};

При клонировании клонированный эффект создаст новый ID3D11Buffer для ObjectData и заполнит его содержимое в поле Применить, но ссылается на исходный ID3D11Buffer для ViewData. Один квалификатор можно игнорировать в процессе клонирования, установив флаг D3DX11_EFFECT_CLONE_FORCE_NONSINGLE.

Эффекты (Direct3D 11)