Método ID3D12Resource::Map (d3d12.h)

Obtiene un puntero de CPU al subrecurso especificado en el recurso, pero no puede revelar el valor de puntero a las aplicaciones. La asignación también invalida la memoria caché de CPU, cuando sea necesario, para que las lecturas de CPU en esta dirección reflejen las modificaciones realizadas por la GPU.

Sintaxis

HRESULT Map(
                  UINT              Subresource,
  [in, optional]  const D3D12_RANGE *pReadRange,
  [out, optional] void              **ppData
);

Parámetros

Subresource

Tipo: UINT

Especifica el número de índice del subrecurso.

[in, optional] pReadRange

Tipo: const D3D12_RANGE*

Puntero a una estructura de D3D12_RANGE que describe el intervalo de memoria al que se va a acceder.

Esto indica la región que la CPU podría leer y las coordenadas son relativas al subrecurso. Un puntero nulo indica que la CPU podría leer todo el subrecurso. Es válido especificar que la CPU no leerá ningún dato pasando un intervalo donde End es menor o igual que Begin.

[out, optional] ppData

Tipo: void**

Puntero a un bloque de memoria que recibe un puntero a los datos del recurso.

Un puntero nulo es válido y es útil almacenar en caché un intervalo de direcciones virtuales de CPU para métodos como WriteToSubresource. Cuando ppData no es NULL, el puntero devuelto nunca se desplaza por ningún valor de pReadRange.

Valor devuelto

Tipo: HRESULT

Este método devuelve uno de los códigos de retorno de Direct3D 12.

Comentarios

Varios subprocesos pueden llamar a map y Unmap de forma segura. Se admiten las llamadas de mapa anidadas y se cuentan con referencias. 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. La dirección virtual de CPU se devuelve normalmente a la aplicación; pero manipular el contenido de las texturas con diseños desconocidos impide revelar la dirección virtual de cpu. Consulte WriteToSubresource para obtener más detalles. Las aplicaciones no pueden confiar en que la dirección sea coherente, a menos que map esté anidada de forma persistente.

No se garantiza que los punteros devueltos por Map tengan todas las funcionalidades de punteros normales, pero la mayoría de las aplicaciones no observarán una diferencia en el uso normal. Por ejemplo, los punteros con WRITE_COMBINE comportamiento tienen garantías de ordenación de memoria de CPU más débiles que WRITE_BACK comportamiento. No se garantiza que la memoria accesible tanto por CPU como por GPU compartan las mismas garantías de memoria atómica que tiene la CPU, debido a las limitaciones de PCIe. Use barreras para la sincronización.

Hay dos categorías de modelo de uso para Mapa, simple y avanzado. Los modelos de uso simples maximizan el rendimiento de las herramientas, por lo que se recomienda que las aplicaciones se ajusten a los modelos simples hasta que la aplicación demuestre que los modelos avanzados son necesarios.

Modelos de uso simples

Las aplicaciones deben ajustarse a las abstracciones de tipo montón de UPLOAD, DEFAULT y READBACK, con el fin de admitir todas las arquitecturas de adaptadores razonablemente bien.

Las aplicaciones deben evitar lecturas de CPU de punteros a recursos en montones de carga, incluso accidentalmente. Las lecturas de CPU funcionarán, pero son prohibitivamente lentas en muchas arquitecturas de GPU comunes, por lo que tenga en cuenta lo siguiente:

  • No haga que la CPU lea de los recursos asociados a montones que están D3D12_HEAP_TYPE_UPLOAD o que tienen D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE.
  • La región de memoria a la que se pueden asignar puntos pData con PAGE_WRITECOMBINE y la aplicación debe respetar todas las restricciones asociadas a dicha memoria.
  • Incluso el siguiente código de C++ puede leer de la memoria y desencadenar la penalización de rendimiento porque el código puede expandirse al siguiente código de ensamblado x86.

    Código de C++:

    *((int*)MappedResource.pData) = 0;
    

    Código de ensamblado x86:

    AND DWORD PTR [EAX],0
    
  • Use la configuración de optimización y las construcciones de lenguaje adecuadas para ayudar a evitar esta penalización de rendimiento. Por ejemplo, puede evitar la optimización de xor mediante un puntero volátil o mediante la optimización de la velocidad del código en lugar del tamaño del código.
Se recomienda a las aplicaciones dejar los recursos sin asignar, mientras que la CPU no los modificará y use intervalos estrictos y precisos en todo momento. Esto permite los modos más rápidos para las herramientas, como la depuración de gráficos y la capa de depuración. Estas herramientas deben realizar un seguimiento de todas las modificaciones de CPU en la memoria que la GPU podría leer.

Modelos de uso avanzado

Los recursos de los montones accesibles para cpu se pueden asignar de forma persistente, lo que significa que se puede llamar a Map una vez, inmediatamente después de la creación de recursos. Nunca es necesario llamar a un mapa, pero la dirección devuelta de Map ya no se debe usar después de que se libere la última referencia al recurso. Al usar la asignación persistente, la aplicación debe asegurarse de que la CPU termina de escribir datos en la memoria antes de que la GPU ejecute una lista de comandos que lea o escriba la memoria. En escenarios comunes, la aplicación simplemente debe escribir en memoria antes de llamar a ExecuteCommandLists; pero el uso de una barrera para retrasar la ejecución de la lista de comandos también funciona.

Todos los tipos de memoria accesibles para cpu admiten el uso de asignación persistente, donde el recurso se asigna pero, a continuación, nunca se desasigna, siempre que la aplicación no tenga acceso al puntero después de que se haya eliminado el recurso.

Ejemplos

El ejemplo D3D12Bundles usa ID3D12Resource::Map de la siguiente manera:

Copie los datos del triángulo en el búfer de vértices.

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

Cree un montón de carga para los búferes de 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)));

Consulte el código de ejemplo en la referencia de D3D12.

Requisitos

Requisito Value
Plataforma de destino Windows
Encabezado d3d12.h
Library D3D12.lib
Archivo DLL D3D12.dll

Consulte también

ID3D12Resource

Subrecursos

Unmap