ラベル DirectX の投稿を表示しています。 すべての投稿を表示
ラベル DirectX の投稿を表示しています。 すべての投稿を表示

2015年9月25日金曜日

DXGIFactoryの生成または取得方法

生成または取得する方法がいくつかあるのでまとめておきます.

#include <Windows.h>
#include <tchar.h>
#include <wrl/client.h>
#include <d3d11_3.h>
#include <dxgi1_4.h>

#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "dxgi.lib")

using namespace Microsoft::WRL;
using namespace std;

int WINAPI wWinMain(
    HINSTANCE hInstance,
    HINSTANCE,
    LPWSTR lpCmdLine,
    int nCmdShow
)
{
    HRESULT hr = S_OK;

    // CreateDXGIFactoryによるDXGIFactoryの生成
    {
        ComPtr<idxgifactory> pFactory;
        hr = CreateDXGIFactory(
            IID_PPV_ARGS(pFactory.GetAddressOf())
        );
        if(FAILED(hr)) { return 0; }

        // インターフェースがサポートされていない,と失敗する
        // ComPtr<idxgifactory1> pFactory1;
        // hr = pFactory.As(&pFactory1);
        // if(FAILED(hr)) { return 0; }
    }

    // CreateDXGIFactory1によるDXGIFactory1の生成 (Windows 7以降)
    {
        ComPtr<idxgifactory1> pFactory1;
        hr = CreateDXGIFactory1(
            IID_PPV_ARGS(pFactory1.GetAddressOf())
        );
        if(FAILED(hr)) { return 0; }

        ComPtr<idxgifactory> pFactory;
        hr = pFactory1.As(&pFactory);
        if(FAILED(hr)) { return 0; }

        ComPtr<idxgifactory3> pFactory3;
        hr = pFactory1.As(&pFactory3);
        if(FAILED(hr)) { return 0; }

        ComPtr<idxgifactory4> pFactory4;
        hr = pFactory1.As(&pFactory4);
        if(FAILED(hr)) { return 0; }
    }

    // CreateDXGIFactory2によるDXGIFactory2の生成 (Windows 8.1以降)
    {
        ComPtr<idxgifactory2> pFactory2;
        ULONG creationFlag = 0;
#ifdef _DEBUG
        creationFlag |= DXGI_CREATE_FACTORY_DEBUG;
#endif

        hr = CreateDXGIFactory2(
            creationFlag,
            IID_PPV_ARGS(pFactory2.GetAddressOf())
        );
        if(FAILED(hr)) { return 0; }

        ComPtr<idxgifactory> pFactory;
        hr = pFactory2.As(&pFactory);
        if(FAILED(hr)) { return 0; }

        ComPtr<idxgifactory1> pFactory1;
        hr = pFactory2.As(&pFactory1);
        if(FAILED(hr)) { return 0; }

        ComPtr<idxgifactory3> pFactory3;
        hr = pFactory2.As(&pFactory3);
        if(FAILED(hr)) { return 0; }

        ComPtr<idxgifactory4> pFactory4;
        hr = pFactory2.As(&pFactory4);
        if(FAILED(hr)) { return 0; }
    }

    // D3D機能レベルの一覧を用意
    D3D_FEATURE_LEVEL featureLevels[] =
    {
        D3D_FEATURE_LEVEL_12_1,
        D3D_FEATURE_LEVEL_12_0,
        D3D_FEATURE_LEVEL_11_1,
        D3D_FEATURE_LEVEL_11_0,
        D3D_FEATURE_LEVEL_10_1,
        D3D_FEATURE_LEVEL_10_0,
        D3D_FEATURE_LEVEL_9_3,
        D3D_FEATURE_LEVEL_9_2,
        D3D_FEATURE_LEVEL_9_1,
    };
    D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_9_1;
    UINT deviceCreationFlag = 0;

    // D3D11デバイスおよびイメディエイトコンテキストの生成
    ComPtr<id3d11device> pDevice;
    ComPtr<id3d11devicecontext> pImmediateContext;
    hr = D3D11CreateDevice(
        nullptr,
        D3D_DRIVER_TYPE_HARDWARE,
        nullptr,
        deviceCreationFlag,
        featureLevels,
        _countof(featureLevels),
        D3D11_SDK_VERSION,
        pDevice.GetAddressOf(),
        &featureLevel,
        pImmediateContext.GetAddressOf()
    );
    if(FAILED(hr)) { return 0; }

    ComPtr<idxgidevice> pDXGIDevice;
    hr = pDevice.As(&pDXGIDevice);
    if(FAILED(hr)) { return 0; }

    // D3D11DeviceからDXGIDeviceを取得し,
    // DXGIDeviceからDXGIAdapterを取得し,
    // DXGIAdapterの親であるDXGIFactoryを取得する.
    // そこからIDXGIFactory1,2,3,4を取得する.
    {
        ComPtr<idxgiadapter> pDXGIAdapter;
        hr = pDXGIDevice->GetAdapter(
            pDXGIAdapter.GetAddressOf()
        );
        if(FAILED(hr)) { return 0; }

        ComPtr<idxgifactory> pFactory;
        hr = pDXGIAdapter->GetParent(
            IID_PPV_ARGS(pFactory.GetAddressOf())
        );
        if(FAILED(hr)) { return 0; }

        ComPtr<idxgifactory1> pFactory1;
        hr = pFactory.As(&pFactory1);
        if(FAILED(hr)) { return 0; }なn

        ComPtr<idxgifactory2> pFactory2;
        hr = pFactory.As(&pFactory2);
        if(FAILED(hr)) { return 0; }

        ComPtr<idxgifactory3> pFactory3;
        hr = pFactory.As(&pFactory3);
        if(FAILED(hr)) { return 0; }

        ComPtr<idxgifactory4> pFactory4;
        hr = pFactory.As(&pFactory4);
        if(FAILED(hr)) { return 0; }
    }

    return 0;
}

