概述:
Vulkan的学习曲线是比较陡峭的,学习Vulkan刚开始像是在爬一个陡坡,等上了这个陡坡之后,后面学习曲线就相对比较平缓了。那么在Vulkan中绘制一个三角形,就相当于是在爬这样一个陡坡,因为绘制三角形需要用到很多Vulkan API,写很多代码,并理解很多3D图形绘制的知识。当熟悉了一个三角形的绘制过程以后,基本上也就掌握了Vulkan工作流程以及Vulkan API间的相互关系,后面的东西就比较好学了。总体来说绘制一个三角形总体上分为以下几步:
第一步:初始化Vulkan实例并选择合适的物理设备(GPU设备)
绘制三角形的第一件事是需要初始化一个Vulkan实例,即VkInstance对象,它用来将Vulkan应用程序和Vulkan库连接起来,并将Vulkan应用的一些配置信息传递给下面的Vulkan驱动,比如Vulkan版本信息,Vulkan扩展信息,Vulkan应用程序名称等。
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; //指定vulkan版本
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!");
}
}
Vulkan 的设计理念是尽可能减少驱动层的开销,像参数校验不会在驱动内部做,这也并不是说Vulkan无法做参数的合法性检查,Vulkan提供了一个非常优雅的机制,提出了层(Layer)的概念,可以把参数校验放到校验层中做。
bool checkValidationLayerSupport() {
uint32_t layerCount;
vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
std::vector<VkLayerProperties> availableLayers(layerCount);
vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());
for (const char* layerName : validationLayers) {
bool layerFound = false;
for (const auto& layerProperties : availableLayers) {
if (strcmp(layerName, layerProperties.layerName) == 0) {
layerFound = true;
break;
}
}
if (!layerFound) {
return false;
}
}
return true;
}
第二步:创建逻辑设备和命令队列族(未完待续)