Freigeben über


Hochladen von Texturdaten über Puffer

Das Hochladen von 2D- oder 3D-Texturdaten ähnelt dem Hochladen von 1D-Daten, mit der Ausnahme, dass Anwendungen die Datenausrichtung im Zusammenhang mit der Zeilenhöhe stärker beachten müssen. Puffer können orthogonal und gleichzeitig aus mehreren Teilen der Grafikpipeline verwendet werden und sind sehr flexibel.

Hochladen von Texturdaten über Puffer

Anwendungen müssen Daten über ID3D12GraphicsCommandList::CopyTextureRegion oder ID3D12GraphicsCommandList::CopyBufferRegion hochladen. Texturdaten sind viel wahrscheinlicher größer, greifen wiederholt zu und profitieren von der verbesserten Cachekohärenz nichtlinearer Speicherlayouts als andere Ressourcendaten. Wenn Puffer in D3D12 verwendet werden, haben Anwendungen die vollständige Kontrolle über die Datenplatzierung und -anordnung im Zusammenhang mit dem Kopieren von Ressourcendaten, solange die Speicherausrichtungsanforderungen erfüllt sind.

Das Beispiel zeigt, wo die Anwendung 2D-Daten einfach in 1D vereinfacht, bevor sie im Puffer platziert werden. Für das mipmap 2D-Szenario kann die Anwendung entweder jede Unterressource diskret und schnell mit einem 1D-Unterzuordnungsalgorithmus vereinfachen oder eine kompliziertere 2D-Unterzuordnungsmethode verwenden, um die Auslastung des Videospeichers zu minimieren. Es wird erwartet, dass die erste Technik häufiger verwendet wird, da sie einfacher ist. Die zweite Technik kann beim Packen von Daten auf einen Datenträger oder über ein Netzwerk nützlich sein. In beiden Fällen muss die Anwendung weiterhin die Kopier-APIs für jede Unterressource aufrufen.

// 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 );

Beachten Sie die Verwendung der Hilfsstrukturen CD3DX12_HEAP_PROPERTIES und CD3DX12_TEXTURE_COPY_LOCATION sowie der Methoden CreateCommittedResource und CopyTextureRegion.

Wird kopiert

D3D12-Methoden ermöglichen Es Anwendungen, D3D11 UpdateSubresource, CopySubresourceRegion und Ressourcenanfangsdaten zu ersetzen. Eine einzelne 3D-Unterressource von Zeilen-Haupttexturdaten kann sich in Pufferressourcen befinden. CopyTextureRegion kann diese Texturdaten aus dem Puffer in eine Texturressource mit einem unbekannten Texturlayout kopieren und umgekehrt. Anwendungen sollten diese Art von Technik bevorzugen, um häufig verwendete GPU-Ressourcen aufzufüllen, indem sie große Puffer in einem UPLOAD-Heap erstellen, während die häufig verwendeten GPU-Ressourcen in einem DEFAULT-Heap ohne CPU-Zugriff erstellt werden. Eine solche Technik unterstützt effizient diskrete GPUs und deren große Mengen an CPU-nicht zugänglichem Arbeitsspeicher, ohne dass UMA-Architekturen häufig beeinträchtigt werden.

Beachten Sie die folgenden beiden Konstanten:

const UINT D3D12_TEXTURE_DATA_PITCH_ALIGNMENT = 256;
const UINT D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT = 512;

Zuordnung und Aufheben der Zuordnung

Map und Unmap können von mehreren Threads sicher aufgerufen werden. Der erste Aufruf von Map ordnet der Ressource einen virtuellen CPU-Adressbereich zu. Durch den letzten Aufruf von Unmap wird die Zuordnung des virtuellen CPU-Adressbereichs aufgehoben. Die virtuelle CPU-Adresse wird häufig an die Anwendung zurückgegeben.

Wenn Daten zwischen CPU und GPU über Ressourcen in Readback-Heaps übergeben werden, müssen Map und Unmap verwendet werden, um alle Systeme zu unterstützen, auf die D3D12 unterstützt wird. Wenn Sie die Bereiche so eng wie möglich halten, wird die Effizienz der Systeme maximiert, die Bereiche benötigen (siehe D3D12_RANGE).

Die Leistung von Debugtools profitiert nicht nur von der genauen Verwendung von Bereichen bei allen Map / Unmap-Aufrufen , sondern auch von Anwendungen, die Ressourcen aufheben, wenn keine CPU-Änderungen mehr vorgenommen werden.

Die D3D11-Methode zur Verwendung von Map (mit festgelegtem DISCARD-Parameter) zum Umbenennen von Ressourcen wird in D3D12 nicht unterstützt. Anwendungen müssen die Ressourcenumbenennung selbst implementieren. Alle Zuordnungsaufrufe werden implizit NO_OVERWRITE und Multithreads ausgeführt. Es liegt in der Verantwortung der Anwendung sicherzustellen, dass alle relevanten GPU-Aufgaben, die in Befehlslisten enthalten sind, abgeschlossen werden, bevor der Zugriff auf Daten mit der CPU erfolgt. D3D12-Aufrufe von Map leeren weder implizit Befehlspuffer, noch blockieren sie, bis die GPU die Arbeit abgeschlossen hat. Daher können Map und Unmap in einigen Szenarien sogar optimiert werden.

Pufferausrichtung

Pufferausrichtungseinschränkungen:

  • Lineares Kopieren von Unterressourcen muss auf 512 Bytes ausgerichtet sein (wobei der Zeilenabstand an D3D12_TEXTURE_DATA_PITCH_ALIGNMENT Bytes ausgerichtet ist).
  • Konstante Datenlesevorgänge müssen ein Vielfaches von 256 Bytes vom Anfang des Heaps sein (d. h. nur von Adressen, die 256 Byte ausgerichtet sind).
  • Indexdatenlesungen müssen ein Vielfaches der Indexdatentypgröße aufweisen (d. h. nur von Adressen, die natürlich für die Daten ausgerichtet sind).
  • ID3D12GraphicsCommandList::ExecuteIndirect-Daten müssen aus Offsets stammen, die ein Vielfaches von 4 sind (d.h. nur von Adressen, die DWORD ausgerichtet sind).