Listas de comandos de suporte

Esta seção se aplica somente ao Windows 7 e posterior e ao Windows Server 2008 R2 e versões posteriores do Windows.

O runtime do Direct3D usa a seguinte DDI do Direct3D 11 para listas de comandos:

A semântica das funções CommandListExecute, CalcPrivateCommandListSize, CreateCommandList e DestroyCommandList do driver é basicamente autoexplicativa, com base em outras funções DDI semelhantes e na documentação da API para a DDI correspondente.

Depois que o runtime do Direct3D chama com êxito a função CreateCommandList ou RecycleCreateCommandList do driver no contexto adiado especificado no membro hDeferredContext da estrutura D3D11DDIARG_CREATECOMMANDLIST para a qual o parâmetro pCreateCommandList aponta, o runtime do Direct3D executa a seguinte sequência de destruição no contexto adiado:

  1. O runtime do Direct3D "fecha" todos os identificadores de objeto adiados abertos. Observe que esses identificadores ainda podem parecer associados ao contexto adiado.

  2. O runtime destrói o contexto adiado.

Durante a chamada para CreateCommandList ou RecycleCreateCommandList, todas as chamadas feitas pelo driver para as funções de retorno de chamada DDI de atualização de estado continuam a divulgar o estado atual do contexto adiado. No entanto, durante o "fechamento" e a destruição do contexto adiado, todas as chamadas para a DDI de atualização de estado refletem que nada está associado (ou seja, imediatamente após a chamada para CreateCommandList ou RecycleCreateCommandList, tudo está implicitamente desassociado).

Um contexto adiado também pode ser abandonado explicitamente pelo aplicativo ou devido a uma condição de erro pela API ou pelo driver. Para esses casos, o runtime do Direct3D executa a seguinte sequência:

  1. O runtime do Direct3D chama a função AbandonCommandList do driver.

  2. O runtime desassocia identificadores do contexto adiado um por um.

  3. O runtime "fecha" todos os identificadores de objeto adiado abertos.

  4. O runtime recua ou destrói o contexto adiado.

A sequência anterior é semelhante à sequência de destruição de um contexto imediato. A chamada para a função AbandonCommandList do driver fornece uma oportunidade para o driver aplicar o estado no que o driver preferir.

Durante a chamada para a função CommandListExecute do driver, o driver deve fazer a transição do estado do contexto adiado para torná-lo equivalente ao estado quando o dispositivo foi criado. Essa operação também é conhecida como uma operação de estado não criptografado. Durante a chamada para a função CommandListExecute do driver, no entanto, todas as chamadas feitas pelo driver para as funções de retorno de chamada DDI de atualização de estado ainda refletem o estado do que foi associado durante a última chamada DDI a uma função de driver. Durante a próxima chamada DDI para uma função de driver, todas as chamadas que o driver faz para as funções de retorno de chamada DDI de atualização de estado mostram o estado atual como completamente vazio, o que reflete a transição de estado implícita de CommandListExecute. Esse fato difere ligeiramente da semântica típica e do comportamento das funções de retorno de chamada DDI de atualização de estado. Se o driver tivesse chamado uma função de retorno de chamada DDI de atualização de estado durante uma chamada para uma das funções SetShader do driver, a função de retorno de chamada DDI de atualização de estado seria mostrada como já associada ao novo sombreador que está sendo associado. Essa divergência do comportamento de retorno de chamada DDI de atualização de estado fornece mais flexibilidade para o driver refletir o estado antigo durante CommandListExecute.

A API do Direct3D versão 11 garante que nenhuma consulta tenha sido manipulada (ou seja, teve QueryBegin ou QueryEnd chamado) pela lista de comandos e foi apenas "iniciada" pelo contexto que tenta executar a lista de comandos. A API também garante que nenhuma lista de comandos que registrou o mapa de um recurso dinâmico seja executada em um contexto que tenha o mesmo recurso mapeado no momento. Antes que um aplicativo chame a função FinishCommandList , o runtime do Direct3D chama a função DDI QueryEnd e ResourceUnmap do driver em qualquer consulta ou recurso dinâmico que ainda contenha uma consulta iniciada ou um recurso mapeado aberto porque FinishCommandList encerra implicitamente intervalos de consulta e cancela qualquer recurso mapeado.

Otimização para listas de comandos pequenos

