2016年7月6日水曜日

Vulkan - インスタンスの生成と破棄

ようやくVulkanインスタンスを生成します.

VkApplicationInfoの初期化

Vulkanインスタンスを生成するために,構造体VkInstanceCreateInfoが必要です.
この構造体を初期化するために,構造体VkApplicationInfoを初期化する必要があります.

構造体VkApplicationInfoは,次のような構造になっています.

struct VkApplicationInfo {
    VkStructureType    sType;
    const void*        pNext;
    const char*        pApplicationName;
    uint32_t           applicationVersion;
    const char*        pEngineName;
    uint32_t           engineVersion;
    uint32_t           apiVersion;
};

sTypeには,VK_STRUCTURE_TYPE_APPLICATION_INFOを設定する必要があります.
pNextはnullptrを設定する必要があります.
apiVersionには,VK_API_VERSION_1_0を設定します.今のところ,他のバージョンを設定するとインスタンスが生成できない場合があります.
pApplicatoinName,applicationVersion,pEngineName,engineVersionは適当でも大丈夫そうですが,今後どうなるかは分かりません.

VkInstanceCreateInfoの初期化

VkApplicationInfoを初期化したら,VkInstanceCreateInfoを初期化します.VkInstanceCreateInfoは次のような構造になっています.

struct VkInstanceCreateInfo {
    VkStructureType             sType;
    const void*                 pNext;
    VkInstanceCreateFlags       flags;
    const VkApplicationInfo*    pApplicationInfo;
    uint32_t                    enabledLayerCount;
    const char* const*          ppEnabledLayerNames;
    uint32_t                    enabledExtensionCount;
    const char* const*          ppEnabledExtensionNames;
};

sTypeには,VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFOを設定する必要があります.
pNextはnullptrを設定する必要があります.
flagsは今後のために予約されており,現時点では0を指定します.
pApplicationInfoには,前もって初期化しておいたVkApplicationInfoの変数へのポインタを設定します.
enabledLayerCountには有効にしたいレイヤーの数を,ppEnabledLayerNamesには有効にしたいレイヤー名へのポインタの配列を設定します.
enabledExtensionCount,ppEnabledExtensionNamesもレイヤーと同様に,有効にしたい拡張機能の数と名前へのポインタの配列を設定します.

Vulkanインスタンスの生成

VkInstanceCreateInfoが初期化できたら,次のようなvkCreateInstance()を呼び出してVulkanインスタンスを生成します.

VkResult vkCreateInstance(
    const VkInstanceCreateInfo * pCreateInfo,
    const VkAllocationCallbacks * pAllocator,
    VkInstance * pInstance
);

pCreateInfoには,初期化しておいたVkInstanceCreateInfoの変数へのポインタを渡します.
pAllocatorは,nullptrを指定します.適切な設定をすると,メモリ管理を制御できるのですが,今回は触れません.
pInstanceには,実際に生成されたVulkanインスタンスへのハンドルが設定されるので,VkInstanceの変数へのポインタを渡します.

Vulkanインスタンスの破棄

最後に,次のようなvkDestroyInstance()を呼び出してインスタンスを破棄して終了です.

void vkDestroyInstance(
    VkInstance * pInstance
    const VkAllocationCallbacks * pAllocator
);

実例

以下は,実際にVulkanインスタンスを生成して破棄するだけのコードです.本来は,それぞれのレイヤーがあるかどうか,拡張機能は利用できるかどうか,などを確認すべきですが,ここではそのあたりは省略しています.

#include <iostream>
#include <vector>
#include <vulkan/vulkan.h>

#pragma comment(lib, "vulkan-1")

using namespace std;

