Dessin indirect

Le dessin indirect permet de déplacer certaines scènes de traversée et d’élimination de l’UC vers le GPU, ce qui peut 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 le dessin indirect, en définissant notamment 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 biais de tout moyen choisi par le développeur de l’application). Les commandes contiennent éventuellement l’état à définir pour les vues de mémoire tampon de vertex, les vues de mémoire tampon d’index, les constantes racines et les descripteurs racine (SRV/UAV/CBV bruts ou structurés). Ces dispositions d’arguments ne sont pas spécifiques au matériel, de sorte que les applications peuvent 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 en fonction du format défini par une signature de commande particulière.

Si la signature de commande change des arguments racine, celle-ci est stockée dans la signature de commande en tant que sous-ensemble d’une signature racine.

Notez qu’aucun état de signature de commande ne revient à la liste des commandes une fois l’exécution terminée.

Par exemple, supposons qu’un développeur d’applications souhaite qu’une constante racine unique soit spécifiée par appel par 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.
  • Les arguments de dessin (nombre de vertex, nombre de instance, etc.).

La mémoire tampon d’arguments indirecte 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 GPU.

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

Format de la 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 indirecte (avec le processeur ou le GPU) :

Création d’une signature de commande

Pour créer une signature de commande, utilisez les éléments 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 (graphique)/dispatch (calcul) au sein d’une mémoire tampon d’arguments indirectes sont étroitement compressés. Toutefois, les applications sont autorisées à spécifier une foulée d’octets arbitraire entre les commandes draw/dispatch dans une mémoire tampon d’arguments indirecte.

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

Pour SRV/UAV/CBV racine, la taille spécifiée par l’application est 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 de la foulée d’octets de structure (déclaré dans le nuanceur).

Une signature de commande donnée est un dessin ou 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 d’une signature de commande de calcul.

Les sections suivantes présentent quelques exemples de signatures de commande.

Aucune modification d’argument

Dans cet exemple, la mémoire tampon d’argument indirect 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 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’argument indirect 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 de vertex

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

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

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ètre racine 2
4:7 Données pour l’index de paramètre racine 6
8:15 Adresse virtuelle de VB à l’emplacement 3 (64 bits)
16:19 Taille vb
20:23 Stride 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 de GPU indirect et asynchrone

Dessin indirect et élimination GPU : procédure pas à pas du code

Rendu