ID3D12Resource ::Map, méthode (d3d12.h)
Obtient un pointeur processeur vers la sous-ressource spécifiée dans la ressource, mais peut ne pas divulguer la valeur du pointeur aux applications. La carte invalide également le cache du processeur, si nécessaire, afin que les lectures du processeur à cette adresse reflètent toutes les modifications apportées par le GPU.
Syntaxe
HRESULT Map(
UINT Subresource,
[in, optional] const D3D12_RANGE *pReadRange,
[out, optional] void **ppData
);
Paramètres
Subresource
Type : UINT
Spécifie le numéro d’index de la sous-ressource.
[in, optional] pReadRange
Type : const D3D12_RANGE*
Pointeur vers une structure de D3D12_RANGE qui décrit la plage de mémoire à accéder.
Cela indique la région que le processeur peut lire, et les coordonnées sont sous-relatives aux ressources. Un pointeur null indique que la sous-ressource entière peut être lue par le processeur. Il est valide de spécifier que le processeur ne lit aucune donnée en passant une plage où End est inférieur ou égal à Begin.
[out, optional] ppData
Type : void**
Pointeur vers un bloc de mémoire qui reçoit un pointeur vers les données de ressource.
Un pointeur null est valide et est utile pour mettre en cache une plage d’adresses virtuelles du processeur pour des méthodes telles que WriteToSubresource. Lorsque ppData n’a pas la valeur NULL, le pointeur retourné n’est jamais décalé par les valeurs de pReadRange.
Valeur retournée
Type : HRESULT
Cette méthode retourne l’un des codes de retour Direct3D 12.
Remarques
Map et Unmap peuvent être appelés par plusieurs threads en toute sécurité. Les appels de carte imbriqués sont pris en charge et sont comptabilisés dans les références. Le premier appel à mapper alloue une plage d’adresses virtuelles du processeur pour la ressource. Le dernier appel à Unmap libère la plage d’adresses virtuelles du processeur. L’adresse virtuelle du processeur est généralement retournée à l’application ; mais la manipulation du contenu des textures avec des dispositions inconnues empêche la divulgation de l’adresse virtuelle du processeur. Pour plus d’informations, consultez WriteToSubresource . Les applications ne peuvent pas compter sur la cohérence de l’adresse, sauf si Map est imbriquée de manière permanente.
Les pointeurs retournés par Map ne sont pas garantis d’avoir toutes les fonctionnalités des pointeurs normaux, mais la plupart des applications ne remarquent pas de différence dans l’utilisation normale. Par exemple, les pointeurs avec un comportement WRITE_COMBINE ont des garanties de classement de mémoire processeur plus faibles que WRITE_BACK comportement. La mémoire accessible à la fois par l’UC et le GPU ne sont pas garanties pour partager les mêmes garanties de mémoire atomique que le processeur, en raison des limitations PCIe. Utilisez des clôtures pour la synchronisation.
Il existe deux catégories de modèles d’utilisation pour Map : simple et avancé. Les modèles d’utilisation simples optimisent les performances des outils. Il est donc recommandé aux applications de s’en tenir aux modèles simples jusqu’à ce que les modèles avancés soient requis par l’application.
Modèles d’utilisation simples
Les applications doivent s’en tenir aux abstractions de type tas de UPLOAD, DEFAULT et READBACK, afin de prendre en charge raisonnablement bien toutes les architectures d’adaptateurs.Les applications doivent éviter les lectures du processeur des pointeurs vers les ressources sur les tas de chargement, même accidentellement. Les lectures du processeur fonctionnent, mais sont excessivement lentes sur de nombreuses architectures GPU courantes. Tenez donc compte des points suivants :
- Ne faites pas lire le processeur à partir de ressources associées à des tas qui sont D3D12_HEAP_TYPE_UPLOAD ou qui ont D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE.
- La région de mémoire à laquelle les points pData peuvent être alloués avec PAGE_WRITECOMBINE, et votre application doit respecter toutes les restrictions associées à cette mémoire.
-
Même le code C++ suivant peut lire à partir de la mémoire et déclencher une pénalité de performances, car le code peut s’étendre au code d’assembly x86 suivant.
Code C++ :
*((int*)MappedResource.pData) = 0;
Code d’assembly x86 :
AND DWORD PTR [EAX],0
- Utilisez les paramètres d’optimisation et les constructions linguistiques appropriés pour éviter cette pénalité de performances. Par exemple, vous pouvez éviter l’optimisation xor à l’aide d’un pointeur volatile ou en optimisant la vitesse du code au lieu de la taille du code.
Modèles d’utilisation avancés
Les ressources sur les tas accessibles par le processeur peuvent être mappées de manière permanente, ce qui signifie que Map peut être appelé une seule fois, immédiatement après la création de la ressource. Unmap n’a jamais besoin d’être appelé, mais l’adresse renvoyée par Map ne doit plus être utilisée après la publication de la dernière référence à la ressource. Lors de l’utilisation d’une carte persistante, l’application doit s’assurer que le processeur termine l’écriture des données dans la mémoire avant que le GPU exécute une liste de commandes qui lit ou écrit la mémoire. Dans les scénarios courants, l’application doit simplement écrire en mémoire avant d’appeler ExecuteCommandLists ; mais l’utilisation d’une clôture pour retarder l’exécution de la liste de commandes fonctionne également.Tous les types de mémoire accessibles au processeur prennent en charge l’utilisation permanente du mappage, où la ressource est mappée mais jamais démaquée, à condition que l’application n’accède pas au pointeur une fois la ressource supprimée.
Exemples
L’exemple D3D12Bundles utilise ID3D12Resource ::Map comme suit :
Copiez les données du triangle dans la mémoire tampon de vertex.
// Copy the triangle data to the vertex buffer.
UINT8* pVertexDataBegin;
CD3DX12_RANGE readRange(0, 0); // We do not intend to read from this resource on the CPU.
ThrowIfFailed(m_vertexBuffer->Map(0, &readRange, reinterpret_cast<void**>(&pVertexDataBegin)));
memcpy(pVertexDataBegin, triangleVertices, sizeof(triangleVertices));
m_vertexBuffer->Unmap(0, nullptr);
Créez un tas de chargement pour les mémoires tampons constantes.
// Create an upload heap for the constant buffers.
ThrowIfFailed(pDevice->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC::Buffer(sizeof(ConstantBuffer) * m_cityRowCount * m_cityColumnCount),
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr,
IID_PPV_ARGS(&m_cbvUploadHeap)));
// Map the constant buffers. Note that unlike D3D11, the resource
// does not need to be unmapped for use by the GPU. In this sample,
// the resource stays 'permanently' mapped to avoid overhead with
// mapping/unmapping each frame.
CD3DX12_RANGE readRange(0, 0); // We do not intend to read from this resource on the CPU.
ThrowIfFailed(m_cbvUploadHeap->Map(0, &readRange, reinterpret_cast<void**>(&m_pConstantBuffers)));
Reportez-vous à l’exemple de code dans la référence D3D12.
Configuration requise
Condition requise | Valeur |
---|---|
Plateforme cible | Windows |
En-tête | d3d12.h |
Bibliothèque | D3D12.lib |
DLL | D3D12.dll |