Clonación de un efecto

La clonación de un efecto crea una segunda copia casi idéntica del efecto. Consulte el siguiente calificador único para obtener una explicación de por qué no es exacto. Una segunda copia de un efecto es útil cuando se quiere usar el marco de efectos en varios subprocesos, ya que el tiempo de ejecución del efecto no es seguro para subprocesos para mantener un alto rendimiento.

Dado que los contextos de dispositivo también no son seguros para subprocesos, los distintos subprocesos deben pasar contextos de dispositivo diferentes al método ID3DX11EffectPass::Apply.

Un efecto se puede clonar con la sintaxis siguiente:

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

En el ejemplo anterior, la copia clonada encapsulará el mismo estado que el efecto original, independientemente del estado en el que se encuentra el efecto original. En concreto:

  1. Si pEffect está optimizado, se optimiza el efecto pCloned.
  2. Si pEffect tiene algunas variables administradas por el usuario, pCloned Effect tendrá las mismas variables administradas por el usuario (consulte la descripción única siguiente).
  3. Las actualizaciones de variables pendientes (hasta que un estado de dispositivo Aplicar actualizaciones de llamadas) en pEffect estarán pendientes en pClonedEffect.

Los siguientes objetos de dispositivo direct3D 11 son inmutables o nunca actualizados por el marco de efectos, por lo que el efecto clonado apuntará a los mismos objetos que el efecto original:

  1. Objetos de bloque de estado (ID3D11BlendState, ID3D11RasterizerState, ID3D11DepthStencilState, ID3D11SamplerState)
  2. Sombreadores
  3. Instancias de clase
  4. Texturas (sin incluir búferes de textura)
  5. Vistas de acceso desordenadas

Los siguientes objetos de dispositivo direct3D 11 son inmutables y modificados por el tiempo de ejecución del efecto (a menos que el usuario administrado o único en un efecto clonado); se crean nuevas copias de estos objetos cuando no son únicas:

  1. Búferes de constantes
  2. Búferes de textura

Búferes de constante única y búferes de textura

Tenga en cuenta que esta explicación se aplica tanto a los búferes de constantes como a las texturas, pero se supone que los búferes de constantes son fáciles de leer.

Puede haber casos en los que un subproceso solo actualiza un búfer de constantes, pero el estado del dispositivo establecido por efectos clonados usará estos datos. Por ejemplo, el efecto principal puede actualizar las matrices de mundo y vista a las que se hace referencia desde sombreadores en efectos clonados que no cambian las matrices de mundo y vista. En estos casos, los efectos clonados deben hacer referencia al búfer de constantes actual en lugar de volver a crear uno.

Hay dos maneras de lograr este resultado deseado:

  1. Use ID3DX11EffectConstantBuffer::SetConstantBuffer en el efecto clonado para que sea administrado por el usuario.
  2. Marque el búfer de constantes como "único" en el código HLSL, lo que obliga al tiempo de ejecución de efecto a tratar es como administrado por el usuario después de la clonación.

Hay dos diferencias entre los dos métodos anteriores. En primer lugar, en el método 1, se creará un nuevo id3D11Buffer y se creará el usuario antes de llamar a SetConstantBuffer. Además, después de llamar a UndoSetConstantBuffer en el efecto clonado, la variable del método 1 apuntará al búfer recién creado (los efectos se actualizarán en Apply) mientras que la variable del método 2 seguirá apuntando al búfer original (no actualizarlo en Apply).

Consulte el ejemplo siguiente en HLSL:

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

Durante la clonación, el efecto clonado creará un nuevo id3D11Buffer para ObjectData y rellenará su contenido en Apply, pero hará referencia al id3D11Buffer original para ViewData. El calificador único se puede omitir en el proceso de clonación estableciendo la marca D3DX11_EFFECT_CLONE_FORCE_NONSINGLE.

Efectos (Direct3D 11)