Compartir a través de


Carga de datos de textura a través de búferes

Cargar datos de textura 2D o 3D es similar a cargar datos 1D, excepto que las aplicaciones necesitan prestar más atención a la alineación de datos relacionada con el tono de fila. Los búferes se pueden usar ortogonalmente y simultáneamente desde varias partes de la canalización de gráficos, y son muy flexibles.

Carga de datos de textura a través de búferes

Las aplicaciones deben cargar datos a través de ID3D12GraphicsCommandList::CopyTextureRegion o ID3D12GraphicsCommandList::CopyBufferRegion. Es mucho más probable que los datos de textura sean más grandes, a los que se accede repetidamente y se beneficien de la coherencia mejorada de la caché de diseños de memoria no lineales que otros datos de recursos. Cuando se usan búferes en D3D12, las aplicaciones tienen control total sobre la selección de ubicación de datos y la disposición asociadas a la copia de datos de recursos, siempre y cuando se cumplan los requisitos de alineación de memoria.

En el ejemplo se resalta dónde la aplicación simplemente aplana los datos 2D en 1D antes de colocarlos en el búfer. Para el escenario mipmap 2D, la aplicación puede aplanar cada subrecurso discretamente y usar rápidamente un algoritmo de asignación secundaria 1D, o bien usar una técnica de asignación secundaria 2D más complicada para minimizar el uso de memoria de vídeo. Se espera que la primera técnica se use con más frecuencia, ya que es más sencilla. La segunda técnica puede ser útil al empaquetar datos en un disco o a través de una red. En cualquier caso, la aplicación todavía debe llamar a las API de copia para cada subrecurso.

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

Tenga en cuenta el uso de las estructuras auxiliares CD3DX12_HEAP_PROPERTIES y CD3DX12_TEXTURE_COPY_LOCATION, y los métodos CreateCommittedResource y CopyTextureRegion.

asincrónica

Los métodos D3D12 permiten a las aplicaciones reemplazar los datos iniciales de D3D11 UpdateSubresource, CopySubresourceRegion y resource. Un único subrecurso 3D de datos de textura principal de fila puede encontrarse en recursos de búfer. CopyTextureRegion puede copiar esos datos de textura del búfer en un recurso de textura con un diseño de textura desconocido y viceversa. Las aplicaciones deben preferir este tipo de técnica para rellenar los recursos de GPU a los que se accede con frecuencia, mediante la creación de búferes grandes en un montón de carga mientras se crean los recursos de GPU a los que se accede con frecuencia en un montón PREDETERMINADO que no tiene acceso a la CPU. Esta técnica admite eficazmente GPU discretas y sus grandes cantidades de memoria inaccesible de CPU, sin afectar normalmente a las arquitecturas de UMA.

Tenga en cuenta las dos constantes siguientes:

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

Asignación y desasignación

Varios subprocesos pueden llamar a map y Unmap de forma segura. La primera llamada a Map asigna un intervalo de direcciones virtuales de CPU para el recurso. La última llamada a Desasignar desasigna el intervalo de direcciones virtuales de CPU. Normalmente, la dirección virtual de CPU se devuelve a la aplicación.

Cada vez que se pasan datos entre la CPU y la GPU a través de recursos en montones de lectura diferida, se debe usar Map y Unmap para admitir todos los sistemas en los que se admite D3D12. Mantener los intervalos lo más ajustados posible maximiza la eficiencia en los sistemas que requieren rangos (consulte D3D12_RANGE).

El rendimiento de las herramientas de depuración se beneficia no solo del uso preciso de intervalos en todas las llamadasunmap de mapa / , sino también de las aplicaciones que no asignan recursos cuando ya no se realicen modificaciones de CPU.

El método D3D11 de usar Map (con el parámetro DISCARD establecido) para cambiar el nombre de los recursos no se admite en D3D12. Las aplicaciones deben implementar el cambio de nombre de los propios recursos. Todas las llamadas de asignación se NO_OVERWRITE implícitamente y multiproceso. Es responsabilidad de la aplicación asegurarse de que cualquier trabajo de GPU pertinente contenido en las listas de comandos finalice antes de que los datos de acceso con la CPU. Las llamadas D3D12 a Map no vacían implícitamente ningún búfer de comandos ni bloquean la espera de que la GPU finalice el trabajo. Como resultado, laasignación y el desasignación pueden incluso optimizarse en algunos escenarios.

Alineación del búfer

Restricciones de alineación del búfer:

  • La copia lineal de subrecursos debe estar alineada a 512 bytes (con el tono de fila alineado con D3D12_TEXTURE_DATA_PITCH_ALIGNMENT bytes).
  • Las lecturas de datos constantes deben ser un múltiplo de 256 bytes desde el principio del montón (es decir, solo desde direcciones alineadas de 256 bytes).
  • Las lecturas de datos de índice deben ser un múltiplo del tamaño del tipo de datos de índice (es decir, solo las direcciones que están alineadas de forma natural para los datos).
  • Los datos ID3D12GraphicsCommandList::ExecuteIndirect deben estar a partir de desplazamientos que sean múltiplos de 4 (es decir, solo de las direcciones que están alineadas con DWORD).