Partilhar via


Executando e sincronizando listas de comandos

No Microsoft Direct3D 12, o modo imediato de versões anteriores não está mais presente. Em vez disso, os aplicativos criam listas de comandos e pacotes e, em seguida, gravam conjuntos de comandos da GPU. As filas de comandos são usadas para enviar listas de comandos a serem executadas. Este modelo permite que os desenvolvedores tenham mais controle sobre o uso eficiente da unidade de processamento gráfico (GPU) e da CPU.

Visão geral da fila de comandos

As filas de comandos do Direct3D 12 substituem o tempo de execução e a sincronização de drivers do envio de trabalho em modo imediato, anteriormente não expostos ao desenvolvedor, por APIs para gerenciar explicitamente simultaneidade, paralelismo e sincronização. As filas de comandos fornecem as seguintes melhorias para os desenvolvedores:

  • Permite que os desenvolvedores evitem ineficiências acidentais causadas por sincronização inesperada.
  • Permite que os desenvolvedores introduzam a sincronização em um nível mais alto, onde a sincronização necessária pode ser determinada de forma mais eficiente e precisa. Isso significa que o tempo de execução e o driver gráfico gastará menos tempo a projetar o paralelismo de forma reativa.
  • Torna as operações dispendiosas mais explícitas.

Essas melhorias habilitam ou aprimoram os seguintes cenários:

  • Maior paralelismo - Os aplicativos podem usar filas mais profundas para cargas de trabalho em segundo plano, como decodificação de vídeo, quando têm filas separadas para trabalho em primeiro plano.
  • Trabalho assíncrono e de baixa prioridade da GPU - O modelo de fila de comandos permite a execução simultânea de trabalho de GPU de baixa prioridade e operações atômicas que permitem que um thread de GPU consuma os resultados de outro thread não sincronizado sem bloqueio.
  • Trabalho de computação de alta prioridade - Este design permite que cenários que exigem a interrupção da renderização 3D façam uma pequena quantidade de trabalho de computação de alta prioridade para que o resultado possa ser obtido antecipadamente para processamento adicional na CPU.

Inicializando uma fila de comandos

As filas de comandos podem ser criadas chamando ID3D12Device::CreateCommandQueue. Esse método utiliza um D3D12_COMMAND_LIST_TYPE indicando que tipo de fila deve ser criada e, por isso, que tipo de comandos podem ser enviados para ela. Lembre-se de que os pacotes só podem ser chamados a partir de listas de comandos diretos e não podem ser enviados diretamente para uma fila. Os tipos de fila suportados são:

Em geral, as filas DIRECT e as listas de comandos aceitam qualquer comando, as filas COMPUTE e as listas de comandos aceitam comandos relacionados a computação e cópia, e as filas e listas de comandos COPY aceitam apenas comandos de cópia.

Executando listas de comandos

Depois de gravar uma lista de comandos e recuperar a fila de comandos padrão ou criar uma nova, execute listas de comandos chamando ID3D12CommandQueue::ExecuteCommandLists.

As aplicações podem enviar listas de comandos para qualquer fila de comandos a partir de várias linhas de execução. O runtime irá realizar o trabalho de serializar essas solicitações pela ordem de envio.

O tempo de execução validará a lista de comandos enviada e descartará a chamada para ExecuteCommandLists se alguma das restrições for violada. As chamadas serão canceladas pelos seguintes motivos:

Acessar recursos de várias filas de comandos

Há algumas regras impostas pelo tempo de execução que restringem o acesso de recursos de várias filas de comando. Estas regras são as seguintes:

  1. Um recurso não pode ser gravado a partir de várias filas de comandos simultaneamente. Quando um recurso transita para um estado gravável em uma fila, ele é considerado de propriedade exclusiva dessa fila e deve fazer a transição para um estado de leitura ou COMUM (consulte D3D12_RESOURCE_STATES) antes de poder ser acessado por outra fila.

  2. Quando em estado de leitura, um recurso pode ser lido a partir de várias filas de comandos simultaneamente, incluindo entre processos, com base no seu estado de leitura.

Para obter mais informações sobre restrições de acesso a recursos e o uso de barreiras de recursos para sincronizar o acesso a recursos, consulte Usando barreiras de recursos para sincronizar estados de recursos.

Sincronizando a execução da lista de comandos usando cercas de fila de comandos

O suporte para várias filas de comandos paralelos no Direct3D 12 oferece mais flexibilidade e controle sobre a priorização do trabalho assíncrono na GPU. Esse design também significa que os aplicativos precisam gerenciar explicitamente a sincronização do trabalho, especialmente quando as listas de comandos em uma fila dependem de recursos que estão sendo operados por outra fila de comandos. Alguns exemplos disso incluem aguardar a conclusão de uma operação em uma fila de computação para que o resultado possa ser usado para uma operação de renderização na fila 3D e aguardar a conclusão de uma operação 3D para que uma operação na fila de computação possa acessar um recurso para gravação. Para habilitar a sincronização do trabalho entre filas, o Direct3D 12 usa o conceito de cercas, que são representadas na API pela interfaceID3D12Fence.

Uma cerca é um número inteiro que representa a unidade atual de trabalho que está sendo processada. Quando o aplicativo avança a cerca, ao chamar ID3D12CommandQueue::Signal, o inteiro é atualizado. Os aplicativos podem verificar o valor de uma cerca e determinar se uma unidade de trabalho foi concluída para decidir se uma operação subsequente pode ser iniciada.

Sincronizando recursos acessados por filas de comandos

No Direct3D 12, a sincronização do estado de alguns recursos é implementada com barreiras de recursos. Em cada barreira de recurso, um aplicativo declara os estados antes e depois de um recurso. Um exemplo comum é a transição de um recurso entre uma exibição de recurso de sombreador para uma exibição de destino de renderização. Na maioria das vezes, essas barreiras de recursos são gerenciadas dentro de listas de comandos. Quando as camadas de depuração são habilitadas, o sistema impõe que os estados antes e depois de todos os recursos coincidam, garantindo que o recurso esteja no estado correto para uma operação específica em uma transição de barreira.

Para obter mais informações sobre como sincronizar o estado do recurso, consulte Usando barreiras de recursos para sincronizar estados de recursos.

Suporte para fila de comandos para recursos em mosaico

Os métodos para gerenciar recursos em mosaico, que foram expostos pela interfaceID3D11DeviceContext2 nodo Direct3D 11, são fornecidos pela interfaceID3D12CommandQueue nodo Direct3D 12. Esses métodos incluem:

Método Descrição
CopiarMapeamentosDeTelhas Copia mapeamentos de um recurso em mosaico de origem para um recurso em mosaico de destino.
UpdateTileMappings Atualiza os mapeamentos das localizações de ladrilho em recursos em mosaico para locais de memória numa pilha de recursos.

Para obter mais informações sobre como usar recursos em mosaico em aplicações Direct3D 12, consulte Direct3D11 Tiled Resources.

Envio de trabalho no Direct3D 12