Uma otimização de reciclagem de memória para listas de comandos de pequena quantidade de memória pode ser importante para reduzir a contenção entre chamadas de função DDI da lista de comandos e reduzir a sobrecarga do processamento de chamadas necessário para listas de comandos. A sobrecarga de processamento que é inherant em cada lista de comandos é significativa. Essa otimização destina-se a listas de comandos em que a sobrecarga de processamento necessária para as listas de comandos domina o tempo de CPU e o espaço de memória necessário para as listas de comandos. Uma lista de comandos de quantidade de memória pequena é, por exemplo, um único comando gráfico, como CopyResource. A quantidade de memória necessária para CopyResource é de dois ponteiros. No entanto, CopyResource ainda requer a mesma quantidade de processamento de chamadas de lista de comandos que uma lista de comandos de grande quantidade de memória. Quando listas de comandos de quantidade de memória pequena são geradas em alta frequência, a sobrecarga de processamento necessária para o runtime chamar as funções CreateCommandList, DestroyCommandList, CreateDeferredContext e DestroyDevice(D3D10) do driver (para contexto adiado) torna-se cada vez mais importante. A memória mencionada aqui é a memória do sistema que contém estruturas de dados de driver, que inclui a memória para identificadores DDI.

A função RecycleCommandList do driver deve notificar o driver quando os identificadores de driver saem de uso (mas ainda não foram excluídos) e quando os identificadores de driver não utilizados anteriormente são reutilizados. Essa notificação se aplica a identificadores de lista de comandos e de contexto adiado. A única memória para a qual o driver deve reciclar é a memória para a qual o identificador DDI aponta. Embora o objetivo de RecycleCommandList seja reciclar a memória associada ao identificador, para eficiência, o driver tem total flexibilidade para escolher qual memória reciclar. O driver não pode alterar o tamanho da região da memória para a qual a lista de comandos de contexto imediato manipula pontos. Esse tamanho é o valor retornado de CalcPrivateCommandListSize. O driver também não pode alterar o tamanho da região da memória para a qual o comando de contexto lista pontos de identificador locais. Esse tamanho é o valor retornado de CalcDeferredContextHandleSize.

As funções DDI RecycleCreateCommandList e RecycleCreateDeferredContext do driver devem retornar códigos de erro de memória insuficiente como E_OUTOFMEMORY valores HRESULT. Essas funções não fornecem esses códigos de erro por meio de chamadas para a função pfnSetErrorCb . Esse requisito de driver impede que o runtime precise usar a sincronização em todo o dispositivo para watch para erros de contexto imediatos dessas funções de driver de tipo de criação. Observar esses erros seria uma fonte de contenção catastrófica para listas de comandos de pequena quantidade de memória.

As distinções entre as funções RecycleDestroyCommandList, RecycleCommandList e RecycleCreateCommandList do driver são importantes. Seus recursos incluem o seguinte.

RecycleDestroyCommandList

O runtime chama a função RecycleDestroyCommandList do driver para notificar o driver de que a destruição leve é necessária. Ou seja, o driver ainda não deve desalocar a memória para o identificador de lista de comandos DDI. A função RecycleDestroyCommandList do driver é de thread livre, assim como a função DestroyCommandList do driver.

RecycleCommandList

A função RecycleCommandList do driver informa ao driver que o runtime integrou um identificador de lista de comandos de volta ao cache de contexto adiado. Em seguida, a função fornece ao driver uma oportunidade de integrar a memória associada à lista de comandos de volta ao cache de contexto adiado. O runtime chama a função RecycleCommandList do driver do thread de contexto adiado. A função DDI RecycleCommandList reduz a necessidade de o driver executar a sincronização própria.

RecycleCreateCommandList

O runtime chama a função RecycleCreateCommandList do driver para tornar um identificador DDI não utilizado anteriormente completamente válido novamente.

Essas funções DDI de reciclagem fornecem oportunidades de otimização para ajudar a reciclar recursos para listas de comandos de pequena quantidade de memória. O pseudocódigo a seguir mostra a implementação do runtime por meio do fluxo de chamadas de função da API para a DDI :

::FinishCommandList()
{
  // Empty InterlockedSList, integrating into the cache
  Loop { DC::pfnRecycleCommandList }

  If (Previously Destroyed CommandList Available)
 { IC::pfnRecycleCreateCommandList }
 else
  {
    IC::pfnCalcPrivateCommandListSize
    IC::pfnCreateCommandList
    IC::pfnCalcDeferredContextHandleSize(D3D11DDI_HT_COMMANDLIST)
  }

  Loop { DC::pfnDestroy* (context-local handle destroy) }

  IC::pfnRecycleCreateDeferredContext
}
...
Sporadic: DC::pfnCreate* (context-local open during first-bind per CommandList)

CommandList::Destroy()
{
  // If DC still alive, almost always recycle:
  If (DC still alive)
 { IC::pfnRecycleDestroyCommandList }
  Else
 { IC::pfnDestroyCommandList }
  // Add to InterlockedSList
}

O diagrama de estado a seguir mostra a validade de um identificador de lista de comandos DDI de contexto imediato. O estado verde representa um identificador que pode ser usado com CommandListExecute.

Diagrama ilustrando os estados de validade de um identificador de lista de comandos DDI de contexto imediato.