Comment utiliser UpdateSubresource et Map / Unmap?

8

D'après ce que j'ai compris (en lisant différentes pages), il y a 2 façons de mettre à jour un tampon:

  1. UpdateSubresource()(lorsque le tampon est créé avec DEFAULTutilisation)
  2. Map(), copiez les nouvelles données, Unmap()(lorsque le tampon est créé avec DYNAMICutilisation)

Dans le premier cas, est-ce que j'appelle uniquement cette fonction (rien de plus)? Parce que j'ai vu des gens dire qu'ils mappent le tampon puis mettent à jour la sous-ressource, ou peut-être que je les ai mal compris.

Y a-t-il également un autre moyen (en douter: P)? Dois-je bien comprendre les choses?

NPS
la source

Réponses:

11

Il y a une bonne présentation à ce sujet: Don't Throw It All Away: Efficient Buffer Management par John McDonald chez NVIDIA. Il couvre divers sujets, mais au sujet de votre question, le conseil général est de créer des tampons à usage dynamique et à utiliser Map()avec D3D11_MAP_WRITE_DISCARD, lorsque les données doivent être mises à jour fréquemment (comme chaque trame, ou plusieurs fois par trame). Cela serait utilisé pour les tampons constants, les tampons de vertex pour les systèmes de particules, etc.

Selon la présentation, l'utilisation par défaut / UpdateSubresource()entraîne plus de surcharge CPU que l'utilisation dynamique / Map(). Cependant, il recommande l'utilisation par défaut / UpdateSubresource()pour les données qui ne doivent être mises à jour qu'une fois de temps en temps, telles que les données diffusées depuis le disque dans un jeu en monde ouvert.

Et oui, dans le cas où vous l'utilisez UpdateSubresource(), vous l'utiliseriez seul, pas en combinaison avec Map().

Nathan Reed
la source
2
Curieusement, vous avez tous deux répondu dans la même minute et publié le même lien.
NPS
Dans un autre thread, vous avez écrit: "Vous n'avez pas besoin de lier le tampon pour le mettre à jour avec UpdateSubresource. En fait, il ne devrait pas être lié lorsque vous le mettez à jour". Est-ce à dire que je devrais toujours dissocier tous les tampons avant de les mettre à jour? Si oui, comment puis-je dissocier un tampon?
NPS
1
@NPS Tout d'abord, il sera implicitement non lié si vous avez déjà lié autre chose à sa place. Sinon, vous pouvez lier explicitement NULL pour dissocier un tampon. Par exemple, vous pouvez faire ID3D11ShaderResourceView * nullsrv = NULL; pCtx->PSSetShaderResources(0, 1, &nullsrv);pour délier une texture de l'emplacement 0.
Nathan Reed
Je connaissais l'implicite mais j'avais besoin de l'explicite, thx. Mais vous n'avez pas répondu à ma première question - dois-je le faire toujours pour tous les tampons que je voulais mettre à jour?
NPS
1
@NPS Idéalement, le tampon ne devrait pas être utilisé par le GPU au moment où vous le mettez à jour sur le CPU. Mais le GPU et le CPU fonctionnent de manière asynchrone, ce n'est donc pas facile à garantir. Je dirais ne vous inquiétez pas à moins que vous ne trouviez que c'est un problème de performance réel.
Nathan Reed
2

Ils peuvent faire référence à l'acte réel de mise à jour d'une ressource et non à l'appel de fonction réel. En général, UpdateSubResource doit être utilisé pour les ressources par défaut qui ne sont pas soumises à des mises à jour fréquentes (c'est-à-dire pas toutes les trames. Dans ce cas, il est plus probable que le tampon puisse être copié dans un tampon temporaire accessible à partir du tampon de commande ( en raison des conditions de course par exemple.) Il vous permettra également la mise à jour des sous ressources (dans les textures, par exemple).

Map / Unmap doit être utilisé lorsqu'une ressource va être mise à jour très fréquemment (c'est-à-dire chaque trame), comme certains tampons constants. Le cas le plus courant est lorsque vous écrasez tout le tampon avec WriteDiscard. Il y a une présentation nVidia où ils recommandent cette pratique.

Le vagabond
la source