インスタンスの作成
まず最初にインスタンスという物を作ります。Vulkanを使う場合、全ての機能はこのインスタンスを介して利用します。
main関数に以下のコードを追加しましょう。
vk::InstanceCreateInfo instCreateInfo;
vk::Instance instance = vk::createInstance(instCreateInfo);
instance.destroy();
vk::createInstance関数でインスタンスを作成しています。
エラーなく実行できましたか?おめでとうございます。これであなたはVulkanインスタンスを作って壊すことに成功しました。これからあなたはVulkanインスタンスを作ってから壊すまでの間に色々な処理を書いていくことになります。
ところで、このコードではインスタンスをdestroyメソッドで明示的に破棄していますが、VulkanのC++向けラッパーであるVulkan-HppではもっとC++らしい書き方ができるように作られています。一般的なC++erであれば何かしらのオブジェクトの破棄処理を見た場合、そんな処理はプログラマーの手動ではなくデストラクタに任せたいと思うはずです。処理を以下のように書き換えましょう。
vk::InstanceCreateInfo instCreateInfo;
vk::UniqueInstance instance = vk::createInstanceUnique(instCreateInfo);
vk::Instanceがvk::UniqueInstanceに、vk::createInstanceがvk::createInstanceUniqueになっていますね。
このようにVulkan-Hppでは、破棄処理の必要な大概のオブジェクト型についてvk::Unique《オブジェクト型名》 という対応する型があり、またそれに対応したcreate《オブジェクト型名》Uniqueという関数が存在します。Vulkanの話というよりはVulkan-HppとC++の話になりますが、積極的に使っていきましょう。Unique付きの型の特性はC++標準のunique_ptrと大体同じです。メソッドはドット演算子(.)の代わりにアロー演算子(->)でアクセスできます。
インスタンス作成時のオプション
先ほど示したソースコードにvk::InstanceCreateInfoなる構造体がありました。これに色々情報を乗っけることで、例えばVulkanの拡張機能をオンにしたりだとかデバッグ情報を表示させるといったことができます。オプション的なものなのでこれの説明は後ほどに回そうと思います。
物理デバイスの取得
インスタンスを作成したら次は物理デバイスを選びます。物理デバイスというのは、実際にコンピューターに刺さっている一枚一枚のグラボだとかに対応したオブジェクトです。例えばGTX1060とintel Core i7が刺さっている構成のコンピュータであれば、物理デバイスは2つ取得できるはずです(今のintelのCPUにはintel HD GraphicsというGPUが内蔵されています)。
我々は描画する仕事をGPUに頼みたい訳なので、GPUが複数あるなら頼む相手をまず選ぶ必要があります。特殊なことでもやらない限り基本的に1つ選べば良いのですが、GPUの型式などによってサポートしている機能とサポートしていない機能があったりするため、だいたい「インスタンスを介して物理デバイスを列挙する」→「それぞれの物理デバイスの情報を取得する」→「一番いいのを頼む」という流れになります。
なお、ここで言う「選ぶ」とは、特定のGPUを完全に占有してしまうとかそういう話ではありません。詳しくは「2-2. 論理デバイス」の項で説明します。物理デバイスの一覧はvk::InstanceのenumeratePhysicalDevices関数で取得できます。
std::vector<vk::PhysicalDevice> physicalDevices = instance->enumeratePhysicalDevices();
物理デバイスはvk::PhysicalDevice型で表されます。enumeratePhysicalDevices を呼ぶとstd::vectorで一覧を返してくれます。
ここで本来であれば各物理デバイスの情報を取得して、どれを使用するか吟味して決めるプログラムを書きます。ですが、ここではそれに必要な知識をまだ説明していないので、とりあえず最初の物理デバイスを採用してしまいましょう。
vk::PhysicalDevice physicalDevice = physicalDevices[0];
ちなみにvk::Instanceにはそれに対応するvk::UniqueInstanceが存在しましたが、vk::PhysicalDeviceにはvk::UniquePhysicalDevice は存在しません。destroyなどを呼ぶ必要もありません。vk::PhysicalDeviceは単に物理的なデバイスの情報を表しているに過ぎないので、構築したり破棄したりする必要がある類のオブジェクトではないのです。
この節ではインスタンスの作成と物理デバイスの選択をやりました。次節では論理デバイスの作成をやります。
// 環境に合わせて
#define VK_USE_PLATFORM_WIN32_KHR
#define VULKAN_HPP_TYPESAFE_CONVERSION
#include <vulkan/vulkan.hpp>
#include <vector>
int main()
{
vk::InstanceCreateInfo instCreateInfo;
vk::UniqueInstance instance;
instance = vk::createInstanceUnique(instCreateInfo);
std::vector<vk::PhysicalDevice> physicalDevices = instance->enumeratePhysicalDevices();
vk::PhysicalDevice physicalDevice = physicalDevices[0];
return 0;
}