前ページでデバイスを作成しました。
このデバイスで描画に必要なものを作成していきます。
1:デバッグレイヤーの有効化
2:デバイスの作成
3:その他諸々の作成
:コマンドキュー
:スワップチェーン
:レンダーターゲットビュー
:コマンドリスト
:フェンス
4:バックカラー変更の実装
コマンドキュー
コマンドキューの作成です。
CreateCommandQueueを使用します。
// コマンドキューの作成
bool Graphic::CreateCommandQueue()
{
D3D12_COMMAND_QUEUE_DESC queueDesc;
// GPU が実行できるコマンドバッファー
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
// 優先度は通常
queueDesc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL;
// 既定のコマンドキュー
queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
// GPUアダプターが1つなら0
queueDesc.NodeMask = 0;
// キューの作成
HRESULT result = m_pDevice->CreateCommandQueue(
&queueDesc,
IID_PPV_ARGS(&m_pCommandQueue)
);
IS_S_FALSE(result);
return true;
}
スワップチェーン
次はスワップチェーンの作成です。
CreateSwapChainForHwndを使用します。
DXGI_SWAP_CHAIN_DESC1は適宜設定を行います。WidthやHeightが0ですが、ウィンドウサイズを設定します。
// スワップチェーンの作成
bool Graphic::CreateSwapChain(HWND hwnd)
{
// DXGIオブジェクトを作成するためのもの
HRESULT result = CreateDXGIFactory1(IID_PPV_ARGS(&m_pFactory));
IS_S_FALSE(result);
DXGI_SWAP_CHAIN_DESC1 desc = {};
desc.Width = 0;
desc.Height = 0;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.Stereo = false;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.BufferUsage = DXGI_USAGE_BACK_BUFFER;
desc.BufferCount = BACK_BUFFER_NUM; // ダブルバッファー
desc.Scaling = DXGI_SCALING_STRETCH;
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
desc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
desc.Flags = 0;
// スワップチェーンの作成
result = m_pFactory->CreateSwapChainForHwnd(
m_pCommandQueue,
hwnd,
&desc,
nullptr, // ウィンドウモードはnull
nullptr, // とりあえずnull
(IDXGISwapChain1**)&m_pSwapChain
);
IS_S_FALSE(result);
// 今のバックバッファーのインデックス
m_FrameIndex = m_pSwapChain->GetCurrentBackBufferIndex();
return true;
}
レンダーターゲットビュー
続いてレンダーターゲットビューの作成です。
CreateRenderTargetViewを使用します。
がその前に・・・
ディスクリプタヒープ
レンダーターゲットビューを作るために、ディスクリプタヒープの作成です。
CreateDescriptorHeapを使用します。
ディスクリプタ=記述子。記述子は「構造や内容の要約、属性などが記されたもの」とのこと。
// レンダーターゲットの作成
bool Graphic::CreateRenderTarget()
{
D3D12_DESCRIPTOR_HEAP_DESC heapDesc = {};
// レンダーターゲットビュー
heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
// ダブルバッファー
heapDesc.NumDescriptors = BACK_BUFFER_NUM;
// デフォルト
heapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
// GPUアダプターが1つなら0
heapDesc.NodeMask = 0;
// ディスクリプタヒープの作成
HRESULT result = m_pDevice->CreateDescriptorHeap(
&heapDesc,
IID_PPV_ARGS(&m_pRenderTargetHeap)
);
IS_S_FALSE(result);
// 先頭のアドレス
D3D12_CPU_DESCRIPTOR_HANDLE handle = m_pRenderTargetHeap->GetCPUDescriptorHandleForHeapStart();
m_RTVIncrementSize = m_pDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
for (int i = 0; i < BACK_BUFFER_NUM; ++i)
{
// スワップチェーンのバッファーを取得
result = m_pSwapChain->GetBuffer(i, IID_PPV_ARGS(&m_pRenderTargets[i]));
IS_S_FALSE(result);
// レンダーターゲットビューの作成
m_pDevice->CreateRenderTargetView(
m_pRenderTargets[i],
nullptr, // とりあえずnull
handle
);
// 次へずらす
handle.ptr += m_RTVIncrementSize;
}
return true;
}
コマンドリスト
お次はコマンドリストの作成です。
CreateCommandListを使用します。
コマンドアロケータ
コマンドリストにはコマンドアロケータの作成が必要になります。
CreateCommandAllocatorで作成します。
// コマンドリストの作成
bool Graphic::CreateCommandList()
{
// コマンドアロケータの作成
HRESULT result = m_pDevice->CreateCommandAllocator(
D3D12_COMMAND_LIST_TYPE_DIRECT, // GPUが実行できるコマンドリスト
IID_PPV_ARGS(&m_pCommandAllocator)
);
IS_S_FALSE(result);
// コマンドリストの作成
result = m_pDevice->CreateCommandList(
0, // GPUアダプターが1つなら0
D3D12_COMMAND_LIST_TYPE_DIRECT,
m_pCommandAllocator,
nullptr, // パイプライン状態
IID_PPV_ARGS(&m_pCommandList)
);
IS_S_FALSE(result);
// 閉じておく
m_pCommandList->Close();
return true;
}
フェンス
フェンスの作成です。
CreateFenceを使用します。
フェンスはコマンドの処理が完了したかを確認するためのもの。
今回はCreateEventと組み合わせて使用します。
// フェンスの作成
bool Graphic::CreateFence()
{
// フェンスの生成
HRESULT result = m_pDevice->CreateFence(
0,
D3D12_FENCE_FLAG_NONE,
IID_PPV_ARGS(&m_pFence)
);
IS_S_FALSE(result);
m_FenceValue = 1;
// イベントの生成
m_pFenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
if (m_pFenceEvent == nullptr) {
return false;
}
return true;
}
作成処理をまとめる
これまでの作成処理をまとめておきます。
// 初期化
bool Graphic::Initialize(HWND hwnd)
{
// デバッグ有効
EnableDebugLayer();
// 色々作成
if (CreateDevice() == false) {
return false;
}
if (CreateCommandQueue() == false) {
return false;
}
if (CreateSwapChain(hwnd) == false) {
return false;
}
if (CreateRenderTarget() == false) {
return false;
}
if (CreateCommandList() == false) {
return false;
}
if (CreateFence() == false) {
return false;
}
return true;
}
次は作成したもので、描画を実装していきます。
コメント