デバイス生成から画面クリアまで

1. はじめに

Direct3D 12ゲームグラフィックス実践ガイドを発売してからはや4年。Visual Studio 2026対応していないので,VS2026対応だけやっておこうと思いました。一番単純なデバイス生成と画面クリアを行うプログラムです。詳しい説明については書籍のChapter.2をご参照ください。

実行結果

2. デバイス生成時の注意

今年になって色々なハードで動かす機会があって、デバイス生成にちゃんと気を付けないといけないということがわかりました。特にRTXとかいいGPUを積んでいてもプログラムの組み方が悪かったり,BIOS設定側でちゃんとされていない場合は,Intel HD Graphicsなど低パフォーマンスなAdapterが選択されてしまったりして,高いパフォーマンスが発揮できない状態でDirect3D 12の初期化がされてしまう場合があります。そのため,次のように明示的にハイパフォーマンスなAdapterを選択するようにしたほうが良いです。

    ComPtr<IDXGIFactory6> pFactory;
    {
        uint32_t flags = 0;
    #if defined(DEBUG) || defined(_DEBUG)
        flags |= DXGI_CREATE_FACTORY_DEBUG;
    #endif

        ComPtr<IDXGIFactory2> factory;

        auto hr = CreateDXGIFactory2(flags, IID_PPV_ARGS(factory.GetAddressOf()));
        if (FAILED(hr))
        {
            OutputDebugStringA("Error : CreateDXGIFactory2() Failed.");
            return false;
        }

        hr = factory.As(&pFactory);
        if (FAILED(hr))
        {
            OutputDebugStringA("Error : ComPtr::As() Failed.");
            return false;
        }
    }

    // DXGIアダプター生成.
    ComPtr<IDXGIAdapter1> pAdapter;
    {
        // 高パフォーマンスのものを選択.
        for(auto adapterId=0;
            DXGI_ERROR_NOT_FOUND != pFactory->EnumAdapterByGpuPreference(adapterId, DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE, IID_PPV_ARGS(pAdapter.ReleaseAndGetAddressOf()));
            adapterId++)
        {
            DXGI_ADAPTER_DESC1 desc;
            auto hr = pAdapter->GetDesc1(&desc);
            if (FAILED(hr))
            { continue; }

            // ソフトウェアは回避する.
            if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE)
            { continue; }

            // 最初に見つかったものをD3D12デバイス生成として利用する.
            hr = D3D12CreateDevice(pAdapter.Get(), D3D_FEATURE_LEVEL_11_0, __uuidof(ID3D12Device), nullptr);
            if (SUCCEEDED(hr))
            { break; }
        }
    }

    // デバイスの生成.
    auto hr = D3D12CreateDevice(
        pAdapter.Get(),
        D3D_FEATURE_LEVEL_11_0,
        IID_PPV_ARGS(m_pDevice.GetAddressOf()));
    if (FAILED(hr))
    { return false; }

実装のポイントはIDXGIFactory6::EnumAdapterByGpuPreference()の引数に,DXGI_GPU_PEREFERENCE_HIGH_PERFORMANCEを指定して,高パフォーマンスなIDXGIAdapter1を調べていくことです。そして,IDXGIAdapter1::GetDesc1()を使って,FlagsでDXGI_ADAPTER_FLAG_SOFTWAREが立っていないものを調べます。これで最初に見つかって,D3D12CreateDevice()に成功したものをIDXGIAdapterとして採用するようにします。そして,決定したIDXGIAdapterを使って,D3D12CreateDevice()の第1引数に設定して,ちゃんとしたデバイスを作成します。こうして作成しないと、後々メッシュシェーダなどを実装する際に,サポートされていないアダプターが設定されてしまって、新機能が使えない、しかもパフォーマンスも悪いという残念なことになるのでご注意ください。

3. 参考文献

Pocol, “Direct3D 12ゲームグラフィックス実践ガイド”, pp.42-95, 技術評論社, 2021.

サンプルコード

本ソースコードおよびプログラムはMITライセンスに準じます。
プログラムの作成にはWindows 11, およびMicrosoft Visual Studio 2026 Communityを用いています。




Copyright © 2006-2026 Pocol.