CreateDXGIFactoryでDXGIFactoryを生成した場合,以降のIDXGIFactory1,2,3,4のインターフェースをサポートしたオブジェクトにはならないようです.

ところで,D3D11DeviceからDXGIDeviceを取得できるって,どこかに関係の説明があるんでしょうか?
MSDNにサンプルがあったのでこうできるというのは分かったんですが,その関係性が書いてあるドキュメントが見つけられないんですよね.

2015/09/26 追記

IDXGIDeviceのドキュメントが2つあって,
こちらには情報が載っていなくて,
こちらには載っていました.
何なんだろう.

2012年1月12日木曜日

IDirect3D9::GetAdapterIdentifier

ドライバ名とかグラフィックスボードの名前まで取得可能.そして,そこまでの情報を利用する必要があるのかは良く分からない.PCゲームはあまりやらないからなぁ.

#include <sdkddkver.h>

#define WIN32_LEAN_AND_MEAN
#include <Windows.h>

#include <tchar.h>
#include <sstream>
typedef std::basic_ostringstream<TCHAR> tostringstream;

#include <d3d9.h>

#include <memory>

template <typename T>
struct release_deleter {
    typedef T * pointer;

    void operator()(T * p) const
    {
        p->Release();
    }
};

typedef std::unique_ptr<IDirect3D9, release_deleter<IDirect3D9> > d3d_ptr;

