【自作ゲームエンジン開発】Vulkan インスタンスの作成

IQZeus

はじめて読む方へ

この記事はサイト主が【自作ゲームエンジン開発】を行うまでのほぼ全行程を記事にまとめたものです。

主自体はC++からVulkanから何まで初心者のため、同じようなレベルの人の役に立てればと書いています。

上級者の方々にはあまりおすすめできない記事ですのでご了承ください。

前の記事→【自作ゲームエンジン開発】Vulkan ウィンドウの作成

自作ゲームエンジン開発記事一覧→【自作ゲームエンジン開発】記事一覧

Vulkan インスタンスの作成

どうしよう。。。

記事作成の方がプログラムより数倍時間がかかる。。。

まずは前回から増えた分のコードを載せておきます。

このコードがインスタンス作成に関係するコード+αです。

クラスと階層関係が合うように適宜コードに追加して下さい。

#include <vector>
class HelloTriangleApplication {
private:
    VkInstance instance;
    void createInstance() {
        VkApplicationInfo appInfo{};
        appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
        appInfo.pApplicationName = "Hello Triangle";
        appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
        appInfo.pEngineName = "No Engine";
        appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
        appInfo.apiVersion = VK_API_VERSION_1_0;
        VkInstanceCreateInfo createInfo{};
        createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
        createInfo.pApplicationInfo = &appInfo;
        uint32_t glfwExtensionCount = 0;
        const char** glfwExtensions;
        glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
        createInfo.enabledExtensionCount = glfwExtensionCount;
        createInfo.ppEnabledExtensionNames = glfwExtensions;
        createInfo.enabledLayerCount = 0;
        if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) {
            throw std::runtime_error("failed to create instance!");
        }
        uint32_t extensionCount = 0;
        vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
        std::vector<VkExtensionProperties> extensions(extensionCount);
        vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data());
        std::cout << "available extensions:\n";
        for (const auto& extension : extensions) {
            std::cout << '\t' << extension.extensionName << '\n';
        }
    }
}

前回の記事から増えた部分はVkInstance = instance;createInstance()の部分です。

しいて言うならあとはVectorをインクルードしています。

必要な構造体の作成

コードの説明ですが、まずはVulkanインスタンスを作成するのに必要な構造体を作成します。

ですが、その構造体を作るために別の構造体も必要なので先にそちらから作成します。

それがVkApplicationInfo構造体です。

appInfo{}と書かれている部分ですね。

その下の6行で構造体を構成して言っているわけですが構造体の中身は見たままなので特に説明はいらないでしょう。

そういうものだとテンプレとして覚えておくのがいいと思います。

次にVkInstanceCreateInfo構造体です。

これも定型文なのでそのまま覚えるのがいいと思います。

この構造体を作るのにVkApplicationInfo構造体を使います。

次はVulkanインスタンス作成に必要な拡張機能の設定

glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);

こちらのコードを使うとVulkanインスタンスの作成に必要な拡張機能名を返してくれます。

同時にglfwExtensionCountにその拡張機能の数が入ります。

なのでこれをcreateInfoにセットしてレイヤーの数をひとまず0にセットしておけば、この構造体の設定は完了です。

Vulkanインスタンスの作成

さて、いよいよVulkanインスタンスの作成です。

vkCreateInstance(&createInfo, nullptr, &instance);この関数を使うとVulkanインスタンスを作成できます。

第一引数にはVkInstanceCreateInfo構造体を指定します。

第二引数はカスタムアロケーターコールバックを入れる。今回はnullptrでOK。

第三引数にはVkInstanceを入れます。

戻り値としてVK_SUCCESSかエラーコードが返されます。

このエラーコードで条件分岐して

if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) {
    throw std::runtime_error("failed to create instance!");
}

インスタンスの作成に失敗していたらエラーを投げます。

拡張機能サポートの確認

Vulkanでは拡張機能を設定する時に

使える拡張機能の数を取得→拡張機能の個数分拡張機能を取得→取得した拡張機能を設定する

という流れで設定を行います。

uint32_t extensionCount = 0;
vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);

std::vector<VkExtensionProperties> extensions(extensionCount);

vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data());

このコードでその取得から設定までの流れを行っています。

C++をやった事ない方は変数の更新のされ方がよく分からないと思いますが引数でした変数にそのまま規定の値が入ると考えて下さい。

そうしたらコードが理解出来るかと思います。

CleanUp

最後にcleanup関数の中でvkDestroyInstance(instance, nullptr);

を実行しインスタンスの破棄をしています。

さいごに

いかがでしたか?

私はvulkan的な難しさよりC++的な難しさの方が理解を阻みましたがなんとか出来ましたかね?

次回は検証レイヤーかな?

記事書くのめんどくさい(笑)

コメント

タイトルとURLをコピーしました