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 が読み取る可能性がある領域を示し、座標がサブリソース相対であることを示します。 null ポインターは、サブリソース全体が CPU によって読み取られる可能性があることを示します。 End が Begin 以下の範囲を渡すことによって、CPU がデータを読み取らないことを指定することは有効です。
[out, optional] ppData
型: void**
リソース データへのポインターを受け取るメモリ ブロックへのポインター。
null ポインターは有効であり、 WriteToSubresource などのメソッドの CPU 仮想アドレス範囲をキャッシュするのに役立ちます。 ppData が NULL でない場合、返されるポインターは pReadRange の値によってオフセットされることはありません。
戻り値
種類: HRESULT
このメソッドは、Direct3D 12リターン コードのいずれかを返します。
注釈
Map と Unmap は、複数のスレッドから安全に呼び出すことができます。 入れ子になった マップ 呼び出しがサポートされ、参照カウントされます。 Map を最初に呼び出したときに、リソースの CPU 仮想アドレス範囲が割り当てられます。 この CPU 仮想アドレス範囲は、Unmap を最後に呼び出したときに割り当て解除されます。 CPU 仮想アドレスは、一般的にアプリケーションに返されます。しかし、不明なレイアウトでテクスチャの内容を操作すると、CPU 仮想アドレスが開示されません。 詳細については、「 WriteToSubresource 」を参照してください。 Map が永続的に入れ子になっていない限り、アプリケーションはアドレスの一貫性に依存できません。
Map によって返されるポインターは、通常のポインターのすべての機能を持っていることは保証されませんが、ほとんどのアプリケーションでは通常の使用の違いに気付くことはありません。 たとえば、WRITE_COMBINE動作を持つポインターの CPU メモリ順序の保証は、WRITE_BACK動作よりも弱くなります。 CPU と GPU の両方からアクセスできるメモリは、PCIe の制限により、CPU が持っているのと同じアトミック メモリの保証を共有することは保証されません。 同期にはフェンスを使用します。
Map には、シンプルと高度の 2 つの使用モデル カテゴリがあります。 シンプルな使用モデルはツールのパフォーマンスを最大化するため、高度なモデルがアプリに必要であることが証明されるまで、アプリケーションは単純なモデルに従うことをお勧めします。
単純な使用モデル
アプリケーションは、すべてのアダプター アーキテクチャを合理的にサポートするために、UPLOAD、DEFAULT、READBACK のヒープ型の抽象化に固執する必要があります。アプリケーションでは、誤ってアップロード ヒープ上のリソースへのポインターからの CPU 読み取りを回避する必要があります。 CPU 読み取りは機能しますが、多くの一般的な GPU アーキテクチャでは非常に遅いので、次の点を考慮してください。
- D3D12_HEAP_TYPE_UPLOADまたはD3D12_CPU_PAGE_PROPERTY_WRITE_COMBINEがあるヒープに関連付けられているリソースから CPU を読み取らないでください。
- pData がポイントするメモリ領域は、PAGE_WRITECOMBINEで割り当てることができ、アプリは、このようなメモリに関連付けられているすべての制限を遵守する必要があります。
-
次の C++ コードでもメモリから読み取り、パフォーマンスの低下をトリガーできます。これは、コードが次の x86 アセンブリ コードに拡張できるためです。
C++ コード:
*((int*)MappedResource.pData) = 0;
x86 アセンブリ コード:
AND DWORD PTR [EAX],0
- このパフォーマンスの低下を回避するには、適切な最適化設定と言語コンストラクトを使用します。 たとえば、 揮発性 ポインターを使用するか、コード サイズではなくコード速度を最適化することで、xor の最適化を回避できます。
高度な使用モデル
CPU アクセス可能なヒープ上のリソースは永続的にマップできます。つまり、リソースの作成直後に Map を 1 回呼び出すことができます。 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)));
要件
要件 | 値 |
---|---|
対象プラットフォーム | Windows |
ヘッダー | d3d12.h |
Library | D3D12.lib |
[DLL] | D3D12.dll |