Partager via


Listes de commandes de prise en charge

Cette section s’applique uniquement à Windows 7 et versions ultérieures, et Windows Server 2008 R2 et versions ultérieures de Windows.

Le runtime Direct3D utilise la solution DDI Direct3D 11 suivante pour les listes de commandes :

La sémantique des fonctions CommandListExecute, CalcPrivateCommandListSize, CreateCommandList et DestroyCommandList du pilote sont principalement explicites, basées sur d’autres fonctions DDI similaires et la documentation de l’API pour la DDI correspondante.

Une fois le runtime Direct3D correctement appelé les fonctions CreateCommandList ou RecycleCreateCommandList du pilote sur le contexte différé spécifié dans le membre hDeferredContext de la structure D3D11DDIARG_CREATECOMMANDLIST vers laquelle pointe le paramètre pCreateCommandList, le runtime Direct3D exécute la séquence de destruction suivante sur le contexte différé :

  1. Le runtime Direct3D « ferme » tous les handles d’objets différés ouverts. Notez que ces handles peuvent toujours apparaître liés au contexte différé.

  2. Le runtime détruit le contexte différé.

Pendant l’appel à CreateCommandList ou RecycleCreateCommandList, tous les appels effectués par le pilote aux fonctions de rappel DDI d’actualisation de l’état continuent de divulguer l’état actuel du contexte différé. Toutefois, lors de la « fermeture » et de la destruction du contexte différé, tous les appels à l’actualisation de l’état de la DDI reflètent que rien n’est lié (c’est-à-dire, immédiatement après l’appel à CreateCommandList ou RecycleCreateCommandList, tout est implicitement indépendant).

Un contexte différé peut également être abandonné explicitement par l’application ou en raison d’une condition d’erreur de l’API ou du pilote. Dans ce cas, le runtime Direct3D effectue la séquence suivante :

  1. Le runtime Direct3D appelle la fonction AbandonCommandList du pilote.

  2. Le runtime annule les handles à partir du contexte différé un par un.

  3. Le runtime « ferme » tous les handles d’objets différés ouverts.

  4. Le runtime recycle ou détruit le contexte différé.

La séquence précédente est similaire à la séquence de destruction d’un contexte immédiat. L’appel à la fonction AbandonCommandList donne l’occasion au pilote d’appliquer l’état selon ses préférences.

Pendant l’appel à la fonction CommandListExecute du pilote, ce dernier doit passer l’état du contexte différé pour le rendre équivalent à l’état de l’appareil lors de sa création. Cette opération est également appelée opération d’état effacé. Lors de l’appel à la fonction CommandListExecute du pilote, toutefois, tous les appels effectués par le pilote aux fonctions de rappel DDI d’actualisation de l’état reflètent toujours l’état de ce qui a été lié pendant le dernier appel DDI à une fonction de pilote. Lors de l’appel DDI suivant à une fonction de pilote, tous les appels effectués par le pilote aux fonctions de rappel DDI d’actualisation de l’état indiquent l’état actuel comme étant complètement vide, ce qui reflète la transition d’état implicite de CommandListExecute. Cela diffère légèrement de la sémantique et du comportement typiques des fonctions de rappel DDI d’actualisation de l’état. Si le pilote avait appelé une fonction de rappel DDI d’actualisation de l’état pendant un appel à l’une des fonctions SetShader du pilote, la fonction de rappel DDI d’actualisation de l’état montrerait comme déjà lié le nouveau nuanceur qui est en train d’être lié. Cette divergence de comportement de rappel DDI d’actualisation de l’état offre plus de flexibilité au pilote pour refléter l’ancien état pendant CommandListExecute.

L’API Direct3D version 11 garantit qu’aucune requête n’a été manipulée (autrement dit, QueryBegin or QueryEnd l’a appelée) par la liste de commandes et n’a été « commencée » que par le contexte qui tente d’exécuter la liste de commandes. L’API garantit également qu’aucune liste de commandes qui a enregistré la carte d’une ressource dynamique n’est exécutée sur un contexte qui a la même ressource actuellement mappée. Avant qu’une application appelle la fonction FinishCommandList, le runtime Direct3D appelle les fonctions DDI QueryEnd et ResourceUnmap du pilote sur toute requête ou ressource dynamique qui contient toujours une requête commencée ou une ressource mappée ouverte, car FinishCommandList met implicitement fin aux plages de requêtes et annule tout mappage de ressource mappée.

Optimisation des listes de commandes de petite taille

