ウィンドウが用意できたので、次は何かを表示させたい!
と思っていましたが、結構大変っぽい・・・
ということで、まずは背景色を変更するところまでやっていきます。
1:デバッグレイヤーの有効化
2:デバイスの作成
3:その他諸々の作成
4:バックカラー変更の実装
グラフィッククラスを追加
全て処理をmain.cppに書くとごちゃごちゃになるので、新しいファイルを追加して、そこに処理を書いていきます。
cppとhファイルを追加します。
Graphicとしましたが、好きな名前でOKです。
ヘッダーファイル
DX12を使用するためにヘッダーをインクルードします。
クラスや変数、関数名も自分が理解しやすいように変更してください。
#pragma once
// include
#include <d3d12.h>
#include <dxgi1_6.h>
// DirextX関連のクラス
class Graphic
{
private:
static const int BACK_BUFFER_NUM = 2;
public:
Graphic();
~Graphic();
// 初期化
bool Initialize(HWND hwnd);
// 毎フレーム呼び出し
void ResetCommand();
void SetRenderTarget();
void ExecuteCommand();
private:
// デバイスの作成
bool CreateDevice();
// コマンドキューの作成
bool CreateCommandQueue();
// スワップチェーンの作成
bool CreateSwapChain(HWND hwnd);
// レンダーターゲットの作成
bool CreateRenderTarget();
// コマンドリストの作成
bool CreateCommandList();
// フェンスの作成
bool CreateFence();
// デバッグレイヤーを有効に
void EnableDebugLayer();
private:
ID3D12Device* m_pDevice;
ID3D12CommandQueue* m_pCommandQueue;
IDXGIFactory7* m_pFactory;
IDXGISwapChain4* m_pSwapChain;
ID3D12DescriptorHeap* m_pRenderTargetHeap;
ID3D12Resource* m_pRenderTargets[BACK_BUFFER_NUM];
UINT m_RTVIncrementSize;
UINT m_FrameIndex;
ID3D12CommandAllocator* m_pCommandAllocator;
ID3D12GraphicsCommandList* m_pCommandList;
ID3D12Fence* m_pFence;
HANDLE m_pFenceEvent;
UINT64 m_FenceValue;
};
ポインタにしていますが、ComPtr だと開放が楽になります。
C++ファイル
用意したヘッダーのインクルード、ライブラリファイルのリンクを追加します。
SAFE_RELEASEはComPtrなら書かなくてOK。
IS_S_FALSEはこのページを見やすくするためのものです。
#include "Graphic.h"
#pragma comment(lib, "d3d12.lib")
#pragma comment(lib, "dxgi.lib")
#define SAFE_RELEASE(p) if(p){p->Release(); p=nullptr;}
#define IS_S_FALSE(n) if(n != S_OK){return false;}
// コンストラクタ
Graphic::Graphic()
: m_pDevice(nullptr)
, m_pCommandQueue(nullptr)
, m_pFactory(nullptr)
, m_pSwapChain(nullptr)
, m_pCommandAllocator(nullptr)
, m_pCommandList(nullptr)
, m_pFence(nullptr)
, m_pFenceEvent(nullptr)
, m_FenceValue(0)
, m_pRenderTargetHeap(nullptr)
, m_RTVIncrementSize(0)
, m_FrameIndex(0)
{
for (int i = 0; i < BACK_BUFFER_NUM; ++i) {
m_pRenderTargets[i] = nullptr;
}
}
// デストラクタ
Graphic::~Graphic()
{
if (m_pFenceEvent) {
CloseHandle(m_pFenceEvent);
}
SAFE_RELEASE(m_pFence);
SAFE_RELEASE(m_pCommandList);
SAFE_RELEASE(m_pCommandAllocator);
for (int i = 0; i < BACK_BUFFER_NUM; ++i) {
SAFE_RELEASE(m_pRenderTargets[i]);
}
SAFE_RELEASE(m_pRenderTargetHeap);
SAFE_RELEASE(m_pSwapChain);
SAFE_RELEASE(m_pFactory);
SAFE_RELEASE(m_pCommandQueue);
SAFE_RELEASE(m_pDevice);
}
コンストラクタで初期化、デストラクタで開放しています。
デバッグレイヤー
まずやることは「デバッグレイヤーの有効化」です。
デバイス作成前に有効化する必要があります。
これで何か間違えていた場合、出力にエラーが表示されるようになります。
// デバッグレイヤーを有効に
void Graphic::EnableDebugLayer()
{
#ifdef _DEBUG
ID3D12Debug* pDebugLayer;
HRESULT result = D3D12GetDebugInterface(IID_PPV_ARGS(&pDebugLayer));
if (result == S_OK){
pDebugLayer->EnableDebugLayer();
pDebugLayer->Release();
}
#endif
}
Debugのときだけ処理されるようにして、有効化したらすぐに開放しておきます。
デバイス
有効化が終わったらデバイスの作成です。
D3D12CreateDeviceを使用します。
ビデオカードによって機能レベルが違うため、成功するまでレベルを変更して作成する。成功しなかった場合、対応していないので終了させています。
// デバイスの作成
bool Graphic::CreateDevice()
{
// 機能レベル
D3D_FEATURE_LEVEL featureLevels[] =
{
D3D_FEATURE_LEVEL_12_2,
D3D_FEATURE_LEVEL_12_1,
D3D_FEATURE_LEVEL_12_0,
D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0,
};
int levelNum = sizeof(featureLevels) / sizeof(D3D_FEATURE_LEVEL);
// 各レベルでデバイス作成を試す
for (int i = 0; i < levelNum; ++i)
{
HRESULT result = D3D12CreateDevice(
nullptr, // 既定のアダプター
featureLevels[i], // 機能レベル
IID_PPV_ARGS(&m_pDevice)
);
// 作成完了
if (result == S_OK){
break;
}
}
// デバイス作成に失敗
if (m_pDevice == nullptr) {
return false;
}
return true;
}
次はこのデバイスを使って、描画に必要なものを作成していきます。
コメント