Chargement de données de texture via des mémoires tampons
Le chargement de données de texture 2D ou 3D est similaire au chargement de données 1D, sauf que les applications doivent accorder une attention plus étroite à l’alignement des données liés à l’inclinaison des lignes. Les mémoires tampons peuvent être utilisées de manière orthogonale et simultanée à partir de plusieurs parties du pipeline graphique et sont très flexibles.
- Charger des données de texture via des mémoires tampons
- Copie
- Mappage et démappage
- Alignement de la mémoire tampon
- Rubriques connexes
Charger des données de texture via des mémoires tampons
Les applications doivent charger des données via ID3D12GraphicsCommandList::CopyTextureRegion ou ID3D12GraphicsCommandList::CopyBufferRegion. Les données de texture sont beaucoup plus susceptibles d’être plus volumineuses, d’être consultées à plusieurs reprises et de tirer parti de l’amélioration de la cohérence du cache des dispositions de mémoire non linéaires que d’autres données de ressources. Lorsque les mémoires tampons sont utilisées dans D3D12, les applications disposent d’un contrôle total sur le placement et l’organisation des données associées à la copie des données de ressources, tant que les exigences d’alignement de la mémoire sont satisfaites.
L’exemple met en évidence où l’application aplatit simplement les données 2D en 1D avant de les placer dans la mémoire tampon. Pour le scénario mipmap 2D, l’application peut soit aplatir discrètement et rapidement chaque sous-ressource utiliser un algorithme de sous-allocation 1D, soit utiliser une technique de sous-allocation 2D plus compliquée pour réduire l’utilisation de la mémoire vidéo. La première technique devrait être utilisée plus souvent, car elle est plus simple. La deuxième technique peut être utile lors de l’empaquetage de données sur un disque ou sur un réseau. Dans les deux cas, l’application doit toujours appeler les API de copie pour chaque sous-ressource.
// Prepare a pBitmap in memory, with bitmapWidth, bitmapHeight, and pixel format of DXGI_FORMAT_B8G8R8A8_UNORM.
//
// Sub-allocate from the buffer for texture data.
//
D3D12_SUBRESOURCE_FOOTPRINT pitchedDesc = { 0 };
pitchedDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
pitchedDesc.Width = bitmapWidth;
pitchedDesc.Height = bitmapHeight;
pitchedDesc.Depth = 1;
pitchedDesc.RowPitch = Align(bitmapWidth * sizeof(DWORD), D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
//
// Note that the helper function UpdateSubresource in D3DX12.h, and ID3D12Device::GetCopyableFootprints
// can help applications fill out D3D12_SUBRESOURCE_FOOTPRINT and D3D12_PLACED_SUBRESOURCE_FOOTPRINT structures.
//
// Refer to the D3D12 Code example for the previous section "Uploading Different Types of Resources"
// for the code for SuballocateFromBuffer.
//
SuballocateFromBuffer(
pitchedDesc.Height * pitchedDesc.RowPitch,
D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT
);
D3D12_PLACED_SUBRESOURCE_FOOTPRINT placedTexture2D = { 0 };
placedTexture2D.Offset = m_pDataCur – m_pDataBegin;
placedTexture2D.Footprint = pitchedDesc;
//
// Copy texture data from DWORD* pBitmap->pixels to the buffer
//
for (UINT y = 0; y < bitmapHeight; y++)
{
UINT8 *pScan = m_pDataBegin + placedTexture2D.Offset + y * pitchedDesc.RowPitch;
memcpy( pScan, &(pBitmap->pixels[y * bitmapWidth]), sizeof(DWORD) * bitmapWidth );
}
//
// Create default texture2D resource.
//
D3D12_RESOURCE_DESC textureDesc { ... };
CComPtr<ID3D12Resource> texture2D;
d3dDevice->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
D3D12_HEAP_FLAG_NONE, &textureDesc,
D3D12_RESOURCE_STATE_COPY_DEST,
nullptr,
IID_PPV_ARGS(&texture2D) );
//
// Copy heap data to texture2D.
//
commandList->CopyTextureRegion(
&CD3DX12_TEXTURE_COPY_LOCATION( texture2D, 0 ),
0, 0, 0,
&CD3DX12_TEXTURE_COPY_LOCATION( m_spUploadHeap, placedTexture2D ),
nullptr );
Notez l’utilisation des structures d’assistance CD3DX12_HEAP_PROPERTIES et CD3DX12_TEXTURE_COPY_LOCATION, ainsi que des méthodes CreateCommittedResource et CopyTextureRegion.
Copie
Les méthodes D3D12 permettent aux applications de remplacer D3D11 UpdateSubresource, CopySubresourceRegion et les données initiales des ressources. Une seule valeur de sous-ressource 3D de données de texture principales de ligne peut se trouver dans les ressources de mémoire tampon. CopyTextureRegion peut copier ces données de texture de la mémoire tampon vers une ressource de texture avec une disposition de texture inconnue, et inversement. Les applications doivent préférer ce type de technique pour remplir les ressources GPU fréquemment consultées, en créant des mémoires tampons volumineuses dans un tas DE CHARGEMENT tout en créant les ressources GPU fréquemment consultées dans un tas DEFAULT qui n’a pas d’accès au processeur. Une telle technique prend en charge efficacement les GPU discrets et leurs grandes quantités de mémoire inaccessibles au processeur, sans nuire fréquemment aux architectures UMA.
Notez les deux constantes suivantes :
const UINT D3D12_TEXTURE_DATA_PITCH_ALIGNMENT = 256;
const UINT D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT = 512;
- D3D12_SUBRESOURCE_FOOTPRINT
- D3D12_PLACED_SUBRESOURCE_FOOTPRINT
- D3D12_TEXTURE_COPY_LOCATION
- D3D12_TEXTURE_COPY_TYPE
- ID3D12Device::GetCopyableFootprints
- ID3D12GraphicsCommandList::CopyResource
- ID3D12GraphicsCommandList::CopyTextureRegion
- ID3D12GraphicsCommandList::CopyBufferRegion
- ID3D12GraphicsCommandList::CopyTiles
- ID3D12CommandQueue::UpdateTileMappings
Mappage et démappage
Map et Unmap peuvent être appelés par plusieurs threads en toute sécurité. 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.
Chaque fois que des données sont transmises entre le processeur et le GPU via des ressources dans des tas de lecture différée, Map et Unmap doivent être utilisés pour prendre en charge tous les systèmes sur 3D12. Le fait de garder les plages aussi étroites que possible optimise l’efficacité sur les systèmes qui nécessitent des plages (reportez-vous à D3D12_RANGE).
Les performances des outils de débogage tirent parti non seulement de l’utilisation précise des plages sur tous les / appelsd’annulation de carte, mais également des applications qui démappent les ressources lorsque des modifications du processeur ne sont plus apportées.
La méthode D3D11 d’utilisation de Map (avec le paramètre DISCARD défini) pour renommer des ressources n’est pas prise en charge dans D3D12. Les applications doivent implémenter elles-mêmes le renommage des ressources. Tous les appels de carte sont implicitement NO_OVERWRITE et multithreads. Il incombe à l’application de s’assurer que tout travail GPU pertinent contenu dans les listes de commandes est terminé avant l’accès aux données avec le processeur. Les appels D3D12 à Map ne vident pas implicitement les mémoires tampons de commande et ne bloquent pas l’attente de la fin du travail du GPU. Par conséquent, Map et Unmap peuvent même être optimisés dans certains scénarios.
Alignement de la mémoire tampon
Restrictions d’alignement de la mémoire tampon :
- La copie linéaire de sous-ressources doit être alignée sur 512 octets (avec le pitch de ligne aligné sur D3D12_TEXTURE_DATA_PITCH_ALIGNMENT octets).
- Les lectures de données constantes doivent être un multiple de 256 octets à partir du début du tas (c’est-à-dire uniquement à partir d’adresses alignées sur 256 octets).
- Les lectures de données d’index doivent être un multiple de la taille du type de données d’index (c’est-à-dire uniquement à partir d’adresses naturellement alignées pour les données).
- LES données ID3D12GraphicsCommandList::ExecuteIndirect doivent provenir de décalages qui sont des multiples de 4 (c’est-à-dire uniquement des adresses alignées DWORD).