Condividi tramite


Caricamento dei dati delle trame tramite buffer

Il caricamento di dati di trama 2D o 3D è simile al caricamento di dati 1D, ad eccezione del fatto che le applicazioni devono prestare maggiore attenzione all'allineamento dei dati correlato all'inclinazione delle righe. I buffer possono essere usati in modo ortogonale e simultaneo da più parti della pipeline grafica e sono molto flessibili.

Caricare i dati delle trame tramite buffer

Le applicazioni devono caricare dati tramite ID3D12GraphicsCommandList::CopyTextureRegion o ID3D12GraphicsCommandList::CopyBufferRegion. È molto più probabile che i dati delle trame siano più grandi, a cui si accede ripetutamente e traggono vantaggio dalla migliore coerenza della cache dei layout di memoria non lineari rispetto ad altri dati delle risorse. Quando i buffer vengono usati in D3D12, le applicazioni hanno il controllo completo sul posizionamento dei dati e sulla disposizione associati alla copia dei dati delle risorse, purché vengano soddisfatti i requisiti di allineamento della memoria.

L'esempio evidenzia dove l'applicazione semplicemente rende flat i dati 2D in 1D prima di inserirli nel buffer. Per lo scenario mipmap 2D, l'applicazione può rendere flat ogni risorsa secondaria in modo discreto e usare rapidamente un algoritmo di allocazione secondaria 1D oppure usare una tecnica di allocazione secondaria 2D più complessa per ridurre al minimo l'utilizzo della memoria video. Si prevede che la prima tecnica venga usata più spesso perché è più semplice. La seconda tecnica può essere utile durante la compressione dei dati in un disco o in una rete. In entrambi i casi, l'applicazione deve comunque chiamare le API di copia per ogni risorsa secondaria.

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

Si noti l'uso delle strutture helper CD3DX12_HEAP_PROPERTIES e CD3DX12_TEXTURE_COPY_LOCATION e dei metodi CreateCommittedResource e CopyTextureRegion.

asincrona

I metodi D3D12 consentono alle applicazioni di sostituire D3D11 UpdateSubresource, CopySubresourceRegion e i dati iniziali delle risorse. Una singola sottorisorsa 3D vale la pena di dati di trama principali delle righe può trovarsi nelle risorse del buffer. CopyTextureRegion può copiare i dati della trama dal buffer a una risorsa trama con un layout di trama sconosciuto e viceversa. Le applicazioni devono preferire questo tipo di tecnica per popolare le risorse GPU a cui si accede di frequente, creando buffer di grandi dimensioni in un heap UPLOAD durante la creazione delle risorse GPU a cui si accede di frequente in un heap DEFAULT senza accesso alla CPU. Una tecnica di questo tipo supporta in modo efficiente GPU discrete e grandi quantità di memoria inaccessibile della CPU, senza compromettere in genere le architetture UMA.

Si notino le due costanti seguenti:

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

Mapping e annullamento del mapping

Map e Unmap possono essere chiamati da più thread in modo sicuro. La prima chiamata a Map alloca un intervallo di indirizzi virtuali della CPU per la risorsa. L'ultima chiamata a Unmap dealloca l'intervallo di indirizzi virtuali della CPU. L'indirizzo virtuale della CPU viene in genere restituito all'applicazione.

Ogni volta che i dati vengono passati tra la CPU e la GPU tramite le risorse negli heap di readback, è necessario usare Mapping e Unmap per supportare tutti i sistemi D3D12 su cui è supportato. Mantenere gli intervalli il più stretto possibile ottimizza l'efficienza nei sistemi che richiedono intervalli (fare riferimento a D3D12_RANGE).

Le prestazioni degli strumenti di debug traggono vantaggio non solo dall'utilizzo accurato degli intervalli in tutte le / chiamate mappa nonmappate, ma anche dalle applicazioni che annullano il mapping delle risorse quando le modifiche della CPU non verranno più apportate.

Il metodo D3D11 dell'uso di Map (con il set di parametri DISCARD) per rinominare le risorse non è supportato in D3D12. Le applicazioni devono implementare la ridenominazione delle risorse. Tutte le chiamate mappa vengono NO_OVERWRITE in modo implicito e multithreading. È responsabilità dell'applicazione assicurarsi che qualsiasi lavoro GPU pertinente contenuto negli elenchi di comandi venga completato prima dell'accesso ai dati con la CPU. Le chiamate D3D12 a Map non scaricano in modo implicito alcun buffer dei comandi, né bloccano l'attesa del lavoro della GPU. Di conseguenza, map e unmap possono anche essere ottimizzati in alcuni scenari.

Allineamento del buffer

Restrizioni di allineamento del buffer:

  • La copia di sottorisorse lineari deve essere allineata a 512 byte (con l'inclinazione della riga allineata a D3D12_TEXTURE_DATA_PITCH_ALIGNMENT byte).
  • Le letture dei dati costanti devono essere un multiplo di 256 byte dall'inizio dell'heap ,ad esempio solo da indirizzi allineati a 256 byte.
  • Le letture dei dati dell'indice devono essere un multiplo delle dimensioni del tipo di dati dell'indice, ad esempio solo da indirizzi allineati naturalmente per i dati.
  • I dati ID3D12GraphicsCommandList::ExecuteIndirect devono essere costituiti da offset multipli di 4 (ad esempio solo da indirizzi allineati con DWORD).