Vulkan 画三角形第二章:创建 Vulkan 实例
开始一切之前,我们先引入 Vulkan 的头文件
#include <vulkan/vulkan.h>
注意这行代码要写在包含 GLFW 之前,因为 GLFW 可以通过条件编译来为 Vulkan 提供一些支持
创建实例
然后要做的事情就是创建 Vulkan 实例。实例可以把你的应用程序跟 Vulkan 类库连接起来,创建实例需要指定一些信息
首先添加一个成员变量用来保存和处理实例
VkInstance instance;
然后添加一个成员函数 createInstance
用于创建实例,并在 initVulkan
中调用它
void initVulkan() {
createInstance();
}
接下来我们开始填充这个成员函数
首先我们需要填充一个结构体用于存储我们应用程序的相关信息。这并不是必须的,但是驱动可以通过我们提供的信息对我们的应用进行优化。比如说我们的应用如果使用了一个知名的图形引擎,那么驱动就可以针对这个引擎的特定行为进行优化
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;
}
对于这个结构体,我们在 sType
中明确地指定了它的类型,并且 Vulkan 中大部分的其他结构体也都是一样
接下来我们需要填充另一个结构体,这个结构体存储着创建实例所需要的信息,并作会在创建实例时直接把这个结构体作为参数传递过去。需要注意的是,Vulkan 中的大部分方法调用也都是直接传递一个结构体,而不是拆开为一个一个的参数
我们在 createInstance
方法的末端添加以下代码
// 实例创建信息
VkInstanceCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
createInfo.pApplicationInfo = &appInfo;
这两行代码的作用显而易见,然后我们来指定扩展。Vulkan 是一个跨平台的 API,这就意味着你需要一些扩展来跟窗体系统交互。而 GLFW 提供了方便的内建函数来获取所需要的扩展,于是我们只需要把它们存入结构体中就行了
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!");
贴一下 createInstance
的完整代码,但其实就是把上面的代码片段按顺序拼接到 createInstance
函数里,为了方便,后面的文章就不贴完整代码了
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!");
}
销毁实例
另外,需要在 cleanup
函数中销毁实例
void cleanup() {
vkDestroyInstance(instance, nullptr);
glfwDestroyWindow(window);
glfwTerminate();
}
最后我们可以调试看看有没有写错