Une optimisation du recyclage de la mémoire pour les listes de commandes à faible quantité de mémoire peut s’avérer importante pour réduire la contention entre les appels de fonctions DDI des listes de commandes et pour réduire la surcharge du traitement des appels qui est nécessaire pour ces dernières. La surcharge de traitement inhérente à chaque liste de commandes est importante. Cette optimisation est destinée aux listes de commandes pour lesquelles la charge de traitement requise domine le temps de l’unité centrale et l’espace mémoire requis pour les listes de commandes. Une liste de commandes à faible quantité de mémoire est, par exemple, une seule commande graphique, telle que CopyResource. La quantité de mémoire requise pour CopyResource est deux pointeurs. Toutefois, CopyResource nécessite toujours la même quantité de traitement des appels de liste de commandes qu’une liste de commandes volumineuse en mémoire. Lorsque des listes de commandes à faible quantité de mémoire sont générées selon une fréquence élevée, la surcharge de traitement requise pour l’exécution pour appeler les fonctions CreateCommandList, DestroyCommandList, CreateDeferredContext et DestroyDevice(D3D10) du pilote (pour le contexte différé) devient de plus en plus importante. La mémoire mentionnée ici est la mémoire système qui contient les structures de données du pilote, qui inclut la mémoire des handles DDI.

La fonction RecycleCommandList du pilote doit avertir ce dernier lorsque les handles de pilotes sont obsolètes (mais ne sont pas encore supprimées) et lorsque les handles de pilotes inutilisés précédemment sont réutilisés. Cette notification s’applique à la fois à la liste de commande et aux handles de contexte différé. La seule mémoire que le pilote doit recycler est la mémoire vers laquelle pointe le handle DDI. Bien que l’objectif de RecycleCommandList soit de recycler la mémoire associée au handle, par souci d’efficacité, le pilote dispose d’une flexibilité totale pour choisir la mémoire à recycler. Le pilote ne peut pas modifier la taille de la région de la mémoire vers laquelle pointe le handle de la liste de commandes de contexte immédiat. Cette taille est la valeur de renvoi de CalcPrivateCommandListSize. Le pilote ne peut pas non plus modifier la taille de la région de mémoire vers laquelle pointe le handle local de la liste de commandes de contexte. Cette taille est la valeur de renvoi de CalcDeferredContextHandleSize.

Les fonctions RecycleCreateCommandList et RecycleCreateDeferredContext du pilote doivent renvoyer des codes d’erreur de mémoire insuffisante comme des valeurs E_OUTOFMEMORY HRESULT. Ces fonctions ne fournissent pas de tels codes d’erreur à l’aide d’appels à la fonction pfnSetErrorCb. Cette exigence du pilote évite au runtime de devoir utiliser la synchronisation à l’échelle de l’appareil pour surveiller les erreurs de contexte immédiates provenant de ces fonctions de pilote de type création. La surveillance de ces erreurs constituerait une source de contention catastrophique pour les listes de commandes à faible quantité de mémoire.

Les distinctions entre les fonctions RecycleDestroyCommandList, RecycleCommandList et RecycleCreateCommandList du pilote sont importantes. Leurs fonctionnalités incluent les suivantes.

RecycleDestroyCommandList

Le runtime appelle la fonction RecycleDestroyCommandList du pilote pour l’informer que la destruction légère est requise. Autrement dit, le pilote ne doit pas encore désallouer la mémoire pour le handle de la liste de commandes DDI. La fonction RecycleDestroyCommandList du pilote est libre de threads comme la fonction DestroyCommandList du pilote.

RecycleCommandList

La fonction RecycleCommandList du pilote l’informe que le runtime a intégré un handle de liste de commandes dans le cache de contexte différé. La fonction fournit ensuite au pilote la possibilité d’intégrer la mémoire associée à la liste de commandes dans le cache de contexte différé. Le runtime appelle la fonction RecycleCommandList du pilote à partir du thread de contexte différé. La fonction RecycleCommandList DDI réduit la nécessité pour le pilote d’effectuer sa propre synchronisation.

RecycleCreateCommandList

Le runtime appelle la fonction RecycleCreateCommandList du pilote pour rendre une gestion DDI précédemment inutilisée entièrement valide.

Ces fonctions DDI de recyclage offrent des opportunités d’optimisation pour aider à recycler les ressources pour les listes de commandes à faible quantité de mémoire. Le pseudocode suivant montre l’implémentation du runtime via le flux d’appels de fonction de l’API vers la 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
}

Le schéma d’état suivant montre la validité d’un handle de liste de commandes DDI de contexte immédiat. L’état vert représente un handle qui peut être utilisé avec CommandListExecute.

Schéma illustrant les états de validité d’un handle de liste de commandes DDI de contexte immédiat.