Dessin indirect

Le dessin indirect permet de transférer une partie du parcours de scène et de l’élimination de l’UC vers le GPU, ce qui permet d’améliorer les performances. La mémoire tampon de commandes peut être générée par le processeur ou le GPU.

Signatures de commande

L’objet de signature de commande (ID3D12CommandSignature) permet aux applications de spécifier un dessin indirect, en particulier en définissant les éléments suivants :

Au démarrage, une application crée un petit ensemble de signatures de commande. Au moment de l’exécution, l’application remplit une mémoire tampon avec des commandes (par le moyen que le développeur d’applications choisit). Les commandes contenant éventuellement l’état à définir pour les vues de mémoire tampon vertex, les vues de mémoire tampon d’index, les constantes racines et les descripteurs racines (SRV/UAV/CBV bruts ou structurés). Ces dispositions d’arguments ne sont pas spécifiques au matériel, afin que les applications puissent générer les mémoires tampons directement. La signature de commande hérite de l’état restant de la liste de commandes. Ensuite, l’application appelle ExecuteIndirect pour indiquer au GPU d’interpréter le contenu de la mémoire tampon d’arguments indirects selon le format défini par une signature de commande particulière.

Si la signature de commande modifie tous les arguments racines, elle est stockée dans la signature de commande en tant que sous-ensemble d’une signature racine.

Aucun état de signature de commande n’est renvoyé à la liste de commandes une fois l’exécution terminée. Cependant, après ExecuteIndirect, toutes les liaisons sont réinitialisées aux valeurs connues. En particulier :

  • Si la signature de commande lie une mémoire tampon vertex à un emplacement particulier, après l’appel à ExecuteIndirect, une mémoire tampon vertex NULL est liée à cet emplacement.
  • Si la signature de commande lie une mémoire tampon d’index, après l’appel à ExecuteIndirect, une mémoire tampon d’index NULL est liée.
  • Si la signature de commande définit une constante racine, après l’appel à ExecuteIndirect, la valeur de la constante racine est définie sur 0.
  • Si la signature de commande définit une vue racine (CBV/SRV/UAV), après l’appel à ExecuteIndirect, la vue racine est définie sur une vue NULL.

Exemple avec les signatures de commande : supposons qu’un développeur d’applications souhaite qu’une constante racine unique soit spécifiée par appel de dessin dans la mémoire tampon d’arguments indirects. L’application crée une signature de commande qui permet à la mémoire tampon d’arguments indirects de spécifier les paramètres suivants par appel de dessin :

  • Valeur d’une constante racine.
  • Arguments de dessin (nombre de vertex, nombre d’instances, etc.).

La mémoire tampon d’arguments indirects générée par l’application contient un tableau d’enregistrements de taille fixe. Chaque structure correspond à un appel de dessin. Chaque structure contient les arguments de dessin et la valeur de la constante racine. Le nombre d’appels de dessin est spécifié dans une mémoire tampon distincte visible par le GPU.

Voici un exemple de mémoire tampon de commandes générée par l’application :

format de mémoire tampon de commandes

Structures de mémoire tampon d’arguments indirects

Les structures suivantes définissent la façon dont des arguments particuliers apparaissent dans une mémoire tampon d’arguments indirects. Ces structures n’apparaissent dans aucune API D3D12. Les applications utilisent ces définitions lors de l’écriture dans une mémoire tampon d’arguments indirects (avec l’UC ou le GPU) :

Création d’une signature de commande

Pour créer une signature de commande, utilisez les éléments d’API suivants :

L’ordre des arguments dans une mémoire tampon d’arguments indirects est défini pour correspondre exactement à l’ordre des arguments spécifié dans le paramètre pArguments de D3D12_COMMAND_SIGNATURE_DESC. Tous les arguments d’un appel de dessin (graphisme)/répartition (calcul) au sein d’une mémoire tampon d’arguments indirects sont intégrés de façon compacte. Toutefois, les applications sont autorisées à spécifier un pas d’octet arbitraire entre les commandes de dessin/répartition dans une mémoire tampon d’arguments indirects.

