初めに
まず、D3D12MAをセットアップしてから記事の内容へ入りましょう
以下、翻訳を掲載します
① D3D12MemAlloc.cpp と D3D12MemAlloc.h をあなたのプロジェクトにコピーしてください。
② D3D12MemAlloc.cpp を C++ コードとしてプロジェクト内でコンパイルするように設定してください。
③ このライブラリを使用する必要がある各 CPP ファイルで、ライブラリのヘッダーをインクルードしてください。
(https://gpuopen-librariesandsdks.github.io/D3D12MemoryAllocator/html/quick_start.html
より)
D3D12Memory Allocator(MA)とは?
Direct3D12メモリ管理用のフレームワークです
D3D12MAを使うことの利点
DirectXTK12と併用して抽象度の比較的高いコーディングから
徐々にネイティブ寄り実装への移行も可能
高度なパフォーマンスチューニングにも対応
数多くのゲームアプリや開発ソフトでの採用実績
おことわり
今回、D3D12の初期化実装に
Direct3D Game VS templates
を使用しています
フルコードは
https://github.com/kantamRobo/D3D12MA_DirectXTK12Polygon
に掲載しています。
解説コメントをそちらにも掲載しておりますので
興味があればぜひご覧ください
今回、D3D12MAを使って三角ポリゴンを描くのですが、頂点バッファ生成以外の箇所は
DirectX-Graphics-samplesのHelloTriangleサンプルをベースにしています
https://github.com/microsoft/DirectX-Graphics-Samples/tree/master/Samples/Desktop/D3D12HelloWorld/src/HelloTriangle
また、DirectXTK12を使用しております
ポリゴン生成の過程については以前の記事に掲載した事柄を把握されていることを前提に記事の内容を進めます。ご了承ください。
今回、バッファ生成をするための関数がこちらになります。
D3D12MA::CALLOCATION_DESC allocDesc = D3D12MA::CALLOCATION_DESC{
D3D12_HEAP_TYPE_UPLOAD,
D3D12MA::ALLOCATION_FLAG_STRATEGY_MIN_TIME };
auto resdesc = CD3DX12_RESOURCE_DESC::Buffer(vertexBufferSize);
ソースコードはD3D12MA公式のクイックスタートより
https://gpuopen-librariesandsdks.github.io/D3D12MemoryAllocator/html/quick_start.html#quick_start_helper_structures
CALLOCATION_DESC?
D3D12MA::ALLOCATION_DESCのヘルパー構造体となります
ALLOCATION_DESCについてはこちらの公式ドキュメントを参照
https://gpuopen-librariesandsdks.github.io/D3D12MemoryAllocator/html/struct_d3_d12_m_a_1_1_a_l_l_o_c_a_t_i_o_n___d_e_s_c.html
リソース生成には
CALLOCATION_DESC (D3D12_HEAP_TYPE heapType, ALLOCATION_FLAGS flags=ALLOCATION_FLAG_NONE, void *privateData=NULL, D3D12_HEAP_FLAGS extraHeapFlags=D3D12MA_RECOMMENDED_HEAP_FLAGS) noexcept
を使用しており、これのおかげでこちらが指定する必要のある引数はD3D12_HEAP_TYPEのみとなります
ちなみに、HEAP_TYPEは主に3つです。
CALLOCATION_DESCで指定するHEAP_TYPEの一覧
| HEAPTYPE | 何をするのか |
|---|---|
| D3D12_HEAP_TYPE_DEFAULT | GPUリソースのヒープをGPUやGPUバッファ領域に指定。CPUからのデータ読み書きはできないが、ビデオメモリアクセス処理が速い。テクスチャや頂点に使うことが多い |
| D3D12_HEAP_TYPE_UPLOAD | CPUからGPU側にデータを読み書きする際に使う。DEFAULTヒープに確保したいGPUリソースの一時バッファとして使用することが多い。または定数バッファをCPUからGPUに書き込む場合に使う |
| D3D12_HEAP_TYPE_READBACK | GPUからCPU側にデータを受け取るためのヒープ領域を設定。CPU側での動きがよくなりやすいように設定されている。たとえばレンダーターゲット用のフレームバッファに使う |
カスタム設定のHEAPTYPEもありますが、ここでは割愛します。
GPUリソースの作成
//リソース生成に直接ヘルパー関数によるリソースデスクの代入はできない。
D3D12MA::Allocation* alloc;
allocator->CreateResource(&allocDesc, &resdesc,
D3D12_RESOURCE_STATE_GENERIC_READ, NULL, &alloc, IID_PPV_ARGS(&m_vertexBuffer));
・D3D12MA::CALLOCATION_DESC allocDescは
D3D12MA::ALLOCATION_DESCを継承したヘルパー構造体となります。
この継承元を使った設定の一例がこちらです
D3D12MA::ALLOCATION_DESC allocDesc;
allocDesc.Flags = D3D12MA::ALLOCATION_FLAG_STRATEGY_MIN_TIME;
allocDesc.HeapType = D3D12_HEAP_TYPE_UPLOAD;
allocDesc.ExtraHeapFlags = D3D12_HEAP_FLAG_NONE;
allocDesc.CustomPool = NULL;
allocDesc.pPrivateData = NULL;
コードがD3D12(以下ネイティブ)の
D3D12_HEAP_PROPERTIESの一部です
これはバッファを作成する関数である、
CreateResourceが内部で呼び出しているCreateCommitedResource、
またはPlacedResourceに必要な構造体となりますが、
ここではD3D12に関する詳細の記述は割愛します。
※これはDirectXTK12のバッファ生成も同様で、
ID3D12Resourceのラッパークラスとなる、GraphicResourcesのメモリ領域確保にはこのようなネイティブが内部で動いています。
あとは・・・・こちらも簡単に説明を。
// 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.
m_vertexBuffer->Map(0, &readRange, reinterpret_cast<void**>(&pVertexDataBegin));
memcpy(pVertexDataBegin, triangleVertices, sizeof(triangleVertices));
m_vertexBuffer->Unmap(0, nullptr);
頂点バッファへの頂点の実データのコピー処理です
もう少しわかりやすいであろう例を示すと
int verticessize =sizeof(vertices);
std::vector<VertexBuffer> m_vertexBuffer ={};
for(int i=0;i<verticessize;i++){
m_vertexBuffer.push_back(vertices[i]);
}
と似たことを行っています。
黒太文字で示した部分が、予め
「このバッファの、この範囲に
頂点データを対応付けしておくぞ」

