Клонирование эффекта
Клонирование эффекта создает вторую, почти идентичную копию эффекта. Объяснение того, почему он не является точным, см. в следующем квалификаторе. Вторая копия эффекта полезна, если требуется использовать платформу эффектов в нескольких потоках, так как среда выполнения эффекта не является потокобезопасной для поддержания высокой производительности.
Так как контексты устройств также не являются потокобезопасными, разные потоки должны передавать разные контексты устройства в метод ID3DX11EffectPass::Apply.
Эффект можно клонировать с помощью следующего синтаксиса:
ID3DX11Effect* pClonedEffect = NULL;
UINT Flags = D3DX11_EFFECT_CLONE_FORCE_NONSINGLE;
HRESULT hr = pEffect->CloneEffect( Flags, &pClonedEffect );
В приведенном выше примере клонированная копия будет инкапсулировать то же состояние, что и исходный эффект, независимо от того, в каком состоянии находится исходный эффект. В частности:
- Если pEffect оптимизирован, то оптимизирован эффект pCloned.
- Если pEffect имеет некоторые управляемые пользователем переменные, pCloned Effect будет иметь те же переменные, управляемые пользователем (см. одно описание ниже).
- Все ожидающие обновления переменных (до тех пор, пока не будет применен вызов обновляет состояние устройства) в pEffect будут находиться в состоянии pClonedEffect.
Следующие объекты устройств Direct3D 11 неизменяемы или никогда не обновляются платформой эффектов, поэтому клонированный эффект будет указывать на те же объекты, что и исходный эффект:
- Объекты блоков состояния (ID3D11BlendState, ID3D11RasterizerState, ID3D11DepthStencilState, ID3D11SamplerState)
- Шейдеры
- Экземпляры класса
- Текстуры (не включая буферы текстур)
- Неупорядоченные представления доступа
Следующие объекты устройств Direct3D 11 являются как неизменяемыми, так и изменены средой выполнения эффекта (если только не управляемые пользователем или одиночные объекты в клонированном эффекте); новые копии этих объектов создаются, если они не являются отдельными:
- Буферы констант
- Буферы текстур
Буферы отдельных констант и буферы текстур
Обратите внимание, что это обсуждение относится как к буферам констант, так и к текстурам, но для удобства чтения предполагается, что буферы констант.
Бывают случаи, когда буфер констант обновляется только одним потоком, но состояние устройства, заданное с помощью клонированных эффектов, будет использовать эти данные. Например, эффект main может обновлять матрицы мира и представления, на которые ссылаются шейдеры в клонированных эффектах, которые не изменяют матрицы мира и представления. В таких случаях клонированные эффекты должны ссылаться на текущий буфер констант, а не воссоздавать его.
Существует два способа достижения желаемого результата:
- Используйте ID3DX11EffectConstantBuffer::SetConstantBuffer для клонированного эффекта, чтобы сделать его управляемым пользователем
- Пометьте буфер констант как "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.
Связанные темы