int APIENTRY _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int)
{
    // IDirect3D9オブジェクトの生成
    d3d_ptr pD3D(Direct3DCreate9(D3D_SDK_VERSION));

    // エラーチェック
    if(pD3D == NULL){
        MessageBox(
            NULL,
            TEXT("IDirect3D9のオブジェクトを生成できませんでした."),
            TEXT("失敗"),
            MB_OK
        );
        return -1;
    }

    UINT n = pD3D->GetAdapterCount();
    for(UINT i = 0; i < n; ++i){
        D3DADAPTER_IDENTIFIER9 identifier;
        pD3D->GetAdapterIdentifier(
            i,
            0,  // D3DENUM_WHQL_LEVELを指定するとネットから情報取得?
            &identifier
        );

        // GetAdapterIdentifier()の結果を文字列に
        tostringstream msg;
        msg << "Adapter " << i << '\n';
        msg << "Driver           : " << identifier.Driver << '\n';
        msg << "Description      : " << identifier.Description << '\n';
        msg << "DeviceName       : " << identifier.DeviceName << '\n';
        msg << "DriverVersion\n";
        msg << "    Product      : " << HIWORD(identifier.DriverVersion.HighPart) << '\n';
        msg << "    Version      : " << LOWORD(identifier.DriverVersion.HighPart) << '\n';
        msg << "    SubVersion   : " << HIWORD(identifier.DriverVersion.LowPart) << '\n';
        msg << "    Build        : " << LOWORD(identifier.DriverVersion.LowPart) << '\n';
        msg << "VendorId         : " << identifier.VendorId << '\n';
        msg << "DeviceId         : " << identifier.DeviceId << '\n';
        msg << "SubSysId         : " << identifier.SubSysId << '\n';
        msg << "Revision         : " << identifier.Revision << '\n';
        // msg << "DeviceIdentifier : " << identifier.DeviceIdentifier << '\n';
        msg << "WHQLLevel        : " <<
            (identifier.WHQLLevel >> 16) << TEXT("年") << 
            ((identifier.WHQLLevel & 0xFFFF) >> 8) << TEXT("月") <<
            (identifier.WHQLLevel & 0xFF) << TEXT("日\n");

        MessageBox(
            NULL,
            msg.str().c_str(),
            TEXT("結果"),
            MB_OK
        );
    }
    
    return 0;
}

IDirect3D9::EnumAdapterModes

EnumAdapterModesは,指定されたアダプタ,フォーマットで指定された番号のモードに関して,幅,高さ,リフレッシュレート,フォーマットを,最後の引数に渡したポインタが指す変数に返す.しかし,日本語のドキュメントが最後の引数が配列,と書いていたけど,英語だと単なるポインタになっているので,誤訳だと思われる.

#include <sdkddkver.h>

#define WIN32_LEAN_AND_MEAN
#include <Windows.h>

#include <tchar.h>
#include <sstream>
typedef std::basic_ostringstream<TCHAR> tostringstream;

#include <d3d9.h>

#include <memory>

template <typename T>
struct release_deleter {
    typedef T * pointer;

    void operator()(T * p) const
    {
        p->Release();
    }
};

typedef std::unique_ptr<IDirect3D9, release_deleter<IDirect3D9> > d3d_ptr;

int APIENTRY _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int)
{
    // IDirect3D9オブジェクトの生成
    d3d_ptr pD3D(Direct3DCreate9(D3D_SDK_VERSION));

    // エラーチェック
    if(pD3D == NULL){
        MessageBox(
            NULL,
            TEXT("IDirect3D9のオブジェクトを生成できませんでした."),
            TEXT("失敗"),
            MB_OK
        );
        return -1;
    }

    UINT n = pD3D->GetAdapterCount();
    for(UINT i = 0; i < n; ++i){

        UINT m = pD3D->GetAdapterModeCount(i, D3DFMT_X8R8G8B8);
        for(UINT j = 0; j < m; ++j){
            D3DDISPLAYMODE DisplayMode;
            pD3D->EnumAdapterModes(i, D3DFMT_X8R8G8B8, j, &DisplayMode);
            
            // EnumAdapterModes()の結果を文字列に
            tostringstream msg;
            msg << "Adapter " << i << " : Mode " << j << '\n';
            msg << "Format      : " << DisplayMode.Format << '\n';
            msg << "Width       : " << DisplayMode.Width << '\n';
            msg << "Height      : " << DisplayMode.Height << '\n';
            msg << "RefreshRate : " << DisplayMode.RefreshRate << '\n';

            /* 結果の表示は大量に出ることもあるのでコメントアウト
            MessageBox(
                NULL,
                msg.str().c_str(),
                TEXT("結果"),
                MB_OK
            );
            */
        }
    }
    
    return 0;
}

こっそり,IDirect3D9オブジェクトの解放をuniqu_ptrにやらせるように変更してみたり.

2012年1月10日火曜日

IDirect3D9::GetAdapterModeCount

ディスプレイモードの数を返すIDirect3D9::GetAdapterModeCount.最初の引数は,0以上でIDirect3D9::GetAdapterCount()が返す値未満の値を渡す.第二引数には,D3DFORMATの値を渡す.ただ,D3DFORMATの値ならどれでも良いのかが,ドキュメント読んだだけではいまいち分からない.

#include <sdkddkver.h>

