Clonando um efeito

Clonar um efeito cria uma segunda cópia quase idêntica do efeito. Consulte o qualificador único a seguir para obter uma explicação de por que ele não é exato. Uma segunda cópia de um efeito é útil quando se deseja usar a estrutura de efeitos em vários threads, pois o runtime de efeito não é thread-safe para manter o alto desempenho.

Como os contextos do dispositivo também são nã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 que o efeito original, independentemente do estado em que o efeito original está. Especialmente:

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

Os seguintes objetos de dispositivo Direct3D 11 são imutáveis ou nunca 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 (sem incluir buffers de textura)
  5. Exibições de acesso não ordenadas

Os seguintes objetos de dispositivo Direct3D 11 são imutáveis e modificados pelo runtime de efeito (a menos que gerenciado pelo usuário ou único em um efeito clonado); novas cópias desses objetos são criadas quando não são simples:

  1. Buffers constantes
  2. Buffers de textura

Buffers constantes únicos e buffers de textura

Observe que essa discussão se aplica a buffers constantes e texturas, mas buffers constantes são considerados 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 main pode atualizar o mundo e exibir matrizes que são referenciadas de sombreadores em efeitos clonados que não alteram o mundo e exibem matrizes. Nesses casos, os efeitos clonados precisam referenciar o buffer constante atual em vez de recriar um.

Há duas maneiras de alcançar esse resultado desejado:

  1. Usar ID3DX11EffectConstantBuffer::SetConstantBuffer no efeito clonado para torná-lo gerenciado pelo usuário
  2. Marque o buffer constante como "único" no código HLSL, forçando o runtime de efeito a tratar como gerenciado pelo usuário após a clonagem

Há duas diferenças entre os dois métodos acima. Primeiro, no método 1, um novo ID3D11Buffer será criado e o usuário 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 (quais efeitos serão atualizados em Apply), enquanto a variável no método 2 continuará apontando para o buffer original (não atualizando-o em Apply).

Consulte 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 Aplicar, mas fará referência ao ID3D11Buffer original para ViewData. O qualificador único pode ser ignorado no processo de clonagem definindo o sinalizador D3DX11_EFFECT_CLONE_FORCE_NONSINGLE.

Efeitos (Direct3D 11)