ID3D12Resource::Map-Methode (d3d12.h)

Ruft einen CPU-Zeiger auf die angegebene Unterressource in der Ressource ab, gibt den Zeigerwert jedoch möglicherweise nicht an Anwendungen weiter. Map ungültigt bei Bedarf auch den CPU-Cache, sodass CPU-Lesevorgänge an diese Adresse alle änderungen der GPU widerspiegeln.

Syntax

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

Parameter

Subresource

Typ: UINT

Gibt die Indexnummer der Unterquelle an.

[in, optional] pReadRange

Typ: const D3D12_RANGE*

Ein Zeiger auf eine D3D12_RANGE Struktur, die den Speicherbereich beschreibt, auf den zugegriffen werden soll.

Dies gibt die Region an, die die CPU möglicherweise liest, und die Koordinaten sind Unterressourcenresource-relativ. Ein NULL-Zeiger gibt an, dass die gesamte Unterquelle möglicherweise von der CPU gelesen wird. Es ist gültig, anzugeben, dass die CPU keine Daten liest, indem ein Bereich übergeben wird, in dem End kleiner oder gleich "Begin" ist.

[out, optional] ppData

Typ: void**

Ein Zeiger auf einen Speicherblock, der einen Zeiger auf die Ressourcendaten empfängt.

Ein NULL-Zeiger ist gültig und ist nützlich, um einen virtuellen CPU-Adressbereich für Methoden wie WriteToSubresource zwischenzuspeichern. Wenn ppData nicht NULL ist, wird der zurückgegebene Zeiger niemals durch Werte in pReadRange versetzt.

Rückgabewert

Typ: HRESULT

Diese Methode gibt einen der Direct3D 12-Rückgabecodes zurück.

Hinweise

Map und Unmap können von mehreren Threads sicher aufgerufen werden. Geschachtelte Kartenaufrufe werden unterstützt und werden zurückgezählt. Der erste Aufruf von Map weist der Ressource einen virtuellen CPU-Adressbereich zu. Der letzte Aufruf von Unmap deallocates the CPU virtual address range. Die virtuelle CPU-Adresse wird häufig an die Anwendung zurückgegeben. Das Bearbeiten des Inhalts von Texturen mit unbekannten Layouts schließt jedoch die Offenlegung der virtuellen CPU-Adresse aus. Weitere Informationen finden Sie unter WriteToSubresource . Anwendungen können sich nicht darauf verlassen, dass die Adresse konsistent ist, es sei denn , Map ist dauerhaft geschachtelt.

Zeiger, die von Map zurückgegeben werden, sind nicht garantiert, dass sie über alle Funktionen normaler Zeiger verfügen, aber die meisten Anwendungen bemerken keinen Unterschied in der normalen Verwendung. Beispielsweise weisen Zeiger mit WRITE_COMBINE Verhalten eine schwächere CPU-Speicherreihenfolgegarantie auf als WRITE_BACK Verhalten. Aufgrund von PCIe-Einschränkungen wird nicht garantiert, dass der arbeitsspeicherseitig für CPU und GPU zugängliche Speicher denselben atomaren Speicher gemeinsam nutzen kann, über den die CPU verfügt. Verwenden Sie Zäune für die Synchronisierung.

Es gibt zwei Verwendungsmodellkategorien für Map, einfach und erweitert. Die einfachen Nutzungsmodelle maximieren die Toolleistung, sodass Anwendungen empfohlen werden, sich an die einfachen Modelle zu halten, bis die erweiterten Modelle nachweislich von der App benötigt werden.

Einfache Nutzungsmodelle

Anwendungen sollten sich an die Heaptypabstraktionen von UPLOAD, DEFAULT und READBACK halten, um alle Adapterarchitekturen einigermaßen gut zu unterstützen.

Anwendungen sollten CPU-Lesevorgänge von Zeigern auf Ressourcen auf UPLOAD-Heaps vermeiden, auch versehentlich. CPU-Lesevorgänge funktionieren, sind aber bei vielen gängigen GPU-Architekturen unerschwinglich langsam. Beachten Sie folgendes:

  • Lassen Sie die CPU nicht aus Ressourcen lesen, die Heaps zugeordnet sind, die D3D12_HEAP_TYPE_UPLOAD sind oder D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE haben.
  • Der Speicherbereich, dem pData-PunktePAGE_WRITECOMBINE zugeordnet werden können, und Ihre App muss alle Einschränkungen berücksichtigen, die diesem Arbeitsspeicher zugeordnet sind.
  • Sogar der folgende C++-Code kann aus dem Arbeitsspeicher lesen und die Leistungseinbuße auslösen, da der Code auf den folgenden x86-Assemblycode erweitert werden kann.

    C++-Code:

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

    x86-Assemblycode:

    AND DWORD PTR [EAX],0
    
  • Verwenden Sie die entsprechenden Optimierungseinstellungen und Sprachkonstrukte, um diese Leistungseinbußen zu vermeiden. Beispielsweise können Sie die xor-Optimierung vermeiden, indem Sie einen flüchtigen Zeiger verwenden oder die Codegeschwindigkeit anstelle der Codegröße optimieren.
Anwendungen werden empfohlen, Ressourcen nicht zugeordnet zu lassen, während die CPU sie nicht ändert und jederzeit enge, genaue Bereiche verwendet. Dies ermöglicht die schnellsten Modi für Tools, z. B . grafikdebuggen und die Debugebene. Solche Tools müssen alle CPU-Änderungen am Arbeitsspeicher nachverfolgen, die die GPU lesen könnte.

Erweiterte Nutzungsmodelle

Ressourcen auf CPU-zugänglichen Heaps können dauerhaft zugeordnet werden, was bedeutet, dass Die Zuordnung einmal aufgerufen werden kann, unmittelbar nach der Ressourcenerstellung. Unmap muss nie aufgerufen werden, aber die von Map zurückgegebene Adresse darf nicht mehr verwendet werden, nachdem der letzte Verweis auf die Ressource freigegeben wurde. Bei Verwendung einer persistenten Zuordnung muss die Anwendung sicherstellen, dass die CPU das Schreiben von Daten in den Arbeitsspeicher beendet, bevor die GPU eine Befehlsliste ausführt, die den Arbeitsspeicher liest oder schreibt. In häufigen Szenarien muss die Anwendung lediglich in den Arbeitsspeicher schreiben, bevor ExecuteCommandLists aufgerufen wird. Aber die Verwendung eines Zauns zum Verzögern der Ausführung von Befehlslisten funktioniert ebenfalls.

Alle Arbeitsspeichertypen, auf die die CPU zugegriffen werden kann, unterstützen die verwendung der persistenten Zuordnung, wobei die Ressource zugeordnet, aber dann nie aufgehoben wird, vorausgesetzt, die Anwendung greift nicht auf den Zeiger zu, nachdem die Ressource verworfen wurde.

Beispiele

Im D3D12Bundles-Beispiel wird ID3D12Resource::Map wie folgt verwendet:

Kopieren Sie Dreiecksdaten in den Vertexpuffer.

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

Erstellen Sie einen Uploadheap für die Konstantenpuffer.

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

Weitere Informationen finden Sie im Beispielcode in der D3D12-Referenz.

Anforderungen

Anforderung Wert
Zielplattform Windows
Kopfzeile d3d12.h
Bibliothek D3D12.lib
DLL D3D12.dll

Weitere Informationen

ID3D12Resource

Unterressourcen

Unmap