#define WIN32_LEAN_AND_MEAN
#include <Windows.h>

#include <tchar.h>
#include <sstream>
typedef std::basic_ostringstream<TCHAR> tostringstream;

#include <d3d9.h>

int APIENTRY _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int)
{
    // IDirect3D9オブジェクトの生成
    LPDIRECT3D9 pD3D = Direct3DCreate9(D3D_SDK_VERSION);

    // エラーチェック
    if(pD3D == NULL){
        MessageBox(
            NULL,
            TEXT("IDirect3D9のオブジェクトを生成できませんでした."),
            TEXT("失敗"),
            MB_OK
        );
        return -1;
    }

    UINT n = pD3D->GetAdapterCount();
    for(UINT i = 0; i < n; ++i){
        // GetAdapterModeCount()の結果を文字列に
        tostringstream msg;

        msg << "Adapter " << i << '\n';
        msg << "D3DFMT_X8R8G8B8     : " << pD3D->GetAdapterModeCount(i, D3DFMT_X8R8G8B8) << '\n';

        MessageBox(
            NULL,
            msg.str().c_str(),
            TEXT("結果"),
            MB_OK
        );
    }
    
    // 後始末
    pD3D->Release();

    return 0;
}

IDirect3D9::GetAdapterCount

Direct3DCreate9()でIDirect3D9オブジェクトを生成したので,そのオブジェクトを使ったコードを書いていってみよう.他のオブジェクトを必要とせずに書けるのはどこまでだろう.

とりあえず,今回はGetAdapterCount().その名の通りアダプタの数を取得する.アダプタというのは,出力先と考えれば良いっぽい.

#include <sdkddkver.h>

#define WIN32_LEAN_AND_MEAN
#include <Windows.h>

#include <tchar.h>
#include <sstream>
typedef std::basic_ostringstream<TCHAR> tostringstream;

#include <d3d9.h>

int APIENTRY _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int)
{
    // IDirect3D9オブジェクトの生成
    LPDIRECT3D9 pD3D = Direct3DCreate9(D3D_SDK_VERSION);

    // エラーチェック
    if(pD3D == NULL){
        MessageBox(
            NULL,
            TEXT("IDirect3D9のオブジェクトを生成できませんでした."),
            TEXT("失敗"),
            MB_OK
        );
        return -1;
    }

    // GetAdapterCount()の結果を文字列に
    tostringstream msg;
    msg << "GetAdapterCount() == " << pD3D->>GetAdapterCount();

    MessageBox(
        NULL,
        msg.str().c_str(),
        TEXT("結果"),
        MB_OK
    );
    
    // 後始末
    pD3D->Release();

    return 0;
}

複数ディスプレイがある場合に,どのディスプレイに出力するか選べるとかに使うんだろうか? 実は使い道が分かっていない.

2012年1月9日月曜日

Direct3DCreate9

思いつきで,DirectX 9から順に11に向かって,それぞれの関数なんかを対象に,それを利用したコードを書いてみようかと.というわけで,まずはDirect3DをDirectX 9で使う場合に必須の,Direct3DCreate9のコードを書いてみた.

#include <sdkddkver.h>

#define WIN32_LEAN_AND_MEAN
#include <Windows.h>

#include <tchar.h>

#include <d3d9.h>

int APIENTRY _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int)
{
    // IDirect3D9オブジェクトの生成
    LPDIRECT3D9 pD3D = Direct3DCreate9(D3D_SDK_VERSION);

    // エラーチェック
    if(pD3D != NULL){
        MessageBox(
            NULL,
            TEXT("IDirect3D9のオブジェクトを生成しました."),
            TEXT("成功"),
            MB_OK
        );
    }else{
        MessageBox(
            NULL,
            TEXT("IDirect3D9のオブジェクトを生成できませんでした."),
            TEXT("失敗"),
            MB_OK
        );
        return -1;
    }

    // IDirect3D9オブジェクトの後始末
    pD3D->Release();

    return 0;
}

Direct3DCreate9の引数は必ずD3D_SDK_VERSIONにしなくてはならない,とのこと.
Direct3DCreate9Exという関数もあるけれど,これはVista以降でないと使えないので注意,ということ.
こっちはまた今度書いてみよう.