La signature racine doit être spécifiée si et uniquement si la signature de commande modifie l’un des arguments racines.

Pour le SRV/UAV/CBV racine, l’application spécifie la taille en octets. La couche de débogage valide les restrictions suivantes sur l’adresse :

  • CBV : l’adresse doit être un multiple de 256 octets.
  • SRV/UAV brut : l’adresse doit être un multiple de 4 octets.
  • SRV/UAV structuré : l’adresse doit être un multiple du pas d’octet de structure (déclaré dans le nuanceur).

Une signature de commande donnée est soit un dessin soit une signature de commande de calcul. Si une signature de commande contient une opération de dessin, il s’agit d’une signature de commande graphique. Sinon, la signature de commande doit contenir une opération de répartition, et il s’agit alors d’une signature de commande de calcul.

Les sections suivantes vous montrent quelques exemples de signatures de commande.

Aucun changement d’argument

Dans cet exemple, la mémoire tampon d’arguments indirects générée par l’application contient un tableau de structures de 36 octets. Chaque structure contient uniquement les cinq paramètres passés à DrawIndexedInstanced (plus des caractères de remplissage).

Le code permettant de créer la description de la signature de commande suit :

D3D12_INDIRECT_ARGUMENT_DESC Args[1];
Args[0].Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED;

D3D12_COMMAND_SIGNATURE_DESC ProgramDesc;
ProgramDesc.ByteStride = 36;
ProgramDesc.NumArgumentDescs = 1;
ProgramDesc.pArguments = Args;

La disposition d’une structure unique dans une mémoire tampon d’arguments indirects est la suivante :

Octets Description
0:3 IndexCountPerInstance
4:7 InstanceCount
8:11 StartIndexLocation
12:15 BaseVertexLocation
16:19 StartInstanceLocation
20:35 Remplissage

 

Constantes racines et mémoires tampons vertex

Dans cet exemple, chaque structure d’une mémoire tampon d’arguments indirects modifie deux constantes racines, modifie une liaison de mémoire tampon vertex et effectue une opération de dessin non indexée. Il n’y a pas d’éléments de remplissage entre les structures.

Le code permettant de créer la description de la signature de commande est :

D3D12_INDIRECT_ARGUMENT_DESC Args[4];
Args[0].Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT;
Args[0].Constant.RootParameterIndex = 2;
Args[0].Constant.DestOffsetIn32BitValues = 0;
Args[0].Constant.Num32BitValuesToSet = 1;

Args[1].Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT;
Args[1].Constant.RootParameterIndex = 6;
Args[1].Constant.DestOffsetIn32BitValues = 0;
Args[1].Constant.Num32BitValuesToSet = 1;

Args[2].Type = D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW;
Args[2].VertexBuffer.Slot = 3;

Args[3].Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW;

D3D12_COMMAND_SIGNATURE_DESC ProgramDesc;
ProgramDesc.ByteStride = 40;
ProgramDesc.NumArgumentDescs = 4;
ProgramDesc.pArguments = Args;

La disposition d’une structure unique dans la mémoire tampon d’arguments indirects est la suivante :

Octets Description
0:3 Données pour l’index de paramètres racines 2
4:7 Données pour l’index de paramètres racines 6
8:15 Adresse virtuelle de VB à l’emplacement 3 (64 bits)
16:19 Taille de VB
20:23 Pas de VB
24:27 VertexCountPerInstance
28:31 InstanceCount
32:35 StartVertexLocation
36:39 StartInstanceLocation

 

Tutoriels vidéo sur l’apprentissage avancé DirectX : Exécuter l’élimination GPU indirecte et asynchrone

Dessin indirect et élimination GPU : parcours pas à pas du code

Rendu