int main()
{
    // アプリケーション情報を初期化
    VkApplicationInfo applicationInfo {};
    applicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
    applicationInfo.pNext = nullptr;
    applicationInfo.pApplicationName = "";
    applicationInfo.applicationVersion = 0;
    applicationInfo.pEngineName = "";
    applicationInfo.engineVersion = 0;
    // VK_VERSION_1_0と間違えないこと
    applicationInfo.apiVersion = VK_API_VERSION_1_0;

    // APIの実引数をダンプしてくれるレイヤーを有効化しておく
    vector<const char *> layerNames {
        "VK_LAYER_LUNARG_api_dump"
    };
    // 今後必要になる拡張機能を有効にしておく
    vector<const char *> extensionNames {
        "VK_KHR_surface",
        "VK_KHR_win32_surface"
    };

    // インスタンス生成情報を初期化
    VkInstanceCreateInfo instanceCreateInfo {};
    instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
    instanceCreateInfo.pNext = nullptr;
    instanceCreateInfo.flags = 0;
    instanceCreateInfo.pApplicationInfo = &applicationInfo;
    instanceCreateInfo.enabledLayerCount = layerNames.size();
    instanceCreateInfo.ppEnabledLayerNames = layerNames.data();
    instanceCreateInfo.enabledExtensionCount = extensionNames.size();
    instanceCreateInfo.ppEnabledExtensionNames = extensionNames.data();

    // Vulkanインスタンスを生成
    VkInstance instance = VK_NULL_HANDLE;
    VkResult result = vkCreateInstance(&instanceCreateInfo, nullptr, &instance);
    if(result != VK_SUCCESS)
    {
        cerr << "Vulkanインスタンスの生成に失敗" << endl;
        return -1;
    }
    cout << "Vulkanインスタンスの生成に成功" << endl;

    vkDestroyInstance(instance, nullptr);
}

サンプルコードは,ryutorion/LearningVulkan (GitHubリポジトリ)の003_CreateInstanceにもあります.

Vulkan - インスタンス拡張機能の列挙

拡張機能とは

レイヤーの列挙,でも書いたように,レイヤーはVulkan APIによって発行されるコマンドに割り込みをかけるものです.

一方,拡張機能はVulkanのコマンドなどを追加します.

インスタンス拡張機能の列挙

拡張機能を列挙するための手順は,レイヤーを列挙する際の手順に似ています.インスタンス拡張機能の場合,次のようなvkEnumerateInstanceExtensionProperties()を呼び出します.

VkResult vkEnumerateInstanceExtensionProperties(
    const char * pLayerName,
    uint32_t * pPropertyCount,
    VkExtensionProperties * pProperties
);

仮引数の名前を見ると分かるように,インスタンス拡張機能はレイヤーに紐付いています.ただし,pLayerNameにnullptrを指定することも可能で,その場合はデフォルトで利用可能なインスタンス拡張が列挙されます.

インスタンス拡張機能の情報は,次のような構造体に保存されます.

struct VkExtensionProperties {
    char        extensionName[VK_MAX_EXTENSION_NAME_SIZE];
    uint32_t    specVersion;
};

以下の例では,利用可能なレイヤー名を全て取得し,更にnullptrを追加した上で,インスタンス拡張を列挙して,その情報をダンプしています.

#include <iostream>
#include <vector>
#include <vulkan/vulkan.h>

#pragma comment(lib, "vulkan-1")

using namespace std;

class version
{
public:
    version(uint32_t value) : mValue(value) {}

    uint32_t value() const { return mValue; }
    uint32_t major() const { return VK_VERSION_MAJOR(mValue); }
    uint32_t minor() const { return VK_VERSION_MINOR(mValue); }
    uint32_t patch() const { return VK_VERSION_PATCH(mValue); }

private:
    uint32_t mValue;
};

std::ostream & operator<<(std::ostream & out, const version & v)
{
    out << v.major() << "." << v.minor() << "." << v.patch();
    return out;
}

