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


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

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

Так как контексты устройств также не являются потокобезопасными, различные потоки должны передавать разные контексты устройств в метод 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 до тех пор, пока вызов функции Apply не обновит состояние устройства.

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

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

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

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

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

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

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

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

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

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

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

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

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

Эффекты (Direct3D 11)