Partilhar via


Clonagem de um efeito

A clonagem de um efeito cria uma segunda cópia quase idêntica do efeito. Veja o qualificador único a seguir para uma explicação do motivo pelo qual ele não é exato. Uma duplicata de um efeito é útil quando se deseja usar o framework de efeitos em vários threads, uma vez que o tempo de execução do efeito não é seguro para threads, garantindo assim um alto desempenho.

Como os contextos de dispositivo também não são thread-safe, threads diferentes devem passar contextos de dispositivo diferentes para o método ID3DX11EffectPass::Apply.

Um efeito pode ser clonado com a seguinte sintaxe:

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

No exemplo acima, a cópia clonada encapsulará o mesmo estado do efeito original, independentemente do estado em que o efeito original se encontra. Em especial:

  1. Se o pEffect estiver otimizado, o efeito pCloned será otimizado
  2. Se o pEffect tiver algumas variáveis gerenciadas pelo usuário, o pCloned Effect terá as mesmas variáveis gerenciadas pelo usuário (veja a descrição única abaixo)
  3. Quaisquer atualizações de variáveis pendentes (até que uma chamada de aplicação atualize o estado do dispositivo) no pEffect estarão pendentes no pClonedEffect.

Os seguintes objetos de dispositivo Direct3D 11 são imutáveis ou nunca são atualizados pela estrutura de efeitos, portanto, o efeito clonado apontará para os mesmos objetos que o efeito original:

  1. Objetos de bloco de estado (ID3D11BlendState, ID3D11RasterizerState, ID3D11DepthStencilState, ID3D11SamplerState)
  2. Sombreadores
  3. Instâncias de classe
  4. Texturas (não incluindo buffers de textura)
  5. Vistas de acesso desordenado

Os seguintes objetos de dispositivo do Direct3D 11 são imutáveis e modificados pelo tempo de execução de efeitos (a menos que geridos pelo utilizador ou sejam únicos num efeito clonado); novas cópias destes objetos são criadas quando não são únicos:

  1. Buffers constantes
  2. Buffers de textura

Buffers de constante única e buffers de textura

Note que esta discussão se aplica a buffers constantes e texturas, mas um buffer constante é assumido para facilitar a leitura.

Pode haver casos em que um buffer constante é atualizado apenas por um thread, mas o estado do dispositivo definido por efeitos clonados usará esses dados. Por exemplo, o efeito principal pode atualizar as matrizes de mundo e de visualização que são referenciadas a partir de sombreadores em efeitos clonados, que não alteram as matrizes de mundo e de visualização. Nesses casos, os efeitos clonados precisam fazer referência ao buffer constante atual em vez de recriar um.

Existem duas formas de alcançar este resultado desejado:

  1. Use ID3DX11EffectConstantBuffer::SetConstantBuffer no efeito clonado para torná-lo gerenciado pelo usuário
  2. Marque o buffer constante como "exclusivo" no código HLSL, forçando o tempo de execução do efeito a tratá-lo como gerenciado pelo usuário após a clonagem

Existem duas diferenças entre os dois métodos acima. Primeiro, no método 1, um novo ID3D11Buffer será criado e usado antes de SetConstantBuffer ser chamado. Além disso, depois de chamar UndoSetConstantBuffer no efeito clonado, a variável no método 1 apontará para o buffer recém-criado (cujos efeitos serão atualizados em Apply), enquanto a variável no método 2 continuará a apontar para o buffer original (não atualizando-o em Apply).

Veja o seguinte exemplo em HLSL:

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

Durante a clonagem, o efeito clonado criará um novo ID3D11Buffer para ObjectData e preencherá seu conteúdo em Apply, mas fará referência ao ID3D11Buffer original para ViewData. É possível ignorar o qualificador único no processo de clonagem, definindo o sinalizador D3DX11_EFFECT_CLONE_FORCE_NONSINGLE.

Efeitos (Direct3D 11)