int main()
{
    VkResult result = VK_SUCCESS;
    vector<VkLayerProperties> layers {};
    do {
        uint32_t count = 0;
        result = vkEnumerateInstanceLayerProperties(&count, nullptr);
        if(result != VK_SUCCESS)
        {
            break;
        }

        layers.resize(count);
        result = vkEnumerateInstanceLayerProperties(&count, layers.data());
    } while(result == VK_INCOMPLETE);

    // レイヤー名の配列を生成
    vector<const char *> layerNames(layers.size() + 1);
    for(auto i = 0; i < layers.size(); ++i)
    {
        layerNames[i] = layers[i].layerName;
    }
    layerNames[layers.size()] = nullptr;

    for(auto layerName : layerNames)
    {
        cout << (layerName ? layerName : "No Layer Name") << endl;

        // レイヤーに対応する拡張の取得
        vector<VkExtensionProperties> extensions;
        do {
            uint32_t count = 0;
            result = vkEnumerateInstanceExtensionProperties(layerName, &count, nullptr);
            if(result != VK_SUCCESS)
            {
                break;
            }

            extensions.resize(count);
            result = vkEnumerateInstanceExtensionProperties(layerName, &count, extensions.data());
        } while(result == VK_INCOMPLETE);

        for(auto & extension : extensions)
        {
            cout << "\tExtension Name        : " << extension.extensionName << endl;
            cout << "\tSpecification Version : " << version(extension.specVersion) << endl;
            cout << endl;
        }
    }
}

GitHubのリポジトリryutorion/LearningVulkanの002_EnumerateInstanceExtensionsに実際のコードがあります.

2016年7月5日火曜日

Vulkan - レイヤーの列挙

最近ブログ書いてなかったので,Vulkanについて調べたり試したことを書いていこうかと思います.

環境

OS Windows 10 Pro
GPU NVIDIA GeForce GTX 860M (ドライバー 368.22)
Vulkan SDKバージョン 1.0.17.0

レイヤーとは

Vulkanのインスタンス,またはインスタンスを介して生成されたオブジェクトに対して発行されるVulkanのコマンドに対して,割り込みをかけるための機能です.

例えば,VK_LAYER_LUNARG_api_dumpというレイヤーは,VulkanのAPIを実行した際に,実引数をダンプしてくれます.

レイヤーは,Vulkanのインスタンスを生成する際に指定することで有効になります.

レイヤーの列挙

利用可能なレイヤーの一覧を取得するには,次のvkEnumerateInstanceLayerProperties()を利用します.
VkResult vkEnumerateInstanceLayerProperties(
    uint32_t * pPropertyCount,
    VkLayerProperties * pProperties
);

まず,pPropertyCountに変数へのポインタ,pPropertiesにnullptrを渡すことでレイヤーの数を取得します.
uint32_t count;
vkEnumerateInstanceLayerProperties(&count, nullptr);

次に,必要なバッファを用意して各レイヤーの情報を取得します.ここでは,vectorクラスを利用しています.
vector<VkLayerProperties> layers {};
VkResult result = vkEnumerateInstanceLayerProperties(&count, layers.data());

実際に各レイヤーの情報を取得する際に,レイヤーの数を取得してから情報を取得するまでの間に,レイヤーが追加される場合があります.そんな珍しい状況が発生した場合,vkEnumerateInstanceLayerProperties()はVK_INCOMPLETEを返します.VK_INCOMPLETEが返された場合,レイヤー数の取得からやり直します.

取得されたレイヤーの情報は,次のような構造体に格納されます.

struct VkLayerProperties {
    char        layerName[VK_MAX_EXTENSION_NAME_SIZE];
    uint32_t    specVersion;
    uint32_t    implementationVersion;
    char        description[VK_MAX_DESCRIPTION_SIZE];
};

サンプルコード

以下のコードは,vkEnumerateInstanceLayerProperties()を使って,全てのレイヤー情報をダンプするものです.Vulkanのバージョン情報を分かりやすい形で表示するために,versionクラスを導入しています.

#include <iostream>
#include <vector>
#include <vulkan/vulkan.h>

#pragma comment(lib, "vulkan-1")

using namespace std;

class version
{
public:
    version(uint32_t value) : mValue(value) {}

    //! 値を返す
    uint32_t value() const { return mValue; }

