DirectX12 事始め 定数バッファの生成

今回は定数バッファを作って行きます。
定数バッファは、バッファにデータを送り、GPUがその値を参照していくのです。

まず、定数バッファを作る前に外部参照されてもいいように、宣言用のヘッダーを作ります。

```c++:Typedef.h
#include <DirectXMath.h>
// 円周率
#define PI 3.14159265359f
// ラジアン変換
#define RAD(X) (X) * PI / 180.0f
// 頂点
struct Vertex {
   //座標
   DirectX::XMFLOAT3 pos;
   //UV
   DirectX::XMFLOAT2 uv;
};
// 空間行列
struct WVP
{
   //ワールド
   DirectX::XMMATRIX world;
   //ビュープロジェクション
   DirectX::XMMATRIX viewProjection;
};
```

次回、頂点バッファを作るのでその前準備として頂点情報も宣言しておきます。

```c++:Constant.h
#include "Descriptor.h"
#include "Typedef.h"
#include <vector>
class Constant :
   public Descriptor
{
public:
   // コンストラクタ
   Constant(Device* dev, List* list);
   // デストラクタ
   ~Constant();

   // WVPの更新
   void UpDataWVP(void);
   // 定数バッファのセット
   void SetConstant(UINT rootIndex = 0, UINT index = 0);

   // リソースの取得
   ID3D12Resource* GetResoure(UINT index) const {
      return resource[index];
   }
   // リソースの取得
   std::vector<ID3D12Resource*> GetResoure() const {
      return resource;
   }
private:
   // WVPのセット
   void SetWVP(void);
   // リソースの生成
   HRESULT CreateResource(UINT index, UINT64 size);
   // リソースビューの生成
   HRESULT CreateView(UINT index, UINT size, UINT stride);

   // リソース
   std::vector<ID3D12Resource*> resource;
   // 送信データ
   std::vector<UINT8*> data;
   // WVP
   WVP wvp;
};
```

```c++:Constant.cpp
#include "Constant.h"
#include “Device.h"
#include "List.h"

// リソースの最大数
#define RESOURCE_MAX 1

// コンストラクタ
Constant::Constant(Device* dev, List* list)
{
   this->dev  = dev;
   this->list = list;

   resource.clear();
   resource.resize(RESOURCE_MAX);
   data.clear();
   data.resize(RESOURCE_MAX);
   wvp = {};

   SetWVP();
   CreateHeap();
   CreateResource(0, ((sizeof(WVP) + 0xff) &~0xff));
   CreateView(0, (sizeof(WVP) + 0xff) &~0xff, sizeof(WVP));
}
// デストラクタ
Constant::~Constant()
{
   for (UINT i = 0; i < resource.size(); ++i)
   {
      if (resource[i] != nullptr)
      {
         resource[i]->Unmap(0, nullptr);
      }

      Release(resource[i]);
   }
   Release(heap);
}
// WVPのセット
void Constant::SetWVP(void)
{
   //ダミー宣言
   FLOAT pos = 0.0f;
   DirectX::XMMATRIX view   = DirectX::XMMatrixIdentity();
   //カメラの位置
   DirectX::XMVECTOR eye    = { 0, pos,  -1 };
   //カメラの焦点
   DirectX::XMVECTOR target = { 0, pos,   0 };
   //カメラの上方向
   DirectX::XMVECTOR upper  = { 0, 1,     0 };

   view = DirectX::XMMatrixLookAtLH(eye, target, upper);

   //ダミー宣言
   DirectX::XMMATRIX projection = DirectX::XMMatrixIdentity();

   projection = DirectX::XMMatrixPerspectiveFovLH(RAD(90.0f), ((static_cast<FLOAT>(win.lock()->GetX()) / static_cast<FLOAT>(win.lock()->GetY()))), 0.5f, 500.0f);

   //更新
   wvp.world          = DirectX::XMMatrixIdentity();
   wvp.viewProjection = view * projection;
}
// リソースの生成
HRESULT Constant::CreateResource(UINT index, UINT64 size)
{
   result = CreateHeap(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE);

   //プロパティ設定用構造体の設定
   D3D12_HEAP_PROPERTIES prop = {};
   prop.Type                 = D3D12_HEAP_TYPE_UPLOAD;
   prop.CPUPageProperty      = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
   prop.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
   prop.CreationNodeMask     = 1;
   prop.VisibleNodeMask      = 1;

   //リソース設定用構造体の設定
   D3D12_RESOURCE_DESC desc = {};
   desc.Dimension        = D3D12_RESOURCE_DIMENSION_BUFFER;
   desc.Width            = size;
   desc.Height           = 1;
   desc.DepthOrArraySize = 1;
   desc.MipLevels        = 1;
   desc.Format           = DXGI_FORMAT_UNKNOWN;
   desc.SampleDesc.Count = 1;
   desc.Flags            = D3D12_RESOURCE_FLAG_NONE;
   desc.Layout           = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;

   //リソースの生成
   result = dev->Get()->CreateCommittedResource(&prop, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&resource[index]));

   return result;
}
// リソースビューの生成
HRESULT Constant::CreateView(UINT index, UINT size, UINT stride)
{
   //ハンドル
   D3D12_CPU_DESCRIPTOR_HANDLE handle = heap->GetCPUDescriptorHandleForHeapStart();
   handle.ptr += this->size * index;

   //定数バッファビュー設定用構造体の設定
   D3D12_CONSTANT_BUFFER_VIEW_DESC desc = {};
   desc.SizeInBytes    = size;
   desc.BufferLocation = resource[index]->GetGPUVirtualAddress();

   //送信範囲
   D3D12_RANGE range = { 0, 0 };

   //定数バッファビュー生成
   dev->Get()->CreateConstantBufferView(&desc, handle);

   //マッピング
   result = resource[index]->Map(0, &range, (void**)(&data[index]));

   //コピー
   memcpy(data[index], &wvp, stride);

   return result;
}

// WVPの更新
void Constant::UpDataWVP(void)
{
   //回転
   static float angle = 0.0f;
   //行列更新
   wvp.world = DirectX::XMMatrixRotationY(RAD(angle));

   //行列データ更新
   memcpy(data[0], &wvp, sizeof(WVP));

   angle++;
}
// 定数バッファのセット
void Constant::SetConstant(UINT rootIndex, UINT index)
{
   //ハンドル
   D3D12_GPU_DESCRIPTOR_HANDLE handle = heap->GetGPUDescriptorHandleForHeapStart();
   handle.ptr += this->size * index;

   //ヒープのセット
   list->GetList()->SetDescriptorHeaps(1, &heap);

   //ルートシグネチャとの関連づけ
   list->GetList()->SetGraphicsRootDescriptorTable(rootIndex, handle);
}
```

以上で定数バッファの生成が終了しました。
ポリゴンを描画する際に3Dにして回転させて確認できるようにしてます。