共用方式為


ID3D12Resource::Map 方法 (d3d12.h)

取得 CPU 指標指向該資源中指定的子資源,但不得向應用程式揭露指標值。 Map 也會在必要時使 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 可能讀取的區域,座標是子資源相關的。 空指標表示 CPU 可能會讀取整個子資源。 透過傳遞一個範圍,讓 End 小於或等於 Begin 來指定 CPU 不會讀取任何資料是合理的。

[out, optional] ppData

類型: 無效**

指向記憶體區塊的指標,該區塊接收到資源資料的指標。

空指標有效且有助於快取 CPU 虛擬位址範圍,用於像 WriteToSubresource 這類方法。 當 ppData 非 NULL 時,回傳的指標不會被 pReadRange 中的任何值所偏移。

返回值

類型: HRESULT

此方法會回傳 Direct3D 12 回傳碼之一。

備註

Map Unmap 可以被多個執行緒安全地呼叫。 支援巢狀 地圖 呼叫並有參考資料。 第一次呼叫 Map 會為資源分配一個 CPU 虛擬位址範圍。 最後一次呼叫 Unmap 會釋放 CPU 虛擬位址範圍。 CPU 虛擬位址通常會回傳給應用程式;但若操作紋理內容且配置未知,則無法揭露 CPU 虛擬位址。 更多詳情請參見 WriteToSubresource 。 應用程式無法依賴位址一致性,除非 Map 持續巢狀。

Map 回傳的指標不保證具備一般指標的所有功能,但大多數應用程式不會察覺正常使用中的差異。 例如,具有WRITE_COMBINE行為的指標,CPU 記憶體排序的保證比WRITE_BACK行為弱。 由於 PCIe 限制,CPU 與 GPU 可存取的記憶體無法保證共享 CPU 所擁有的相同原子記憶體。 用圍欄來同步。

Map 有兩個使用模型類別,簡單型和進階型。 簡單使用模型能最大化工具效能,因此建議應用程式在應用程式證明進階模型為必需品前,先堅持使用簡單模型。

簡單使用模型

應用程式應遵循堆積類型的抽象,如上傳(UPLOAD)、預設(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
    
  • 使用適當的優化設定與語言結構,以避免此效能損失。 例如,你可以透過使用 揮發性 指標或優化程式碼速度而非程式碼大小來避免異或優化。
應用程式被鼓勵在 CPU 不修改資源的情況下保持不映射,並始終使用精確且精確的範圍。 這使得工具(如 圖形除錯 與除錯層)能使用最快的模式。 這類工具需要追蹤 GPU 能讀取的所有 CPU 對記憶體的修改。

進階使用模型

CPU 可存取堆積上的資源可以被持續映射,也就是說, Map 可以在資源建立後立即呼叫一次。 Unmap 從不需要被呼叫,但在最後一次資源引用被釋放 後,Map 回傳的位址必須不再使用。 使用持久映射時,應用程式必須確保 CPU 在 GPU 執行讀取或寫入記憶體的指令清單前,先完成資料寫入記憶體。 在常見情境中,應用程式只需在呼叫 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 參考文獻中的範例程式碼

需求

Requirement 價值觀
目標平臺 窗戶
Header d3d12.h
Library D3D12.lib
DLL D3D12.dll

另請參閱

ID3D12Resource

子資源

取消地圖