> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Map

> 取得資源中指定子資源的 CPU 指標，但可能不會向應用程式揭露指標值。Map 也會使 CPU 快取失效。

取得資源中指定子資源的 CPU 指標，但可能不會向應用程式揭露指標值。**Map** 也會在必要時使 CPU 快取失效，讓 CPU 對此位址的讀取能反映 GPU 所做的任何修改。

## 語法

```cpp theme={null}
HRESULT Map(
    UINT Subresource,
    const D3D12_RANGE  pReadRange,
    void  ppData
)
```

### 參數

*Subresource*<br />類型：UINT

指定子資源的索引編號。

*pReadRange \[in, optional]*<br />類型：const D3D12\_RANGE \*

指向 [D3D12\_RANGE](/zh-TW/reference/graphics/d3d12/structs/d3d12_range_public) 結構的指標，該結構描述要存取的記憶體範圍。

這表示 CPU 可能讀取的區域，且座標是相對於子資源。Null 指標表示 CPU 可能讀取整個子資源。傳遞 **End** 小於或等於 **Begin** 的範圍，以指定 CPU 不會讀取任何資料，是有效的做法。

*ppData \[out, optional]*<br />類型：void \*\*

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

Null 指標是有效的，且適用於為 [WriteToSubresource](/zh-TW/reference/graphics/d3d12/interfaces/id3d12resource/methods/id3d12resource_writetosubresource_public) 等方法快取 CPU 虛擬位址範圍。當 <i>ppData</i> 不是 NULL 時，傳回的指標永遠不會因 <i>pReadRange</i> 中的任何值而產生位移。

### 傳回值

類型：HRESULT

