【DX12を学びたい】デバイス作成~背景の色を変更する

背景色の変更 DirextX

ウィンドウが用意できたので、次は何かを表示させたい!

と思っていましたが、結構大変っぽい・・・

ということで、まずは背景色を変更するところまでやっていきます。

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;
}

 

次はこのデバイスを使って、描画に必要なものを作成していきます。

かれいど

ゲームをしたり、作ったり
色々な事に挑戦していきたい!

サッカー観戦も趣味で
主にJ1リーグを観ています。

かれいどをフォローする
DirextX
スポンサーリンク
シェアする

コメント