    //! メジャーバージョンを返す
    uint32_t major() const { return VK_VERSION_MAJOR(mValue); }

    //! マイナーバージョンを返す
    uint32_t minor() const { return VK_VERSION_MINOR(mValue); }

    //! パッチバージョンを返す
    uint32_t patch() const { return VK_VERSION_PATCH(mValue); }

private:
    uint32_t mValue;
};

std::ostream & operator<<(std::ostream & out, const version & v)
{
    out << v.major() << "." << v.minor() << "." << v.patch();
    return out;
}

int main()
{
    VkResult result = VK_SUCCESS;
    vector layers {};
    do {
        // レイヤー数を取得
        uint32_t count = 0;
        result = vkEnumerateInstanceLayerProperties(&count, nullptr);
        if(result != VK_SUCCESS)
        {
            break;
        }

        // 各レイヤーのプロパティを取得
        layers.resize(count);
        result = vkEnumerateInstanceLayerProperties(&count, layers.data());

        // 全てのレイヤーを取得していない場合,やり直す
    } while(result == VK_INCOMPLETE);

    // 各レイヤーのプロパティを出力する
    for(auto layer : layers)
    {
        cout << "Layer Name             : " << layer.layerName << endl;
        cout << "Specification Version  : " << version(layer.specVersion) << endl;
        cout << "Implementation Version : " << version(layer.implementationVersion) << endl;
        cout << "Description            : " << layer.description << endl;
        cout << endl;
    }
}

インスタンスを生成する際には上記の手順で取得したレイヤーを指定すれば良いのですが,まだ問題が起きるレイヤーがあります.しばらくは,レイヤーの使用に問題が無いか確認してから,本番環境で有効化するか検討した方が良いでしょう.

サンプルコードは,ryutorion/LearningVulkan (GitHubリポジトリ)の001_EnumerateInstanceLayerにもあります.

2016年3月9日水曜日

Code alignment Visual Studio拡張

ふと思い立って検索したところ,Code alignmentというVisual Studioの拡張機能を見つけました.
名前の通り,コードの整列をしてくれる拡張機能です.なお,Notepad++にも対応しているようです.

例えば,こんなコードがあったとします.
DXGI_SWAP_CHAIN_DESC SwapChainDesc{};
SwapChainDesc.BufferDesc.Width = Width;
SwapChainDesc.BufferDesc.Height = Height;
SwapChainDesc.BufferDesc.RefreshRate.Numerator = 60;
SwapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
SwapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
SwapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
SwapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
SwapChainDesc.SampleDesc.Count = 1;
SwapChainDesc.SampleDesc.Quality = 0;
SwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
SwapChainDesc.BufferCount = 1;
SwapChainDesc.OutputWindow = hWnd;
SwapChainDesc.Windowed = TRUE;
SwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
SwapChainDesc.Flags = 0;

Ctrl+Shift+;でダイアログを表示し,そろえるための文字を指定します.
例えば,"="を指定すると,次のようになります.

SwapChainDesc.BufferDesc.Width                   = Width;
SwapChainDesc.BufferDesc.Height                  = Height;
SwapChainDesc.BufferDesc.RefreshRate.Numerator   = 60;
SwapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
SwapChainDesc.BufferDesc.Format                  = DXGI_FORMAT_R8G8B8A8_UNORM;
SwapChainDesc.BufferDesc.ScanlineOrdering        = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
SwapChainDesc.BufferDesc.Scaling                 = DXGI_MODE_SCALING_UNSPECIFIED;
SwapChainDesc.SampleDesc.Count                   = 1;
SwapChainDesc.SampleDesc.Quality                 = 0;
SwapChainDesc.BufferUsage                        = DXGI_USAGE_RENDER_TARGET_OUTPUT;
SwapChainDesc.BufferCount                        = 1;
SwapChainDesc.OutputWindow                       = hWnd;
SwapChainDesc.Windowed                           = TRUE;
SwapChainDesc.SwapEffect                         = DXGI_SWAP_EFFECT_DISCARD;
SwapChainDesc.Flags                              = 0;

