使用校验层
在本章节,我们将使用LunarG的Vulkan SDK提供的校验层。和使用扩展一样,使用校验层需要指定校验层的名称。LunarG的Vulkan SDK允许我们通过VK_LAYER_KHRONOS_validation来隐式地开启所有可用的校验层。
首先,让我们添加两个变量到程序中来控制是否启用指定的校验层。这里,我们通过条件编译来设定是否启用校验层。代码中的NDEBUG宏是C++标准的一部分,表示是否处于非调试模式下:
const int WIDTH = 800;
const int HEIGHT = 600;
const std::vector<const char*> validationLayers = {
"VK_LAYER_KHRONOS_validation"
};
#ifdef NDEBUG
const bool enableValidationLayers = false;
#else
const bool enableValidationLayers = true;
#endif
接着,我们添加了一个叫做checkValidationLayerSupport的函数来请求所有可用的校验层。首先,我们调用vkEnumerateInstanceLayerProperties函数获取了所有可用的校验层列表。这一函数的用法和前面我们在创建Vulkan实例章节中使用的vkEnumerateInstanceExtensionProperties函数相同。
bool checkValidationLayerSupport() {
uint32_t layerCount;
vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
std::vector<VkLayerProperties> availableLayers(layerCount);
vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());
return false;
}
接着,检查是否所有validationLayers列表中的校验层都可以在availableLayers列表中找到:
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;
现在,我们在createInstance函数中调用它:
void createInstance() {
if (enableValidationLayers && !checkValidationLayerSupport()) {
throw std::runtime_error("validation layers requested, but not available!");
}
...
}
现在,在调试模式下编译运行程序,确保没有错误出现。如果程序运行时出现错误,请确保正确安装了Vulkan SDK。如果程序报告缺少可用的校验层,可以查阅LunarG的Vulkan SDK的官方文档寻找解决方法。
最后,修改我们之前的填写的VkInstanceCreateInfo结构体信息,在校验层启用时使用校验层:
if (enableValidationLayers) {
createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
createInfo.ppEnabledLayerNames = validationLayers.data();
} else {
createInfo.enabledLayerCount = 0;
}
如果校验层检查成功,vkCreateInstance函数调用就不会返回VK_ERROR_LAYER_NOT_PRESENT这一错误代码,但为了保险起见,读者应该运行程序来确保没有问题出现。