Vulkan 实例
Vulkan API 使用vkInstance
对象来存储应用级别的状态。在进行其他的操作之前,应用必须创建一个Vulkan实例。
基础的Vulkan架构看起来像这样
这个图说明,Vulkan应用与Vulkan 库相关联,使用loader。实例的创建会初始化loader。这个loader会加载和初始化一个由GPU提供的二级的图形驱动。
请注意在图表中提到的layers,它们也是被loader加载的。layers通常被用来validation。validation是驱动的错误校验。在Vulkan中,驱动比在其他的API更加的轻量化,这正是因为驱动将validation功能给layers代理的结果。layers并不是必须的,而且在每一次创建实例的时候,layers可以被选择性的加载。
vkCreateInstance
查看01-init_instance.cpp源代码,找到vkCreateInstance的调用,其原型为
VkResult vkCreateInstance(
const VkInstanceCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkInstance* pInstance);
来一点一点的分析这个函数原型
VkResult
- 函数的返回状态。
VkInstanceCreateInfo
- 创建一个实例所需要的额外的信息。这是一个相当重要的结构体。
VkAllocationCallbacks
- 用户可以设定自定义的内存分配函数,不指定的话,Vulkan会使用默认的。
例子中并没有使用这个特性,所以这个参数一直都是NULL
。
VkInstance
- 如果instance能够被顺利的创建,这个就是实例的句柄。
VkInstanceCreateInfo
结构体
Vulkan创建对象的时候,总会有一个VkObjectCreateInfo参数。
typedef struct VkInstanceCreateInfo{
VkStructureType sType;
const void* pNext;
VkInstanceCreateFlags flags;
const VkApplicationInfo* pApplicationInfo;
uint32_t enabledLayerCount;
const char* const* ppEnableLayerNames;
uint32_t enabledExtensionCount;
const char* const* ppEnabledExtensionNames;
}VkInstanceCreateInfo;
sType
- 指明这个结构体的类型。既然这是一个VkInstanceCreateInfo
结构体,你需要将其设置为VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO
。这样做的话,看起来有点重复了。但是这样做还是有一些价值的:
- driver,validation layer或者其他的该结构体的消费者,能够通过该字段做一些校验。
- 结构体可以通过void*指针来传递给使用这个结构体的对象,然后还是能够识别出这个指针该有的类型。
由于该字段总是结构体的第一个字段,该结构体的消费者总是能够轻易的确定它的类型,然后决定来如何处理它。
pNext
- 该字段通常被设置为NULL
。这个空指针有时被用于传递扩展指定的消息。
flags
- 当前没有flags被定义,将其设置为0。
pApplicationInfo
- 稍后再说。
enabledLayerCount
和 ppEnabledLayerNames
- 该教程不涉及到这个,先空着吧。
enabledExtensionCount
和 ppEnabledExtensionNames
- 稍后再讲。
VkApplicationInfo
结构体
这个结构体提供了应用的一些由Vulkan实现的基本的信息。
typedef struct VkApplicationInfo {
VkStructureType sType;
const void* pNext;
const char* pApplicationName;
uint32_t applicationVersion;
const char* pEngineName;
uint32_t engineVersion;
uint32_t apiVersion;
} VkApplicationInfo;
sType
and pNext
- 同 vkInstanceCreateInfo structure
。
pApplicationName
, applicationVersion
, pEngineName
, engineVersion
- 这些不是非得要填写的字段。一些 tools, loaders, layers, 或者 drivers 的实现可能会用这些字段进行debugging或者出报告。driver甚至可以使用这些字段来更改自身的行为。
apiVersion
- This field communicates the major, minor, and patch levels of the Vulkan API header used to compile the application. If you are using Vulkan 1.0, major should be 1 and minor should be 0. Using the VK_API_VERSION_1_0 macro from vulkan.h accomplishes this, with a patch level of 0. Differences in the patch level should not affect the full compatibility between versions that differ only in the patch level. Generally, you should set this field to VK_API_VERSION_1_0 unless you have a good reason to do otherwise.
回到代码
一旦这些结构体被填充了,sample可以创建instance了
VkInstance inst;
VkResult res;
res = vkCreateInstance(&inst_info, NULL, &inst);
if (res == VK_ERROR_INCOMPATIBLE_DRIVER) {
std::cout << "cannot find a compatible Vulkan ICD\n";
exit(-1);
} else if (res) {
std::cout << "unknown error\n";
exit(-1);
}
vkDestroyInstance(inst, NULL);
在上面的代码中,应用快速的校验了返回值,并将其输出到标准输入输出流。当返回值为0(VK_SUCCESS)的时候,即说明执行正确。
最后,应用在退出前销毁了这个实例。