此方法會傳回其中一個 [Direct3D 12 傳回碼](https://learn.microsoft.com/en-us/windows/desktop/direct3d12/d3d12-graphics-reference-returnvalues)。

## 備註

多個執行緒可以安全地呼叫 **Map** 和 [Unmap](/zh-TW/reference/graphics/d3d12/interfaces/id3d12resource/methods/id3d12resource_unmap_public)。支援巢狀 **Map** 呼叫，且會進行參考計數。第一次呼叫 **Map** 時會為資源配置 CPU 虛擬位址範圍。最後一次呼叫 **Unmap** 時會解除配置 CPU 虛擬位址範圍。CPU 虛擬位址通常會傳回給應用程式；但操作版面配置未知之紋理的內容時，則無法揭露 CPU 虛擬位址。如需詳細資訊，請參閱 [WriteToSubresource](/zh-TW/reference/graphics/d3d12/interfaces/id3d12resource/methods/id3d12resource_writetosubresource_public)。除非 **Map** 持續保持巢狀，否則應用程式不能依賴位址保持一致。

**Map** 傳回的指標不保證具備一般指標的所有功能，但大部分應用程式在一般使用情況下不會察覺差異。例如，具有 WRITE\_COMBINE 行為的指標，其 CPU 記憶體排序保證比 WRITE\_BACK 行為弱。由於 PCIe 的限制，CPU 和 GPU 皆可存取的記憶體不保證與 CPU 具有相同的不可部分完成記憶體保證。請使用柵欄進行同步處理。

**Map** 的使用模型分為兩類：簡單和進階。簡單使用模型可將工具效能最大化，因此建議應用程式持續使用簡單模型，直到證實應用程式需要進階模型為止。

<h3><a id="Simple_Usage_Models" /><a id="simple_usage_models" /><a id="SIMPLE_USAGE_MODELS" />簡單使用模型</h3> 應用程式應遵循 UPLOAD、DEFAULT 和 READBACK 的堆積類型抽象，以合理地支援所有介面卡架構。

應用程式應避免 CPU 從指向 UPLOAD 堆積上資源的指標讀取，即使是意外的讀取也應避免。CPU 讀取可以運作，但在許多常見的 GPU 架構上速度慢到令人無法接受，因此請考慮下列事項：

<ul>
  <li>
    不要讓 CPU 從與 D3D12\_HEAP\_TYPE\_UPLOAD 堆積或具有 D3D12\_CPU\_PAGE\_PROPERTY\_WRITE\_COMBINE 之堆積相關聯的資源讀取。
  </li>

  <li>
    **pData** 所指向的記憶體區域可以使用 [PAGE\_WRITECOMBINE](https://learn.microsoft.com/en-us/windows/desktop/Memory/memory-protection-constants) 配置，而您的應用程式必須遵守與此類記憶體相關的所有限制。
  </li>

  <li>
    即使是下列 C++ 程式碼也可能從記憶體讀取並觸發效能損失，因為程式碼可能會展開為下列 x86 組合語言程式碼。

    C++ 程式碼：

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

    x86 組合語言程式碼：

    ```
    AND DWORD PTR [EAX],0
    ```
  </li>

  <li>
    使用適當的最佳化設定和語言結構，協助避免此效能損失。例如，您可以使用 **volatile** 指標，或針對程式碼速度而非程式碼大小進行最佳化，以避免 xor 最佳化。
  </li>
</ul>

建議應用程式在 CPU 不會修改資源時讓資源保持未對應狀態，並隨時使用精確且緊密的範圍。這可讓 [圖形偵錯](https://learn.microsoft.com/en-us/visualstudio/debugger/visual-studio-graphics-diagnostics) 和偵錯層等工具使用最快的模式。這類工具需要追蹤 CPU 對 GPU 可能讀取之記憶體所做的所有修改。

<h3><a id="Advanced_Usage_Models" /><a id="advanced_usage_models" /><a id="ADVANCED_USAGE_MODELS" />進階使用模型</h3> CPU 可存取之堆積上的資源可以持續對應，也就是說，可以在建立資源後立即呼叫一次 **Map**。永遠不需要呼叫 [Unmap](/zh-TW/reference/graphics/d3d12/interfaces/id3d12resource/methods/id3d12resource_unmap_public)，但在釋放資源的最後一個參考之後，就不得再使用 **Map** 傳回的位址。使用持續對應時，應用程式必須確保 CPU 在 GPU 執行讀取或寫入該記憶體的命令清單之前，完成將資料寫入記憶體。在常見情況下，應用程式只需在呼叫 [ExecuteCommandLists](/zh-TW/reference/graphics/d3d12_x/interfaces/id3d12commandqueue/methods/id3d12commandqueue_executecommandlists) 之前寫入記憶體即可；但使用柵欄延遲命令清單執行也同樣可行。

所有 CPU 可存取的記憶體類型都支援持續對應用法，也就是資源經過對應後永遠不會解除對應，前提是應用程式在資源處置後不會存取該指標。

#### 範例

[D3D12Bundles](https://learn.microsoft.com/en-us/windows/desktop/direct3d12/working-samples) 範例使用 **ID3D12Resource::Map** 的方式如下：

將三角形資料複製到頂點緩衝區。

```cpp theme={null}
// 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);
```

為常數緩衝區建立上傳堆積。

```cpp theme={null}
// 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 參考中的範例程式碼](https://learn.microsoft.com/en-us/windows/desktop/direct3d12/notes-on-example-code)。

<div class="code" />

## 需求

**標頭:** d3d12\_xs.h 或 d3d12\_x.h<br />**程式庫:** d3d12\_xs.lib 或 d3d12\_x.lib<br />**支援的平台**: XBOX Series 主機與 XBOX One 系列

## 另請參閱

[ID3D12Resource](/zh-TW/reference/graphics/d3d12_xs/interfaces/ID3D12Resource/id3d12resource_xs)

[子資源](https://learn.microsoft.com/en-us/windows/desktop/direct3d12/subresources)

[Unmap](/zh-TW/reference/graphics/d3d12/interfaces/id3d12resource/methods/id3d12resource_unmap_public)


## Related topics

- [XMemMapPhysicalPages](/zh-TW/reference/system/xmem/functions/xmemmapphysicalpages.md)
- [ApuMapApuAddress](/zh-TW/reference/audio/apu/functions/apumapapuaddress.md)
- [ApuMapVirtualAddress](/zh-TW/reference/audio/apu/functions/apumapvirtualaddress.md)
- [XMemMapPhysicalPagesScatter](/zh-TW/reference/system/xmem/functions/xmemmapphysicalpagesscatter.md)
- [將欄位值新增至統計資料規則](/zh-TW/services/xbox-services/player-data/stats-leaderboards/event-based/config/live-stat-name-value.md)