ブログの幅の関係で汚く見えるかもしれませんが,Visual Studio上で見る分にはスッキリして見えます.

また,よく使うパターンについてはショートカットが用意されています.
Tools(ツール) > Options(オプション) > Environment(環境) > Keyboard(キーボード)でEdit.Alignあたりまでを検索ボックスに入力すると,ショートカットが確認でき,ショートカットキーを割り当てることができます.

例えば,Edit.AlignByEqual(=で整列),Edit.AlignByEqualEqual(==で整列)などがあるようです.

2016年1月29日金曜日

TortoiseSVNのインストール,およびメニューの日本語化手順

バージョン管理というと,最近の流行りはGitなのですが,まだまだSubversionを使う機会もあります.

Windows環境でSubversionを使う場合,いくつかソフトウェアがありますが,ここではTortoiseSVN(トータスエスブイエヌ)を紹介します.以下の手順は,Windows 10 64bit環境での手順になります.

ダウンロード

まず,TortoiseSVNのウェブサイトにアクセスします.次のような画面が表示されるので,画面上のDownloadタブをクリックし,インストーラーなどをダウンロードします.


ここでは,64bit OSという前提なので,次の図のように右側の64-bit版インストーラをダウンロードします.


合わせて,日本語化のための言語パックをダウンロードしておきます.言語パックは,TortoiseSVNのインストーラより下の方に,国別に用意されています.ここでも,64bit版を選ぶようにします.


適切にダウンロードできていれば,次の図のように2つのファイルがダウンロードされているはずです.


インストール

TortoiseSVNのインストーラを起動すると,次のような画面が表示されます.まずは,Nextを選んで先に進みましょう.


EULA(End User License Agreement),つまりライセンスへの同意が求められるので,問題が無ければNextを押して次へ進みます.


次の図のように,デフォルトではコマンドラインツールをインストールしないようになっています.しかし,コマンドラインツールは有った方が便利なので,×印が付いている部分をクリックし,"Will be installed on local hard drive"を選びましょう.これでコマンドラインツールもインストールされます.


設定ができたら,管理者権限でインストールを開始します.


インストールが終わると,次のような画面が表示されるので,Show Changelog(変更履歴の表示)のチェックを外しておいて,変更履歴が表示されないようにしてから,Finishを選んでインストールを終了します.


言語パックのインストール

このままでも使えなくはないのですが,メニューなどが日本語になっている方が良いでしょう.ダウンロードした言語パックのインストーラを起動します.特に選択肢などは無いので,そのまま「次へ」を選んで,「完了」を選びます.



言語パックをインストールしたら,適当な場所で右クリックをし,TortoiseSVNからSettingsを選びます.

設定画面が開くので,GeneralにあるLanguageを日本語に変更し,適用します.
これで,メニューが日本語化されます.

2016年1月1日金曜日

ChromeでWebGL 2.0を有効にする方法

ChromeでWebGL 2.0を実行できる環境を用意するための手順.
なお,開発版のChromeを利用する必要があるため,以下の手順を試す場合,自己責任でお願いいたします.
また,Windows 10での動作確認のため,その他のOSでの動作確認はしていません.

Chrome Canaryのインストール

公式サイトから,Chromeの開発版であるChrome Canaryをダウンロードし,インストールします.

ショートカットの編集

デスクトップにショートカットができると思うので,右クリックをして,プロパティを表示させます.このリンク先の部分の最後に,"--enable-unsafe-es3-apis"を追加します.


このショートカットからChrome Canaryを起動すれば,WebGL 2.0が利用できるようになっています.

var c = document.getElementById('canvas-id');
var gl = c.getContext('webgl2');

このように,canvas要素のgetContextメソッドに'webgl2'を渡せば,WebGL 2.0のレンダリングコンテキストが取得できます.

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つあって,
こちらには情報が載っていなくて,
こちらには載っていました.
何なんだろう.