ID3D12Resource::Map 方法 (d3d12.h)
取得資源中指定子資源的CPU指標,但可能不會向應用程式揭露指標值。 對應 也會在必要時使CPU快取失效,讓CPU讀取至此位址時反映 GPU 所做的任何修改。
語法
HRESULT Map(
UINT Subresource,
[in, optional] const D3D12_RANGE *pReadRange,
[out, optional] void **ppData
);
參數
Subresource
類型: UINT
指定子資源的索引編號。
[in, optional] pReadRange
類型: const D3D12_RANGE*
描述要存取之內存範圍的 D3D12_RANGE 結構的指標。
這表示 CPU 可能讀取的區域,而且座標是子資源相對的。 Null 指標表示 CPU 可能會讀取整個子資源。 藉由傳遞 End 小於或等於 Begin 的範圍,指定 CPU 將不會讀取任何數據。
[out, optional] ppData
類型: void**
記憶體區塊的指標,可接收資源數據的指標。
Null 指標有效,而且對於 WriteToSubresource 之類的方法快取 CPU 虛擬位址範圍很有用。 當 ppData 不是 NULL 時,傳回的指標永遠不會由 pReadRange 中的任何值位移。
傳回值
類型: HRESULT
這個方法會傳回其中一個 Direct3D 12 傳回碼。
備註
多個 線程可以安全地呼叫 Map 和 Unmap 。 支援巢狀 對應 呼叫,並且會計算 ref 計數。 對應的第一次呼叫 會配置資源的 CPU 虛擬位址範圍。 最後一次 呼叫 Unmap 會解除分配 CPU 虛擬位址範圍。 CPU 虛擬位址通常會傳回給應用程式;但操作具有未知版面配置之紋理的內容,會排除公開 CPU 虛擬位址。 如需詳細資訊 ,請參閱 WriteToSubresource 。 除非 Map 持續巢狀,否則應用程式無法依賴位址保持一致。
Map 傳回的指標不保證具有一般指標的所有功能,但大部分的應用程式都不會注意到一般使用方式的差異。 例如,具有WRITE_COMBINE行為的指標具有比WRITE_BACK行為更弱的CPU記憶體排序保證。 CPU 和 GPU 可存取的記憶體不保證會因為 PCIe 限制而共用相同的不可部分完成記憶體保證 CPU 具有。 使用柵欄進行同步處理。
地圖有兩個使用模型類別,簡單和進階。 簡單的使用模型會將工具效能最大化,因此建議應用程式使用簡單模型,直到應用程序證明需要進階模型為止。
簡單使用模型
應用程式應該保持上傳、DEFAULT 和 READBACK 的堆積類型抽象概念,才能合理地支援所有配接器架構。應用程式應該避免 CPU 從 UPLOAD 堆積上的資源指標讀取,甚至不小心。 CPU 讀取將會運作,但在許多常見的 GPU 架構上非常緩慢,因此請考慮下列事項:
- 請勿讓 CPU 從與D3D12_HEAP_TYPE_UPLOAD或具有D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE的堆積相關聯的資源讀取。
- pData 點可使用PAGE_WRITECOMBINE配置至其中的記憶體區域,而且您的應用程式必須接受與這類記憶體相關聯的所有限制。
-
即使下列 C++ 程式代碼可以從記憶體讀取並觸發效能負面影響,因為程式代碼可以擴充為下列 x86 元件程式代碼。
C++ 程式代碼:
*((int*)MappedResource.pData) = 0;
x86 元件程式代碼:
AND DWORD PTR [EAX],0
- 使用適當的優化設定和語言建構來協助避免這種效能損失。 例如,您可以使用 變動 性指標或優化程式代碼速度,而不是程式代碼大小來避免 xor 優化。
進階使用模型
CPU 可存取堆積上的資源可以持續對應,這表示在資源建立后立即呼叫 Map 一次。 Unmap 永遠不需要呼叫,但從 Map 傳回的地址在資源最後一次參考發行之後,就不能再使用。 使用永續性對應時,應用程式必須在 GPU 執行讀取或寫入記憶體的命令清單之前,確保 CPU 完成將數據寫入記憶體。 在常見的案例中,應用程式只需要寫入記憶體,才能呼叫 ExecuteCommandLists;但使用柵欄來延遲命令清單執行也正常運作。所有可存取 CPU 的記憶體類型都支援持續性對應使用量,其中資源會對應,但永遠不會取消對應,前提是應用程式在處置資源之後不會存取指標。
範例
D3D12Bundles 範例使用 ID3D12Resource::Map,如下所示:
將三角形數據複製到頂點緩衝區。
// 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);
建立常數緩衝區的上傳堆積。
// 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)));
請參閱 D3D12 參考中的範例程式代碼。
規格需求
需求 | 值 |
---|---|
目標平台 | Windows |
標頭 | d3d12.h |
程式庫 | D3D12.lib |
Dll | D3D12.dll |