Direct3D 11 on 12

D3D11On12 é um mecanismo pelo qual os desenvolvedores podem usar interfaces e objetos D3D11 para conduzir a API D3D12. D3D11on12 permite que os componentes gravados usando D3D11 (por exemplo, texto D2D e interface do usuário) trabalhem em conjunto com componentes gravados visando a API D3D12. D3D11on12 também permite a portabilidade incremental de um aplicativo de D3D11 para D3D12, permitindo que partes do aplicativo continuem direcionando D3D11 para simplificar, enquanto outras direcionam D3D12 para desempenho, enquanto sempre têm renderização completa e correta. D3D11On12 torna mais simples do que usar técnicas de interoperabilidade para compartilhar recursos e sincronizar o trabalho entre as duas APIs.

Inicializando D3D11On12

Para começar a usar D3D11On12, a primeira etapa é criar um dispositivo D3D12 e uma fila de comandos. Esses objetos são fornecidos como entrada para o método de inicialização D3D11On12CreateDevice. Você pode considerar esse método como a criação de um dispositivo D3D11 com o tipo de driver imaginário D3D_DRIVER_TYPE_11ON12, em que o driver D3D11 é responsável por criar objetos e enviar listas de comandos para a API D3D12.

Depois de ter um dispositivo D3D11 e um contexto imediato, você poderá QueryInterface desativar o dispositivo para a interface ID3D11On12Device . Essa é a interface primária usada para interoperabilidade entre D3D11 e D3D12. Para que o contexto do dispositivo D3D11 e as listas de comandos D3D12 operem nos mesmos recursos, é necessário criar "recursos encapsulados" usando a API CreateWrappedResource . Esse método "promove" um recurso D3D12 a ser compreensível em D3D11. Um recurso encapsulado começa no estado "adquirido", uma propriedade que é manipulada pelos métodos AcquireWrappedResources e ReleaseWrappedResources .

Exemplo de uso

O uso típico de D3D11On12 seria usar D2D para renderizar texto ou imagens sobre um buffer traseiro D3D12. Consulte o exemplo D3D11On12 para obter o código de exemplo. Aqui está uma estrutura de tópicos aproximada das etapas a serem tomadas para fazer isso:

  • Crie um dispositivo D3D12 (D3D12CreateDevice) e uma cadeia de troca D3D12 (CreateSwapChain com um ID3D12CommandQueue como uma entrada).
  • Crie um dispositivo D3D11On12 usando o dispositivo D3D12 e a mesma fila de comandos que a entrada.
  • Recupere os buffers de back da cadeia de troca e crie recursos encapsulados em D3D11 para cada um deles. O estado de entrada usado deve ser a última maneira que d3D12 o usou (por exemplo, RENDER_TARGET) e o estado de saída deve ser a maneira como D3D12 o usará após a conclusão do D3D11 (por exemplo, PRESENT).
  • Inicialize d2D e forneça os recursos encapsulados D3D11 para D2D para se preparar para renderização.

Em seguida, em cada quadro, faça o seguinte:

Tela de fundo

D3D11On12 funciona sistematicamente. Cada chamada à API D3D11 passa pela validação típica de runtime e chega ao driver. Na camada de driver, o driver especial 11on12 registra o estado e emite operações de renderização para listas de comandos D3D12. Essas listas de comandos são enviadas conforme necessário (por exemplo, uma consulta GetData ou recurso Map pode exigir a liberação de comandos) ou conforme solicitado pelo Flush. A criação de um objeto D3D11 normalmente resulta na criação do objeto D3D12 correspondente. Algumas operações de renderização de função fixas em D3D11, como GenerateMips ou DrawAuto não, têm suporte em D3D12 e, portanto, D3D11On12 as emula usando sombreadores e recursos adicionais.

Para interoperabilidade, é importante entender como D3D11On12 interage com os objetos D3D12 que o aplicativo criou e forneceu. Para garantir que o trabalho ocorra na ordem correta, o contexto imediato D3D11 deve ser liberado antes que o trabalho D3D12 adicional possa ser enviado para essa fila. Também é importante garantir que a fila fornecida a D3D11On12 seja drenável o tempo todo. Isso significa que todas as esperas na fila devem eventualmente ser atendidas, mesmo que o thread de renderização D3D11 seja bloqueado indefinidamente. Tenha cuidado para não assumir uma dependência de quando D3D11On12 insere liberações ou esperas, pois isso pode mudar com versões futuras. Além disso, d3D11On12 rastreia e manipula estados de recursos por conta própria. A única maneira de garantir a coerência das transições de estado é usar as APIs de aquisição/versão para manipular o acompanhamento de estado para atender às necessidades do aplicativo.

Limpeza

Para liberar um recurso encapsulado D3D11On12, duas coisas precisam acontecer nesta ordem:

  • Todas as referências ao recurso, incluindo quaisquer exibições do recurso, precisam ser liberadas.
  • O processamento de destruição adiada deve ocorrer. A maneira mais simples de garantir que isso aconteça é invocar a API de contexto Flush imediato.

Depois que ambas as etapas forem concluídas, todas as referências feitas pelo recurso encapsulado deverão ser lançadas e o recurso D3D12 se tornará propriedade exclusiva do componente D3D12. Lembre-se de que d3D12 ainda requer aguardar a conclusão da GPU antes de liberar completamente um recurso, portanto, certifique-se de manter uma referência no recurso antes de executar as duas etapas acima, a menos que você já tenha confirmado que a GPU não está mais usando o recurso.

Todos os outros recursos ou objetos criados por D3D11On12 serão limpos no momento apropriado, quando a GPU terminar de usá-los, usando o mecanismo de destruição adiada do D3D11. No entanto, se você tentar liberar o próprio dispositivo D3D11On12 enquanto a GPU ainda estiver em execução, a destruição poderá ser bloqueada até que a GPU seja concluída.

Limitações

A camada D3D11On12 implementa um subconjunto muito grande da API D3D11, mas há algumas lacunas conhecidas (além de bugs na implementação que podem causar renderização incorreta).

A partir de Windows 10, versão 1809 (10.0; Build 17763), desde que D3D11On12 esteja em execução em um driver que dê suporte ao Modelo de Sombreador 6.0 ou posterior, ele poderá executar sombreadores que usam interfaces. Em versões anteriores do Windows, o recurso de interfaces de sombreador não é implementado em D3D11On12 e tentar usar o recurso causará erros e mensagens de depuração.

A partir de Windows 10, versão 1803 (10.0; Build 17134), há suporte para cadeias de troca em dispositivos D3D11On12. Em versões anteriores do Windows, elas não são.

D3D11On12 não foi otimizado para desempenho. Provavelmente haverá sobrecarga moderada da CPU em comparação com um driver D3D11 padrão, sobrecarga mínima de GPU e é conhecido por haver sobrecarga significativa de memória. Portanto, não é recomendável usar D3D11On12 para cenas 3D complicadas e, em vez disso, é recomendado para cenas simples ou renderização 2D.

APIs

AS APIs que compõem a camada 11on12 são descritas na Referência 11on12.

D2D usando o passo a passo D3D11on12

Introdução ao Direct3D 12

Como trabalhar com o Direct2D, o Direct3D 10 e o Direct3D 11