|
| 1 | +# Vulkan Instance |
| 2 | + |
| 3 | +Instead of linking to Vulkan (via the SDK) at build-time, we will load Vulkan at runtime. This requires a few adjustments: |
| 4 | + |
| 5 | +1. In the CMake script `VK_NO_PROTOTYPES` is defined, which turns API function declarations into function pointers |
| 6 | +1. In `app.cpp` this line is added to the global scope: `VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE` |
| 7 | +1. Before and during initialization `VULKAN_HPP_DEFAULT_DISPATCHER.init()` is called |
| 8 | + |
| 9 | +The first thing to do in Vulkan is to create a `vk::Instance`, which will enable enumeration of physical devices (GPUs) and creation of a logical device. |
| 10 | + |
| 11 | +Since we require Vulkan 1.3, store that in a constant to be easily referenced: |
| 12 | + |
| 13 | +```cpp |
| 14 | +namespace { |
| 15 | +constexpr auto vk_version_v = VK_MAKE_VERSION(1, 3, 0); |
| 16 | +} // namespace |
| 17 | +``` |
| 18 | + |
| 19 | +In `App`, create a new member function `create_instance()` and call it after `create_window()` in `run()`. After initializing the dispatcher, check that the loader meets the version requirement: |
| 20 | + |
| 21 | +```cpp |
| 22 | +void App::create_instance() { |
| 23 | + VULKAN_HPP_DEFAULT_DISPATCHER.init(); |
| 24 | + auto const loader_version = vk::enumerateInstanceVersion(); |
| 25 | + if (loader_version < vk_version_v) { |
| 26 | + throw std::runtime_error{"Loader does not support Vulkan 1.3"}; |
| 27 | + } |
| 28 | +} |
| 29 | +``` |
| 30 | + |
| 31 | +We will need the WSI instance extensions, which GLFW conveniently provides for us. Add a helper function in `window.hpp`: |
| 32 | + |
| 33 | +```cpp |
| 34 | +auto glfw::instance_extensions() -> std::span<char const* const> { |
| 35 | + auto count = std::uint32_t{}; |
| 36 | + auto const* extensions = glfwGetRequiredInstanceExtensions(&count); |
| 37 | + return {extensions, static_cast<std::size_t>(count)}; |
| 38 | +} |
| 39 | +``` |
| 40 | + |
| 41 | +Continuing with instance creation, create a `vk::ApplicationInfo` object and fill it up: |
| 42 | + |
| 43 | +```cpp |
| 44 | + auto app_info = vk::ApplicationInfo{}; |
| 45 | + app_info.setPApplicationName("Learn Vulkan").setApiVersion(vk_version_v); |
| 46 | +``` |
| 47 | + |
| 48 | +Create a `vk::InstanceCreateInfo` object and fill it up: |
| 49 | + |
| 50 | +```cpp |
| 51 | + auto instance_ci = vk::InstanceCreateInfo{}; |
| 52 | + auto const extensions = glfw::instance_extensions(); |
| 53 | + instance_ci.setPApplicationInfo(&app_info).setPEnabledExtensionNames( |
| 54 | + extensions); |
| 55 | +``` |
| 56 | + |
| 57 | +Add a `vk::UniqueInstance` member, create it, and initialize the dispatcher against it: |
| 58 | + |
| 59 | +```cpp |
| 60 | + m_instance = vk::createInstanceUnique(instance_ci); |
| 61 | + VULKAN_HPP_DEFAULT_DISPATCHER.init(*m_instance); |
| 62 | +``` |
| 63 | + |
| 64 | +Make sure VkConfig is running with validation layers enabled, and debug/run the app. If "Information" level loader messages are enabled, you should see quite a bit of console output at this point: information about layers being loaded, physical devices and their ICDs being enumerated, etc. |
| 65 | + |
| 66 | +If this line or equivalent is not visible in the logs, re-check your Vulkan Configurator setup and `PATH`: |
| 67 | + |
| 68 | +``` |
| 69 | +INFO | LAYER: Insert instance layer "VK_LAYER_KHRONOS_validation" |
| 70 | +``` |
| 71 | + |
| 72 | +Congratulations, you have successfully initialized a Vulkan Instance! |
| 73 | + |
| 74 | +> Wayland users: seeing the window is still a long way off, these VkConfig/validation logs are your only feedback for now. |
0 commit comments